feat(web): add zoom toggle icon (#2873)

* feat(web): add zoom toggle icon

* update zoom-image dependency

* fix lint issues

* remove variable testing line

* Simplify code using ternary conditional

Co-authored-by: Thomas <9749173+uhthomas@users.noreply.github.com>

* fix typo

---------

Co-authored-by: Thomas <9749173+uhthomas@users.noreply.github.com>
This commit is contained in:
Manuel Taberna 2023-06-20 16:36:38 +02:00 committed by GitHub
parent f9fbf1a2a5
commit 48e4ea5231
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 45 additions and 3 deletions

1
web/src/app.d.ts vendored
View File

@ -29,5 +29,6 @@ declare namespace svelteHTML {
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
interface HTMLAttributes<T> { interface HTMLAttributes<T> {
'on:copyImage'?: () => void; 'on:copyImage'?: () => void;
'on:zoomImage'?: () => void;
} }
} }

View File

@ -11,14 +11,18 @@
import Heart from 'svelte-material-icons/Heart.svelte'; import Heart from 'svelte-material-icons/Heart.svelte';
import HeartOutline from 'svelte-material-icons/HeartOutline.svelte'; import HeartOutline from 'svelte-material-icons/HeartOutline.svelte';
import InformationOutline from 'svelte-material-icons/InformationOutline.svelte'; import InformationOutline from 'svelte-material-icons/InformationOutline.svelte';
import MagnifyPlusOutline from 'svelte-material-icons/MagnifyPlusOutline.svelte';
import MagnifyMinusOutline from 'svelte-material-icons/MagnifyMinusOutline.svelte';
import MotionPauseOutline from 'svelte-material-icons/MotionPauseOutline.svelte'; import MotionPauseOutline from 'svelte-material-icons/MotionPauseOutline.svelte';
import MotionPlayOutline from 'svelte-material-icons/MotionPlayOutline.svelte'; import MotionPlayOutline from 'svelte-material-icons/MotionPlayOutline.svelte';
import CircleIconButton from '../elements/buttons/circle-icon-button.svelte'; import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
import ContextMenu from '../shared-components/context-menu/context-menu.svelte'; import ContextMenu from '../shared-components/context-menu/context-menu.svelte';
import MenuOption from '../shared-components/context-menu/menu-option.svelte'; import MenuOption from '../shared-components/context-menu/menu-option.svelte';
import { photoZoomState } from '$lib/stores/zoom-image.store';
export let asset: AssetResponseDto; export let asset: AssetResponseDto;
export let showCopyButton: boolean; export let showCopyButton: boolean;
export let showZoomButton: boolean;
export let showMotionPlayButton: boolean; export let showMotionPlayButton: boolean;
export let isMotionPhotoPlaying = false; export let isMotionPhotoPlaying = false;
export let showDownloadButton: boolean; export let showDownloadButton: boolean;
@ -65,6 +69,20 @@
/> />
{/if} {/if}
{/if} {/if}
{#if showZoomButton}
<CircleIconButton
isOpacity={true}
hideMobile={true}
logo={$photoZoomState && $photoZoomState.currentZoom > 1
? MagnifyMinusOutline
: MagnifyPlusOutline}
title="Zoom Image"
on:click={() => {
const zoomImage = new CustomEvent('zoomImage');
window.dispatchEvent(zoomImage);
}}
/>
{/if}
{#if showCopyButton} {#if showCopyButton}
<CircleIconButton <CircleIconButton
isOpacity={true} isOpacity={true}

View File

@ -308,6 +308,7 @@
{asset} {asset}
isMotionPhotoPlaying={shouldPlayMotionPhoto} isMotionPhotoPlaying={shouldPlayMotionPhoto}
showCopyButton={canCopyImagesToClipboard && asset.type === AssetTypeEnum.Image} showCopyButton={canCopyImagesToClipboard && asset.type === AssetTypeEnum.Image}
showZoomButton={asset.type === AssetTypeEnum.Image}
showMotionPlayButton={!!asset.livePhotoVideoId} showMotionPlayButton={!!asset.livePhotoVideoId}
showDownloadButton={shouldShowDownloadButton} showDownloadButton={shouldShowDownloadButton}
on:goBack={closeViewer} on:goBack={closeViewer}

View File

@ -8,6 +8,7 @@
NotificationType NotificationType
} from '../shared-components/notification/notification'; } from '../shared-components/notification/notification';
import { useZoomImageWheel } from '@zoom-image/svelte'; import { useZoomImageWheel } from '@zoom-image/svelte';
import { photoZoomState } from '$lib/stores/zoom-image.store';
export let asset: AssetResponseDto; export let asset: AssetResponseDto;
export let publicSharedKey = ''; export let publicSharedKey = '';
@ -73,7 +74,22 @@
} }
}; };
const { createZoomImage: createZoomImageWheel } = useZoomImageWheel(); const doZoomImage = async () => {
setZoomImageWheelState({
currentZoom: $zoomImageWheelState.currentZoom === 1 ? 2 : 1
});
};
const {
createZoomImage: createZoomImageWheel,
zoomImageState: zoomImageWheelState,
setZoomImageState: setZoomImageWheelState
} = useZoomImageWheel();
zoomImageWheelState.subscribe((state) => {
photoZoomState.set(state);
});
$: if (imgElement) { $: if (imgElement) {
createZoomImageWheel(imgElement, { createZoomImageWheel(imgElement, {
wheelZoomRatio: 0.06 wheelZoomRatio: 0.06
@ -81,7 +97,7 @@
} }
</script> </script>
<svelte:window on:keydown={handleKeypress} on:copyImage={doCopy} /> <svelte:window on:keydown={handleKeypress} on:copyImage={doCopy} on:zoomImage={doZoomImage} />
<div <div
transition:fade={{ duration: 150 }} transition:fade={{ duration: 150 }}

View File

@ -8,6 +8,7 @@
export let title = ''; export let title = '';
export let isOpacity = false; export let isOpacity = false;
export let forceDark = false; export let forceDark = false;
export let hideMobile = false;
</script> </script>
<button <button
@ -17,7 +18,8 @@
class:dark:text-immich-dark-fg={!forceDark} class:dark:text-immich-dark-fg={!forceDark}
class="rounded-full p-3 flex place-items-center place-content-center transition-all class="rounded-full p-3 flex place-items-center place-content-center transition-all
{isOpacity ? 'hover:bg-immich-bg/30' : 'immich-circle-icon-button hover:dark:text-immich-dark-gray'} {isOpacity ? 'hover:bg-immich-bg/30' : 'immich-circle-icon-button hover:dark:text-immich-dark-gray'}
{forceDark && 'hover:text-black'}" {forceDark && 'hover:text-black'}
{hideMobile && 'hidden sm:flex'}"
on:click on:click
> >
<svelte:component this={logo} {size} /> <svelte:component this={logo} {size} />

View File

@ -0,0 +1,4 @@
import { writable } from 'svelte/store';
import type { ZoomImageWheelState } from '@zoom-image/core';
export const photoZoomState = writable<ZoomImageWheelState>();