diff --git a/web/src/lib/components/asset-viewer/detail-panel-tags.svelte b/web/src/lib/components/asset-viewer/detail-panel-tags.svelte index 4dd05f520a..c971933f88 100644 --- a/web/src/lib/components/asset-viewer/detail-panel-tags.svelte +++ b/web/src/lib/components/asset-viewer/detail-panel-tags.svelte @@ -21,7 +21,6 @@ const handleAddTag = async () => { const success = await modalManager.show(AssetTagModal, { assetIds: [asset.id] }); - if (success) { asset = await getAssetInfo({ id: asset.id }); } diff --git a/web/src/lib/components/asset-viewer/detail-panel.svelte b/web/src/lib/components/asset-viewer/detail-panel.svelte index 3bcac83914..c115558923 100644 --- a/web/src/lib/components/asset-viewer/detail-panel.svelte +++ b/web/src/lib/components/asset-viewer/detail-panel.svelte @@ -16,21 +16,14 @@ import { locale } from '$lib/stores/preferences.store'; import { featureFlags } from '$lib/stores/server-config.store'; import { preferences, user } from '$lib/stores/user.store'; - import { getAssetThumbnailUrl, getPeopleThumbnailUrl, handlePromiseError } from '$lib/utils'; - import { delay, isFlipped } from '$lib/utils/asset-utils'; + import { getAssetThumbnailUrl, 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 { getMetadataSearchQuery } from '$lib/utils/metadata-search'; import { fromISODateTime, fromISODateTimeUTC } from '$lib/utils/timeline-util'; import { getParentPath } from '$lib/utils/tree-utils'; - import { - AssetMediaSize, - getAssetInfo, - updateAsset, - type AlbumResponseDto, - type AssetResponseDto, - type ExifResponseDto, - } from '@immich/sdk'; + import { AssetMediaSize, getAssetInfo, updateAsset, type AlbumResponseDto, type AssetResponseDto } from '@immich/sdk'; import { IconButton } from '@immich/ui'; import { mdiCalendar, @@ -61,17 +54,28 @@ let { asset, albums = [], currentAlbum = null, onClose }: Props = $props(); - const getDimensions = (exifInfo: ExifResponseDto) => { - const { exifImageWidth: width, exifImageHeight: height } = exifInfo; - if (isFlipped(exifInfo.orientation)) { - return { width: height, height: width }; - } - - return { width, height }; - }; - let showAssetPath = $state(false); let showEditFaces = $state(false); + let isOwner = $derived($user?.id === asset.ownerId); + let people = $derived(asset.people || []); + let unassignedFaces = $derived(asset.unassignedFaces || []); + let showingHiddenPeople = $state(false); + let timeZone = $derived(asset.exifInfo?.timeZone); + let dateTime = $derived( + timeZone && asset.exifInfo?.dateTimeOriginal + ? fromISODateTime(asset.exifInfo.dateTimeOriginal, timeZone) + : fromISODateTimeUTC(asset.localDateTime), + ); + let latlng = $derived( + (() => { + const lat = asset.exifInfo?.latitude; + const lng = asset.exifInfo?.longitude; + + if (lat && lng) { + return { lat: Number(lat.toFixed(7)), lng: Number(lng.toFixed(7)) }; + } + })(), + ); let previousId: string | undefined = $state(); $effect(() => { @@ -84,42 +88,6 @@ } }); - let isOwner = $derived($user?.id === asset.ownerId); - - const handleNewAsset = async (newAsset: AssetResponseDto) => { - // TODO: check if reloading asset data is necessary - if (newAsset.id && !authManager.isSharedLink) { - const data = await getAssetInfo({ id: asset.id }); - people = data?.people || []; - unassignedFaces = data?.unassignedFaces || []; - } - }; - - $effect(() => { - handlePromiseError(handleNewAsset(asset)); - }); - - let latlng = $derived( - (() => { - const lat = asset.exifInfo?.latitude; - const lng = asset.exifInfo?.longitude; - - if (lat && lng) { - return { lat: Number(lat.toFixed(7)), lng: Number(lng.toFixed(7)) }; - } - })(), - ); - - let people = $state(asset.people || []); - let unassignedFaces = $state(asset.unassignedFaces || []); - let showingHiddenPeople = $state(false); - let timeZone = $derived(asset.exifInfo?.timeZone); - let dateTime = $derived( - timeZone && asset.exifInfo?.dateTimeOriginal - ? fromISODateTime(asset.exifInfo.dateTimeOriginal, timeZone) - : fromISODateTimeUTC(asset.localDateTime), - ); - const getMegapixel = (width: number, height: number): number | undefined => { const megapixel = Math.round((height * width) / 1_000_000); @@ -131,10 +99,7 @@ }; const handleRefreshPeople = async () => { - await getAssetInfo({ id: asset.id }).then((data) => { - people = data?.people || []; - unassignedFaces = data?.unassignedFaces || []; - }); + asset = await getAssetInfo({ id: asset.id }); showEditFaces = false; }; diff --git a/web/src/lib/components/utilities-page/duplicates/duplicates-compare-control.svelte b/web/src/lib/components/utilities-page/duplicates/duplicates-compare-control.svelte index ccc0249043..70e0aab076 100644 --- a/web/src/lib/components/utilities-page/duplicates/duplicates-compare-control.svelte +++ b/web/src/lib/components/utilities-page/duplicates/duplicates-compare-control.svelte @@ -2,11 +2,12 @@ import { shortcuts } from '$lib/actions/shortcut'; import Portal from '$lib/components/shared-components/portal/portal.svelte'; import DuplicateAsset from '$lib/components/utilities-page/duplicates/duplicate-asset.svelte'; + import { authManager } from '$lib/managers/auth-manager.svelte'; import { assetViewingStore } from '$lib/stores/asset-viewing.store'; import { handlePromiseError } from '$lib/utils'; import { suggestDuplicate } from '$lib/utils/duplicate-utils'; import { navigate } from '$lib/utils/navigation'; - import { type AssetResponseDto } from '@immich/sdk'; + import { getAssetInfo, type AssetResponseDto } from '@immich/sdk'; import { Button } from '@immich/ui'; import { mdiCheck, mdiImageMultipleOutline, mdiTrashCanOutline } from '@mdi/js'; import { onDestroy, onMount } from 'svelte'; @@ -42,32 +43,32 @@ assetViewingStore.showAssetViewer(false); }); - const onNext = () => { + const onNext = async () => { const index = getAssetIndex($viewingAsset.id) + 1; if (index >= assets.length) { - return Promise.resolve(false); + return false; } - setAsset(assets[index]); - return Promise.resolve(true); + await onViewAsset(assets[index]); + return true; }; - const onPrevious = () => { + const onPrevious = async () => { const index = getAssetIndex($viewingAsset.id) - 1; if (index < 0) { - return Promise.resolve(false); + return false; } - setAsset(assets[index]); - return Promise.resolve(true); + await onViewAsset(assets[index]); + return true; }; - const onRandom = () => { + const onRandom = async () => { if (assets.length <= 0) { - return Promise.resolve(undefined); + return; } const index = Math.floor(Math.random() * assets.length); const asset = assets[index]; - setAsset(asset); - return Promise.resolve(asset); + await onViewAsset(asset); + return { id: asset.id }; }; const onSelectAsset = (asset: AssetResponseDto) => { @@ -86,6 +87,12 @@ selectedAssetIds = new SvelteSet(assets.map((asset) => asset.id)); }; + const onViewAsset = async ({ id }: AssetResponseDto) => { + const asset = await getAssetInfo({ ...authManager.params, id }); + setAsset(asset); + await navigate({ targetRoute: 'current', assetId: asset.id }); + }; + const handleResolve = () => { const trashIds = assets.map((asset) => asset.id).filter((id) => !selectedAssetIds.has(id)); const duplicateAssetIds = assets.map((asset) => asset.id); @@ -102,9 +109,7 @@ { shortcut: { key: 'a' }, onShortcut: onSelectAll }, { shortcut: { key: 's' }, - onShortcut: () => { - setAsset(assets[0]); - }, + onShortcut: () => onViewAsset(assets[0]), }, { shortcut: { key: 'd' }, onShortcut: onSelectNone }, { shortcut: { key: 'c', shift: true }, onShortcut: handleResolve }, @@ -166,12 +171,7 @@