/* * 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 { Movie, QueryIdentifier, Show, getDisplayDate, Genre, Studio, KyooImage, } from "@kyoo/models"; import { Container, H1, ImageBackground, Skeleton, Poster, P, tooltip, Link, IconButton, IconFab, Head, HR, H2, UL, LI, A, ts, Chip, DottedSeparator, focusReset, } from "@kyoo/primitives"; import { Fragment } from "react"; import { useTranslation } from "react-i18next"; import { ImageStyle, Platform, View } from "react-native"; import { Theme, md, px, min, max, em, percent, rem, vh, useYoshiki, Stylable, } from "yoshiki/native"; import { Fetch } from "../fetch"; import PlayArrow from "@material-symbols/svg-400/rounded/play_arrow-fill.svg"; import Theaters from "@material-symbols/svg-400/rounded/theaters-fill.svg"; import { Rating } from "../components/rating"; import { displayRuntime } from "./episode"; import { WatchListInfo } from "../components/watchlist-info"; import { WatchStatusV } from "@kyoo/models/src/resources/watch-status"; import { capitalize } from "@kyoo/primitives"; import { ShowWatchStatusCard } from "./show"; import Download from "@material-symbols/svg-400/rounded/download.svg"; import { useDownloader } from "../downloads"; export const TitleLine = ({ isLoading, playHref, name, tagline, date, rating, runtime, poster, studio, trailerUrl, type, watchStatus, slug, ...props }: { isLoading: boolean; playHref?: string | null; name?: string; tagline?: string | null; date?: string | null; rating?: number | null; runtime?: number | null; poster?: KyooImage | null; studio?: Studio | null; trailerUrl?: string | null; watchStatus?: WatchStatusV | null; type: "movie" | "show" | "collection"; slug?: string; } & Stylable) => { const { css, theme } = useYoshiki(); const { t } = useTranslation(); const downloader = useDownloader(); return (

{isLoading || ( <>

({ xs: theme.user.heading, md: theme.heading }), })} > {name}

{date && (

({ xs: theme.user.paragraph, md: theme.paragraph, }), })} > {" "} ({date})

)} )}

{(isLoading || tagline) && ( {isLoading || (

({ xs: theme.user.heading, md: theme.heading }), })} > {tagline}

)}
)} {playHref !== null && ( )} {trailerUrl && ( )} {watchStatus !== undefined && type !== "collection" && slug && ( )} {type === "movie" && slug && ( downloader(type, slug)} color={{ xs: theme.user.contrast, md: theme.colors.white }} {...tooltip(t("home.episodeMore.download"))} /> )} {rating !== null && ( <> )} {runtime && ( <>

{displayRuntime(runtime)}

)}
{isLoading || (studio && (

theme.user.paragraph, display: "flex", })} > {t("show.studio")}:{" "} {isLoading ? ( ) : ( theme.user.link })}> {studio.name} )}

))}
); }; const Description = ({ isLoading, overview, tags, genres, ...props }: { isLoading: boolean; overview?: string | null; tags?: string[]; genres?: Genre[]; } & Stylable) => { const { t } = useTranslation(); const { css } = useYoshiki(); return (

theme.user.paragraph, })} > {t("show.genre")}:{" "} {(isLoading ? [...Array(3)] : genres!).map((genre, i) => (

{i !== 0 && ", "}

{isLoading ? ( ) : ( {genre} )} ))}

{isLoading || (

{overview ?? t("show.noOverview")}

)}

{t("show.tags")}:

{(isLoading ? [...Array(3)] : tags!).map((tag, i) => ( ))}

{t("show.genre")}

{isLoading || genres?.length ? (
    {(isLoading ? [...Array(3)] : genres!).map((genre, i) => (
  • {isLoading ? ( ) : ( {genre} )}
  • ))}
) : (

{t("show.genre-none")}

)}
); }; export const Header = ({ query, type, }: { query: QueryIdentifier; type: "movie" | "show"; }) => { const { css } = useYoshiki(); const { t } = useTranslation(); return ( {({ isLoading, ...data }) => ( <>

{t("show.links")}:

{(!isLoading ? Object.entries(data.externalId!).filter(([_, data]) => data.link) : [...Array(3)].map((_) => [undefined, undefined] as const) ).map(([name, data], i) => ( ))}
{type === "show" && } )}
); }; Header.containerStyle = { height: { xs: vh(40), sm: min(vh(60), px(750)), md: min(vh(60), px(680)), lg: vh(70), }, minHeight: { xs: px(350), sm: px(300), md: px(400), lg: px(600) }, }; Header.childStyle = { marginTop: { xs: max(vh(20), px(200)), sm: vh(45), md: max(vh(30), px(150)), lg: max(vh(35), px(200)), }, };