From fbd49e0b7979f939114d5a10f94b20d7735a914c Mon Sep 17 00:00:00 2001 From: Jason Rasmussen Date: Thu, 8 Jan 2026 12:40:17 -0500 Subject: [PATCH] refactor: memory lane (#25134) --- pnpm-lock.yaml | 10 +- web/package.json | 2 +- .../memory-page/memory-viewer.svelte | 2 +- .../components/photos-page/memory-lane.svelte | 107 ------------------ web/src/lib/managers/event-manager.svelte.ts | 4 +- web/src/lib/stores/memory.store.svelte.ts | 29 +++-- web/src/lib/utils/auth.ts | 3 + .../(user)/photos/[[assetId=id]]/+page.svelte | 22 +++- web/src/routes/+layout.svelte | 2 + 9 files changed, 49 insertions(+), 132 deletions(-) delete mode 100644 web/src/lib/components/photos-page/memory-lane.svelte diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d4ffc00639d49..a851b1a809127 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -726,8 +726,8 @@ importers: specifier: file:../open-api/typescript-sdk version: link:../open-api/typescript-sdk '@immich/ui': - specifier: ^0.53.3 - version: 0.53.3(@sveltejs/kit@2.49.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.46.1)(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.46.1)(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.46.1) + specifier: ^0.54.0 + version: 0.54.0(@sveltejs/kit@2.49.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.46.1)(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.46.1)(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.46.1) '@mapbox/mapbox-gl-rtl-text': specifier: 0.2.3 version: 0.2.3(mapbox-gl@1.13.3) @@ -3075,8 +3075,8 @@ packages: peerDependencies: svelte: ^5.0.0 - '@immich/ui@0.53.3': - resolution: {integrity: sha512-Ax7ctU9KIZgET58+PoMQnf1XDOIH76Xa341TXDfLwF96F3fQZ/v4TA7Ycb6hmTwIYGU9arIgqGqQDbuuNxc2vA==} + '@immich/ui@0.54.0': + resolution: {integrity: sha512-6jvkvKhgsZ7LvspaJkbht/f8W5IRm+vjYkcZecShFAPaxaowbm7io9sO15MpJdIQfPdXg7vwLI527PV3vlBc6A==} peerDependencies: svelte: ^5.0.0 @@ -15078,7 +15078,7 @@ snapshots: dependencies: svelte: 5.46.1 - '@immich/ui@0.53.3(@sveltejs/kit@2.49.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.46.1)(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.46.1)(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.46.1)': + '@immich/ui@0.54.0(@sveltejs/kit@2.49.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.46.1)(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.46.1)(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.46.1)': dependencies: '@immich/svelte-markdown-preprocess': 0.1.0(svelte@5.46.1) '@internationalized/date': 3.10.0 diff --git a/web/package.json b/web/package.json index ef48a8a92ffaf..acd888783f48d 100644 --- a/web/package.json +++ b/web/package.json @@ -27,7 +27,7 @@ "@formatjs/icu-messageformat-parser": "^3.0.0", "@immich/justified-layout-wasm": "^0.4.3", "@immich/sdk": "file:../open-api/typescript-sdk", - "@immich/ui": "^0.53.3", + "@immich/ui": "^0.54.0", "@mapbox/mapbox-gl-rtl-text": "0.2.3", "@mdi/js": "^7.4.47", "@photo-sphere-viewer/core": "^5.14.0", diff --git a/web/src/lib/components/memory-page/memory-viewer.svelte b/web/src/lib/components/memory-page/memory-viewer.svelte index 34c6ee18db20f..ff1597fedbdb1 100644 --- a/web/src/lib/components/memory-page/memory-viewer.svelte +++ b/web/src/lib/components/memory-page/memory-viewer.svelte @@ -270,7 +270,7 @@ }; afterNavigate(({ from, to }) => { - memoryStore.initialize().then( + memoryStore.ready().then( () => { let target = null; if (to?.params?.assetId) { diff --git a/web/src/lib/components/photos-page/memory-lane.svelte b/web/src/lib/components/photos-page/memory-lane.svelte deleted file mode 100644 index 1d61b61b40e9a..0000000000000 --- a/web/src/lib/components/photos-page/memory-lane.svelte +++ /dev/null @@ -1,107 +0,0 @@ - - -{#if shouldRender} -
(offsetWidth = width)} - onscroll={onScroll} - > - {#if canScrollLeft || canScrollRight} -
- {#if canScrollLeft} -
- -
- {/if} - {#if canScrollRight} -
- -
- {/if} -
- {/if} -
(innerWidth = width)}> - {#each memoryStore.memories as memory (memory.id)} - - {$t('memory_lane_title', -
-

- {$memoryLaneTitle(memory)} -

-
- {/each} -
-
-{/if} - - diff --git a/web/src/lib/managers/event-manager.svelte.ts b/web/src/lib/managers/event-manager.svelte.ts index f9fa87e0cf3a4..5b9803edff33e 100644 --- a/web/src/lib/managers/event-manager.svelte.ts +++ b/web/src/lib/managers/event-manager.svelte.ts @@ -15,9 +15,11 @@ import type { export type Events = { AppInit: []; - UserLogin: []; + AuthLogin: [LoginResponseDto]; AuthLogout: []; + AuthUserLoaded: [UserAdminResponseDto]; + LanguageChange: [{ name: string; code: string; rtl?: boolean }]; ThemeChange: [ThemeSetting]; diff --git a/web/src/lib/stores/memory.store.svelte.ts b/web/src/lib/stores/memory.store.svelte.ts index 05f45b3d7d058..357de394aeb2a 100644 --- a/web/src/lib/stores/memory.store.svelte.ts +++ b/web/src/lib/stores/memory.store.svelte.ts @@ -20,12 +20,18 @@ export type MemoryAsset = MemoryIndex & { }; class MemoryStoreSvelte { + #loading: Promise | undefined; + constructor() { eventManager.on('AuthLogout', () => this.clearCache()); + eventManager.on('AuthUserLoaded', () => void this.initialize()); + } + + ready() { + return this.initialize(); } memories = $state([]); - private initialized = false; private memoryAssets = $derived.by(() => { const memoryAssets: MemoryAsset[] = []; let previous: MemoryAsset | undefined; @@ -101,21 +107,20 @@ class MemoryStoreSvelte { } } - async initialize() { - if (this.initialized) { - return; - } - this.initialized = true; - - await this.loadAllMemories(); + private clearCache() { + this.#loading = undefined; + this.memories = []; } - clearCache() { - this.initialized = false; - this.memories = []; + private initialize() { + if (!this.#loading) { + this.#loading = this.load(); + } + + return this.#loading; } - private async loadAllMemories() { + private async load() { const memories = await searchMemories({ $for: asLocalTimeISO(DateTime.now()) }); this.memories = memories.filter((memory) => memory.assets.length > 0); } diff --git a/web/src/lib/utils/auth.ts b/web/src/lib/utils/auth.ts index feb875e5ec932..99935b8938419 100644 --- a/web/src/lib/utils/auth.ts +++ b/web/src/lib/utils/auth.ts @@ -1,4 +1,5 @@ import { browser } from '$app/environment'; +import { eventManager } from '$lib/managers/event-manager.svelte'; import { purchaseStore } from '$lib/stores/purchase.store'; import { preferences as preferences$, user as user$ } from '$lib/stores/user.store'; import { userInteraction } from '$lib/stores/user.svelte'; @@ -24,6 +25,8 @@ export const loadUser = async () => { user$.set(user); preferences$.set(preferences); + eventManager.emit('AuthUserLoaded', user); + // Check for license status if (serverInfo.licensed || user.license?.activatedAt) { purchaseStore.setPurchaseStatus(true); diff --git a/web/src/routes/(user)/photos/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/photos/[[assetId=id]]/+page.svelte index 8bf8dce94efa1..c0d05bdfcbf2b 100644 --- a/web/src/routes/(user)/photos/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/photos/[[assetId=id]]/+page.svelte @@ -1,7 +1,6 @@ @@ -98,7 +110,7 @@ withStacked > {#if $preferences.memories.enabled} - + {/if} {#snippet empty()} openFileUploadDialog()} class="mt-10 mx-auto" /> diff --git a/web/src/routes/+layout.svelte b/web/src/routes/+layout.svelte index 1c7a190b08841..286573ef78f09 100644 --- a/web/src/routes/+layout.svelte +++ b/web/src/routes/+layout.svelte @@ -49,6 +49,8 @@ toast_info_title: $t('info'), toast_warning_title: $t('warning'), toast_danger_title: $t('error'), + navigate_next: $t('next'), + navigate_previous: $t('previous'), }); });