From daf00268bdf6f0147669d2dd3334dfa2bc841702 Mon Sep 17 00:00:00 2001 From: 4gray Date: Mon, 12 Oct 2026 20:32:28 +0200 Subject: [PATCH] fix(workspace): keep the overlay delay while another playlist refreshes Refresh preparation skipped the cached-load delay for any playlist, so opening a cached portal while another playlist prepared a refresh still flashed the overlay. Only preparation of the shown playlist (any on the dashboard) now shows it at once. Also words the J2 layout-shift history from #1895 in the past tense: the cached-load overlay no longer mounts on a J2 click. Co-Authored-By: Claude Opus 5.5 --- docs/architecture/performance-journeys.md | 4 +-- docs/architecture/workspace-shell.md | 7 ++--- ...kspace-shell-xtream-import.service.spec.ts | 10 +++++++ .../workspace-shell-xtream-import.service.ts | 26 +++++++++++++------ 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/docs/architecture/performance-journeys.md b/docs/architecture/performance-journeys.md index 5f8e16031..b83dbfc00 100644 --- a/docs/architecture/performance-journeys.md +++ b/docs/architecture/performance-journeys.md @@ -1322,8 +1322,8 @@ largest distance in it, the content pane's 323 px, which is why Back added buttons appearing when the categories arrive. The skeletons of the category list and the grid are replaced by content without any shift. Nothing was hidden behind the startup overlay: the "Syncing playlist" overlay of the -cached catalog load flashes for about two frames after the shift and covers -no further one. +cached catalog load flashed for about two frames after the shift and covered +no further one. It no longer mounts on a J2 click (see the J2 section). The content frame and the header controls now slide into place instead of jumping ([Layout slides](./workspace-shell.md#layout-slides)): the new layout diff --git a/docs/architecture/workspace-shell.md b/docs/architecture/workspace-shell.md index c0e125286..58b09ed0c 100644 --- a/docs/architecture/workspace-shell.md +++ b/docs/architecture/workspace-shell.md @@ -195,9 +195,10 @@ services: 5. `WorkspaceShellCommandPaletteService` owns command-palette dialog lifecycle and recent-command recording. 6. `WorkspaceShellXtreamImportService` owns Xtream import/refresh overlay - state and labels. Remote import phases and refresh preparation show the - overlay at once. A session that has only read the saved catalog - (`loading-cached`, `isImporting` still false) shows it only after + state and labels. Remote import phases and refresh preparation of the + shown playlist (of any playlist on the dashboard) show the overlay at + once. A session that has only read the saved catalog (`loading-cached`, + `isImporting` still false) shows it only after `XTREAM_LOCAL_LOAD_OVERLAY_DELAY_MS` (300 ms), so a warm open goes from the skeleton to the page without flashing the overlay, while a slow or stuck cache read still blocks and stays cancellable. diff --git a/libs/workspace/shell/feature/src/lib/workspace-shell/services/workspace-shell-xtream-import.service.spec.ts b/libs/workspace/shell/feature/src/lib/workspace-shell/services/workspace-shell-xtream-import.service.spec.ts index b59611792..31fe6c19f 100644 --- a/libs/workspace/shell/feature/src/lib/workspace-shell/services/workspace-shell-xtream-import.service.spec.ts +++ b/libs/workspace/shell/feature/src/lib/workspace-shell/services/workspace-shell-xtream-import.service.spec.ts @@ -153,6 +153,16 @@ describe('WorkspaceShellXtreamImportService', () => { expect(service.showXtreamImportOverlay()).toBe(true); }); + it('keeps the delay while another playlist prepares a refresh', () => { + refreshPreparation.set({ playlistId: 'other-playlist' }); + activeImportSessionId.set('session-1'); + advance(0); + expect(service.showXtreamImportOverlay()).toBe(false); + + advance(XTREAM_LOCAL_LOAD_OVERLAY_DELAY_MS); + expect(service.showXtreamImportOverlay()).toBe(true); + }); + it('shows the overlay at once while a refresh prepares the playlist', () => { refreshPreparation.set({ playlistId: 'portal-1' }); expect(service.showXtreamImportOverlay()).toBe(true); diff --git a/libs/workspace/shell/feature/src/lib/workspace-shell/services/workspace-shell-xtream-import.service.ts b/libs/workspace/shell/feature/src/lib/workspace-shell/services/workspace-shell-xtream-import.service.ts index e02fd10d2..056bb82d4 100644 --- a/libs/workspace/shell/feature/src/lib/workspace-shell/services/workspace-shell-xtream-import.service.ts +++ b/libs/workspace/shell/feature/src/lib/workspace-shell/services/workspace-shell-xtream-import.service.ts @@ -109,15 +109,25 @@ export class WorkspaceShellXtreamImportService { /** * Remote imports (the store flags `isImporting` for every phase except - * `loading-cached`) and refresh preparation show the overlay at once. A - * session that has only read the saved catalog so far waits - * `XTREAM_LOCAL_LOAD_OVERLAY_DELAY_MS`, so a warm open never flashes it. + * `loading-cached`) and refresh preparation of the shown playlist (any + * on the dashboard) show the overlay at once. A session that has only + * read the saved catalog so far waits `XTREAM_LOCAL_LOAD_OVERLAY_DELAY_MS`, + * so a warm open never flashes it, even while another playlist prepares + * a refresh. */ - private readonly isOverlayImmediate = computed( - () => - Boolean(this.refreshPreparation()) || - this.xtreamStore.isImporting() - ); + private readonly isOverlayImmediate = computed(() => { + if (this.xtreamStore.isImporting()) { + return true; + } + if (this.routeState.currentRoute().kind === 'dashboard') { + return Boolean(this.refreshPreparation()); + } + const playlistId = this.routeState.currentContext()?.playlistId; + return ( + playlistId !== undefined && + this.isRefreshPreparationRunningForPlaylist(playlistId) + ); + }); private readonly localLoadDelayElapsed = signal(false); readonly showXtreamImportOverlay = computed(