mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-09 03:04:20 -04:00
Replacing spaces with tabs
This commit is contained in:
parent
03bf97dab6
commit
a19bf9bce8
@ -1,35 +1,35 @@
|
|||||||
<header id="nav" style="height: 68px;">
|
<header id="nav" style="height: 68px;">
|
||||||
<div class="fixed-top">
|
<div class="fixed-top">
|
||||||
<nav id="toolbar" class="navbar navbar-dark bg-secondary">
|
<nav id="toolbar" class="navbar navbar-dark bg-secondary">
|
||||||
<a class="navbar-brand nav-item ml-3" routerLink="/">
|
<a class="navbar-brand nav-item ml-3" routerLink="/">
|
||||||
Kyoo
|
Kyoo
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<ul class="navbar-nav flex-row">
|
<ul class="navbar-nav flex-row">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" routerLink="/browse" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }">All</a>
|
<a class="nav-link" routerLink="/browse" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }">All</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item" *ngFor="let library of this.libraries">
|
<li class="nav-item" *ngFor="let library of this.libraries">
|
||||||
<a class="nav-link" routerLink="/browse/{{library.slug}}" routerLinkActive="active">{{library.name}}</a>
|
<a class="nav-link" routerLink="/browse/{{library.slug}}" routerLinkActive="active">{{library.name}}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<ul class="navbar-nav flex-row ml-auto">
|
<ul class="navbar-nav flex-row ml-auto">
|
||||||
<li class="nav-item icon searchbar">
|
<li class="nav-item icon searchbar">
|
||||||
<input placeholder="Search" id="search" type="search" (input)="onUpdateValue($event)"/>
|
<input placeholder="Search" id="search" type="search" (input)="onUpdateValue($event)"/>
|
||||||
<mat-icon matTooltipPosition="below" matTooltip="Search" (click)="openSearch()">search</mat-icon>
|
<mat-icon matTooltipPosition="below" matTooltip="Search" (click)="openSearch()">search</mat-icon>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="icon" routerLink="/login" routerLinkActive="active" matTooltipPosition="below" matTooltip="Login">
|
<a class="icon" routerLink="/login" routerLinkActive="active" matTooltipPosition="below" matTooltip="Login">
|
||||||
<mat-icon>account_circle</mat-icon>
|
<mat-icon>account_circle</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
<mat-progress-bar *ngIf="this.isLoading" color="accent" mode="indeterminate"> </mat-progress-bar>
|
<mat-progress-bar *ngIf="this.isLoading" color="accent" mode="indeterminate"> </mat-progress-bar>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main >
|
<main >
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
</main>
|
</main>
|
||||||
|
@ -4,83 +4,83 @@
|
|||||||
|
|
||||||
.navbar
|
.navbar
|
||||||
{
|
{
|
||||||
justify-content: left;
|
justify-content: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-item
|
.nav-item
|
||||||
{
|
{
|
||||||
outline: none;
|
outline: none;
|
||||||
|
|
||||||
> a
|
> a
|
||||||
{
|
{
|
||||||
outline: none;
|
outline: none;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-link
|
.nav-link
|
||||||
{
|
{
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
color: rgba(255, 255, 255, 0.7) !important;
|
color: rgba(255, 255, 255, 0.7) !important;
|
||||||
|
|
||||||
&:host-context(.hoverEnabled) &:hover
|
&:host-context(.hoverEnabled) &:hover
|
||||||
{
|
{
|
||||||
color: white !important;
|
color: white !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.active
|
&.active
|
||||||
{
|
{
|
||||||
color: var(--accentColor) !important;
|
color: var(--accentColor) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar-brand:hover
|
.navbar-brand:hover
|
||||||
{
|
{
|
||||||
color: var(--accentColor);
|
color: var(--accentColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
.searchbar
|
.searchbar
|
||||||
{
|
{
|
||||||
border-radius: 30px;
|
border-radius: 30px;
|
||||||
|
|
||||||
> input
|
> input
|
||||||
{
|
{
|
||||||
background: none !important;
|
background: none !important;
|
||||||
color: white;
|
color: white;
|
||||||
outline: none;
|
outline: none;
|
||||||
border: none;
|
border: none;
|
||||||
border-bottom: 1px solid #cfcfcf;
|
border-bottom: 1px solid #cfcfcf;
|
||||||
width: 0;
|
width: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
transition: width 0.4s ease-in-out;
|
transition: width 0.4s ease-in-out;
|
||||||
|
|
||||||
&:focus, &.searching
|
&:focus, &.searching
|
||||||
{
|
{
|
||||||
width: 12rem;
|
width: 12rem;
|
||||||
|
|
||||||
@include media-breakpoint-up(sm)
|
@include media-breakpoint-up(sm)
|
||||||
{
|
{
|
||||||
width: 20rem;
|
width: 20rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input::-webkit-search-cancel-button
|
input::-webkit-search-cancel-button
|
||||||
{
|
{
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.icon
|
.icon
|
||||||
{
|
{
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
|
|
||||||
&:host-context(.hoverEnabled) &:hover
|
&:host-context(.hoverEnabled) &:hover
|
||||||
{
|
{
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,35 +26,35 @@ import { ShowsListComponent } from './shows-list/shows-list.component';
|
|||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
NotFoundComponent,
|
NotFoundComponent,
|
||||||
BrowseComponent,
|
BrowseComponent,
|
||||||
ShowDetailsComponent,
|
ShowDetailsComponent,
|
||||||
EpisodesListComponent,
|
EpisodesListComponent,
|
||||||
PlayerComponent,
|
PlayerComponent,
|
||||||
CollectionComponent,
|
CollectionComponent,
|
||||||
SearchComponent,
|
SearchComponent,
|
||||||
PeopleListComponent,
|
PeopleListComponent,
|
||||||
ShowsListComponent
|
ShowsListComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
HttpClientModule,
|
HttpClientModule,
|
||||||
AppRoutingModule,
|
AppRoutingModule,
|
||||||
BrowserAnimationsModule,
|
BrowserAnimationsModule,
|
||||||
MatSnackBarModule,
|
MatSnackBarModule,
|
||||||
MatProgressBarModule,
|
MatProgressBarModule,
|
||||||
MatButtonModule,
|
MatButtonModule,
|
||||||
MatIconModule,
|
MatIconModule,
|
||||||
MatSelectModule,
|
MatSelectModule,
|
||||||
MatMenuModule,
|
MatMenuModule,
|
||||||
MatSliderModule,
|
MatSliderModule,
|
||||||
MatTooltipModule,
|
MatTooltipModule,
|
||||||
MatRippleModule,
|
MatRippleModule,
|
||||||
MatCardModule
|
MatCardModule
|
||||||
],
|
],
|
||||||
providers: [],
|
providers: [],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
export class AppModule { }
|
export class AppModule { }
|
||||||
|
@ -1,30 +1,30 @@
|
|||||||
<div class="container-fluid justify-content-center">
|
<div class="container-fluid justify-content-center">
|
||||||
<button mat-icon-button matTooltipPosition="below" matTooltip="Filter">
|
<button mat-icon-button matTooltipPosition="below" matTooltip="Filter">
|
||||||
<mat-icon>filter_list</mat-icon>
|
<mat-icon>filter_list</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button mat-button matTooltipPosition="below" matTooltip="Sort" [matMenuTriggerFor]="sortMenu">
|
<button mat-button matTooltipPosition="below" matTooltip="Sort" [matMenuTriggerFor]="sortMenu">
|
||||||
<mat-icon>sort</mat-icon> Sort by {{this.sortType}} <i *ngIf="this.sortUp" class="material-icons arrow">arrow_upward</i><i *ngIf="!this.sortUp" class="material-icons arrow">arrow_downward</i>
|
<mat-icon>sort</mat-icon> Sort by {{this.sortType}} <i *ngIf="this.sortUp" class="material-icons arrow">arrow_upward</i><i *ngIf="!this.sortUp" class="material-icons arrow">arrow_downward</i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<mat-menu #sortMenu="matMenu">
|
<mat-menu #sortMenu="matMenu">
|
||||||
<div *ngFor="let type of this.sortTypes">
|
<div *ngFor="let type of this.sortTypes">
|
||||||
<button *ngIf="type != this.sortType; else elseBlock;" mat-menu-item (click)="sort(type, true)">
|
<button *ngIf="type != this.sortType; else elseBlock;" mat-menu-item (click)="sort(type, true)">
|
||||||
Sort by {{type}}
|
Sort by {{type}}
|
||||||
</button>
|
</button>
|
||||||
<ng-template #elseBlock>
|
<ng-template #elseBlock>
|
||||||
<button mat-menu-item (click)="sort(type, !this.sortUp)">
|
<button mat-menu-item (click)="sort(type, !this.sortUp)">
|
||||||
Sort by {{type}} <i *ngIf="!this.sortUp" class="material-icons arrow">arrow_upward</i><i *ngIf="this.sortUp" class="material-icons arrow">arrow_downward</i>
|
Sort by {{type}} <i *ngIf="!this.sortUp" class="material-icons arrow">arrow_upward</i><i *ngIf="this.sortUp" class="material-icons arrow">arrow_downward</i>
|
||||||
</button>
|
</button>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</div>
|
</div>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
|
|
||||||
<div class="container-fluid justify-content-center">
|
<div class="container-fluid justify-content-center">
|
||||||
<a class="show" *ngFor="let show of this.shows" [href]="getLink(show)" [routerLink]="getLink(show)">
|
<a class="show" *ngFor="let show of this.shows" [href]="getLink(show)" [routerLink]="getLink(show)">
|
||||||
<div matRipple [style.background-image]="getThumb(show.slug)" > </div>
|
<div matRipple [style.background-image]="getThumb(show.slug)" > </div>
|
||||||
<p class="title">{{show.title}}</p>
|
<p class="title">{{show.title}}</p>
|
||||||
<p class="date" *ngIf="show.endYear; else elseBlock">{{show.startYear}} - {{show.endYear}}</p>
|
<p class="date" *ngIf="show.endYear; else elseBlock">{{show.startYear}} - {{show.endYear}}</p>
|
||||||
<ng-template #elseBlock><p class="date">{{show.startYear}}</p></ng-template>
|
<ng-template #elseBlock><p class="date">{{show.startYear}}</p></ng-template>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,93 +4,93 @@
|
|||||||
|
|
||||||
button
|
button
|
||||||
{
|
{
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.arrow
|
.arrow
|
||||||
{
|
{
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container-fluid
|
.container-fluid
|
||||||
{
|
{
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.show
|
.show
|
||||||
{
|
{
|
||||||
width: 33%;
|
width: 33%;
|
||||||
min-width: 120px;
|
min-width: 120px;
|
||||||
max-width: 200px;
|
max-width: 200px;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
padding: .5em;
|
padding: .5em;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
|
||||||
@include media-breakpoint-up(sm)
|
@include media-breakpoint-up(sm)
|
||||||
{
|
{
|
||||||
width: 25%;
|
width: 25%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include media-breakpoint-up(md)
|
@include media-breakpoint-up(md)
|
||||||
{
|
{
|
||||||
width: 20%;
|
width: 20%;
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include media-breakpoint-up(lg)
|
@include media-breakpoint-up(lg)
|
||||||
{
|
{
|
||||||
width: 18%;
|
width: 18%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include media-breakpoint-up(xl)
|
@include media-breakpoint-up(xl)
|
||||||
{
|
{
|
||||||
width: 15%;
|
width: 15%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
&:focus, &:hover
|
&:focus, &:hover
|
||||||
{
|
{
|
||||||
> div
|
> div
|
||||||
{
|
{
|
||||||
outline: solid var(--accentColor);
|
outline: solid var(--accentColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
> .title
|
> .title
|
||||||
{
|
{
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> div
|
> div
|
||||||
{
|
{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 0;
|
height: 0;
|
||||||
padding-top: 147.0588%;
|
padding-top: 147.0588%;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-color: #333333;
|
background-color: #333333;
|
||||||
}
|
}
|
||||||
|
|
||||||
> p
|
> p
|
||||||
{
|
{
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
|
||||||
&.date
|
&.date
|
||||||
{
|
{
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:host-context(.hoverEnabled) &:hover
|
&:host-context(.hoverEnabled) &:hover
|
||||||
{
|
{
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,17 +4,17 @@ import { DomSanitizer } from '@angular/platform-browser';
|
|||||||
import { Show } from "../../models/show";
|
import { Show } from "../../models/show";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-browse',
|
selector: 'app-browse',
|
||||||
templateUrl: './browse.component.html',
|
templateUrl: './browse.component.html',
|
||||||
styleUrls: ['./browse.component.scss']
|
styleUrls: ['./browse.component.scss']
|
||||||
})
|
})
|
||||||
export class BrowseComponent
|
export class BrowseComponent
|
||||||
{
|
{
|
||||||
@Input() shows: Show[];
|
@Input() shows: Show[];
|
||||||
sortType: string = "title";
|
sortType: string = "title";
|
||||||
sortUp: boolean = true;
|
sortUp: boolean = true;
|
||||||
|
|
||||||
sortTypes: string[] = ["title", "release date"];
|
sortTypes: string[] = ["title", "release date"];
|
||||||
|
|
||||||
constructor(private route: ActivatedRoute, private sanitizer: DomSanitizer)
|
constructor(private route: ActivatedRoute, private sanitizer: DomSanitizer)
|
||||||
{
|
{
|
||||||
@ -24,37 +24,37 @@ export class BrowseComponent
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getThumb(slug: string)
|
getThumb(slug: string)
|
||||||
{
|
{
|
||||||
return this.sanitizer.bypassSecurityTrustStyle("url(/poster/" + slug + ")");
|
return this.sanitizer.bypassSecurityTrustStyle("url(/poster/" + slug + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
getLink(show: Show)
|
getLink(show: Show)
|
||||||
{
|
{
|
||||||
if (show.isCollection)
|
if (show.isCollection)
|
||||||
return "/collection/" + show.slug;
|
return "/collection/" + show.slug;
|
||||||
else
|
else
|
||||||
return "/show/" + show.slug;
|
return "/show/" + show.slug;
|
||||||
}
|
}
|
||||||
|
|
||||||
sort(type: string, order: boolean)
|
sort(type: string, order: boolean)
|
||||||
{
|
{
|
||||||
this.sortType = type;
|
this.sortType = type;
|
||||||
this.sortUp = order;
|
this.sortUp = order;
|
||||||
|
|
||||||
if (type == this.sortTypes[0])
|
if (type == this.sortTypes[0])
|
||||||
{
|
{
|
||||||
if (order)
|
if (order)
|
||||||
this.shows.sort((a, b) => { if (a.title < b.title) return -1; else if (a.title > b.title) return 1; return 0; });
|
this.shows.sort((a, b) => { if (a.title < b.title) return -1; else if (a.title > b.title) return 1; return 0; });
|
||||||
else
|
else
|
||||||
this.shows.sort((a, b) => { if (a.title < b.title) return 1; else if (a.title > b.title) return -1; return 0; });
|
this.shows.sort((a, b) => { if (a.title < b.title) return 1; else if (a.title > b.title) return -1; return 0; });
|
||||||
}
|
}
|
||||||
else if (type == this.sortTypes[1])
|
else if (type == this.sortTypes[1])
|
||||||
{
|
{
|
||||||
if (order)
|
if (order)
|
||||||
this.shows.sort((a, b) => a.startYear - b.startYear);
|
this.shows.sort((a, b) => a.startYear - b.startYear);
|
||||||
else
|
else
|
||||||
this.shows.sort((a, b) => b.startYear - a.startYear);
|
this.shows.sort((a, b) => b.startYear - a.startYear);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-md-4 col-lg-3 col-xl-2 collection-info">
|
<div class="col-md-4 col-lg-3 col-xl-2 collection-info">
|
||||||
<div [style.background-image]="getThumb()"></div>
|
<div [style.background-image]="getThumb()"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-8 col-lg-9 col-xl-10">
|
<div class="col-md-8 col-lg-9 col-xl-10">
|
||||||
<h3 class="text-center text-md-left p-2 p-md-3">{{collection.name}}</h3>
|
<h3 class="text-center text-md-left p-2 p-md-3">{{collection.name}}</h3>
|
||||||
<h5 class="date" *ngIf="collection.endYear; else elseBlock">{{collection.startYear}} - {{collection.endYear}}</h5>
|
<h5 class="date" *ngIf="collection.endYear; else elseBlock">{{collection.startYear}} - {{collection.endYear}}</h5>
|
||||||
<ng-template #elseBlock><h5 class="date">{{collection.startYear}}</h5></ng-template>
|
<ng-template #elseBlock><h5 class="date">{{collection.startYear}}</h5></ng-template>
|
||||||
<hr />
|
<hr />
|
||||||
<app-browse [shows]="collection.shows"></app-browse>
|
<app-browse [shows]="collection.shows"></app-browse>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
.collection-info
|
.collection-info
|
||||||
{
|
{
|
||||||
width: 60%;
|
width: 60%;
|
||||||
|
|
||||||
> div
|
> div
|
||||||
{
|
{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 0;
|
height: 0;
|
||||||
padding-top: 147.0588%;
|
padding-top: 147.0588%;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-color: #333333;
|
background-color: #333333;
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hr
|
hr
|
||||||
{
|
{
|
||||||
margin: 10px 0 10px 0;
|
margin: 10px 0 10px 0;
|
||||||
border-top: 1px solid rgba(255, 255, 255, .60);
|
border-top: 1px solid rgba(255, 255, 255, .60);
|
||||||
border-left: 0;
|
border-left: 0;
|
||||||
width: inherit;
|
width: inherit;
|
||||||
height: 2px;
|
height: 2px;
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,13 @@ import { ActivatedRoute } from "@angular/router";
|
|||||||
import { DomSanitizer } from "@angular/platform-browser";
|
import { DomSanitizer } from "@angular/platform-browser";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-collection',
|
selector: 'app-collection',
|
||||||
templateUrl: './collection.component.html',
|
templateUrl: './collection.component.html',
|
||||||
styleUrls: ['./collection.component.scss']
|
styleUrls: ['./collection.component.scss']
|
||||||
})
|
})
|
||||||
export class CollectionComponent
|
export class CollectionComponent
|
||||||
{
|
{
|
||||||
collection: Collection;
|
collection: Collection;
|
||||||
|
|
||||||
constructor(private route: ActivatedRoute, private sanitizer: DomSanitizer)
|
constructor(private route: ActivatedRoute, private sanitizer: DomSanitizer)
|
||||||
{
|
{
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
<div class="root">
|
<div class="root">
|
||||||
<div class="episodes" #scrollView (scroll)="onScroll()">
|
<div class="episodes" #scrollView (scroll)="onScroll()">
|
||||||
<a class="episode" *ngFor="let episode of this.episodes" #episodeDom routerLink="/watch/{{episode.link}}" href="/watch/{{episode.link}}">
|
<a class="episode" *ngFor="let episode of this.episodes" #episodeDom routerLink="/watch/{{episode.link}}" href="/watch/{{episode.link}}">
|
||||||
<div matRipple class="img" [style.background-image]="sanitize(episode.thumb)">
|
<div matRipple class="img" [style.background-image]="sanitize(episode.thumb)">
|
||||||
<button mat-icon-button class="playBtn"><i class="material-icons playIcon">play_circle_outline</i></button>
|
<button mat-icon-button class="playBtn"><i class="material-icons playIcon">play_circle_outline</i></button>
|
||||||
</div>
|
</div>
|
||||||
<ng-container *ngIf="displayShowTitle; else noTitle;">
|
<ng-container *ngIf="displayShowTitle; else noTitle;">
|
||||||
<h6 *ngIf="episode.seasonNumber != 0; else elseBlock;" class="title">{{episode.showTitle}} - S{{episode.seasonNumber}}:E{{episode.episodeNumber}}</h6>
|
<h6 *ngIf="episode.seasonNumber != 0; else elseBlock;" class="title">{{episode.showTitle}} - S{{episode.seasonNumber}}:E{{episode.episodeNumber}}</h6>
|
||||||
<ng-template #elseBlock><h6 class="title">{{episode.showTitle}}</h6></ng-template>
|
<ng-template #elseBlock><h6 class="title">{{episode.showTitle}}</h6></ng-template>
|
||||||
<p class="subtitle">{{episode.title}}</p>
|
<p class="subtitle">{{episode.title}}</p>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-template #noTitle>
|
<ng-template #noTitle>
|
||||||
<h6 *ngIf="episode.seasonNumber != 0; else elseBlock;" class="title">S{{episode.seasonNumber}}:E{{episode.episodeNumber}} - {{episode.title}}</h6>
|
<h6 *ngIf="episode.seasonNumber != 0; else elseBlock;" class="title">S{{episode.seasonNumber}}:E{{episode.episodeNumber}} - {{episode.title}}</h6>
|
||||||
<ng-template #elseBlock><h6 class="title">{{episode.title}}</h6></ng-template>
|
<ng-template #elseBlock><h6 class="title">{{episode.title}}</h6></ng-template>
|
||||||
<p class="overview">{{episode.overview}}</p>
|
<p class="overview">{{episode.overview}}</p>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<button mat-raised-button color="accent" class="scrollBtn leftBtn d-none" #leftBtn (click)="scrollLeft()"><mat-icon>arrow_left</mat-icon></button>
|
<button mat-raised-button color="accent" class="scrollBtn leftBtn d-none" #leftBtn (click)="scrollLeft()"><mat-icon>arrow_left</mat-icon></button>
|
||||||
<button mat-raised-button color="accent" class="scrollBtn rightBtn" #rightBtn (click)="scrollRight()"><mat-icon>arrow_right</mat-icon></button>
|
<button mat-raised-button color="accent" class="scrollBtn rightBtn" #rightBtn (click)="scrollRight()"><mat-icon>arrow_right</mat-icon></button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,179 +4,179 @@
|
|||||||
|
|
||||||
.root
|
.root
|
||||||
{
|
{
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
&:host-context(.hoverEnabled) &:hover
|
&:host-context(.hoverEnabled) &:hover
|
||||||
{
|
{
|
||||||
.scrollBtn
|
.scrollBtn
|
||||||
{
|
{
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.episodes
|
.episodes
|
||||||
{
|
{
|
||||||
display: flex;
|
display: flex;
|
||||||
padding-left: 15px;
|
padding-left: 15px;
|
||||||
padding-right: 15px;
|
padding-right: 15px;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
scrollbar-width: thin;
|
scrollbar-width: thin;
|
||||||
scrollbar-color: #999 transparent;
|
scrollbar-color: #999 transparent;
|
||||||
|
|
||||||
&::-webkit-scrollbar
|
&::-webkit-scrollbar
|
||||||
{
|
{
|
||||||
height: 4px;
|
height: 4px;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-scrollbar-thumb
|
&::-webkit-scrollbar-thumb
|
||||||
{
|
{
|
||||||
background-color: #999;
|
background-color: #999;
|
||||||
border-radius: 90px;
|
border-radius: 90px;
|
||||||
|
|
||||||
&:host-context(.hoverEnabled) &:hover
|
&:host-context(.hoverEnabled) &:hover
|
||||||
{
|
{
|
||||||
background-color: rgb(134, 127, 127);
|
background-color: rgb(134, 127, 127);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.episode
|
.episode
|
||||||
{
|
{
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: .25rem;
|
padding: .25rem;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
width: 55%;
|
width: 55%;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
text-decoration: inherit;
|
text-decoration: inherit;
|
||||||
|
|
||||||
@include media-breakpoint-up(sm)
|
@include media-breakpoint-up(sm)
|
||||||
{
|
{
|
||||||
width: 40%;
|
width: 40%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include media-breakpoint-up(md)
|
@include media-breakpoint-up(md)
|
||||||
{
|
{
|
||||||
width: 33%;
|
width: 33%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include media-breakpoint-up(lg)
|
@include media-breakpoint-up(lg)
|
||||||
{
|
{
|
||||||
width: 28%;
|
width: 28%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include media-breakpoint-up(xl)
|
@include media-breakpoint-up(xl)
|
||||||
{
|
{
|
||||||
width: 18%;
|
width: 18%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.img
|
.img
|
||||||
{
|
{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 0;
|
height: 0;
|
||||||
padding-top: 56.25%;
|
padding-top: 56.25%;
|
||||||
background-color: #333333;
|
background-color: #333333;
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
> button
|
> button
|
||||||
{
|
{
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
width: 64px;
|
width: 64px;
|
||||||
height: 64px;
|
height: 64px;
|
||||||
outline: none;
|
outline: none;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.title
|
.title
|
||||||
{
|
{
|
||||||
padding-top: .2rem;
|
padding-top: .2rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
-webkit-line-clamp: 1;
|
-webkit-line-clamp: 1;
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.overview
|
.overview
|
||||||
{
|
{
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
-webkit-line-clamp: 4;
|
-webkit-line-clamp: 4;
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.subtitle
|
.subtitle
|
||||||
{
|
{
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
-webkit-line-clamp: 1;
|
-webkit-line-clamp: 1;
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:host-context(.hoverEnabled) &:hover
|
&:host-context(.hoverEnabled) &:hover
|
||||||
{
|
{
|
||||||
.img
|
.img
|
||||||
{
|
{
|
||||||
outline: solid var(--accentColor);
|
outline: solid var(--accentColor);
|
||||||
|
|
||||||
.playBtn
|
.playBtn
|
||||||
{
|
{
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.title
|
.title
|
||||||
{
|
{
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.playIcon
|
.playIcon
|
||||||
{
|
{
|
||||||
font-size: 64px;
|
font-size: 64px;
|
||||||
width: 64px;
|
width: 64px;
|
||||||
height: 64px;
|
height: 64px;
|
||||||
line-height: 64px;
|
line-height: 64px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.scrollBtn
|
.scrollBtn
|
||||||
{
|
{
|
||||||
padding: 0;
|
padding: 0;
|
||||||
outline: none;
|
outline: none;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 20%;
|
top: 20%;
|
||||||
bottom: 60%;
|
bottom: 60%;
|
||||||
display: none;
|
display: none;
|
||||||
|
|
||||||
&.leftBtn
|
&.leftBtn
|
||||||
{
|
{
|
||||||
left: 0;
|
left: 0;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
padding-right: 2px;
|
padding-right: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.rightBtn
|
&.rightBtn
|
||||||
{
|
{
|
||||||
right: 0;
|
right: 0;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
padding-left: 2px;
|
padding-left: 2px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,14 @@ import { DomSanitizer } from "@angular/platform-browser";
|
|||||||
import { Episode } from "../../models/episode";
|
import { Episode } from "../../models/episode";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-episodes-list',
|
selector: 'app-episodes-list',
|
||||||
templateUrl: './episodes-list.component.html',
|
templateUrl: './episodes-list.component.html',
|
||||||
styleUrls: ['./episodes-list.component.scss']
|
styleUrls: ['./episodes-list.component.scss']
|
||||||
})
|
})
|
||||||
export class EpisodesListComponent
|
export class EpisodesListComponent
|
||||||
{
|
{
|
||||||
@Input() displayShowTitle: boolean = false;
|
@Input() displayShowTitle: boolean = false;
|
||||||
@Input() episodes: Episode[];
|
@Input() episodes: Episode[];
|
||||||
@ViewChild("scrollView", { static: true }) private scrollView: ElementRef;
|
@ViewChild("scrollView", { static: true }) private scrollView: ElementRef;
|
||||||
@ViewChild("leftBtn", { static: false }) private leftBtn: MatButton;
|
@ViewChild("leftBtn", { static: false }) private leftBtn: MatButton;
|
||||||
@ViewChild("rightBtn", { static: false }) private rightBtn: MatButton;
|
@ViewChild("rightBtn", { static: false }) private rightBtn: MatButton;
|
||||||
@ -53,8 +53,8 @@ export class EpisodesListComponent
|
|||||||
this.rightBtn._elementRef.nativeElement.classList.remove("d-none");
|
this.rightBtn._elementRef.nativeElement.classList.remove("d-none");
|
||||||
}
|
}
|
||||||
|
|
||||||
sanitize(url: string)
|
sanitize(url: string)
|
||||||
{
|
{
|
||||||
return this.sanitizer.bypassSecurityTrustStyle("url(" + url + ")");
|
return this.sanitizer.bypassSecurityTrustStyle("url(" + url + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,6 @@
|
|||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<h1>404 Error</h1>
|
<h1>404 Error</h1>
|
||||||
<p>The page you requested was not found.</p>
|
<p>The page you requested was not found.</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-not-found',
|
selector: 'app-not-found',
|
||||||
templateUrl: './not-found.component.html',
|
templateUrl: './not-found.component.html',
|
||||||
styleUrls: ['./not-found.component.scss']
|
styleUrls: ['./not-found.component.scss']
|
||||||
})
|
})
|
||||||
export class NotFoundComponent implements OnInit {
|
export class NotFoundComponent implements OnInit {
|
||||||
|
|
||||||
constructor() { }
|
constructor() { }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
<div class="scroll-row mb-5">
|
<div class="scroll-row mb-5">
|
||||||
<div class="people-container" #scrollView (scroll)="onScroll()">
|
<div class="people-container" #scrollView (scroll)="onScroll()">
|
||||||
<a class="people" *ngFor="let people of this.people" routerLink="/people/{{people.slug}}" href="/people/{{people.slug}}">
|
<a class="people" *ngFor="let people of this.people" routerLink="/people/{{people.slug}}" href="/people/{{people.slug}}">
|
||||||
<div matRipple [style.background-image]="getPeopleIcon(people.slug)"> </div>
|
<div matRipple [style.background-image]="getPeopleIcon(people.slug)"> </div>
|
||||||
<h6 class="name">{{people.name}}</h6>
|
<h6 class="name">{{people.name}}</h6>
|
||||||
<p class="role">{{people.role}}</p>
|
<p class="role">{{people.role}}</p>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<button mat-raised-button color="accent" class="scrollBtn leftBtn d-none" #leftBtn (click)="scrollLeft()"><mat-icon>arrow_left</mat-icon></button>
|
<button mat-raised-button color="accent" class="scrollBtn leftBtn d-none" #leftBtn (click)="scrollLeft()"><mat-icon>arrow_left</mat-icon></button>
|
||||||
<button mat-raised-button color="accent" class="scrollBtn rightBtn" #rightBtn (click)="scrollRight()"><mat-icon>arrow_right</mat-icon></button>
|
<button mat-raised-button color="accent" class="scrollBtn rightBtn" #rightBtn (click)="scrollRight()"><mat-icon>arrow_right</mat-icon></button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,138 +4,138 @@
|
|||||||
|
|
||||||
.people-container
|
.people-container
|
||||||
{
|
{
|
||||||
display: flex;
|
display: flex;
|
||||||
padding-left: 15px;
|
padding-left: 15px;
|
||||||
padding-right: 15px;
|
padding-right: 15px;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
scrollbar-width: thin;
|
scrollbar-width: thin;
|
||||||
scrollbar-color: #999 transparent;
|
scrollbar-color: #999 transparent;
|
||||||
|
|
||||||
&::-webkit-scrollbar
|
&::-webkit-scrollbar
|
||||||
{
|
{
|
||||||
height: 4px;
|
height: 4px;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-scrollbar-thumb
|
&::-webkit-scrollbar-thumb
|
||||||
{
|
{
|
||||||
background-color: #999;
|
background-color: #999;
|
||||||
border-radius: 90px;
|
border-radius: 90px;
|
||||||
|
|
||||||
&:host-context(.hoverEnabled) &:hover
|
&:host-context(.hoverEnabled) &:hover
|
||||||
{
|
{
|
||||||
background-color: rgb(134, 127, 127);
|
background-color: rgb(134, 127, 127);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.people
|
.people
|
||||||
{
|
{
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
margin: .25rem;
|
margin: .25rem;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
outline: none;
|
outline: none;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
width: 33%;
|
width: 33%;
|
||||||
|
|
||||||
@include media-breakpoint-up(sm)
|
@include media-breakpoint-up(sm)
|
||||||
{
|
{
|
||||||
width: 22%;
|
width: 22%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include media-breakpoint-up(md)
|
@include media-breakpoint-up(md)
|
||||||
{
|
{
|
||||||
width: 20%;
|
width: 20%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include media-breakpoint-up(lg)
|
@include media-breakpoint-up(lg)
|
||||||
{
|
{
|
||||||
width: 15%;
|
width: 15%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include media-breakpoint-up(xl)
|
@include media-breakpoint-up(xl)
|
||||||
{
|
{
|
||||||
width: 10%;
|
width: 10%;
|
||||||
}
|
}
|
||||||
|
|
||||||
> div
|
> div
|
||||||
{
|
{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 0;
|
height: 0;
|
||||||
padding-top: 147.0588%;
|
padding-top: 147.0588%;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-color: #333333;
|
background-color: #333333;
|
||||||
}
|
}
|
||||||
|
|
||||||
> p, h6
|
> p, h6
|
||||||
{
|
{
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
|
|
||||||
&.role
|
&.role
|
||||||
{
|
{
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:host-context(.hoverEnabled) &:hover
|
&:host-context(.hoverEnabled) &:hover
|
||||||
{
|
{
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
> img
|
> img
|
||||||
{
|
{
|
||||||
outline: solid var(--accentColor);
|
outline: solid var(--accentColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
.name
|
.name
|
||||||
{
|
{
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.scroll-row
|
.scroll-row
|
||||||
{
|
{
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
&:host-context(.hoverEnabled) &:hover
|
&:host-context(.hoverEnabled) &:hover
|
||||||
{
|
{
|
||||||
.scrollBtn
|
.scrollBtn
|
||||||
{
|
{
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.scrollBtn
|
.scrollBtn
|
||||||
{
|
{
|
||||||
padding: 0;
|
padding: 0;
|
||||||
outline: none;
|
outline: none;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 30%;
|
top: 30%;
|
||||||
bottom: 40%;
|
bottom: 40%;
|
||||||
display: none;
|
display: none;
|
||||||
|
|
||||||
&.leftBtn
|
&.leftBtn
|
||||||
{
|
{
|
||||||
left: 0;
|
left: 0;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
padding-right: 2px;
|
padding-right: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.rightBtn
|
&.rightBtn
|
||||||
{
|
{
|
||||||
right: 0;
|
right: 0;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
padding-left: 2px;
|
padding-left: 2px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,154 +1,154 @@
|
|||||||
<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)="videoClicked()">
|
||||||
</video>
|
</video>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="loadIndicator">
|
<div id="loadIndicator">
|
||||||
<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" [ngClass]="{'d-block': this.displayStats}">
|
||||||
<mat-card-header style="margin-bottom: 0.5rem;">
|
<mat-card-header style="margin-bottom: 0.5rem;">
|
||||||
<h4 style="align-self: center; margin-bottom: 0;">Stats</h4>
|
<h4 style="align-self: center; margin-bottom: 0;">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" style="outline: none;">
|
||||||
<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 style="float: right">{{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 style="float: right">{{this.item.container}} <i class="material-icons" style="vertical-align: middle; font-size: 14px">{{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 style="float: right">{{this.item.video.codec}} <i class="material-icons" style="vertical-align: middle; font-size: 14px">{{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 style="float: right">{{this.item.audios[0].codec}} <i class="material-icons" style="vertical-align: middle; font-size: 14px">{{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 style="float: right">{{this.selectedSubtitle ? this.selectedSubtitle.codec : "none"}} <i class="material-icons" style="vertical-align: middle; font-size: 14px">{{getSupportedFeature("subtitle")}}</i></span>
|
||||||
<br />
|
<br />
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
|
||||||
<div id="hover">
|
<div id="hover">
|
||||||
<div class="back">
|
<div class="back">
|
||||||
<a mat-icon-button matTooltipPosition="below" matTooltip="Back" (click)="back()">
|
<a mat-icon-button matTooltipPosition="below" matTooltip="Back" (click)="back()">
|
||||||
<mat-icon>arrow_back</mat-icon>
|
<mat-icon>arrow_back</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
<h5>{{this.item.showTitle}}</h5>
|
<h5>{{this.item.showTitle}}</h5>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="controller container-fluid" id="controller">
|
<div class="controller container-fluid" id="controller">
|
||||||
<div class="img d-none d-sm-block">
|
<div class="img d-none d-sm-block">
|
||||||
<img src="poster/{{this.item.showSlug}}" />
|
<img src="poster/{{this.item.showSlug}}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<h3>S{{this.item.seasonNumber}}:E{{this.item.episodeNumber}} - {{this.item.title}}</h3>
|
<h3>S{{this.item.seasonNumber}}:E{{this.item.episodeNumber}} - {{this.item.title}}</h3>
|
||||||
|
|
||||||
<div id="progress-bar">
|
<div id="progress-bar">
|
||||||
<div class="seek-bar">
|
<div class="seek-bar">
|
||||||
<div id="buffered"></div>
|
<div id="buffered"></div>
|
||||||
<div id="progress"></div>
|
<div id="progress"></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="thumb"><div></div></div>
|
<div id="thumb"><div></div></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<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" [matTooltip]="playTooltip" id="play" (click)="tooglePlayback()">
|
||||||
<mat-icon>{{this.playIcon}}</mat-icon>
|
<mat-icon>{{this.playIcon}}</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>
|
||||||
|
|
||||||
<div id="next">
|
<div id="next">
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<img src="{{this.item.nextEpisode.thumb}}" />
|
<img src="{{this.item.nextEpisode.thumb}}" />
|
||||||
</div>
|
</div>
|
||||||
<div id="overview">
|
<div id="overview">
|
||||||
<h6>S{{this.item.nextEpisode.seasonNumber}}:E{{this.item.nextEpisode.episodeNumber}} - {{this.item.nextEpisode.title}}</h6>
|
<h6>S{{this.item.nextEpisode.seasonNumber}}:E{{this.item.nextEpisode.episodeNumber}} - {{this.item.nextEpisode.title}}</h6>
|
||||||
<p>{{this.item.nextEpisode.overview}}</p>
|
<p>{{this.item.nextEpisode.overview}}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<div id="volume">
|
<div id="volume">
|
||||||
<button mat-icon-button matTooltipPosition="above" matTooltip="Volume" (click)="toogleMute()">
|
<button mat-icon-button matTooltipPosition="above" matTooltip="Volume" (click)="toogleMute()">
|
||||||
<mat-icon>{{this.volumeIcon}}</mat-icon>
|
<mat-icon>{{this.volumeIcon}}</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<mat-slider [value]="volume" (input)="changeVolume($event.value)"></mat-slider>
|
<mat-slider [value]="volume" (input)="changeVolume($event.value)"></mat-slider>
|
||||||
</div>
|
</div>
|
||||||
<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>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<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">
|
||||||
<mat-icon>cast</mat-icon>
|
<mat-icon>cast</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<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" [matTooltip]="fullscreenTooltip" id="fullscreen" (click)="fullscreen()">
|
||||||
<mat-icon>{{fullscreenIcon}}</mat-icon>
|
<mat-icon>{{fullscreenIcon}}</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<mat-menu #subtitles="matMenu">
|
<mat-menu #subtitles="matMenu">
|
||||||
<ng-template matMenuContent>
|
<ng-template matMenuContent>
|
||||||
<button [ngClass]="{'selected': this.selectedSubtitle == null}" mat-menu-item (click)="selectSubtitle(null)">
|
<button [ngClass]="{'selected': this.selectedSubtitle == null}" mat-menu-item (click)="selectSubtitle(null)">
|
||||||
<span>None</span>
|
<span>None</span>
|
||||||
</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>
|
||||||
|
|
||||||
<ng-template #elseBlock>
|
<ng-template #elseBlock>
|
||||||
<button mat-menu-item disabled>
|
<button mat-menu-item disabled>
|
||||||
<span>{{subtitle.displayName}} ({{subtitle.codec}})</span>
|
<span>{{subtitle.displayName}} ({{subtitle.codec}})</span>
|
||||||
</button>
|
</button>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
|
|
||||||
<mat-menu #settings="matMenu">
|
<mat-menu #settings="matMenu">
|
||||||
<ng-template matMenuContent>
|
<ng-template matMenuContent>
|
||||||
<button mat-menu-item (click)="this.displayStats = !this.displayStats">
|
<button mat-menu-item (click)="this.displayStats = !this.displayStats">
|
||||||
<span>Stats</span>
|
<span>Stats</span>
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item [matMenuTriggerFor]="method">
|
<button mat-menu-item [matMenuTriggerFor]="method">
|
||||||
<span>Method</span>
|
<span>Method</span>
|
||||||
</button>
|
</button>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
|
|
||||||
<mat-menu #method="matMenu">
|
<mat-menu #method="matMenu">
|
||||||
<ng-template matMenuContent>
|
<ng-template matMenuContent>
|
||||||
<button mat-menu-item (click)="selectPlayMethod(methodType.direct)">
|
<button mat-menu-item (click)="selectPlayMethod(methodType.direct)">
|
||||||
<span>Direct Play</span>
|
<span>Direct Play</span>
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item (click)="selectPlayMethod(methodType.transmux)">
|
<button mat-menu-item (click)="selectPlayMethod(methodType.transmux)">
|
||||||
<span>Transmux</span>
|
<span>Transmux</span>
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item (click)="selectPlayMethod(methodType.transcode)">
|
<button mat-menu-item (click)="selectPlayMethod(methodType.transcode)">
|
||||||
<span>Transcode</span>
|
<span>Transcode</span>
|
||||||
</button>
|
</button>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,339 +3,339 @@
|
|||||||
|
|
||||||
.player
|
.player
|
||||||
{
|
{
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
background: #000;
|
background: #000;
|
||||||
|
|
||||||
> video
|
> video
|
||||||
{
|
{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#hover
|
#hover
|
||||||
{
|
{
|
||||||
transition: opacity .2s linear;
|
transition: opacity .2s linear;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
|
|
||||||
&.idle
|
&.idle
|
||||||
{
|
{
|
||||||
transition: opacity .6s linear, visibility 0s .6s;
|
transition: opacity .6s linear, visibility 0s .6s;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.back
|
.back
|
||||||
{
|
{
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
background: rgba(0, 0, 0, 0.6);
|
background: rgba(0, 0, 0, 0.6);
|
||||||
padding: .33%;
|
padding: .33%;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
> a
|
> a
|
||||||
{
|
{
|
||||||
outline: none;
|
outline: none;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
> h5
|
> h5
|
||||||
{
|
{
|
||||||
margin: 0;
|
margin: 0;
|
||||||
margin-left: .5rem;
|
margin-left: .5rem;
|
||||||
align-self: center;
|
align-self: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.controller
|
.controller
|
||||||
{
|
{
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
background: rgba(0, 0, 0, 0.6);
|
background: rgba(0, 0, 0, 0.6);
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 1%;
|
padding: 1%;
|
||||||
|
|
||||||
.img
|
.img
|
||||||
{
|
{
|
||||||
width: 15%;
|
width: 15%;
|
||||||
position: relative;
|
position: relative;
|
||||||
height: auto;
|
height: auto;
|
||||||
|
|
||||||
> img
|
> img
|
||||||
{
|
{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.content
|
.content
|
||||||
{
|
{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-left: 1rem;
|
margin-left: 1rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
.buttons
|
.buttons
|
||||||
{
|
{
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
> div
|
> div
|
||||||
{
|
{
|
||||||
&.left
|
&.left
|
||||||
{
|
{
|
||||||
align-self: start;
|
align-self: start;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
> p
|
> p
|
||||||
{
|
{
|
||||||
margin: 0;
|
margin: 0;
|
||||||
margin-left: 1rem;
|
margin-left: 1rem;
|
||||||
align-self: center;
|
align-self: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.right
|
&.right
|
||||||
{
|
{
|
||||||
align-self: end;
|
align-self: end;
|
||||||
}
|
}
|
||||||
|
|
||||||
> button
|
> button
|
||||||
{
|
{
|
||||||
margin-left: .3rem;
|
margin-left: .3rem;
|
||||||
margin-right: .3rem;
|
margin-right: .3rem;
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
> a
|
> a
|
||||||
{
|
{
|
||||||
margin-left: .3rem;
|
margin-left: .3rem;
|
||||||
margin-right: .3rem;
|
margin-right: .3rem;
|
||||||
outline: none;
|
outline: none;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
text-decoration: inherit;
|
text-decoration: inherit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#progress-bar
|
#progress-bar
|
||||||
{
|
{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
padding-top: 1rem;
|
padding-top: 1rem;
|
||||||
padding-bottom: 1rem;
|
padding-bottom: 1rem;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.seek-bar
|
.seek-bar
|
||||||
{
|
{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 4px;
|
height: 4px;
|
||||||
position: relative;
|
position: relative;
|
||||||
background-color: rgba(255, 255, 255, .2);
|
background-color: rgba(255, 255, 255, .2);
|
||||||
transform: scaleY(.6);
|
transform: scaleY(.6);
|
||||||
|
|
||||||
#progress
|
#progress
|
||||||
{
|
{
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: var(--accentColor);
|
background-color: var(--accentColor);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#buffered
|
#buffered
|
||||||
{
|
{
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: rgba(255, 255, 255, .5);
|
background-color: rgba(255, 255, 255, .5);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#thumb
|
#thumb
|
||||||
{
|
{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 12px;
|
height: 12px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: -6px;
|
left: -6px;
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
||||||
> div
|
> div
|
||||||
{
|
{
|
||||||
width: 12px;
|
width: 12px;
|
||||||
height: 12px;
|
height: 12px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
background-color: var(--accentColor);
|
background-color: var(--accentColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.hoverEnabled &:hover, &.seeking
|
.hoverEnabled &:hover, &.seeking
|
||||||
{
|
{
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
.seek-bar
|
.seek-bar
|
||||||
{
|
{
|
||||||
transform: scaleY(1);
|
transform: scaleY(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#thumb
|
#thumb
|
||||||
{
|
{
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#nextBtn
|
#nextBtn
|
||||||
{
|
{
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.hoverEnabled &:hover
|
.hoverEnabled &:hover
|
||||||
{
|
{
|
||||||
#next
|
#next
|
||||||
{
|
{
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#next
|
#next
|
||||||
{
|
{
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
bottom: 100%;
|
bottom: 100%;
|
||||||
display: none;
|
display: none;
|
||||||
background-color: #212121;
|
background-color: #212121;
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
height: 150px;
|
height: 150px;
|
||||||
|
|
||||||
#main
|
#main
|
||||||
{
|
{
|
||||||
width: auto;
|
width: auto;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
|
|
||||||
> img
|
> img
|
||||||
{
|
{
|
||||||
width: auto;
|
width: auto;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#overview
|
#overview
|
||||||
{
|
{
|
||||||
padding: 1%;
|
padding: 1%;
|
||||||
width: 50%;
|
width: 50%;
|
||||||
min-width: 300px;
|
min-width: 300px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
> p
|
> p
|
||||||
{
|
{
|
||||||
text-align: justify;
|
text-align: justify;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#volume
|
#volume
|
||||||
{
|
{
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
> button
|
> button
|
||||||
{
|
{
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hoverEnabled &:hover, &:focus-within
|
.hoverEnabled &:hover, &:focus-within
|
||||||
{
|
{
|
||||||
> mat-slider
|
> mat-slider
|
||||||
{
|
{
|
||||||
width: 100px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> mat-slider
|
> mat-slider
|
||||||
{
|
{
|
||||||
width: 0px;
|
width: 0px;
|
||||||
min-width: 0px;
|
min-width: 0px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
transition: width .2s cubic-bezier(0.4,0, 1, 1);
|
transition: width .2s cubic-bezier(0.4,0, 1, 1);
|
||||||
|
|
||||||
> div
|
> div
|
||||||
{
|
{
|
||||||
top: 19px;
|
top: 19px;
|
||||||
left: 10px;
|
left: 10px;
|
||||||
right: 10px;
|
right: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mat-menu-item
|
.mat-menu-item
|
||||||
{
|
{
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.selected
|
.selected
|
||||||
{
|
{
|
||||||
background: #595959 !important;
|
background: #595959 !important;
|
||||||
color: var(--accentColor);
|
color: var(--accentColor);
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
}
|
}
|
||||||
|
|
||||||
#loadIndicator
|
#loadIndicator
|
||||||
{
|
{
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
background: rgba(0, 0, 0, 0.3);
|
background: rgba(0, 0, 0, 0.3);
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.volume
|
.volume
|
||||||
{
|
{
|
||||||
min-width: 0px !important;
|
min-width: 0px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info-panel
|
.info-panel
|
||||||
{
|
{
|
||||||
min-width: 250px !important;
|
min-width: 250px !important;
|
||||||
max-width: 300px !important;
|
max-width: 300px !important;
|
||||||
}
|
}
|
||||||
|
@ -371,7 +371,7 @@ export class PlayerComponent implements OnInit
|
|||||||
let queryMethod: string = this.route.snapshot.queryParams["method"];
|
let queryMethod: string = this.route.snapshot.queryParams["method"];
|
||||||
if (queryMethod)
|
if (queryMethod)
|
||||||
this.playMethod = method[queryMethod];
|
this.playMethod = method[queryMethod];
|
||||||
else
|
else
|
||||||
this.playMethod = getPlaybackMethod(this.player, this.item);
|
this.playMethod = getPlaybackMethod(this.player, this.item);
|
||||||
|
|
||||||
this.selectPlayMethod(this.playMethod);
|
this.selectPlayMethod(this.playMethod);
|
||||||
@ -428,7 +428,7 @@ export class PlayerComponent implements OnInit
|
|||||||
next()
|
next()
|
||||||
{
|
{
|
||||||
if (this.item.nextEpisode != null)
|
if (this.item.nextEpisode != null)
|
||||||
this.router.navigate(["/watch/" + this.item.nextEpisode.link], { queryParamsHandling: "merge", replaceUrl: true });
|
this.router.navigate(["/watch/" + this.item.nextEpisode.link], { queryParamsHandling: "merge", replaceUrl: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
previous()
|
previous()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
::cue
|
::cue
|
||||||
{
|
{
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;
|
text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<div *ngIf="items.shows.length > 0" class="container-fluid mt-3">
|
<div *ngIf="items.shows.length > 0" class="container-fluid mt-3">
|
||||||
<h3>Shows</h3>
|
<h3>Shows</h3>
|
||||||
</div>
|
</div>
|
||||||
<app-shows-list [shows]="items.shows"></app-shows-list>
|
<app-shows-list [shows]="items.shows"></app-shows-list>
|
||||||
<div *ngIf="items.episodes.length > 0" class="container-fluid mt-5">
|
<div *ngIf="items.episodes.length > 0" class="container-fluid mt-5">
|
||||||
<h3>Episodes</h3>
|
<h3>Episodes</h3>
|
||||||
</div>
|
</div>
|
||||||
<app-episodes-list displayShowTitle="true" [episodes]="items.episodes"></app-episodes-list>
|
<app-episodes-list displayShowTitle="true" [episodes]="items.episodes"></app-episodes-list>
|
||||||
<div *ngIf="items.people.length > 0" class="container-fluid mt-5">
|
<div *ngIf="items.people.length > 0" class="container-fluid mt-5">
|
||||||
<h3>People</h3>
|
<h3>People</h3>
|
||||||
</div>
|
</div>
|
||||||
<app-people-list [people]="items.people"></app-people-list>
|
<app-people-list [people]="items.people"></app-people-list>
|
||||||
|
@ -4,9 +4,9 @@ import { SearchResut } from "../../models/search-result";
|
|||||||
import { Title } from "@angular/platform-browser";
|
import { Title } from "@angular/platform-browser";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-search',
|
selector: 'app-search',
|
||||||
templateUrl: './search.component.html',
|
templateUrl: './search.component.html',
|
||||||
styleUrls: ['./search.component.scss']
|
styleUrls: ['./search.component.scss']
|
||||||
})
|
})
|
||||||
export class SearchComponent implements OnInit, OnDestroy
|
export class SearchComponent implements OnInit, OnDestroy
|
||||||
{
|
{
|
||||||
|
@ -7,27 +7,27 @@ import { catchError } from 'rxjs/operators'
|
|||||||
import { Collection } from "../../models/collection";
|
import { Collection } from "../../models/collection";
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class CollectionResolverService implements Resolve<Collection>
|
export class CollectionResolverService implements Resolve<Collection>
|
||||||
{
|
{
|
||||||
constructor(private http: HttpClient, private snackBar: MatSnackBar) { }
|
constructor(private http: HttpClient, private snackBar: MatSnackBar) { }
|
||||||
|
|
||||||
resolve(route: ActivatedRouteSnapshot): Collection | Observable<Collection> | Promise<Collection>
|
resolve(route: ActivatedRouteSnapshot): Collection | Observable<Collection> | Promise<Collection>
|
||||||
{
|
{
|
||||||
let collection: string = route.paramMap.get("collection-slug");
|
let collection: string = route.paramMap.get("collection-slug");
|
||||||
return this.http.get<Collection>("api/collection/" + collection).pipe(catchError((error: HttpErrorResponse) =>
|
return this.http.get<Collection>("api/collection/" + collection).pipe(catchError((error: HttpErrorResponse) =>
|
||||||
{
|
{
|
||||||
console.log(error.status + " - " + error.message);
|
console.log(error.status + " - " + error.message);
|
||||||
if (error.status == 404)
|
if (error.status == 404)
|
||||||
{
|
{
|
||||||
this.snackBar.open("Collection \"" + collection + "\" not found.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
this.snackBar.open("Collection \"" + collection + "\" not found.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.snackBar.open("An unknow error occured.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
this.snackBar.open("An unknow error occured.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
||||||
}
|
}
|
||||||
return EMPTY;
|
return EMPTY;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,36 +10,36 @@ import { Show } from "../../models/show";
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class LibraryResolverService implements Resolve<Show[]>
|
export class LibraryResolverService implements Resolve<Show[]>
|
||||||
{
|
{
|
||||||
constructor(private http: HttpClient, private snackBar: MatSnackBar) { }
|
constructor(private http: HttpClient, private snackBar: MatSnackBar) { }
|
||||||
|
|
||||||
resolve(route: ActivatedRouteSnapshot): Show[] | Observable<Show[]> | Promise<Show[]>
|
resolve(route: ActivatedRouteSnapshot): Show[] | Observable<Show[]> | Promise<Show[]>
|
||||||
{
|
{
|
||||||
let slug: string = route.paramMap.get("library-slug");
|
let slug: string = route.paramMap.get("library-slug");
|
||||||
|
|
||||||
if (slug == null)
|
if (slug == null)
|
||||||
{
|
{
|
||||||
return this.http.get<Show[]>("api/shows").pipe(catchError((error: HttpErrorResponse) =>
|
return this.http.get<Show[]>("api/shows").pipe(catchError((error: HttpErrorResponse) =>
|
||||||
{
|
{
|
||||||
console.log(error.status + " - " + error.message);
|
console.log(error.status + " - " + error.message);
|
||||||
this.snackBar.open("An unknow error occured.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
this.snackBar.open("An unknow error occured.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
||||||
return EMPTY;
|
return EMPTY;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return this.http.get<Show[]>("api/libraries/" + slug).pipe(catchError((error: HttpErrorResponse) =>
|
return this.http.get<Show[]>("api/libraries/" + slug).pipe(catchError((error: HttpErrorResponse) =>
|
||||||
{
|
{
|
||||||
console.log(error.status + " - " + error.message);
|
console.log(error.status + " - " + error.message);
|
||||||
if (error.status == 404)
|
if (error.status == 404)
|
||||||
{
|
{
|
||||||
this.snackBar.open("Library \"" + slug + "\" not found.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
this.snackBar.open("Library \"" + slug + "\" not found.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.snackBar.open("An unknow error occured.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
this.snackBar.open("An unknow error occured.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
||||||
}
|
}
|
||||||
return EMPTY;
|
return EMPTY;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import { Collection } from "../../models/collection";
|
|||||||
import { People } from "../../models/people";
|
import { People } from "../../models/people";
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class PeopleResolverService implements Resolve<Collection>
|
export class PeopleResolverService implements Resolve<Collection>
|
||||||
{
|
{
|
||||||
|
@ -7,20 +7,20 @@ import { catchError } from 'rxjs/operators';
|
|||||||
import { SearchResut } from "../../models/search-result";
|
import { SearchResut } from "../../models/search-result";
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class SearchResolverService implements Resolve<SearchResut>
|
export class SearchResolverService implements Resolve<SearchResut>
|
||||||
{
|
{
|
||||||
constructor(private http: HttpClient, private snackBar: MatSnackBar) { }
|
constructor(private http: HttpClient, private snackBar: MatSnackBar) { }
|
||||||
|
|
||||||
resolve(route: ActivatedRouteSnapshot): SearchResut | Observable<SearchResut> | Promise<SearchResut>
|
resolve(route: ActivatedRouteSnapshot): SearchResut | Observable<SearchResut> | Promise<SearchResut>
|
||||||
{
|
{
|
||||||
let query: string = route.paramMap.get("query");
|
let query: string = route.paramMap.get("query");
|
||||||
return this.http.get<SearchResut>("api/search/" + query).pipe(catchError((error: HttpErrorResponse) =>
|
return this.http.get<SearchResut>("api/search/" + query).pipe(catchError((error: HttpErrorResponse) =>
|
||||||
{
|
{
|
||||||
console.log(error.status + " - " + error.message);
|
console.log(error.status + " - " + error.message);
|
||||||
this.snackBar.open("An unknow error occured.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
this.snackBar.open("An unknow error occured.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
||||||
return EMPTY;
|
return EMPTY;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,23 +9,19 @@ import { Show } from "../../models/show";
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class ShowResolverService implements Resolve<Show>
|
export class ShowResolverService implements Resolve<Show>
|
||||||
{
|
{
|
||||||
constructor(private http: HttpClient, private snackBar: MatSnackBar) { }
|
constructor(private http: HttpClient, private snackBar: MatSnackBar) { }
|
||||||
|
|
||||||
resolve(route: ActivatedRouteSnapshot): Show | Observable<Show> | Promise<Show>
|
resolve(route: ActivatedRouteSnapshot): Show | Observable<Show> | Promise<Show>
|
||||||
{
|
{
|
||||||
let slug: string = route.paramMap.get("show-slug");
|
let slug: string = route.paramMap.get("show-slug");
|
||||||
return this.http.get<Show>("api/shows/" + slug).pipe(catchError((error: HttpErrorResponse) =>
|
return this.http.get<Show>("api/shows/" + slug).pipe(catchError((error: HttpErrorResponse) =>
|
||||||
{
|
{
|
||||||
console.log(error.status + " - " + error.message);
|
console.log(error.status + " - " + error.message);
|
||||||
if (error.status == 404)
|
if (error.status == 404)
|
||||||
{
|
this.snackBar.open("Show \"" + slug + "\" not found.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
||||||
this.snackBar.open("Show \"" + slug + "\" not found.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
else
|
||||||
}
|
this.snackBar.open("An unknow error occured.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
||||||
else
|
return EMPTY;
|
||||||
{
|
}));
|
||||||
this.snackBar.open("An unknow error occured.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
}
|
||||||
}
|
|
||||||
return EMPTY;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -10,23 +10,23 @@ import { WatchItem } from "../../models/watch-item";
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class StreamResolverService implements Resolve<WatchItem>
|
export class StreamResolverService implements Resolve<WatchItem>
|
||||||
{
|
{
|
||||||
constructor(private http: HttpClient, private snackBar: MatSnackBar) { }
|
constructor(private http: HttpClient, private snackBar: MatSnackBar) { }
|
||||||
|
|
||||||
resolve(route: ActivatedRouteSnapshot): WatchItem | Observable<WatchItem> | Promise<WatchItem>
|
resolve(route: ActivatedRouteSnapshot): WatchItem | Observable<WatchItem> | Promise<WatchItem>
|
||||||
{
|
{
|
||||||
let item: string = route.paramMap.get("item");
|
let item: string = route.paramMap.get("item");
|
||||||
return this.http.get<WatchItem>("api/watch/" + item).pipe(catchError((error: HttpErrorResponse) =>
|
return this.http.get<WatchItem>("api/watch/" + item).pipe(catchError((error: HttpErrorResponse) =>
|
||||||
{
|
{
|
||||||
console.log(error.status + " - " + error.message);
|
console.log(error.status + " - " + error.message);
|
||||||
if (error.status == 404)
|
if (error.status == 404)
|
||||||
{
|
{
|
||||||
this.snackBar.open("Episode \"" + item + "\" not found.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
this.snackBar.open("Episode \"" + item + "\" not found.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.snackBar.open("An unknow error occured.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
this.snackBar.open("An unknow error occured.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
||||||
}
|
}
|
||||||
return EMPTY;
|
return EMPTY;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,79 +1,79 @@
|
|||||||
<div class="backdrop">
|
<div class="backdrop">
|
||||||
<img id="backdrop" src="backdrop/{{this.show.slug}}" />
|
<img id="backdrop" src="backdrop/{{this.show.slug}}" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="header container pt-sm-5">
|
<div class="header container pt-sm-5">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<img class="poster d-none d-sm-block" src="poster/{{this.show.slug}}" />
|
<img class="poster d-none d-sm-block" src="poster/{{this.show.slug}}" />
|
||||||
<div class="main col">
|
<div class="main col">
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<h1 class="title">{{this.show.title}}</h1>
|
<h1 class="title">{{this.show.title}}</h1>
|
||||||
<h2 class="date" *ngIf="show.endYear; else elseBlock">{{show.startYear}} - {{show.endYear}}</h2>
|
<h2 class="date" *ngIf="show.endYear; else elseBlock">{{show.startYear}} - {{show.endYear}}</h2>
|
||||||
<ng-template #elseBlock><h2 class="date">{{show.startYear}}</h2></ng-template>
|
<ng-template #elseBlock><h2 class="date">{{show.startYear}}</h2></ng-template>
|
||||||
</div>
|
</div>
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<button mat-mini-fab matTooltipPosition="above" matTooltip="Play" class="mr-3">
|
<button mat-mini-fab matTooltipPosition="above" matTooltip="Play" class="mr-3">
|
||||||
<mat-icon>play_arrow</mat-icon>
|
<mat-icon>play_arrow</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button *ngIf="this.show.trailerUrl" mat-icon-button matTooltipPosition="above" matTooltip="Trailer">
|
<button *ngIf="this.show.trailerUrl" mat-icon-button matTooltipPosition="above" matTooltip="Trailer">
|
||||||
<mat-icon>local_movies</mat-icon>
|
<mat-icon>local_movies</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button mat-icon-button matTooltipPosition="above" matTooltip="Download">
|
<button mat-icon-button matTooltipPosition="above" matTooltip="Download">
|
||||||
<mat-icon>cloud_download</mat-icon>
|
<mat-icon>cloud_download</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button mat-icon-button matTooltipPosition="above" matTooltip="Watched">
|
<button mat-icon-button matTooltipPosition="above" matTooltip="Watched">
|
||||||
<mat-icon>done</mat-icon>
|
<mat-icon>done</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button mat-icon-button matTooltipPosition="above" matTooltip="More">
|
<button mat-icon-button matTooltipPosition="above" matTooltip="More">
|
||||||
<mat-icon>more_horiz</mat-icon>
|
<mat-icon>more_horiz</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-3 secondary d-none d-md-block">
|
<div class="col-3 secondary d-none d-md-block">
|
||||||
<img src="logo/{{this.show.slug}}" />
|
<img src="logo/{{this.show.slug}}" />
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<p>Studio: <b><a routerLink="/studio/{{this.show.studio?.slug}}">{{this.show.studio?.name}}</a></b></p>
|
<p>Studio: <b><a routerLink="/studio/{{this.show.studio?.slug}}">{{this.show.studio?.name}}</a></b></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row pt-3 d-md-none">
|
<div class="row pt-3 d-md-none">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<p class="mr-1 d-inline-block">Studio: <b><a routerLink="/studio/{{this.show.studio?.slug}}">{{this.show.studio?.name}}</a></b></p>
|
<p class="mr-1 d-inline-block">Studio: <b><a routerLink="/studio/{{this.show.studio?.slug}}">{{this.show.studio?.name}}</a></b></p>
|
||||||
<div class="d-sm-none">
|
<div class="d-sm-none">
|
||||||
<p>Genres: <span *ngFor="let genre of this.show.genres; let isLast = last"><b><a routerLink="/genre/{{genre.slug}}">{{genre.name}}</a></b>{{isLast ? "" : ", "}}</span></p>
|
<p>Genres: <span *ngFor="let genre of this.show.genres; let isLast = last"><b><a routerLink="/genre/{{genre.slug}}">{{genre.name}}</a></b>{{isLast ? "" : ", "}}</span></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row pt-3">
|
<div class="row pt-3">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<p class="text-justify overview">{{this.show.overview}}</p>
|
<p class="text-justify overview">{{this.show.overview}}</p>
|
||||||
</div>
|
</div>
|
||||||
<hr class="d-none d-sm-block">
|
<hr class="d-none d-sm-block">
|
||||||
<div class="col-3 d-none d-sm-block">
|
<div class="col-3 d-none d-sm-block">
|
||||||
<h3 style="opacity: .8;">Genres</h3>
|
<h3 style="opacity: .8;">Genres</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li *ngFor="let genre of this.show.genres"><b><a class="genre" routerLink="/genre/{{genre.slug}}">{{genre.name}}</a></b></li>
|
<li *ngFor="let genre of this.show.genres"><b><a class="genre" routerLink="/genre/{{genre.slug}}">{{genre.name}}</a></b></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="container-fluid mt-3">
|
<div class="container-fluid mt-3">
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>Season</mat-label>
|
<mat-label>Season</mat-label>
|
||||||
<mat-select [(value)]="season" (selectionChange)="getEpisodes()">
|
<mat-select [(value)]="season" (selectionChange)="getEpisodes()">
|
||||||
<mat-option *ngFor="let season of this.show.seasons" [value]="season.seasonNumber">{{season.title}}</mat-option>
|
<mat-option *ngFor="let season of this.show.seasons" [value]="season.seasonNumber">{{season.title}}</mat-option>
|
||||||
</mat-select>
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
<app-episodes-list [episodes]="episodes"></app-episodes-list>
|
<app-episodes-list [episodes]="episodes"></app-episodes-list>
|
||||||
|
|
||||||
<div class="container-fluid mt-5">
|
<div class="container-fluid mt-5">
|
||||||
<h3>Staff</h3>
|
<h3>Staff</h3>
|
||||||
</div>
|
</div>
|
||||||
<app-people-list [people]="show.people"></app-people-list>
|
<app-people-list [people]="show.people"></app-people-list>
|
||||||
|
@ -4,149 +4,149 @@
|
|||||||
|
|
||||||
a
|
a
|
||||||
{
|
{
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.backdrop
|
.backdrop
|
||||||
{
|
{
|
||||||
margin-top: -68px;
|
margin-top: -68px;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
|
|
||||||
> img
|
> img
|
||||||
{
|
{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-height: 75vh;
|
max-height: 75vh;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
min-height: 20vh;
|
min-height: 20vh;
|
||||||
|
|
||||||
@include media-breakpoint-up(md)
|
@include media-breakpoint-up(md)
|
||||||
{
|
{
|
||||||
min-height: 60vh;
|
min-height: 60vh;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:after
|
&:after
|
||||||
{
|
{
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, rgba(0, 0, 0, 0.6) 100%);
|
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, rgba(0, 0, 0, 0.6) 100%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header
|
.header
|
||||||
{
|
{
|
||||||
@include media-breakpoint-up(sm)
|
@include media-breakpoint-up(sm)
|
||||||
{
|
{
|
||||||
margin-top: -12rem;
|
margin-top: -12rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include media-breakpoint-up(md)
|
@include media-breakpoint-up(md)
|
||||||
{
|
{
|
||||||
margin-top: -13rem;
|
margin-top: -13rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include media-breakpoint-up(lg)
|
@include media-breakpoint-up(lg)
|
||||||
{
|
{
|
||||||
margin-top: -19rem;
|
margin-top: -19rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include media-breakpoint-up(xl)
|
@include media-breakpoint-up(xl)
|
||||||
{
|
{
|
||||||
margin-top: -23rem;
|
margin-top: -23rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.poster
|
.poster
|
||||||
{
|
{
|
||||||
width: 33%;
|
width: 33%;
|
||||||
background-color: #333333;
|
background-color: #333333;
|
||||||
|
|
||||||
@include media-breakpoint-up(md)
|
@include media-breakpoint-up(md)
|
||||||
{
|
{
|
||||||
width: 25%;
|
width: 25%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.main
|
.main
|
||||||
{
|
{
|
||||||
align-self: center;
|
align-self: center;
|
||||||
padding-left: 2.5em;
|
padding-left: 2.5em;
|
||||||
|
|
||||||
.info
|
.info
|
||||||
{
|
{
|
||||||
margin-top: -3.25rem;
|
margin-top: -3.25rem;
|
||||||
|
|
||||||
@include media-breakpoint-up(sm)
|
@include media-breakpoint-up(sm)
|
||||||
{
|
{
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title
|
.title
|
||||||
{
|
{
|
||||||
font-weight: 900 !important;
|
font-weight: 900 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.date
|
.date
|
||||||
{
|
{
|
||||||
font-weight: 300 !important;
|
font-weight: 300 !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.buttons
|
.buttons
|
||||||
{
|
{
|
||||||
> button
|
> button
|
||||||
{
|
{
|
||||||
outline: none;
|
outline: none;
|
||||||
margin: .3em;
|
margin: .3em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.secondary
|
.secondary
|
||||||
{
|
{
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
> img
|
> img
|
||||||
{
|
{
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
> div
|
> div
|
||||||
{
|
{
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
> div > p
|
> div > p
|
||||||
{
|
{
|
||||||
opacity: .87;
|
opacity: .87;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.overview
|
.overview
|
||||||
{
|
{
|
||||||
opacity: .87;
|
opacity: .87;
|
||||||
|
|
||||||
@include media-breakpoint-up(sm)
|
@include media-breakpoint-up(sm)
|
||||||
{
|
{
|
||||||
padding-top: 2.25rem;
|
padding-top: 2.25rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hr
|
hr
|
||||||
{
|
{
|
||||||
margin: 0 10px 0 10px;
|
margin: 0 10px 0 10px;
|
||||||
border-right: 1px solid rgba(255, 255, 255, .60);
|
border-right: 1px solid rgba(255, 255, 255, .60);
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
height: inherit;
|
height: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.genre
|
.genre
|
||||||
{
|
{
|
||||||
opacity: .8;
|
opacity: .8;
|
||||||
}
|
}
|
||||||
|
@ -7,76 +7,76 @@ import { Episode } from "../../models/episode";
|
|||||||
import { Show } from "../../models/show";
|
import { Show } from "../../models/show";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-show-details',
|
selector: 'app-show-details',
|
||||||
templateUrl: './show-details.component.html',
|
templateUrl: './show-details.component.html',
|
||||||
styleUrls: ['./show-details.component.scss']
|
styleUrls: ['./show-details.component.scss']
|
||||||
})
|
})
|
||||||
export class ShowDetailsComponent implements OnInit
|
export class ShowDetailsComponent implements OnInit
|
||||||
{
|
{
|
||||||
show: Show;
|
show: Show;
|
||||||
episodes: Episode[] = null;
|
episodes: Episode[] = null;
|
||||||
season: number;
|
season: number;
|
||||||
|
|
||||||
private toolbar: HTMLElement;
|
private toolbar: HTMLElement;
|
||||||
private backdrop: HTMLElement;
|
private backdrop: HTMLElement;
|
||||||
|
|
||||||
constructor(private route: ActivatedRoute, private http: HttpClient, private snackBar: MatSnackBar, private title: Title)
|
constructor(private route: ActivatedRoute, private http: HttpClient, private snackBar: MatSnackBar, private title: Title)
|
||||||
{
|
{
|
||||||
this.route.queryParams.subscribe(params =>
|
this.route.queryParams.subscribe(params =>
|
||||||
{
|
{
|
||||||
this.season = params["season"];
|
this.season = params["season"];
|
||||||
});
|
});
|
||||||
|
|
||||||
this.route.data.subscribe(data =>
|
this.route.data.subscribe(data =>
|
||||||
{
|
{
|
||||||
this.show = data.show;
|
this.show = data.show;
|
||||||
this.title.setTitle(this.show.title + " - Kyoo");
|
this.title.setTitle(this.show.title + " - Kyoo");
|
||||||
|
|
||||||
if (this.season == null || this.show.seasons.find(x => x.seasonNumber == this.season) == null)
|
if (this.season == null || this.show.seasons.find(x => x.seasonNumber == this.season) == null)
|
||||||
this.season = 1;
|
this.season = 1;
|
||||||
|
|
||||||
this.getEpisodes();
|
this.getEpisodes();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit()
|
ngOnInit()
|
||||||
{
|
{
|
||||||
this.toolbar = document.getElementById("toolbar");
|
this.toolbar = document.getElementById("toolbar");
|
||||||
this.backdrop = document.getElementById("backdrop");
|
this.backdrop = document.getElementById("backdrop");
|
||||||
window.addEventListener("scroll", this.scroll, true);
|
window.addEventListener("scroll", this.scroll, true);
|
||||||
this.toolbar.setAttribute("style", `background-color: rgba(0, 0, 0, 0) !important`);
|
this.toolbar.setAttribute("style", `background-color: rgba(0, 0, 0, 0) !important`);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy()
|
ngOnDestroy()
|
||||||
{
|
{
|
||||||
window.removeEventListener("scroll", this.scroll, true);
|
window.removeEventListener("scroll", this.scroll, true);
|
||||||
this.title.setTitle("Kyoo");
|
this.title.setTitle("Kyoo");
|
||||||
this.toolbar.setAttribute("style", `background-color: #000000 !important`);
|
this.toolbar.setAttribute("style", `background-color: #000000 !important`);
|
||||||
}
|
}
|
||||||
|
|
||||||
scroll = () =>
|
scroll = () =>
|
||||||
{
|
{
|
||||||
let opacity: number = 2 * window.scrollY / this.backdrop.clientHeight;
|
let opacity: number = 2 * window.scrollY / this.backdrop.clientHeight;
|
||||||
this.toolbar.setAttribute("style", `background-color: rgba(0, 0, 0, ${opacity}) !important`);
|
this.toolbar.setAttribute("style", `background-color: rgba(0, 0, 0, ${opacity}) !important`);
|
||||||
}
|
}
|
||||||
|
|
||||||
getEpisodes()
|
getEpisodes()
|
||||||
{
|
{
|
||||||
if (this.show == null)
|
if (this.show == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this.show.seasons.find(x => x.seasonNumber == this.season).episodes != null)
|
if (this.show.seasons.find(x => x.seasonNumber == this.season).episodes != null)
|
||||||
this.episodes = this.show.seasons.find(x => x.seasonNumber == this.season).episodes;
|
this.episodes = this.show.seasons.find(x => x.seasonNumber == this.season).episodes;
|
||||||
|
|
||||||
|
|
||||||
this.http.get<Episode[]>("api/episodes/" + this.show.slug + "/season/" + this.season).subscribe((episodes: Episode[]) =>
|
this.http.get<Episode[]>("api/episodes/" + this.show.slug + "/season/" + this.season).subscribe((episodes: Episode[]) =>
|
||||||
{
|
{
|
||||||
this.show.seasons.find(x => x.seasonNumber == this.season).episodes = episodes;
|
this.show.seasons.find(x => x.seasonNumber == this.season).episodes = episodes;
|
||||||
this.episodes = episodes;
|
this.episodes = episodes;
|
||||||
}, error =>
|
}, error =>
|
||||||
{
|
{
|
||||||
console.log(error.status + " - " + error.message);
|
console.log(error.status + " - " + error.message);
|
||||||
this.snackBar.open("An unknow error occured while getting episodes.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
this.snackBar.open("An unknow error occured while getting episodes.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<div class="scroll-row mb-5">
|
<div class="scroll-row mb-5">
|
||||||
<div class="shows-container" #scrollView (scroll)="onScroll()">
|
<div class="shows-container" #scrollView (scroll)="onScroll()">
|
||||||
<a class="show" *ngFor="let show of this.shows" routerLink="/show/{{show.slug}}" href="/show/{{show.slug}}">
|
<a class="show" *ngFor="let show of this.shows" routerLink="/show/{{show.slug}}" href="/show/{{show.slug}}">
|
||||||
<div matRipple [style.background-image]="getThumb(show.slug)"> </div>
|
<div matRipple [style.background-image]="getThumb(show.slug)"> </div>
|
||||||
<p class="title">{{show.title}}</p>
|
<p class="title">{{show.title}}</p>
|
||||||
<p class="date" *ngIf="show.endYear; else elseBlock">{{show.startYear}} - {{show.endYear}}</p>
|
<p class="date" *ngIf="show.endYear; else elseBlock">{{show.startYear}} - {{show.endYear}}</p>
|
||||||
<ng-template #elseBlock><p class="date">{{show.startYear}}</p></ng-template>
|
<ng-template #elseBlock><p class="date">{{show.startYear}}</p></ng-template>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<button mat-raised-button color="accent" class="scrollBtn leftBtn d-none" #leftBtn (click)="scrollLeft()"><mat-icon>arrow_left</mat-icon></button>
|
<button mat-raised-button color="accent" class="scrollBtn leftBtn d-none" #leftBtn (click)="scrollLeft()"><mat-icon>arrow_left</mat-icon></button>
|
||||||
<button mat-raised-button color="accent" class="scrollBtn rightBtn" #rightBtn (click)="scrollRight()"><mat-icon>arrow_right</mat-icon></button>
|
<button mat-raised-button color="accent" class="scrollBtn rightBtn" #rightBtn (click)="scrollRight()"><mat-icon>arrow_right</mat-icon></button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,145 +4,145 @@
|
|||||||
|
|
||||||
.shows-container
|
.shows-container
|
||||||
{
|
{
|
||||||
display: flex;
|
display: flex;
|
||||||
padding-left: 15px;
|
padding-left: 15px;
|
||||||
padding-right: 15px;
|
padding-right: 15px;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|
||||||
&::-webkit-scrollbar
|
&::-webkit-scrollbar
|
||||||
{
|
{
|
||||||
height: 4px;
|
height: 4px;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-scrollbar-thumb
|
&::-webkit-scrollbar-thumb
|
||||||
{
|
{
|
||||||
background-color: #999;
|
background-color: #999;
|
||||||
border-radius: 90px;
|
border-radius: 90px;
|
||||||
|
|
||||||
&:host-context(.hoverEnabled) &:hover
|
&:host-context(.hoverEnabled) &:hover
|
||||||
{
|
{
|
||||||
background-color: rgb(134, 127, 127);
|
background-color: rgb(134, 127, 127);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.show
|
.show
|
||||||
{
|
{
|
||||||
width: 33%;
|
width: 33%;
|
||||||
min-width: 120px;
|
min-width: 120px;
|
||||||
max-width: 200px;
|
max-width: 200px;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
padding: .5em;
|
padding: .5em;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
outline: none;
|
outline: none;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
|
|
||||||
@include media-breakpoint-up(sm)
|
@include media-breakpoint-up(sm)
|
||||||
{
|
{
|
||||||
width: 25%;
|
width: 25%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include media-breakpoint-up(md)
|
@include media-breakpoint-up(md)
|
||||||
{
|
{
|
||||||
width: 20%;
|
width: 20%;
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include media-breakpoint-up(lg)
|
@include media-breakpoint-up(lg)
|
||||||
{
|
{
|
||||||
width: 18%;
|
width: 18%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include media-breakpoint-up(xl)
|
@include media-breakpoint-up(xl)
|
||||||
{
|
{
|
||||||
width: 15%;
|
width: 15%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
&:focus, &:hover
|
&:focus, &:hover
|
||||||
{
|
{
|
||||||
> div
|
> div
|
||||||
{
|
{
|
||||||
outline: solid var(--accentColor);
|
outline: solid var(--accentColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
> .title
|
> .title
|
||||||
{
|
{
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> div
|
> div
|
||||||
{
|
{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 0;
|
height: 0;
|
||||||
padding-top: 147.0588%;
|
padding-top: 147.0588%;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-color: #333333;
|
background-color: #333333;
|
||||||
}
|
}
|
||||||
|
|
||||||
> p
|
> p
|
||||||
{
|
{
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
|
||||||
&.date
|
&.date
|
||||||
{
|
{
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:host-context(.hoverEnabled) &:hover
|
&:host-context(.hoverEnabled) &:hover
|
||||||
{
|
{
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.scroll-row
|
.scroll-row
|
||||||
{
|
{
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
&:host-context(.hoverEnabled) &:hover
|
&:host-context(.hoverEnabled) &:hover
|
||||||
{
|
{
|
||||||
.scrollBtn
|
.scrollBtn
|
||||||
{
|
{
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.scrollBtn
|
.scrollBtn
|
||||||
{
|
{
|
||||||
padding: 0;
|
padding: 0;
|
||||||
outline: none;
|
outline: none;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 30%;
|
top: 30%;
|
||||||
bottom: 40%;
|
bottom: 40%;
|
||||||
display: none;
|
display: none;
|
||||||
|
|
||||||
&.leftBtn
|
&.leftBtn
|
||||||
{
|
{
|
||||||
left: 0;
|
left: 0;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
padding-right: 2px;
|
padding-right: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.rightBtn
|
&.rightBtn
|
||||||
{
|
{
|
||||||
right: 0;
|
right: 0;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
padding-left: 2px;
|
padding-left: 2px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
export const environment = {
|
export const environment = {
|
||||||
production: true
|
production: true
|
||||||
};
|
};
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
// The list of file replacements can be found in `angular.json`.
|
// The list of file replacements can be found in `angular.json`.
|
||||||
|
|
||||||
export const environment = {
|
export const environment = {
|
||||||
production: false
|
production: false
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -13,4 +13,4 @@ export const environment = {
|
|||||||
* This import should be commented out in production mode because it will have a negative impact
|
* This import should be commented out in production mode because it will have a negative impact
|
||||||
* on performance if an error is thrown.
|
* on performance if an error is thrown.
|
||||||
*/
|
*/
|
||||||
// import 'zone.js/dist/zone-error'; // Included with Angular CLI.
|
// import 'zone.js/dist/zone-error'; // Included with Angular CLI.
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Kyoo</title>
|
<title>Kyoo</title>
|
||||||
<base href="/">
|
<base href="/">
|
||||||
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#000000" />
|
||||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<app-root></app-root>
|
<app-root></app-root>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -72,8 +72,8 @@ let SubtitleManager = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var det_C0_C1 = (C[0] * C[3]) - (C[2] * C[1]);
|
var det_C0_C1 = (C[0] * C[3]) - (C[2] * C[1]);
|
||||||
var det_C0_X = (C[0] * X[1]) - (C[2] * X[0]);
|
var det_C0_X = (C[0] * X[1]) - (C[2] * X[0]);
|
||||||
var det_X_C1 = (X[0] * C[3]) - (X[1] * C[1]);
|
var det_X_C1 = (X[0] * C[3]) - (X[1] * C[1]);
|
||||||
var alpha_l = det_C0_C1 === 0 ? 0 : det_X_C1 / det_C0_C1;
|
var alpha_l = det_C0_C1 === 0 ? 0 : det_X_C1 / det_C0_C1;
|
||||||
var alpha_r = det_C0_C1 === 0 ? 0 : det_C0_X / det_C0_C1;
|
var alpha_r = det_C0_C1 === 0 ? 0 : det_C0_X / det_C0_C1;
|
||||||
var segLength = norm(subtract(points[0], points[len-1]));
|
var segLength = norm(subtract(points[0], points[len-1]));
|
||||||
@ -209,8 +209,8 @@ let SubtitleManager = (function() {
|
|||||||
} else if (curr.start_time < prev.end_time) {
|
} else if (curr.start_time < prev.end_time) {
|
||||||
let [prev_start_time,prev_start_value,prev_prev_accel] = points[points.length-2];
|
let [prev_start_time,prev_start_value,prev_prev_accel] = points[points.length-2];
|
||||||
let last = points[points.length-1];
|
let last = points[points.length-1];
|
||||||
last[0] = curr.start_time;
|
last[0] = curr.start_time;
|
||||||
last[1] = prev_start_value + (prev.end_value - prev_start_value) * Math.pow((curr.start_time - prev_start_time) / (prev.end_time - prev_start_time), last[2]);
|
last[1] = prev_start_value + (prev.end_value - prev_start_value) * Math.pow((curr.start_time - prev_start_time) / (prev.end_time - prev_start_time), last[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
points.push([curr.end_time,curr.end_value,curr.accel]);
|
points.push([curr.end_time,curr.end_value,curr.accel]);
|
||||||
@ -251,8 +251,8 @@ let SubtitleManager = (function() {
|
|||||||
let combineAdjacentBlocks = text => text.replace(reAdjacentBlocks,"$1$2").replace(reAdjacentBlocks,"$1$2");
|
let combineAdjacentBlocks = text => text.replace(reAdjacentBlocks,"$1$2").replace(reAdjacentBlocks,"$1$2");
|
||||||
|
|
||||||
// Map to convert SSAv4 alignment values to ASSv4+ values.
|
// Map to convert SSAv4 alignment values to ASSv4+ values.
|
||||||
// 1, 2, 3, 5, 6, 7, 9, 10, 11
|
// 1, 2, 3, 5, 6, 7, 9, 10, 11
|
||||||
let SSA_ALIGNMENT_MAP = [0, 1, 2, 3, 0, 7, 8, 9, 0, 4, 5, 6];
|
let SSA_ALIGNMENT_MAP = [0, 1, 2, 3, 0, 7, 8, 9, 0, 4, 5, 6];
|
||||||
|
|
||||||
// Alias for creating SVG elements.
|
// Alias for creating SVG elements.
|
||||||
let createSVGElement = document.createElementNS.bind(document,"http://www.w3.org/2000/svg");
|
let createSVGElement = document.createElementNS.bind(document,"http://www.w3.org/2000/svg");
|
||||||
@ -803,10 +803,10 @@ let SubtitleManager = (function() {
|
|||||||
return computedPaths[pathID];
|
return computedPaths[pathID];
|
||||||
|
|
||||||
path = path.toLowerCase();
|
path = path.toLowerCase();
|
||||||
path = path.replace(/b/g,"C"); // cubic bézier curve to point 3 using point 1 and 2 as the control points
|
path = path.replace(/b/g,"C"); // cubic bézier curve to point 3 using point 1 and 2 as the control points
|
||||||
path = path.replace(/l/g,"L"); // line-to <x>, <y>
|
path = path.replace(/l/g,"L"); // line-to <x>, <y>
|
||||||
path = path.replace(/m/g,"Z M"); // move-to <x>, <y> (closing the shape first)
|
path = path.replace(/m/g,"Z M"); // move-to <x>, <y> (closing the shape first)
|
||||||
path = path.replace(/n/g,"M"); // move-to <x>, <y> (without closing the shape)
|
path = path.replace(/n/g,"M"); // move-to <x>, <y> (without closing the shape)
|
||||||
|
|
||||||
// extend b-spline to <x>, <y>
|
// extend b-spline to <x>, <y>
|
||||||
// The "p" command is only supposed to be used after an "s" command,
|
// The "p" command is only supposed to be used after an "s" command,
|
||||||
@ -829,7 +829,7 @@ let SubtitleManager = (function() {
|
|||||||
// done by copying the starting location and the first two points
|
// done by copying the starting location and the first two points
|
||||||
// to the end of the spline.
|
// to the end of the spline.
|
||||||
// before: x0 y0 s x1 y1 x2 y2 ... c
|
// before: x0 y0 s x1 y1 x2 y2 ... c
|
||||||
// after: x0 y0 s x1 y1 x2 y2 ... x0 y0 x1 y1 x2 y2
|
// after: x0 y0 s x1 y1 x2 y2 ... x0 y0 x1 y1 x2 y2
|
||||||
changes = true;
|
changes = true;
|
||||||
while (changes) {
|
while (changes) {
|
||||||
changes = false;
|
changes = false;
|
||||||
@ -842,10 +842,10 @@ let SubtitleManager = (function() {
|
|||||||
// 3rd degree uniform b-spline
|
// 3rd degree uniform b-spline
|
||||||
// SVG doesn't have this, so we have convert them to a series of
|
// SVG doesn't have this, so we have convert them to a series of
|
||||||
// Bézier curves.
|
// Bézier curves.
|
||||||
// x0 y0 s x1 y1 x2 y2 x3 y3 x4 y4 x5 y5
|
// x0 y0 s x1 y1 x2 y2 x3 y3 x4 y4 x5 y5
|
||||||
// |-----------------------| Bézier 1
|
// |-----------------------| Bézier 1
|
||||||
// |---------------------| Bézier 2
|
// |---------------------| Bézier 2
|
||||||
// |---------------------| Bézier 3
|
// |---------------------| Bézier 3
|
||||||
// Since the start point for a Bézier is different from a spline,
|
// Since the start point for a Bézier is different from a spline,
|
||||||
// we also need to add a move before the first Bézier and after the
|
// we also need to add a move before the first Bézier and after the
|
||||||
// last Bézier. However, the bounding box of b-splines is different
|
// last Bézier. However, the bounding box of b-splines is different
|
||||||
@ -1099,8 +1099,8 @@ let SubtitleManager = (function() {
|
|||||||
let newPieces = [];
|
let newPieces = [];
|
||||||
for (let piece of pieces) {
|
for (let piece of pieces) {
|
||||||
// convert text
|
// convert text
|
||||||
// from "{overide1}some text here{overridde2}more text ..."
|
// from "{overide1}some text here{overridde2}more text ..."
|
||||||
// to [["override1",["some"," ","text"," ","here"]], ["override2",["more"," ","text"]], ...]
|
// to [["override1",["some"," ","text"," ","here"]], ["override2",["more"," ","text"]], ...]
|
||||||
// taking care not to split on non-breaking spaces or paths
|
// taking care not to split on non-breaking spaces or paths
|
||||||
let data = piece.text.split("{").slice(1).map(a => a.split("}")).map(b => [b[0], isPath(b[0]) ? [b[1]] : b[1].split(/([^\S\xA0]+)/g)]);
|
let data = piece.text.split("{").slice(1).map(a => a.split("}")).map(b => [b[0], isPath(b[0]) ? [b[1]] : b[1].split(/([^\S\xA0]+)/g)]);
|
||||||
|
|
||||||
@ -1230,19 +1230,19 @@ let SubtitleManager = (function() {
|
|||||||
if (slice.width) slices.push(slice);
|
if (slice.width) slices.push(slice);
|
||||||
|
|
||||||
// Bubble pieces down through the slices while keeping the constraints:
|
// Bubble pieces down through the slices while keeping the constraints:
|
||||||
// don't make a line shorter than the one after it
|
// don't make a line shorter than the one after it
|
||||||
// don't include whitespace at the start or end
|
// don't include whitespace at the start or end
|
||||||
let bubbled, last_slice = slices.length - 1;
|
let bubbled, last_slice = slices.length - 1;
|
||||||
do {
|
do {
|
||||||
bubbled = false;
|
bubbled = false;
|
||||||
for (let i = last_slice; i > 0; --i) {
|
for (let i = last_slice; i > 0; --i) {
|
||||||
let curr = slices[i], prev = slices[i-1];
|
let curr = slices[i], prev = slices[i-1];
|
||||||
|
|
||||||
/* prev curr
|
/* prev curr
|
||||||
|----------| |--| Before
|
|----------| |--| Before
|
||||||
XXXXXXXX XX XXXX
|
XXXXXXXX XX XXXX
|
||||||
|------| |------| After
|
|------| |------| After
|
||||||
prev curr
|
prev curr
|
||||||
*/
|
*/
|
||||||
while (true) {
|
while (true) {
|
||||||
// Find the next non-whitespace piece
|
// Find the next non-whitespace piece
|
||||||
@ -1376,19 +1376,19 @@ let SubtitleManager = (function() {
|
|||||||
if (slice.width) slices.unshift(slice);
|
if (slice.width) slices.unshift(slice);
|
||||||
|
|
||||||
// Bubble pieces up through the slices while keeping the constraints:
|
// Bubble pieces up through the slices while keeping the constraints:
|
||||||
// don't make a line shorter than the one before it
|
// don't make a line shorter than the one before it
|
||||||
// don't include whitespace at the start or end
|
// don't include whitespace at the start or end
|
||||||
let bubbled, last_slice = slices.length - 1;
|
let bubbled, last_slice = slices.length - 1;
|
||||||
do {
|
do {
|
||||||
bubbled = false;
|
bubbled = false;
|
||||||
for (let i = 0; i < last_slice; ++i) {
|
for (let i = 0; i < last_slice; ++i) {
|
||||||
let curr = slices[i], next = slices[i+1];
|
let curr = slices[i], next = slices[i+1];
|
||||||
|
|
||||||
/* curr next
|
/* curr next
|
||||||
|--| |----------| Before
|
|--| |----------| Before
|
||||||
XXXX XX XXXXXXXX
|
XXXX XX XXXXXXXX
|
||||||
|------| |------| After
|
|------| |------| After
|
||||||
curr next
|
curr next
|
||||||
*/
|
*/
|
||||||
while (true) {
|
while (true) {
|
||||||
// Find the next non-whitespace piece
|
// Find the next non-whitespace piece
|
||||||
@ -2196,8 +2196,8 @@ let SubtitleManager = (function() {
|
|||||||
this.group = null;
|
this.group = null;
|
||||||
|
|
||||||
this.Margin = {"L" : (data.MarginL && parseInt(data.MarginL,10)) || renderer.styles[data.Style].MarginL,
|
this.Margin = {"L" : (data.MarginL && parseInt(data.MarginL,10)) || renderer.styles[data.Style].MarginL,
|
||||||
"R" : (data.MarginR && parseInt(data.MarginR,10)) || renderer.styles[data.Style].MarginR,
|
"R" : (data.MarginR && parseInt(data.MarginR,10)) || renderer.styles[data.Style].MarginR,
|
||||||
"V" : (data.MarginV && parseInt(data.MarginV,10)) || renderer.styles[data.Style].MarginV};
|
"V" : (data.MarginV && parseInt(data.MarginV,10)) || renderer.styles[data.Style].MarginV};
|
||||||
|
|
||||||
this.time = {"start" : timeConvert(data.Start), "end" : timeConvert(data.End)};
|
this.time = {"start" : timeConvert(data.Start), "end" : timeConvert(data.End)};
|
||||||
this.time.milliseconds = (this.time.end - this.time.start) * 1000;
|
this.time.milliseconds = (this.time.end - this.time.start) * 1000;
|
||||||
@ -2982,8 +2982,8 @@ let SubtitleManager = (function() {
|
|||||||
|
|
||||||
// Create the font-face CSS.
|
// Create the font-face CSS.
|
||||||
css += "@font-face {\n";
|
css += "@font-face {\n";
|
||||||
css += " font-family: \"" + fontname + "\";\n";
|
css += " font-family: \"" + fontname + "\";\n";
|
||||||
css += " src: url(data:font/" + submime + ";charset=utf-8;base64," + btoa(fontdata) + ");\n";
|
css += " src: url(data:font/" + submime + ";charset=utf-8;base64," + btoa(fontdata) + ");\n";
|
||||||
css += "}\n\n";
|
css += "}\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,8 +6,8 @@ import { environment } from './environments/environment';
|
|||||||
import "hammerjs"
|
import "hammerjs"
|
||||||
|
|
||||||
if (environment.production) {
|
if (environment.production) {
|
||||||
enableProdMode();
|
enableProdMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
platformBrowserDynamic().bootstrapModule(AppModule)
|
platformBrowserDynamic().bootstrapModule(AppModule)
|
||||||
.catch(err => console.error(err));
|
.catch(err => console.error(err));
|
||||||
|
@ -2,11 +2,11 @@ import { Show } from "./show";
|
|||||||
|
|
||||||
export interface Collection
|
export interface Collection
|
||||||
{
|
{
|
||||||
slug: string;
|
slug: string;
|
||||||
name: string;
|
name: string;
|
||||||
poster: string;
|
poster: string;
|
||||||
overview: string;
|
overview: string;
|
||||||
startYear: number,
|
startYear: number,
|
||||||
endYear: number,
|
endYear: number,
|
||||||
shows: Show[];
|
shows: Show[];
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
export interface Episode
|
export interface Episode
|
||||||
{
|
{
|
||||||
seasonNumber: number;
|
seasonNumber: number;
|
||||||
episodeNumber: number;
|
episodeNumber: number;
|
||||||
title: string;
|
title: string;
|
||||||
thumb: string;
|
thumb: string;
|
||||||
link: string;
|
link: string;
|
||||||
overview: string;
|
overview: string;
|
||||||
releaseDate;
|
releaseDate;
|
||||||
runtime: number;
|
runtime: number;
|
||||||
externalIDs: string;
|
externalIDs: string;
|
||||||
showTitle: string;
|
showTitle: string;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
export interface Genre
|
export interface Genre
|
||||||
{
|
{
|
||||||
slug: string;
|
slug: string;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
export interface People
|
export interface People
|
||||||
{
|
{
|
||||||
slug: string;
|
slug: string;
|
||||||
name: string;
|
name: string;
|
||||||
role: string;
|
role: string;
|
||||||
type: string;
|
type: string;
|
||||||
|
|
||||||
externalIDs: string;
|
externalIDs: string;
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,8 @@ import { Episode } from "./episode";
|
|||||||
|
|
||||||
export interface Season
|
export interface Season
|
||||||
{
|
{
|
||||||
seasonNumber: number;
|
seasonNumber: number;
|
||||||
title: string;
|
title: string;
|
||||||
overview: string;
|
overview: string;
|
||||||
episodes: Episode[];
|
episodes: Episode[];
|
||||||
}
|
}
|
||||||
|
@ -5,20 +5,20 @@ import { Studio } from "./studio";
|
|||||||
|
|
||||||
export interface Show
|
export interface Show
|
||||||
{
|
{
|
||||||
slug: string;
|
slug: string;
|
||||||
title: string;
|
title: string;
|
||||||
Aliases: string[];
|
Aliases: string[];
|
||||||
overview: string;
|
overview: string;
|
||||||
genres: Genre[];
|
genres: Genre[];
|
||||||
status: string;
|
status: string;
|
||||||
studio: Studio;
|
studio: Studio;
|
||||||
people: People[];
|
people: People[];
|
||||||
seasons: Season[];
|
seasons: Season[];
|
||||||
trailerUrl: string;
|
trailerUrl: string;
|
||||||
isCollection: boolean;
|
isCollection: boolean;
|
||||||
|
|
||||||
startYear: number;
|
startYear: number;
|
||||||
endYear : number;
|
endYear : number;
|
||||||
|
|
||||||
externalIDs: string;
|
externalIDs: string;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
export interface Studio
|
export interface Studio
|
||||||
{
|
{
|
||||||
slug: string;
|
slug: string;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -2,31 +2,31 @@ import { Episode } from "./episode";
|
|||||||
|
|
||||||
export interface WatchItem
|
export interface WatchItem
|
||||||
{
|
{
|
||||||
showTitle: string;
|
showTitle: string;
|
||||||
showSlug: string;
|
showSlug: string;
|
||||||
seasonNumber: number;
|
seasonNumber: number;
|
||||||
episodeNumber: number;
|
episodeNumber: number;
|
||||||
title: string;
|
title: string;
|
||||||
link: string;
|
link: string;
|
||||||
duration: number;
|
duration: number;
|
||||||
releaseDate;
|
releaseDate;
|
||||||
|
|
||||||
previousEpisode: string;
|
previousEpisode: string;
|
||||||
nextEpisode: Episode;
|
nextEpisode: Episode;
|
||||||
|
|
||||||
container: string;
|
container: string;
|
||||||
video: Track;
|
video: Track;
|
||||||
audios: Track[];
|
audios: Track[];
|
||||||
subtitles: Track[];
|
subtitles: Track[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Track
|
export interface Track
|
||||||
{
|
{
|
||||||
displayName: string;
|
displayName: string;
|
||||||
title: string;
|
title: string;
|
||||||
language: string;
|
language: string;
|
||||||
isDefault: boolean;
|
isDefault: boolean;
|
||||||
isForced: boolean;
|
isForced: boolean;
|
||||||
codec: string;
|
codec: string;
|
||||||
link: string;
|
link: string;
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
* You can add your own extra polyfills to this file.
|
* You can add your own extra polyfills to this file.
|
||||||
*
|
*
|
||||||
* This file is divided into 2 sections:
|
* This file is divided into 2 sections:
|
||||||
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
|
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
|
||||||
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
|
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
|
||||||
* file.
|
* file.
|
||||||
*
|
*
|
||||||
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
|
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
|
||||||
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
|
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
|
||||||
@ -19,14 +19,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
|
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
|
||||||
// import 'classlist.js'; // Run `npm install --save classlist.js`.
|
// import 'classlist.js'; // Run `npm install --save classlist.js`.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Web Animations `@angular/platform-browser/animations`
|
* Web Animations `@angular/platform-browser/animations`
|
||||||
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
|
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
|
||||||
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
|
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
|
||||||
*/
|
*/
|
||||||
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* By default, zone.js will patch all possible macroTask and DomEvents
|
* By default, zone.js will patch all possible macroTask and DomEvents
|
||||||
@ -45,17 +45,17 @@
|
|||||||
* (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
|
* (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
|
||||||
* (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
|
* (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
|
||||||
*
|
*
|
||||||
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
|
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
|
||||||
* with the following flag, it will bypass `zone.js` patch for IE/Edge
|
* with the following flag, it will bypass `zone.js` patch for IE/Edge
|
||||||
*
|
*
|
||||||
* (window as any).__Zone_enable_cross_context_check = true;
|
* (window as any).__Zone_enable_cross_context_check = true;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/***************************************************************************************************
|
/***************************************************************************************************
|
||||||
* Zone JS is required by default for Angular itself.
|
* Zone JS is required by default for Angular itself.
|
||||||
*/
|
*/
|
||||||
import 'zone.js/dist/zone'; // Included with Angular CLI.
|
import 'zone.js/dist/zone'; // Included with Angular CLI.
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************************************
|
/***************************************************************************************************
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
@import "~bootstrap/scss/variables";
|
@import "~bootstrap/scss/variables";
|
||||||
|
|
||||||
$theme-colors: (
|
$theme-colors: (
|
||||||
"primary": #0a1128,
|
"primary": #0a1128,
|
||||||
"secondary": #000000,
|
"secondary": #000000,
|
||||||
"accentColor": #e23c00,
|
"accentColor": #e23c00,
|
||||||
"textPrimary": #ffffff
|
"textPrimary": #ffffff
|
||||||
);
|
);
|
||||||
|
|
||||||
$body-bg: theme-color("primary");
|
$body-bg: theme-color("primary");
|
||||||
@ -18,12 +18,12 @@ $font-family-base: "Roboto", Arial, sans-serif;
|
|||||||
|
|
||||||
p
|
p
|
||||||
{
|
{
|
||||||
opacity: .6;
|
opacity: .6;
|
||||||
}
|
}
|
||||||
|
|
||||||
h6
|
h6
|
||||||
{
|
{
|
||||||
opacity: .87;
|
opacity: .87;
|
||||||
}
|
}
|
||||||
|
|
||||||
@import "~bootstrap/scss/bootstrap";
|
@import "~bootstrap/scss/bootstrap";
|
||||||
@ -43,63 +43,63 @@ $theme: mat-dark-theme($primary, $accent);
|
|||||||
|
|
||||||
.mat-ripple-element
|
.mat-ripple-element
|
||||||
{
|
{
|
||||||
background-color: rgba(255, 255, 255, .3) !important;
|
background-color: rgba(255, 255, 255, .3) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mat-card-header-text
|
.mat-card-header-text
|
||||||
{
|
{
|
||||||
margin: 0 5px !important;
|
margin: 0 5px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Material Icons
|
//Material Icons
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Material Icons';
|
font-family: 'Material Icons';
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
src: url(/iconfont/MaterialIcons-Regular.eot); /* For IE6-8 */
|
src: url(/iconfont/MaterialIcons-Regular.eot); /* For IE6-8 */
|
||||||
src: local('Material Icons'),
|
src: local('Material Icons'),
|
||||||
local('MaterialIcons-Regular'),
|
local('MaterialIcons-Regular'),
|
||||||
url(/iconfont/MaterialIcons-Regular.woff2) format('woff2'),
|
url(/iconfont/MaterialIcons-Regular.woff2) format('woff2'),
|
||||||
url(/iconfont/MaterialIcons-Regular.woff) format('woff'),
|
url(/iconfont/MaterialIcons-Regular.woff) format('woff'),
|
||||||
url(/iconfont/MaterialIcons-Regular.ttf) format('truetype');
|
url(/iconfont/MaterialIcons-Regular.ttf) format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
.material-icons
|
.material-icons
|
||||||
{
|
{
|
||||||
font-family: 'Material Icons';
|
font-family: 'Material Icons';
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-size: 24px; /* Preferred icon size */
|
font-size: 24px; /* Preferred icon size */
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
text-transform: none;
|
text-transform: none;
|
||||||
letter-spacing: normal;
|
letter-spacing: normal;
|
||||||
word-wrap: normal;
|
word-wrap: normal;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
direction: ltr;
|
direction: ltr;
|
||||||
/* Support for all WebKit browsers. */
|
/* Support for all WebKit browsers. */
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
/* Support for Safari and Chrome. */
|
/* Support for Safari and Chrome. */
|
||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
/* Support for Firefox. */
|
/* Support for Firefox. */
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
/* Support for IE. */
|
/* Support for IE. */
|
||||||
font-feature-settings: 'liga';
|
font-feature-settings: 'liga';
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-icon
|
mat-icon
|
||||||
{
|
{
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.snackError
|
.snackError
|
||||||
{
|
{
|
||||||
background-color: theme-color("accentColor");
|
background-color: theme-color("accentColor");
|
||||||
color: theme-color("textPrimary");
|
color: theme-color("textPrimary");
|
||||||
}
|
}
|
||||||
|
|
||||||
.scroll-row
|
.scroll-row
|
||||||
{
|
{
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
}
|
}
|
||||||
|
@ -3,16 +3,16 @@
|
|||||||
import 'zone.js/dist/zone-testing';
|
import 'zone.js/dist/zone-testing';
|
||||||
import { getTestBed } from '@angular/core/testing';
|
import { getTestBed } from '@angular/core/testing';
|
||||||
import {
|
import {
|
||||||
BrowserDynamicTestingModule,
|
BrowserDynamicTestingModule,
|
||||||
platformBrowserDynamicTesting
|
platformBrowserDynamicTesting
|
||||||
} from '@angular/platform-browser-dynamic/testing';
|
} from '@angular/platform-browser-dynamic/testing';
|
||||||
|
|
||||||
declare const require: any;
|
declare const require: any;
|
||||||
|
|
||||||
// First, initialize the Angular testing environment.
|
// First, initialize the Angular testing environment.
|
||||||
getTestBed().initTestEnvironment(
|
getTestBed().initTestEnvironment(
|
||||||
BrowserDynamicTestingModule,
|
BrowserDynamicTestingModule,
|
||||||
platformBrowserDynamicTesting()
|
platformBrowserDynamicTesting()
|
||||||
);
|
);
|
||||||
// Then we find all the tests.
|
// Then we find all the tests.
|
||||||
const context = require.context('./', true, /\.spec\.ts$/);
|
const context = require.context('./', true, /\.spec\.ts$/);
|
||||||
|
@ -3,157 +3,157 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|||||||
var detect_browser_1 = require("detect-browser");
|
var detect_browser_1 = require("detect-browser");
|
||||||
var method;
|
var method;
|
||||||
(function (method) {
|
(function (method) {
|
||||||
method["direct"] = "Direct Play";
|
method["direct"] = "Direct Play";
|
||||||
method["transmux"] = "Transmux";
|
method["transmux"] = "Transmux";
|
||||||
method["transcode"] = "Transcode";
|
method["transcode"] = "Transcode";
|
||||||
})(method = exports.method || (exports.method = {}));
|
})(method = exports.method || (exports.method = {}));
|
||||||
;
|
;
|
||||||
var SupportList = /** @class */ (function () {
|
var SupportList = /** @class */ (function () {
|
||||||
function SupportList() {
|
function SupportList() {
|
||||||
}
|
}
|
||||||
return SupportList;
|
return SupportList;
|
||||||
}());
|
}());
|
||||||
exports.SupportList = SupportList;
|
exports.SupportList = SupportList;
|
||||||
function getPlaybackMethod(player, item) {
|
function getPlaybackMethod(player, item) {
|
||||||
var supportList = getWhatIsSupported(player, item);
|
var supportList = getWhatIsSupported(player, item);
|
||||||
if (supportList.container) {
|
if (supportList.container) {
|
||||||
if (supportList.videoCodec && supportList.audioCodec)
|
if (supportList.videoCodec && supportList.audioCodec)
|
||||||
return method.direct;
|
return method.direct;
|
||||||
return method.transcode;
|
return method.transcode;
|
||||||
}
|
}
|
||||||
if (supportList.videoCodec && supportList.audioCodec)
|
if (supportList.videoCodec && supportList.audioCodec)
|
||||||
return method.transmux;
|
return method.transmux;
|
||||||
return method.transcode;
|
return method.transcode;
|
||||||
}
|
}
|
||||||
exports.getPlaybackMethod = getPlaybackMethod;
|
exports.getPlaybackMethod = getPlaybackMethod;
|
||||||
function getWhatIsSupported(player, item) {
|
function getWhatIsSupported(player, item) {
|
||||||
var supportList = new SupportList();
|
var supportList = new SupportList();
|
||||||
var browser = detect_browser_1.detect();
|
var browser = detect_browser_1.detect();
|
||||||
if (!browser) {
|
if (!browser) {
|
||||||
supportList.container = false;
|
supportList.container = false;
|
||||||
supportList.videoCodec = false;
|
supportList.videoCodec = false;
|
||||||
supportList.audioCodec = false;
|
supportList.audioCodec = false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
supportList.container = containerIsSupported(player, item.container, browser.name) && item.audios.length <= 1;
|
supportList.container = containerIsSupported(player, item.container, browser.name) && item.audios.length <= 1;
|
||||||
supportList.videoCodec = videoCodecIsSupported(player, item.video.codec, browser.name);
|
supportList.videoCodec = videoCodecIsSupported(player, item.video.codec, browser.name);
|
||||||
supportList.audioCodec = audioCodecIsSupported(player, item.audios.map(function (value) { return value.codec; }), browser.name);
|
supportList.audioCodec = audioCodecIsSupported(player, item.audios.map(function (value) { return value.codec; }), browser.name);
|
||||||
}
|
}
|
||||||
return (supportList);
|
return (supportList);
|
||||||
}
|
}
|
||||||
exports.getWhatIsSupported = getWhatIsSupported;
|
exports.getWhatIsSupported = getWhatIsSupported;
|
||||||
function containerIsSupported(player, container, browser) {
|
function containerIsSupported(player, container, browser) {
|
||||||
var supported = false;
|
var supported = false;
|
||||||
switch (container) {
|
switch (container) {
|
||||||
case "asf":
|
case "asf":
|
||||||
supported = browser == "tizen" || browser == "orsay" || browser == "edge";
|
supported = browser == "tizen" || browser == "orsay" || browser == "edge";
|
||||||
//videoAudioCodecs = [];
|
//videoAudioCodecs = [];
|
||||||
break;
|
break;
|
||||||
case "avi":
|
case "avi":
|
||||||
supported = browser == "tizen" || browser == "orsay" || browser == "edge";
|
supported = browser == "tizen" || browser == "orsay" || browser == "edge";
|
||||||
break;
|
break;
|
||||||
case "mpg":
|
case "mpg":
|
||||||
case "mpeg":
|
case "mpeg":
|
||||||
supported = browser == "tizen" || browser == "orsay" || browser == "edge";
|
supported = browser == "tizen" || browser == "orsay" || browser == "edge";
|
||||||
break;
|
break;
|
||||||
case "flv":
|
case "flv":
|
||||||
supported = browser == "tizen" || browser == "orsay";
|
supported = browser == "tizen" || browser == "orsay";
|
||||||
break;
|
break;
|
||||||
case "3gp":
|
case "3gp":
|
||||||
case "mts":
|
case "mts":
|
||||||
case "trp":
|
case "trp":
|
||||||
case "vob":
|
case "vob":
|
||||||
case "vro":
|
case "vro":
|
||||||
supported = browser == "tizen" || browser == "orsay";
|
supported = browser == "tizen" || browser == "orsay";
|
||||||
break;
|
break;
|
||||||
case "mov":
|
case "mov":
|
||||||
supported = browser == "tizen" || browser == "orsay" || browser == "edge" || browser == "chrome";
|
supported = browser == "tizen" || browser == "orsay" || browser == "edge" || browser == "chrome";
|
||||||
break;
|
break;
|
||||||
case "m2ts":
|
case "m2ts":
|
||||||
supported = browser == "tizen" || browser == "orsay" || browser == "edge";
|
supported = browser == "tizen" || browser == "orsay" || browser == "edge";
|
||||||
break;
|
break;
|
||||||
case "wmv":
|
case "wmv":
|
||||||
supported = browser == "tizen" || browser == "orsay" || browser == "edge";
|
supported = browser == "tizen" || browser == "orsay" || browser == "edge";
|
||||||
//videoAudioCodecs = [];
|
//videoAudioCodecs = [];
|
||||||
break;
|
break;
|
||||||
case "ts":
|
case "ts":
|
||||||
supported = browser == "tizen" || browser == "orsay" || browser == "edge";
|
supported = browser == "tizen" || browser == "orsay" || browser == "edge";
|
||||||
break;
|
break;
|
||||||
case "mp4":
|
case "mp4":
|
||||||
case "m4v":
|
case "m4v":
|
||||||
supported = true;
|
supported = true;
|
||||||
break;
|
break;
|
||||||
case "mkv":
|
case "mkv":
|
||||||
supported = browser == "tizen" || browser == "orsay" || browser == "chrome" || browser == "edge";
|
supported = browser == "tizen" || browser == "orsay" || browser == "chrome" || browser == "edge";
|
||||||
if (supported)
|
if (supported)
|
||||||
break;
|
break;
|
||||||
if (player.canPlayType("video/x-matroska") || player.canPlayType("video/mkv"))
|
if (player.canPlayType("video/x-matroska") || player.canPlayType("video/mkv"))
|
||||||
supported = true;
|
supported = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return supported;
|
return supported;
|
||||||
}
|
}
|
||||||
//SHOULD CHECK FOR DEPTH (8bits ok but 10bits unsuported for almost every browsers)
|
//SHOULD CHECK FOR DEPTH (8bits ok but 10bits unsuported for almost every browsers)
|
||||||
function videoCodecIsSupported(player, codec, browser) {
|
function videoCodecIsSupported(player, codec, browser) {
|
||||||
switch (codec) {
|
switch (codec) {
|
||||||
case "h264":
|
case "h264":
|
||||||
return !!player.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"'); //The !! is used to parse the string as a bool
|
return !!player.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"'); //The !! is used to parse the string as a bool
|
||||||
case "h265":
|
case "h265":
|
||||||
case "hevc":
|
case "hevc":
|
||||||
if (browser == "tizen" || browser == "orsay" || browser == "xboxOne" || browser == "ios")
|
if (browser == "tizen" || browser == "orsay" || browser == "xboxOne" || browser == "ios")
|
||||||
return true;
|
return true;
|
||||||
//SHOULD SUPPORT CHROMECAST ULTRA
|
//SHOULD SUPPORT CHROMECAST ULTRA
|
||||||
// if (browser.chromecast)
|
// if (browser.chromecast)
|
||||||
// {
|
// {
|
||||||
// var isChromecastUltra = userAgent.indexOf('aarch64') !== -1;
|
// var isChromecastUltra = userAgent.indexOf('aarch64') !== -1;
|
||||||
// if (isChromecastUltra)
|
// if (isChromecastUltra)
|
||||||
// {
|
// {
|
||||||
// return true;
|
// return true;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
return !!player.canPlayType('video/hevc; codecs="hevc, aac"');
|
return !!player.canPlayType('video/hevc; codecs="hevc, aac"');
|
||||||
case "mpeg2video":
|
case "mpeg2video":
|
||||||
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
||||||
case "vc1":
|
case "vc1":
|
||||||
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
||||||
case "msmpeg4v2":
|
case "msmpeg4v2":
|
||||||
return browser == "orsay" || browser == "tizen";
|
return browser == "orsay" || browser == "tizen";
|
||||||
case "vp8":
|
case "vp8":
|
||||||
return !!player.canPlayType('video/webm; codecs="vp8');
|
return !!player.canPlayType('video/webm; codecs="vp8');
|
||||||
case "vp9":
|
case "vp9":
|
||||||
return !!player.canPlayType('video/webm; codecs="vp9"');
|
return !!player.canPlayType('video/webm; codecs="vp9"');
|
||||||
case "vorbis":
|
case "vorbis":
|
||||||
return browser == "orsay" || browser == "tizen" || !!player.canPlayType('video/webm; codecs="vp8');
|
return browser == "orsay" || browser == "tizen" || !!player.canPlayType('video/webm; codecs="vp8');
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//SHOULD CHECK FOR NUMBER OF AUDIO CHANNEL (2 ok but 5 not in some browsers)
|
//SHOULD CHECK FOR NUMBER OF AUDIO CHANNEL (2 ok but 5 not in some browsers)
|
||||||
function audioCodecIsSupported(player, codecs, browser) {
|
function audioCodecIsSupported(player, codecs, browser) {
|
||||||
for (var _i = 0, codecs_1 = codecs; _i < codecs_1.length; _i++) {
|
for (var _i = 0, codecs_1 = codecs; _i < codecs_1.length; _i++) {
|
||||||
var codec = codecs_1[_i];
|
var codec = codecs_1[_i];
|
||||||
switch (codec) {
|
switch (codec) {
|
||||||
case "mp3":
|
case "mp3":
|
||||||
return !!player.canPlayType('video/mp4; codecs="avc1.640029, mp4a.69"') ||
|
return !!player.canPlayType('video/mp4; codecs="avc1.640029, mp4a.69"') ||
|
||||||
!!player.canPlayType('video/mp4; codecs="avc1.640029, mp4a.6B"');
|
!!player.canPlayType('video/mp4; codecs="avc1.640029, mp4a.6B"');
|
||||||
case "aac":
|
case "aac":
|
||||||
return !!player.canPlayType('video/mp4; codecs="avc1.640029, mp4a.40.2"');
|
return !!player.canPlayType('video/mp4; codecs="avc1.640029, mp4a.40.2"');
|
||||||
case "mp2":
|
case "mp2":
|
||||||
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
||||||
case "pcm_s16le":
|
case "pcm_s16le":
|
||||||
case "pcm_s24le":
|
case "pcm_s24le":
|
||||||
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
||||||
case "aac_latm":
|
case "aac_latm":
|
||||||
return browser == "orsay" || browser == "tizen";
|
return browser == "orsay" || browser == "tizen";
|
||||||
case "opus":
|
case "opus":
|
||||||
return !!player.canPlayType('audio/ogg; codecs="opus"');
|
return !!player.canPlayType('audio/ogg; codecs="opus"');
|
||||||
case "flac":
|
case "flac":
|
||||||
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//# sourceMappingURL=playbackMethodDetector.js.map
|
//# sourceMappingURL=playbackMethodDetector.js.map
|
@ -121,16 +121,16 @@ function videoCodecIsSupported(player: HTMLVideoElement, codec: string, browser:
|
|||||||
case "hevc":
|
case "hevc":
|
||||||
if (browser == "tizen" || browser == "orsay" || browser == "xboxOne" || browser == "ios")
|
if (browser == "tizen" || browser == "orsay" || browser == "xboxOne" || browser == "ios")
|
||||||
return true;
|
return true;
|
||||||
//SHOULD SUPPORT CHROMECAST ULTRA
|
//SHOULD SUPPORT CHROMECAST ULTRA
|
||||||
// if (browser.chromecast)
|
// if (browser.chromecast)
|
||||||
// {
|
// {
|
||||||
|
|
||||||
// var isChromecastUltra = userAgent.indexOf('aarch64') !== -1;
|
// var isChromecastUltra = userAgent.indexOf('aarch64') !== -1;
|
||||||
// if (isChromecastUltra)
|
// if (isChromecastUltra)
|
||||||
// {
|
// {
|
||||||
// return true;
|
// return true;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
return !!player.canPlayType('video/hevc; codecs="hevc, aac"');
|
return !!player.canPlayType('video/hevc; codecs="hevc, aac"');
|
||||||
case "mpeg2video":
|
case "mpeg2video":
|
||||||
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
||||||
@ -145,7 +145,7 @@ function videoCodecIsSupported(player: HTMLVideoElement, codec: string, browser:
|
|||||||
case "vorbis":
|
case "vorbis":
|
||||||
return browser == "orsay" || browser == "tizen" || !!player.canPlayType('video/webm; codecs="vp8');
|
return browser == "orsay" || browser == "tizen" || !!player.canPlayType('video/webm; codecs="vp8');
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,5 +175,5 @@ function audioCodecIsSupported(player: HTMLVideoElement, codecs: string[], brows
|
|||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user