diff --git a/front/packages/models/src/resources/index.ts b/front/packages/models/src/resources/index.ts
index 8f5b9ce7..3d934384 100644
--- a/front/packages/models/src/resources/index.ts
+++ b/front/packages/models/src/resources/index.ts
@@ -30,4 +30,5 @@ export * from "./episode";
export * from "./season";
export * from "./watch-info";
export * from "./watch-status";
+export * from "./watchlist";
export * from "./user";
diff --git a/front/packages/models/src/resources/watchlist.ts b/front/packages/models/src/resources/watchlist.ts
new file mode 100644
index 00000000..fd533afc
--- /dev/null
+++ b/front/packages/models/src/resources/watchlist.ts
@@ -0,0 +1,47 @@
+/*
+ * 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 { MovieP } from "./movie";
+import { ShowP } from "./show";
+
+/**
+ * The type of item, ether a show, a movie or an episode.
+ */
+export enum WatchlistKind {
+ Show = "Show",
+ Movie = "Movie",
+}
+
+export const WatchlistP = z.union([
+ /*
+ * Either a show
+ */
+ ShowP.and(z.object({ kind: z.literal(WatchlistKind.Show) })),
+ /*
+ * Or a Movie
+ */
+ MovieP.and(z.object({ kind: z.literal(WatchlistKind.Movie) })),
+]);
+
+/**
+ * A item in the user's watchlist.
+ */
+export type Watchlist = z.infer;
diff --git a/front/packages/ui/src/details/episode.tsx b/front/packages/ui/src/details/episode.tsx
index 6ed31620..82927f62 100644
--- a/front/packages/ui/src/details/episode.tsx
+++ b/front/packages/ui/src/details/episode.tsx
@@ -105,7 +105,7 @@ export const EpisodeBox = ({
src={thumbnail}
quality="low"
alt=""
- graditent={false}
+ gradient={false}
hideLoad={false}
forcedLoading={isLoading}
layout={{ width: percent(100), aspectRatio: 16 / 9 }}
diff --git a/front/packages/ui/src/home/index.tsx b/front/packages/ui/src/home/index.tsx
index bac76a50..fed6c3de 100644
--- a/front/packages/ui/src/home/index.tsx
+++ b/front/packages/ui/src/home/index.tsx
@@ -28,6 +28,7 @@ import { Recommanded } from "./recommanded";
import { VerticalRecommanded } from "./vertical";
import { NewsList } from "./news";
import { useEffect, useState } from "react";
+import { WatchlistList } from "./watchlist";
export const HomePage: QueryPage<{}, Genre> = ({ randomItems }) => {
const [isClient, setClient] = useState(false);
@@ -48,6 +49,7 @@ export const HomePage: QueryPage<{}, Genre> = ({ randomItems }) => {
/>
)}
+
{randomItems
.filter((_, i) => i < 2)
@@ -72,6 +74,7 @@ HomePage.getLayout = { Layout: DefaultLayout, props: { transparent: true } };
HomePage.getFetchUrls = (_, randomItems) => [
Header.query(),
+ WatchlistList.query(),
NewsList.query(),
...randomItems.filter((_, i) => i < 6).map((x) => GenreGrid.query(x)),
Recommanded.query(),
diff --git a/front/packages/ui/src/home/watchlist.tsx b/front/packages/ui/src/home/watchlist.tsx
new file mode 100644
index 00000000..56c05a35
--- /dev/null
+++ b/front/packages/ui/src/home/watchlist.tsx
@@ -0,0 +1,92 @@
+/*
+ * 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 {
+ QueryIdentifier,
+ Watchlist,
+ WatchlistKind,
+ WatchlistP,
+ getDisplayDate,
+} from "@kyoo/models";
+import { useYoshiki } from "yoshiki/native";
+import { ItemGrid } from "../browse/grid";
+import { InfiniteFetch } from "../fetch-infinite";
+import { useTranslation } from "react-i18next";
+import { Header } from "./genre";
+import { EpisodeBox, episodeDisplayNumber } from "../details/episode";
+
+export const WatchlistList = () => {
+ const { t } = useTranslation();
+ const { css } = useYoshiki();
+
+ return (
+ <>
+
+
+ (x.kind === WatchlistKind.Show && x.watchStatus?.nextEpisode) || (x.isLoading && i % 2)
+ ? "episode"
+ : "item"
+ }
+ empty={t("home.none")}
+ >
+ {(x, i) => {
+ const episode = x.kind === WatchlistKind.Show ? x.watchStatus?.nextEpisode : null;
+ return (x.kind === WatchlistKind.Show && x.watchStatus?.nextEpisode) ||
+ (x.isLoading && i % 2) ? (
+
+ ) : (
+
+ );
+ }}
+
+ >
+ );
+};
+
+WatchlistList.query = (): QueryIdentifier => ({
+ parser: WatchlistP,
+ infinite: true,
+ path: ["watchlist"],
+ params: {
+ // Limit the inital numbers of items
+ limit: 10,
+ fields: ["watchStatus"],
+ },
+});
diff --git a/front/translations/en.json b/front/translations/en.json
index 98c8f484..b969458b 100644
--- a/front/translations/en.json
+++ b/front/translations/en.json
@@ -2,6 +2,7 @@
"home": {
"recommanded": "Recommanded",
"news": "News",
+ "watchlist": "Continue watching",
"info": "See more",
"none": "No episodes"
},
diff --git a/front/translations/fr.json b/front/translations/fr.json
index 00dc0c3b..bb28f436 100644
--- a/front/translations/fr.json
+++ b/front/translations/fr.json
@@ -2,6 +2,7 @@
"home": {
"recommanded": "Recommandé",
"news": "Nouveautés",
+ "watchlist": "Continuer de regarder",
"info": "Voir plus",
"none": "Aucun episode"
},