Add low/medium/high image link on every images

This commit is contained in:
Zoe Roux 2023-08-09 12:52:06 +09:00
parent 090f305f02
commit 60afaf6211
No known key found for this signature in database
11 changed files with 104 additions and 34 deletions

View File

@ -20,6 +20,7 @@ using System;
using System.ComponentModel; using System.ComponentModel;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Globalization; using System.Globalization;
using Kyoo.Abstractions.Models.Attributes;
namespace Kyoo.Abstractions.Models namespace Kyoo.Abstractions.Models
{ {
@ -59,6 +60,24 @@ namespace Kyoo.Abstractions.Models
[MaxLength(32)] [MaxLength(32)]
public string Blurhash { get; set; } public string Blurhash { get; set; }
[SerializeIgnore]
public string Path { private get; set; }
/// <summary>
/// The url to retrieve the low quality image.
/// </summary>
public string Low => $"{Path}?quality=low";
/// <summary>
/// The url to retrieve the medium quality image.
/// </summary>
public string Medium => $"{Path}?quality=medium";
/// <summary>
/// The url to retrieve the high quality image.
/// </summary>
public string High => $"{Path}?quality=high";
public Image(string source, string? blurhash = null) public Image(string source, string? blurhash = null)
{ {
Source = source; Source = source;

View File

@ -53,11 +53,12 @@ namespace Kyoo.Core.Controllers
/// <inheritdoc /> /// <inheritdoc />
public override async Task<ICollection<Collection>> Search(string query) public override async Task<ICollection<Collection>> Search(string query)
{ {
return await Sort( return (await Sort(
_database.Collections _database.Collections
.Where(_database.Like<Collection>(x => x.Name + " " + x.Slug, $"%{query}%")) .Where(_database.Like<Collection>(x => x.Name + " " + x.Slug, $"%{query}%"))
.Take(20) .Take(20)
).ToListAsync(); ).ToListAsync())
.Select(SetBackingImageSelf).ToList();
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -79,7 +79,7 @@ namespace Kyoo.Core.Controllers
{ {
return _database.Episodes.FirstOrDefaultAsync(x => x.ShowId == showID return _database.Episodes.FirstOrDefaultAsync(x => x.ShowId == showID
&& x.SeasonNumber == seasonNumber && x.SeasonNumber == seasonNumber
&& x.EpisodeNumber == episodeNumber); && x.EpisodeNumber == episodeNumber).Then(SetBackingImage);
} }
/// <inheritdoc /> /// <inheritdoc />
@ -87,7 +87,7 @@ namespace Kyoo.Core.Controllers
{ {
return _database.Episodes.FirstOrDefaultAsync(x => x.Show.Slug == showSlug return _database.Episodes.FirstOrDefaultAsync(x => x.Show.Slug == showSlug
&& x.SeasonNumber == seasonNumber && x.SeasonNumber == seasonNumber
&& x.EpisodeNumber == episodeNumber); && x.EpisodeNumber == episodeNumber).Then(SetBackingImage);
} }
/// <inheritdoc /> /// <inheritdoc />
@ -112,14 +112,14 @@ namespace Kyoo.Core.Controllers
public Task<Episode> GetAbsolute(int showID, int absoluteNumber) public Task<Episode> GetAbsolute(int showID, int absoluteNumber)
{ {
return _database.Episodes.FirstOrDefaultAsync(x => x.ShowId == showID return _database.Episodes.FirstOrDefaultAsync(x => x.ShowId == showID
&& x.AbsoluteNumber == absoluteNumber); && x.AbsoluteNumber == absoluteNumber).Then(SetBackingImage);
} }
/// <inheritdoc /> /// <inheritdoc />
public Task<Episode> GetAbsolute(string showSlug, int absoluteNumber) public Task<Episode> GetAbsolute(string showSlug, int absoluteNumber)
{ {
return _database.Episodes.FirstOrDefaultAsync(x => x.Show.Slug == showSlug return _database.Episodes.FirstOrDefaultAsync(x => x.Show.Slug == showSlug
&& x.AbsoluteNumber == absoluteNumber); && x.AbsoluteNumber == absoluteNumber).Then(SetBackingImage);
} }
/// <inheritdoc /> /// <inheritdoc />
@ -134,7 +134,10 @@ namespace Kyoo.Core.Controllers
.Take(20) .Take(20)
.ToListAsync(); .ToListAsync();
foreach (Episode ep in ret) foreach (Episode ep in ret)
{
ep.Show.Episodes = null; ep.Show.Episodes = null;
SetBackingImage(ep);
}
return ret; return ret;
} }

View File

@ -24,6 +24,7 @@ using System.Threading.Tasks;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Postgresql; using Kyoo.Postgresql;
using Kyoo.Utils;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace Kyoo.Core.Controllers namespace Kyoo.Core.Controllers
@ -54,13 +55,19 @@ namespace Kyoo.Core.Controllers
/// <inheritdoc /> /// <inheritdoc />
public override async Task<ILibraryItem> GetOrDefault(int id) public override async Task<ILibraryItem> GetOrDefault(int id)
{ {
return await _database.LibraryItems.FirstOrDefaultAsync(x => x.Id == id); return await _database.LibraryItems.SingleOrDefaultAsync(x => x.Id == id).Then(SetBackingImage);
} }
/// <inheritdoc /> /// <inheritdoc />
public override async Task<ILibraryItem> GetOrDefault(string slug) public override async Task<ILibraryItem> GetOrDefault(string slug)
{ {
return await _database.LibraryItems.SingleOrDefaultAsync(x => x.Slug == slug); return await _database.LibraryItems.SingleOrDefaultAsync(x => x.Slug == slug).Then(SetBackingImage);
}
/// <inheritdoc />
public override async Task<ILibraryItem> GetOrDefault(Expression<Func<ILibraryItem, bool>> where, Sort<ILibraryItem> sortBy = default)
{
return await Sort(_database.LibraryItems, sortBy).FirstOrDefaultAsync(where).Then(SetBackingImage);
} }
/// <inheritdoc /> /// <inheritdoc />
@ -68,7 +75,8 @@ namespace Kyoo.Core.Controllers
Sort<ILibraryItem> sort = default, Sort<ILibraryItem> sort = default,
Pagination limit = default) Pagination limit = default)
{ {
return await ApplyFilters(_database.LibraryItems, where, sort, limit); return (await ApplyFilters(_database.LibraryItems, where, sort, limit))
.Select(SetBackingImageSelf).ToList();
} }
/// <inheritdoc /> /// <inheritdoc />
@ -83,12 +91,14 @@ namespace Kyoo.Core.Controllers
/// <inheritdoc /> /// <inheritdoc />
public override async Task<ICollection<ILibraryItem>> Search(string query) public override async Task<ICollection<ILibraryItem>> Search(string query)
{ {
return await Sort( return (await Sort(
_database.LibraryItems _database.LibraryItems
.Where(_database.Like<LibraryItem>(x => x.Name, $"%{query}%")) .Where(_database.Like<LibraryItem>(x => x.Name, $"%{query}%"))
) )
.Take(20) .Take(20)
.ToListAsync(); .ToListAsync())
.Select(SetBackingImageSelf)
.ToList();
} }
/// <inheritdoc /> /// <inheritdoc />
@ -100,7 +110,7 @@ namespace Kyoo.Core.Controllers
=> throw new InvalidOperationException(); => throw new InvalidOperationException();
/// <inheritdoc /> /// <inheritdoc />
public override Task<ILibraryItem> Edit(ILibraryItem obj) public override Task<ILibraryItem> Edit(ILibraryItem edited)
=> throw new InvalidOperationException(); => throw new InvalidOperationException();
/// <inheritdoc /> /// <inheritdoc />

View File

@ -30,7 +30,6 @@ using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Core.Api; using Kyoo.Core.Api;
using Kyoo.Utils; using Kyoo.Utils;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
namespace Kyoo.Core.Controllers namespace Kyoo.Core.Controllers
{ {
@ -227,6 +226,28 @@ namespace Kyoo.Core.Controllers
return Expression.Lambda<Func<T, bool>>(filter!, x); return Expression.Lambda<Func<T, bool>>(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;
}
/// <summary> /// <summary>
/// Get a resource from it's ID and make the <see cref="Database"/> instance track it. /// Get a resource from it's ID and make the <see cref="Database"/> instance track it.
/// </summary> /// </summary>
@ -236,6 +257,7 @@ namespace Kyoo.Core.Controllers
protected virtual async Task<T> GetWithTracking(int id) protected virtual async Task<T> GetWithTracking(int id)
{ {
T ret = await Database.Set<T>().AsTracking().FirstOrDefaultAsync(x => x.Id == id); T ret = await Database.Set<T>().AsTracking().FirstOrDefaultAsync(x => x.Id == id);
SetBackingImage(ret);
if (ret == null) if (ret == null)
throw new ItemNotFoundException($"No {typeof(T).Name} found with the id {id}"); throw new ItemNotFoundException($"No {typeof(T).Name} found with the id {id}");
return ret; return ret;
@ -271,30 +293,31 @@ namespace Kyoo.Core.Controllers
/// <inheritdoc /> /// <inheritdoc />
public virtual Task<T> GetOrDefault(int id) public virtual Task<T> GetOrDefault(int id)
{ {
return Database.Set<T>().FirstOrDefaultAsync(x => x.Id == id); return Database.Set<T>().FirstOrDefaultAsync(x => x.Id == id).Then(SetBackingImage);
} }
/// <inheritdoc /> /// <inheritdoc />
public virtual Task<T> GetOrDefault(string slug) public virtual Task<T> GetOrDefault(string slug)
{ {
return Database.Set<T>().FirstOrDefaultAsync(x => x.Slug == slug); return Database.Set<T>().FirstOrDefaultAsync(x => x.Slug == slug).Then(SetBackingImage);
} }
/// <inheritdoc /> /// <inheritdoc />
public virtual Task<T> GetOrDefault(Expression<Func<T, bool>> where, Sort<T> sortBy = default) public virtual Task<T> GetOrDefault(Expression<Func<T, bool>> where, Sort<T> sortBy = default)
{ {
return Sort(Database.Set<T>(), sortBy).FirstOrDefaultAsync(where); return Sort(Database.Set<T>(), sortBy).FirstOrDefaultAsync(where).Then(SetBackingImage);
} }
/// <inheritdoc/> /// <inheritdoc/>
public abstract Task<ICollection<T>> Search(string query); public abstract Task<ICollection<T>> Search(string query);
/// <inheritdoc/> /// <inheritdoc/>
public virtual Task<ICollection<T>> GetAll(Expression<Func<T, bool>> where = null, public virtual async Task<ICollection<T>> GetAll(Expression<Func<T, bool>> where = null,
Sort<T> sort = default, Sort<T> sort = default,
Pagination limit = default) Pagination limit = default)
{ {
return ApplyFilters(Database.Set<T>(), where, sort, limit); return (await ApplyFilters(Database.Set<T>(), where, sort, limit))
.Select(SetBackingImageSelf).ToList();
} }
/// <summary> /// <summary>
@ -349,6 +372,7 @@ namespace Kyoo.Core.Controllers
if (thumbs.Logo != null) if (thumbs.Logo != null)
Database.Entry(thumbs).Reference(x => x.Logo).TargetEntry.State = EntityState.Added; Database.Entry(thumbs).Reference(x => x.Logo).TargetEntry.State = EntityState.Added;
} }
SetBackingImage(obj);
return obj; return obj;
} }
@ -400,6 +424,7 @@ namespace Kyoo.Core.Controllers
await EditRelations(old, edited); await EditRelations(old, edited);
await Database.SaveChangesAsync(); await Database.SaveChangesAsync();
OnEdited?.Invoke(old); OnEdited?.Invoke(old);
SetBackingImage(old);
return old; return old;
} }
finally finally
@ -423,6 +448,7 @@ namespace Kyoo.Core.Controllers
await Database.SaveChangesAsync(); await Database.SaveChangesAsync();
OnEdited?.Invoke(resource); OnEdited?.Invoke(resource);
SetBackingImage(resource);
return resource; return resource;
} }
finally finally

