mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Parse watch status on the front
This commit is contained in:
parent
d1febd13fd
commit
db3d7f1f2e
@ -196,7 +196,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
public WatchStatus Status { get; set; }
|
public WatchStatus Status { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The numder of episodes the user has not seen.
|
/// The number of episodes the user has not seen.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int UnseenEpisodesCount { get; set; }
|
public int UnseenEpisodesCount { get; set; }
|
||||||
|
|
||||||
@ -206,7 +206,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
[SerializeIgnore] public Guid NextEpisodeId { get; set; }
|
[SerializeIgnore] public Guid NextEpisodeId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="Show"/> started.
|
/// The next <see cref="Episode"/> to watch.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Episode? NextEpisode { get; set; }
|
public Episode? NextEpisode { get; set; }
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { ShowP } from "./show";
|
import { ShowP } from "./show";
|
||||||
import { BaseEpisodeP } from "./episode.base";
|
import { BaseEpisodeP } from "./episode.base";
|
||||||
|
import { WatchStatusP } from "./watch-status";
|
||||||
|
|
||||||
export const EpisodeP = BaseEpisodeP.and(
|
export const EpisodeP = BaseEpisodeP.and(
|
||||||
z.object({
|
z.object({
|
||||||
@ -36,6 +37,10 @@ export const EpisodeP = BaseEpisodeP.and(
|
|||||||
nextEpisode: BaseEpisodeP.nullable().optional(),
|
nextEpisode: BaseEpisodeP.nullable().optional(),
|
||||||
|
|
||||||
show: ShowP.optional(),
|
show: ShowP.optional(),
|
||||||
|
/**
|
||||||
|
* Metadata of what an user as started/planned to watch.
|
||||||
|
*/
|
||||||
|
watchStatus: WatchStatusP.optional().nullable(),
|
||||||
}),
|
}),
|
||||||
).transform((x) => {
|
).transform((x) => {
|
||||||
if (x.show && !x.thumbnail && x.show.thumbnail) x.thumbnail = x.show.thumbnail;
|
if (x.show && !x.thumbnail && x.show.thumbnail) x.thumbnail = x.show.thumbnail;
|
||||||
|
@ -26,6 +26,7 @@ import { StudioP } from "./studio";
|
|||||||
import { Status } from "./show";
|
import { Status } from "./show";
|
||||||
import { CollectionP } from "./collection";
|
import { CollectionP } from "./collection";
|
||||||
import { MetadataP } from "./metadata";
|
import { MetadataP } from "./metadata";
|
||||||
|
import { WatchStatusP } from "./watch-status";
|
||||||
|
|
||||||
export const MovieP = withImages(
|
export const MovieP = withImages(
|
||||||
ResourceP.extend({
|
ResourceP.extend({
|
||||||
@ -99,6 +100,10 @@ export const MovieP = withImages(
|
|||||||
* The link to metadata providers that this show has.
|
* The link to metadata providers that this show has.
|
||||||
*/
|
*/
|
||||||
externalId: MetadataP,
|
externalId: MetadataP,
|
||||||
|
/**
|
||||||
|
* Metadata of what an user as started/planned to watch.
|
||||||
|
*/
|
||||||
|
watchStatus: WatchStatusP.optional().nullable(),
|
||||||
}),
|
}),
|
||||||
"movies",
|
"movies",
|
||||||
)
|
)
|
||||||
|
@ -27,6 +27,7 @@ import { StudioP } from "./studio";
|
|||||||
import { BaseEpisodeP } from "./episode.base";
|
import { BaseEpisodeP } from "./episode.base";
|
||||||
import { CollectionP } from "./collection";
|
import { CollectionP } from "./collection";
|
||||||
import { MetadataP } from "./metadata";
|
import { MetadataP } from "./metadata";
|
||||||
|
import { WatchStatusP } from "./watch-status";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The enum containing show's status.
|
* The enum containing show's status.
|
||||||
@ -104,6 +105,23 @@ export const ShowP = withImages(
|
|||||||
* The link to metadata providers that this show has.
|
* The link to metadata providers that this show has.
|
||||||
*/
|
*/
|
||||||
externalId: MetadataP,
|
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",
|
"shows",
|
||||||
)
|
)
|
||||||
|
56
front/packages/models/src/resources/watch-status.ts
Normal file
56
front/packages/models/src/resources/watch-status.ts
Normal file
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<typeof WatchStatusP>;
|
@ -19,7 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { ReactElement } from "react";
|
import { ReactElement } from "react";
|
||||||
import { MeQuery, Navbar } from "./navbar";
|
import { Navbar } from "./navbar";
|
||||||
import { useYoshiki, vw } from "yoshiki/native";
|
import { useYoshiki, vw } from "yoshiki/native";
|
||||||
import { Main } from "@kyoo/primitives";
|
import { Main } from "@kyoo/primitives";
|
||||||
|
|
||||||
@ -60,4 +60,3 @@ export const DefaultLayout = ({
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
DefaultLayout.getFetchUrls = () => [MeQuery];
|
|
||||||
|
@ -18,15 +18,7 @@
|
|||||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import { deleteAccount, logout, useAccount, useAccounts } from "@kyoo/models";
|
||||||
deleteAccount,
|
|
||||||
logout,
|
|
||||||
QueryIdentifier,
|
|
||||||
useAccount,
|
|
||||||
useAccounts,
|
|
||||||
User,
|
|
||||||
UserP,
|
|
||||||
} from "@kyoo/models";
|
|
||||||
import {
|
import {
|
||||||
Alert,
|
Alert,
|
||||||
Input,
|
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 Register from "@material-symbols/svg-400/rounded/app_registration.svg";
|
||||||
import Logout from "@material-symbols/svg-400/rounded/logout.svg";
|
import Logout from "@material-symbols/svg-400/rounded/logout.svg";
|
||||||
import Delete from "@material-symbols/svg-400/rounded/delete.svg";
|
import Delete from "@material-symbols/svg-400/rounded/delete.svg";
|
||||||
import { FetchNE } from "../fetch";
|
|
||||||
import { KyooLongLogo } from "./icon";
|
import { KyooLongLogo } from "./icon";
|
||||||
import { forwardRef, useContext, useEffect, useRef, useState } from "react";
|
import { forwardRef, useEffect, useRef, useState } from "react";
|
||||||
import { useQueryClient } from "@tanstack/react-query";
|
|
||||||
|
|
||||||
export const NavbarTitle = (props: Stylable & { onLayout?: ViewProps["onLayout"] }) => {
|
export const NavbarTitle = (props: Stylable & { onLayout?: ViewProps["onLayout"] }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@ -95,11 +85,6 @@ const SearchBar = forwardRef<TextInput, Stylable>(function SearchBar(props, ref)
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
export const MeQuery: QueryIdentifier<User> = {
|
|
||||||
path: ["auth", "me"],
|
|
||||||
parser: UserP,
|
|
||||||
};
|
|
||||||
|
|
||||||
const getDisplayUrl = (url: string) => {
|
const getDisplayUrl = (url: string) => {
|
||||||
url = url.replace(/\/api$/, "");
|
url = url.replace(/\/api$/, "");
|
||||||
url = url.replace(/https?:\/\//, "");
|
url = url.replace(/https?:\/\//, "");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user