fix(settings): offer the portal unlock row in fail-closed mode

When the lock store cannot be read every portal category is withheld
but no locked ids are known, so the rail showed no "Enter PIN to show"
row. It now shows the row without a count in that state.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
4grayandClaude Opus 5.5 committed 2026-09-27 14:33:40 +02:00
1 parent 5e4ad097e3
commit b5ba77b67b
4 files changed
+39 -4

No files matched your search

+3 -1
View File
@@ -19,7 +19,9 @@ follow in a second PR.
- The unit of locking is the category. Nothing is blurred or greyed: a
withheld category and its rows are absent. The only trace is one
"N locked · Enter PIN to show" row at the bottom of a portal's category
rail, which opens the PIN prompt.
rail, which opens the PIN prompt. In fail-closed mode (lock store
unreadable) the row shows without a count, since which categories are
locked is unknown while every one of them is withheld.
- The unlock lives in memory only. The app locks again on every restart, on
"Lock now" (header button, command palette, settings), and after
`Settings.parentalLockRelockMinutes` minutes without user interaction
@@ -214,7 +214,7 @@
}
}
@if (withheldCategoryCount() > 0) {
@if (withheldCategoryCount() > 0 || withholdsAllCategories()) {
<button
type="button"
class="context-locked-row"
@@ -225,8 +225,10 @@
<mat-icon>lock</mat-icon>
<span class="context-locked-row__label">
{{
'PARENTAL_LOCK.LOCKED_CATEGORIES_ROW'
| translate: { count: withheldCategoryCount() }
withholdsAllCategories()
? ('PARENTAL_LOCK.LOCKED_COUNT' | translate)
: ('PARENTAL_LOCK.LOCKED_CATEGORIES_ROW'
| translate: { count: withheldCategoryCount() })
}}
</span>
<span class="context-locked-row__hint">
@@ -906,6 +906,27 @@ describe('WorkspaceContextPanelComponent', () => {
});
});
it('offers the unlock row in fail-closed mode, when no locked ids are known', () => {
const parentalLock = TestBed.inject(ParentalLockService);
Object.defineProperty(parentalLock, 'withholdsEverything', {
configurable: true,
value: signal(true),
});
fixture.componentRef.setInput('context', {
provider: 'stalker',
playlistId: 'stalker-1',
});
fixture.componentRef.setInput('section', 'itv');
fixture.detectChanges();
expect(fixture.componentInstance.withheldCategoryCount()).toBe(0);
expect(
fixture.nativeElement.querySelector(
'[data-test-id="context-locked-categories"]'
)
).not.toBeNull();
});
describe('Stalker lock dialog', () => {
function enableLock(): void {
const parentalLock = TestBed.inject(ParentalLockService);
@@ -233,6 +233,16 @@ export class WorkspaceContextPanelComponent {
}
return 0;
});
/**
* Fail-closed mode (the lock store could not be read): every category
* is withheld, but which ones are locked is unknown, so the count above
* is zero. The rail still offers the unlock row, without a count.
*/
readonly withholdsAllCategories = computed(
() =>
(this.isXtreamCategories() || this.isStalkerCategories()) &&
this.parentalLock.withholdsEverything()
);
readonly xtreamStatusText = computed(() => {
if (
!this.isXtreamCategories() ||