View File

@ -69,12 +69,14 @@ namespace Kyoo.Core.Controllers
public override async Task<ICollection<Movie>> Search(string query) public override async Task<ICollection<Movie>> Search(string query)
{ {
query = $"%{query}%"; query = $"%{query}%";
return await Sort( return (await Sort(
_database.Movies _database.Movies
.Where(_database.Like<Movie>(x => x.Name + " " + x.Slug, query)) .Where(_database.Like<Movie>(x => x.Name + " " + x.Slug, query))
) )
.Take(20) .Take(20)
.ToListAsync(); .ToListAsync())
.Select(SetBackingImageSelf)
.ToList();
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -63,12 +63,14 @@ namespace Kyoo.Core.Controllers
/// <inheritdoc /> /// <inheritdoc />
public override async Task<ICollection<People>> Search(string query) public override async Task<ICollection<People>> Search(string query)
{ {
return await Sort( return (await Sort(
_database.People _database.People
.Where(_database.Like<People>(x => x.Name, $"%{query}%")) .Where(_database.Like<People>(x => x.Name, $"%{query}%"))
) )
.Take(20) .Take(20)
.ToListAsync(); .ToListAsync())
.Select(SetBackingImageSelf)
.ToList();
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -24,6 +24,7 @@ using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Postgresql; using Kyoo.Postgresql;
using Kyoo.Utils;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace Kyoo.Core.Controllers namespace Kyoo.Core.Controllers
@ -87,25 +88,27 @@ namespace Kyoo.Core.Controllers
public Task<Season> GetOrDefault(int showID, int seasonNumber) public Task<Season> GetOrDefault(int showID, int seasonNumber)
{ {
return _database.Seasons.FirstOrDefaultAsync(x => x.ShowId == showID return _database.Seasons.FirstOrDefaultAsync(x => x.ShowId == showID
&& x.SeasonNumber == seasonNumber); && x.SeasonNumber == seasonNumber).Then(SetBackingImage);
} }
/// <inheritdoc/> /// <inheritdoc/>
public Task<Season> GetOrDefault(string showSlug, int seasonNumber) public Task<Season> GetOrDefault(string showSlug, int seasonNumber)
{ {
return _database.Seasons.FirstOrDefaultAsync(x => x.Show.Slug == showSlug return _database.Seasons.FirstOrDefaultAsync(x => x.Show.Slug == showSlug
&& x.SeasonNumber == seasonNumber); && x.SeasonNumber == seasonNumber).Then(SetBackingImage);
} }
/// <inheritdoc/> /// <inheritdoc/>
public override async Task<ICollection<Season>> Search(string query) public override async Task<ICollection<Season>> Search(string query)
{ {
return await Sort( return (await Sort(
_database.Seasons _database.Seasons
.Where(_database.Like<Season>(x => x.Name, $"%{query}%")) .Where(_database.Like<Season>(x => x.Name, $"%{query}%"))
) )
.Take(20) .Take(20)
.ToListAsync(); .ToListAsync())
.Select(SetBackingImageSelf)
.ToList();
} }
/// <inheritdoc/> /// <inheritdoc/>

View File

@ -70,12 +70,14 @@ namespace Kyoo.Core.Controllers
public override async Task<ICollection<Show>> Search(string query) public override async Task<ICollection<Show>> Search(string query)
{ {
query = $"%{query}%"; query = $"%{query}%";
return await Sort( return (await Sort(
_database.Shows _database.Shows
.Where(_database.Like<Show>(x => x.Name + " " + x.Slug, query)) .Where(_database.Like<Show>(x => x.Name + " " + x.Slug, query))
) )
.Take(20) .Take(20)
.ToListAsync(); .ToListAsync())
.Select(SetBackingImageSelf)
.ToList();
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -16,7 +16,6 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>. // along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -54,12 +53,14 @@ namespace Kyoo.Core.Controllers
/// <inheritdoc /> /// <inheritdoc />
public override async Task<ICollection<Studio>> Search(string query) public override async Task<ICollection<Studio>> Search(string query)
{ {
return await Sort( return (await Sort(
_database.Studios _database.Studios
.Where(_database.Like<Studio>(x => x.Name, $"%{query}%")) .Where(_database.Like<Studio>(x => x.Name, $"%{query}%"))
) )
.Take(20) .Take(20)
.ToListAsync(); .ToListAsync())
.Select(SetBackingImageSelf)
.ToList();
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -16,7 +16,6 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>. // along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -53,12 +52,14 @@ namespace Kyoo.Core.Controllers
/// <inheritdoc /> /// <inheritdoc />
public override async Task<ICollection<User>> Search(string query) public override async Task<ICollection<User>> Search(string query)
{ {
return await Sort( return (await Sort(
_database.Users _database.Users
.Where(_database.Like<User>(x => x.Username, $"%{query}%")) .Where(_database.Like<User>(x => x.Username, $"%{query}%"))
) )
.Take(20) .Take(20)
.ToListAsync(); .ToListAsync())
.Select(SetBackingImageSelf)
.ToList();
} }
/// <inheritdoc /> /// <inheritdoc />