diff --git a/back/src/Kyoo.Abstractions/Models/Resources/Interfaces/IThumbnails.cs b/back/src/Kyoo.Abstractions/Models/Resources/Interfaces/IThumbnails.cs
index e3454fc1..72a6d455 100644
--- a/back/src/Kyoo.Abstractions/Models/Resources/Interfaces/IThumbnails.cs
+++ b/back/src/Kyoo.Abstractions/Models/Resources/Interfaces/IThumbnails.cs
@@ -20,6 +20,7 @@ using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
+using Kyoo.Abstractions.Models.Attributes;
namespace Kyoo.Abstractions.Models
{
@@ -59,6 +60,24 @@ namespace Kyoo.Abstractions.Models
[MaxLength(32)]
public string Blurhash { get; set; }
+ [SerializeIgnore]
+ public string Path { private get; set; }
+
+ ///
+ /// The url to retrieve the low quality image.
+ ///
+ public string Low => $"{Path}?quality=low";
+
+ ///
+ /// The url to retrieve the medium quality image.
+ ///
+ public string Medium => $"{Path}?quality=medium";
+
+ ///
+ /// The url to retrieve the high quality image.
+ ///
+ public string High => $"{Path}?quality=high";
+
public Image(string source, string? blurhash = null)
{
Source = source;
diff --git a/back/src/Kyoo.Core/Controllers/Repositories/CollectionRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/CollectionRepository.cs
index f5d19bc3..ca90cec7 100644
--- a/back/src/Kyoo.Core/Controllers/Repositories/CollectionRepository.cs
+++ b/back/src/Kyoo.Core/Controllers/Repositories/CollectionRepository.cs
@@ -53,11 +53,12 @@ namespace Kyoo.Core.Controllers
///
public override async Task> Search(string query)
{
- return await Sort(
+ return (await Sort(
_database.Collections
.Where(_database.Like(x => x.Name + " " + x.Slug, $"%{query}%"))
.Take(20)
- ).ToListAsync();
+ ).ToListAsync())
+ .Select(SetBackingImageSelf).ToList();
}
///
diff --git a/back/src/Kyoo.Core/Controllers/Repositories/EpisodeRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/EpisodeRepository.cs
index 5fba8395..19c5b839 100644
--- a/back/src/Kyoo.Core/Controllers/Repositories/EpisodeRepository.cs
+++ b/back/src/Kyoo.Core/Controllers/Repositories/EpisodeRepository.cs
@@ -79,7 +79,7 @@ namespace Kyoo.Core.Controllers
{
return _database.Episodes.FirstOrDefaultAsync(x => x.ShowId == showID
&& x.SeasonNumber == seasonNumber
- && x.EpisodeNumber == episodeNumber);
+ && x.EpisodeNumber == episodeNumber).Then(SetBackingImage);
}
///
@@ -87,7 +87,7 @@ namespace Kyoo.Core.Controllers
{
return _database.Episodes.FirstOrDefaultAsync(x => x.Show.Slug == showSlug
&& x.SeasonNumber == seasonNumber
- && x.EpisodeNumber == episodeNumber);
+ && x.EpisodeNumber == episodeNumber).Then(SetBackingImage);
}
///
@@ -112,14 +112,14 @@ namespace Kyoo.Core.Controllers
public Task GetAbsolute(int showID, int absoluteNumber)
{
return _database.Episodes.FirstOrDefaultAsync(x => x.ShowId == showID
- && x.AbsoluteNumber == absoluteNumber);
+ && x.AbsoluteNumber == absoluteNumber).Then(SetBackingImage);
}
///
public Task GetAbsolute(string showSlug, int absoluteNumber)
{
return _database.Episodes.FirstOrDefaultAsync(x => x.Show.Slug == showSlug
- && x.AbsoluteNumber == absoluteNumber);
+ && x.AbsoluteNumber == absoluteNumber).Then(SetBackingImage);
}
///
@@ -134,7 +134,10 @@ namespace Kyoo.Core.Controllers
.Take(20)
.ToListAsync();
foreach (Episode ep in ret)
+ {
ep.Show.Episodes = null;
+ SetBackingImage(ep);
+ }
return ret;
}
diff --git a/back/src/Kyoo.Core/Controllers/Repositories/LibraryItemRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/LibraryItemRepository.cs
index 0a6350f8..87a28f24 100644
--- a/back/src/Kyoo.Core/Controllers/Repositories/LibraryItemRepository.cs
+++ b/back/src/Kyoo.Core/Controllers/Repositories/LibraryItemRepository.cs
@@ -24,6 +24,7 @@ using System.Threading.Tasks;
using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models;
using Kyoo.Postgresql;
+using Kyoo.Utils;
using Microsoft.EntityFrameworkCore;
namespace Kyoo.Core.Controllers
@@ -54,13 +55,19 @@ namespace Kyoo.Core.Controllers
///
public override async Task GetOrDefault(int id)
{
- return await _database.LibraryItems.FirstOrDefaultAsync(x => x.Id == id);
+ return await _database.LibraryItems.SingleOrDefaultAsync(x => x.Id == id).Then(SetBackingImage);
}
///
public override async Task GetOrDefault(string slug)
{
- return await _database.LibraryItems.SingleOrDefaultAsync(x => x.Slug == slug);
+ return await _database.LibraryItems.SingleOrDefaultAsync(x => x.Slug == slug).Then(SetBackingImage);
+ }
+
+ ///
+ public override async Task GetOrDefault(Expression> where, Sort sortBy = default)
+ {
+ return await Sort(_database.LibraryItems, sortBy).FirstOrDefaultAsync(where).Then(SetBackingImage);
}
///
@@ -68,7 +75,8 @@ namespace Kyoo.Core.Controllers
Sort sort = default,
Pagination limit = default)
{
- return await ApplyFilters(_database.LibraryItems, where, sort, limit);
+ return (await ApplyFilters(_database.LibraryItems, where, sort, limit))
+ .Select(SetBackingImageSelf).ToList();
}
///
@@ -83,12 +91,14 @@ namespace Kyoo.Core.Controllers
///
public override async Task> Search(string query)
{
- return await Sort(
+ return (await Sort(
_database.LibraryItems
.Where(_database.Like(x => x.Name, $"%{query}%"))
)
.Take(20)
- .ToListAsync();
+ .ToListAsync())
+ .Select(SetBackingImageSelf)
+ .ToList();
}
///
@@ -100,7 +110,7 @@ namespace Kyoo.Core.Controllers
=> throw new InvalidOperationException();
///
- public override Task Edit(ILibraryItem obj)
+ public override Task Edit(ILibraryItem edited)
=> throw new InvalidOperationException();
///
diff --git a/back/src/Kyoo.Core/Controllers/Repositories/LocalRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/LocalRepository.cs
index 5c3340d8..a079abc3 100644
--- a/back/src/Kyoo.Core/Controllers/Repositories/LocalRepository.cs
+++ b/back/src/Kyoo.Core/Controllers/Repositories/LocalRepository.cs
@@ -30,7 +30,6 @@ using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Core.Api;
using Kyoo.Utils;
using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.ChangeTracking;
namespace Kyoo.Core.Controllers
{
@@ -227,6 +226,28 @@ namespace Kyoo.Core.Controllers
return Expression.Lambda>(filter!, x);
}
+ protected void SetBackingImage(T obj)
+ {
+ if (obj is not IThumbnails thumbs)
+ return;
+ string type = obj is ILibraryItem item
+ ? item.Kind.ToString().ToLowerInvariant()
+ : typeof(T).Name.ToLowerInvariant();
+
+ if (thumbs.Poster != null)
+ thumbs.Poster.Path = $"{type}/{obj.Slug}/poster";
+ if (thumbs.Thumbnail != null)
+ thumbs.Thumbnail.Path = $"{type}/{obj.Slug}/thumbnail";
+ if (thumbs.Logo != null)
+ thumbs.Logo.Path = $"{type}/{obj.Slug}/logo";
+ }
+
+ protected T SetBackingImageSelf(T obj)
+ {
+ SetBackingImage(obj);
+ return obj;
+ }
+
///
/// Get a resource from it's ID and make the instance track it.
///
@@ -236,6 +257,7 @@ namespace Kyoo.Core.Controllers
protected virtual async Task GetWithTracking(int id)
{
T ret = await Database.Set().AsTracking().FirstOrDefaultAsync(x => x.Id == id);
+ SetBackingImage(ret);
if (ret == null)
throw new ItemNotFoundException($"No {typeof(T).Name} found with the id {id}");
return ret;
@@ -271,30 +293,31 @@ namespace Kyoo.Core.Controllers
///
public virtual Task GetOrDefault(int id)
{
- return Database.Set().FirstOrDefaultAsync(x => x.Id == id);
+ return Database.Set().FirstOrDefaultAsync(x => x.Id == id).Then(SetBackingImage);
}
///
public virtual Task GetOrDefault(string slug)
{
- return Database.Set().FirstOrDefaultAsync(x => x.Slug == slug);
+ return Database.Set().FirstOrDefaultAsync(x => x.Slug == slug).Then(SetBackingImage);
}
///
public virtual Task GetOrDefault(Expression> where, Sort sortBy = default)
{
- return Sort(Database.Set(), sortBy).FirstOrDefaultAsync(where);
+ return Sort(Database.Set(), sortBy).FirstOrDefaultAsync(where).Then(SetBackingImage);
}
///
public abstract Task> Search(string query);
///
- public virtual Task> GetAll(Expression> where = null,
+ public virtual async Task> GetAll(Expression> where = null,
Sort sort = default,
Pagination limit = default)
{
- return ApplyFilters(Database.Set(), where, sort, limit);
+ return (await ApplyFilters(Database.Set(), where, sort, limit))
+ .Select(SetBackingImageSelf).ToList();
}
///
@@ -349,6 +372,7 @@ namespace Kyoo.Core.Controllers
if (thumbs.Logo != null)
Database.Entry(thumbs).Reference(x => x.Logo).TargetEntry.State = EntityState.Added;
}
+ SetBackingImage(obj);
return obj;
}
@@ -400,6 +424,7 @@ namespace Kyoo.Core.Controllers
await EditRelations(old, edited);
await Database.SaveChangesAsync();
OnEdited?.Invoke(old);
+ SetBackingImage(old);
return old;
}
finally
@@ -423,6 +448,7 @@ namespace Kyoo.Core.Controllers
await Database.SaveChangesAsync();
OnEdited?.Invoke(resource);
+ SetBackingImage(resource);
return resource;
}
finally
diff --git a/back/src/Kyoo.Core/Controllers/Repositories/MovieRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/MovieRepository.cs
index cc5f89eb..49f315bb 100644
--- a/back/src/Kyoo.Core/Controllers/Repositories/MovieRepository.cs
+++ b/back/src/Kyoo.Core/Controllers/Repositories/MovieRepository.cs
@@ -69,12 +69,14 @@ namespace Kyoo.Core.Controllers
public override async Task> Search(string query)
{
query = $"%{query}%";
- return await Sort(
+ return (await Sort(
_database.Movies
.Where(_database.Like(x => x.Name + " " + x.Slug, query))
)
.Take(20)
- .ToListAsync();
+ .ToListAsync())
+ .Select(SetBackingImageSelf)
+ .ToList();
}
///
diff --git a/back/src/Kyoo.Core/Controllers/Repositories/PeopleRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/PeopleRepository.cs
index a01b2c4f..c7cdcbda 100644
--- a/back/src/Kyoo.Core/Controllers/Repositories/PeopleRepository.cs
+++ b/back/src/Kyoo.Core/Controllers/Repositories/PeopleRepository.cs
@@ -63,12 +63,14 @@ namespace Kyoo.Core.Controllers
///
public override async Task> Search(string query)
{
- return await Sort(
+ return (await Sort(
_database.People
.Where(_database.Like(x => x.Name, $"%{query}%"))
)
.Take(20)
- .ToListAsync();
+ .ToListAsync())
+ .Select(SetBackingImageSelf)
+ .ToList();
}
///
diff --git a/back/src/Kyoo.Core/Controllers/Repositories/SeasonRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/SeasonRepository.cs
index d9d41d2c..e7aed032 100644
--- a/back/src/Kyoo.Core/Controllers/Repositories/SeasonRepository.cs
+++ b/back/src/Kyoo.Core/Controllers/Repositories/SeasonRepository.cs
@@ -24,6 +24,7 @@ using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Postgresql;
+using Kyoo.Utils;
using Microsoft.EntityFrameworkCore;
namespace Kyoo.Core.Controllers
@@ -87,25 +88,27 @@ namespace Kyoo.Core.Controllers
public Task GetOrDefault(int showID, int seasonNumber)
{
return _database.Seasons.FirstOrDefaultAsync(x => x.ShowId == showID
- && x.SeasonNumber == seasonNumber);
+ && x.SeasonNumber == seasonNumber).Then(SetBackingImage);
}
///
public Task GetOrDefault(string showSlug, int seasonNumber)
{
return _database.Seasons.FirstOrDefaultAsync(x => x.Show.Slug == showSlug
- && x.SeasonNumber == seasonNumber);
+ && x.SeasonNumber == seasonNumber).Then(SetBackingImage);
}
///
public override async Task> Search(string query)
{
- return await Sort(
+ return (await Sort(
_database.Seasons
.Where(_database.Like(x => x.Name, $"%{query}%"))
)
.Take(20)
- .ToListAsync();
+ .ToListAsync())
+ .Select(SetBackingImageSelf)
+ .ToList();
}
///
diff --git a/back/src/Kyoo.Core/Controllers/Repositories/ShowRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/ShowRepository.cs
index 0a829e0f..065202ee 100644
--- a/back/src/Kyoo.Core/Controllers/Repositories/ShowRepository.cs
+++ b/back/src/Kyoo.Core/Controllers/Repositories/ShowRepository.cs
@@ -70,12 +70,14 @@ namespace Kyoo.Core.Controllers
public override async Task> Search(string query)
{
query = $"%{query}%";
- return await Sort(
+ return (await Sort(
_database.Shows
.Where(_database.Like(x => x.Name + " " + x.Slug, query))
)
.Take(20)
- .ToListAsync();
+ .ToListAsync())
+ .Select(SetBackingImageSelf)
+ .ToList();
}
///
diff --git a/back/src/Kyoo.Core/Controllers/Repositories/StudioRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/StudioRepository.cs
index 536accba..22201c74 100644
--- a/back/src/Kyoo.Core/Controllers/Repositories/StudioRepository.cs
+++ b/back/src/Kyoo.Core/Controllers/Repositories/StudioRepository.cs
@@ -16,7 +16,6 @@
// 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;
@@ -54,12 +53,14 @@ namespace Kyoo.Core.Controllers
///
public override async Task> Search(string query)
{
- return await Sort(
+ return (await Sort(
_database.Studios
.Where(_database.Like(x => x.Name, $"%{query}%"))
)
.Take(20)
- .ToListAsync();
+ .ToListAsync())
+ .Select(SetBackingImageSelf)
+ .ToList();
}
///
diff --git a/back/src/Kyoo.Core/Controllers/Repositories/UserRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/UserRepository.cs
index c91c8a49..2fcecb8a 100644
--- a/back/src/Kyoo.Core/Controllers/Repositories/UserRepository.cs
+++ b/back/src/Kyoo.Core/Controllers/Repositories/UserRepository.cs
@@ -16,7 +16,6 @@
// 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;
@@ -53,12 +52,14 @@ namespace Kyoo.Core.Controllers
///
public override async Task> Search(string query)
{
- return await Sort(
+ return (await Sort(
_database.Users
.Where(_database.Like(x => x.Username, $"%{query}%"))
)
.Take(20)
- .ToListAsync();
+ .ToListAsync())
+ .Select(SetBackingImageSelf)
+ .ToList();
}
///