From 48ae67168bab3863ccdd654aa10e89389b1184b6 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sat, 16 Apr 2022 18:11:09 +0200 Subject: [PATCH] Updating the front for the new font api --- README.md | 1 - docker-compose.yml | 1 - front/projects/host/src/app/models/font.ts | 5 + .../src/app/pages/player/player.component.ts | 25 ++-- .../host/src/app/services/api.service.ts | 11 +- src/Kyoo.Core/Views/Resources/EpisodeApi.cs | 6 +- .../Kyoo.Tests/Transcoder/TranscoderTests.cs | 110 ++++++++++++++++++ 7 files changed, 135 insertions(+), 24 deletions(-) create mode 100644 front/projects/host/src/app/models/font.ts create mode 100644 tests/Kyoo.Tests/Transcoder/TranscoderTests.cs diff --git a/README.md b/README.md index 9c1b965a..983e9f05 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,6 @@ services: environment: - KYOO_DATADIR=/var/lib/kyoo - BASICS__PUBLICURL=https://demo.kyoo.moe - - BASICS__MetadataInShow=false - DATABASE__ENABLED=postgres - DATABASE__CONFIGURATIONS__POSTGRES__SERVER=postgres - DATABASE__CONFIGURATIONS__POSTGRES__USER ID=kyoo diff --git a/docker-compose.yml b/docker-compose.yml index ed6b8c58..313392e8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,7 +7,6 @@ services: environment: - KYOO_DATADIR=/var/lib/kyoo - BASICS__PUBLICURL=http://localhost:5000 - - BASICS__MetadataInShow=false - DATABASE__ENABLED=postgres - DATABASE__CONFIGURATIONS__POSTGRES__SERVER=postgres - DATABASE__CONFIGURATIONS__POSTGRES__USER ID=kyoo diff --git a/front/projects/host/src/app/models/font.ts b/front/projects/host/src/app/models/font.ts new file mode 100644 index 00000000..9f2e93e5 --- /dev/null +++ b/front/projects/host/src/app/models/font.ts @@ -0,0 +1,5 @@ +export interface Font { + slug: string; + file: string; + format: string; +} diff --git a/front/projects/host/src/app/pages/player/player.component.ts b/front/projects/host/src/app/pages/player/player.component.ts index c53be96f..f41e3907 100644 --- a/front/projects/host/src/app/pages/player/player.component.ts +++ b/front/projects/host/src/app/pages/player/player.component.ts @@ -15,7 +15,7 @@ import { DomSanitizer, Title } from "@angular/platform-browser"; import { ActivatedRoute, Event, NavigationCancel, NavigationEnd, NavigationStart, Router } from "@angular/router"; import { OidcSecurityService } from "angular-auth-oidc-client"; import Hls from "hls.js"; -import { ShowService } from "../../services/api.service"; +import { EpisodeService, ShowService } from "../../services/api.service"; import { StartupService } from "../../services/startup.service"; import { getWhatIsSupported, @@ -24,6 +24,7 @@ import { } from "./playbackMethodDetector"; import { AppComponent } from "../../app.component"; import { Track, WatchItem } from "../../models/watch-item"; +import { Font } from "../../models/font"; import SubtitlesOctopus from "libass-wasm/dist/js/subtitles-octopus.js"; import MouseMoveEvent = JQuery.MouseMoveEvent; import TouchMoveEvent = JQuery.TouchMoveEvent; @@ -161,13 +162,12 @@ export class PlayerComponent implements OnInit, OnDestroy, AfterViewInit private hlsPlayer: Hls = new Hls(); private oidcSecurity: OidcSecurityService; constructor(private route: ActivatedRoute, - private sanitizer: DomSanitizer, private snackBar: MatSnackBar, private title: Title, private router: Router, private location: Location, private injector: Injector, - private shows: ShowService, + private episode: EpisodeService, private startup: StartupService) { } @@ -481,18 +481,13 @@ export class PlayerComponent implements OnInit, OnDestroy, AfterViewInit if (subtitle.codec === "ass") { - if (!this.subtitlesManager) - { - const fonts: { [key: string]: string } = await this.shows.getFonts(this.item.showSlug).toPromise(); - this.subtitlesManager = new SubtitlesOctopus({ - video: this.player, - subUrl: `subtitle/${subtitle.slug}`, - fonts: Object.values(fonts), - renderMode: "fast" - }); - } - else - this.subtitlesManager.setTrackByUrl(`subtitle/${subtitle.slug}`); + const fonts: Font[] = await this.episode.getFonts(this.item.slug).toPromise(); + this.subtitlesManager = new SubtitlesOctopus({ + video: this.player, + subUrl: `subtitle/${subtitle.slug}`, + fonts: fonts.map(x => `/api/episode/${this.item.slug}/font/${x.slug}.${x.format}`), + renderMode: "fast" + }); } else if (subtitle.codec === "subrip") { diff --git a/front/projects/host/src/app/services/api.service.ts b/front/projects/host/src/app/services/api.service.ts index 33d18b53..a15aa042 100644 --- a/front/projects/host/src/app/services/api.service.ts +++ b/front/projects/host/src/app/services/api.service.ts @@ -9,6 +9,7 @@ import { LibraryItem } from "../models/resources/library-item"; import { map } from "rxjs/operators"; import { Season } from "../models/resources/season"; import { Episode } from "../models/resources/episode"; +import { Font } from "../models/font"; import { People } from "../models/resources/people"; import { Show } from "../models/resources/show"; import { Studio } from "../models/resources/studio"; @@ -126,6 +127,11 @@ export class EpisodeService extends CrudApi return this.client.get(`/api/seasons/${show}-s${seasonNumber}/episodes${this.ArgsAsQuery(args)}`) .pipe(map(x => Object.assign(new Page(), x))); } + + getFonts(id: string | number): Observable + { + return this.client.get(`/api/episodes/${id}/fonts`); + } } @Injectable({ @@ -177,11 +183,6 @@ export class ShowService extends CrudApi return this.client.get>(`/api/collections/${collection}/shows${this.ArgsAsQuery(args)}`) .pipe(map(x => Object.assign(new Page(), x))); } - - getFonts(id: string | number): Observable<{[font: string]: string}> - { - return this.client.get(`/api/shows/${id}/fonts`); - } } @Injectable({ diff --git a/src/Kyoo.Core/Views/Resources/EpisodeApi.cs b/src/Kyoo.Core/Views/Resources/EpisodeApi.cs index 0d8d2267..cd568e91 100644 --- a/src/Kyoo.Core/Views/Resources/EpisodeApi.cs +++ b/src/Kyoo.Core/Views/Resources/EpisodeApi.cs @@ -207,8 +207,8 @@ namespace Kyoo.Core.Api /// The slug of the font to retrieve. /// A page of collections. /// No show with the given ID/slug could be found or the font does not exist. - [HttpGet("{identifier:id}/fonts/{font}")] - [HttpGet("{identifier:id}/font/{font}", Order = AlternativeRoute)] + [HttpGet("{identifier:id}/fonts/{slug}")] + [HttpGet("{identifier:id}/font/{slug}", Order = AlternativeRoute)] [PartialPermission(Kind.Read)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] @@ -220,6 +220,8 @@ namespace Kyoo.Core.Api ); if (episode == null) return NotFound(); + if (slug.Contains('.')) + slug = slug[..slug.LastIndexOf('.')]; Font font = await _transcoder.GetFont(episode, slug); if (font == null) return NotFound(); diff --git a/tests/Kyoo.Tests/Transcoder/TranscoderTests.cs b/tests/Kyoo.Tests/Transcoder/TranscoderTests.cs new file mode 100644 index 00000000..63aaee57 --- /dev/null +++ b/tests/Kyoo.Tests/Transcoder/TranscoderTests.cs @@ -0,0 +1,110 @@ +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Kyoo.Abstractions.Controllers; +using Kyoo.Abstractions.Models; +using Kyoo.Core.Controllers; +using Kyoo.Core.Models.Options; +using Kyoo.Utils; +using Microsoft.Extensions.Options; +using Moq; +using Xunit; +using Xunit.Abstractions; + +using KTranscoder = Kyoo.Core.Controllers.Transcoder; + +namespace Kyoo.Tests.Transcoder +{ + public class TranscoderTests + { + private readonly Mock _files; + private readonly ITranscoder _transcoder; + + public TranscoderTests(ITestOutputHelper output) + { + _files = new Mock(); + _transcoder = new KTranscoder( + _files.Object, + Options.Create(new BasicOptions()), + output.BuildLoggerFor() + ); + } + + [Fact] + public async Task ListFontsTest() + { + Episode episode = TestSample.Get(); + _files.Setup(x => x.ListFiles(It.IsAny(), System.IO.SearchOption.TopDirectoryOnly)) + .ReturnsAsync(new[] { "font.ttf", "font.TTF", "toto.ttf" }); + ICollection fonts = await _transcoder.ListFonts(episode); + List fontsFiles = fonts.Select(x => x.File).ToList(); + Assert.Equal(3, fonts.Count); + Assert.Contains("font.TTF", fontsFiles); + Assert.Contains("font.ttf", fontsFiles); + Assert.Contains("toto.ttf", fontsFiles); + } + + [Fact] + public async Task GetNoFontTest() + { + Episode episode = TestSample.Get(); + _files.Setup(x => x.GetExtraDirectory(It.IsAny())) + .ReturnsAsync("/path"); + _files.Setup(x => x.ListFiles(It.IsAny(), System.IO.SearchOption.TopDirectoryOnly)) + .ReturnsAsync(new[] { "font.ttf", "font.TTF", "toto.ttf" }); + Font font = await _transcoder.GetFont(episode, "toto.ttf"); + Assert.Null(font); + } + + [Fact] + public async Task GetFontTest() + { + Episode episode = TestSample.Get(); + _files.Setup(x => x.GetExtraDirectory(It.IsAny())) + .ReturnsAsync("/path"); + _files.Setup(x => x.ListFiles(It.IsAny(), System.IO.SearchOption.TopDirectoryOnly)) + .ReturnsAsync(new[] { "/path/font.ttf", "/path/font.TTF", "/path/toto.ttf" }); + Font font = await _transcoder.GetFont(episode, "toto"); + Assert.NotNull(font); + Assert.Equal("toto.ttf", font.File); + Assert.Equal("toto", font.Slug); + Assert.Equal("ttf", font.Format); + Assert.Equal("/path/toto.ttf", font.Path); + } + + [Fact] + public async Task GetFontNoExtensionTest() + { + Episode episode = TestSample.Get(); + _files.Setup(x => x.GetExtraDirectory(It.IsAny())) + .ReturnsAsync("/path"); + _files.Setup(x => x.ListFiles(It.IsAny(), System.IO.SearchOption.TopDirectoryOnly)) + .ReturnsAsync(new[] { "/path/font", "/path/toto.ttf" }); + Font font = await _transcoder.GetFont(episode, "font"); + Assert.NotNull(font); + Assert.Equal("font", font.File); + Assert.Equal("font", font.Slug); + Assert.Equal("", font.Format); + Assert.Equal("/path/font", font.Path); + } + } +}