From 2c3a06b6f999bab7a64b2aa1f9bdb2a0dc12b71e Mon Sep 17 00:00:00 2001 From: 4gray Date: Mon, 1 Apr 2024 23:32:40 +0200 Subject: [PATCH] feat(xtream): update live streams layout --- .../live-stream-layout.component.html | 40 ++++++++++++++ .../live-stream-layout.component.scss | 47 +++++++++++++++++ .../live-stream-layout.component.ts | 24 +++++++++ .../xtream-main-container.component.html | 18 +++++-- .../xtream/xtream-main-container.component.ts | 52 +++++++++++++++---- 5 files changed, 168 insertions(+), 13 deletions(-) create mode 100644 src/app/portals/live-stream-layout/live-stream-layout.component.html create mode 100644 src/app/portals/live-stream-layout/live-stream-layout.component.scss create mode 100644 src/app/portals/live-stream-layout/live-stream-layout.component.ts diff --git a/src/app/portals/live-stream-layout/live-stream-layout.component.html b/src/app/portals/live-stream-layout/live-stream-layout.component.html new file mode 100644 index 000000000..aebd99c8e --- /dev/null +++ b/src/app/portals/live-stream-layout/live-stream-layout.component.html @@ -0,0 +1,40 @@ +
+ + @if (player === 'videojs' || player === 'html5') { +
+ @if (streamUrl) { + + } +
+ } +
+
+ +
+
+
diff --git a/src/app/portals/live-stream-layout/live-stream-layout.component.scss b/src/app/portals/live-stream-layout/live-stream-layout.component.scss new file mode 100644 index 000000000..7f6de82ab --- /dev/null +++ b/src/app/portals/live-stream-layout/live-stream-layout.component.scss @@ -0,0 +1,47 @@ +:host { + width: 100%; +} + +.itv-container { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + grid-template-rows: 1fr 1fr 1fr; + gap: 0 0; + grid-auto-flow: row; + grid-template-areas: + 'sidebar video-player video-player' + 'sidebar epg epg' + 'sidebar epg epg'; + height: 100%; +} + +.itv-container-epg { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + grid-template-rows: 1fr 1fr 1fr; + gap: 0 0; + grid-auto-flow: row; + grid-template-areas: + 'sidebar epg epg' + 'sidebar epg epg' + 'sidebar epg epg'; + height: 100%; +} + +.sidebar { grid-area: sidebar; } + +.video-player { grid-area: video-player; } + +.epg { grid-area: epg; } + +.epg-content { + height: 100%; + overflow-y: auto; + border-right: #111 1px solid; +} + +.sidebar-content { + height: 100%; + overflow-y: auto; + border-right: #111 1px solid; +} diff --git a/src/app/portals/live-stream-layout/live-stream-layout.component.ts b/src/app/portals/live-stream-layout/live-stream-layout.component.ts new file mode 100644 index 000000000..fc28cddc7 --- /dev/null +++ b/src/app/portals/live-stream-layout/live-stream-layout.component.ts @@ -0,0 +1,24 @@ +import { NgIf } from '@angular/common'; +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { MatListModule } from '@angular/material/list'; +import { XtreamItem } from '../../../../shared/xtream-item.interface'; +import { VideoPlayer } from '../../settings/settings.interface'; +import { EpgItem } from '../../xtream/epg-item.interface'; +import { EpgViewComponent } from '../epg-view/epg-view.component'; +import { WebPlayerViewComponent } from '../web-player-view/web-player-view.component'; + +@Component({ + standalone: true, + selector: 'app-live-stream-layout', + templateUrl: './live-stream-layout.component.html', + styleUrls: ['./live-stream-layout.component.scss'], + imports: [EpgViewComponent, MatListModule, NgIf, WebPlayerViewComponent], +}) +export class LiveStreamLayoutComponent { + @Input({ required: true }) channels: XtreamItem[]; + @Input({ required: true }) player: VideoPlayer = VideoPlayer.VideoJs; + @Input() epgItems: EpgItem[]; + @Input() streamUrl: string; + + @Output() itemClicked = new EventEmitter(); +} diff --git a/src/app/xtream/xtream-main-container.component.html b/src/app/xtream/xtream-main-container.component.html index 577727dd3..b1cd40ce0 100644 --- a/src/app/xtream/xtream-main-container.component.html +++ b/src/app/xtream/xtream-main-container.component.html @@ -30,10 +30,20 @@ /> } @case ('category_content') { - + @if (selectedContentType === 'itv') { + + } @else { + + } } @case ('vod-details') { ; breadcrumbs: Breadcrumb[] = []; items = []; @@ -160,6 +173,8 @@ export class XtreamMainContainerComponent implements OnInit { searchPhrase = this.portalStore.searchPhrase(); contentId: number; errorViewInfo = { title: '', message: '' }; + streamUrl: string; + epgItems = []; commandsList = [ new IpcCommand(XTREAM_RESPONSE, (response: XtreamResponse) => @@ -233,6 +248,15 @@ export class XtreamMainContainerComponent implements OnInit { this.currentLayout = 'serie-details'; this.vodDetails = response.payload as XtreamSerieDetails; break; + case 'get_short_epg': + this.epgItems = ( + (response.payload as any).epg_listings as EpgItem[] + ).map((i) => ({ + ...i, + title: b64DecodeUnicode(i.title).trim(), + description: b64DecodeUnicode(i.description).trim(), + })); + break; default: break; } @@ -287,6 +311,11 @@ export class XtreamMainContainerComponent implements OnInit { this.contentId = item.stream_id; this.sendRequest({ action, vod_id: item.stream_id }); } else if (item.stream_type && item.stream_type === 'live') { + this.sendRequest({ + action: 'get_short_epg', + stream_id: item.stream_id, + limit: 10, + }); this.playLiveStream(item); } else if (item.series_id) { this.items = []; @@ -304,22 +333,25 @@ export class XtreamMainContainerComponent implements OnInit { } openPlayer(streamUrl: string, title: string) { - const player = this.settings().player; - if (player === VideoPlayer.MPV) { + this.player = this.settings().player ?? VideoPlayer.VideoJs; + if (this.player === VideoPlayer.MPV) { this.dialog.open(ExternalPlayerInfoDialogComponent); this.dataService.sendIpcEvent(OPEN_MPV_PLAYER, { url: streamUrl, }); - } else if (player === VideoPlayer.VLC) { + } else if (this.player === VideoPlayer.VLC) { this.dialog.open(ExternalPlayerInfoDialogComponent); this.dataService.sendIpcEvent(OPEN_VLC_PLAYER, { url: streamUrl, }); } else { - this.dialog.open(PlayerDialogComponent, { - data: { streamUrl, player, title }, - width: '80%', - }); + this.streamUrl = streamUrl; + if (this.selectedContentType !== ContentType.ITV) { + this.dialog.open(PlayerDialogComponent, { + data: { streamUrl, player: this.player, title }, + width: '80%', + }); + } } } @@ -427,7 +459,9 @@ export class XtreamMainContainerComponent implements OnInit { } sendRequest(params: Record) { - this.isLoading = true; + if (params.action !== 'get_short_epg') { + this.isLoading = true; + } const { serverUrl, username, password } = this.currentPlaylist(); this.dataService.sendIpcEvent(XTREAM_REQUEST, { url: serverUrl,