mirror of
				https://github.com/immich-app/immich.git
				synced 2025-10-31 10:37:11 -04:00 
			
		
		
		
	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:
		
							parent
							
								
									f9fbf1a2a5
								
							
						
					
					
						commit
						48e4ea5231
					
				
							
								
								
									
										1
									
								
								web/src/app.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								web/src/app.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -29,5 +29,6 @@ declare namespace svelteHTML { | ||||
| 	// eslint-disable-next-line @typescript-eslint/no-unused-vars
 | ||||
| 	interface HTMLAttributes<T> { | ||||
| 		'on:copyImage'?: () => void; | ||||
| 		'on:zoomImage'?: () => void; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -11,14 +11,18 @@ | ||||
| 	import Heart from 'svelte-material-icons/Heart.svelte'; | ||||
| 	import HeartOutline from 'svelte-material-icons/HeartOutline.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 MotionPlayOutline from 'svelte-material-icons/MotionPlayOutline.svelte'; | ||||
| 	import CircleIconButton from '../elements/buttons/circle-icon-button.svelte'; | ||||
| 	import ContextMenu from '../shared-components/context-menu/context-menu.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 showCopyButton: boolean; | ||||
| 	export let showZoomButton: boolean; | ||||
| 	export let showMotionPlayButton: boolean; | ||||
| 	export let isMotionPhotoPlaying = false; | ||||
| 	export let showDownloadButton: boolean; | ||||
| @ -65,6 +69,20 @@ | ||||
| 				/> | ||||
| 			{/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} | ||||
| 			<CircleIconButton | ||||
| 				isOpacity={true} | ||||
|  | ||||
| @ -308,6 +308,7 @@ | ||||
| 			{asset} | ||||
| 			isMotionPhotoPlaying={shouldPlayMotionPhoto} | ||||
| 			showCopyButton={canCopyImagesToClipboard && asset.type === AssetTypeEnum.Image} | ||||
| 			showZoomButton={asset.type === AssetTypeEnum.Image} | ||||
| 			showMotionPlayButton={!!asset.livePhotoVideoId} | ||||
| 			showDownloadButton={shouldShowDownloadButton} | ||||
| 			on:goBack={closeViewer} | ||||
|  | ||||
| @ -8,6 +8,7 @@ | ||||
| 		NotificationType | ||||
| 	} from '../shared-components/notification/notification'; | ||||
| 	import { useZoomImageWheel } from '@zoom-image/svelte'; | ||||
| 	import { photoZoomState } from '$lib/stores/zoom-image.store'; | ||||
| 
 | ||||
| 	export let asset: AssetResponseDto; | ||||
| 	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) { | ||||
| 		createZoomImageWheel(imgElement, { | ||||
| 			wheelZoomRatio: 0.06 | ||||
| @ -81,7 +97,7 @@ | ||||
| 	} | ||||
| </script> | ||||
| 
 | ||||
| <svelte:window on:keydown={handleKeypress} on:copyImage={doCopy} /> | ||||
| <svelte:window on:keydown={handleKeypress} on:copyImage={doCopy} on:zoomImage={doZoomImage} /> | ||||
| 
 | ||||
| <div | ||||
| 	transition:fade={{ duration: 150 }} | ||||
|  | ||||
| @ -8,6 +8,7 @@ | ||||
| 	export let title = ''; | ||||
| 	export let isOpacity = false; | ||||
| 	export let forceDark = false; | ||||
| 	export let hideMobile = false; | ||||
| </script> | ||||
| 
 | ||||
| <button | ||||
| @ -17,7 +18,8 @@ | ||||
| 	class:dark:text-immich-dark-fg={!forceDark} | ||||
| 	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'} | ||||
|   {forceDark && 'hover:text-black'}" | ||||
|   {forceDark && 'hover:text-black'} | ||||
|   {hideMobile && 'hidden sm:flex'}" | ||||
| 	on:click | ||||
| > | ||||
| 	<svelte:component this={logo} {size} /> | ||||
|  | ||||
							
								
								
									
										4
									
								
								web/src/lib/stores/zoom-image.store.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								web/src/lib/stores/zoom-image.store.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | ||||
| import { writable } from 'svelte/store'; | ||||
| import type { ZoomImageWheelState } from '@zoom-image/core'; | ||||
| 
 | ||||
| export const photoZoomState = writable<ZoomImageWheelState>(); | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user