mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-11 19:46:16 -08:00
fix(ui): hold the provider play action and the reset row during their busy windows
The downloaded movie's provider action stays enabled while a start was pending, so a second press could start beside a launch already inside the player IPC. The series menu's reset row stayed enabled while a watched batch persisted, although the hosts refuse the reset meanwhile. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
5c9a12fa79
commit
5a5fe4adcf
6 files changed
+33
-4
No files matched your search
@@ -66,6 +66,7 @@ export class StalkerSeriesMenuService {
|
||||
hasProgress: this.bindings()?.hasProgress() ?? false,
|
||||
playbackActive: this.bindings()?.playbackActive() ?? false,
|
||||
startPending: this.bindings()?.startPending() ?? false,
|
||||
watchBatchRunning: container?.seasonWatchBatchRunning() ?? false,
|
||||
sourcesCount: 0,
|
||||
externalPlayerHint:
|
||||
quickStart?.action &&
|
||||
|
||||
@@ -163,6 +163,7 @@ export class SerialDetailsMenuService {
|
||||
hasProgress: this.hasProgress(),
|
||||
playbackActive: this.bindings()?.playbackActive() ?? false,
|
||||
startPending: this.bindings()?.startPending() ?? false,
|
||||
watchBatchRunning: container?.seasonWatchBatchRunning() ?? false,
|
||||
sourcesCount: 0,
|
||||
externalPlayerHint:
|
||||
quickStart && this.runtime.supportsManagedExternalPlayers
|
||||
|
||||
@@ -16,6 +16,7 @@ const BASE = {
|
||||
hasProgress: true,
|
||||
playbackActive: false,
|
||||
startPending: false,
|
||||
watchBatchRunning: false,
|
||||
sourcesCount: 0,
|
||||
externalPlayerHint: 'MPV' as const,
|
||||
copyUrlEpisodeCode: null,
|
||||
@@ -49,6 +50,12 @@ describe('buildSeriesMenuSections', () => {
|
||||
expect(resetRow({ seriesActionDisabled: true })?.disabled).toBeFalsy();
|
||||
});
|
||||
|
||||
it('disables the progress reset while a watched batch persists', () => {
|
||||
// The hosts refuse the reset request meanwhile; an enabled row
|
||||
// would close the menu and do nothing.
|
||||
expect(resetRow({ watchBatchRunning: true })?.disabled).toBe(true);
|
||||
});
|
||||
|
||||
it('hides the reset once every episode is watched', () => {
|
||||
expect(resetRow({ seriesFullyWatched: true })).toBeUndefined();
|
||||
});
|
||||
|
||||
@@ -195,6 +195,8 @@ export interface SeriesMenuInput {
|
||||
readonly playbackActive: boolean;
|
||||
/** A start has not settled: another launch would double it. */
|
||||
readonly startPending: boolean;
|
||||
/** A season/series watched batch still persists: a reset request is refused meanwhile. */
|
||||
readonly watchBatchRunning: boolean;
|
||||
readonly sourcesCount: number;
|
||||
readonly externalPlayerHint: 'MPV' | 'VLC' | null;
|
||||
readonly copyUrlEpisodeCode: string | null;
|
||||
@@ -242,7 +244,7 @@ export function buildSeriesMenuSections(
|
||||
id: SERIES_MENU_ACTION.ResetProgress,
|
||||
labelKey: 'PORTALS.DETAIL.RESET_PROGRESS',
|
||||
icon: 'history_toggle_off',
|
||||
disabled: input.playbackActive,
|
||||
disabled: input.playbackActive || input.watchBatchRunning,
|
||||
testId: 'vod-menu-reset-progress',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -158,6 +158,9 @@
|
||||
"
|
||||
icon="play_arrow"
|
||||
testId="vod-play-provider"
|
||||
[disabled]="
|
||||
isExternalLaunchPending() || playbackStartPending()
|
||||
"
|
||||
(pressed)="onProviderAction()"
|
||||
/>
|
||||
}
|
||||
|
||||
@@ -160,9 +160,7 @@ describe('VodDetailsComponent offline playback', () => {
|
||||
};
|
||||
|
||||
const closeMenu = async (): Promise<void> => {
|
||||
document
|
||||
.querySelector<HTMLElement>('.cdk-overlay-backdrop')
|
||||
?.click();
|
||||
document.querySelector<HTMLElement>('.cdk-overlay-backdrop')?.click();
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
};
|
||||
@@ -420,6 +418,23 @@ describe('VodDetailsComponent offline playback', () => {
|
||||
expect(playDownload).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('holds the downloaded provider action while a start is pending', async () => {
|
||||
completeDownload();
|
||||
await render();
|
||||
expect(providerPlayButton()?.disabled).toBe(false);
|
||||
|
||||
// Same window as the primary action: a second start could not cancel
|
||||
// a launch already inside the player IPC.
|
||||
fixture.componentRef.setInput('playbackStartPending', true);
|
||||
fixture.detectChanges();
|
||||
expect(providerPlayButton()?.disabled).toBe(true);
|
||||
|
||||
providerPlayButton()?.click();
|
||||
await fixture.whenStable();
|
||||
expect(playClicked).not.toHaveBeenCalled();
|
||||
expect(resumeClicked).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('resumes the provider source from the downloaded secondary action', async () => {
|
||||
completeDownload();
|
||||
await render({ playbackPosition: 83 });
|
||||
|
||||
Reference in new issue
Block a user