From dae01ac99d5804b74158cc0ca69e6cec9686654b Mon Sep 17 00:00:00 2001 From: Mister-Hope Date: Sat, 21 Dec 2024 14:52:06 +0800 Subject: [PATCH] fix(plugin-photo-swipe): avoid loading multiple instances at startup (#317) --- .../src/client/composables/usePhotoSwipe.ts | 114 ++++++++++-------- 1 file changed, 64 insertions(+), 50 deletions(-) diff --git a/plugins/features/plugin-photo-swipe/src/client/composables/usePhotoSwipe.ts b/plugins/features/plugin-photo-swipe/src/client/composables/usePhotoSwipe.ts index 6f7cc1b277..5a9529285b 100644 --- a/plugins/features/plugin-photo-swipe/src/client/composables/usePhotoSwipe.ts +++ b/plugins/features/plugin-photo-swipe/src/client/composables/usePhotoSwipe.ts @@ -55,71 +55,85 @@ export const usePhotoSwipe = ({ scrollToClose, })) + let photoSwipeLoader: Promise | null = null let photoSwipeId = 0 let photoSwipe: PhotoSwipe | null = null - const handlePhotoSwipe = async (event: MouseEvent): Promise => { + const initPhotoSwipe = async (event: MouseEvent): Promise => { const el = event.target as HTMLImageElement - if (imageSelector.value && el.matches(imageSelector.value)) { - photoSwipe?.destroy() - - const { default: PhotoSwipe } = await import( - /* webpackChunkName: "photo-swipe" */ 'photoswipe' - ) - - const images = Array.from( - document.querySelectorAll(imageSelector.value), - ) - const currentIndex = images.findIndex((image) => image === el) - - const dataSource = images.map((image) => ({ - html: LOADING_ICON, - element: image, - msrc: image.src, - })) - - dataSource.splice(currentIndex, 1, await resolveImageInfoFromElement(el)) - - const id = Date.now() - - photoSwipeId = id - photoSwipe = new PhotoSwipe({ - preloaderDelay: 0, - showHideAnimationType: 'zoom', - ...options, - dataSource, - index: currentIndex, - ...(scrollToClose - ? { closeOnVerticalDrag: true, wheelToZoom: false } - : {}), - }) - - setupPhotoSwipe(photoSwipe, { download, fullscreen }) + if ( + // not enabled + !imageSelector.value || + // Photoswipe is not being loaded + !photoSwipeLoader || + // not an matched element + !el.matches(imageSelector.value) + ) + return + + // there is an active instance + if (photoSwipeId !== 0) photoSwipe!.destroy() + + const id = Date.now() + const PhotoSwipeConstructor = await photoSwipeLoader + + const images = Array.from( + document.querySelectorAll(imageSelector.value), + ) + const dataSource = images.map((image) => ({ + html: LOADING_ICON, + element: image, + msrc: image.src, + })) + + const index = images.findIndex((image) => image === el) + + photoSwipe = new PhotoSwipeConstructor({ + preloaderDelay: 0, + showHideAnimationType: 'zoom', + ...options, + dataSource, + index, + ...(scrollToClose + ? { closeOnVerticalDrag: true, wheelToZoom: false } + : {}), + }) + photoSwipeId = id - photoSwipe.init() + setupPhotoSwipe(photoSwipe, { download, fullscreen }) - photoSwipe.on('destroy', () => { - photoSwipe = null - photoSwipeId = 0 - }) + photoSwipe.init() - images.forEach((image, index) => { - if (index === currentIndex || photoSwipeId !== id) return + photoSwipe.on('destroy', () => { + photoSwipe = null + photoSwipeId = 0 + }) - void resolveImageInfoFromElement(image).then((data) => { - dataSource.splice(index, 1, data) - photoSwipe?.refreshSlideContent(index) - }) - }) - } + void images.map((image, imageIndex) => + resolveImageInfoFromElement(image).then((data) => { + if (photoSwipeId !== id) return + dataSource.splice(imageIndex, 1, data) + photoSwipe?.refreshSlideContent(imageIndex) + }), + ) } onMounted(() => { - useEventListener('click', handlePhotoSwipe) + const rIC = + 'requestIdleCallback' in window ? window.requestIdleCallback : setTimeout + + useEventListener('click', initPhotoSwipe) useEventListener('wheel', () => { if (options.value.scrollToClose) photoSwipe?.close() }) + rIC(() => { + photoSwipeLoader = import( + /* webpackChunkName: "photo-swipe" */ 'photoswipe' + ).then(({ default: _PhotoSwipe }) => { + return _PhotoSwipe + }) + }) }) onUnmounted(() => {