From 4e526dfaae577336ab5a5e4aea451e722eeabdd7 Mon Sep 17 00:00:00 2001 From: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com> Date: Mon, 27 Mar 2023 05:53:35 +0200 Subject: [PATCH] feat(web): improve and refactor thumbnails (#2087) * feat(web): improve and refactor thumbnails * only play live photos on icon hover --- web/src/api/api.ts | 28 ++ .../album-page/thumbnail-selection.svelte | 4 +- .../assets/thumbnail/image-thumbnail.svelte | 19 ++ .../assets/thumbnail/thumbnail.svelte | 140 ++++++++ .../assets/thumbnail/video-thumbnail.svelte | 88 +++++ .../photos-page/asset-date-group.svelte | 4 +- .../gallery-viewer/gallery-viewer.svelte | 4 +- .../shared-components/immich-thumbnail.svelte | 311 ------------------ web/src/lib/utils/time-to-seconds.spec.ts | 24 ++ web/src/lib/utils/time-to-seconds.ts | 13 + web/src/routes/(user)/explore/+page.svelte | 16 +- 11 files changed, 321 insertions(+), 330 deletions(-) create mode 100644 web/src/lib/components/assets/thumbnail/image-thumbnail.svelte create mode 100644 web/src/lib/components/assets/thumbnail/thumbnail.svelte create mode 100644 web/src/lib/components/assets/thumbnail/video-thumbnail.svelte delete mode 100644 web/src/lib/components/shared-components/immich-thumbnail.svelte create mode 100644 web/src/lib/utils/time-to-seconds.spec.ts create mode 100644 web/src/lib/utils/time-to-seconds.ts diff --git a/web/src/api/api.ts b/web/src/api/api.ts index 329e146283..197d4598ac 100644 --- a/web/src/api/api.ts +++ b/web/src/api/api.ts @@ -12,8 +12,11 @@ import { ServerInfoApi, ShareApi, SystemConfigApi, + ThumbnailFormat, UserApi } from './open-api'; +import { BASE_PATH } from './open-api/base'; +import { DUMMY_BASE_URL, toPathString } from './open-api/common'; export class ImmichApi { public userApi: UserApi; @@ -48,6 +51,21 @@ export class ImmichApi { this.shareApi = new ShareApi(this.config); } + private createUrl(path: string, params?: Record) { + const searchParams = new URLSearchParams(); + for (const key in params) { + const value = params[key]; + if (value !== undefined && value !== null) { + searchParams.set(key, value.toString()); + } + } + + const url = new URL(path, DUMMY_BASE_URL); + url.search = searchParams.toString(); + + return (this.config.basePath || BASE_PATH) + toPathString(url); + } + public setAccessToken(accessToken: string) { this.config.accessToken = accessToken; } @@ -59,6 +77,16 @@ export class ImmichApi { public setBaseUrl(baseUrl: string) { this.config.basePath = baseUrl; } + + public getAssetFileUrl(assetId: string, isThumb?: boolean, isWeb?: boolean, key?: string) { + const path = `/asset/file/${assetId}`; + return this.createUrl(path, { isThumb, isWeb, key }); + } + + public getAssetThumbnailUrl(assetId: string, format?: ThumbnailFormat, key?: string) { + const path = `/asset/thumbnail/${assetId}`; + return this.createUrl(path, { format, key }); + } } export const api = new ImmichApi({ basePath: '/api' }); diff --git a/web/src/lib/components/album-page/thumbnail-selection.svelte b/web/src/lib/components/album-page/thumbnail-selection.svelte index 59778eca7d..1da40fb21a 100644 --- a/web/src/lib/components/album-page/thumbnail-selection.svelte +++ b/web/src/lib/components/album-page/thumbnail-selection.svelte @@ -3,8 +3,8 @@ import { createEventDispatcher } from 'svelte'; import { quintOut } from 'svelte/easing'; import { fly } from 'svelte/transition'; + import Thumbnail from '../assets/thumbnail/thumbnail.svelte'; import ControlAppBar from '../shared-components/control-app-bar.svelte'; - import ImmichThumbnail from '../shared-components/immich-thumbnail.svelte'; export let album: AlbumResponseDto; @@ -43,7 +43,7 @@
{#each album.assets as asset} - (selectedThumbnail = asset)} selected={isSelected(asset.id)} diff --git a/web/src/lib/components/assets/thumbnail/image-thumbnail.svelte b/web/src/lib/components/assets/thumbnail/image-thumbnail.svelte new file mode 100644 index 0000000000..8472a7a764 --- /dev/null +++ b/web/src/lib/components/assets/thumbnail/image-thumbnail.svelte @@ -0,0 +1,19 @@ + + +{altText} (loading = false)} +/> diff --git a/web/src/lib/components/assets/thumbnail/thumbnail.svelte b/web/src/lib/components/assets/thumbnail/thumbnail.svelte new file mode 100644 index 0000000000..daf18873b3 --- /dev/null +++ b/web/src/lib/components/assets/thumbnail/thumbnail.svelte @@ -0,0 +1,140 @@ + + + +
(mouseOver = true)} + on:mouseleave={() => (mouseOver = false)} + on:click={thumbnailClickedHandler} + on:keydown={thumbnailClickedHandler} + > + {#if intersecting} +
+ + {#if !readonly} + + {/if} +
+ +
+ +
+ + + {#if asset.isFavorite && !publicSharedKey} +
+ +
+ {/if} + + + + {#if asset.type === AssetTypeEnum.Video} +
+ +
+ {/if} + + {#if asset.type === AssetTypeEnum.Image && asset.livePhotoVideoId} +
+ +
+ {/if} +
+ {/if} +
+ diff --git a/web/src/lib/components/assets/thumbnail/video-thumbnail.svelte b/web/src/lib/components/assets/thumbnail/video-thumbnail.svelte new file mode 100644 index 0000000000..b8690794df --- /dev/null +++ b/web/src/lib/components/assets/thumbnail/video-thumbnail.svelte @@ -0,0 +1,88 @@ + + +
+ {#if showTime} + + {Duration.fromObject({ seconds: remainingSeconds }).toFormat('m:ss')} + + {/if} + + { + if (playbackOnIconHover) { + enablePlayback = true; + } + }} + on:mouseleave={() => { + if (playbackOnIconHover) { + enablePlayback = false; + } + }} + > + {#if enablePlayback} + {#if loading} + + {:else if error} + + {:else} + + {/if} + {:else} + + {/if} + +
+ +{#if enablePlayback} +