fix(settings): keep the M3U groups view when every group is locked

With every group locked the filtered channel list is empty, so the
container showed its generic empty state and the groups rail's
"N locked · Enter PIN to show" row never appeared.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
4grayandClaude Opus 5.5 committed 2026-09-27 11:07:38 +02:00
1 parent 73ccdebb60
commit 39f5bf2b5f
4 files changed
+36 -2

No files matched your search

+4 -1
View File
@@ -229,7 +229,10 @@ on either side.
- **M3U groups rail:** `ChannelListContainerComponent` derives
`withheldGroupCount` (groups of the playlist the active lock withholds)
and the groups rail renders the same "N locked · Enter PIN to show" row
as the portal category rail, so locked groups do not simply vanish.
as the portal category rail, so locked groups do not simply vanish —
also when EVERY group is locked: the container keeps the groups view
(`showChannelViews`) and the groups view keeps its rail instead of the
generic empty state.
- **Xtream (PWA):** `PwaXtreamDataSource` drops withheld categories,
streams and search hits at read time; the same reloads apply.
- **Warm-cache detection (Electron):** the filtered category/content reads
@@ -3,7 +3,7 @@
[view]="activeView()"
[showEpg]="shouldShowEpg()"
/>
} @else if (displayedChannels().length) {
} @else if (showChannelViews()) {
@if (
!compact() &&
viewTitle() &&
@@ -201,6 +201,26 @@ describe('ChannelListContainerComponent', () => {
fixture = TestBed.createComponent(ChannelListContainerComponent);
});
it('keeps the groups view (and its unlock row) when every group is withheld', () => {
const withheld = signal(0);
Object.defineProperty(fixture.componentInstance, 'withheldGroupCount', {
value: withheld,
});
fixture.componentRef.setInput('activeView', 'groups');
fixture.detectChanges();
const component = fixture.componentInstance;
// No channels and nothing withheld: the generic empty state.
expect(component.showChannelViews()).toBe(false);
withheld.set(3);
expect(component.showChannelViews()).toBe(true);
// Other views have no unlock row to show.
fixture.componentRef.setInput('activeView', 'all');
expect(component.showChannelViews()).toBe(false);
});
it('does not clear the shared channel list on destroy', () => {
fixture.detectChanges();
@@ -354,6 +354,17 @@ export class ChannelListContainerComponent implements OnInit, OnDestroy {
withheld.has(group.key)
).length;
});
/**
* Whether the channel views render instead of the generic empty state.
* With every M3U group locked the filtered list is empty, yet the groups
* view must still render: it carries the "N locked · Enter PIN to show"
* row, the only in-context way back.
*/
readonly showChannelViews = computed(
() =>
this.displayedChannels().length > 0 ||
(this.activeView() === 'groups' && this.withheldGroupCount() > 0)
);
/** Group titles currently withheld: locked AND the lock is active. */
private readonly withheldGroupTitles = computed(() => {
this.parentalLock.version();