diff --git a/front/packages/primitives/src/chip.tsx b/front/packages/primitives/src/chip.tsx index c16f4de1..1c757ce8 100644 --- a/front/packages/primitives/src/chip.tsx +++ b/front/packages/primitives/src/chip.tsx @@ -22,8 +22,7 @@ import { px, rem, Theme, useYoshiki } from "yoshiki/native"; import { Link } from "./links"; import { P } from "./text"; import { capitalize, ts } from "./utils"; -import { EnhancedStyle } from "yoshiki/src/native/type"; -import { TextProps, TextStyle, ViewStyle } from "react-native"; +import { TextProps } from "react-native"; import { Skeleton } from "./skeleton"; export const Chip = ({ diff --git a/front/packages/primitives/src/icons.tsx b/front/packages/primitives/src/icons.tsx index 287c7f8b..becd5c5c 100644 --- a/front/packages/primitives/src/icons.tsx +++ b/front/packages/primitives/src/icons.tsx @@ -87,6 +87,7 @@ export const IconButton = forwardRef(function IconButton { + let marginLeft = 0; + let marginRight = 0; + + if (layout !== "vertical" && numColumns > 1) { + if (index % numColumns === 0) { + marginRight = (gap * 2) / 3; + } else if ((index + 1) % numColumns === 0) { + marginLeft = (gap * 2) / 3; + } else { + marginLeft = gap / 3; + marginRight = gap / 3; + } + } + + return { + marginLeft, + marginRight, + marginTop: layout !== "horizontal" && index >= numColumns ? gap : 0, + }; +}; export const InfiniteFetchList = ({ query, @@ -37,6 +64,7 @@ export const InfiniteFetchList = ({ headerProps, getItemType, fetchMore = true, + contentContainerStyle, ...props }: { query: ReturnType>; @@ -54,10 +82,11 @@ export const InfiniteFetchList = ({ headerProps?: Props; getItemType?: (item: WithLoading, index: number) => string | number; fetchMore?: boolean; + contentContainerStyle?: ContentStyle; }): JSX.Element | null => { const { numColumns, size, gap } = useBreakpointMap(layout); const oldItems = useRef(); - let { items, error, fetchNextPage, hasNextPage, isFetching, refetch, isRefetching } = query; + let { items, error, fetchNextPage, isFetching, refetch, isRefetching } = query; if (incremental && items) oldItems.current = items; if (error) return ; @@ -77,15 +106,11 @@ export const InfiniteFetchList = ({ return ( ( - + {children({ isLoading: false, ...item } as any, index)} )} diff --git a/front/packages/ui/src/fetch-infinite.web.tsx b/front/packages/ui/src/fetch-infinite.web.tsx index 3f691b73..53e77245 100644 --- a/front/packages/ui/src/fetch-infinite.web.tsx +++ b/front/packages/ui/src/fetch-infinite.web.tsx @@ -32,6 +32,8 @@ import { } from "react"; import { Stylable, nativeStyleToCss, useYoshiki, ysMap } from "yoshiki"; import { EmptyView, ErrorView, Layout, WithLoading, addHeader } from "./fetch"; +import { ViewStyle } from "react-native"; +import type { ContentStyle } from "@shopify/flash-list"; const InfiniteScroll = ({ children, @@ -43,6 +45,7 @@ const InfiniteScroll = ({ Header, headerProps, fetchMore = true, + contentContainerStyle, ...props }: { children?: ReactElement | (ReactElement | null)[] | null; @@ -54,6 +57,7 @@ const InfiniteScroll = ({ Header?: ComponentType | ReactElement; headerProps?: Props; fetchMore?: boolean; + contentContainerStyle?: ContentStyle; } & Stylable) => { const ref = useRef(null); const { css } = useYoshiki(); @@ -110,6 +114,7 @@ const InfiniteScroll = ({ overflowY: "auto", padding: layout.gap as any, }, + contentContainerStyle as any, ], nativeStyleToCss(props), )} @@ -162,6 +167,7 @@ export const InfiniteFetchList = ({ headerProps: HeaderProps; getItemType?: (item: WithLoading, index: number) => string | number; fetchMore?: boolean; + contentContainerStyle?: ContentStyle; }): JSX.Element | null => { const oldItems = useRef(); const { items, error, fetchNextPage, hasNextPage, isFetching } = query; diff --git a/front/packages/ui/src/home/recommanded.tsx b/front/packages/ui/src/home/recommanded.tsx index 226925b2..c4b31e85 100644 --- a/front/packages/ui/src/home/recommanded.tsx +++ b/front/packages/ui/src/home/recommanded.tsx @@ -44,14 +44,12 @@ import { ts, } from "@kyoo/primitives"; import { useTranslation } from "react-i18next"; -import { Pressable, ScrollView, View } from "react-native"; -import { useRouter } from "solito/router"; +import { ScrollView, View } from "react-native"; import { Theme, calc, percent, px, rem, useYoshiki } from "yoshiki/native"; import { Layout, WithLoading } from "../fetch"; import { InfiniteFetch } from "../fetch-infinite"; import PlayArrow from "@material-symbols/svg-400/rounded/play_arrow-fill.svg"; import { ItemGrid, ItemWatchStatus } from "../browse/grid"; -import Done from "@material-symbols/svg-400/rounded/done-fill.svg"; export const ItemDetails = ({ isLoading, @@ -78,111 +76,134 @@ export const ItemDetails = ({ watchStatus: WatchStatusV | null; unseenEpisodesCount: number | null; }>) => { - const { push } = useRouter(); const { t } = useTranslation(); const { css } = useYoshiki("recommanded-card"); return ( - theme.variant.background, - borderRadius: calc(px(imageBorderRadius), "+", ts(0.25)), - overflow: "hidden", - borderColor: (theme) => theme.background, - borderWidth: ts(0.25), - borderStyle: "solid", - fover: { - self: { - ...focusReset, - borderColor: (theme: Theme) => theme.accent, - }, - title: { - textDecorationLine: "underline", - }, - }, - }, - props, - )} + - - theme.darkOverlay, + theme.variant.background, + borderRadius: calc(px(imageBorderRadius), "+", ts(0.25)), + overflow: "hidden", + borderColor: (theme) => theme.background, + borderWidth: ts(0.25), + borderStyle: "solid", + fover: { + self: { + ...focusReset, + borderColor: (theme: Theme) => theme.accent, + }, + title: { + textDecorationLine: "underline", + }, + }, + }, + props, + )} + > + - - {isLoading || ( -

theme.colors.white }, "title"])}> - {name} -

+ theme.darkOverlay, + position: "absolute", + left: 0, + right: 0, + bottom: 0, + p: ts(1), + })} + > + + {isLoading || ( +

theme.colors.white }, "title"])}> + {name} +

+ )} +
+ {(subtitle || isLoading) && ( + + {isLoading || {subtitle}} + )} -
- {(subtitle || isLoading) && ( - - {isLoading || {subtitle}} +
+ +
+ + {(isLoading || tagline) && ( + + {isLoading ||

{tagline}

}
)} + + + {isLoading || ( + {overview ?? t("show.noOverview")} + )} + +
- - - - {(isLoading || tagline) && ( - - {isLoading ||

{tagline}

} -
+ + + {/* This view needs to be out of the Link because nested are not allowed on the web */} + theme.themeOverlay, + flexDirection: "row", + pX: 4, + justifyContent: "flex-end", + height: px(50), + })} + > + {(isLoading || genres) && ( + + {(genres || [...Array(3)])?.map((x, i) => ( + + ))} + + )} + {playHref !== null && ( + )} - - - {isLoading || ( - {overview ?? t("show.noOverview")} - )} - - - theme.themeOverlay, - flexDirection: "row", - pX: 4, - justifyContent: "flex-end", - minHeight: px(50), - })} - > - {(isLoading || genres) && ( - - {(genres || [...Array(3)])?.map((x, i) => ( - - ))} - - )} - {playHref !== null && ( - push(playHref ?? "")} - {...tooltip(t("show.play"))} - {...css({ fover: { self: { transform: "scale(1.2)" as any, mX: ts(0.5) } } })} - /> - )} - - +
); }; @@ -205,7 +226,7 @@ export const Recommanded = () => { layout={ItemDetails.layout} placeholderCount={6} fetchMore={false} - {...css({ padding: 0 })} + contentContainerStyle={{ padding: 0, paddingHorizontal: 0 }} > {(x) => (