diff --git a/front/packages/primitives/src/container.tsx b/front/packages/primitives/src/container.tsx index 0fcedcd8..b85b15ff 100644 --- a/front/packages/primitives/src/container.tsx +++ b/front/packages/primitives/src/container.tsx @@ -35,7 +35,7 @@ export const Container = ({ { display: "flex", paddingHorizontal: px(15), - marginHorizontal: "auto", + alignSelf: "center", width: { xs: percent(100), sm: px(540), diff --git a/front/packages/primitives/src/divider.tsx b/front/packages/primitives/src/divider.tsx index ce2f5fef..9ba164b9 100644 --- a/front/packages/primitives/src/divider.tsx +++ b/front/packages/primitives/src/divider.tsx @@ -24,9 +24,9 @@ import { alpha } from "./themes"; import { ts } from "./utils"; export const HR = ({ - orientation, + orientation = "horizontal", ...props -}: { orientation: "vertical" | "horizontal" } & Stylable) => { +}: { orientation?: "vertical" | "horizontal" } & Stylable) => { const { css } = useYoshiki(); return ( diff --git a/front/packages/ui/src/browse/grid.tsx b/front/packages/ui/src/browse/grid.tsx index 560f599b..0901610e 100644 --- a/front/packages/ui/src/browse/grid.tsx +++ b/front/packages/ui/src/browse/grid.tsx @@ -87,5 +87,5 @@ export const ItemGrid = ({ ItemGrid.layout = { size: px(150), - numColumns: { xs: 3, md: 5, xl: 7 }, + numColumns: { xs: 3, sm: 5, xl: 7 }, } satisfies Layout; diff --git a/front/packages/ui/src/details/episode.tsx b/front/packages/ui/src/details/episode.tsx index b844f0a4..5fa49b11 100644 --- a/front/packages/ui/src/details/episode.tsx +++ b/front/packages/ui/src/details/episode.tsx @@ -22,7 +22,7 @@ import { H6, Image, Link, P, Skeleton, ts } from "@kyoo/primitives"; import { useTranslation } from "react-i18next"; import { View } from "react-native"; import { Layout, WithLoading } from "../fetch"; -import { percent, rem, Stylable, useYoshiki, vw } from "yoshiki/native"; +import { percent, rem, Stylable, useYoshiki } from "yoshiki/native"; export const episodeDisplayNumber = ( episode: { @@ -111,5 +111,5 @@ export const EpisodeLine = ({ }; EpisodeLine.layout = { numColumns: 1, - size: 100, //vw(18) / (16 / 9) + ts(2), + size: 100, } satisfies Layout; diff --git a/front/packages/ui/src/details/header.tsx b/front/packages/ui/src/details/header.tsx index 62281668..d1c37c5f 100644 --- a/front/packages/ui/src/details/header.tsx +++ b/front/packages/ui/src/details/header.tsx @@ -40,7 +40,7 @@ import { } from "@kyoo/primitives"; import { Fragment } from "react"; import { useTranslation } from "react-i18next"; -import { View } from "react-native"; +import { Platform, View } from "react-native"; import { Theme, md, @@ -55,8 +55,8 @@ import { 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 PlayArrow from "@material-symbols/svg-400/rounded/play_arrow-fill.svg"; +import Theaters from "@material-symbols/svg-400/rounded/theaters-fill.svg"; const TitleLine = ({ isLoading, @@ -100,7 +100,10 @@ const TitleLine = ({ layout={{ width: { xs: percent(50), md: percent(25) }, }} - {...css({ maxWidth: { xs: px(175), sm: "unset" }, flexShrink: 0 })} + {...css({ + maxWidth: { xs: px(175), sm: Platform.OS === "web" ? "unset" : 99999999 }, + flexShrink: 0, + })} /> { +export const EpisodeList = ({ + slug, + season, + Header, +}: { + slug: string; + season: string | number; + Header: ComponentType<{ children: JSX.Element }>; +}) => { const { t } = useTranslation(); return ( {(item) => ( => ({ +EpisodeList.query = (slug: string, season: string | number): QueryIdentifier => ({ parser: EpisodeP, path: ["shows", slug, "episode"], params: { @@ -57,47 +66,34 @@ EpisodeGrid.query = (slug: string, season: string | number): QueryIdentifier ( - - - -); - export const SeasonTab = ({ slug, season, ...props }: { slug: string; season: number | string } & Stylable) => { // TODO: handle absolute number only shows (without seasons) + return null; return ( - - {({ css, theme }) => ( - - - theme.background }, props)}> - - {/* setSeason(i)} aria-label="List of seasons"> */} - {/* {seasons */} - {/* ? seasons.map((x) => ( */} - {/* */} - {/* )) */} - {/* : [...Array(3)].map((_, i) => ( */} - {/* } value={i + 1} disabled /> */} - {/* ))} */} - {/* */} - - - - - )} - + + + {/* setSeason(i)} aria-label="List of seasons"> */} + {/* {seasons */} + {/* ? seasons.map((x) => ( */} + {/* */} + {/* )) */} + {/* : [...Array(3)].map((_, i) => ( */} + {/* } value={i + 1} disabled /> */} + {/* ))} */} + {/* */} + + ); }; diff --git a/front/packages/ui/src/details/show.tsx b/front/packages/ui/src/details/show.tsx index 70dabb70..1b23769c 100644 --- a/front/packages/ui/src/details/show.tsx +++ b/front/packages/ui/src/details/show.tsx @@ -19,11 +19,27 @@ */ import { QueryIdentifier, QueryPage, Show, ShowP } from "@kyoo/models"; -import { Platform, ScrollView } from "react-native"; -import { useYoshiki } from "yoshiki/native"; +import { Platform, ScrollView, View, ViewProps } from "react-native"; +import { percent, useYoshiki, vh } from "yoshiki/native"; import { TransparentLayout } from "../layout"; -import { SeasonTab } from "./season"; +import { EpisodeList, SeasonTab } from "./season"; import { Header } from "./header"; +import Svg, { Path, SvgProps } from "react-native-svg"; +import { Container, SwitchVariant } from "@kyoo/primitives"; + +const SvgWave = (props: SvgProps) => { + const { css } = useYoshiki(); + const width = 612; + const height = 52.771; + + return ( + + + + + + ); +}; const query = (slug: string): QueryIdentifier => ({ parser: ShowP, @@ -34,14 +50,39 @@ const query = (slug: string): QueryIdentifier => ({ }); export const ShowDetails: QueryPage<{ slug: string; season: string }> = ({ slug, season }) => { - const { css } = useYoshiki(); + const { css, theme } = useYoshiki(); - return ( - + const ShowHeader = ({ children, ...props }: ViewProps) => ( + theme.background }, + Platform.OS === "web" && { flexGrow: 1, flexShrink: 1, overflow: "overlay" as any }, + ], + props, + )} + >
{/* */} - - + + {/* */} + + {children} + + + ); + + return ( + + {({ css, theme }) => ( + + + + )} + ); }; diff --git a/front/packages/ui/src/fetch-infinite.tsx b/front/packages/ui/src/fetch-infinite.tsx index c4854fec..6fc94b2c 100644 --- a/front/packages/ui/src/fetch-infinite.tsx +++ b/front/packages/ui/src/fetch-infinite.tsx @@ -21,7 +21,7 @@ import { Page, QueryIdentifier, useInfiniteFetch } from "@kyoo/models"; import { useBreakpointMap, HR } from "@kyoo/primitives"; import { FlashList } from "@shopify/flash-list"; -import { ReactElement } from "react"; +import { ComponentType, ReactElement } from "react"; import { EmptyView, ErrorView, Layout, WithLoading } from "./fetch"; export const InfiniteFetch = ({ @@ -32,6 +32,7 @@ export const InfiniteFetch = ({ layout, empty, divider = false, + Header, ...props }: { query: QueryIdentifier; @@ -43,7 +44,8 @@ export const InfiniteFetch = ({ i: number, ) => ReactElement | null; empty?: string | JSX.Element; - divider?: boolean | JSX.Element; + divider?: boolean | ComponentType; + Header?: ComponentType<{ children: JSX.Element }>; }): JSX.Element | null => { if (!query.infinite) console.warn("A non infinite query was passed to an InfiniteFetch."); @@ -57,26 +59,14 @@ export const InfiniteFetch = ({ return ; } + const placeholders = [ + ...Array(items ? numColumns - (items.length % numColumns) + numColumns : placeholderCount), + ].map((_, i) => ({ id: `gen${i}`, isLoading: true } as Data)); + return ( ( - <> - {(divider === true && index !== 0) ?
: divider} - {children({ isLoading: false, ...item } as any, index)} - - )} - data={ - hasNextPage - ? [ - ...(items || []), - ...[ - ...Array( - items ? numColumns - (items.length % numColumns) + numColumns : placeholderCount, - ), - ].map((_, i) => ({ id: `gen${i}`, isLoading: true } as Data)), - ] - : items - } + renderItem={({ item, index }) => children({ isLoading: false, ...item } as any, index)} + data={hasNextPage !== false ? [...(items || []), ...placeholders] : items} horizontal={horizontal} keyExtractor={(item: any) => item.id?.toString()} numColumns={numColumns} @@ -85,6 +75,8 @@ export const InfiniteFetch = ({ onEndReachedThreshold={0.5} onRefresh={refetch} refreshing={isRefetching} + ItemSeparatorComponent={divider === true ? HR : divider || null} + ListHeaderComponent={Header} {...props} /> ); diff --git a/front/packages/ui/src/fetch-infinite.web.tsx b/front/packages/ui/src/fetch-infinite.web.tsx index 44f0d859..11da71d7 100644 --- a/front/packages/ui/src/fetch-infinite.web.tsx +++ b/front/packages/ui/src/fetch-infinite.web.tsx @@ -20,7 +20,7 @@ import { Page, QueryIdentifier, useInfiniteFetch } from "@kyoo/models"; import { HR } from "@kyoo/primitives"; -import { Fragment, ReactElement, useRef } from "react"; +import { ComponentType, Fragment, ReactElement, useRef } from "react"; import { Stylable, useYoshiki } from "yoshiki"; import { EmptyView, ErrorView, Layout, WithLoading } from "./fetch"; @@ -93,7 +93,8 @@ export const InfiniteFetch = ({ layout, horizontal = false, empty, - divider = false, + divider: Divider = false, + Header, ...props }: { query: QueryIdentifier; @@ -105,7 +106,8 @@ export const InfiniteFetch = ({ i: number, ) => ReactElement | null; empty?: string | JSX.Element; - divider?: boolean | JSX.Element; + divider?: boolean | ComponentType; + Header?: ComponentType<{ children: JSX.Element }>; }): JSX.Element | null => { if (!query.infinite) console.warn("A non infinite query was passed to an InfiniteFetch."); @@ -118,7 +120,7 @@ export const InfiniteFetch = ({ return ; } - return ( + const list = ( ({ isFetching={isFetching} loader={[...Array(12)].map((_, i) => ( - {(divider === true && i !== 0) ?
: divider} + {Divider && i !== 0 && (Divider === true ?
: )} {children({ isLoading: true } as any, i)}
))} @@ -134,10 +136,12 @@ export const InfiniteFetch = ({ > {items?.map((item, i) => ( - {(divider === true && i !== 0) ?
: divider} + {Divider && i !== 0 && (Divider === true ?
: )} {children({ ...item, isLoading: false } as any, i)}
))}
); + + return Header ?
{list}
: list; }; diff --git a/front/packages/ui/src/fetch.tsx b/front/packages/ui/src/fetch.tsx index 7aa689e6..70b64852 100644 --- a/front/packages/ui/src/fetch.tsx +++ b/front/packages/ui/src/fetch.tsx @@ -48,10 +48,12 @@ export const Fetch = ({ const { data, error } = useFetch(query); if (error) return ; - if (!data) - return ( - <>{[...Array(placeholderCount)].map((_, i) => children({ isLoading: true } as any, i))} + if (!data) { + const placeholders = [...Array(placeholderCount)].map((_, i) => + children({ isLoading: true } as any, i), ); + return <>{placeholderCount === 1 ? placeholders[0] : placeholders}; + } if (!isPage(data)) return children(data ? { ...data, isLoading: false } : ({ isLoading: true } as any), 0); return <>{data.items.map((item, i) => children({ ...item, isLoading: false } as any, i))};