mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +03:00
fix(web): address review feedback on hero view transitions
Change-Id: I9f12e1616ddcf124a9926d54868b5e166a6a6964
This commit is contained in:
-5344
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
-16
@@ -1,16 +0,0 @@
|
||||
import { HttpError } from '@oazapfts/runtime';
|
||||
export interface ApiValidationError {
|
||||
code: string;
|
||||
path: (string | number)[];
|
||||
message: string;
|
||||
}
|
||||
export interface ApiExceptionResponse {
|
||||
message: string;
|
||||
error?: string;
|
||||
statusCode: number;
|
||||
errors?: ApiValidationError[];
|
||||
}
|
||||
export interface ApiHttpError extends HttpError {
|
||||
data: ApiExceptionResponse;
|
||||
}
|
||||
export declare function isHttpError(error: unknown): error is ApiHttpError;
|
||||
@@ -1,4 +0,0 @@
|
||||
import { HttpError } from '@oazapfts/runtime';
|
||||
export function isHttpError(error) {
|
||||
return error instanceof HttpError;
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
export * from './fetch-client.js';
|
||||
export * from './fetch-errors.js';
|
||||
export interface InitOptions {
|
||||
baseUrl: string;
|
||||
apiKey: string;
|
||||
headers?: Record<string, string>;
|
||||
}
|
||||
export declare const init: ({ baseUrl, apiKey, headers }: InitOptions) => void;
|
||||
export declare const getBaseUrl: () => string;
|
||||
export declare const setBaseUrl: (baseUrl: string) => void;
|
||||
export declare const setApiKey: (apiKey: string) => void;
|
||||
export declare const setHeader: (key: string, value: string) => void;
|
||||
export declare const setHeaders: (headers: Record<string, string>) => void;
|
||||
export declare const getAssetOriginalPath: (id: string) => string;
|
||||
export declare const getAssetThumbnailPath: (id: string) => string;
|
||||
export declare const getAssetPlaybackPath: (id: string) => string;
|
||||
export declare const getUserProfileImagePath: (userId: string) => string;
|
||||
export declare const getPeopleThumbnailPath: (personId: string) => string;
|
||||
@@ -1,40 +0,0 @@
|
||||
import { defaults } from './fetch-client.js';
|
||||
export * from './fetch-client.js';
|
||||
export * from './fetch-errors.js';
|
||||
export const init = ({ baseUrl, apiKey, headers }) => {
|
||||
setBaseUrl(baseUrl);
|
||||
setApiKey(apiKey);
|
||||
if (headers) {
|
||||
setHeaders(headers);
|
||||
}
|
||||
};
|
||||
export const getBaseUrl = () => defaults.baseUrl;
|
||||
export const setBaseUrl = (baseUrl) => {
|
||||
defaults.baseUrl = baseUrl;
|
||||
};
|
||||
export const setApiKey = (apiKey) => {
|
||||
defaults.headers = defaults.headers || {};
|
||||
defaults.headers['x-api-key'] = apiKey;
|
||||
};
|
||||
export const setHeader = (key, value) => {
|
||||
assertNoApiKey(key);
|
||||
defaults.headers = defaults.headers || {};
|
||||
defaults.headers[key] = value;
|
||||
};
|
||||
export const setHeaders = (headers) => {
|
||||
defaults.headers = defaults.headers || {};
|
||||
for (const [key, value] of Object.entries(headers)) {
|
||||
assertNoApiKey(key);
|
||||
defaults.headers[key] = value;
|
||||
}
|
||||
};
|
||||
const assertNoApiKey = (headerKey) => {
|
||||
if (headerKey.toLowerCase() === 'x-api-key') {
|
||||
throw new Error('The API key header can only be set using setApiKey().');
|
||||
}
|
||||
};
|
||||
export const getAssetOriginalPath = (id) => `/assets/${id}/original`;
|
||||
export const getAssetThumbnailPath = (id) => `/assets/${id}/thumbnail`;
|
||||
export const getAssetPlaybackPath = (id) => `/assets/${id}/video/playback`;
|
||||
export const getUserProfileImagePath = (userId) => `/users/${userId}/profile-image`;
|
||||
export const getPeopleThumbnailPath = (personId) => `/people/${personId}/thumbnail`;
|
||||
Generated
-15
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"name": "immich-monorepo",
|
||||
"version": "2.7.5",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "immich-monorepo",
|
||||
"version": "2.7.5",
|
||||
"engines": {
|
||||
"pnpm": ">=10.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -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,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);
|
||||
|
||||
Reference in New Issue
Block a user