Starting to clean up the player

This commit is contained in:
Zoe Roux 2020-10-11 01:47:57 +02:00
parent de8fed8694
commit 2b8c527fdf
4 changed files with 188 additions and 160 deletions

View File

@ -18,6 +18,8 @@ export class AppComponent
libraries: Library[]; libraries: Library[];
isLoading: boolean = false; isLoading: boolean = false;
static isMobile: boolean = false;
constructor(private libraryService: LibraryService, constructor(private libraryService: LibraryService,
private router: Router, private router: Router,
private location: Location, private location: Location,
@ -47,7 +49,8 @@ export class AppComponent
} }
}); });
if (!navigator.userAgent.match(/Mobi/)) AppComponent.isMobile = !!navigator.userAgent.match(/Mobi/);
if (!AppComponent.isMobile)
document.body.classList.add("hoverEnabled"); document.body.classList.add("hoverEnabled");
} }

View File

@ -1,6 +1,14 @@
<div id="root"> <div id="root">
<div class="player data-vjs-player"> <div class="player data-vjs-player">
<video id="player" poster="backdrop/{{this.item.showSlug}}" autoplay muted (click)="videoClicked()"> <video id="player"
poster="backdrop/{{this.item.showSlug}}"
autoplay muted
(click)="this.videoClicked()"
(play)="this.playing = true"
(pause)="this.playing = false"
(ended)="this.next()"
[volume]="this.volume / 100"
[muted]="this.muted">
</video> </video>
</div> </div>
@ -8,25 +16,41 @@
<div class="spinner-border align-self-center" role="status"></div> <div class="spinner-border align-self-center" role="status"></div>
</div> </div>
<mat-card class="d-none w-25 m-5" [ngClass]="{'d-block': this.displayStats}"> <mat-card class="d-none w-25 m-5 stats" [ngClass]="{'d-block': this.displayStats}">
<mat-card-header style="margin-bottom: 0.5rem;"> <mat-card-header>
<h4 style="align-self: center; margin-bottom: 0;">Stats</h4> <h4>Stats</h4>
<div style="flex: 1 1 auto"></div> <div style="flex: 1 1 auto"></div>
<button mat-icon-button aria-label="Close" (click)="this.displayStats = false" style="outline: none;"> <button mat-icon-button aria-label="Close" (click)="this.displayStats = false">
<mat-icon>close</mat-icon> <mat-icon>close</mat-icon>
</button> </button>
</mat-card-header> </mat-card-header>
<mat-card-content> <mat-card-content>
Play method: <span style="float: right">{{this.playMethod}}</span> Play method: <span>{{this.playMethod}}</span>
<br /> <br />
<br /> <br />
Video Container: <span style="float: right">{{this.item.container}} <i class="material-icons" style="vertical-align: middle; font-size: 14px">{{getSupportedFeature("container")}}</i></span> Video Container:
<span>
{{this.item.container}}
<i class="material-icons">{{getSupportedFeature("container")}}</i>
</span>
<br /> <br />
Video Codec: <span style="float: right">{{this.item.video.codec}} <i class="material-icons" style="vertical-align: middle; font-size: 14px">{{getSupportedFeature("video")}}</i></span> Video Codec:
<span>
{{this.item.video.codec}}
<i class="material-icons">{{getSupportedFeature("video")}}</i>
</span>
<br /> <br />
Audio Codec: <span style="float: right">{{this.item.audios[0].codec}} <i class="material-icons" style="vertical-align: middle; font-size: 14px">{{getSupportedFeature("audio")}}</i></span> Audio Codec:
<span>
{{this.item.audios[0].codec}}
<i class="material-icons">{{getSupportedFeature("audio")}}</i>
</span>
<br /> <br />
Subtitle Codec: <span style="float: right">{{this.selectedSubtitle ? this.selectedSubtitle.codec : "none"}} <i class="material-icons" style="vertical-align: middle; font-size: 14px">{{getSupportedFeature("subtitle")}}</i></span> Subtitle Codec:
<span>
{{this.selectedSubtitle ? this.selectedSubtitle.codec : "none"}}
<i class="material-icons">{{getSupportedFeature("subtitle")}}</i>
</span>
<br /> <br />
</mat-card-content> </mat-card-content>
</mat-card> </mat-card>
@ -60,8 +84,10 @@
<a *ngIf="this.item.previousEpisode" mat-icon-button matTooltipPosition="above" matTooltip="Previous" (click)="previous()"> <a *ngIf="this.item.previousEpisode" mat-icon-button matTooltipPosition="above" matTooltip="Previous" (click)="previous()">
<mat-icon>skip_previous</mat-icon> <mat-icon>skip_previous</mat-icon>
</a> </a>
<button mat-icon-button matTooltipPosition="above" [matTooltip]="playTooltip" id="play" (click)="tooglePlayback()"> <button mat-icon-button matTooltipPosition="above" id="play"
<mat-icon>{{this.playIcon}}</mat-icon> [matTooltip]="this.playing ? 'Pause' : 'Play'"
(click)="togglePlayback()">
<mat-icon>{{this.playing ? 'pause' : 'play_arrow'}}</mat-icon>
</button> </button>
<a mat-icon-button id="nextBtn" *ngIf="this.item.nextEpisode" (click)="next()"> <a mat-icon-button id="nextBtn" *ngIf="this.item.nextEpisode" (click)="next()">
<mat-icon>skip_next</mat-icon> <mat-icon>skip_next</mat-icon>
@ -76,13 +102,15 @@
</div> </div>
</div> </div>
</a> </a>
<div id="volume"> <div id="volume" [ngClass]="{'d-none': this.isMobile}">
<button mat-icon-button matTooltipPosition="above" matTooltip="Volume" (click)="toogleMute()"> <button mat-icon-button matTooltipPosition="above" matTooltip="Volume"
<mat-icon>{{this.volumeIcon}}</mat-icon> (click)="this.muted = !this.muted">
<mat-icon>{{this.getVolumeBtn()}}</mat-icon>
</button> </button>
<mat-slider [value]="volume" (input)="changeVolume($event.value)"></mat-slider> <mat-slider [value]="this.volume" (input)="this.volume = $event.value"></mat-slider>
</div> </div>
<!-- TODO REWORK THIS DUMPSTER FIRE OF A TIMER. -->
<p *ngIf="this.maxHours; else elseBlock">{{this.hours | number: '2.0-0'}}:{{this.minutes | number: '2.0-0'}}:{{this.seconds | number: '2.0-0'}} / {{this.maxHours | number: '2.0-0'}}:{{this.maxMinutes | number: '2.0-0'}}:{{this.maxSeconds | number: '2.0-0'}}</p> <p *ngIf="this.maxHours; else elseBlock">{{this.hours | number: '2.0-0'}}:{{this.minutes | number: '2.0-0'}}:{{this.seconds | number: '2.0-0'}} / {{this.maxHours | number: '2.0-0'}}:{{this.maxMinutes | number: '2.0-0'}}:{{this.maxSeconds | number: '2.0-0'}}</p>
<ng-template #elseBlock><p>{{this.minutes | number: '2.0-0'}}:{{this.seconds | number: '2.0-0'}} / {{this.maxMinutes | number: '2.0-0'}}:{{this.maxSeconds | number: '2.0-0'}}</p></ng-template> <ng-template #elseBlock><p>{{this.minutes | number: '2.0-0'}}:{{this.seconds | number: '2.0-0'}} / {{this.maxMinutes | number: '2.0-0'}}:{{this.maxSeconds | number: '2.0-0'}}</p></ng-template>
</div> </div>
@ -90,7 +118,8 @@
<button id="volume" *ngIf="this.item.audios.length > 1" mat-icon-button matTooltipPosition="above" matTooltip="Select audio track"> <button id="volume" *ngIf="this.item.audios.length > 1" mat-icon-button matTooltipPosition="above" matTooltip="Select audio track">
<mat-icon>music_note</mat-icon> <mat-icon>music_note</mat-icon>
</button> </button>
<button *ngIf="this.item.subtitles.length > 0" mat-icon-button [matMenuTriggerFor]="subtitles" matTooltipPosition="above" matTooltip="Select subtitle track"> <button *ngIf="this.item.subtitles.length > 0" mat-icon-button [matMenuTriggerFor]="subtitles"
matTooltipPosition="above" matTooltip="Select subtitle track">
<mat-icon>closed_caption</mat-icon> <mat-icon>closed_caption</mat-icon>
</button> </button>
<button mat-icon-button matTooltipPosition="above" matTooltip="Cast"> <button mat-icon-button matTooltipPosition="above" matTooltip="Cast">
@ -99,8 +128,11 @@
<button mat-icon-button matTooltipPosition="above" [matMenuTriggerFor]="settings" matTooltip="Settings"> <button mat-icon-button matTooltipPosition="above" [matMenuTriggerFor]="settings" matTooltip="Settings">
<mat-icon>settings</mat-icon> <mat-icon>settings</mat-icon>
</button> </button>
<button mat-icon-button matTooltipPosition="above" [matTooltip]="fullscreenTooltip" id="fullscreen" (click)="fullscreen()"> <button mat-icon-button matTooltipPosition="above"
<mat-icon>{{fullscreenIcon}}</mat-icon> [ngClass]="{'d-none': this.isMobile}"
[matTooltip]="this.isFullScreen ? 'Exit fullscreen' : 'Fullscreen'"
(click)="fullscreen()">
<mat-icon>{{this.isFullScreen ? "fullscreen_exit" : "fullscreen"}}</mat-icon>
</button> </button>
</div> </div>
</div> </div>
@ -113,7 +145,10 @@
</button> </button>
<div *ngFor="let subtitle of this.item.subtitles"> <div *ngFor="let subtitle of this.item.subtitles">
<button [ngClass]="{'selected': this.selectedSubtitle == subtitle}" mat-menu-item *ngIf="subtitle.codec == 'ass' || subtitle.codec == 'subrip'; else elseBlock" (click)="selectSubtitle(subtitle)"> <button [ngClass]="{'selected': this.selectedSubtitle == subtitle}"
mat-menu-item *ngIf="subtitle.codec === 'ass' || subtitle.codec === 'subrip';
else elseBlock"
(click)="selectSubtitle(subtitle)">
<span>{{subtitle.displayName}}</span> <span>{{subtitle.displayName}}</span>
</button> </button>

