mirror of
https://github.com/immich-app/immich
synced 2025-06-08 04:11:01 +00:00
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:
parent
df927dd3ce
commit
d544053c67
@ -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",
|
||||
|
@ -352,7 +352,9 @@
|
||||
const handleUpdateSelectedEditType = (type: string) => {
|
||||
selectedEditType = type;
|
||||
};
|
||||
|
||||
let isFullScreen = $derived(fullscreenElement !== null);
|
||||
|
||||
$effect(() => {
|
||||
if (asset) {
|
||||
previewStackedAsset = undefined;
|
||||
|
@ -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 },
|
||||
|
@ -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}
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user