mirror of
https://github.com/immich-app/immich.git
synced 2025-01-01 08:31:59 +00:00
feat(web): add an option to fill the screen with the slideshow view (#8909)
* feat: add an option to fill the screen with the slideshow view * fix: rename var
This commit is contained in:
parent
4478e524f8
commit
eaf9e5e477
3 changed files with 46 additions and 12 deletions
|
@ -14,6 +14,9 @@
|
||||||
import LoadingSpinner from '../shared-components/loading-spinner.svelte';
|
import LoadingSpinner from '../shared-components/loading-spinner.svelte';
|
||||||
import { NotificationType, notificationController } from '../shared-components/notification/notification';
|
import { NotificationType, notificationController } from '../shared-components/notification/notification';
|
||||||
import { getAltText } from '$lib/utils/thumbnail-util';
|
import { getAltText } from '$lib/utils/thumbnail-util';
|
||||||
|
import { slideshowLookCssMapping, SlideshowState, slideshowStore } from '$lib/stores/slideshow.store';
|
||||||
|
|
||||||
|
const { slideshowState, slideshowLook } = slideshowStore;
|
||||||
|
|
||||||
export let asset: AssetResponseDto;
|
export let asset: AssetResponseDto;
|
||||||
export let preloadAssets: AssetResponseDto[] | null = null;
|
export let preloadAssets: AssetResponseDto[] | null = null;
|
||||||
|
@ -158,7 +161,9 @@
|
||||||
transition:fade={{ duration: haveFadeTransition ? 150 : 0 }}
|
transition:fade={{ duration: haveFadeTransition ? 150 : 0 }}
|
||||||
src={assetData}
|
src={assetData}
|
||||||
alt={getAltText(asset)}
|
alt={getAltText(asset)}
|
||||||
class="h-full w-full object-contain"
|
class="h-full w-full {$slideshowState === SlideshowState.None
|
||||||
|
? 'object-contain'
|
||||||
|
: slideshowLookCssMapping[$slideshowLook]}"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
/>
|
/>
|
||||||
{#each getBoundingBox($boundingBoxesArray, $photoZoomState, $photoViewer) as boundingbox}
|
{#each getBoundingBox($boundingBoxesArray, $photoZoomState, $photoViewer) as boundingbox}
|
||||||
|
|
|
@ -4,27 +4,34 @@
|
||||||
SettingInputFieldType,
|
SettingInputFieldType,
|
||||||
} from '$lib/components/shared-components/settings/setting-input-field.svelte';
|
} from '$lib/components/shared-components/settings/setting-input-field.svelte';
|
||||||
import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
|
import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
|
||||||
import { mdiArrowDownThin, mdiArrowUpThin, mdiShuffle } from '@mdi/js';
|
import { mdiArrowDownThin, mdiArrowUpThin, mdiFitToPageOutline, mdiFitToScreenOutline, mdiShuffle } from '@mdi/js';
|
||||||
import { SlideshowNavigation, slideshowStore } from '../stores/slideshow.store';
|
import { SlideshowLook, SlideshowNavigation, slideshowStore } from '../stores/slideshow.store';
|
||||||
import Button from './elements/buttons/button.svelte';
|
import Button from './elements/buttons/button.svelte';
|
||||||
import type { RenderedOption } from './elements/dropdown.svelte';
|
import type { RenderedOption } from './elements/dropdown.svelte';
|
||||||
import SettingDropdown from './shared-components/settings/setting-dropdown.svelte';
|
import SettingDropdown from './shared-components/settings/setting-dropdown.svelte';
|
||||||
|
|
||||||
const { slideshowDelay, showProgressBar, slideshowNavigation } = slideshowStore;
|
const { slideshowDelay, showProgressBar, slideshowNavigation, slideshowLook } = slideshowStore;
|
||||||
|
|
||||||
export let onClose = () => {};
|
export let onClose = () => {};
|
||||||
|
|
||||||
const options: Record<SlideshowNavigation, RenderedOption> = {
|
const navigationOptions: Record<SlideshowNavigation, RenderedOption> = {
|
||||||
[SlideshowNavigation.Shuffle]: { icon: mdiShuffle, title: 'Shuffle' },
|
[SlideshowNavigation.Shuffle]: { icon: mdiShuffle, title: 'Shuffle' },
|
||||||
[SlideshowNavigation.AscendingOrder]: { icon: mdiArrowUpThin, title: 'Backward' },
|
[SlideshowNavigation.AscendingOrder]: { icon: mdiArrowUpThin, title: 'Backward' },
|
||||||
[SlideshowNavigation.DescendingOrder]: { icon: mdiArrowDownThin, title: 'Forward' },
|
[SlideshowNavigation.DescendingOrder]: { icon: mdiArrowDownThin, title: 'Forward' },
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleToggle = (selectedOption: RenderedOption) => {
|
const lookOptions: Record<SlideshowLook, RenderedOption> = {
|
||||||
|
[SlideshowLook.Contain]: { icon: mdiFitToScreenOutline, title: 'Contain' },
|
||||||
|
[SlideshowLook.Cover]: { icon: mdiFitToPageOutline, title: 'Cover' },
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleToggle = <Type extends SlideshowNavigation | SlideshowLook>(
|
||||||
|
record: RenderedOption,
|
||||||
|
options: Record<Type, RenderedOption>,
|
||||||
|
): undefined | Type => {
|
||||||
for (const [key, option] of Object.entries(options)) {
|
for (const [key, option] of Object.entries(options)) {
|
||||||
if (option === selectedOption) {
|
if (option === record) {
|
||||||
$slideshowNavigation = key as SlideshowNavigation;
|
return key as Type;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -34,9 +41,19 @@
|
||||||
<div class="flex flex-col gap-4 text-immich-primary dark:text-immich-dark-primary">
|
<div class="flex flex-col gap-4 text-immich-primary dark:text-immich-dark-primary">
|
||||||
<SettingDropdown
|
<SettingDropdown
|
||||||
title="Direction"
|
title="Direction"
|
||||||
options={Object.values(options)}
|
options={Object.values(navigationOptions)}
|
||||||
selectedOption={options[$slideshowNavigation]}
|
selectedOption={navigationOptions[$slideshowNavigation]}
|
||||||
onToggle={(option) => handleToggle(option)}
|
onToggle={(option) => {
|
||||||
|
$slideshowNavigation = handleToggle(option, navigationOptions) || $slideshowNavigation;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<SettingDropdown
|
||||||
|
title="Look"
|
||||||
|
options={Object.values(lookOptions)}
|
||||||
|
selectedOption={lookOptions[$slideshowLook]}
|
||||||
|
onToggle={(option) => {
|
||||||
|
$slideshowLook = handleToggle(option, lookOptions) || $slideshowLook;
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<SettingSwitch id="show-progress-bar" title="Show Progress Bar" bind:checked={$showProgressBar} />
|
<SettingSwitch id="show-progress-bar" title="Show Progress Bar" bind:checked={$showProgressBar} />
|
||||||
<SettingInputField
|
<SettingInputField
|
||||||
|
|
|
@ -13,6 +13,16 @@ export enum SlideshowNavigation {
|
||||||
DescendingOrder = 'descending-order',
|
DescendingOrder = 'descending-order',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum SlideshowLook {
|
||||||
|
Contain = 'contain',
|
||||||
|
Cover = 'cover',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const slideshowLookCssMapping: Record<SlideshowLook, string> = {
|
||||||
|
[SlideshowLook.Contain]: 'object-contain',
|
||||||
|
[SlideshowLook.Cover]: 'object-cover',
|
||||||
|
};
|
||||||
|
|
||||||
function createSlideshowStore() {
|
function createSlideshowStore() {
|
||||||
const restartState = writable<boolean>(false);
|
const restartState = writable<boolean>(false);
|
||||||
const stopState = writable<boolean>(false);
|
const stopState = writable<boolean>(false);
|
||||||
|
@ -21,6 +31,7 @@ function createSlideshowStore() {
|
||||||
'slideshow-navigation',
|
'slideshow-navigation',
|
||||||
SlideshowNavigation.DescendingOrder,
|
SlideshowNavigation.DescendingOrder,
|
||||||
);
|
);
|
||||||
|
const slideshowLook = persisted<SlideshowLook>('slideshow-look', SlideshowLook.Contain);
|
||||||
const slideshowState = writable<SlideshowState>(SlideshowState.None);
|
const slideshowState = writable<SlideshowState>(SlideshowState.None);
|
||||||
|
|
||||||
const showProgressBar = persisted<boolean>('slideshow-show-progressbar', true);
|
const showProgressBar = persisted<boolean>('slideshow-show-progressbar', true);
|
||||||
|
@ -50,6 +61,7 @@ function createSlideshowStore() {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
slideshowNavigation,
|
slideshowNavigation,
|
||||||
|
slideshowLook,
|
||||||
slideshowState,
|
slideshowState,
|
||||||
slideshowDelay,
|
slideshowDelay,
|
||||||
showProgressBar,
|
showProgressBar,
|
||||||
|
|
Loading…
Reference in a new issue