mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-12 12:06:16 -08:00
refactor: improve archive playback support in video player and unify EPG display across components
This commit is contained in:
1 parent
4005687f18
commit
9c0d49a1dc
6 files changed
+67
-5
No files matched your search
@@ -27,6 +27,7 @@
|
||||
|
||||
<div class="content-container">
|
||||
@if (activeChannel(); as activeChannel) {
|
||||
@let playbackTarget = playbackChannel();
|
||||
@if (activeChannel.radio === 'true' || shouldShowInlinePlayer(activeChannel)) {
|
||||
<div class="video-player">
|
||||
@if (activeChannel.radio === 'true') {
|
||||
@@ -42,8 +43,8 @@
|
||||
sources: [
|
||||
{
|
||||
src:
|
||||
activeChannel.url +
|
||||
activeChannel.epgParams,
|
||||
playbackTarget?.url +
|
||||
playbackTarget?.epgParams,
|
||||
type: 'application/x-mpegURL',
|
||||
},
|
||||
],
|
||||
@@ -54,14 +55,14 @@
|
||||
}
|
||||
@if (playerSettings.player === 'html5') {
|
||||
<app-html-video-player
|
||||
[channel]="activeChannel"
|
||||
[channel]="playbackTarget!"
|
||||
[volume]="volume"
|
||||
[showCaptions]="playerSettings.showCaptions!"
|
||||
/>
|
||||
}
|
||||
@if (playerSettings.player === 'artplayer') {
|
||||
<app-art-player
|
||||
[channel]="activeChannel"
|
||||
[channel]="playbackTarget!"
|
||||
[volume]="volume"
|
||||
[showCaptions]="playerSettings.showCaptions!"
|
||||
/>
|
||||
@@ -73,7 +74,9 @@
|
||||
@if (activeChannel.radio !== 'true') {
|
||||
<div class="epg">
|
||||
<div class="epg-content">
|
||||
<app-epg-list />
|
||||
<app-epg-list
|
||||
[archivePlaybackAvailable]="archivePlaybackAvailable()"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import { BehaviorSubject, of } from 'rxjs';
|
||||
import {
|
||||
ChannelActions,
|
||||
selectActive,
|
||||
selectActivePlaybackUrl,
|
||||
selectChannels,
|
||||
selectCurrentEpgProgram,
|
||||
} from 'm3u-state';
|
||||
@@ -34,6 +35,7 @@ describe('VideoPlayerComponent', () => {
|
||||
|
||||
const playlistId = signal('playlist-1');
|
||||
const activeChannel = signal<Channel | null>(null);
|
||||
const activePlaybackUrl = signal<string | null>(null);
|
||||
const channels = signal<Channel[]>([]);
|
||||
const currentEpgProgram = signal(null);
|
||||
|
||||
@@ -66,6 +68,8 @@ describe('VideoPlayerComponent', () => {
|
||||
switch (selector) {
|
||||
case selectActive:
|
||||
return activeChannel;
|
||||
case selectActivePlaybackUrl:
|
||||
return activePlaybackUrl;
|
||||
case selectChannels:
|
||||
return channels;
|
||||
case selectCurrentEpgProgram:
|
||||
@@ -143,6 +147,7 @@ describe('VideoPlayerComponent', () => {
|
||||
localStorage.removeItem('m3u-sidebar-width');
|
||||
player.set(VideoPlayer.VideoJs);
|
||||
showCaptions.set(false);
|
||||
activePlaybackUrl.set(null);
|
||||
currentEpgProgram.set(null);
|
||||
currentEpgProgram$.next(null);
|
||||
overlayMock.create.mockClear();
|
||||
@@ -286,6 +291,25 @@ describe('VideoPlayerComponent', () => {
|
||||
).not.toBeNull();
|
||||
});
|
||||
|
||||
it('uses the active playback override url when archive playback is active', () => {
|
||||
syncStoreState(sampleChannel);
|
||||
player.set(VideoPlayer.VideoJs);
|
||||
activePlaybackUrl.set(
|
||||
'http://localhost/archive.m3u8?utc=123&lutc=456'
|
||||
);
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(component.playbackChannel()?.url).toBe(
|
||||
'http://localhost/archive.m3u8?utc=123&lutc=456'
|
||||
);
|
||||
|
||||
activePlaybackUrl.set(null);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(component.playbackChannel()?.url).toBe(sampleChannel.url);
|
||||
});
|
||||
|
||||
it('updates the outer sidebar width while grouped view requests a larger total width', () => {
|
||||
fixture.detectChanges();
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import { Store } from '@ngrx/store';
|
||||
import { StorageMap } from '@ngx-pwa/local-storage';
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { ResizableDirective } from 'components';
|
||||
import { isM3uCatchupPlaybackSupported } from 'm3u-utils';
|
||||
import { PlaylistContextFacade } from '@iptvnator/playlist/shared/util';
|
||||
import {
|
||||
COMPONENT_OVERLAY_REF,
|
||||
@@ -28,6 +29,7 @@ import {
|
||||
ChannelActions,
|
||||
PlaylistActions,
|
||||
selectActive,
|
||||
selectActivePlaybackUrl,
|
||||
selectChannels,
|
||||
selectCurrentEpgProgram,
|
||||
} from 'm3u-state';
|
||||
@@ -114,8 +116,31 @@ export class VideoPlayerComponent implements OnInit, OnDestroy {
|
||||
|
||||
/** Active selected channel */
|
||||
readonly activeChannel = this.store.selectSignal(selectActive);
|
||||
readonly activePlaybackUrl = this.store.selectSignal(
|
||||
selectActivePlaybackUrl
|
||||
);
|
||||
readonly activePlaylistId = this.playlistContext.resolvedPlaylistId;
|
||||
readonly channels = this.store.selectSignal(selectChannels);
|
||||
readonly archivePlaybackAvailable = computed(() =>
|
||||
isM3uCatchupPlaybackSupported(this.activeChannel())
|
||||
);
|
||||
readonly playbackChannel = computed<Channel | null>(() => {
|
||||
const activeChannel = this.activeChannel();
|
||||
if (!activeChannel) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const playbackUrl = this.activePlaybackUrl();
|
||||
if (!playbackUrl) {
|
||||
return activeChannel;
|
||||
}
|
||||
|
||||
return {
|
||||
...activeChannel,
|
||||
url: playbackUrl,
|
||||
epgParams: '',
|
||||
} as Channel;
|
||||
});
|
||||
readonly sidebarStorageKey = computed(() =>
|
||||
this.activeView() === 'groups'
|
||||
? M3U_GROUPS_SIDEBAR_STORAGE_KEY
|
||||
|
||||
+3
@@ -112,6 +112,9 @@
|
||||
<app-epg-list
|
||||
[controlledChannel]="currentM3uChannel()"
|
||||
[controlledPrograms]="currentM3uPrograms()"
|
||||
[archivePlaybackAvailable]="
|
||||
currentM3uArchivePlaybackAvailable()
|
||||
"
|
||||
/>
|
||||
} @else {
|
||||
<app-epg-view [epgItems]="currentPortalEpgItems()" />
|
||||
|
||||
+4
@@ -12,6 +12,7 @@ import {
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { isM3uCatchupPlaybackSupported } from 'm3u-utils';
|
||||
import {
|
||||
matchesOpenLiveCollectionItem,
|
||||
OpenLiveCollectionItemState,
|
||||
@@ -106,6 +107,9 @@ export class UnifiedLiveTabComponent {
|
||||
|
||||
return detail.channel ?? null;
|
||||
});
|
||||
readonly currentM3uArchivePlaybackAvailable = computed(() =>
|
||||
isM3uCatchupPlaybackSupported(this.currentM3uChannel())
|
||||
);
|
||||
readonly activeRadioChannel = computed(() => {
|
||||
const channel = this.currentM3uChannel();
|
||||
return channel?.radio === 'true' ? channel : null;
|
||||
|
||||
+3
@@ -107,6 +107,9 @@
|
||||
<app-epg-list
|
||||
[controlledPrograms]="epgPrograms"
|
||||
[controlledArchiveDays]="controlledArchiveDays()"
|
||||
[archivePlaybackAvailable]="
|
||||
archivePlaybackAvailable()
|
||||
"
|
||||
(programActivated)="onProgramActivated($event)"
|
||||
/>
|
||||
} @else if (!isElectron && epgItems().length > 0) {
|
||||
|
||||
Reference in new issue
Block a user