fix(web): address review feedback on hero view transitions

Change-Id: I9f12e1616ddcf124a9926d54868b5e166a6a6964
This commit is contained in:
midzelis
2026-05-14 02:30:18 +00:00
parent c7cf2714ef
commit 51afef5ad2
14 changed files with 251 additions and 8458 deletions
+16 -13
View File
@@ -10,6 +10,7 @@
import { assetsSnapshot, filterIsInOrNearViewport } from '$lib/managers/timeline-manager/utils.svelte';
import { viewTransitionManager } from '$lib/managers/ViewTransitionManager.svelte';
import { uploadAssetsStore } from '$lib/stores/upload';
import { handlePromiseError } from '$lib/utils';
import type { CommonPosition } from '$lib/utils/layout-utils';
import { fromTimelinePlainDate, getDateLocaleString } from '$lib/utils/timeline-util';
import { Icon } from '@immich/ui';
@@ -68,19 +69,21 @@
if (!asset) {
return;
}
void viewTransitionManager.startTransition({
types: ['timeline'],
performUpdate: async () => {
assetViewerManager.emit('ViewerCloseTransitionReady');
const event = await eventManager.untilNext('TimelineLoaded');
toTimelineHeroAssetId = event.id;
await tick();
},
onFinished: () => {
toTimelineHeroAssetId = null;
focusAsset(asset.id);
},
});
handlePromiseError(
viewTransitionManager.startTransition({
types: ['timeline'],
performUpdate: async () => {
assetViewerManager.emit('ViewerCloseTransitionReady');
const event = await eventManager.untilNext('TimelineLoaded');
toTimelineHeroAssetId = event.id;
await tick();
},
onFinished: () => {
toTimelineHeroAssetId = null;
focusAsset(asset.id);
},
}),
);
};
if (viewTransitionManager.isSupported()) {
onMount(() => assetViewerManager.on({ ViewerCloseTransition: handleViewerCloseTransition }));
@@ -22,6 +22,7 @@
import type { TimelineAsset, TimelineManagerOptions, ViewportTopMonth } from '$lib/managers/timeline-manager/types';
import { assetsSnapshot } from '$lib/managers/timeline-manager/utils.svelte';
import { mediaQueryManager } from '$lib/stores/media-query-manager.svelte';
import { handlePromiseError } from '$lib/utils';
import { isAssetViewerRoute, navigate } from '$lib/utils/navigation';
import { getTimes, type ScrubberListener } from '$lib/utils/timeline-util';
import { type AlbumResponseDto, type PersonResponseDto, type UserResponseDto } from '@immich/sdk';
@@ -581,11 +582,13 @@
}
const openViewer = () => void navigate({ targetRoute: 'current', assetId: asset.id });
startViewerTransition(
asset.id,
openViewer,
(id) => (toViewerHeroAssetId = id),
() => (toViewerHeroAssetId = null),
handlePromiseError(
startViewerTransition(
asset.id,
openViewer,
(id) => (toViewerHeroAssetId = id),
() => (toViewerHeroAssetId = null),
),
);
};
</script>
@@ -99,7 +99,9 @@
const handleClose = async (assetId: string) => {
if (viewTransitionManager.isSupported()) {
const transitionReady = assetViewerManager.untilNext('ViewerCloseTransitionReady');
const transitionReady = assetViewerManager.untilNext('ViewerCloseTransitionReady', {
signal: AbortSignal.timeout(200),
});
assetViewerManager.emit('ViewerCloseTransition', { id: assetId });
await transitionReady;
}
+2 -2
View File
@@ -2,13 +2,13 @@ import { tick } from 'svelte';
import { viewTransitionManager } from '$lib/managers/ViewTransitionManager.svelte';
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
export function startViewerTransition(
export async function startViewerTransition(
heroAssetId: string,
openViewer: () => void,
activateHeroAsset: (assetId: string) => void,
deactivateHeroAsset: () => void,
) {
void viewTransitionManager.startTransition({
await viewTransitionManager.startTransition({
types: ['viewer'],
prepareOldSnapshot: () => {
activateHeroAsset(heroAssetId);