diff --git a/back/src/Kyoo.Abstractions/Models/Resources/WatchStatus.cs b/back/src/Kyoo.Abstractions/Models/Resources/WatchStatus.cs index ffb74638..78e1e438 100644 --- a/back/src/Kyoo.Abstractions/Models/Resources/WatchStatus.cs +++ b/back/src/Kyoo.Abstractions/Models/Resources/WatchStatus.cs @@ -196,7 +196,7 @@ namespace Kyoo.Abstractions.Models public WatchStatus Status { get; set; } /// - /// The numder of episodes the user has not seen. + /// The number of episodes the user has not seen. /// public int UnseenEpisodesCount { get; set; } @@ -206,7 +206,7 @@ namespace Kyoo.Abstractions.Models [SerializeIgnore] public Guid NextEpisodeId { get; set; } /// - /// The started. + /// The next to watch. /// public Episode? NextEpisode { get; set; } diff --git a/front/packages/models/src/resources/episode.ts b/front/packages/models/src/resources/episode.ts index 702b371e..5aa19dde 100644 --- a/front/packages/models/src/resources/episode.ts +++ b/front/packages/models/src/resources/episode.ts @@ -21,6 +21,7 @@ import { z } from "zod"; import { ShowP } from "./show"; import { BaseEpisodeP } from "./episode.base"; +import { WatchStatusP } from "./watch-status"; export const EpisodeP = BaseEpisodeP.and( z.object({ @@ -36,6 +37,10 @@ export const EpisodeP = BaseEpisodeP.and( nextEpisode: BaseEpisodeP.nullable().optional(), show: ShowP.optional(), + /** + * Metadata of what an user as started/planned to watch. + */ + watchStatus: WatchStatusP.optional().nullable(), }), ).transform((x) => { if (x.show && !x.thumbnail && x.show.thumbnail) x.thumbnail = x.show.thumbnail; diff --git a/front/packages/models/src/resources/movie.ts b/front/packages/models/src/resources/movie.ts index 64acaeb7..c0d1ae35 100644 --- a/front/packages/models/src/resources/movie.ts +++ b/front/packages/models/src/resources/movie.ts @@ -26,6 +26,7 @@ import { StudioP } from "./studio"; import { Status } from "./show"; import { CollectionP } from "./collection"; import { MetadataP } from "./metadata"; +import { WatchStatusP } from "./watch-status"; export const MovieP = withImages( ResourceP.extend({ @@ -99,6 +100,10 @@ export const MovieP = withImages( * The link to metadata providers that this show has. */ externalId: MetadataP, + /** + * Metadata of what an user as started/planned to watch. + */ + watchStatus: WatchStatusP.optional().nullable(), }), "movies", ) diff --git a/front/packages/models/src/resources/show.ts b/front/packages/models/src/resources/show.ts index 454fe4cb..b3943fff 100644 --- a/front/packages/models/src/resources/show.ts +++ b/front/packages/models/src/resources/show.ts @@ -27,6 +27,7 @@ import { StudioP } from "./studio"; import { BaseEpisodeP } from "./episode.base"; import { CollectionP } from "./collection"; import { MetadataP } from "./metadata"; +import { WatchStatusP } from "./watch-status"; /** * The enum containing show's status. @@ -104,6 +105,23 @@ export const ShowP = withImages( * The link to metadata providers that this show has. */ externalId: MetadataP, + /** + * Metadata of what an user as started/planned to watch. + */ + watchStatus: WatchStatusP.and( + z.object({ + /** + * The number of episodes the user has not seen. + */ + unseenEpisodeCount: z.number().int().gte(0), + /** + * The next episode to watch + */ + nextEpisode: BaseEpisodeP.nullable(), + }), + ) + .nullable() + .optional(), }), "shows", ) diff --git a/front/packages/models/src/resources/watch-status.ts b/front/packages/models/src/resources/watch-status.ts new file mode 100644 index 00000000..990ac02a --- /dev/null +++ b/front/packages/models/src/resources/watch-status.ts @@ -0,0 +1,56 @@ +/* + * Kyoo - A portable and vast media library solution. + * Copyright (c) Kyoo. + * + * See AUTHORS.md and LICENSE file in the project root for full license information. + * + * Kyoo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * Kyoo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Kyoo. If not, see . + */ + +import { z } from "zod"; +import { zdate } from "../utils" + +export enum WatchStatusV { + Completed = "Completed", + Watching = "Watching", + Droped = "Droped", + Planned = "Planned", +} + +export const WatchStatusP = z.object({ + /** + * The date this item was added to the watchlist (watched or plan to watch by the user). + */ + addedDate: zdate(), + /** + * The date at which this item was played. + */ + playedDate: zdate().nullable(), + /** + * Has the user started watching, is it planned? + */ + status: z.nativeEnum(WatchStatusV), + /** + * Where the player has stopped watching the episode (in seconds). + * Null if the status is not Watching or if the next episode is not started. + */ + watchedTime: z.number().int().gte(0).nullable(), + /** + * Where the player has stopped watching the episode (in percentage between 0 and 100). + * Null if the status is not Watching or if the next episode is not started. + */ + watchedPercent: z.number().int().gte(0).lte(100), +}); + +export type WatchStatus = z.infer; diff --git a/front/packages/ui/src/layout.tsx b/front/packages/ui/src/layout.tsx index 24c66214..0a1e2f17 100644 --- a/front/packages/ui/src/layout.tsx +++ b/front/packages/ui/src/layout.tsx @@ -19,7 +19,7 @@ */ import { ReactElement } from "react"; -import { MeQuery, Navbar } from "./navbar"; +import { Navbar } from "./navbar"; import { useYoshiki, vw } from "yoshiki/native"; import { Main } from "@kyoo/primitives"; @@ -60,4 +60,3 @@ export const DefaultLayout = ({ ); }; -DefaultLayout.getFetchUrls = () => [MeQuery]; diff --git a/front/packages/ui/src/navbar/index.tsx b/front/packages/ui/src/navbar/index.tsx index ceeaf59a..cd9ae89e 100644 --- a/front/packages/ui/src/navbar/index.tsx +++ b/front/packages/ui/src/navbar/index.tsx @@ -18,15 +18,7 @@ * along with Kyoo. If not, see . */ -import { - deleteAccount, - logout, - QueryIdentifier, - useAccount, - useAccounts, - User, - UserP, -} from "@kyoo/models"; +import { deleteAccount, logout, useAccount, useAccounts } from "@kyoo/models"; import { Alert, Input, @@ -49,10 +41,8 @@ import Login from "@material-symbols/svg-400/rounded/login.svg"; import Register from "@material-symbols/svg-400/rounded/app_registration.svg"; import Logout from "@material-symbols/svg-400/rounded/logout.svg"; import Delete from "@material-symbols/svg-400/rounded/delete.svg"; -import { FetchNE } from "../fetch"; import { KyooLongLogo } from "./icon"; -import { forwardRef, useContext, useEffect, useRef, useState } from "react"; -import { useQueryClient } from "@tanstack/react-query"; +import { forwardRef, useEffect, useRef, useState } from "react"; export const NavbarTitle = (props: Stylable & { onLayout?: ViewProps["onLayout"] }) => { const { t } = useTranslation(); @@ -95,11 +85,6 @@ const SearchBar = forwardRef(function SearchBar(props, ref) ); }); -export const MeQuery: QueryIdentifier = { - path: ["auth", "me"], - parser: UserP, -}; - const getDisplayUrl = (url: string) => { url = url.replace(/\/api$/, ""); url = url.replace(/https?:\/\//, "");