diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 77555bc151ac3..d291b7de9151e 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -67,7 +67,6 @@ updates:
open-pull-requests-limit: 20
versioning-strategy: increase
ignore: # These are all vendored so need to be updated manually. See lib/tasks/javascript.rake
- - dependency-name: "magnific-popup"
- dependency-name: "moment"
- dependency-name: "moment-timezone"
- dependency-name: "@discourse/moment-timezone-names-translations"
diff --git a/app/assets/stylesheets/common/base/_index.scss b/app/assets/stylesheets/common/base/_index.scss
index a00e08164f29b..188b81ff12cfa 100644
--- a/app/assets/stylesheets/common/base/_index.scss
+++ b/app/assets/stylesheets/common/base/_index.scss
@@ -31,7 +31,6 @@
@import "list-controls";
@import "login";
@import "login-signup-page";
-@import "magnific-popup";
@import "photoswipe";
@import "menu-panel";
@import "modal";
diff --git a/app/assets/stylesheets/common/base/lightbox.scss b/app/assets/stylesheets/common/base/lightbox.scss
index 0f3e839cdd40d..e35d050b92ad0 100644
--- a/app/assets/stylesheets/common/base/lightbox.scss
+++ b/app/assets/stylesheets/common/base/lightbox.scss
@@ -111,10 +111,6 @@
}
}
-.mfp-preloader .spinner {
- margin: auto;
-}
-
.discourse-no-touch {
a.lightbox {
transition: all 0.6s cubic-bezier(0.165, 0.84, 0.44, 1);
diff --git a/app/assets/stylesheets/common/base/magnific-popup.scss b/app/assets/stylesheets/common/base/magnific-popup.scss
deleted file mode 100644
index 1e67521a5d9ae..0000000000000
--- a/app/assets/stylesheets/common/base/magnific-popup.scss
+++ /dev/null
@@ -1,673 +0,0 @@
-/* Magnific Popup CSS */
-
-////////////////////////
-//
-// Contents:
-//
-// 1. Default Settings
-// 2. General styles
-// - Translucent overlay
-// - Containers, wrappers
-// - Cursors
-// - Helper classes
-// 3. Appearance
-// - Preloader & text that displays error messages
-// - CSS reset for buttons
-// - Close icon
-// - "1 of X" counter
-// - Navigation (left/right) arrows
-// - Iframe content type styles
-// - Image content type styles
-// - Media query where size of arrows is reduced
-// - IE7 support
-//
-////////////////////////
-
-////////////////////////
-// 1. Default Settings
-////////////////////////
-
-@use "sass:math";
-
-$overlay-color: #000 !default;
-$overlay-opacity: 0.8 !default;
-$shadow: 0 0 8px rgb(0, 0, 0, 0.6) !default; // shadow on image or iframe
-$popup-padding-left: 8px !default; // Padding from left and from right side
-$popup-padding-left-mobile: 6px !default; // Same as above, but is applied when width of window is less than 800px
-
-$z-index-base: 1040 !default; // Base z-index of popup
-$include-arrows: true !default; // include styles for nav arrows
-$controls-opacity: 0.65 !default;
-$controls-color: #fff !default;
-$inner-close-icon-color: #333 !default;
-$controls-text-color: #ccc !default; // Color of preloader and "1 of X" indicator
-$controls-text-color-hover: #fff !default;
-
-// Iframe-type options
-$include-iframe-type: true !default;
-$iframe-padding-top: 40px !default;
-$iframe-background: #000 !default;
-$iframe-max-width: 900px !default;
-$iframe-ratio: math.div(9, 16) !default;
-
-// Image-type options
-$include-image-type: true !default;
-$image-background: linear-gradient(45deg, #111 0%, #333 100%) !default;
-$image-padding-top: 40px !default;
-$image-padding-bottom: 40px !default;
-$include-mobile-layout-for-image: true !default; // Removes paddings from top and bottom
-
-// Image caption options
-$caption-title-color: #f3f3f3 !default;
-$caption-subtitle-color: #bdbdbd !default;
-
-// A11y
-$use-visuallyhidden: false !default; // Hide content from browsers, but make it available for screen readers
-
-////////////////////////
-// 2. General styles
-////////////////////////
-
-// Translucent overlay
-.mfp-bg {
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- z-index: z("modal", "popover");
- overflow: hidden;
- position: fixed;
- background: $overlay-color;
- animation: fade 0.3s alternate;
-}
-
-// Wrapper for popup
-.mfp-wrap {
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- z-index: z("modal", "popover") + 1;
- position: fixed;
- outline: 0 !important;
- backface-visibility: hidden; // fixes webkit bug that can cause "false" scrollbar
-}
-
-// Root container
-.mfp-container {
- text-align: center;
- position: absolute;
- width: 100%;
- height: 100%;
- left: 0;
- top: 0;
- padding: 0 $popup-padding-left;
- box-sizing: border-box;
-
- // Vertical centerer helper
- &::before {
- content: "";
- display: inline-block;
- height: 100%;
- vertical-align: middle;
- }
-}
-
-// Remove vertical centering when popup has class `mfp-align-top`
-.mfp-align-top {
- .mfp-container {
- &::before {
- display: none;
- }
- }
-}
-
-// Popup content holder
-.mfp-content {
- position: relative;
- display: inline-block;
- vertical-align: middle;
- margin: 0 auto;
- text-align: left;
- z-index: $z-index-base + 5;
-}
-
-.mfp-inline-holder,
-.mfp-ajax-holder {
- .mfp-content {
- width: 100%;
- cursor: auto;
- }
-}
-
-// Cursors
-.mfp-ajax-cur {
- cursor: progress;
-}
-
-.mfp-zoom-out-cur {
- &,
- .mfp-image-holder .mfp-close {
- cursor: zoom-out;
- }
-}
-
-.mfp-zoom {
- cursor: zoom-in;
-}
-
-.mfp-auto-cursor {
- .mfp-content {
- cursor: auto;
- }
-}
-
-.mfp-close,
-.mfp-arrow,
-.mfp-preloader,
-.mfp-counter {
- @include unselectable;
-}
-
-// Hide the image during the loading
-.mfp-loading {
- &.mfp-figure {
- display: none;
- }
-}
-
-// Helper class that hides stuff
-@if $use-visuallyhidden {
- // From HTML5 Boilerplate https://github.com/h5bp/html5-boilerplate/blob/v4.2.0/doc/css.md#visuallyhidden
- .mfp-hide {
- border: 0 !important;
- clip-path: rect(0 0 0 0) !important;
- height: 1px !important;
- margin: -1px !important;
- overflow: hidden !important;
- padding: 0 !important;
- position: absolute !important;
- width: 1px !important;
- }
-} @else {
- .mfp-hide {
- display: none !important;
- }
-}
-
-////////////////////////
-// 3. Appearance
-////////////////////////
-
-// Preloader and text that displays error messages
-.mfp-preloader {
- color: $controls-text-color;
- position: absolute;
- top: 50%;
- width: auto;
- text-align: center;
- margin-top: -0.8em;
- left: 8px;
- right: 8px;
- z-index: $z-index-base + 4;
-
- a {
- color: $controls-text-color;
-
- &:hover {
- color: $controls-text-color-hover;
- }
- }
-}
-
-// Hide preloader when content successfully loaded
-.mfp-s-ready {
- .mfp-preloader {
- display: none;
- }
-}
-
-// Hide content when it was not loaded
-.mfp-s-error {
- .mfp-content {
- display: none;
- }
-}
-
-// CSS-reset for buttons
-button {
- &.mfp-close,
- &.mfp-arrow {
- overflow: visible;
- cursor: pointer;
- background: transparent;
- border: 0;
- appearance: none;
- display: block;
- padding: 0;
- z-index: $z-index-base + 6;
- box-shadow: none;
- }
-
- &::-moz-focus-inner {
- padding: 0;
- border: 0;
- }
-}
-
-// Close icon
-.mfp-close {
- width: 44px;
- height: 44px;
- line-height: var(--line-height-large);
- position: absolute;
- right: 0;
- top: 0;
- text-decoration: none;
- text-align: center;
- opacity: $controls-opacity;
- padding: 0 0 18px 10px;
- color: $controls-color;
- font-style: normal;
- font-size: var(--font-up-5);
- font-family: Arial, Baskerville, monospace;
-
- &:hover,
- &:focus {
- opacity: 1;
- outline: 0;
- }
-
- &:active {
- top: 1px;
- }
-}
-
-.mfp-close-btn-in {
- .mfp-close {
- color: $inner-close-icon-color;
- }
-}
-
-.mfp-image-holder,
-.mfp-iframe-holder {
- .mfp-close {
- color: $controls-color;
- right: -6px;
- text-align: right;
- padding-right: 6px;
- width: 100%;
- }
-}
-
-// "1 of X" counter
-.mfp-counter {
- position: absolute;
- top: 0;
- right: 0;
- color: $controls-text-color;
- font-size: var(--font-down-1);
- line-height: var(--line-height-medium);
-}
-
-// Navigation arrows
-@if $include-arrows {
- .mfp-arrow {
- position: absolute;
- opacity: $controls-opacity;
- top: 50%;
- margin: -55px 0 0;
- padding: 0;
- width: 90px;
- height: 110px;
- -webkit-tap-highlight-color: rgb(0, 0, 0, 0);
-
- &:active {
- margin-top: -54px;
- }
-
- &:hover,
- &:focus {
- outline: 0;
- opacity: 1;
- }
-
- &::before,
- &::after,
- .mfp-b,
- .mfp-a {
- content: "";
- display: block;
- width: 0;
- height: 0;
- position: absolute;
- left: 0;
- top: 0;
- margin-top: 35px;
- margin-left: 35px;
- border: medium inset transparent;
- }
-
- &::after,
- .mfp-a {
- border-top-width: 13px;
- border-bottom-width: 13px;
- top: 8px;
- }
-
- &::before,
- .mfp-b {
- border-top-width: 21px;
- border-bottom-width: 21px;
- }
- }
-
- .mfp-arrow-left {
- left: 0;
-
- &::after,
- .mfp-a {
- border-right: 17px solid #fff;
- margin-left: 31px;
- }
-
- &::before,
- .mfp-b {
- margin-left: 25px;
- border-right: 27px solid #3f3f3f;
- }
- }
-
- .mfp-arrow-right {
- right: 0;
-
- &::after,
- .mfp-a {
- border-left: 17px solid #fff;
- margin-left: 39px;
- }
-
- &::before,
- .mfp-b {
- border-left: 27px solid #3f3f3f;
- }
- }
-}
-
-// Iframe content type
-@if $include-iframe-type {
- .mfp-iframe-holder {
- padding-top: $iframe-padding-top;
- padding-bottom: $iframe-padding-top;
-
- .mfp-content {
- line-height: 0;
- width: 100%;
- max-width: $iframe-max-width;
- }
-
- .mfp-close {
- top: -40px;
- }
- }
-
- .mfp-iframe-scaler {
- width: 100%;
- height: 0;
- overflow: hidden;
- padding-top: $iframe-ratio * 100%;
-
- iframe {
- position: absolute;
- display: block;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- box-shadow: $shadow;
- background: $iframe-background;
- }
- }
-}
-
-// Image content type
-@if $include-image-type {
- /* Main image in popup */
- img {
- &.mfp-img {
- width: auto;
- max-width: 100%;
- height: auto;
- display: block;
- line-height: 0;
- box-sizing: border-box;
- padding: $image-padding-top 0 $image-padding-bottom;
- margin: 0 auto;
- }
- }
-
- /* The shadow behind the image */
- .mfp-figure {
- line-height: 0;
-
- &::after {
- content: "";
- position: absolute;
- left: 0;
- top: $image-padding-top;
- bottom: $image-padding-bottom;
- display: block;
- right: 0;
- width: auto;
- height: auto;
- z-index: -1;
- box-shadow: $shadow;
- background: $image-background;
- }
-
- small {
- color: $caption-subtitle-color;
- display: block;
- font-size: var(--font-down-1);
- line-height: var(--line-height-medium);
- }
-
- figure {
- margin: 0;
- }
- }
-
- .mfp-bottom-bar {
- margin-top: -$image-padding-bottom + 4;
- position: absolute;
- top: 100%;
- left: 0;
- width: 100%;
- cursor: auto;
- }
-
- .mfp-title {
- text-align: left;
- line-height: var(--line-height-medium);
- color: $caption-title-color;
- overflow-wrap: break-word;
- padding-right: 36px; // leave some space for counter at right side
- max-width: 100%;
-
- // add the download icon
- a.image-source-link .d-icon {
- padding-right: 5px;
- }
-
- a {
- color: var(--tertiary-medium);
- }
- }
-
- .mfp-ready {
- .mfp-content {
- min-width: 300px;
- }
- }
-
- .mfp-title,
- .mfp-title .image-source-link {
- display: inline-block;
- }
-
- .mfp-image-holder {
- .mfp-content {
- max-width: 100%;
- }
- }
-
- .mfp-gallery {
- .mfp-image-holder {
- .mfp-figure {
- cursor: pointer;
- }
- }
- }
-
- @if $include-mobile-layout-for-image {
- @media all and (width <= 800px) and (orientation: landscape),
- screen and (height <= 300px) {
- /**
- * Remove all paddings around the image on small screen
- */
-
- .mfp-img-mobile {
- .mfp-image-holder {
- padding-left: 0;
- padding-right: 0;
- }
-
- img {
- &.mfp-img {
- padding: 0;
- }
- }
-
- .mfp-figure {
- /* The shadow behind the image */
- &::after {
- top: 0;
- bottom: 0;
- }
-
- small {
- display: inline;
- margin-left: 5px;
- }
- }
-
- .mfp-bottom-bar {
- background: rgb(0, 0, 0, 0.6);
- bottom: 0;
- margin: 0;
- top: auto;
- padding: 3px 5px;
- position: fixed;
- box-sizing: border-box;
-
- &:empty {
- padding: 0;
- }
- }
-
- .mfp-counter {
- right: 5px;
- top: 3px;
- }
-
- .mfp-close {
- top: 0;
- right: 0;
- width: 35px;
- height: 35px;
- line-height: var(--line-height-large);
- background: rgb(0, 0, 0, 0.6);
- position: fixed;
- text-align: center;
- padding: 0;
- }
- }
- }
- }
-}
-
-// Scale navigation arrows and reduce padding from sides
-@media all and (width <= 900px) {
- .mfp-arrow {
- transform: scale(0.75);
- }
-
- .mfp-arrow-left {
- transform-origin: 0;
- }
-
- .mfp-arrow-right {
- transform-origin: 100%;
- }
-
- .mfp-container {
- padding-left: $popup-padding-left-mobile;
- padding-right: $popup-padding-left-mobile;
- }
-}
-
-.mfp-zoom-in {
- /* start state */
- .mfp-content {
- opacity: 0;
- transform: scale(0.8);
-
- @media screen and (prefers-reduced-motion: no-preference) {
- transition: all 0.2s;
- }
- }
-
- &.mfp-bg {
- opacity: 0;
- transition: all 0.3s ease-out;
- }
-
- /* animate in */
- &.mfp-ready {
- .mfp-content {
- opacity: 1;
- transform: scale(1);
- }
-
- &.mfp-bg {
- opacity: 0.7;
- }
- }
-
- /* animate out */
- &.mfp-removing {
- .mfp-content {
- transform: scale(0.8);
- opacity: 0;
- }
-
- &.mfp-bg {
- opacity: 0;
- }
- }
-}
-
-.mfp-force-scrollbars {
- &.mfp-wrap {
- overflow-y: auto !important;
- overflow-x: auto !important;
- }
-
- .mfp-figure {
- overflow: auto;
- }
-
- .mfp-img {
- max-width: none;
- }
-}
diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml
index 760f910726ab9..af1a309cd5f12 100644
--- a/config/locales/server.en.yml
+++ b/config/locales/server.en.yml
@@ -2752,7 +2752,6 @@ en:
experimental_auto_grid_images: "Automatically wraps images in [grid] tags when 3 or more images are uploaded in the composer."
experimental_impersonation: "Impersonate a user without having to log out of your admin account."
experimental_impersonation_time_limit_minutes: "How long before an impersonation session is automatically ended."
- experimental_lightbox: "Use PhotoSwipe to lightbox larger images."
page_loading_indicator: "Configure the loading indicator which appears during page navigations within Discourse. 'Spinner' is a full page indicator. 'Slider' shows a narrow bar at the top of the screen."
show_user_menu_avatars: "Show user avatars in the user menu"
about_page_hidden_groups: "Do not show members of specific groups on the /about page."
diff --git a/config/site_settings.yml b/config/site_settings.yml
index ae9f91598e87e..5f9f983abb9a9 100644
--- a/config/site_settings.yml
+++ b/config/site_settings.yml
@@ -4260,10 +4260,6 @@ experimental:
default: 15
hidden: true
area: "experimental"
- experimental_lightbox:
- client: true
- default: true
- area: "experimental"
show_preview_for_form_templates:
client: true
default: true
diff --git a/frontend/discourse/admin/components/admin-config-areas/upcoming-change-item.gjs b/frontend/discourse/admin/components/admin-config-areas/upcoming-change-item.gjs
index ecb5e4f284333..f8acb590743d6 100644
--- a/frontend/discourse/admin/components/admin-config-areas/upcoming-change-item.gjs
+++ b/frontend/discourse/admin/components/admin-config-areas/upcoming-change-item.gjs
@@ -25,7 +25,6 @@ import { i18n } from "discourse-i18n";
export default class UpcomingChangeItem extends Component {
@service toasts;
- @service siteSettings;
@tracked bufferedGroups = this.args.change.groups;
@tracked bufferedEnabledFor = this.args.change.upcoming_change.enabled_for;
@@ -34,7 +33,7 @@ export default class UpcomingChangeItem extends Component {
registeredMenu = null;
- applyLightbox = modifier((element) => lightbox(element, this.siteSettings));
+ applyLightbox = modifier((element) => lightbox(element));
willDestroy() {
super.willDestroy(...arguments);
diff --git a/frontend/discourse/app/components/uppy-image-uploader.gjs b/frontend/discourse/app/components/uppy-image-uploader.gjs
index 6a94ae6cb8d78..80bab33da85e2 100644
--- a/frontend/discourse/app/components/uppy-image-uploader.gjs
+++ b/frontend/discourse/app/components/uppy-image-uploader.gjs
@@ -8,7 +8,6 @@ import { service } from "@ember/service";
import { htmlSafe } from "@ember/template";
import { isEmpty } from "@ember/utils";
import { modifier } from "ember-modifier";
-import $ from "jquery";
import DButton from "discourse/components/d-button";
import PickFilesButton from "discourse/components/pick-files-button";
import concatClass from "discourse/helpers/concat-class";
@@ -60,12 +59,7 @@ export default class UppyImageUploader extends Component {
willDestroy() {
super.willDestroy(...arguments);
-
- if (this.siteSettings.experimental_lightbox) {
- window.pswp?.close();
- } else {
- $.magnificPopup?.instance.close();
- }
+ window.pswp?.close();
}
get disabled() {
@@ -147,7 +141,6 @@ export default class UppyImageUploader extends Component {
@action
toggleLightbox() {
- // Only allow lightbox for images, not videos
if (this.isVideoFile) {
return;
}
@@ -158,12 +151,8 @@ export default class UppyImageUploader extends Component {
return;
}
- if (this.siteSettings.experimental_lightbox) {
- lightbox(lightboxImage, this.siteSettings);
- lightboxImage.click();
- } else {
- $(lightboxImage).magnificPopup("open");
- }
+ lightbox(lightboxImage);
+ lightboxImage.click();
}
@action
diff --git a/frontend/discourse/app/instance-initializers/clean-dom-on-route-change.js b/frontend/discourse/app/instance-initializers/clean-dom-on-route-change.js
index d7de8dee1340d..f9b0220565247 100644
--- a/frontend/discourse/app/instance-initializers/clean-dom-on-route-change.js
+++ b/frontend/discourse/app/instance-initializers/clean-dom-on-route-change.js
@@ -1,5 +1,4 @@
import { scheduleOnce } from "@ember/runloop";
-import $ from "jquery";
function _clean(transition) {
if (window.MiniProfiler && transition.from) {
@@ -18,12 +17,6 @@ function _clean(transition) {
// Close PhotoSwipe
window.pswp?.close();
- // Close the lightbox
- if ($.magnificPopup?.instance) {
- $.magnificPopup.instance.close();
- document.body.classList.remove("mfp-zoom-out-cur");
- }
-
// Remove any link focus
const { activeElement } = document;
if (activeElement && !activeElement.classList.contains("no-blur")) {
diff --git a/frontend/discourse/app/instance-initializers/post-decorations.js b/frontend/discourse/app/instance-initializers/post-decorations.js
index f54de44d8f312..d6f18ae66a997 100644
--- a/frontend/discourse/app/instance-initializers/post-decorations.js
+++ b/frontend/discourse/app/instance-initializers/post-decorations.js
@@ -28,7 +28,7 @@ export default {
});
api.decorateCookedElement((elem, helper) => {
- return lightbox(elem, siteSettings, { post: helper.model });
+ return lightbox(elem, { post: helper.model });
});
api.decorateCookedElement((elem) => {
diff --git a/frontend/discourse/app/lib/lightbox.js b/frontend/discourse/app/lib/lightbox.js
index 02f99378fb2c3..b588070c63b83 100644
--- a/frontend/discourse/app/lib/lightbox.js
+++ b/frontend/discourse/app/lib/lightbox.js
@@ -1,470 +1,354 @@
-import { waitForPromise } from "@ember/test-waiters";
-import $ from "jquery";
-import { spinnerHTML } from "discourse/helpers/loading-spinner";
import { isRailsTesting, isTesting } from "discourse/lib/environment";
import { helperContext } from "discourse/lib/helpers";
-import { renderIcon } from "discourse/lib/icon-library";
import { SELECTORS } from "discourse/lib/lightbox/constants";
import quoteImage, {
canBuildImageQuote,
} from "discourse/lib/lightbox/quote-image";
import { isDocumentRTL } from "discourse/lib/text-direction";
-import {
- escapeExpression,
- postRNWebviewMessage,
-} from "discourse/lib/utilities";
+import { escapeExpression } from "discourse/lib/utilities";
import { i18n } from "discourse-i18n";
-export async function loadMagnificPopup() {
- await waitForPromise(import("magnific-popup"));
-}
-
-export default async function lightbox(
- elem,
- siteSettings,
- additionalData = {}
-) {
+export default async function lightbox(elem, additionalData = {}) {
if (!elem) {
return;
}
const currentUser = helperContext()?.currentUser;
+ const siteSettings = helperContext().siteSettings;
const caps = helperContext().capabilities;
- const imageClickNavigation = caps.touch;
+
+ const { default: PhotoSwipeLightbox } = await import("photoswipe/lightbox");
+ const isTestEnv = isTesting() || isRailsTesting();
const canDownload =
!siteSettings.prevent_anons_from_downloading_files || !!currentUser;
const canQuoteImage = !!currentUser;
+ const rtl = isDocumentRTL();
+ const items = [...elem.querySelectorAll(SELECTORS.DEFAULT_ITEM_SELECTOR)];
- if (siteSettings.experimental_lightbox) {
- const { default: PhotoSwipeLightbox } = await import("photoswipe/lightbox");
- const isTestEnv = isTesting() || isRailsTesting();
-
- const rtl = isDocumentRTL();
- const items = [...elem.querySelectorAll(SELECTORS.DEFAULT_ITEM_SELECTOR)];
-
- if (rtl) {
- items.reverse();
- }
-
- items.forEach((el, index) => {
- el.addEventListener("click", (e) => {
- e.preventDefault();
-
- lightboxEl.loadAndOpen(index);
- });
- });
-
- const lightboxEl = new PhotoSwipeLightbox({
- dataSource: items,
- arrowPrevTitle: i18n("lightbox.previous"),
- arrowNextTitle: i18n("lightbox.next"),
- closeTitle: i18n("lightbox.close"),
- zoomTitle: i18n("lightbox.zoom"),
- errorMsg: i18n("lightbox.error"),
- showHideAnimationType: isTestEnv ? "none" : "zoom",
- counter: false,
- escKey: false,
- tapAction,
- paddingFn,
- pswpModule: async () => await import("photoswipe"),
- appendToEl: isTesting() && document.getElementById("ember-testing"),
- });
-
- const keyDownHandler = function (event) {
- if (event.key !== "Escape") {
- return;
- }
-
- event.stopPropagation();
- event.preventDefault();
-
- lightboxEl.pswp.close();
- };
+ if (rtl) {
+ items.reverse();
+ }
- lightboxEl.on("afterInit", () => {
- const el = lightboxEl.pswp.currSlide.data.element;
- el.querySelector(".meta")?.classList.add("open");
+ items.forEach((el, index) => {
+ el.addEventListener("click", (e) => {
+ e.preventDefault();
- lightboxEl.pswp.element.addEventListener("keydown", (event) =>
- keyDownHandler(event)
- );
+ lightboxEl.loadAndOpen(index);
});
+ });
+
+ const lightboxEl = new PhotoSwipeLightbox({
+ dataSource: items,
+ arrowPrevTitle: i18n("lightbox.previous"),
+ arrowNextTitle: i18n("lightbox.next"),
+ closeTitle: i18n("lightbox.close"),
+ zoomTitle: i18n("lightbox.zoom"),
+ errorMsg: i18n("lightbox.error"),
+ showHideAnimationType: isTestEnv ? "none" : "zoom",
+ counter: false,
+ escKey: false,
+ tapAction,
+ paddingFn,
+ pswpModule: async () => await import("photoswipe"),
+ appendToEl: isTesting() && document.getElementById("ember-testing"),
+ });
+
+ const keyDownHandler = function (event) {
+ if (event.key !== "Escape") {
+ return;
+ }
- lightboxEl.on("close", function () {
- lightboxEl.pswp.element.classList.add("pswp--behind-header");
- lightboxEl.pswp.element.removeEventListener("keydown", keyDownHandler);
- });
+ event.stopPropagation();
+ event.preventDefault();
- lightboxEl.on("destroy", () => {
- const el = lightboxEl.pswp.currSlide.data.element;
- el.querySelector(".meta")?.classList.remove("open");
- });
+ lightboxEl.pswp.close();
+ };
- lightboxEl.on("uiRegister", function () {
- // adds a custom caption to lightbox
- lightboxEl.pswp.ui.registerElement({
- name: "caption",
- order: 11,
- isButton: false,
- appendTo: "root",
- html: "",
- onInit: (caption, pswp) => {
- pswp.on("change", () => {
- const { element, title, inlineSVG } = pswp.currSlide.data;
+ lightboxEl.on("afterInit", () => {
+ const el = lightboxEl.pswp.currSlide.data.element;
+ el.querySelector(".meta")?.classList.add("open");
- if (!element || !title || inlineSVG) {
- return;
- }
-
- const captionTitle = escapeExpression(title);
- const captionDetails =
- element.querySelector(".informations")?.textContent;
- const titleEl = captionTitle
- ? `
${captionTitle}
`
- : null;
- const detailsEl = captionDetails
- ? `${captionDetails}
`
- : null;
-
- caption.innerHTML = [titleEl, detailsEl].filter(Boolean).join("");
- });
- },
- });
+ lightboxEl.pswp.element.addEventListener("keydown", (event) =>
+ keyDownHandler(event)
+ );
+ });
+
+ lightboxEl.on("close", function () {
+ lightboxEl.pswp.element.classList.add("pswp--behind-header");
+ lightboxEl.pswp.element.removeEventListener("keydown", keyDownHandler);
+ });
+
+ lightboxEl.on("destroy", () => {
+ const el = lightboxEl.pswp.currSlide.data.element;
+ el.querySelector(".meta")?.classList.remove("open");
+ });
+
+ lightboxEl.on("uiRegister", function () {
+ lightboxEl.pswp.ui.registerElement({
+ name: "caption",
+ order: 11,
+ isButton: false,
+ appendTo: "root",
+ html: "",
+ onInit: (caption, pswp) => {
+ pswp.on("change", () => {
+ const { element, title, inlineSVG } = pswp.currSlide.data;
+
+ if (!element || !title || inlineSVG) {
+ return;
+ }
- // adds a download button
- if (canDownload) {
- lightboxEl.pswp.ui.registerElement({
- name: "download-image",
- order: 7,
- isButton: true,
- tagName: "a",
- title: i18n("lightbox.download"),
- html: {
- isCustomSVG: true,
- inner:
- '',
- outlineID: "pswp__icn-download",
- },
- onInit: (el, pswp) => {
- el.setAttribute("download", "");
- el.setAttribute("target", "_blank");
- el.setAttribute("rel", "noopener");
-
- pswp.on("change", () => {
- const href = pswp.currSlide.data.element.dataset.downloadHref;
- if (!href) {
- el.style.display = "none";
- return;
- }
- el.href = href;
- });
- },
+ const captionTitle = escapeExpression(title);
+ const captionDetails =
+ element.querySelector(".informations")?.innerHTML;
+ const titleEl = captionTitle
+ ? `${captionTitle}
`
+ : null;
+ const detailsEl = captionDetails
+ ? `${captionDetails}
`
+ : null;
+
+ caption.innerHTML = [titleEl, detailsEl].filter(Boolean).join("");
});
- }
+ },
+ });
- // adds a view original image button
+ if (canDownload) {
lightboxEl.pswp.ui.registerElement({
- name: "original-image",
- order: 8,
+ name: "download-image",
+ order: 7,
isButton: true,
tagName: "a",
- title: i18n("lightbox.open"),
+ title: i18n("lightbox.download"),
html: {
isCustomSVG: true,
inner:
- '',
- outlineID: "pswp__icn-image",
+ '',
+ outlineID: "pswp__icn-download",
},
onInit: (el, pswp) => {
+ el.setAttribute("download", "");
el.setAttribute("target", "_blank");
el.setAttribute("rel", "noopener");
pswp.on("change", () => {
- el.href = pswp.currSlide.data.src;
+ const href = pswp.currSlide.data.element.dataset.downloadHref;
+ if (!href) {
+ el.style.display = "none";
+ return;
+ }
+ el.href = href;
});
},
});
+ }
+
+ lightboxEl.pswp.ui.registerElement({
+ name: "original-image",
+ order: 8,
+ isButton: true,
+ tagName: "a",
+ title: i18n("lightbox.open"),
+ html: {
+ isCustomSVG: true,
+ inner:
+ '',
+ outlineID: "pswp__icn-image",
+ },
+ onInit: (el, pswp) => {
+ el.setAttribute("target", "_blank");
+ el.setAttribute("rel", "noopener");
+
+ pswp.on("change", () => {
+ el.href = pswp.currSlide.data.src;
+ });
+ },
+ });
+
+ lightboxEl.pswp.ui.registerElement({
+ name: "image-info",
+ order: 9,
+ isButton: true,
+ tagName: "a",
+ title: i18n("lightbox.image_info"),
+ html: {
+ isCustomSVG: true,
+ inner:
+ '',
+ outlineID: "pswp__icn-info",
+ },
+ onInit: (el, pswp) => {
+ pswp.on("change", () => {
+ el.style.display = pswp.currSlide.data.details ? "block" : "none";
+ });
+ },
+ onClick: () => {
+ lightboxEl.pswp.element.classList.toggle("pswp--caption-expanded");
+ },
+ });
+ if (canQuoteImage) {
lightboxEl.pswp.ui.registerElement({
- name: "image-info",
- order: 9,
+ name: "quote-image",
+ order: 10,
isButton: true,
- tagName: "a",
- title: i18n("lightbox.image_info"),
+ title: i18n("lightbox.quote"),
html: {
isCustomSVG: true,
inner:
- '',
- outlineID: "pswp__icn-info",
+ '',
+ outlineID: "pswp__icn-quote",
},
onInit: (el, pswp) => {
pswp.on("change", () => {
- el.style.display = pswp.currSlide.data.details ? "block" : "none";
+ const slideData = pswp.currSlide?.data;
+ const slideElement = slideData?.element;
+ el.style.display = canBuildImageQuote(slideElement, slideData)
+ ? ""
+ : "none";
});
},
onClick: () => {
- lightboxEl.pswp.element.classList.toggle("pswp--caption-expanded");
+ const slideData = lightboxEl.pswp.currSlide?.data;
+ const slideElement = slideData?.element;
+ quoteImage(slideElement, slideData).then((didQuote) => {
+ if (didQuote) {
+ lightboxEl.pswp.close();
+ }
+ });
},
});
+ }
- if (canQuoteImage) {
- lightboxEl.pswp.ui.registerElement({
- name: "quote-image",
- order: 10,
- isButton: true,
- title: i18n("lightbox.quote"),
- html: {
- isCustomSVG: true,
- inner:
- '',
- outlineID: "pswp__icn-quote",
- },
- onInit: (el, pswp) => {
- pswp.on("change", () => {
- const slideData = pswp.currSlide?.data;
- const slideElement = slideData?.element;
- el.style.display = canBuildImageQuote(slideElement, slideData)
- ? ""
- : "none";
- });
- },
- onClick: () => {
- const slideData = lightboxEl.pswp.currSlide?.data;
- const slideElement = slideData?.element;
- quoteImage(slideElement, slideData).then((didQuote) => {
- if (didQuote) {
- lightboxEl.pswp.close();
- }
- });
- },
+ lightboxEl.pswp.ui.registerElement({
+ name: "custom-counter",
+ order: 6,
+ isButton: false,
+ appendTo: "bar",
+ onInit: (el, pswp) => {
+ pswp.on("change", () => {
+ const total = pswp.getNumItems();
+ const index = rtl ? total - pswp.currIndex : pswp.currIndex + 1;
+ el.textContent = `${index} / ${total}`;
});
- }
-
- lightboxEl.pswp.ui.registerElement({
- name: "custom-counter",
- order: 6,
- isButton: false,
- appendTo: "bar",
- onInit: (el, pswp) => {
- pswp.on("change", () => {
- const total = pswp.getNumItems();
- const index = rtl ? total - pswp.currIndex : pswp.currIndex + 1;
- el.textContent = `${index} / ${total}`;
- });
- },
- });
+ },
});
+ });
- lightboxEl.addFilter("itemData", (data) => {
- const el = data.element;
-
- if (!el) {
- return data;
- }
-
- // use data attributes for width/height when available
- let width = el.getAttribute("data-target-width");
- let height = el.getAttribute("data-target-height");
- const isSVG = el.querySelector("svg[viewBox]") !== null;
-
- if (isSVG) {
- const encodedSVG = encodeURIComponent(el.innerHTML.trim());
- data.src = `data:image/svg+xml,${encodedSVG}`;
- data.inlineSVG = true;
- width = (el.clientWidth || 400) * 10;
- height = (el.clientHeight || 300) * 10;
-
- // 1x1 placeholder to prevent background flicker on inline SVGs
- data.msrc =
- "data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A//www.w3.org/2000/svg%27%20width%3D%271%27%20height%3D%271%27/%3E";
- }
-
- const imgInfo = el.querySelector(".informations")?.textContent || "";
- const imgEl = el.tagName === "IMG" ? el : el.querySelector("img");
-
- if (!width || !height) {
- const dimensions = imgInfo.trim().split(" ")[0];
- [width, height] = dimensions.split(/x|×/).map(Number);
- }
-
- // this ensures that cropped images (eg: grid) do not cause jittering when closing
- data.thumbCropped = true;
-
- data.src = data.src || el.getAttribute("data-large-src");
- data.origSrc =
- imgEl?.getAttribute("data-orig-src") ||
- el.getAttribute("data-orig-src") ||
- null;
- data.title = el.title || imgEl?.alt || imgEl?.title || null;
- data.base62SHA1 =
- imgEl?.getAttribute("data-base62-sha1") ||
- el.getAttribute("data-base62-sha1") ||
- null;
- data.details = imgInfo;
- data.w = data.width = width;
- data.h = data.height = height;
- data.targetWidth =
- el.getAttribute("data-target-width") ||
- imgEl?.getAttribute("width") ||
- null;
- data.targetHeight =
- el.getAttribute("data-target-height") ||
- imgEl?.getAttribute("height") ||
- null;
-
- // So we can attach things like a Post model from the caller.
- Object.keys(additionalData).forEach((key) => {
- data[key] = additionalData[key];
- });
+ lightboxEl.addFilter("itemData", (data) => {
+ const el = data.element;
+ if (!el) {
return data;
- });
-
- const itemsToPreload = items.filter((item) => {
- const { largeSrc, targetWidth, targetHeight } = item.dataset;
- const hasImageSrc = largeSrc || item.getAttribute("href");
- const missingDimensions = !targetWidth || !targetHeight;
- const imgDimensions = item
- .querySelector(".informations")
- ?.textContent.trim()
- .split(" ")[0];
- const missingMetaData = !imgDimensions?.split(/x|×/).every((d) => !!d);
-
- return hasImageSrc && missingDimensions && missingMetaData;
- });
-
- await Promise.all(
- itemsToPreload.map(
- (item) =>
- new Promise((resolve) => {
- const img = new Image();
- img.src =
- item.getAttribute("data-large-src") || item.getAttribute("href");
- img.onload = () => {
- item.setAttribute("data-target-width", img.naturalWidth);
- item.setAttribute("data-target-height", img.naturalHeight);
- resolve();
- };
- img.onerror = resolve;
- })
- )
- );
- function tapAction(pt, event) {
- const pswp = lightboxEl.pswp;
- if (event.target.classList.contains("pswp__img")) {
- pswp?.element?.classList.toggle("pswp--ui-visible");
- } else {
- pswp?.close();
- }
}
- function paddingFn(viewportSize, itemData) {
- if (viewportSize.x < 1200 || caps.isMobileDevice) {
- return { top: 0, bottom: 0, left: 0, right: 0 };
- }
- return {
- top: 20,
- bottom: itemData.title ? 75 : 20,
- left: 20,
- right: 20,
- };
+ // use data attributes for width/height when available
+ let width = el.getAttribute("data-target-width");
+ let height = el.getAttribute("data-target-height");
+ const isSVG = el.querySelector("svg[viewBox]") !== null;
+
+ if (isSVG) {
+ const encodedSVG = encodeURIComponent(el.innerHTML.trim());
+ data.src = `data:image/svg+xml,${encodedSVG}`;
+ data.inlineSVG = true;
+ width = (el.clientWidth || 400) * 10;
+ height = (el.clientHeight || 300) * 10;
+
+ // 1x1 placeholder to prevent background flicker on inline SVGs
+ data.msrc =
+ "data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A//www.w3.org/2000/svg%27%20width%3D%271%27%20height%3D%271%27/%3E";
}
- lightboxEl.init();
- } else {
- // Magnific lightbox
- const images = elem.querySelectorAll(SELECTORS.DEFAULT_ITEM_SELECTOR);
+ const imgInfo = el.querySelector(".informations")?.textContent || "";
+ const imgEl = el.tagName === "IMG" ? el : el.querySelector("img");
- if (!images.length) {
- return;
+ if (!width || !height) {
+ const dimensions = imgInfo.trim().split(" ")[0];
+ [width, height] = dimensions.split(/x|×/).map(Number);
}
- await loadMagnificPopup();
-
- $(images).magnificPopup({
- type: "image",
- closeOnContentClick: false,
- removalDelay: isTesting() ? 0 : 300,
- mainClass: "mfp-zoom-in",
- tClose: i18n("lightbox.close"),
- tLoading: spinnerHTML,
- prependTo: isTesting() && document.getElementById("ember-testing"),
-
- gallery: {
- enabled: true,
- tPrev: i18n("lightbox.previous"),
- tNext: i18n("lightbox.next"),
- tCounter: i18n("lightbox.counter"),
- navigateByImgClick: imageClickNavigation,
- },
-
- ajax: {
- tError: i18n("lightbox.content_load_error"),
- },
-
- callbacks: {
- open() {
- if (!imageClickNavigation) {
- const wrap = this.wrap,
- img = this.currItem.img,
- maxHeight = img.css("max-height");
-
- wrap.on("click.pinhandler", "img", function () {
- wrap.toggleClass("mfp-force-scrollbars");
- img.css(
- "max-height",
- wrap.hasClass("mfp-force-scrollbars") ? "none" : maxHeight
- );
- });
- }
+ // this ensures that cropped images (eg: grid) do not cause jittering when closing
+ data.thumbCropped = true;
+
+ data.src = data.src || el.getAttribute("data-large-src");
+ data.origSrc =
+ imgEl?.getAttribute("data-orig-src") ||
+ el.getAttribute("data-orig-src") ||
+ null;
+ data.title = el.title || imgEl?.alt || imgEl?.title || null;
+ data.base62SHA1 =
+ imgEl?.getAttribute("data-base62-sha1") ||
+ el.getAttribute("data-base62-sha1") ||
+ null;
+ data.details = imgInfo;
+ data.w = data.width = width;
+ data.h = data.height = height;
+ data.targetWidth =
+ el.getAttribute("data-target-width") ||
+ imgEl?.getAttribute("width") ||
+ null;
+ data.targetHeight =
+ el.getAttribute("data-target-height") ||
+ imgEl?.getAttribute("height") ||
+ null;
+
+ // So we can attach things like a Post model from the caller.
+ Object.keys(additionalData).forEach((key) => {
+ data[key] = additionalData[key];
+ });
- if (caps.isAppWebview) {
- postRNWebviewMessage(
- "headerBg",
- $(".mfp-bg").css("background-color")
- );
- }
- },
- change() {
- this.wrap.removeClass("mfp-force-scrollbars");
- },
- beforeClose() {
- this.wrap.off("click.pinhandler");
- this.wrap.removeClass("mfp-force-scrollbars");
- if (caps.isAppWebview) {
- postRNWebviewMessage(
- "headerBg",
- $(".d-header").css("background-color")
- );
- }
- },
- },
+ return data;
+ });
+
+ const itemsToPreload = items.filter((item) => {
+ const { largeSrc, targetWidth, targetHeight } = item.dataset;
+ const hasImageSrc = largeSrc || item.getAttribute("href");
+ const missingDimensions = !targetWidth || !targetHeight;
+ const imgDimensions = item
+ .querySelector(".informations")
+ ?.textContent.trim()
+ .split(" ")[0];
+ const missingMetaData = !imgDimensions?.split(/x|×/).every((d) => !!d);
+
+ return hasImageSrc && missingDimensions && missingMetaData;
+ });
+
+ await Promise.all(
+ itemsToPreload.map(
+ (item) =>
+ new Promise((resolve) => {
+ const img = new Image();
+ img.src =
+ item.getAttribute("data-large-src") || item.getAttribute("href");
+ img.onload = () => {
+ item.setAttribute("data-target-width", img.naturalWidth);
+ item.setAttribute("data-target-height", img.naturalHeight);
+ resolve();
+ };
+ img.onerror = resolve;
+ })
+ )
+ );
+ function tapAction(pt, event) {
+ const pswp = lightboxEl.pswp;
+ if (event.target.classList.contains("pswp__img")) {
+ pswp?.element?.classList.toggle("pswp--ui-visible");
+ } else {
+ pswp?.close();
+ }
+ }
- image: {
- tError: i18n("lightbox.image_load_error"),
- titleSrc(item) {
- const href = item.el.data("download-href") || item.src;
- const downloadText =
- renderIcon("string", "download") + i18n("lightbox.download");
- const origImgText =
- renderIcon("string", "image") + i18n("lightbox.open");
-
- let src = [
- escapeExpression(item.el.attr("title")),
- $("span.informations", item.el).text(),
- ];
-
- if (canDownload) {
- src.push(
- `${downloadText}`
- );
- }
- src.push(
- `${origImgText}`
- );
- return src.join(" · ");
- },
- },
- });
+ function paddingFn(viewportSize, itemData) {
+ if (viewportSize.x < 1200 || caps.isMobileDevice) {
+ return { top: 0, bottom: 0, left: 0, right: 0 };
+ }
+ return {
+ top: 20,
+ bottom: itemData.title ? 75 : 20,
+ left: 20,
+ right: 20,
+ };
}
+
+ lightboxEl.init();
}
diff --git a/frontend/discourse/package.json b/frontend/discourse/package.json
index 3f4071e7ecdea..732b40040b4ed 100644
--- a/frontend/discourse/package.json
+++ b/frontend/discourse/package.json
@@ -55,7 +55,6 @@
"highlight.js": "11.11.1",
"immer": "^11.0.1",
"jspreadsheet-ce": "^4.15.0",
- "magnific-popup": "1.1.0",
"moment": "2.30.1",
"moment-timezone": "0.5.45",
"morphlex": "^0.0.16",
diff --git a/frontend/discourse/tests/acceptance/lightbox-test.js b/frontend/discourse/tests/acceptance/lightbox-test.js
index 9769e0da551c9..81e16451ae5b4 100644
--- a/frontend/discourse/tests/acceptance/lightbox-test.js
+++ b/frontend/discourse/tests/acceptance/lightbox-test.js
@@ -26,45 +26,7 @@ acceptance("Lightbox", function (needs) {
);
});
- test("Shows download and direct URL", async function (assert) {
- this.siteSettings.experimental_lightbox = false;
-
- await visit("/t/internationalization-localization/280");
- await click(".lightbox");
-
- assert
- .dom(".mfp-title")
- .hasText(
- " · 1500×842 234 KB · Download · Original image"
- );
-
- assert
- .dom(".image-source-link:nth-child(1)")
- .hasAttribute(
- "href",
- "//discourse.local/uploads/default/ad768537789cdf4679a18161ac0b0b6f0f4ccf9e"
- );
-
- assert
- .dom(".image-source-link:nth-child(2)")
- .hasAttribute("href", `/images/d-logo-sketch.png`);
-
- await click(".mfp-close");
- });
-
- test("Correctly escapes image caption", async function (assert) {
- this.siteSettings.experimental_lightbox = false;
-
- await visit("/t/internationalization-localization/280");
- await click(".lightbox");
-
- assert.dom(".mfp-title").hasHtml(/^<script>image<\/script> · /);
- });
-
- // PhotoSwipe
test("Shows 'download' and 'original image' buttons", async function (assert) {
- this.siteSettings.experimental_lightbox = true;
-
await visit("/t/internationalization-localization/280");
await click(".lightbox");
@@ -92,8 +54,6 @@ acceptance("Lightbox", function (needs) {
});
test("Correctly escapes image caption", async function (assert) {
- this.siteSettings.experimental_lightbox = true;
-
await visit("/t/internationalization-localization/280");
await click(".lightbox");
diff --git a/frontend/discourse/tests/integration/components/uppy-image-uploader-test.gjs b/frontend/discourse/tests/integration/components/uppy-image-uploader-test.gjs
index dda96f47f60e3..d6d9dd151fbcb 100644
--- a/frontend/discourse/tests/integration/components/uppy-image-uploader-test.gjs
+++ b/frontend/discourse/tests/integration/components/uppy-image-uploader-test.gjs
@@ -1,4 +1,4 @@
-import { click, render, triggerEvent } from "@ember/test-helpers";
+import { click, render, triggerEvent, waitFor } from "@ember/test-helpers";
import { module, test } from "qunit";
import UppyImageUploader from "discourse/components/uppy-image-uploader";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
@@ -7,8 +7,6 @@ module("Integration | Component | uppy-image-uploader", function (hooks) {
setupRenderingTest(hooks);
test("with image", async function (assert) {
- this.siteSettings.experimental_lightbox = false;
-
await render(
{
if (this.args.uploads.length > 0) {
- loadLightbox(element, this.siteSettings);
+ lightbox(element);
}
});
diff --git a/plugins/chat/assets/javascripts/discourse/initializers/chat-decorators.js b/plugins/chat/assets/javascripts/discourse/initializers/chat-decorators.js
index 879449fbd0df2..a0d5424ed7cb6 100644
--- a/plugins/chat/assets/javascripts/discourse/initializers/chat-decorators.js
+++ b/plugins/chat/assets/javascripts/discourse/initializers/chat-decorators.js
@@ -2,10 +2,10 @@ import { decorateGithubOneboxBody } from "discourse/instance-initializers/onebox
import { samePrefix } from "discourse/lib/get-url";
import { decorateHashtags } from "discourse/lib/hashtag-decorator";
import highlightSyntax from "discourse/lib/highlight-syntax";
+import lightbox from "discourse/lib/lightbox";
import { withPluginApi } from "discourse/lib/plugin-api";
import DiscourseURL from "discourse/lib/url";
import { i18n } from "discourse-i18n";
-import loadLightbox from "../lib/lightbox";
export default {
name: "chat-decorators",
@@ -64,7 +64,7 @@ export default {
api.decorateChatMessage(this.forceLinksToOpenNewTab, {
id: "linksNewTab",
});
- api.decorateChatMessage((element) => loadLightbox(element, siteSettings), {
+ api.decorateChatMessage((element) => lightbox(element), {
id: "lightbox",
});
api.decorateChatMessage((element) => decorateHashtags(element, site), {
diff --git a/plugins/chat/assets/javascripts/discourse/initializers/chat-keyboard-shortcuts.js b/plugins/chat/assets/javascripts/discourse/initializers/chat-keyboard-shortcuts.js
index b2aae0da26493..5c0612b53a392 100644
--- a/plugins/chat/assets/javascripts/discourse/initializers/chat-keyboard-shortcuts.js
+++ b/plugins/chat/assets/javascripts/discourse/initializers/chat-keyboard-shortcuts.js
@@ -22,7 +22,6 @@ export default {
const chatChannelsManager = container.lookup(
"service:chat-channels-manager"
);
- const siteSettings = container.lookup("service:site-settings");
const openQuickChannelSelector = (e) => {
if (isInputSelection(event.target) && !isChatComposer(event.target)) {
@@ -104,10 +103,7 @@ export default {
const closeChat = (event) => {
// when escaping from lightbox, do not close chat
- const lightboxClass = siteSettings.experimental_lightbox
- ? "lightbox"
- : "mfp-wrap";
- if (event.srcElement?.classList?.value?.includes(lightboxClass)) {
+ if (event.srcElement?.classList?.value?.includes("lightbox")) {
return;
}
diff --git a/plugins/chat/assets/javascripts/discourse/lib/lightbox.js b/plugins/chat/assets/javascripts/discourse/lib/lightbox.js
deleted file mode 100644
index 995aab910bf62..0000000000000
--- a/plugins/chat/assets/javascripts/discourse/lib/lightbox.js
+++ /dev/null
@@ -1,50 +0,0 @@
-import $ from "jquery";
-import { spinnerHTML } from "discourse/helpers/loading-spinner";
-import lightbox, { loadMagnificPopup } from "discourse/lib/lightbox";
-import { i18n } from "discourse-i18n";
-
-export default function loadLightbox(element, siteSettings) {
- if (!element) {
- return;
- }
-
- if (siteSettings.experimental_lightbox) {
- lightbox(element, siteSettings);
- return;
- }
-
- // catches chat message uploads and quoted images
- const images = element?.querySelectorAll("img:not(.emoji, .avatar)");
-
- if (!images.length) {
- return;
- }
-
- loadMagnificPopup().then(function () {
- $(images).magnificPopup({
- type: "image",
- closeOnContentClick: false,
- mainClass: "mfp-zoom-in",
- tClose: i18n("lightbox.close"),
- tLoading: spinnerHTML,
- image: {
- verticalFit: true,
- },
- gallery: {
- enabled: true,
- },
- callbacks: {
- elementParse: (item) => {
- item.src = item.el[0].dataset.largeSrc || item.el[0].src;
- },
- open: function () {
- this.touchActionValue = document.body.style.touchAction;
- document.body.style.touchAction = "";
- },
- close: function () {
- document.body.style.touchAction = this.touchActionValue;
- },
- },
- });
- });
-}
diff --git a/plugins/chat/spec/system/channel_message_upload_spec.rb b/plugins/chat/spec/system/channel_message_upload_spec.rb
index 1063d8abc5fc3..17512f36c7b8e 100644
--- a/plugins/chat/spec/system/channel_message_upload_spec.rb
+++ b/plugins/chat/spec/system/channel_message_upload_spec.rb
@@ -25,7 +25,6 @@
end
it "can collapse/expand an image and still have lightbox working" do
- SiteSetting.experimental_lightbox = false
chat.visit_channel(channel_1)
find(".chat-message-collapser-button").click
@@ -34,16 +33,7 @@
expect(page).to have_no_css(".chat-message-collapser-body.hidden")
find(".chat-img-upload").click
- # visible false is because the upload doesn’t exist but it's enough to know lightbox is working
- expect(page).to have_css(".mfp-image-holder img[src*='#{image.url}']", visible: :hidden)
- end
-
- it "can open image in lightbox when using PhotoSwipe" do
- SiteSetting.experimental_lightbox = true
-
- chat.visit_channel(channel_1)
- find(".chat-img-upload").click
-
- expect(page).to have_css(".pswp")
+ # upload doesn’t exist but it's enough to know lightbox is working
+ expect(page).to have_css(".pswp--open")
end
end
diff --git a/plugins/chat/spec/system/shortcuts/drawer_spec.rb b/plugins/chat/spec/system/shortcuts/drawer_spec.rb
index 75b8806b8ad6f..cbf3bf31f7c20 100644
--- a/plugins/chat/spec/system/shortcuts/drawer_spec.rb
+++ b/plugins/chat/spec/system/shortcuts/drawer_spec.rb
@@ -65,8 +65,6 @@
Fabricate(:chat_message, chat_channel: channel_1, upload_ids: [upload.id])
end
- before { SiteSetting.experimental_lightbox = true }
-
it "does not close the drawer" do
expect(chat_page).to have_drawer
diff --git a/plugins/chat/test/javascripts/acceptance/chat-live-pane-collapse-test.js b/plugins/chat/test/javascripts/acceptance/chat-live-pane-collapse-test.js
index 470e8399684c7..ed07297e1a7b0 100644
--- a/plugins/chat/test/javascripts/acceptance/chat-live-pane-collapse-test.js
+++ b/plugins/chat/test/javascripts/acceptance/chat-live-pane-collapse-test.js
@@ -141,14 +141,14 @@ acceptance("Discourse Chat - Chat live pane collapse", function (needs) {
await click(image);
- assert.dom(".mfp-img").exists("can see lightbox");
- await click(".mfp-container");
+ assert.dom(".pswp--open").exists("can see lightbox");
+ await click(".pswp__bg");
await click(collapseImage);
await click(expandImage);
await click(image);
- assert.dom(".mfp-img").exists("can see lightbox after collapse expand");
- await click(".mfp-container");
+ assert.dom(".pswp--open").exists("can see lightbox after collapse expand");
+ await click(".pswp__bg");
});
});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 45a0b60670580..5ed31dcf7c826 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -319,9 +319,6 @@ importers:
jspreadsheet-ce:
specifier: ^4.15.0
version: 4.15.0
- magnific-popup:
- specifier: 1.1.0
- version: 1.1.0
moment:
specifier: 2.30.1
version: 2.30.1
@@ -6487,10 +6484,6 @@ packages:
magic-string@0.30.21:
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
- magnific-popup@1.1.0:
- resolution: {integrity: sha512-ghSa/1TKsOUL6ZlHfcfFCoB9Wms2nqaDdBEPh6QX9jFYQyMkUu7ciU1mrxedWWq4NM2m1C/llhHKLt6GKRYOzg==}
- engines: {node: '>= 0.8.0'}
-
make-dir@3.1.0:
resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
engines: {node: '>=8'}
@@ -16211,8 +16204,6 @@ snapshots:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
- magnific-popup@1.1.0: {}
-
make-dir@3.1.0:
dependencies:
semver: 6.3.1
diff --git a/spec/system/admin_about_config_area_spec.rb b/spec/system/admin_about_config_area_spec.rb
index 9643c189b578f..6ac1fe06af92a 100644
--- a/spec/system/admin_about_config_area_spec.rb
+++ b/spec/system/admin_about_config_area_spec.rb
@@ -88,7 +88,6 @@
describe "the general settings card" do
it "can saves its fields to their corresponding site settings" do
- SiteSetting.experimental_lightbox = false
config_area.visit
image_file = file_from_fixtures("logo.png", "images")
diff --git a/spec/system/lightbox_spec.rb b/spec/system/lightbox_spec.rb
index d1109e60eaf15..fd0dd40105189 100644
--- a/spec/system/lightbox_spec.rb
+++ b/spec/system/lightbox_spec.rb
@@ -14,7 +14,6 @@
let(:cpp) { CookedPostProcessor.new(post, disable_dominant_color: true) }
before do
- SiteSetting.experimental_lightbox = true
SiteSetting.create_thumbnails = true
sign_in(current_user)
diff --git a/spec/system/page_objects/components/uppy_image_uploader.rb b/spec/system/page_objects/components/uppy_image_uploader.rb
index 6beb7c1ce8d04..b895ca6daa3b3 100644
--- a/spec/system/page_objects/components/uppy_image_uploader.rb
+++ b/spec/system/page_objects/components/uppy_image_uploader.rb
@@ -40,11 +40,11 @@ def toggle_lightbox_preview
end
def close_lightbox_preview
- find(".mfp-close").click
+ find(".pswp__button--close").click
end
def has_lightbox_preview?
- has_css?(".mfp-container")
+ has_css?(".pswp--open")
end
end
end