From 89d64472c0cf9c3fc1d3e066405f33a039e1c3c9 Mon Sep 17 00:00:00 2001 From: 4gray Date: Tue, 13 Oct 2026 20:13:55 +0200 Subject: [PATCH] fix(switcher): fall back to All when the remembered type has no sources left Local review round 7 (Greptile 5/5 with one P2; Codex was clean): when the last source of the remembered switcher type was removed while two other types remained, the list kept filtering by the missing type. Its segment was gone, no segment was selected, and the list said "Nothing found". The list now filters by All until a source of that type returns; the remembered choice is kept. Co-Authored-By: Claude Opus 5.5 --- .../playlist-switcher-panel.component.html | 2 +- .../playlist-switcher-panel.component.spec.ts | 19 +++++++++++++++++++ .../playlist-switcher-panel.component.ts | 17 +++++++++++++++-- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/libs/playlist/shared/ui/src/lib/playlist-switcher/playlist-switcher-panel.component.html b/libs/playlist/shared/ui/src/lib/playlist-switcher/playlist-switcher-panel.component.html index dcd2baa47..785337a66 100644 --- a/libs/playlist/shared/ui/src/lib/playlist-switcher/playlist-switcher-panel.component.html +++ b/libs/playlist/shared/ui/src/lib/playlist-switcher/playlist-switcher-panel.component.html @@ -60,7 +60,7 @@ diff --git a/libs/playlist/shared/ui/src/lib/playlist-switcher/playlist-switcher-panel.component.spec.ts b/libs/playlist/shared/ui/src/lib/playlist-switcher/playlist-switcher-panel.component.spec.ts index 736c7775a..5b3a09732 100644 --- a/libs/playlist/shared/ui/src/lib/playlist-switcher/playlist-switcher-panel.component.spec.ts +++ b/libs/playlist/shared/ui/src/lib/playlist-switcher/playlist-switcher-panel.component.spec.ts @@ -233,6 +233,25 @@ describe('PlaylistSwitcherPanelComponent', () => { ).toContain('WORKSPACE.SWITCHER.NO_MATCHES'); }); + it('falls back to All when the remembered type has no sources left', () => { + component.setType('xtream'); + fixture.detectChanges(); + expect(optionIds()).toEqual(['playlist-switcher-all-bravo']); + + // The last Xtream source is removed; two other types remain. + playlists.set([ALPHA, CHARLIE]); + fixture.detectChanges(); + expect(component.activeType()).toBe('all'); + expect(optionIds()).toEqual([ + 'playlist-switcher-all-alpha', + 'playlist-switcher-all-charlie', + ]); + // The choice is kept for when an Xtream source returns. + expect(localStorage.getItem('playlist-switcher:type:v2')).toBe( + 'xtream' + ); + }); + it('filters by type with one segment and remembers it', () => { component.setType('xtream'); fixture.detectChanges(); diff --git a/libs/playlist/shared/ui/src/lib/playlist-switcher/playlist-switcher-panel.component.ts b/libs/playlist/shared/ui/src/lib/playlist-switcher/playlist-switcher-panel.component.ts index 4e41812c4..7737d0e09 100644 --- a/libs/playlist/shared/ui/src/lib/playlist-switcher/playlist-switcher-panel.component.ts +++ b/libs/playlist/shared/ui/src/lib/playlist-switcher/playlist-switcher-panel.component.ts @@ -135,6 +135,19 @@ export class PlaylistSwitcherPanelComponent { readonly showTypeFilter = computed( () => KINDS.filter((kind) => this.typeCounts()[kind] > 0).length > 1 ); + /** + * The type the list filters by: the remembered one while it has sources + * and its segment shows, else All. Removing the last source of the + * remembered type would otherwise leave an empty list with no segment + * selected. The remembered choice itself is kept for when it returns. + */ + readonly activeType = computed(() => { + const type = this.type(); + return this.showTypeFilter() && + (type === 'all' || this.typeCounts()[type] > 0) + ? type + : 'all'; + }); /** The Sources page order, so both lists agree. */ private readonly ordered = computed(() => { const options = this.sortOptions(); @@ -151,7 +164,7 @@ export class PlaylistSwitcherPanelComponent { buildSwitcherGroups( this.ordered(), this.recentHistory.ids(), - this.showTypeFilter() ? this.type() : 'all', + this.activeType(), this.query() ) ); @@ -174,7 +187,7 @@ export class PlaylistSwitcherPanelComponent { >({ source: () => ({ query: this.query(), - type: this.type(), + type: this.activeType(), ids: this.options().map((option) => option.id), }), computation: (source, previous) => {