diff --git a/Kyoo/ClientApp/src/app/app-routing.module.ts b/Kyoo/ClientApp/src/app/app-routing.module.ts
index 67153c0e..723a2f82 100644
--- a/Kyoo/ClientApp/src/app/app-routing.module.ts
+++ b/Kyoo/ClientApp/src/app/app-routing.module.ts
@@ -14,7 +14,7 @@ const routes: Routes = [
{ path: "browse", component: BrowseComponent, pathMatch: "full", resolve: { shows: LibraryResolverService } },
{ path: "browse/:library-slug", component: BrowseComponent, resolve: { shows: LibraryResolverService } },
{ path: "show/:show-slug", component: ShowDetailsComponent, resolve: { show: ShowResolverService } },
- { path: "watch/:item", component: PlayerComponent, resolve: { show: StreamResolverService } },
+ { path: "watch/:item", component: PlayerComponent, resolve: { item: StreamResolverService }, runGuardsAndResolvers: "always" },
{ path: "**", component: NotFoundComponent }
];
diff --git a/Kyoo/ClientApp/src/app/player/player.component.html b/Kyoo/ClientApp/src/app/player/player.component.html
index 76f9f38f..36e26e12 100644
--- a/Kyoo/ClientApp/src/app/player/player.component.html
+++ b/Kyoo/ClientApp/src/app/player/player.component.html
@@ -1 +1,58 @@
-
player works!
+
+
+
+
+
+
+
+
{{this.item.showTitle}}
+
+
+
+
+

