From 9a57eaff920850cc30d2c87cfd6f5e8a64137c0f Mon Sep 17 00:00:00 2001 From: 4gray Date: Sat, 28 Feb 2026 13:16:03 +0100 Subject: [PATCH] fix(playlist): add content initialization state and prevent redundant imports --- .../stores/features/with-content.feature.ts | 17 ++++++++++++++++- .../xtream-shell/xtream-shell.component.ts | 13 ++++++++----- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/apps/web/src/app/xtream-electron/stores/features/with-content.feature.ts b/apps/web/src/app/xtream-electron/stores/features/with-content.feature.ts index 0959b8c9c..015b391d2 100644 --- a/apps/web/src/app/xtream-electron/stores/features/with-content.feature.ts +++ b/apps/web/src/app/xtream-electron/stores/features/with-content.feature.ts @@ -12,13 +12,13 @@ import { XtreamSerieItem, XtreamVodStream, } from 'shared-interfaces'; +import { createLogger } from '../../../shared/utils/logger'; import { XTREAM_DATA_SOURCE, XtreamCategoryFromDb, } from '../../data-sources/xtream-data-source.interface'; import { XtreamCredentials } from '../../services/xtream-api.service'; import { ContentType } from '../../xtream-state'; -import { createLogger } from '../../../shared/utils/logger'; /** * Content state for managing categories and streams @@ -35,6 +35,7 @@ export interface ContentState { isImporting: boolean; importCount: number; itemsToImport: number; + isContentInitialized: boolean; } /** @@ -52,6 +53,7 @@ const initialContentState: ContentState = { isImporting: false, importCount: 0, itemsToImport: 0, + isContentInitialized: false, }; /** @@ -108,6 +110,11 @@ export function withContent() { * Check if content is being imported */ isContentImporting: computed(() => store.isImporting()), + + /** + * Check if content is already initialized + */ + isContentInitialized: computed(() => store.isContentInitialized()), })), withMethods((store) => { @@ -248,6 +255,11 @@ export function withContent() { const ctx = getCredentialsFromStore(); if (!ctx) return; + // Skip if we already initialized content for this playlist + if (store.isContentInitialized()) { + return; + } + patchState(store, { isImporting: true, importCount: 0, @@ -280,6 +292,9 @@ export function withContent() { logger.error('Error restoring user data', err); } } + + // Mark as initialized so next routings won't re-trigger it + patchState(store, { isContentInitialized: true }); } finally { patchState(store, { isImporting: false }); } diff --git a/apps/web/src/app/xtream-electron/xtream-shell/xtream-shell.component.ts b/apps/web/src/app/xtream-electron/xtream-shell/xtream-shell.component.ts index ae4814807..8a008a289 100644 --- a/apps/web/src/app/xtream-electron/xtream-shell/xtream-shell.component.ts +++ b/apps/web/src/app/xtream-electron/xtream-shell/xtream-shell.component.ts @@ -9,10 +9,10 @@ import { import { Store } from '@ngrx/store'; import { TranslateModule } from '@ngx-translate/core'; import { PlaylistActions } from 'm3u-state'; +import { filter } from 'rxjs'; import { LoadingOverlayComponent } from '../loading-overlay/loading-overlay.component'; import { NavigationComponent } from '../navigation/navigation.component'; import { XtreamStore } from '../stores/xtream.store'; -import { filter } from 'rxjs'; @Component({ templateUrl: './xtream-shell.component.html', @@ -51,14 +51,17 @@ export class XtreamShellComponent { .subscribe(async (params) => { const newPlaylistId = params['id']; - // Skip if playlist ID hasn't changed + // Skip if this component instance already processed this ID if (this.currentPlaylistId === newPlaylistId) { return; } - // Always reset the store when playlist changes to prevent stale data - // from previous sessions showing up (the store is a singleton) - this.xtreamStore.resetStore(newPlaylistId); + // If the global store already has this playlist loaded, don't wipe it out. + // This prevents reloading everything when returning from other views (e.g. Sources). + if (this.xtreamStore.playlistId() !== newPlaylistId) { + this.xtreamStore.resetStore(newPlaylistId); + } + this.currentPlaylistId = newPlaylistId; this.store.dispatch(