fix(settings): clear an Xtream detail from a hidden category synchronously on relock

The synchronous relock step now clears a selected Xtream item whose
category the visible category list cannot place (a manually hidden
category opened through search), instead of leaving it usable until the
awaited reloads and lookup finish.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
4grayandClaude Opus 5.5 committed 2026-09-27 13:20:05 +02:00
1 parent 92382052d8
commit e9afb56017
3 files changed
+36 -4

No files matched your search

@@ -349,6 +349,33 @@ describe('ParentalLockEnforcementService', () => {
expect(xtreamStore.refreshSearchResults).toHaveBeenCalled();
});
it('clears on relock, synchronously, a detail whose category is not in the visible list', () => {
// Opened through search from a manually hidden category: the
// on-screen list cannot place it, and the unfiltered lookup is
// an awaited read that may hang.
router.url = '/workspace/xtreams/xtream-1/vod/55/900';
xtreamStore.selectedItem.set({ category_id: 55 });
service.failClosedNow();
expect(xtreamStore.setSelectedItem).toHaveBeenCalledWith(null);
expect(router.navigate).toHaveBeenCalledWith([
'/workspace',
'xtreams',
'xtream-1',
'vod',
]);
});
it('keeps a detail on relock whose visible category is not locked', () => {
router.url = '/workspace/xtreams/xtream-1/vod/7/900';
xtreamStore.selectedItem.set({ category_id: 7 });
service.failClosedNow();
expect(xtreamStore.setSelectedItem).not.toHaveBeenCalled();
});
it('fails closed synchronously on relock: detail, catalog and search', () => {
router.url = '/workspace/xtreams/xtream-1/vod/42';
lockProvider(70);
@@ -223,8 +223,10 @@ export class ParentalLockEnforcementService {
* Clears a selected Xtream item whose category the lock store already
* says is locked. Electron rows carry the SQLite category row id; the
* category list still on screen maps it to the provider id the store is
* keyed by, the PWA carries the provider id directly. An item that
* cannot be placed is left to the post-reload check.
* keyed by, the PWA carries the provider id directly. An item whose
* category is not in that list (a manually hidden category, opened
* through search) cannot be judged without an awaited read that may
* hang, so it is cleared too: fail closed.
*/
private stepOffLockedXtreamSelection(
playlistId: string,
@@ -249,7 +251,8 @@ export class ParentalLockEnforcementService {
) as { xtream_id?: number; category_id?: string } | undefined;
const providerId = Number(category?.xtream_id ?? category?.category_id);
if (
!Number.isFinite(providerId) ||
category &&
Number.isFinite(providerId) &&
!this.parentalLock.isXtreamCategoryLocked(
playlistId,
categoryType,