+
+
+
S{{this.item.seasonNumber}}:E{{this.item.episodeNumber}} - {{this.item.title}}
+
+
+
+
+
diff --git a/Kyoo/ClientApp/src/app/player/player.component.scss b/Kyoo/ClientApp/src/app/player/player.component.scss
index e69de29b..796ca57d 100644
--- a/Kyoo/ClientApp/src/app/player/player.component.scss
+++ b/Kyoo/ClientApp/src/app/player/player.component.scss
@@ -0,0 +1,116 @@
+.player
+{
+ position: fixed;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background: #000;
+
+ > video
+ {
+ width: 100%;
+ height: 100%;
+ object-fit: contain;
+ }
+}
+
+.back
+{
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ background: rgba(0, 0, 0, 0.6);
+ padding: .33%;
+ display: flex;
+
+ > button
+ {
+ outline: none;
+ }
+
+ > h5
+ {
+ margin: 0;
+ margin-left: .5rem;
+ align-self: center;
+ }
+}
+
+.controller
+{
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background: rgba(0, 0, 0, 0.6);
+ display: flex;
+ padding: 1%;
+
+ .img
+ {
+ width: 15%;
+ position: relative;
+ height: auto;
+
+ > img
+ {
+ width: 100%;
+ height: auto;
+ bottom: 0;
+ position: absolute;
+ }
+ }
+
+ .content
+ {
+ width: 100%;
+ margin-left: 1rem;
+ display: flex;
+ flex-direction: column;
+
+ > mat-progress-bar
+ {
+ width: 100%;
+ height: 2px;
+ margin-top: 1rem;
+ margin-bottom: 1rem;
+ }
+
+ .buttons
+ {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+
+ > div
+ {
+ &.left
+ {
+ align-self: start;
+ display: flex;
+
+ > p
+ {
+ margin: 0;
+ margin-left: 1rem;
+ align-self: center;
+ }
+ }
+
+ &.right
+ {
+ align-self: end;
+ }
+
+ > button
+ {
+ margin-left: .3rem;
+ margin-right: .3rem;
+ outline: none;
+ }
+ }
+ }
+ }
+}
diff --git a/Kyoo/ClientApp/src/app/player/player.component.ts b/Kyoo/ClientApp/src/app/player/player.component.ts
index 99e54ecf..fa6a1871 100644
--- a/Kyoo/ClientApp/src/app/player/player.component.ts
+++ b/Kyoo/ClientApp/src/app/player/player.component.ts
@@ -1,21 +1,93 @@
import { Component, OnInit } from '@angular/core';
+import { WatchItem } from "../../models/watch-item";
+import { ActivatedRoute } from "@angular/router";
+import { DomSanitizer } from "@angular/platform-browser";
+import { Location } from "@angular/common";
@Component({
selector: 'app-player',
templateUrl: './player.component.html',
styleUrls: ['./player.component.scss']
})
-export class PlayerComponent implements OnInit {
+export class PlayerComponent implements OnInit
+{
+ item: WatchItem;
+ video: string;
- constructor() { }
+ playIcon: string = "pause"; //Icon used by the play btn.
+ fullscreenIcon: string = "fullscreen"; //Icon used by the fullscreen btn.
+
+ private player: HTMLVideoElement;
+
+ constructor(private route: ActivatedRoute, private location: Location)
+ {
+ this.video = this.route.snapshot.paramMap.get("item");
+ }
ngOnInit()
{
document.getElementById("nav").classList.add("d-none");
+ this.item = this.route.snapshot.data.item;
+ console.log("Init");
+ }
+
+ ngAfterViewInit()
+ {
+ this.player = document.getElementById("player") as HTMLVideoElement;
+ this.player.controls = false;
+
+ $('[data-toggle="tooltip"]').tooltip();
+
+ document.addEventListener("fullscreenchange", (event) =>
+ {
+ if (document.fullscreenElement != null)
+ {
+ this.fullscreenIcon = "fullscreen_exit";
+ $("#fullscreen").attr("data-original-title", "Exit fullscreen").tooltip("show");
+ }
+ else
+ {
+ this.fullscreenIcon = "fullscreen";
+ $("#fullscreen").attr("data-original-title", "Fullscreen").tooltip("show");
+ }
+ });
}
ngOnDestroy()
{
document.getElementById("nav").classList.remove("d-none");
}
+
+ back()
+ {
+ this.location.back();
+ }
+
+ tooglePlayback()
+ {
+ let playBtn: HTMLElement = document.getElementById("play");
+
+ if (this.player.paused)
+ {
+ this.player.play();
+
+ this.playIcon = "pause"
+ $(playBtn).attr("data-original-title", "Pause").tooltip("show");
+ }
+ else
+ {
+ this.player.pause();
+
+ this.playIcon = "play_arrow"
+ $(playBtn).attr("data-original-title", "Play").tooltip("show");
+ }
+ }
+
+ fullscreen()
+ {
+ if (document.fullscreenElement == null)
+ document.getElementById("root").requestFullscreen();
+ else
+ document.exitFullscreen();
+ }
}
diff --git a/Kyoo/ClientApp/src/models/watch-item.js b/Kyoo/ClientApp/src/models/watch-item.js
new file mode 100644
index 00000000..d9a9328a
--- /dev/null
+++ b/Kyoo/ClientApp/src/models/watch-item.js
@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=watch-item.js.map
\ No newline at end of file
diff --git a/Kyoo/ClientApp/src/models/watch-item.js.map b/Kyoo/ClientApp/src/models/watch-item.js.map
new file mode 100644
index 00000000..3fe37e3b
--- /dev/null
+++ b/Kyoo/ClientApp/src/models/watch-item.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"watch-item.js","sourceRoot":"","sources":["watch-item.ts"],"names":[],"mappings":""}
\ No newline at end of file
diff --git a/Kyoo/ClientApp/src/models/watch-item.ts b/Kyoo/ClientApp/src/models/watch-item.ts
new file mode 100644
index 00000000..eaa07a55
--- /dev/null
+++ b/Kyoo/ClientApp/src/models/watch-item.ts
@@ -0,0 +1,20 @@
+export interface WatchItem
+{
+ showTitle: string;
+ showSlug: string;
+ seasonNumber: number;
+ episodeNumber: number;
+ title: string;
+ releaseDate;
+ audio: Stream[];
+ subtitles: Stream[];
+}
+
+export interface Stream
+{
+ title: string;
+ language: string;
+ isDefault: boolean;
+ isForced: boolean;
+ format: string;
+}
diff --git a/Kyoo/InternalAPI/LibraryManager/LibraryManager.cs b/Kyoo/InternalAPI/LibraryManager/LibraryManager.cs
index ea7fdd92..be3958fd 100644
--- a/Kyoo/InternalAPI/LibraryManager/LibraryManager.cs
+++ b/Kyoo/InternalAPI/LibraryManager/LibraryManager.cs
@@ -305,7 +305,7 @@ namespace Kyoo.InternalAPI
public WatchItem GetWatchItem(string showSlug, long seasonNumber, long episodeNumber)
{
- string query = "SELECT episodes.id, shows.title as showTitle, seasonNumber, episodeNumber, episodes.title, releaseDate, episodes.path FROM episodes JOIN shows ON shows.id = episodes.showID WHERE shows.slug = $showSlug AND episodes.seasonNumber = $seasonNumber AND episodes.episodeNumber = $episodeNumber;";
+ string query = "SELECT episodes.id, shows.title as showTitle, shows.slug as showSlug, seasonNumber, episodeNumber, episodes.title, releaseDate, episodes.path FROM episodes JOIN shows ON shows.id = episodes.showID WHERE shows.slug = $showSlug AND episodes.seasonNumber = $seasonNumber AND episodes.episodeNumber = $episodeNumber;";
using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection))
{
diff --git a/Kyoo/Kyoo.csproj b/Kyoo/Kyoo.csproj
index faff7919..0a2a60e7 100644
--- a/Kyoo/Kyoo.csproj
+++ b/Kyoo/Kyoo.csproj
@@ -31,6 +31,7 @@
+
@@ -69,6 +70,7 @@
+
diff --git a/Kyoo/Models/WatchItem.cs b/Kyoo/Models/WatchItem.cs
index 73af1397..52e1dc48 100644
--- a/Kyoo/Models/WatchItem.cs
+++ b/Kyoo/Models/WatchItem.cs
@@ -11,6 +11,7 @@ namespace Kyoo.Models
[JsonIgnore] public readonly long episodeID;
public string ShowTitle;
+ public string ShowSlug;
public long seasonNumber;
public long episodeNumber;
public string Title;
@@ -23,10 +24,11 @@ namespace Kyoo.Models
public WatchItem() { }
- public WatchItem(long episodeID, string showTitle, long seasonNumber, long episodeNumber, string title, DateTime? releaseDate, string path)
+ public WatchItem(long episodeID, string showTitle, string showSlug, long seasonNumber, long episodeNumber, string title, DateTime? releaseDate, string path)
{
this.episodeID = episodeID;
ShowTitle = showTitle;
+ ShowSlug = showSlug;
this.seasonNumber = seasonNumber;
this.episodeNumber = episodeNumber;
Title = title;
@@ -34,7 +36,7 @@ namespace Kyoo.Models
Path = path;
}
- public WatchItem(long episodeID, string showTitle, long seasonNumber, long episodeNumber, string title, DateTime? releaseDate, string path, Stream[] audios, Stream[] subtitles) : this(episodeID, showTitle, seasonNumber, episodeNumber, title, releaseDate, path)
+ public WatchItem(long episodeID, string showTitle, string showSlug, long seasonNumber, long episodeNumber, string title, DateTime? releaseDate, string path, Stream[] audios, Stream[] subtitles) : this(episodeID, showTitle, showSlug, seasonNumber, episodeNumber, title, releaseDate, path)
{
this.audios = audios;
this.subtitles = subtitles;
@@ -44,6 +46,7 @@ namespace Kyoo.Models
{
return new WatchItem((long)reader["id"],
reader["showTitle"] as string,
+ reader["showSlug"] as string,
(long)reader["seasonNumber"],
(long)reader["episodeNumber"],
reader["title"] as string,