diff --git a/back/src/Kyoo.Abstractions/Models/Resources/Interfaces/IThumbnails.cs b/back/src/Kyoo.Abstractions/Models/Resources/Interfaces/IThumbnails.cs index 5095dfe4..2bbffa72 100644 --- a/back/src/Kyoo.Abstractions/Models/Resources/Interfaces/IThumbnails.cs +++ b/back/src/Kyoo.Abstractions/Models/Resources/Interfaces/IThumbnails.cs @@ -17,12 +17,9 @@ // along with Kyoo. If not, see . using System; -using System.ComponentModel; using System.ComponentModel.DataAnnotations; -using System.Globalization; using System.Text.Json; using System.Text.Json.Serialization; -using Kyoo.Abstractions.Models.Attributes; namespace Kyoo.Abstractions.Models; @@ -49,9 +46,13 @@ public interface IThumbnails } [JsonConverter(typeof(ImageConvertor))] -[SqlFirstColumn(nameof(Source))] public class Image { + /// + /// A unique identifier for the image. Used for proper http caches. + /// + public Guid Id { get; set; } + /// /// The original image from another server. /// @@ -63,6 +64,21 @@ public class Image [MaxLength(32)] public string Blurhash { get; set; } + /// + /// The url to access the image in low quality. + /// + public string Low => $"/thumbnails/{Id}?quality=low"; + + /// + /// The url to access the image in medium quality. + /// + public string Medium => $"/thumbnails/{Id}?quality=medium"; + + /// + /// The url to access the image in high quality. + /// + public string High => $"/thumbnails/{Id}?quality=high"; + public Image() { } [JsonConstructor] @@ -97,6 +113,9 @@ public class Image writer.WriteStartObject(); writer.WriteString("source", value.Source); writer.WriteString("blurhash", value.Blurhash); + writer.WriteString("low", value.Low); + writer.WriteString("medium", value.Medium); + writer.WriteString("high", value.High); writer.WriteEndObject(); } } diff --git a/back/src/Kyoo.Abstractions/Utility/JsonKindResolver.cs b/back/src/Kyoo.Abstractions/Utility/JsonKindResolver.cs index 45cdfdaa..db72f7e2 100644 --- a/back/src/Kyoo.Abstractions/Utility/JsonKindResolver.cs +++ b/back/src/Kyoo.Abstractions/Utility/JsonKindResolver.cs @@ -25,7 +25,6 @@ using System.Text.Json; using System.Text.Json.Serialization.Metadata; using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models.Attributes; -using Microsoft.AspNetCore.Http; using static System.Text.Json.JsonNamingPolicy; namespace Kyoo.Utils; diff --git a/back/src/Kyoo.Core/Controllers/Repositories/DapperHelper.cs b/back/src/Kyoo.Core/Controllers/Repositories/DapperHelper.cs index f98e84ce..19383169 100644 --- a/back/src/Kyoo.Core/Controllers/Repositories/DapperHelper.cs +++ b/back/src/Kyoo.Core/Controllers/Repositories/DapperHelper.cs @@ -252,7 +252,7 @@ public static class DapperHelper this IDbConnection db, FormattableString command, Dictionary config, - Func, T> mapper, + Func, T> mapper, Func> get, SqlVariableContext context, Include? include, @@ -327,23 +327,6 @@ public static class DapperHelper ? ExpendProjections(typeV, prefix, include) : null; - if (typeV.IsAssignableTo(typeof(IThumbnails))) - { - string posterProj = string.Join( - ", ", - new[] { "poster", "thumbnail", "logo" }.Select(x => - $"{prefix}{x}_source as source, {prefix}{x}_blurhash as blurhash" - ) - ); - projection = string.IsNullOrEmpty(projection) - ? posterProj - : $"{projection}, {posterProj}"; - types.InsertRange( - types.IndexOf(typeV) + 1, - Enumerable.Repeat(typeof(Image), 3) - ); - } - if (string.IsNullOrEmpty(projection)) return leadingComa; return $", {projection}{leadingComa}"; @@ -355,19 +338,7 @@ public static class DapperHelper types.ToArray(), items => { - List nItems = new(items.Length); - for (int i = 0; i < items.Length; i++) - { - if (types[i] == typeof(Image)) - continue; - nItems.Add(items[i]); - if (items[i] is not IThumbnails thumbs) - continue; - thumbs.Poster = items[++i] as Image; - thumbs.Thumbnail = items[++i] as Image; - thumbs.Logo = items[++i] as Image; - } - return mapIncludes(mapper(nItems), nItems.Skip(config.Count)); + return mapIncludes(mapper(items), items.Skip(config.Count)); }, ParametersDictionary.LoadFrom(cmd), splitOn: string.Join( @@ -384,7 +355,7 @@ public static class DapperHelper this IDbConnection db, FormattableString command, Dictionary config, - Func, T> mapper, + Func, T> mapper, SqlVariableContext context, Include? include, Filter? filter, diff --git a/back/src/Kyoo.Core/Controllers/Repositories/DapperRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/DapperRepository.cs index 18f0677b..7c37d79d 100644 --- a/back/src/Kyoo.Core/Controllers/Repositories/DapperRepository.cs +++ b/back/src/Kyoo.Core/Controllers/Repositories/DapperRepository.cs @@ -37,7 +37,7 @@ public abstract class DapperRepository : IRepository protected abstract Dictionary Config { get; } - protected abstract T Mapper(List items); + protected abstract T Mapper(IList items); protected DbConnection Database { get; init; } diff --git a/back/src/Kyoo.Core/Controllers/Repositories/LibraryItemRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/LibraryItemRepository.cs index 958f12ca..9da7cc99 100644 --- a/back/src/Kyoo.Core/Controllers/Repositories/LibraryItemRepository.cs +++ b/back/src/Kyoo.Core/Controllers/Repositories/LibraryItemRepository.cs @@ -67,7 +67,7 @@ public class LibraryItemRepository : DapperRepository { "c", typeof(Collection) } }; - protected override ILibraryItem Mapper(List items) + protected override ILibraryItem Mapper(IList items) { if (items[0] is Show show && show.Id != Guid.Empty) return show; diff --git a/back/src/Kyoo.Core/Controllers/Repositories/NewsRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/NewsRepository.cs index f55cb31a..c91c2eed 100644 --- a/back/src/Kyoo.Core/Controllers/Repositories/NewsRepository.cs +++ b/back/src/Kyoo.Core/Controllers/Repositories/NewsRepository.cs @@ -49,7 +49,7 @@ public class NewsRepository : DapperRepository protected override Dictionary Config => new() { { "e", typeof(Episode) }, { "m", typeof(Movie) }, }; - protected override INews Mapper(List items) + protected override INews Mapper(IList items) { if (items[0] is Episode episode && episode.Id != Guid.Empty) return episode; diff --git a/back/src/Kyoo.Core/Controllers/Repositories/WatchStatusRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/WatchStatusRepository.cs index e3137616..3159cbfb 100644 --- a/back/src/Kyoo.Core/Controllers/Repositories/WatchStatusRepository.cs +++ b/back/src/Kyoo.Core/Controllers/Repositories/WatchStatusRepository.cs @@ -135,7 +135,7 @@ public class WatchStatusRepository( { "_mw", typeof(MovieWatchStatus) }, }; - protected IWatchlist Mapper(List items) + protected IWatchlist Mapper(IList items) { if (items[0] is Show show && show.Id != Guid.Empty) { diff --git a/back/src/Kyoo.Postgresql/DatabaseContext.cs b/back/src/Kyoo.Postgresql/DatabaseContext.cs index 31e7b40f..320021d3 100644 --- a/back/src/Kyoo.Postgresql/DatabaseContext.cs +++ b/back/src/Kyoo.Postgresql/DatabaseContext.cs @@ -201,9 +201,9 @@ public abstract class DatabaseContext : DbContext private static void _HasImages(ModelBuilder modelBuilder) where T : class, IThumbnails { - modelBuilder.Entity().OwnsOne(x => x.Poster); - modelBuilder.Entity().OwnsOne(x => x.Thumbnail); - modelBuilder.Entity().OwnsOne(x => x.Logo); + modelBuilder.Entity().OwnsOne(x => x.Poster, x => x.ToJson()); + modelBuilder.Entity().OwnsOne(x => x.Thumbnail, x => x.ToJson()); + modelBuilder.Entity().OwnsOne(x => x.Logo, x => x.ToJson()); } private static void _HasAddedDate(ModelBuilder modelBuilder) diff --git a/back/src/Kyoo.Postgresql/PostgresContext.cs b/back/src/Kyoo.Postgresql/PostgresContext.cs index f907accd..8052fdcc 100644 --- a/back/src/Kyoo.Postgresql/PostgresContext.cs +++ b/back/src/Kyoo.Postgresql/PostgresContext.cs @@ -94,6 +94,7 @@ public class PostgresContext(DbContextOptions options, IHttpContextAccessor acce typeof(Dictionary), new JsonTypeHandler>() ); + SqlMapper.AddTypeHandler(typeof(Image), new JsonTypeHandler()); SqlMapper.AddTypeHandler(typeof(List), new ListTypeHandler()); SqlMapper.AddTypeHandler(typeof(List), new ListTypeHandler()); SqlMapper.AddTypeHandler(typeof(Wrapper), new Wrapper.Handler());