diff --git a/libs/playlist/m3u/feature-player/src/lib/video-player/video-player.component.ts b/libs/playlist/m3u/feature-player/src/lib/video-player/video-player.component.ts index 4999d4820..be43235a5 100644 --- a/libs/playlist/m3u/feature-player/src/lib/video-player/video-player.component.ts +++ b/libs/playlist/m3u/feature-player/src/lib/video-player/video-player.component.ts @@ -21,7 +21,10 @@ import { Store } from '@ngrx/store'; import { StorageMap } from '@ngx-pwa/local-storage'; import { TranslatePipe } from '@ngx-translate/core'; import { ResizableDirective } from '@iptvnator/ui/components'; -import { isM3uCatchupPlaybackSupported } from '@iptvnator/shared/m3u-utils'; +import { + getM3uArchiveDays, + isM3uCatchupPlaybackSupported, +} from '@iptvnator/shared/m3u-utils'; import { PlaylistContextFacade } from '@iptvnator/playlist/shared/util'; import { COMPONENT_OVERLAY_REF, @@ -171,12 +174,12 @@ export class VideoPlayerComponent implements OnInit, OnDestroy { readonly epgPrograms = toSignal(this.epgService.currentEpgPrograms$, { initialValue: [] as EpgProgram[], }); - readonly epgArchiveDays = computed(() => { - const channel = this.activeChannel(); - const value = - channel?.tvg?.rec ?? channel?.timeshift ?? channel?.catchup?.days; - return Math.max(0, Number(value ?? 0) || 0); - }); + // Shared helper skips blank strings (`tvg-rec=""` is a common default that + // `??` would not fall through), so a channel with only `timeshift`/ + // `catchup-days` still gets its real window instead of 0 (unbounded). + readonly epgArchiveDays = computed(() => + getM3uArchiveDays(this.activeChannel()) + ); readonly timelineChannelName = computed( () => this.activeChannel()?.name ?? '' ); diff --git a/libs/shared/m3u-utils/src/lib/catchup.utils.spec.ts b/libs/shared/m3u-utils/src/lib/catchup.utils.spec.ts index 19c9961df..676c415d0 100644 --- a/libs/shared/m3u-utils/src/lib/catchup.utils.spec.ts +++ b/libs/shared/m3u-utils/src/lib/catchup.utils.spec.ts @@ -66,6 +66,20 @@ describe('catchup.utils', () => { ).toBe(7); }); + it('skips a blank tvg-rec and uses a real timeshift value', () => { + // `tvg-rec=""` is a common parser default; a nullish (`??`) chain would + // stop on it and yield 0 (unbounded window). The non-blank helper skips + // it and returns the real timeshift days. + expect( + getM3uArchiveDays({ + ...baseChannel, + catchup: undefined, + timeshift: '7', + tvg: { ...baseChannel.tvg, rec: '' }, + }) + ).toBe(7); + }); + it('supports legacy same-stream shift playback when catchup type is shift', () => { expect(isM3uCatchupPlaybackSupported(baseChannel)).toBe(true); expect(resolveM3uCatchupUrl(baseChannel, archivedProgram, 1_775_820_000))