View File

@ -51,8 +51,7 @@
> h5 > h5
{ {
margin: 0; margin: 0 0 0 .5rem;
margin-left: .5rem;
align-self: center; align-self: center;
} }
} }
@ -104,8 +103,7 @@
> p > p
{ {
margin: 0; margin: 0 0 0 1rem;
margin-left: 1rem;
align-self: center; align-self: center;
} }
} }
@ -288,8 +286,8 @@
> mat-slider > mat-slider
{ {
width: 0px; width: 0;
min-width: 0px; min-width: 0;
padding: 0; padding: 0;
height: 40px; height: 40px;
overflow: hidden; overflow: hidden;
@ -331,7 +329,7 @@
.volume .volume
{ {
min-width: 0px !important; min-width: 0 !important;
} }
.info-panel .info-panel
@ -339,3 +337,30 @@
min-width: 250px !important; min-width: 250px !important;
max-width: 300px !important; max-width: 300px !important;
} }
.stats
{
> mat-card-header
{
margin-bottom: 0.5rem;
> h4
{
align-self: center;
margin-bottom: 0;
}
> button
{
outline: none;
}
}
> mat-card-content > span
{
float: right;
> i
{
vertical-align: middle;
font-size: 14px;
}
}
}

View File

@ -1,26 +1,34 @@
import {Component, Injector, OnInit, ViewEncapsulation} from '@angular/core'; import { Component, Injector, OnInit, ViewEncapsulation } from "@angular/core";
import {MatSnackBar} from "@angular/material/snack-bar"; import { MatSnackBar } from "@angular/material/snack-bar";
import {DomSanitizer, Title} from "@angular/platform-browser"; import { DomSanitizer, Title } from "@angular/platform-browser";
import {ActivatedRoute, Event, NavigationCancel, NavigationEnd, NavigationStart, Router} from "@angular/router"; import { ActivatedRoute, Event, NavigationCancel, NavigationEnd, NavigationStart, Router } from "@angular/router";
import {Track, WatchItem} from "../../models/watch-item"; import { AppComponent } from "../../app.component";
import {Location} from "@angular/common"; import { Track, WatchItem } from "../../models/watch-item";
import { Location } from "@angular/common";
import { getPlaybackMethod, getWhatIsSupported, method, SupportList } from "../../../videoSupport/playbackMethodDetector";
import { OidcSecurityService } from "angular-auth-oidc-client";
import * as Hls from "hls.js" import * as Hls from "hls.js"
import {getPlaybackMethod, getWhatIsSupported, method, SupportList} from "../../../videoSupport/playbackMethodDetector";
import {OidcSecurityService} from "angular-auth-oidc-client";
declare var SubtitleManager: any; declare var SubtitleManager: any;
@Component({ @Component({
selector: 'app-player', selector: "app-player",
templateUrl: './player.component.html', templateUrl: "./player.component.html",
styleUrls: ['./player.component.scss'], styleUrls: ["./player.component.scss"],
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
}) })
export class PlayerComponent implements OnInit export class PlayerComponent implements OnInit
{ {
item: WatchItem; item: WatchItem;
playing: boolean = true;
muted: boolean = false;
private _volume: number = 100;
get volume(): number { return this._volume; }
set volume(value: number) { this._volume = Math.max(0, Math.min(value, 100)); }
volume: number = 100;
seeking: boolean = false; seeking: boolean = false;
videoHider; videoHider;
controllerHovered: boolean = false; controllerHovered: boolean = false;
@ -34,13 +42,6 @@ export class PlayerComponent implements OnInit
maxMinutes: number; maxMinutes: number;
maxSeconds: number; maxSeconds: number;
playIcon: string = "pause"; //Icon used by the play btn.
volumeIcon: string = "volume_up"; //Icon used by the volume btn.
fullscreenIcon: string = "fullscreen"; //Icon used by the fullscreen btn.
playTooltip: string = "Pause"; //Text used in the play tooltip
fullscreenTooltip: string = "Fullscreen"; //Text used in the fullscreen tooltip
playMethod: method = method.direct; playMethod: method = method.direct;
methodType = method; methodType = method;
@ -56,7 +57,14 @@ export class PlayerComponent implements OnInit
private oidcSecurity: OidcSecurityService; private oidcSecurity: OidcSecurityService;
constructor(private route: ActivatedRoute, private sanitizer: DomSanitizer, private snackBar: MatSnackBar, private title: Title, private router: Router, private location: Location, private injector: Injector) { } constructor(private route: ActivatedRoute,
private sanitizer: DomSanitizer,
private snackBar: MatSnackBar,
private title: Title,
private router: Router,
private location: Location,
private injector: Injector)
{ }
ngOnInit() ngOnInit()
{ {
@ -64,27 +72,21 @@ export class PlayerComponent implements OnInit
this.route.data.subscribe((data) => this.route.data.subscribe((data) =>
{ {
this.item = data.item; this.item = data.item;
this.item.duration = 20 * 60;
if (this.player) if (this.player)
{
this.player.load(); this.player.load();
this.initPlayBtn();
}
this.setDuration(this.item.duration); this.setDuration(this.item.duration);
if (this.item.isMovie) if (this.item.isMovie)
this.title.setTitle(this.item.showTitle + " - Kyoo"); this.title.setTitle(`${this.item.showTitle} - Kyoo`);
else else
this.title.setTitle(this.item.showTitle + " S" + this.item.seasonNumber + ":E" + this.item.episodeNumber + " - Kyoo"); this.title.setTitle(`${this.item.showTitle} S${this.item.seasonNumber}:E${this.item.episodeNumber} - Kyoo`);
if (navigator.userAgent.match(/Mobi/) && document.fullscreenElement == null) if (AppComponent.isMobile && !this.isFullScreen)
{ {
this.fullscreen(); this.fullscreen();
screen.orientation.lock("landscape"); screen.orientation.lock("landscape");
$("#fullscreen").addClass("d-none");
$("#volume").addClass("d-none");
} }
setTimeout(() => setTimeout(() =>
{ {
@ -94,24 +96,22 @@ export class PlayerComponent implements OnInit
}); });
} }
get isFullScreen(): boolean
{
return document.fullscreenElement != null;
}
get isMobile(): boolean
{
return AppComponent.isMobile;
}
ngAfterViewInit() ngAfterViewInit()
{ {
this.player = document.getElementById("player") as HTMLVideoElement; this.player = document.getElementById("player") as HTMLVideoElement;
this.thumb = document.getElementById("thumb") as HTMLElement; this.thumb = document.getElementById("thumb") as HTMLElement;
this.progress = document.getElementById("progress") as HTMLElement; this.progress = document.getElementById("progress") as HTMLElement;
this.buffered = document.getElementById("buffered") as HTMLElement; this.buffered = document.getElementById("buffered") as HTMLElement;
this.player.controls = false;
this.player.onplay = () =>
{
this.initPlayBtn();
};
this.player.onpause = () =>
{
this.playIcon = "play_arrow";
this.playTooltip = "Play";
};
this.player.ontimeupdate = () => this.player.ontimeupdate = () =>
{ {
@ -139,16 +139,11 @@ export class PlayerComponent implements OnInit
loadIndicator.classList.add("d-none"); loadIndicator.classList.add("d-none");
}; };
this.player.onended = () =>
{
this.next();
};
this.player.onerror = () => this.player.onerror = () =>
{ {
if (this.playMethod == method.transcode) if (this.playMethod == method.transcode)
{ {
this.snackBar.open("This episode can't be played.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 10000 }); this.snackBar.open("This episode can't be played.", null, { horizontalPosition: "left", panelClass: ["snackError"], duration: 10000 });
} }
else else
{ {
@ -277,20 +272,6 @@ export class PlayerComponent implements OnInit
if (document.fullscreenElement == null && this.router.url.startsWith("/watch")) if (document.fullscreenElement == null && this.router.url.startsWith("/watch"))
this.back(); this.back();
} }
else
{
if (document.fullscreenElement != null)
{
this.fullscreenIcon = "fullscreen_exit";
this.fullscreenTooltip = "Exit fullscreen";
}
else
{
this.fullscreenIcon = "fullscreen";
this.fullscreenTooltip = "Fullscreen";
}
}
}); });
$(window).keydown((e) => $(window).keydown((e) =>
@ -298,15 +279,15 @@ export class PlayerComponent implements OnInit
switch (e.keyCode) switch (e.keyCode)
{ {
case 32: //space case 32: //space
this.tooglePlayback(); this.togglePlayback();
break; break;
case 38: //Key up case 38: //Key up
this.changeVolume(this.volume + 5); this.volume += 5;
this.snackBar.open(this.volume + "%", null, { verticalPosition: "top", horizontalPosition: "right", duration: 300, panelClass: "volume" }); this.snackBar.open(this.volume + "%", null, { verticalPosition: "top", horizontalPosition: "right", duration: 300, panelClass: "volume" });
break; break;
case 40: //Key down case 40: //Key down
this.changeVolume(this.volume - 5); this.volume += 5;
this.snackBar.open(this.volume + "%", null, { verticalPosition: "top", horizontalPosition: "right", duration: 300, panelClass: "volume" }); this.snackBar.open(this.volume + "%", null, { verticalPosition: "top", horizontalPosition: "right", duration: 300, panelClass: "volume" });
break; break;
@ -326,7 +307,7 @@ export class PlayerComponent implements OnInit
break; break;
case 77: //M key case 77: //M key
this.toogleMute(); this.muted = !this.muted;
if (this.player.muted) if (this.player.muted)
this.snackBar.open("Sound muted.", null, { verticalPosition: "top", horizontalPosition: "right", duration: 750, panelClass: "info-panel" }); this.snackBar.open("Sound muted.", null, { verticalPosition: "top", horizontalPosition: "right", duration: 750, panelClass: "info-panel" });
else else
@ -351,16 +332,12 @@ export class PlayerComponent implements OnInit
switch (true) switch (true)
{ {
case event instanceof NavigationStart: case event instanceof NavigationStart:
{ loadIndicator.classList.remove("d-none");
loadIndicator.classList.remove("d-none"); break;
break;
}
case event instanceof NavigationEnd: case event instanceof NavigationEnd:
case event instanceof NavigationCancel: case event instanceof NavigationCancel:
{ loadIndicator.classList.add("d-none");
loadIndicator.classList.add("d-none"); break;
break;
}
default: default:
break; break;
} }
@ -395,7 +372,12 @@ export class PlayerComponent implements OnInit
setTimeout(() => setTimeout(() =>
{ {
this.snackBar.open("Playing: " + this.item.showTitle + " S" + this.item.seasonNumber + ":E" + this.item.episodeNumber, null, { verticalPosition: "top", horizontalPosition: "right", duration: 2000, panelClass: "info-panel" }); this.snackBar.open(`Playing: ${this.item.showTitle} S${this.item.seasonNumber}:E${this.item.episodeNumber}`, null, {
verticalPosition: "top",
horizontalPosition: "right",
duration: 2000,
panelClass: "info-panel"
});
}, 750); }, 750);
} }
@ -405,7 +387,7 @@ export class PlayerComponent implements OnInit
if (this.oidcSecurity === undefined) if (this.oidcSecurity === undefined)
this.oidcSecurity = this.injector.get(OidcSecurityService); this.oidcSecurity = this.injector.get(OidcSecurityService);
this.hlsPlayer.config.xhrSetup = (xhr, url) => this.hlsPlayer.config.xhrSetup = xhr =>
{ {
const token = this.oidcSecurity.getToken(); const token = this.oidcSecurity.getToken();
if (token) if (token)
@ -413,9 +395,7 @@ export class PlayerComponent implements OnInit
}; };
if (this.playMethod == method.direct) if (this.playMethod == method.direct)
{ this.player.src = `/video/${this.item.slug}`;
this.player.src = "/video/" + this.item.slug;
}
else if (this.playMethod == method.transmux) else if (this.playMethod == method.transmux)
{ {
this.hlsPlayer.loadSource("/video/transmux/" + this.item.slug + "/"); this.hlsPlayer.loadSource("/video/transmux/" + this.item.slug + "/");
@ -438,19 +418,25 @@ export class PlayerComponent implements OnInit
back() back()
{ {
this.location.back(); this.router.navigate(["/show", this.item.showSlug]);
} }
next() next()
{ {
if (this.item.nextEpisode != null) if (this.item.nextEpisode == null)
this.router.navigate(["/watch/" + this.item.nextEpisode.slug], { queryParamsHandling: "merge", replaceUrl: true }); return;
this.router.navigate(["/watch", this.item.nextEpisode.slug], {
queryParamsHandling: "merge"
});
} }
previous() previous()
{ {
if (this.item.previousEpisode != null) if (this.item.previousEpisode == null)
this.router.navigate(["/watch/" + this.item.previousEpisode], { queryParamsHandling: "merge", replaceUrl: true }); return;
this.router.navigate(["/watch", this.item.previousEpisode], {
queryParamsHandling: "merge"
});
} }
getTimeFromSeekbar(progressBar: HTMLElement, pageX: number) getTimeFromSeekbar(progressBar: HTMLElement, pageX: number)
@ -492,7 +478,7 @@ export class PlayerComponent implements OnInit
videoClicked() videoClicked()
{ {
if (!navigator.userAgent.match(/Mobi/)) if (!navigator.userAgent.match(/Mobi/))
this.tooglePlayback(); this.togglePlayback();
else else
{ {
if ($("#hover").hasClass("idle")) if ($("#hover").hasClass("idle"))
@ -515,7 +501,7 @@ export class PlayerComponent implements OnInit
} }
} }
tooglePlayback() togglePlayback()
{ {
if (this.player.paused) if (this.player.paused)
this.player.play(); this.player.play();
@ -523,22 +509,6 @@ export class PlayerComponent implements OnInit
this.player.pause(); this.player.pause();
} }
toogleMute()
{
if (this.player.muted)
this.player.muted = false;
else
this.player.muted = true;
this.updateVolumeBtn()
}
initPlayBtn()
{
this.playIcon = "pause";
this.playTooltip = "Pause";
}
fullscreen() fullscreen()
{ {
if (document.fullscreenElement == null) if (document.fullscreenElement == null)
@ -547,35 +517,16 @@ export class PlayerComponent implements OnInit
document.exitFullscreen(); document.exitFullscreen();
} }
//Value from 0 to 100 getVolumeBtn(): string
changeVolume(value: number)
{ {
value = Math.max(0, Math.min(value, 100)); if (this.volume == 0 || this.muted)
return "volume_off";
this.player.muted = false; else if (this.volume < 25)
this.player.volume = value / 100; return "volume_mute";
this.volume = value; else if (this.volume < 65)
return "volume_down";
this.updateVolumeBtn();
}
updateVolumeBtn()
{
if (this.player.muted)
{
this.volumeIcon = "volume_off"
}
else else
{ return "volume_up";
if (this.volume == 0)
this.volumeIcon = "volume_off";
else if (this.volume < 25)
this.volumeIcon = "volume_mute";
else if (this.volume < 65)
this.volumeIcon = "volume_down";
else
this.volumeIcon = "volume_up";
}
} }
selectSubtitle(subtitle: Track, changeUrl: boolean = true) selectSubtitle(subtitle: Track, changeUrl: boolean = true)
@ -590,25 +541,39 @@ export class PlayerComponent implements OnInit
subSlug += "-for"; subSlug += "-for";
} }
this.router.navigate([], { relativeTo: this.route, queryParams: { sub: subSlug }, replaceUrl: true, queryParamsHandling: "merge" }); this.router.navigate([], {
relativeTo: this.route,
queryParams: {sub: subSlug},
replaceUrl: true,
queryParamsHandling: "merge"
});
} }
this.selectedSubtitle = subtitle; this.selectedSubtitle = subtitle;
if (subtitle == null) if (subtitle == null)
{ {
this.snackBar.open("Subtitle removed.", null, { verticalPosition: "top", horizontalPosition: "right", duration: 750, panelClass: "info-panel" }); this.snackBar.open("Subtitle removed.", null, {
verticalPosition: "top",
horizontalPosition: "right",
duration: 750,
panelClass: "info-panel"
});
SubtitleManager.remove(this.player); SubtitleManager.remove(this.player);
this.removeHtmlTrack(); this.removeHtmlTrack();
} }
else else
{ {
this.snackBar.open(subtitle.displayName + " subtitle loaded.", null, { verticalPosition: "top", horizontalPosition: "right", duration: 750, panelClass: "info-panel" }); this.snackBar.open(`${subtitle.displayName} subtitle loaded.`, null, {
verticalPosition: "top",
horizontalPosition: "right",
duration: 750,
panelClass: "info-panel"
});
this.removeHtmlTrack(); this.removeHtmlTrack();
if (subtitle.codec == "ass") if (subtitle.codec == "ass")
SubtitleManager.add(this.player, `subtitle/${subtitle.slug}`, true); SubtitleManager.add(this.player, `subtitle/${subtitle.slug}`, true);
else if (subtitle.codec == "subrip") else if (subtitle.codec == "subrip")
{ {
SubtitleManager.remove(this.player); SubtitleManager.remove(this.player);