feat(web): improve slideshow quality of life (#18778)

* Add a new setting to toggle autoplay when showing the slideshow.
* Fix an issue where the slideshow would restart automatically when
navigating after it was paused.
* Add a keyboard shortcut 's' to start the slideshow from the asset
viewer.
* Add a keyboard shortcut ' ' to toggle the slideshow play/paused.
* Change the timeout for hiding the slideshow controls from 10 to 2.5
seconds.
* Add English translation for the 'autoplay_slideshow' setting.

Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
Dag Stuan 2025-06-02 16:45:39 +02:00 committed by GitHub
parent df927dd3ce
commit d544053c67
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 45 additions and 11 deletions

View File

@ -477,6 +477,7 @@
"authorized_devices": "Authorized Devices",
"automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere",
"automatic_endpoint_switching_title": "Automatic URL switching",
"autoplay_slideshow": "Autoplay slideshow",
"back": "Back",
"back_close_deselect": "Back, close, or deselect",
"background_location_permission": "Background location permission",

View File

@ -352,7 +352,9 @@
const handleUpdateSelectedEditType = (type: string) => {
selectedEditType = type;
};
let isFullScreen = $derived(fullscreenElement !== null);
$effect(() => {
if (asset) {
previewStackedAsset = undefined;

View File

@ -113,6 +113,8 @@
});
};
const onPlaySlideshow = () => ($slideshowState = SlideshowState.PlaySlideshow);
$effect(() => {
if (isFaceEditMode.value && $photoZoomState.currentZoom > 1) {
zoomToggle();
@ -206,6 +208,8 @@
<svelte:document
use:shortcuts={[
{ shortcut: { key: 'z' }, onShortcut: zoomToggle, preventDefault: true },
{ shortcut: { key: 's' }, onShortcut: onPlaySlideshow, preventDefault: true },
{ shortcut: { key: 'c', ctrl: true }, onShortcut: onCopyShortcut, preventDefault: false },
{ shortcut: { key: 'c', meta: true }, onShortcut: onCopyShortcut, preventDefault: false },
{ shortcut: { key: 'z' }, onShortcut: zoomToggle, preventDefault: false },

View File

@ -28,7 +28,8 @@
onSetToFullScreen = () => {},
}: Props = $props();
const { restartProgress, stopProgress, slideshowDelay, showProgressBar, slideshowNavigation } = slideshowStore;
const { restartProgress, stopProgress, slideshowDelay, showProgressBar, slideshowNavigation, slideshowAutoplay } =
slideshowStore;
let progressBarStatus: ProgressBarStatus | undefined = $state();
let progressBar = $state<ReturnType<typeof ProgressBar>>();
@ -60,20 +61,20 @@
showControls = false;
setCursorStyle('none');
}
}, 10_000);
}, 2500);
};
onMount(() => {
hideControlsAfterDelay();
unsubscribeRestart = restartProgress.subscribe((value) => {
if (value) {
progressBar?.restart(value);
progressBar?.restart();
}
});
unsubscribeStop = stopProgress.subscribe((value) => {
if (value) {
progressBar?.restart(false);
progressBar?.restart();
stopControlsHideTimer();
}
});
@ -90,7 +91,7 @@
});
const handleDone = async () => {
await progressBar?.reset();
await progressBar?.resetProgress();
if ($slideshowNavigation === SlideshowNavigation.AscendingOrder) {
onPrevious();
@ -113,6 +114,17 @@
{ shortcut: { key: 'Escape' }, onShortcut: onClose },
{ shortcut: { key: 'ArrowLeft' }, onShortcut: onPrevious },
{ shortcut: { key: 'ArrowRight' }, onShortcut: onNext },
{
shortcut: { key: ' ' },
onShortcut: () => {
if (progressBarStatus === ProgressBarStatus.Paused) {
progressBar?.play();
} else {
progressBar?.pause();
}
},
preventDefault: true,
},
]}
/>
@ -187,7 +199,7 @@
{/if}
<ProgressBar
autoplay
autoplay={$slideshowAutoplay}
hidden={!$showProgressBar}
duration={$slideshowDelay}
bind:this={progressBar}

View File

@ -51,7 +51,11 @@
onMount(async () => {
if (autoplay) {
status = ProgressBarStatus.Playing;
await play();
} else {
status = ProgressBarStatus.Paused;
await progress.set(0);
}
});
@ -67,16 +71,15 @@
await progress.set($progress);
};
export const restart = async (autoplay: boolean) => {
export const restart = async () => {
await progress.set(0);
if (autoplay) {
if (status !== ProgressBarStatus.Paused) {
await play();
}
};
export const reset = async () => {
status = ProgressBarStatus.Paused;
export const resetProgress = async () => {
await progress.set(0);
};

View File

@ -16,7 +16,14 @@
import type { RenderedOption } from './elements/dropdown.svelte';
import SettingDropdown from './shared-components/settings/setting-dropdown.svelte';
const { slideshowDelay, showProgressBar, slideshowNavigation, slideshowLook, slideshowTransition } = slideshowStore;
const {
slideshowDelay,
showProgressBar,
slideshowNavigation,
slideshowLook,
slideshowTransition,
slideshowAutoplay,
} = slideshowStore;
interface Props {
onClose?: () => void;
@ -30,6 +37,7 @@
let tempSlideshowNavigation = $state($slideshowNavigation);
let tempSlideshowLook = $state($slideshowLook);
let tempSlideshowTransition = $state($slideshowTransition);
let tempSlideshowAutoplay = $state($slideshowAutoplay);
const navigationOptions: Record<SlideshowNavigation, RenderedOption> = {
[SlideshowNavigation.Shuffle]: { icon: mdiShuffle, title: $t('shuffle') },
@ -60,6 +68,7 @@
$slideshowNavigation = tempSlideshowNavigation;
$slideshowLook = tempSlideshowLook;
$slideshowTransition = tempSlideshowTransition;
$slideshowAutoplay = tempSlideshowAutoplay;
onClose();
};
</script>
@ -83,6 +92,7 @@
tempSlideshowLook = handleToggle(option, lookOptions) || tempSlideshowLook;
}}
/>
<SettingSwitch title={$t('autoplay_slideshow')} bind:checked={tempSlideshowAutoplay} />
<SettingSwitch title={$t('show_progress_bar')} bind:checked={tempShowProgressBar} />
<SettingSwitch title={$t('show_slideshow_transition')} bind:checked={tempSlideshowTransition} />
<SettingInputField

View File

@ -39,6 +39,7 @@ function createSlideshowStore() {
const showProgressBar = persisted<boolean>('slideshow-show-progressbar', true);
const slideshowDelay = persisted<number>('slideshow-delay', 5, {});
const slideshowTransition = persisted<boolean>('slideshow-transition', true);
const slideshowAutoplay = persisted<boolean>('slideshow-autoplay', true, {});
return {
restartProgress: {
@ -69,6 +70,7 @@ function createSlideshowStore() {
slideshowDelay,
showProgressBar,
slideshowTransition,
slideshowAutoplay,
};
}