mirror of
https://github.com/immich-app/immich.git
synced 2025-07-09 03:04:16 -04:00
fix(web): viewing asset lock (#19499)
* fix(web): viewing asset lock * fix: lint * make mutex stateless --------- Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
parent
73733370a2
commit
fb384fe90b
10
web/package-lock.json
generated
10
web/package-lock.json
generated
@ -20,6 +20,7 @@
|
|||||||
"@photo-sphere-viewer/settings-plugin": "^5.11.5",
|
"@photo-sphere-viewer/settings-plugin": "^5.11.5",
|
||||||
"@photo-sphere-viewer/video-plugin": "^5.11.5",
|
"@photo-sphere-viewer/video-plugin": "^5.11.5",
|
||||||
"@zoom-image/svelte": "^0.3.0",
|
"@zoom-image/svelte": "^0.3.0",
|
||||||
|
"async-mutex": "^0.5.0",
|
||||||
"dom-to-image": "^2.6.0",
|
"dom-to-image": "^2.6.0",
|
||||||
"fabric": "^6.5.4",
|
"fabric": "^6.5.4",
|
||||||
"geojson": "^0.5.0",
|
"geojson": "^0.5.0",
|
||||||
@ -3924,6 +3925,15 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/async-mutex": {
|
||||||
|
"version": "0.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.5.0.tgz",
|
||||||
|
"integrity": "sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/asynckit": {
|
"node_modules/asynckit": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
"@photo-sphere-viewer/settings-plugin": "^5.11.5",
|
"@photo-sphere-viewer/settings-plugin": "^5.11.5",
|
||||||
"@photo-sphere-viewer/video-plugin": "^5.11.5",
|
"@photo-sphere-viewer/video-plugin": "^5.11.5",
|
||||||
"@zoom-image/svelte": "^0.3.0",
|
"@zoom-image/svelte": "^0.3.0",
|
||||||
|
"async-mutex": "^0.5.0",
|
||||||
"dom-to-image": "^2.6.0",
|
"dom-to-image": "^2.6.0",
|
||||||
"fabric": "^6.5.4",
|
"fabric": "^6.5.4",
|
||||||
"geojson": "^0.5.0",
|
"geojson": "^0.5.0",
|
||||||
|
@ -91,7 +91,7 @@
|
|||||||
empty,
|
empty,
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
let { isViewing: showAssetViewer, asset: viewingAsset, preloadAssets, gridScrollTarget } = assetViewingStore;
|
let { isViewing: showAssetViewer, asset: viewingAsset, preloadAssets, gridScrollTarget, mutex } = assetViewingStore;
|
||||||
|
|
||||||
let element: HTMLElement | undefined = $state();
|
let element: HTMLElement | undefined = $state();
|
||||||
|
|
||||||
@ -438,6 +438,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handlePrevious = async () => {
|
const handlePrevious = async () => {
|
||||||
|
const release = await mutex.acquire();
|
||||||
const laterAsset = await timelineManager.getLaterAsset($viewingAsset);
|
const laterAsset = await timelineManager.getLaterAsset($viewingAsset);
|
||||||
|
|
||||||
if (laterAsset) {
|
if (laterAsset) {
|
||||||
@ -447,11 +448,14 @@
|
|||||||
await navigate({ targetRoute: 'current', assetId: laterAsset.id });
|
await navigate({ targetRoute: 'current', assetId: laterAsset.id });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
release();
|
||||||
return !!laterAsset;
|
return !!laterAsset;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleNext = async () => {
|
const handleNext = async () => {
|
||||||
|
const release = await mutex.acquire();
|
||||||
const earlierAsset = await timelineManager.getEarlierAsset($viewingAsset);
|
const earlierAsset = await timelineManager.getEarlierAsset($viewingAsset);
|
||||||
|
|
||||||
if (earlierAsset) {
|
if (earlierAsset) {
|
||||||
const preloadAsset = await timelineManager.getEarlierAsset(earlierAsset);
|
const preloadAsset = await timelineManager.getEarlierAsset(earlierAsset);
|
||||||
const asset = await getAssetInfo({ id: earlierAsset.id, key: authManager.key });
|
const asset = await getAssetInfo({ id: earlierAsset.id, key: authManager.key });
|
||||||
@ -459,6 +463,7 @@
|
|||||||
await navigate({ targetRoute: 'current', assetId: earlierAsset.id });
|
await navigate({ targetRoute: 'current', assetId: earlierAsset.id });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
release();
|
||||||
return !!earlierAsset;
|
return !!earlierAsset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,12 +2,14 @@ import { authManager } from '$lib/managers/auth-manager.svelte';
|
|||||||
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
|
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
|
||||||
import { type AssetGridRouteSearchParams } from '$lib/utils/navigation';
|
import { type AssetGridRouteSearchParams } from '$lib/utils/navigation';
|
||||||
import { getAssetInfo, type AssetResponseDto } from '@immich/sdk';
|
import { getAssetInfo, type AssetResponseDto } from '@immich/sdk';
|
||||||
|
import { Mutex } from 'async-mutex';
|
||||||
import { readonly, writable } from 'svelte/store';
|
import { readonly, writable } from 'svelte/store';
|
||||||
|
|
||||||
function createAssetViewingStore() {
|
function createAssetViewingStore() {
|
||||||
const viewingAssetStoreState = writable<AssetResponseDto>();
|
const viewingAssetStoreState = writable<AssetResponseDto>();
|
||||||
const preloadAssets = writable<TimelineAsset[]>([]);
|
const preloadAssets = writable<TimelineAsset[]>([]);
|
||||||
const viewState = writable<boolean>(false);
|
const viewState = writable<boolean>(false);
|
||||||
|
const viewingAssetMutex = new Mutex();
|
||||||
const gridScrollTarget = writable<AssetGridRouteSearchParams | null | undefined>();
|
const gridScrollTarget = writable<AssetGridRouteSearchParams | null | undefined>();
|
||||||
|
|
||||||
const setAsset = (asset: AssetResponseDto, assetsToPreload: TimelineAsset[] = []) => {
|
const setAsset = (asset: AssetResponseDto, assetsToPreload: TimelineAsset[] = []) => {
|
||||||
@ -28,6 +30,7 @@ function createAssetViewingStore() {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
asset: readonly(viewingAssetStoreState),
|
asset: readonly(viewingAssetStoreState),
|
||||||
|
mutex: viewingAssetMutex,
|
||||||
preloadAssets: readonly(preloadAssets),
|
preloadAssets: readonly(preloadAssets),
|
||||||
isViewing: viewState,
|
isViewing: viewState,
|
||||||
gridScrollTarget,
|
gridScrollTarget,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user