diff --git a/web/src/lib/components/asset-viewer/asset-viewer.svelte b/web/src/lib/components/asset-viewer/asset-viewer.svelte index ccba99a05c..b805e4e9bd 100644 --- a/web/src/lib/components/asset-viewer/asset-viewer.svelte +++ b/web/src/lib/components/asset-viewer/asset-viewer.svelte @@ -62,7 +62,7 @@ let reactions: ActivityResponseDto[] = []; - const { setAssetId } = assetViewingStore; + const { setAsset } = assetViewingStore; const { restartProgress: restartSlideshowProgress, stopProgress: stopSlideshowProgress, @@ -193,7 +193,7 @@ slideshowStateUnsubscribe = slideshowState.subscribe((value) => { if (value === SlideshowState.PlaySlideshow) { slideshowHistory.reset(); - slideshowHistory.queue(asset.id); + slideshowHistory.queue(asset); handlePromiseError(handlePlaySlideshow()); } else if (value === SlideshowState.StopSlideshow) { handlePromiseError(handleStopSlideshow()); @@ -203,7 +203,7 @@ shuffleSlideshowUnsubscribe = slideshowNavigation.subscribe((value) => { if (value === SlideshowNavigation.Shuffle) { slideshowHistory.reset(); - slideshowHistory.queue(asset.id); + slideshowHistory.queue(asset); } }); @@ -278,9 +278,9 @@ return; } - slideshowHistory.queue(asset.id); + slideshowHistory.queue(asset); - await setAssetId(asset.id); + setAsset(asset); $restartSlideshowProgress = true; }; @@ -299,9 +299,7 @@ if ($slideshowState === SlideshowState.PlaySlideshow && assetStore) { const hasNext = - order === 'previous' - ? await assetStore.getPreviousAssetId(asset.id) - : await assetStore.getNextAssetId(asset.id); + order === 'previous' ? await assetStore.getPreviousAsset(asset.id) : await assetStore.getNextAsset(asset.id); if (hasNext) { $restartSlideshowProgress = true; } else { @@ -441,8 +439,8 @@ let assetViewerHtmlElement: HTMLElement; - const slideshowHistory = new SlideshowHistory((assetId: string) => { - handlePromiseError(setAssetId(assetId)); + const slideshowHistory = new SlideshowHistory((asset) => { + setAsset(asset); $restartSlideshowProgress = true; }); diff --git a/web/src/lib/components/photos-page/asset-date-group.svelte b/web/src/lib/components/photos-page/asset-date-group.svelte index e3af259843..a42f8dc786 100644 --- a/web/src/lib/components/photos-page/asset-date-group.svelte +++ b/web/src/lib/components/photos-page/asset-date-group.svelte @@ -80,17 +80,13 @@ }); } - const assetClickHandler = async ( - asset: AssetResponseDto, - assetsInDateGroup: AssetResponseDto[], - groupTitle: string, - ) => { + const assetClickHandler = (asset: AssetResponseDto, assetsInDateGroup: AssetResponseDto[], groupTitle: string) => { if (isSelectionMode || $isMultiSelectState) { assetSelectHandler(asset, assetsInDateGroup, groupTitle); return; } - await assetViewingStore.setAssetId(asset.id); + assetViewingStore.setAsset(asset); }; const handleSelectGroup = (title: string, assets: AssetResponseDto[]) => dispatch('select', { title, assets }); diff --git a/web/src/lib/components/photos-page/asset-grid.svelte b/web/src/lib/components/photos-page/asset-grid.svelte index 8991c69152..9aca51fa00 100644 --- a/web/src/lib/components/photos-page/asset-grid.svelte +++ b/web/src/lib/components/photos-page/asset-grid.svelte @@ -137,26 +137,22 @@ } const handlePrevious = async () => { - const previousAsset = await assetStore.getPreviousAssetId($viewingAsset.id); + const previousAsset = await assetStore.getPreviousAsset($viewingAsset.id); if (previousAsset) { - const preloadId = await assetStore.getPreviousAssetId(previousAsset); - preloadId - ? await assetViewingStore.setAssetId(previousAsset, [preloadId]) - : await assetViewingStore.setAssetId(previousAsset); + const preloadAsset = await assetStore.getPreviousAsset(previousAsset.id); + assetViewingStore.setAsset(previousAsset, preloadAsset ? [preloadAsset] : []); } return !!previousAsset; }; const handleNext = async () => { - const nextAsset = await assetStore.getNextAssetId($viewingAsset.id); + const nextAsset = await assetStore.getNextAsset($viewingAsset.id); if (nextAsset) { - const preloadId = await assetStore.getNextAssetId(nextAsset); - preloadId - ? await assetViewingStore.setAssetId(nextAsset, [preloadId]) - : await assetViewingStore.setAssetId(nextAsset); + const preloadAsset = await assetStore.getNextAsset(nextAsset.id); + assetViewingStore.setAsset(nextAsset, preloadAsset ? [preloadAsset] : []); } return !!nextAsset; diff --git a/web/src/lib/stores/asset-viewing.store.ts b/web/src/lib/stores/asset-viewing.store.ts index 0416d4903c..bb32149953 100644 --- a/web/src/lib/stores/asset-viewing.store.ts +++ b/web/src/lib/stores/asset-viewing.store.ts @@ -7,24 +7,17 @@ function createAssetViewingStore() { const preloadAssets = writable([]); const viewState = writable(false); - const setAssetId = async (id: string, preloadIds?: string[]) => { - const data = await getAssetInfo({ id, key: getKey() }); - - if (preloadIds) { - const preloadList = []; - for (const preloadId of preloadIds) { - if (preloadId) { - const preloadAsset = await getAssetInfo({ id: preloadId, key: getKey() }); - preloadList.push(preloadAsset); - } - } - preloadAssets.set(preloadList); - } - - viewingAssetStoreState.set(data); + const setAsset = (asset: AssetResponseDto, assetsToPreload: AssetResponseDto[] = []) => { + preloadAssets.set(assetsToPreload); + viewingAssetStoreState.set(asset); viewState.set(true); }; + const setAssetId = async (id: string) => { + const asset = await getAssetInfo({ id, key: getKey() }); + setAsset(asset); + }; + const showAssetViewer = (show: boolean) => { viewState.set(show); }; @@ -40,6 +33,7 @@ function createAssetViewingStore() { subscribe: viewState.subscribe, set: viewState.set, }, + setAsset, setAssetId, showAssetViewer, }; diff --git a/web/src/lib/stores/asset.store.spec.ts b/web/src/lib/stores/asset.store.spec.ts index 55f3fe1ff5..e2f702fbab 100644 --- a/web/src/lib/stores/asset.store.spec.ts +++ b/web/src/lib/stores/asset.store.spec.ts @@ -286,7 +286,7 @@ describe('AssetStore', () => { }); }); - describe('getPreviousAssetId', () => { + describe('getPreviousAsset', () => { let assetStore: AssetStore; const bucketAssets: Record = { '2024-03-01T00:00:00.000Z': assetFactory.buildList(1), @@ -307,15 +307,15 @@ describe('AssetStore', () => { }); it('returns null for invalid assetId', async () => { - expect(() => assetStore.getPreviousAssetId('invalid')).not.toThrow(); - expect(await assetStore.getPreviousAssetId('invalid')).toBeNull(); + expect(() => assetStore.getPreviousAsset('invalid')).not.toThrow(); + expect(await assetStore.getPreviousAsset('invalid')).toBeNull(); }); it('returns previous assetId', async () => { await assetStore.loadBucket('2024-01-01T00:00:00.000Z', BucketPosition.Visible); const bucket = assetStore.getBucketByDate('2024-01-01T00:00:00.000Z'); - expect(await assetStore.getPreviousAssetId(bucket!.assets[1].id)).toEqual(bucket!.assets[0].id); + expect(await assetStore.getPreviousAsset(bucket!.assets[1].id)).toEqual(bucket!.assets[0]); }); it('returns previous assetId spanning multiple buckets', async () => { @@ -324,7 +324,7 @@ describe('AssetStore', () => { const bucket = assetStore.getBucketByDate('2024-02-01T00:00:00.000Z'); const previousBucket = assetStore.getBucketByDate('2024-03-01T00:00:00.000Z'); - expect(await assetStore.getPreviousAssetId(bucket!.assets[0].id)).toEqual(previousBucket!.assets[0].id); + expect(await assetStore.getPreviousAsset(bucket!.assets[0].id)).toEqual(previousBucket!.assets[0]); }); it('loads previous bucket', async () => { @@ -333,7 +333,7 @@ describe('AssetStore', () => { const loadBucketSpy = vi.spyOn(assetStore, 'loadBucket'); const bucket = assetStore.getBucketByDate('2024-02-01T00:00:00.000Z'); const previousBucket = assetStore.getBucketByDate('2024-03-01T00:00:00.000Z'); - expect(await assetStore.getPreviousAssetId(bucket!.assets[0].id)).toEqual(previousBucket!.assets[0].id); + expect(await assetStore.getPreviousAsset(bucket!.assets[0].id)).toEqual(previousBucket!.assets[0]); expect(loadBucketSpy).toBeCalledTimes(1); }); @@ -344,12 +344,12 @@ describe('AssetStore', () => { const [assetOne, assetTwo, assetThree] = assetStore.assets; assetStore.removeAssets([assetTwo.id]); - expect(await assetStore.getPreviousAssetId(assetThree.id)).toEqual(assetOne.id); + expect(await assetStore.getPreviousAsset(assetThree.id)).toEqual(assetOne); }); it('returns null when no more assets', async () => { await assetStore.loadBucket('2024-03-01T00:00:00.000Z', BucketPosition.Visible); - expect(await assetStore.getPreviousAssetId(assetStore.assets[0].id)).toBeNull(); + expect(await assetStore.getPreviousAsset(assetStore.assets[0].id)).toBeNull(); }); }); diff --git a/web/src/lib/stores/assets.store.ts b/web/src/lib/stores/assets.store.ts index 4cc92ab868..019a70401f 100644 --- a/web/src/lib/stores/assets.store.ts +++ b/web/src/lib/stores/assets.store.ts @@ -451,7 +451,7 @@ export class AssetStore { this.emit(true); } - async getPreviousAssetId(assetId: string): Promise { + async getPreviousAsset(assetId: string): Promise { const info = this.getBucketInfoForAssetId(assetId); if (!info) { return null; @@ -460,7 +460,7 @@ export class AssetStore { const { bucket, assetIndex, bucketIndex } = info; if (assetIndex !== 0) { - return bucket.assets[assetIndex - 1].id; + return bucket.assets[assetIndex - 1]; } if (bucketIndex === 0) { @@ -469,10 +469,10 @@ export class AssetStore { const previousBucket = this.buckets[bucketIndex - 1]; await this.loadBucket(previousBucket.bucketDate, BucketPosition.Unknown); - return previousBucket.assets.at(-1)?.id || null; + return previousBucket.assets.at(-1) || null; } - async getNextAssetId(assetId: string): Promise { + async getNextAsset(assetId: string): Promise { const info = this.getBucketInfoForAssetId(assetId); if (!info) { return null; @@ -481,7 +481,7 @@ export class AssetStore { const { bucket, assetIndex, bucketIndex } = info; if (assetIndex !== bucket.assets.length - 1) { - return bucket.assets[assetIndex + 1].id; + return bucket.assets[assetIndex + 1]; } if (bucketIndex === this.buckets.length - 1) { @@ -490,7 +490,7 @@ export class AssetStore { const nextBucket = this.buckets[bucketIndex + 1]; await this.loadBucket(nextBucket.bucketDate, BucketPosition.Unknown); - return nextBucket.assets[0]?.id || null; + return nextBucket.assets[0] || null; } triggerUpdate() { diff --git a/web/src/lib/utils/slideshow-history.ts b/web/src/lib/utils/slideshow-history.ts index 8b34359d0b..b9d5fdea7e 100644 --- a/web/src/lib/utils/slideshow-history.ts +++ b/web/src/lib/utils/slideshow-history.ts @@ -1,16 +1,18 @@ +import type { AssetResponseDto } from '@immich/sdk'; + export class SlideshowHistory { - private history: string[] = []; + private history: AssetResponseDto[] = []; private index = 0; - constructor(private onChange: (assetId: string) => void) {} + constructor(private onChange: (asset: AssetResponseDto) => void) {} reset() { this.history = []; this.index = 0; } - queue(assetId: string) { - this.history.push(assetId); + queue(asset: AssetResponseDto) { + this.history.push(asset); // If we were at the end of the slideshow history, move the index to the new end if (this.index === this.history.length - 2) { diff --git a/web/src/routes/(user)/albums/[albumId]/+page.svelte b/web/src/routes/(user)/albums/[albumId]/+page.svelte index d4b665bc0a..5f76012ddc 100644 --- a/web/src/routes/(user)/albums/[albumId]/+page.svelte +++ b/web/src/routes/(user)/albums/[albumId]/+page.svelte @@ -82,7 +82,7 @@ export let data: PageData; - let { isViewing: showAssetViewer, setAssetId } = assetViewingStore; + let { isViewing: showAssetViewer, setAsset } = assetViewingStore; let { slideshowState, slideshowNavigation } = slideshowStore; $: album = data.album; @@ -231,7 +231,7 @@ const asset = $slideshowNavigation === SlideshowNavigation.Shuffle ? await assetStore.getRandomAsset() : assetStore.assets[0]; if (asset) { - await setAssetId(asset.id); + setAsset(asset); $slideshowState = SlideshowState.PlaySlideshow; } };