feat: loop slideshows (#25462)

* Add Repeat to the slideshow in the web UI.

* Fix typo in SlideshowSettingsModal description prop

Fixed spelling

---------

Co-authored-by: generalzero <generalzero@generalzero.org>
This commit is contained in:
Avalanche Ridings 2026-01-23 23:09:29 -05:00 committed by GitHub
parent d0d269677e
commit 497003ec57
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 18 additions and 0 deletions

View file

@ -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",

View file

@ -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<string>();
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) {

View file

@ -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, RenderedOption> = {
[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 @@
<Switch bind:checked={tempSlideshowTransition} />
</Field>
<Field label={$t('slideshow_repeat')} description={$t('slideshow_repeat_description')}>
<Switch bind:checked={tempSlideshowRepeat} />
</Field>
<Field label={$t('duration')}>
<NumberInput min={1} bind:value={tempSlideshowDelay} />
<HelperText>{$t('admin.slideshow_duration_description')}</HelperText>

View file

@ -40,6 +40,7 @@ function createSlideshowStore() {
const slideshowDelay = persisted<number>('slideshow-delay', 5, {});
const slideshowTransition = persisted<boolean>('slideshow-transition', true);
const slideshowAutoplay = persisted<boolean>('slideshow-autoplay', true, {});
const slideshowRepeat = persisted<boolean>('slideshow-repeat', false);
return {
restartProgress: {
@ -71,6 +72,7 @@ function createSlideshowStore() {
showProgressBar,
slideshowTransition,
slideshowAutoplay,
slideshowRepeat,
};
}