From d17e598a189182c72aa4c734598f496e61d575d0 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Tue, 17 Sep 2019 18:04:01 +0200 Subject: [PATCH] Reworking player flow with subtitles and end user subtitles. --- .../src/app/browse/browse.component.ts | 2 +- .../src/app/player/player.component.html | 34 ++++++------ .../src/app/player/player.component.scss | 9 +++ .../src/app/player/player.component.ts | 55 ++++++++++--------- .../show-details/show-details.component.html | 2 +- Kyoo/ClientApp/src/models/watch-item.ts | 1 + Kyoo/Controllers/ThumbnailController.cs | 4 +- .../LibraryManager/ILibraryManager.cs | 2 +- .../LibraryManager/LibraryManager.cs | 6 +- Kyoo/Models/Episode.cs | 9 ++- Kyoo/Models/Track.cs | 37 ++++++++++--- Kyoo/Models/WatchItem.cs | 4 +- 12 files changed, 104 insertions(+), 61 deletions(-) diff --git a/Kyoo/ClientApp/src/app/browse/browse.component.ts b/Kyoo/ClientApp/src/app/browse/browse.component.ts index b1527060..40507218 100644 --- a/Kyoo/ClientApp/src/app/browse/browse.component.ts +++ b/Kyoo/ClientApp/src/app/browse/browse.component.ts @@ -30,7 +30,7 @@ export class BrowseComponent implements OnInit getThumb(slug: string) { - return this.sanitizer.bypassSecurityTrustStyle("url(/thumb/" + slug + ")"); + return this.sanitizer.bypassSecurityTrustStyle("url(/poster/" + slug + ")"); } sort(type: string, order: boolean) diff --git a/Kyoo/ClientApp/src/app/player/player.component.html b/Kyoo/ClientApp/src/app/player/player.component.html index 31b77e19..b3345136 100644 --- a/Kyoo/ClientApp/src/app/player/player.component.html +++ b/Kyoo/ClientApp/src/app/player/player.component.html @@ -35,13 +35,13 @@
- +
- - -
- - - - -
+ + + + +
+ diff --git a/Kyoo/ClientApp/src/app/player/player.component.scss b/Kyoo/ClientApp/src/app/player/player.component.scss index 2d5cb8b2..c8f0a84d 100644 --- a/Kyoo/ClientApp/src/app/player/player.component.scss +++ b/Kyoo/ClientApp/src/app/player/player.component.scss @@ -120,6 +120,15 @@ margin-right: .3rem; outline: none; } + + > a + { + margin-left: .3rem; + margin-right: .3rem; + outline: none; + color: inherit; + text-decoration: inherit; + } } } } diff --git a/Kyoo/ClientApp/src/app/player/player.component.ts b/Kyoo/ClientApp/src/app/player/player.component.ts index 227ed1d4..a3d48c3f 100644 --- a/Kyoo/ClientApp/src/app/player/player.component.ts +++ b/Kyoo/ClientApp/src/app/player/player.component.ts @@ -1,6 +1,6 @@ import { Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; import { WatchItem, Track } from "../../models/watch-item"; -import { ActivatedRoute } from "@angular/router"; +import { ActivatedRoute, Router } from "@angular/router"; import { DomSanitizer, Title } from "@angular/platform-browser"; import { Location } from "@angular/common"; import { MatSliderChange } from "@angular/material/slider"; @@ -39,7 +39,7 @@ export class PlayerComponent implements OnInit private progress: HTMLElement; private buffered: HTMLElement; - constructor(private route: ActivatedRoute, private sanitizer: DomSanitizer, private location: Location, private title: Title) { } + constructor(private route: ActivatedRoute, private sanitizer: DomSanitizer, private location: Location, private title: Title, private router: Router) { } ngOnInit() { @@ -192,6 +192,16 @@ export class PlayerComponent implements OnInit } }); + //Load sub selected from the url. + let sub: string = this.route.snapshot.queryParams["sub"]; + if (sub != null) + { + let languageCode: string = sub.substring(0, 3); + let forced: boolean = sub.length > 3 && sub.substring(4) == "for"; + + this.selectSubtitle(this.item.subtitles.find(x => x.language == languageCode && x.isForced == forced), false); + } + $('[data-toggle="tooltip"]').tooltip({ trigger: "hover" }); } @@ -228,11 +238,6 @@ export class PlayerComponent implements OnInit $('[data-toggle="tooltip"]').hide(); } - back() - { - this.location.back(); - } - tooglePlayback() { if (this.player.paused) @@ -293,37 +298,37 @@ export class PlayerComponent implements OnInit } } - selectSubtitle(subtitle: Track) + selectSubtitle(subtitle: Track, changeUrl: boolean = true) { + if (changeUrl) + { + let subSlug: string; + if (subtitle != null) + { + subSlug = subtitle.language; + if (subtitle.isForced) + subSlug += "-for"; + } + + this.router.navigate([], { relativeTo: this.route, queryParams: { sub: subSlug }, replaceUrl: true, queryParamsHandling: "merge" }); + } + this.selectedSubtitle = subtitle; if (subtitle == null) { + console.log("Removing subtitle"); SubtitleManager.remove(this.player); } else { + console.log("Loading subtitle: " + subtitle.displayName); + if (subtitle.codec == "ass") - SubtitleManager.add(this.player, this.getSubtitleLink(subtitle), true); + SubtitleManager.add(this.player, subtitle.link, true); } } - getSubtitleLink(subtitle: Track): string - { - let link: string = "/api/subtitle/" + this.item.link + "." + subtitle.language; - - if (subtitle.isForced) - link += "-forced"; - - //The extension is not necesarry but we add this because it allow the user to quickly download the file in the good format if he wants. - if (subtitle.codec == "ass") - link += ".ass"; - else if (subtitle.codec == "subrip") - link += ".srt" - - return link; - } - getThumb(url: string) { return this.sanitizer.bypassSecurityTrustStyle("url(" + url + ")"); diff --git a/Kyoo/ClientApp/src/app/show-details/show-details.component.html b/Kyoo/ClientApp/src/app/show-details/show-details.component.html index 2e503cef..7fb8ff37 100644 --- a/Kyoo/ClientApp/src/app/show-details/show-details.component.html +++ b/Kyoo/ClientApp/src/app/show-details/show-details.component.html @@ -4,7 +4,7 @@
- +

