mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Add images links on the front instead of the back
This commit is contained in:
parent
c9c1ac5126
commit
1373d0ce26
@ -54,12 +54,11 @@ 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 />
|
||||||
|
@ -77,7 +77,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task<ICollection<Episode>> Search(string query)
|
public override async Task<ICollection<Episode>> Search(string query)
|
||||||
{
|
{
|
||||||
List<Episode> ret = await Sort(
|
return await Sort(
|
||||||
_database.Episodes
|
_database.Episodes
|
||||||
.Include(x => x.Show)
|
.Include(x => x.Show)
|
||||||
.Where(x => x.EpisodeNumber != null || x.AbsoluteNumber != null)
|
.Where(x => x.EpisodeNumber != null || x.AbsoluteNumber != null)
|
||||||
@ -85,12 +85,6 @@ namespace Kyoo.Core.Controllers
|
|||||||
)
|
)
|
||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
foreach (Episode ep in ret)
|
|
||||||
{
|
|
||||||
ep.Show!.Episodes = null;
|
|
||||||
SetBackingImage(ep);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
@ -54,14 +54,12 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task<ICollection<LibraryItem>> Search(string query)
|
public override async Task<ICollection<LibraryItem>> 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 />
|
||||||
|
@ -278,28 +278,6 @@ namespace Kyoo.Core.Controllers
|
|||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void SetBackingImage(T? obj)
|
|
||||||
{
|
|
||||||
if (obj is not IThumbnails thumbs)
|
|
||||||
return;
|
|
||||||
string type = obj is LibraryItem 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>
|
||||||
@ -309,7 +287,6 @@ 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;
|
||||||
@ -346,8 +323,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
public virtual Task<T?> GetOrDefault(int id, Include<T>? include = default)
|
public virtual Task<T?> GetOrDefault(int id, Include<T>? include = default)
|
||||||
{
|
{
|
||||||
return AddIncludes(Database.Set<T>(), include)
|
return AddIncludes(Database.Set<T>(), include)
|
||||||
.FirstOrDefaultAsync(x => x.Id == id)
|
.FirstOrDefaultAsync(x => x.Id == id);
|
||||||
.Then(SetBackingImage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -357,12 +333,10 @@ namespace Kyoo.Core.Controllers
|
|||||||
{
|
{
|
||||||
return AddIncludes(Database.Set<T>(), include)
|
return AddIncludes(Database.Set<T>(), include)
|
||||||
.OrderBy(x => EF.Functions.Random())
|
.OrderBy(x => EF.Functions.Random())
|
||||||
.FirstOrDefaultAsync()
|
.FirstOrDefaultAsync();
|
||||||
.Then(SetBackingImage);
|
|
||||||
}
|
}
|
||||||
return AddIncludes(Database.Set<T>(), include)
|
return AddIncludes(Database.Set<T>(), include)
|
||||||
.FirstOrDefaultAsync(x => x.Slug == slug)
|
.FirstOrDefaultAsync(x => x.Slug == slug);
|
||||||
.Then(SetBackingImage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -374,21 +348,19 @@ namespace Kyoo.Core.Controllers
|
|||||||
AddIncludes(Database.Set<T>(), include),
|
AddIncludes(Database.Set<T>(), include),
|
||||||
sortBy
|
sortBy
|
||||||
)
|
)
|
||||||
.FirstOrDefaultAsync(where)
|
.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 async Task<ICollection<T>> GetAll(Expression<Func<T, bool>>? where = null,
|
public virtual Task<ICollection<T>> GetAll(Expression<Func<T, bool>>? where = null,
|
||||||
Sort<T>? sort = default,
|
Sort<T>? sort = default,
|
||||||
Pagination? limit = default,
|
Pagination? limit = default,
|
||||||
Include<T>? include = default)
|
Include<T>? include = default)
|
||||||
{
|
{
|
||||||
return (await ApplyFilters(Database.Set<T>(), where, sort, limit, include))
|
return ApplyFilters(Database.Set<T>(), where, sort, limit, include);
|
||||||
.Select(SetBackingImageSelf).ToList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -447,7 +419,6 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -499,7 +470,6 @@ 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
|
||||||
@ -523,7 +493,6 @@ namespace Kyoo.Core.Controllers
|
|||||||
|
|
||||||
await Database.SaveChangesAsync();
|
await Database.SaveChangesAsync();
|
||||||
OnEdited?.Invoke(resource);
|
OnEdited?.Invoke(resource);
|
||||||
SetBackingImage(resource);
|
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
@ -71,14 +71,12 @@ 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 />
|
||||||
|
@ -65,14 +65,12 @@ 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 />
|
||||||
|
@ -71,14 +71,12 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <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/>
|
||||||
|
@ -71,15 +71,12 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task<ICollection<Show>> Search(string query)
|
public override async Task<ICollection<Show>> Search(string 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 />
|
||||||
|
@ -54,14 +54,12 @@ 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 />
|
||||||
|
@ -53,14 +53,12 @@ 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 />
|
||||||
|
@ -59,6 +59,8 @@ namespace Kyoo.Core.Api
|
|||||||
property.ShouldSerialize = _ =>
|
property.ShouldSerialize = _ =>
|
||||||
{
|
{
|
||||||
ICollection<string> fields = (ICollection<string>)_httpContextAccessor.HttpContext!.Items["fields"]!;
|
ICollection<string> fields = (ICollection<string>)_httpContextAccessor.HttpContext!.Items["fields"]!;
|
||||||
|
if (fields == null)
|
||||||
|
return false;
|
||||||
return fields.Contains(member.Name);
|
return fields.Contains(member.Name);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -19,10 +19,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { ImagesP, ResourceP } from "../traits";
|
import { withImages, ResourceP } from "../traits";
|
||||||
|
|
||||||
export const CollectionP = ResourceP.merge(ImagesP)
|
export const CollectionP = withImages(
|
||||||
.extend({
|
ResourceP.extend({
|
||||||
/**
|
/**
|
||||||
* The title of this collection.
|
* The title of this collection.
|
||||||
*/
|
*/
|
||||||
@ -31,11 +31,12 @@ export const CollectionP = ResourceP.merge(ImagesP)
|
|||||||
* The summary of this show.
|
* The summary of this show.
|
||||||
*/
|
*/
|
||||||
overview: z.string().nullable(),
|
overview: z.string().nullable(),
|
||||||
})
|
}),
|
||||||
.transform((x) => ({
|
"collections",
|
||||||
...x,
|
).transform((x) => ({
|
||||||
href: `/collection/${x.slug}`,
|
...x,
|
||||||
}));
|
href: `/collection/${x.slug}`,
|
||||||
|
}));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class representing collections of show or movies.
|
* A class representing collections of show or movies.
|
||||||
|
@ -20,72 +20,77 @@
|
|||||||
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { zdate } from "../utils";
|
import { zdate } from "../utils";
|
||||||
import { ImagesP, imageFn } from "../traits";
|
import { withImages, imageFn } from "../traits";
|
||||||
import { ResourceP } from "../traits/resource";
|
import { ResourceP } from "../traits/resource";
|
||||||
import { ShowP } from "./show";
|
import { ShowP } from "./show";
|
||||||
|
|
||||||
const BaseEpisodeP = ResourceP.merge(ImagesP).extend({
|
const BaseEpisodeP = withImages(
|
||||||
/**
|
ResourceP.extend({
|
||||||
* The season in witch this episode is in.
|
|
||||||
*/
|
|
||||||
seasonNumber: z.number().nullable(),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The number of this episode in it's season.
|
|
||||||
*/
|
|
||||||
episodeNumber: z.number().nullable(),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The absolute number of this episode. It's an episode number that is not reset to 1 after a new
|
|
||||||
* season.
|
|
||||||
*/
|
|
||||||
absoluteNumber: z.number().nullable(),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The title of this episode.
|
|
||||||
*/
|
|
||||||
name: z.string().nullable(),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The overview of this episode.
|
|
||||||
*/
|
|
||||||
overview: z.string().nullable(),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The release date of this episode. It can be null if unknown.
|
|
||||||
*/
|
|
||||||
releaseDate: zdate().nullable(),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The links to see a movie or an episode.
|
|
||||||
*/
|
|
||||||
links: z.object({
|
|
||||||
/**
|
/**
|
||||||
* The direct link to the unprocessed video (pristine quality).
|
* The season in witch this episode is in.
|
||||||
*/
|
*/
|
||||||
direct: z.string().transform(imageFn),
|
seasonNumber: z.number().nullable(),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The link to an HLS master playlist containing all qualities available for this video.
|
* The number of this episode in it's season.
|
||||||
*/
|
*/
|
||||||
hls: z.string().transform(imageFn),
|
episodeNumber: z.number().nullable(),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The absolute number of this episode. It's an episode number that is not reset to 1 after a new
|
||||||
|
* season.
|
||||||
|
*/
|
||||||
|
absoluteNumber: z.number().nullable(),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The title of this episode.
|
||||||
|
*/
|
||||||
|
name: z.string().nullable(),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The overview of this episode.
|
||||||
|
*/
|
||||||
|
overview: z.string().nullable(),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The release date of this episode. It can be null if unknown.
|
||||||
|
*/
|
||||||
|
releaseDate: zdate().nullable(),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The links to see a movie or an episode.
|
||||||
|
*/
|
||||||
|
links: z.object({
|
||||||
|
/**
|
||||||
|
* The direct link to the unprocessed video (pristine quality).
|
||||||
|
*/
|
||||||
|
direct: z.string().transform(imageFn),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The link to an HLS master playlist containing all qualities available for this video.
|
||||||
|
*/
|
||||||
|
hls: z.string().transform(imageFn),
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
});
|
"episodes",
|
||||||
|
);
|
||||||
|
|
||||||
export const EpisodeP = BaseEpisodeP.extend({
|
export const EpisodeP = BaseEpisodeP.and(
|
||||||
/**
|
z.object({
|
||||||
* The episode that come before this one if you follow usual watch orders. If this is the first
|
/**
|
||||||
* episode or this is a movie, it will be null.
|
* The episode that come before this one if you follow usual watch orders. If this is the first
|
||||||
*/
|
* episode, it will be null.
|
||||||
previousEpisode: BaseEpisodeP.nullable().optional(),
|
*/
|
||||||
/**
|
previousEpisode: BaseEpisodeP.nullable().optional(),
|
||||||
* The episode that come after this one if you follow usual watch orders. If this is the last
|
/**
|
||||||
* aired episode or this is a movie, it will be null.
|
* The episode that come after this one if you follow usual watch orders. If this is the last
|
||||||
*/
|
* aired episode, it will be null.
|
||||||
nextEpisode: BaseEpisodeP.nullable().optional(),
|
*/
|
||||||
|
nextEpisode: BaseEpisodeP.nullable().optional(),
|
||||||
|
|
||||||
show: ShowP.optional(),
|
show: ShowP.optional(),
|
||||||
});
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class to represent a single show's episode.
|
* A class to represent a single show's episode.
|
||||||
|
@ -20,13 +20,13 @@
|
|||||||
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { zdate } from "../utils";
|
import { zdate } from "../utils";
|
||||||
import { ImagesP, ResourceP, imageFn } from "../traits";
|
import { withImages, ResourceP, imageFn } from "../traits";
|
||||||
import { Genre } from "./genre";
|
import { Genre } from "./genre";
|
||||||
import { StudioP } from "./studio";
|
import { StudioP } from "./studio";
|
||||||
import { Status } from "./show";
|
import { Status } from "./show";
|
||||||
|
|
||||||
export const MovieP = ResourceP.merge(ImagesP)
|
export const MovieP = withImages(
|
||||||
.extend({
|
ResourceP.extend({
|
||||||
/**
|
/**
|
||||||
* The title of this movie.
|
* The title of this movie.
|
||||||
*/
|
*/
|
||||||
@ -82,7 +82,9 @@ export const MovieP = ResourceP.merge(ImagesP)
|
|||||||
*/
|
*/
|
||||||
hls: z.string().transform(imageFn),
|
hls: z.string().transform(imageFn),
|
||||||
}),
|
}),
|
||||||
})
|
}),
|
||||||
|
"movies",
|
||||||
|
)
|
||||||
.transform((x) => {
|
.transform((x) => {
|
||||||
if (!x.thumbnail && x.poster) {
|
if (!x.thumbnail && x.poster) {
|
||||||
x.thumbnail = { ...x.poster };
|
x.thumbnail = { ...x.poster };
|
||||||
|
@ -19,26 +19,29 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { ImagesP } from "../traits";
|
import { withImages } from "../traits";
|
||||||
import { ResourceP } from "../traits/resource";
|
import { ResourceP } from "../traits/resource";
|
||||||
|
|
||||||
export const PersonP = ResourceP.merge(ImagesP).extend({
|
export const PersonP = withImages(
|
||||||
/**
|
ResourceP.extend({
|
||||||
* The name of this person.
|
/**
|
||||||
*/
|
* The name of this person.
|
||||||
name: z.string(),
|
*/
|
||||||
/**
|
name: z.string(),
|
||||||
* The type of work the person has done for the show. That can be something like "Actor",
|
/**
|
||||||
* "Writer", "Music", "Voice Actor"...
|
* The type of work the person has done for the show. That can be something like "Actor",
|
||||||
*/
|
* "Writer", "Music", "Voice Actor"...
|
||||||
type: z.string().optional(),
|
*/
|
||||||
|
type: z.string().optional(),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The role the People played. This is mostly used to inform witch character was played for actor
|
* The role the People played. This is mostly used to inform witch character was played for actor
|
||||||
* and voice actors.
|
* and voice actors.
|
||||||
*/
|
*/
|
||||||
role: z.string().optional(),
|
role: z.string().optional(),
|
||||||
});
|
}),
|
||||||
|
"people",
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A studio that make shows.
|
* A studio that make shows.
|
||||||
|
@ -20,35 +20,38 @@
|
|||||||
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { zdate } from "../utils";
|
import { zdate } from "../utils";
|
||||||
import { ImagesP } from "../traits";
|
import { withImages } from "../traits";
|
||||||
import { ResourceP } from "../traits/resource";
|
import { ResourceP } from "../traits/resource";
|
||||||
|
|
||||||
export const SeasonP = ResourceP.merge(ImagesP).extend({
|
export const SeasonP = withImages(
|
||||||
/**
|
ResourceP.extend({
|
||||||
* The name of this season.
|
/**
|
||||||
*/
|
* The name of this season.
|
||||||
name: z.string(),
|
*/
|
||||||
/**
|
name: z.string(),
|
||||||
* The number of this season. This can be set to 0 to indicate specials.
|
/**
|
||||||
*/
|
* The number of this season. This can be set to 0 to indicate specials.
|
||||||
seasonNumber: z.number(),
|
*/
|
||||||
/**
|
seasonNumber: z.number(),
|
||||||
* A quick overview of this season.
|
/**
|
||||||
*/
|
* A quick overview of this season.
|
||||||
overview: z.string().nullable(),
|
*/
|
||||||
/**
|
overview: z.string().nullable(),
|
||||||
* The starting air date of this season.
|
/**
|
||||||
*/
|
* The starting air date of this season.
|
||||||
startDate: zdate().nullable(),
|
*/
|
||||||
/**
|
startDate: zdate().nullable(),
|
||||||
* The ending date of this season.
|
/**
|
||||||
*/
|
* The ending date of this season.
|
||||||
endDate: zdate().nullable(),
|
*/
|
||||||
/**
|
endDate: zdate().nullable(),
|
||||||
* The number of episodes available on kyoo of this season.
|
/**
|
||||||
*/
|
* The number of episodes available on kyoo of this season.
|
||||||
episodesCount: z.number(),
|
*/
|
||||||
});
|
episodesCount: z.number(),
|
||||||
|
}),
|
||||||
|
"seasons",
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A season of a Show.
|
* A season of a Show.
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { zdate } from "../utils";
|
import { zdate } from "../utils";
|
||||||
import { ImagesP, ResourceP } from "../traits";
|
import { withImages, ResourceP } from "../traits";
|
||||||
import { Genre } from "./genre";
|
import { Genre } from "./genre";
|
||||||
import { SeasonP } from "./season";
|
import { SeasonP } from "./season";
|
||||||
import { StudioP } from "./studio";
|
import { StudioP } from "./studio";
|
||||||
@ -35,8 +35,7 @@ export enum Status {
|
|||||||
Planned = "Planned",
|
Planned = "Planned",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ShowP = ResourceP.merge(ImagesP)
|
export const ShowP = withImages(ResourceP.extend({
|
||||||
.extend({
|
|
||||||
/**
|
/**
|
||||||
* The title of this show.
|
* The title of this show.
|
||||||
*/
|
*/
|
||||||
@ -85,7 +84,7 @@ export const ShowP = ResourceP.merge(ImagesP)
|
|||||||
* The list of seasons of this show.
|
* The list of seasons of this show.
|
||||||
*/
|
*/
|
||||||
seasons: z.array(SeasonP).optional(),
|
seasons: z.array(SeasonP).optional(),
|
||||||
})
|
}), "shows")
|
||||||
.transform((x) => {
|
.transform((x) => {
|
||||||
if (!x.thumbnail && x.poster) {
|
if (!x.thumbnail && x.poster) {
|
||||||
x.thumbnail = { ...x.poster };
|
x.thumbnail = { ...x.poster };
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Platform } from "react-native";
|
import { Platform } from "react-native";
|
||||||
import { z } from "zod";
|
import { ZodObject, ZodRawShape, z } from "zod";
|
||||||
import { kyooApiUrl } from "..";
|
import { kyooApiUrl } from "..";
|
||||||
|
|
||||||
export const imageFn = (url: string) => (Platform.OS === "web" ? `/api${url}` : kyooApiUrl + url);
|
export const imageFn = (url: string) => (Platform.OS === "web" ? `/api${url}` : kyooApiUrl + url);
|
||||||
@ -27,12 +27,9 @@ export const imageFn = (url: string) => (Platform.OS === "web" ? `/api${url}` :
|
|||||||
export const Img = z.object({
|
export const Img = z.object({
|
||||||
source: z.string(),
|
source: z.string(),
|
||||||
blurhash: z.string(),
|
blurhash: z.string(),
|
||||||
low: z.string().transform(imageFn),
|
|
||||||
medium: z.string().transform(imageFn),
|
|
||||||
high: z.string().transform(imageFn),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const ImagesP = z.object({
|
const ImagesP = z.object({
|
||||||
/**
|
/**
|
||||||
* An url to the poster of this resource. If this resource does not have an image, the link will
|
* An url to the poster of this resource. If this resource does not have an image, the link will
|
||||||
* be null. If the kyoo's instance is not capable of handling this kind of image for the specific
|
* be null. If the kyoo's instance is not capable of handling this kind of image for the specific
|
||||||
@ -55,7 +52,28 @@ export const ImagesP = z.object({
|
|||||||
logo: Img.nullable(),
|
logo: Img.nullable(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const addQualities = (x: object | null | undefined, href: string) => {
|
||||||
|
if (x === null) return null;
|
||||||
|
return {
|
||||||
|
...x,
|
||||||
|
low: imageFn(`${href}?quality=low`),
|
||||||
|
medium: imageFn(`${href}?quality=medium`),
|
||||||
|
high: imageFn(`${href}?quality=high`),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const withImages = <T extends ZodRawShape>(parser: ZodObject<T>, type: string) => {
|
||||||
|
return parser.merge(ImagesP).transform((x) => {
|
||||||
|
return {
|
||||||
|
...x,
|
||||||
|
poster: addQualities(x.poster, `/${type}/${x.slug}/poster`),
|
||||||
|
thumbnail: addQualities(x.thumbnail, `/${type}/${x.slug}/thumbnail`),
|
||||||
|
logo: addQualities(x.logo, `/${type}/${x.slug}/logo`),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base traits for items that has image resources.
|
* Base traits for items that has image resources.
|
||||||
*/
|
*/
|
||||||
export type KyooImage = z.infer<typeof Img>;
|
export type KyooImage = z.infer<typeof Img> & { low: string; medium: string; high: string };
|
||||||
|
@ -98,7 +98,7 @@ SeasonHeader.query = (slug: string): QueryIdentifier<Season, SeasonProcessed> =>
|
|||||||
map: (seasons) =>
|
map: (seasons) =>
|
||||||
seasons.reduce((acc, x) => {
|
seasons.reduce((acc, x) => {
|
||||||
if (x.episodesCount == 0) return acc;
|
if (x.episodesCount == 0) return acc;
|
||||||
return [...acc, { ...x, range: null, href: `/show/${slug}?season=${x.seasonNumber}` }];
|
return [...acc, { ...x, href: `/show/${slug}?season=${x.seasonNumber}` }];
|
||||||
}, [] as SeasonProcessed[]),
|
}, [] as SeasonProcessed[]),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user