From a868ae3ad011f47eaae4a5a95c6f74670a152d41 Mon Sep 17 00:00:00 2001 From: Min Idzelis Date: Tue, 3 Mar 2026 06:25:03 -0500 Subject: [PATCH] perf: move album fetching into detail panel (#26632) --- .../asset-viewer/asset-viewer.svelte | 23 +---- .../asset-viewer/detail-panel.svelte | 96 ++++++++++++------- 2 files changed, 66 insertions(+), 53 deletions(-) diff --git a/web/src/lib/components/asset-viewer/asset-viewer.svelte b/web/src/lib/components/asset-viewer/asset-viewer.svelte index 21077c63ae..786f9fd0ec 100644 --- a/web/src/lib/components/asset-viewer/asset-viewer.svelte +++ b/web/src/lib/components/asset-viewer/asset-viewer.svelte @@ -30,7 +30,6 @@ import { toTimelineAsset } from '$lib/utils/timeline-util'; import { AssetTypeEnum, - getAllAlbums, getAssetInfo, getStack, type AlbumResponseDto, @@ -105,7 +104,6 @@ const asset = $derived(cursor.current); const nextAsset = $derived(cursor.nextAsset); const previousAsset = $derived(cursor.previousAsset); - let appearsInAlbums: AlbumResponseDto[] = $state([]); let sharedLink = getSharedLink(); let previewStackedAsset: AssetResponseDto | undefined = $state(); let fullscreenElement = $state(); @@ -147,7 +145,7 @@ } }; - onMount(async () => { + onMount(() => { syncAssetViewerOpenClass(true); unsubscribes.push( slideshowState.subscribe((value) => { @@ -166,8 +164,6 @@ } }), ); - - await onAlbumAddAssets(); }); onDestroy(() => { @@ -180,18 +176,6 @@ syncAssetViewerOpenClass(false); }); - const onAlbumAddAssets = async () => { - if (authManager.isSharedLink) { - return; - } - - try { - appearsInAlbums = await getAllAlbums({ assetId: asset.id }); - } catch (error) { - console.error('Error getting album that asset belong to', error); - } - }; - const closeViewer = () => { onClose?.(asset); }; @@ -363,7 +347,6 @@ const refresh = async () => { await refreshStack(); - await onAlbumAddAssets(); ocrManager.clear(); if (!sharedLink) { if (previewStackedAsset) { @@ -441,7 +424,7 @@ - + @@ -586,7 +569,7 @@ > {#if showDetailPanel}
- +
{:else if assetViewerManager.isShowEditor}
diff --git a/web/src/lib/components/asset-viewer/detail-panel.svelte b/web/src/lib/components/asset-viewer/detail-panel.svelte index 6e934874e9..e80d376f57 100644 --- a/web/src/lib/components/asset-viewer/detail-panel.svelte +++ b/web/src/lib/components/asset-viewer/detail-panel.svelte @@ -17,9 +17,16 @@ import { getAssetMediaUrl, getPeopleThumbnailUrl } from '$lib/utils'; import { delay, getDimensions } from '$lib/utils/asset-utils'; import { getByteUnitString } from '$lib/utils/byte-units'; + import { handleError } from '$lib/utils/handle-error'; import { fromISODateTime, fromISODateTimeUTC, toTimelineAsset } from '$lib/utils/timeline-util'; import { getParentPath } from '$lib/utils/tree-utils'; - import { AssetMediaSize, getAssetInfo, type AlbumResponseDto, type AssetResponseDto } from '@immich/sdk'; + import { + AssetMediaSize, + getAllAlbums, + getAssetInfo, + type AlbumResponseDto, + type AssetResponseDto, + } from '@immich/sdk'; import { Icon, IconButton, LoadingSpinner, modalManager, Text } from '@immich/ui'; import { mdiCalendar, @@ -38,16 +45,16 @@ import { slide } from 'svelte/transition'; import ImageThumbnail from '../assets/thumbnail/image-thumbnail.svelte'; import PersonSidePanel from '../faces-page/person-side-panel.svelte'; + import OnEvents from '../OnEvents.svelte'; import UserAvatar from '../shared-components/user-avatar.svelte'; import AlbumListItemDetails from './album-list-item-details.svelte'; interface Props { asset: AssetResponseDto; - albums?: AlbumResponseDto[]; currentAlbum?: AlbumResponseDto | null; } - let { asset, albums = [], currentAlbum = null }: Props = $props(); + let { asset, currentAlbum = null }: Props = $props(); let showAssetPath = $state(false); let showEditFaces = $state(false); @@ -74,14 +81,33 @@ let previousId: string | undefined = $state(); let previousRoute = $derived(currentAlbum?.id ? Route.viewAlbum(currentAlbum) : Route.photos()); + const refreshAlbums = async () => { + if (authManager.isSharedLink) { + return []; + } + + try { + return await getAllAlbums({ assetId: asset.id }); + } catch (error) { + handleError(error, 'Error getting asset album membership'); + return []; + } + }; + + let albums = $derived(refreshAlbums()); + $effect(() => { if (!previousId) { previousId = asset.id; + return; } - if (asset.id !== previousId) { - showEditFaces = false; - previousId = asset.id; + + if (asset.id === previousId) { + return; } + + showEditFaces = false; + previousId = asset.id; }); const getMegapixel = (width: number, height: number): number | undefined => { @@ -119,6 +145,8 @@ }; + (albums = refreshAlbums())} /> +
{/if} -{#if albums.length > 0} -
-
- {$t('appears_in')} -
- {#each albums as album (album.id)} - -
+ {/if} +{/await} {#if $preferences?.tags?.enabled}