From 2e861b6a1f2c0744bc1eaae632a79087d1721f41 Mon Sep 17 00:00:00 2001 From: 4gray Date: Sun, 31 Jan 2021 23:16:23 +0100 Subject: [PATCH] feat: epg integration --- src/app/app.component.ts | 11 +---- .../epg-list/epg-list.component.html | 41 +++++++++++------ .../epg-list/epg-list.component.scss | 46 +++++++++++++++++-- .../components/epg-list/epg-list.component.ts | 16 +++++++ .../html-video-player.component.ts | 8 ++-- .../video-player/video-player.component.html | 2 +- 6 files changed, 93 insertions(+), 31 deletions(-) diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 9af594cf6..e174ae347 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,7 +1,5 @@ import { Component, NgZone } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; -import { AppConfig } from '../environments/environment'; -import { akitaDevtools } from '@datorama/akita'; import { Titlebar, Color } from 'custom-electron-titlebar'; import { ElectronService } from './services/electron.service'; import { Router } from '@angular/router'; @@ -33,11 +31,7 @@ export class AppComponent { private snackBar: MatSnackBar, private storage: StorageMap ) { - if (!AppConfig.production) { - akitaDevtools(ngZone); - } this.translate.setDefaultLang('en'); - console.log('AppConfig', AppConfig); if (electronService.isElectron) { console.log(process.env); @@ -61,10 +55,7 @@ export class AppComponent { this.electronService.ipcRenderer.on(EPG_FETCH_DONE, () => { this.ngZone.run(() => { - this.channelStore.update((store) => ({ - ...store, - epgAvailable: true, - })); + this.channelStore.setEpgAvailableFlag(true); this.snackBar.open('EPG was successfully downloaded!', null, { duration: 2000, verticalPosition: 'bottom', diff --git a/src/app/player/components/epg-list/epg-list.component.html b/src/app/player/components/epg-list/epg-list.component.html index c4a3f4918..1ede1420e 100644 --- a/src/app/player/components/epg-list/epg-list.component.html +++ b/src/app/player/components/epg-list/epg-list.component.html @@ -1,27 +1,42 @@ -
- -
- {{ channel?.name[0]?.value }} +
+ +
+
{{ channel?.name[0]?.value }}
+ +
Playing now:
+
+ {{ + playingNow ? playingNow.title[0]?.value : 'Live stream' + }} +
+
- - +
{{ item.start }} - {{ item.stop }} + live

{{ item?.title[0]?.value }}

-
-
+ + diff --git a/src/app/player/components/epg-list/epg-list.component.scss b/src/app/player/components/epg-list/epg-list.component.scss index 5e03280b4..94ab206d1 100644 --- a/src/app/player/components/epg-list/epg-list.component.scss +++ b/src/app/player/components/epg-list/epg-list.component.scss @@ -1,8 +1,21 @@ -.active { - background-color: #ddd; +:host { + display: flex; + flex-direction: column; + position: absolute; + top: 0; + right: 0; + left: 0; + bottom: 0; + height: 100%; } -.time { +.active { + border-bottom: 1px dashed #666; + background: linear-gradient(to top, #d2d2d2 0%, #d6d6d6 20%, rgba(255, 255, 255, 0) 100%) + +} + +.time, .playing-now { color: #666; border-bottom: 1px solid #ccc; font-size: 0.8em; @@ -10,16 +23,41 @@ margin-bottom: 5px; } +.epg-program-name { + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 1; + -webkit-box-orient: vertical; + font-size: 0.9em; +} + #channel-info { padding:10px; border-bottom: 1px solid #ccc; + box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); + background-color: #ccc; } .channel-name { - padding-left: 10px + font-weight: 800; } mat-list { height: calc(100vh - 110px); overflow: auto; +} + +mat-selection-list { + overflow: auto; +} + +.live-badge { + background-color: red; + border-radius: 2px; + padding: 2px 6px; + color: #fff; + text-transform: uppercase; + margin-left: 6px; + font-size: 0.8em; } \ No newline at end of file diff --git a/src/app/player/components/epg-list/epg-list.component.ts b/src/app/player/components/epg-list/epg-list.component.ts index 63432dd5e..994ad7e23 100644 --- a/src/app/player/components/epg-list/epg-list.component.ts +++ b/src/app/player/components/epg-list/epg-list.component.ts @@ -4,6 +4,7 @@ import { EpgProgram } from '../../models/epg-program.model'; import * as moment from 'moment'; import { ElectronService } from '../../../services/electron.service'; import { EPG_GET_PROGRAM_DONE } from '../../../shared/ipc-commands'; +import { ChannelStore } from 'app/state'; interface EpgData { channel: EpgChannel; @@ -30,6 +31,9 @@ export class EpgListComponent { payload: EpgData; }; + /** EPG selected program */ + playingNow: EpgProgram; + /** Current time as formatted string */ timeNow: string; @@ -39,6 +43,7 @@ export class EpgListComponent { * @param ngZone */ constructor( + private channelStore: ChannelStore, private electronService: ElectronService, private ngZone: NgZone ) { @@ -81,6 +86,17 @@ export class EpgListComponent { } } + /** + * Sets the provided epg program as active and starts to play + * @param program + */ + setEpgProgram(program: EpgProgram, isLive?: boolean): void { + isLive + ? this.channelStore.resetActiveEpgProgram() + : this.channelStore.setActiveEpgProgram(program); + this.playingNow = program; + } + /** * Removes all ipc renderer listeners after destroy */ diff --git a/src/app/player/components/html-video-player/html-video-player.component.ts b/src/app/player/components/html-video-player/html-video-player.component.ts index af6727522..b08635706 100644 --- a/src/app/player/components/html-video-player/html-video-player.component.ts +++ b/src/app/player/components/html-video-player/html-video-player.component.ts @@ -41,16 +41,18 @@ export class HtmlVideoPlayerComponent implements OnChanges, OnDestroy { * @param channel given channel object */ playChannel(channel: Channel): void { + const url = channel.url + channel.epgParams; if (Hls.isSupported()) { - console.log('... switching channel to ', channel.name, channel.url); - this.hls.loadSource(channel.url); + console.log('... switching channel to ', channel.name, url); + this.hls.loadSource(url); this.hls.attachMedia(this.videoPlayer.nativeElement); + this.videoPlayer.nativeElement.play(); } else if ( this.videoPlayer.nativeElement.canPlayType( 'application/vnd.apple.mpegurl' ) ) { - this.videoPlayer.nativeElement.src = channel.url; + this.videoPlayer.nativeElement.src = url; this.videoPlayer.nativeElement.addEventListener( 'loadedmetadata', () => { diff --git a/src/app/player/components/video-player/video-player.component.html b/src/app/player/components/video-player/video-player.component.html index 3837cde82..090ad2395 100644 --- a/src/app/player/components/video-player/video-player.component.html +++ b/src/app/player/components/video-player/video-player.component.html @@ -55,7 +55,7 @@ [options]="{ sources: [ { - src: activeChannel.url, + src: activeChannel.url + activeChannel.epgParams, type: 'application/x-mpegURL' } ]