diff --git a/front/packages/ui/src/browse/grid.tsx b/front/packages/ui/src/browse/grid.tsx index 4f24c280..fb88bf92 100644 --- a/front/packages/ui/src/browse/grid.tsx +++ b/front/packages/ui/src/browse/grid.tsx @@ -22,7 +22,6 @@ import { KyooImage, WatchStatusV } from "@kyoo/models"; import { Link, Skeleton, - Poster, ts, focusReset, P, @@ -31,7 +30,7 @@ import { Icon, } from "@kyoo/primitives"; import { ImageStyle, View } from "react-native"; -import { percent, px, rem, Stylable, Theme, useYoshiki } from "yoshiki/native"; +import { percent, px, Stylable, Theme, useYoshiki } from "yoshiki/native"; import { Layout, WithLoading } from "../fetch"; import Done from "@material-symbols/svg-400/rounded/done-fill.svg"; @@ -41,14 +40,16 @@ export const ItemGrid = ({ subtitle, poster, isLoading, - watchInfo, + watchStatus, + unseenEpisodesCount, ...props }: WithLoading<{ href: string; name: string; subtitle?: string; poster?: KyooImage | null; - watchInfo: WatchStatusV | string | null; + watchStatus: WatchStatusV | null; + unseenEpisodesCount: number | null; }> & Stylable<"text">) => { const { css } = useYoshiki("grid"); @@ -89,7 +90,7 @@ export const ItemGrid = ({ layout={{ width: percent(100) }} {...(css("poster") as { style: ImageStyle })} > - {watchInfo && ( + {(watchStatus === WatchStatusV.Completed || unseenEpisodesCount) && ( - {watchInfo === WatchStatusV.Completed ? ( + {watchStatus === WatchStatusV.Completed ? ( ) : ( -

{watchInfo}

+

{unseenEpisodesCount}

)}
)} diff --git a/front/packages/ui/src/browse/index.tsx b/front/packages/ui/src/browse/index.tsx index 9de6c1cb..78cc2a63 100644 --- a/front/packages/ui/src/browse/index.tsx +++ b/front/packages/ui/src/browse/index.tsx @@ -25,7 +25,6 @@ import { LibraryItemP, ItemKind, getDisplayDate, - WatchStatusV, } from "@kyoo/models"; import { ComponentProps, useState } from "react"; import { createParam } from "solito"; @@ -42,16 +41,7 @@ const { useParam } = createParam<{ sortBy?: string }>(); export const itemMap = ( item: WithLoading, ): WithLoading & ComponentProps> => { - if (item.isLoading) return item; - - let watchInfo: string | WatchStatusV | null = null; - if (item.kind !== ItemKind.Collection && item.watchStatus?.status === WatchStatusV.Completed) - watchInfo = WatchStatusV.Completed; - else if (item.kind === ItemKind.Show) { - if (!item.watchStatus) watchInfo = item.episodesCount!.toString(); - else if (item.watchStatus.status === WatchStatusV.Watching) - watchInfo = item.watchStatus.unseenEpisodesCount.toString(); - } + if (item.isLoading) return item as any; return { isLoading: item.isLoading, @@ -60,7 +50,11 @@ export const itemMap = ( href: item.href, poster: item.poster, thumbnail: item.thumbnail, - watchInfo: watchInfo, + watchStatus: item.kind !== ItemKind.Collection ? item.watchStatus?.status ?? null : null, + unseenEpisodesCount: + item.kind === ItemKind.Show + ? item.watchStatus?.unseenEpisodesCount ?? item.episodesCount! + : null, }; }; diff --git a/front/packages/ui/src/browse/list.tsx b/front/packages/ui/src/browse/list.tsx index 28652840..e42cece7 100644 --- a/front/packages/ui/src/browse/list.tsx +++ b/front/packages/ui/src/browse/list.tsx @@ -18,12 +18,23 @@ * along with Kyoo. If not, see . */ -import { KyooImage } from "@kyoo/models"; -import { Link, P, Skeleton, ts, ImageBackground, Poster, Heading } from "@kyoo/primitives"; +import { KyooImage, WatchStatusV } from "@kyoo/models"; +import { + Link, + P, + Skeleton, + ts, + ImageBackground, + Poster, + Heading, + Icon, + PosterBackground, +} from "@kyoo/primitives"; import { useState } from "react"; import { View } from "react-native"; import { percent, px, rem, useYoshiki } from "yoshiki/native"; import { Layout, WithLoading } from "../fetch"; +import Done from "@material-symbols/svg-400/rounded/done-fill.svg"; export const ItemList = ({ href, @@ -32,12 +43,17 @@ export const ItemList = ({ thumbnail, poster, isLoading, + watchStatus, + unseenEpisodesCount, + ...props }: WithLoading<{ href: string; name: string; subtitle?: string; poster?: KyooImage | null; thumbnail?: KyooImage | null; + watchStatus: WatchStatusV | null; + unseenEpisodesCount: number | null; }>) => { const { css } = useYoshiki(); const [isHovered, setHovered] = useState(0); @@ -59,14 +75,17 @@ export const ItemList = ({ imageStyle={{ borderRadius: px(6), }} - {...css({ - alignItems: "center", - justifyContent: "space-evenly", - flexDirection: "row", - height: ItemList.layout.size, - borderRadius: px(6), - marginX: ItemList.layout.gap, - })} + {...css( + { + alignItems: "center", + justifyContent: "space-evenly", + flexDirection: "row", + height: ItemList.layout.size, + borderRadius: px(6), + marginX: ItemList.layout.gap, + }, + props, + )} > )} - + > + {(watchStatus === WatchStatusV.Completed || unseenEpisodesCount) && ( + theme.darkOverlay, + borderRadius: 999999, + })} + > + {watchStatus === WatchStatusV.Completed ? ( + + ) : ( +

{unseenEpisodesCount}

+ )} +
+ )} + ); }; diff --git a/front/packages/ui/src/home/recommanded.tsx b/front/packages/ui/src/home/recommanded.tsx index e6c987f7..966fa517 100644 --- a/front/packages/ui/src/home/recommanded.tsx +++ b/front/packages/ui/src/home/recommanded.tsx @@ -25,15 +25,17 @@ import { LibraryItem, LibraryItemP, QueryIdentifier, + WatchStatusV, getDisplayDate, } from "@kyoo/models"; import { Chip, H3, + Icon, IconFab, - ImageBackground, Link, P, + PosterBackground, Skeleton, SubP, focusReset, @@ -48,6 +50,7 @@ import { Layout, WithLoading } from "../fetch"; import { InfiniteFetch } from "../fetch-infinite"; import PlayArrow from "@material-symbols/svg-400/rounded/play_arrow-fill.svg"; import { ItemGrid } from "../browse/grid"; +import Done from "@material-symbols/svg-400/rounded/done-fill.svg"; export const ItemDetails = ({ isLoading, @@ -59,6 +62,8 @@ export const ItemDetails = ({ genres, href, playHref, + watchStatus, + unseenEpisodesCount, ...props }: WithLoading<{ name: string; @@ -69,6 +74,8 @@ export const ItemDetails = ({ overview: string | null; href: string; playHref: string | null; + watchStatus: WatchStatusV | null; + unseenEpisodesCount: number | null; }>) => { const { push } = useRouter(); const { t } = useTranslation(); @@ -100,13 +107,12 @@ export const ItemDetails = ({ props, )} > - )} - + {(watchStatus === WatchStatusV.Completed || unseenEpisodesCount) && ( + theme.darkOverlay, + borderRadius: 999999, + })} + > + {watchStatus === WatchStatusV.Completed ? ( + + ) : ( +

{unseenEpisodesCount}

+ )} +
+ )} + {(isLoading || tagline) && ( @@ -195,7 +223,7 @@ export const Recommanded = () => { fetchMore={false} {...css({ padding: 0 })} > - {(x, i) => ( + {(x) => ( { genres={"genres" in x ? x.genres : null} href={x.href} playHref={x.kind !== ItemKind.Collection && !x.isLoading ? x.playHref : undefined} + watchStatus={ + !x.isLoading && x.kind !== ItemKind.Collection ? x.watchStatus?.status ?? null : null + } + unseenEpisodesCount={ + x.kind === ItemKind.Show + ? x.watchStatus?.unseenEpisodesCount ?? x.episodesCount! + : null + } /> )} @@ -222,6 +258,6 @@ Recommanded.query = (): QueryIdentifier => ({ params: { sortBy: "random", limit: 6, - fields: ["firstEpisode"], + fields: ["firstEpisode", "episodesCount", "watchStatus"], }, }); diff --git a/front/packages/ui/src/home/vertical.tsx b/front/packages/ui/src/home/vertical.tsx index 2068dde8..f0fcf2ac 100644 --- a/front/packages/ui/src/home/vertical.tsx +++ b/front/packages/ui/src/home/vertical.tsx @@ -26,6 +26,7 @@ import { InfiniteFetch } from "../fetch-infinite"; import { ItemList } from "../browse/list"; import { useTranslation } from "react-i18next"; import { ItemGrid } from "../browse/grid"; +import { itemMap } from "../browse"; export const VerticalRecommanded = () => { const { t } = useTranslation(); @@ -40,19 +41,7 @@ export const VerticalRecommanded = () => { layout={{ ...ItemList.layout, layout: "vertical" }} fetchMore={false} > - {(x, i) => ( - - )} + {(x, i) => } ); @@ -63,6 +52,7 @@ VerticalRecommanded.query = (): QueryIdentifier => ({ infinite: true, path: ["items"], params: { + fields: ["episodesCount", "watchStatus"], sortBy: "random", limit: 3, },