mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Adding thumbnails management (downloading, checking local versions...)
Finishing the browse/library tab of the web app.
This commit is contained in:
parent
fe649df033
commit
edc5def19a
@ -1,7 +1,7 @@
|
||||
<div>
|
||||
<div class="container justify-content-center">
|
||||
<a class="show" *ngFor="let show of this.shows" routerLink="/shows/{{show.slug}}">
|
||||
<img src="{{show.imgPrimary}}" />
|
||||
<p>{{show.title}}</p>
|
||||
<img [style.background-image]="getThumb(show.slug)"/>
|
||||
<p class="title">{{show.title}}</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>
|
||||
</a>
|
||||
|
@ -2,14 +2,20 @@
|
||||
@import "~bootstrap/scss/variables";
|
||||
@import "~bootstrap/scss//mixins/breakpoints";
|
||||
|
||||
.container
|
||||
{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.show
|
||||
{
|
||||
width: 33%;
|
||||
list-style: none;
|
||||
padding: 1em;
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
outline: none;
|
||||
|
||||
@include media-breakpoint-up(md)
|
||||
{
|
||||
@ -26,10 +32,26 @@
|
||||
width: 18%;
|
||||
}
|
||||
|
||||
&:focus, &:hover
|
||||
{
|
||||
> img
|
||||
{
|
||||
outline: solid var(--accentColor);
|
||||
}
|
||||
|
||||
> .title
|
||||
{
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
> img
|
||||
{
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
width: 100%;
|
||||
height: 0;
|
||||
padding-top: 147.0588%;
|
||||
background-size: cover;
|
||||
background-color: #333333;
|
||||
}
|
||||
|
||||
> p
|
||||
@ -39,6 +61,12 @@
|
||||
text-overflow: ellipsis;
|
||||
text-align: center;
|
||||
margin-bottom: 0px;
|
||||
|
||||
&.date
|
||||
{
|
||||
opacity: 0.8;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover
|
||||
@ -46,9 +74,3 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.date
|
||||
{
|
||||
opacity: 0.8;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { DomSanitizer, SafeStyle } from '@angular/platform-browser';
|
||||
|
||||
@Component({
|
||||
selector: 'app-browse',
|
||||
@ -13,7 +14,7 @@ export class BrowseComponent implements OnInit
|
||||
|
||||
private watch: any;
|
||||
|
||||
constructor(private http: HttpClient, private route: ActivatedRoute) { }
|
||||
constructor(private http: HttpClient, private route: ActivatedRoute, private sanitizer: DomSanitizer) {}
|
||||
|
||||
ngOnInit()
|
||||
{
|
||||
@ -42,4 +43,9 @@ export class BrowseComponent implements OnInit
|
||||
{
|
||||
this.watch.unsubscribe();
|
||||
}
|
||||
|
||||
getThumb(slug: string)
|
||||
{
|
||||
return this.sanitizer.bypassSecurityTrustStyle("url(/thumb/" + slug + ")");
|
||||
}
|
||||
}
|
||||
|
@ -1 +1,2 @@
|
||||
<p>Should display show details of: {{this.show.title}}</p>
|
||||
<p *ngIf="this.show; else elseBlock">Should display show details of: {{this.show.title}}</p>
|
||||
<ng-template #elseBlock>Loading</ng-template>
|
||||
|
25
Kyoo/Controllers/ThumbnailController.cs
Normal file
25
Kyoo/Controllers/ThumbnailController.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using Kyoo.InternalAPI;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
|
||||
// For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
|
||||
|
||||
namespace Kyoo.Controllers
|
||||
{
|
||||
public class ThumbnailController : Controller
|
||||
{
|
||||
private ILibraryManager libraryManager;
|
||||
|
||||
public ThumbnailController(ILibraryManager libraryManager)
|
||||
{
|
||||
this.libraryManager = libraryManager;
|
||||
}
|
||||
|
||||
[HttpGet("thumb/{showSlug}")]
|
||||
public IActionResult GetShowThumb(string showSlug)
|
||||
{
|
||||
string thumbPath = libraryManager.GetShowBySlug(showSlug).ImgPrimary;
|
||||
return new PhysicalFileResult(thumbPath, "image/jpg");
|
||||
}
|
||||
}
|
||||
}
|
@ -42,7 +42,7 @@ namespace Kyoo.InternalAPI
|
||||
|
||||
public async void Scan(string folderPath)
|
||||
{
|
||||
string[] files = Directory.GetFiles(folderPath);
|
||||
string[] files = Directory.GetFiles(folderPath, "*", SearchOption.AllDirectories);
|
||||
|
||||
foreach (string file in files)
|
||||
{
|
||||
@ -133,10 +133,9 @@ namespace Kyoo.InternalAPI
|
||||
seasonID = libraryManager.RegisterSeason(season);
|
||||
}
|
||||
|
||||
Episode episode = await metadataProvider.GetEpisode(showProviderIDs, seasonNumber, episodeNumber);
|
||||
Episode episode = await metadataProvider.GetEpisode(showProviderIDs, seasonNumber, episodeNumber, path);
|
||||
episode.ShowID = showID;
|
||||
episode.SeasonID = seasonID;
|
||||
episode.Path = path;
|
||||
libraryManager.RegisterEpisode(episode);
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,6 @@ namespace Kyoo.InternalAPI
|
||||
Task<string> GetSeasonImage(string showName, long seasonNumber);
|
||||
|
||||
//For the episodes
|
||||
Task<Episode> GetEpisode(string externalIDs, long seasonNumber, long episodeNumber);
|
||||
Task<Episode> GetEpisode(string externalIDs, long seasonNumber, long episodeNumber, string episodePath);
|
||||
}
|
||||
}
|
||||
|
@ -269,7 +269,7 @@ namespace Kyoo.InternalAPI.MetadataProvider
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<Episode> GetEpisode(string externalIDs, long seasonNumber, long episodeNumber)
|
||||
public async Task<Episode> GetEpisode(string externalIDs, long seasonNumber, long episodeNumber, string episodePath)
|
||||
{
|
||||
string id = GetID(externalIDs);
|
||||
|
||||
|
@ -1,9 +1,11 @@
|
||||
using Kyoo.InternalAPI.MetadataProvider;
|
||||
using Kyoo.InternalAPI.ThumbnailsManager;
|
||||
using Kyoo.Models;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@ -12,10 +14,12 @@ namespace Kyoo.InternalAPI
|
||||
public class ProviderManager : IMetadataProvider
|
||||
{
|
||||
private readonly List<IMetadataProvider> providers = new List<IMetadataProvider>();
|
||||
private readonly IThumbnailsManager thumbnailsManager;
|
||||
private readonly IConfiguration config;
|
||||
|
||||
public ProviderManager(IConfiguration configuration)
|
||||
public ProviderManager(IThumbnailsManager thumbnailsManager, IConfiguration configuration)
|
||||
{
|
||||
this.thumbnailsManager = thumbnailsManager;
|
||||
config = configuration;
|
||||
LoadProviders();
|
||||
}
|
||||
@ -58,12 +62,21 @@ namespace Kyoo.InternalAPI
|
||||
}
|
||||
}
|
||||
|
||||
//public Show MergeShows(Show baseShow, Show newShow)
|
||||
//{
|
||||
public Show Merge(IEnumerable<Show> shows)
|
||||
{
|
||||
return shows.FirstOrDefault();
|
||||
}
|
||||
|
||||
//}
|
||||
public Season Merge(IEnumerable<Season> seasons)
|
||||
{
|
||||
return seasons.FirstOrDefault();
|
||||
}
|
||||
|
||||
public Episode Merge(IEnumerable<Episode> episodes)
|
||||
{
|
||||
return episodes.FirstOrDefault();
|
||||
}
|
||||
|
||||
|
||||
//For all the following methods, it should use all providers and merge the data.
|
||||
|
||||
public Task<Show> GetImages(Show show)
|
||||
@ -71,34 +84,69 @@ namespace Kyoo.InternalAPI
|
||||
return providers[0].GetImages(show);
|
||||
}
|
||||
|
||||
public Task<Season> GetSeason(string showName, int seasonNumber)
|
||||
public async Task<Season> GetSeason(string showName, int seasonNumber)
|
||||
{
|
||||
return providers[0].GetSeason(showName, seasonNumber);
|
||||
List<Season> datas = new List<Season>();
|
||||
for (int i = 0; i < providers.Count; i++)
|
||||
{
|
||||
datas.Add(await providers[i].GetSeason(showName, seasonNumber));
|
||||
}
|
||||
|
||||
return Merge(datas);
|
||||
}
|
||||
|
||||
public Task<Show> GetShowByID(string id)
|
||||
public async Task<Show> GetShowByID(string id)
|
||||
{
|
||||
return providers[0].GetShowByID(id);
|
||||
List<Show> datas = new List<Show>();
|
||||
for (int i = 0; i < providers.Count; i++)
|
||||
{
|
||||
datas.Add(await providers[i].GetShowByID(id));
|
||||
}
|
||||
|
||||
return Merge(datas);
|
||||
}
|
||||
|
||||
public Task<Show> GetShowFromName(string showName, string showPath)
|
||||
public async Task<Show> GetShowFromName(string showName, string showPath)
|
||||
{
|
||||
return providers[0].GetShowFromName(showName, showPath);
|
||||
List<Show> datas = new List<Show>();
|
||||
for (int i = 0; i < providers.Count; i++)
|
||||
{
|
||||
datas.Add(await providers[i].GetShowFromName(showName, showPath));
|
||||
}
|
||||
|
||||
Show show = Merge(datas);
|
||||
return thumbnailsManager.Validate(show);
|
||||
}
|
||||
|
||||
public Task<Season> GetSeason(string showName, long seasonNumber)
|
||||
public async Task<Season> GetSeason(string showName, long seasonNumber)
|
||||
{
|
||||
return providers[0].GetSeason(showName, seasonNumber);
|
||||
List<Season> datas = new List<Season>();
|
||||
for (int i = 0; i < providers.Count; i++)
|
||||
{
|
||||
datas.Add(await providers[i].GetSeason(showName, seasonNumber));
|
||||
}
|
||||
|
||||
return Merge(datas);
|
||||
}
|
||||
|
||||
public Task<string> GetSeasonImage(string showName, long seasonNumber)
|
||||
{
|
||||
//Should select the best provider for this show.
|
||||
|
||||
return providers[0].GetSeasonImage(showName, seasonNumber);
|
||||
}
|
||||
|
||||
public Task<Episode> GetEpisode(string externalIDs, long seasonNumber, long episodeNumber)
|
||||
public async Task<Episode> GetEpisode(string externalIDs, long seasonNumber, long episodeNumber, string episodePath)
|
||||
{
|
||||
return providers[0].GetEpisode(externalIDs, seasonNumber, episodeNumber);
|
||||
List<Episode> datas = new List<Episode>();
|
||||
for (int i = 0; i < providers.Count; i++)
|
||||
{
|
||||
datas.Add(await providers[i].GetEpisode(externalIDs, seasonNumber, episodeNumber, episodePath));
|
||||
}
|
||||
|
||||
Episode episode = Merge(datas);
|
||||
episode.Path = episodePath;
|
||||
return thumbnailsManager.Validate(episode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
10
Kyoo/InternalAPI/ThumbnailsManager/IThumbnailsManager.cs
Normal file
10
Kyoo/InternalAPI/ThumbnailsManager/IThumbnailsManager.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using Kyoo.Models;
|
||||
|
||||
namespace Kyoo.InternalAPI.ThumbnailsManager
|
||||
{
|
||||
public interface IThumbnailsManager
|
||||
{
|
||||
Show Validate(Show show);
|
||||
Episode Validate(Episode episode);
|
||||
}
|
||||
}
|
40
Kyoo/InternalAPI/ThumbnailsManager/ThumbnailsManager.cs
Normal file
40
Kyoo/InternalAPI/ThumbnailsManager/ThumbnailsManager.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using Kyoo.Models;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
|
||||
namespace Kyoo.InternalAPI.ThumbnailsManager
|
||||
{
|
||||
public class ThumbnailsManager : IThumbnailsManager
|
||||
{
|
||||
public Show Validate(Show show)
|
||||
{
|
||||
string localThumb = Path.Combine(show.Path, "poster.jpg");
|
||||
if (!File.Exists(localThumb))
|
||||
{
|
||||
using (WebClient client = new WebClient())
|
||||
{
|
||||
client.DownloadFileAsync(new Uri(show.ImgPrimary), localThumb);
|
||||
}
|
||||
}
|
||||
|
||||
show.ImgPrimary = localThumb;
|
||||
return show;
|
||||
}
|
||||
|
||||
public Episode Validate(Episode episode)
|
||||
{
|
||||
string localThumb = Path.ChangeExtension(episode.Path, "jpg");
|
||||
if (!File.Exists(localThumb))
|
||||
{
|
||||
using (WebClient client = new WebClient())
|
||||
{
|
||||
client.DownloadFileAsync(new Uri(episode.ImgPrimary), localThumb);
|
||||
}
|
||||
}
|
||||
|
||||
episode.ImgPrimary = localThumb;
|
||||
return episode;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
using Kyoo.InternalAPI;
|
||||
using Kyoo.InternalAPI.MetadataProvider;
|
||||
using Kyoo.InternalAPI.ThumbnailsManager;
|
||||
using Kyoo.Models;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
@ -7,6 +8,7 @@ using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.SpaServices.AngularCli;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using System.Diagnostics;
|
||||
using System.Web.Http;
|
||||
|
||||
@ -32,8 +34,12 @@ namespace Kyoo
|
||||
configuration.RootPath = "ClientApp/dist";
|
||||
});
|
||||
|
||||
//Services needed in the private and in the public API
|
||||
services.AddSingleton<ILibraryManager, LibraryManager>();
|
||||
|
||||
//Services used to get informations about files and register them
|
||||
services.AddHostedService<Crawler>();
|
||||
services.AddSingleton<IThumbnailsManager, ThumbnailsManager>();
|
||||
services.AddSingleton<IMetadataProvider, ProviderManager>();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user