Skip to content

Commit dacfbdd

Browse files
committed
Pause gallery auto-advance on YouTube videos
1 parent b5cf6d0 commit dacfbdd

2 files changed

Lines changed: 26 additions & 3 deletions

File tree

frontend/src/modules/project/components/GalleryCarouselViewer.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ export const GalleryCarouselViewer: React.FC<GalleryCarouselViewerProps> = ({
7373
const rawActiveIndex = isControlled ? activeIndex : localActiveIndex;
7474
const safeActiveIndex = clampIndex(rawActiveIndex, imageCount);
7575
const activeImage = resolvedImages[safeActiveIndex] || resolvedImages[0];
76+
const shouldAutoAdvance = autoAdvance && activeImage?.type !== 'youtube';
7677

7778
const setActiveIndex = useCallback((nextValue: number | ((current: number) => number)) => {
7879
const nextIndex = clampIndex(
@@ -101,14 +102,14 @@ export const GalleryCarouselViewer: React.FC<GalleryCarouselViewerProps> = ({
101102
}, [imageCount, isControlled, onActiveIndexChange, rawActiveIndex, safeActiveIndex]);
102103

103104
useEffect(() => {
104-
if (!autoAdvance || imageCount <= 1) return;
105+
if (!shouldAutoAdvance || imageCount <= 1) return;
105106

106107
const timer = window.setTimeout(() => {
107108
setActiveIndex((prev) => (prev + 1) % imageCount);
108109
}, AUTO_ADVANCE_MS);
109110

110111
return () => window.clearTimeout(timer);
111-
}, [autoAdvance, imageCount, safeActiveIndex, setActiveIndex]);
112+
}, [imageCount, safeActiveIndex, setActiveIndex, shouldAutoAdvance]);
112113

113114
useEffect(() => {
114115
if (imageCount <= 1) return;
@@ -221,7 +222,7 @@ export const GalleryCarouselViewer: React.FC<GalleryCarouselViewerProps> = ({
221222
<div className="absolute bottom-3 left-1/2 -translate-x-1/2 rounded-full bg-blue-950/80 px-3 py-1 text-xs font-black tracking-wider text-white shadow-lg sm:hidden">
222223
{safeActiveIndex + 1} / {imageCount}
223224
</div>
224-
{autoAdvance && (
225+
{shouldAutoAdvance && (
225226
<div className="absolute bottom-0 left-0 right-0 h-1 bg-blue-950/40" aria-hidden="true">
226227
<div
227228
key={`${activeImage.url}-${safeActiveIndex}`}

frontend/tests/modules/project/components/GalleryCarousel.test.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,28 @@ describe('GalleryCarousel', () => {
102102
expect(iframe.getAttribute('src')).toBe('https://www.youtube-nocookie.com/embed/dQw4w9WgXcQ');
103103
});
104104

105+
it('does not auto-advance while a youtube video is active', async () => {
106+
vi.useFakeTimers();
107+
108+
await act(async () => {
109+
root.render(
110+
<GalleryCarousel
111+
images={['https://www.youtube.com/watch?v=dQw4w9WgXcQ', '/two.png']}
112+
title="Skyforge"
113+
/>
114+
);
115+
});
116+
117+
expect(container.querySelector('iframe[title="Skyforge gallery video 1"]')).not.toBeNull();
118+
119+
await act(async () => {
120+
vi.advanceTimersByTime(16000);
121+
});
122+
123+
expect(container.querySelector('iframe[title="Skyforge gallery video 1"]')).not.toBeNull();
124+
expect(container.querySelector('img[alt="Skyforge gallery image 2"]')).toBeNull();
125+
});
126+
105127
it('supports a controlled active index for the gallery popup', async () => {
106128
const onActiveIndexChange = vi.fn();
107129

0 commit comments

Comments
 (0)