mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 17:06:15 -08:00
fix(settings): step off the M3U channel and Stalker selection before awaiting the Xtream relock reload
The Xtream store stays populated after leaving that portal, so its reload runs on every apply; a locked M3U channel no longer keeps playing behind a slow database or provider read. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
5c141b24b8
commit
d4d0754e12
3 files changed
+43
-9
No files matched your search
@@ -9,12 +9,15 @@ import { ParentalLockEnforcementService } from './parental-lock-enforcement.serv
|
||||
import { PlaybackKeepAwakeService } from './playback-keep-awake.service';
|
||||
|
||||
interface Applier {
|
||||
apply(): Promise<void>;
|
||||
applyXtream(version: number): Promise<void>;
|
||||
applyStalker(): Promise<void>;
|
||||
}
|
||||
|
||||
describe('ParentalLockEnforcementService', () => {
|
||||
const router = { url: '/', navigate: jest.fn() };
|
||||
const activeChannel = signal<{ group?: { title: string } } | null>(null);
|
||||
const dispatch = jest.fn();
|
||||
const lockedStalkerIds = new Set<string>();
|
||||
const parentalLock = {
|
||||
version: signal(0),
|
||||
@@ -76,10 +79,7 @@ describe('ParentalLockEnforcementService', () => {
|
||||
{ provide: Router, useValue: router },
|
||||
{
|
||||
provide: Store,
|
||||
useValue: {
|
||||
selectSignal: () => signal(null),
|
||||
dispatch: jest.fn(),
|
||||
},
|
||||
useValue: { selectSignal: () => activeChannel, dispatch },
|
||||
},
|
||||
{
|
||||
provide: PlaybackKeepAwakeService,
|
||||
@@ -87,11 +87,38 @@ describe('ParentalLockEnforcementService', () => {
|
||||
},
|
||||
],
|
||||
});
|
||||
activeChannel.set(null);
|
||||
service = TestBed.inject(
|
||||
ParentalLockEnforcementService
|
||||
) as unknown as Applier;
|
||||
});
|
||||
|
||||
describe('M3U', () => {
|
||||
it('resets a locked playing channel before awaiting the portal reloads', async () => {
|
||||
router.url = '/workspace/playlists/m3u-1';
|
||||
activeChannel.set({ group: { title: 'Adult' } });
|
||||
parentalLock.isM3uGroupLocked.mockReturnValue(true);
|
||||
let releaseReload: () => void = () => undefined;
|
||||
xtreamStore.reloadCategories.mockImplementationOnce(
|
||||
() => new Promise<void>((resolve) => (releaseReload = resolve))
|
||||
);
|
||||
|
||||
const applying = service.apply();
|
||||
await Promise.resolve();
|
||||
|
||||
expect(parentalLock.isM3uGroupLocked).toHaveBeenCalledWith(
|
||||
'm3u-1',
|
||||
'Adult'
|
||||
);
|
||||
expect(dispatch).toHaveBeenCalledTimes(1);
|
||||
expect(xtreamStore.reloadCategories).toHaveBeenCalledTimes(1);
|
||||
|
||||
releaseReload();
|
||||
await applying;
|
||||
parentalLock.isM3uGroupLocked.mockReturnValue(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Stalker', () => {
|
||||
it('clears a detail opened from All whose own genre is withheld', async () => {
|
||||
router.url = '/workspace/stalker/stalker-1/vod/42';
|
||||
|
||||
@@ -79,11 +79,13 @@ export class ParentalLockEnforcementService {
|
||||
|
||||
private async apply(): Promise<void> {
|
||||
const version = this.parentalLock.version();
|
||||
await Promise.all([this.applyXtream(version), this.applyStalker()]);
|
||||
if (this.parentalLock.version() !== version) {
|
||||
return;
|
||||
}
|
||||
// The synchronous surfaces first: an M3U channel or a Stalker
|
||||
// selection must not keep playing behind a slow Xtream database or
|
||||
// provider reload — the Xtream store stays populated after leaving
|
||||
// that portal, so its reload runs on every apply.
|
||||
this.applyM3u();
|
||||
await this.applyStalker();
|
||||
await this.applyXtream(version);
|
||||
}
|
||||
|
||||
private async applyXtream(version: number): Promise<void> {
|
||||
|
||||
@@ -151,7 +151,12 @@ on either side.
|
||||
"All", recently added or search has no selected category to vanish
|
||||
with, so its row disappearing from a list is not enough — the item is
|
||||
cleared and the route returns to the section root while the (still
|
||||
readable) selected category stays. Applies run one at a time and each is
|
||||
readable) selected category stays. Within one apply the synchronous
|
||||
surfaces (the M3U active channel, the Stalker selection) are stepped off
|
||||
BEFORE the Xtream reloads are awaited, so a playing M3U channel never
|
||||
waits behind a slow portal read — the Xtream store stays populated after
|
||||
leaving that portal, so its reload runs on every apply. Applies run one
|
||||
at a time and each is
|
||||
abandoned once a newer `version` exists (the queued apply reads the latest
|
||||
state): `ElectronXtreamDataSource` shares in-flight category/content
|
||||
reads per playlist and type, and its share key carries the lock version,
|
||||
|
||||
Reference in new issue
Block a user