{{this.show.title}}

diff --git a/Kyoo/ClientApp/src/models/watch-item.ts b/Kyoo/ClientApp/src/models/watch-item.ts index e8b15b3d..68b8e020 100644 --- a/Kyoo/ClientApp/src/models/watch-item.ts +++ b/Kyoo/ClientApp/src/models/watch-item.ts @@ -27,4 +27,5 @@ export interface Track isDefault: boolean; isForced: boolean; codec: string; + link: string; } diff --git a/Kyoo/Controllers/ThumbnailController.cs b/Kyoo/Controllers/ThumbnailController.cs index 4ef0be2b..e250a1f7 100644 --- a/Kyoo/Controllers/ThumbnailController.cs +++ b/Kyoo/Controllers/ThumbnailController.cs @@ -17,7 +17,7 @@ namespace Kyoo.Controllers peoplePath = config.GetValue("peoplePath"); } - [HttpGet("thumb/{showSlug}")] + [HttpGet("poster/{showSlug}")] public IActionResult GetShowThumb(string showSlug) { string path = libraryManager.GetShowBySlug(showSlug)?.Path; @@ -72,7 +72,7 @@ namespace Kyoo.Controllers return new PhysicalFileResult(thumbPath, "image/jpg"); } - [HttpGet("thumb/{showSlug}/s{seasonNumber}/e{episodeNumber}")] + [HttpGet("thumb/{showSlug}-s{seasonNumber}e{episodeNumber}")] public IActionResult GetEpisodeThumb(string showSlug, long seasonNumber, long episodeNumber) { string path = libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber)?.Path; diff --git a/Kyoo/InternalAPI/LibraryManager/ILibraryManager.cs b/Kyoo/InternalAPI/LibraryManager/ILibraryManager.cs index e8f4d933..b5983f0b 100644 --- a/Kyoo/InternalAPI/LibraryManager/ILibraryManager.cs +++ b/Kyoo/InternalAPI/LibraryManager/ILibraryManager.cs @@ -17,7 +17,7 @@ namespace Kyoo.InternalAPI int GetSeasonCount(string showSlug, long seasonNumber); //Internal HTML read - (List audios, List subtitles) GetStreams(long episodeID); + (List audios, List subtitles) GetStreams(long episodeID, string showSlug); Track GetSubtitle(string showSlug, long seasonNumber, long episodeNumber, string languageTag, bool forced); //Public read diff --git a/Kyoo/InternalAPI/LibraryManager/LibraryManager.cs b/Kyoo/InternalAPI/LibraryManager/LibraryManager.cs index 6b81df26..b1d0c967 100644 --- a/Kyoo/InternalAPI/LibraryManager/LibraryManager.cs +++ b/Kyoo/InternalAPI/LibraryManager/LibraryManager.cs @@ -189,7 +189,7 @@ namespace Kyoo.InternalAPI } - public (List audios, List subtitles) GetStreams(long episodeID) + public (List audios, List subtitles) GetStreams(long episodeID, string episodeSlug) { string query = "SELECT * FROM tracks WHERE episodeID = $episodeID;"; @@ -203,7 +203,7 @@ namespace Kyoo.InternalAPI while (reader.Read()) { - Track track = Track.FromReader(reader); + Track track = Track.FromReader(reader).SetLink(episodeSlug); if (track.type == StreamType.Audio) audios.Add(track); @@ -229,7 +229,7 @@ namespace Kyoo.InternalAPI SQLiteDataReader reader = cmd.ExecuteReader(); if (reader.Read()) - return Track.FromReader(reader); + return Track.FromReader(reader).SetLink(Episode.GetSlug(showSlug, seasonNumber, episodeNumber)); return null; } diff --git a/Kyoo/Models/Episode.cs b/Kyoo/Models/Episode.cs index dcd47b61..0548a2ea 100644 --- a/Kyoo/Models/Episode.cs +++ b/Kyoo/Models/Episode.cs @@ -77,9 +77,14 @@ namespace Kyoo.Models public Episode SetThumb(string showSlug) { - Thumb = "thumb/" + showSlug + "/s" + seasonNumber + "/e" + episodeNumber; - Link = showSlug + "-s" + seasonNumber + "e" + episodeNumber; + Link = GetSlug(showSlug, seasonNumber, episodeNumber); + Thumb = "thumb/" + Link; return this; } + + public static string GetSlug(string showSlug, long seasonNumber, long episodeNumber) + { + return showSlug + "-s" + seasonNumber + "e" + episodeNumber; + } } } diff --git a/Kyoo/Models/Track.cs b/Kyoo/Models/Track.cs index 9b1633d6..44ba504a 100644 --- a/Kyoo/Models/Track.cs +++ b/Kyoo/Models/Track.cs @@ -29,6 +29,8 @@ namespace Kyoo.Models public class Track : Stream { public string DisplayName; + public string Link; + [JsonIgnore] public readonly long id; [JsonIgnore] public long episodeID; [JsonIgnore] public StreamType type; @@ -44,14 +46,6 @@ namespace Kyoo.Models Codec = codec; IsExternal = isExternal; Path = path; - - //Converting mkv track language to c# system language tag. - if (language == "fre") - language = "fra"; - - DisplayName = CultureInfo.GetCultures(CultureTypes.NeutralCultures).Where(x => x.ThreeLetterISOLanguageName == language).FirstOrDefault()?.DisplayName ?? language; - if (Title != null && Title.Length > 1) - DisplayName += " - " + Title; } public static Track FromReader(System.Data.SQLite.SQLiteDataReader reader) @@ -75,5 +69,32 @@ namespace Kyoo.Models { return new Track(type, stream.Title, stream.Language, stream.IsDefault, stream.IsForced, stream.Codec, false, stream.Path); } + + public Track SetLink(string episodeSlug) + { + string language = Language; + //Converting mkv track language to c# system language tag. + if (language == "fre") + language = "fra"; + + DisplayName = CultureInfo.GetCultures(CultureTypes.NeutralCultures).Where(x => x.ThreeLetterISOLanguageName == language).FirstOrDefault()?.DisplayName ?? language; + Link = "/api/subtitle/" + episodeSlug + "." + Language; + + if (IsForced) + { + DisplayName += " Forced"; + Link += "-forced"; + } + + if (Title != null && Title.Length > 1) + DisplayName += " - " + Title; + + if (Codec == "ass") + Link += ".ass"; + else if (Codec == "subrip") + Link += ".srt"; + + return this; + } } } \ No newline at end of file diff --git a/Kyoo/Models/WatchItem.cs b/Kyoo/Models/WatchItem.cs index 8041f288..8c4afab9 100644 --- a/Kyoo/Models/WatchItem.cs +++ b/Kyoo/Models/WatchItem.cs @@ -37,7 +37,7 @@ namespace Kyoo.Models ReleaseDate = releaseDate; Path = path; - Link = ShowSlug + "-s" + seasonNumber + "e" + episodeNumber; + Link = Episode.GetSlug(ShowSlug, seasonNumber, episodeNumber); } public WatchItem(long episodeID, string showTitle, string showSlug, long seasonNumber, long episodeNumber, string title, DateTime? releaseDate, string path, Track[] audios, Track[] subtitles) : this(episodeID, showTitle, showSlug, seasonNumber, episodeNumber, title, releaseDate, path) @@ -60,7 +60,7 @@ namespace Kyoo.Models public WatchItem SetStreams(ILibraryManager libraryManager) { - (IEnumerable audios, IEnumerable subtitles) streams = libraryManager.GetStreams(episodeID); + (IEnumerable audios, IEnumerable subtitles) streams = libraryManager.GetStreams(episodeID, Link); audios = streams.audios; subtitles = streams.subtitles; return this;