diff --git a/i18n/en.json b/i18n/en.json index 4215f1bc0..8be82ae45 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -2118,6 +2118,8 @@ "skip_to_folders": "Skip to folders", "skip_to_tags": "Skip to tags", "slideshow": "Slideshow", + "slideshow_repeat": "Repeat slideshow", + "slideshow_repeat_description": "Loop back to beginning when slideshow ends", "slideshow_settings": "Slideshow settings", "sort_albums_by": "Sort albums by...", "sort_created": "Date created", diff --git a/web/src/lib/components/asset-viewer/asset-viewer.svelte b/web/src/lib/components/asset-viewer/asset-viewer.svelte index 15ff8ea57..ee30b8304 100644 --- a/web/src/lib/components/asset-viewer/asset-viewer.svelte +++ b/web/src/lib/components/asset-viewer/asset-viewer.svelte @@ -94,6 +94,7 @@ slideshowNavigation, slideshowState, slideshowTransition, + slideshowRepeat, } = slideshowStore; const stackThumbnailSize = 60; const stackSelectedThumbnailSize = 65; @@ -109,6 +110,7 @@ let stack: StackResponseDto | null = $state(null); let playOriginalVideo = $state($alwaysLoadOriginalVideo); + let slideshowStartAssetId = $state(); const setPlayOriginalVideo = (value: boolean) => { playOriginalVideo = value; @@ -238,6 +240,10 @@ if ($slideshowState === SlideshowState.PlaySlideshow) { if (hasNext) { $restartSlideshowProgress = true; + } else if ($slideshowRepeat && slideshowStartAssetId) { + // Loop back to starting asset + await setAssetId(slideshowStartAssetId); + $restartSlideshowProgress = true; } else { await handleStopSlideshow(); } @@ -262,6 +268,7 @@ }; const handlePlaySlideshow = async () => { + slideshowStartAssetId = asset.id; try { await assetViewerHtmlElement?.requestFullscreen?.(); } catch (error) { diff --git a/web/src/lib/modals/SlideshowSettingsModal.svelte b/web/src/lib/modals/SlideshowSettingsModal.svelte index 8a7c69705..d4230f8bf 100644 --- a/web/src/lib/modals/SlideshowSettingsModal.svelte +++ b/web/src/lib/modals/SlideshowSettingsModal.svelte @@ -20,6 +20,7 @@ slideshowLook, slideshowTransition, slideshowAutoplay, + slideshowRepeat, slideshowState, } = slideshowStore; @@ -36,6 +37,7 @@ let tempSlideshowLook = $state($slideshowLook); let tempSlideshowTransition = $state($slideshowTransition); let tempSlideshowAutoplay = $state($slideshowAutoplay); + let tempSlideshowRepeat = $state($slideshowRepeat); const navigationOptions: Record = { [SlideshowNavigation.Shuffle]: { icon: mdiShuffle, title: $t('shuffle') }, @@ -67,6 +69,7 @@ $slideshowLook = tempSlideshowLook; $slideshowTransition = tempSlideshowTransition; $slideshowAutoplay = tempSlideshowAutoplay; + $slideshowRepeat = tempSlideshowRepeat; $slideshowState = SlideshowState.PlaySlideshow; onClose(); }; @@ -104,6 +107,10 @@ + + + + {$t('admin.slideshow_duration_description')} diff --git a/web/src/lib/stores/slideshow.store.ts b/web/src/lib/stores/slideshow.store.ts index 48639f466..4b8fd8336 100644 --- a/web/src/lib/stores/slideshow.store.ts +++ b/web/src/lib/stores/slideshow.store.ts @@ -40,6 +40,7 @@ function createSlideshowStore() { const slideshowDelay = persisted('slideshow-delay', 5, {}); const slideshowTransition = persisted('slideshow-transition', true); const slideshowAutoplay = persisted('slideshow-autoplay', true, {}); + const slideshowRepeat = persisted('slideshow-repeat', false); return { restartProgress: { @@ -71,6 +72,7 @@ function createSlideshowStore() { showProgressBar, slideshowTransition, slideshowAutoplay, + slideshowRepeat, }; }