From 95086777af34b2dd96991f515ad8ac7e66ad4a6e Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Fri, 24 May 2024 11:53:32 +0200 Subject: [PATCH 1/2] Split image backround and gradient image background --- front/packages/primitives/src/image/index.tsx | 113 ++++++++++-------- front/packages/ui/src/browse/list.tsx | 13 +- front/packages/ui/src/collection/index.tsx | 14 ++- front/packages/ui/src/details/collection.tsx | 21 +++- front/packages/ui/src/details/episode.tsx | 8 +- front/packages/ui/src/details/header.tsx | 6 +- front/packages/ui/src/downloads/page.tsx | 4 +- front/packages/ui/src/home/header.tsx | 5 +- 8 files changed, 108 insertions(+), 76 deletions(-) diff --git a/front/packages/primitives/src/image/index.tsx b/front/packages/primitives/src/image/index.tsx index 9eea507f..dca762e4 100644 --- a/front/packages/primitives/src/image/index.tsx +++ b/front/packages/primitives/src/image/index.tsx @@ -22,6 +22,7 @@ import { LinearGradient, type LinearGradientProps } from "expo-linear-gradient"; import type { ComponentProps, ComponentType, ReactElement, ReactNode } from "react"; import { type ImageStyle, View, type ViewProps, type ViewStyle } from "react-native"; import { percent } from "yoshiki/native"; +import { useYoshiki } from "yoshiki/native"; import { imageBorderRadius } from "../constants"; import { ContrastArea } from "../themes"; import type { ImageLayout, Props, YoshikiEnhanced } from "./base-image"; @@ -53,51 +54,50 @@ export const PosterBackground = ({ ...props }: Omit, "layout"> & { style?: ImageStyle } & { layout: YoshikiEnhanced<{ width: ImageStyle["width"] } | { height: ImageStyle["height"] }>; -}) => ( - -); +}) => { + const { css } = useYoshiki(); + + return ( + + ); +}; + +type ImageBackgroundProps = { + children?: ReactNode; + containerStyle?: YoshikiEnhanced; + imageStyle?: YoshikiEnhanced; + layout?: ImageLayout; + contrast?: "light" | "dark" | "user"; +}; export const ImageBackground = ({ src, alt, quality, - gradient = true, as, children, containerStyle, imageStyle, - forcedLoading, - hideLoad = true, - contrast = "dark", layout, + contrast = "dark", + imageSibling, ...asProps }: { as?: ComponentType; - gradient?: Partial | boolean; - children?: ReactNode; - containerStyle?: YoshikiEnhanced; - imageStyle?: YoshikiEnhanced; - hideLoad?: boolean; - contrast?: "light" | "dark" | "user"; - layout?: ImageLayout; + imageSibling?: ReactElement; } & AsProps & + ImageBackgroundProps & Props) => { const Container = as ?? View; + return ( - {({ css, theme }) => ( - + {({ css }) => ( + ({ containerStyle, ])} > - {(src || !hideLoad) && ( + {src && ( {alt!} )} - {gradient && ( - - )} + {imageSibling} {children} @@ -149,3 +131,40 @@ export const ImageBackground = ({ ); }; + +export const GradientImageBackground = ({ + contrast = "dark", + gradient, + ...props +}: { + as?: ComponentType; + gradient?: Partial; +} & AsProps & + ImageBackgroundProps & + Props) => { + const { css, theme } = useYoshiki(); + + return ( + + } + {...(props as any)} + /> + ); +}; diff --git a/front/packages/ui/src/browse/list.tsx b/front/packages/ui/src/browse/list.tsx index e3c6f125..00570e7f 100644 --- a/front/packages/ui/src/browse/list.tsx +++ b/front/packages/ui/src/browse/list.tsx @@ -20,8 +20,8 @@ import type { KyooImage, WatchStatusV } from "@kyoo/models"; import { + GradientImageBackground, Heading, - ImageBackground, Link, P, Poster, @@ -33,7 +33,6 @@ import { } from "@kyoo/primitives"; import { useState } from "react"; import { Platform, View } from "react-native"; -import type { Stylable } from "yoshiki"; import { percent, px, rem, useYoshiki } from "yoshiki/native"; import { ItemContext } from "../components/context-menus"; import type { Layout } from "../fetch"; @@ -65,19 +64,13 @@ export const ItemList = ({ const [moreOpened, setMoreOpened] = useState(false); return ( - setMoreOpened(true)} - containerStyle={{ - borderRadius: px(imageBorderRadius), - }} - imageStyle={{ - borderRadius: px(imageBorderRadius), - }} {...css( { alignItems: "center", @@ -162,7 +155,7 @@ export const ItemList = ({ - + ); }; diff --git a/front/packages/ui/src/collection/index.tsx b/front/packages/ui/src/collection/index.tsx index 978cdec1..eff48457 100644 --- a/front/packages/ui/src/collection/index.tsx +++ b/front/packages/ui/src/collection/index.tsx @@ -27,7 +27,15 @@ import { type QueryPage, getDisplayDate, } from "@kyoo/models"; -import { Container, Head, ImageBackground, P, Skeleton, ts, usePageStyle } from "@kyoo/primitives"; +import { + Container, + GradientImageBackground, + Head, + P, + Skeleton, + ts, + usePageStyle, +} from "@kyoo/primitives"; import { forwardRef } from "react"; import { useTranslation } from "react-i18next"; import { Platform, View, type ViewProps } from "react-native"; @@ -50,7 +58,7 @@ const Header = ({ slug }: { slug: string }) => { <> - { studio={null} {...css(ShowHeader.childStyle)} /> - + -

{overview}

-
+ ); }; diff --git a/front/packages/ui/src/details/episode.tsx b/front/packages/ui/src/details/episode.tsx index 88fa3dfb..4435cee7 100644 --- a/front/packages/ui/src/details/episode.tsx +++ b/front/packages/ui/src/details/episode.tsx @@ -30,6 +30,7 @@ import { Skeleton, SubP, focusReset, + imageBorderRadius, important, tooltip, ts, @@ -98,6 +99,7 @@ export const EpisodeBox = ({ borderColor: (theme) => theme.background, borderWidth: ts(0.5), borderStyle: "solid", + borderRadius: imageBorderRadius, }, more: { opacity: 0, @@ -123,9 +125,8 @@ export const EpisodeBox = ({ src={thumbnail} quality="low" alt="" - gradient={false} layout={{ width: percent(100), aspectRatio: 16 / 9 }} - {...(css("poster") as any)} + {...css("poster")} > {(watchedPercent || watchedStatus === WatchStatusV.Completed) && ( @@ -254,12 +255,11 @@ export const EpisodeLine = ({ src={thumbnail} quality="low" alt="" - gradient={false} layout={{ width: percent(18), aspectRatio: 16 / 9, }} - {...(css({ flexShrink: 0, m: ts(1) }) as { style: ImageStyle })} + {...css({ flexShrink: 0, m: ts(1) })} > {(watchedPercent || watchedStatus === WatchStatusV.Completed) && ( <> diff --git a/front/packages/ui/src/details/header.tsx b/front/packages/ui/src/details/header.tsx index fe241404..22ab23be 100644 --- a/front/packages/ui/src/details/header.tsx +++ b/front/packages/ui/src/details/header.tsx @@ -35,13 +35,13 @@ import { Chip, Container, DottedSeparator, + GradientImageBackground, H1, H2, HR, Head, IconButton, IconFab, - ImageBackground, LI, Link, Menu, @@ -509,7 +509,7 @@ export const Header = ({ {({ isLoading, ...data }) => ( <> - - + {/* {(watchedPercent || watchedStatus === WatchStatusV.Completed) && ( */} {/* <> */} diff --git a/front/packages/ui/src/home/header.tsx b/front/packages/ui/src/home/header.tsx index f26e2e13..4613b2c5 100644 --- a/front/packages/ui/src/home/header.tsx +++ b/front/packages/ui/src/home/header.tsx @@ -20,6 +20,7 @@ import { type KyooImage, type LibraryItem, LibraryItemP, type QueryIdentifier } from "@kyoo/models"; import { + GradientImageBackground, H1, H2, IconButton, @@ -60,7 +61,7 @@ export const Header = ({ const { t } = useTranslation(); return ( - - + ); }; From 4cc36f469022078d3c921056731a5e75b1acdd19 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sat, 25 May 2024 02:49:26 +0200 Subject: [PATCH 2/2] Migrate from next image to img --- .../primitives/src/image/blurhash.web.tsx | 28 +++++++++++-------- .../primitives/src/image/image.web.tsx | 23 +++++++++------ 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/front/packages/primitives/src/image/blurhash.web.tsx b/front/packages/primitives/src/image/blurhash.web.tsx index dc8bc80e..b1cf4ed6 100644 --- a/front/packages/primitives/src/image/blurhash.web.tsx +++ b/front/packages/primitives/src/image/blurhash.web.tsx @@ -276,6 +276,18 @@ const BlurhashDiv = forwardRef< ); }); +export const useRenderType = () => { + const [renderType, setRenderType] = useState<"ssr" | "hydratation" | "client">( + typeof window === "undefined" ? "ssr" : "hydratation", + ); + + useLayoutEffect(() => { + setRenderType("client"); + }, []); + + return renderType; +}; + export const BlurhashContainer = ({ blurhash, children, @@ -285,15 +297,7 @@ export const BlurhashContainer = ({ children?: ReactElement | ReactElement[]; }) => { const { css } = useYoshiki(); - const ref = useRef(null); - const [renderType, setRenderType] = useState<"ssr" | "hydratation" | "client">( - typeof window === "undefined" ? "ssr" : "hydratation", - ); - - useLayoutEffect(() => { - // If the html is empty, it was not SSRed. - if (ref.current?.innerHTML === "") setRenderType("client"); - }, []); + const renderType = useRenderType(); return (
- {renderType === "ssr" && } - {renderType === "client" && } + {renderType === "ssr" && } + {renderType === "client" && } {renderType === "hydratation" && ( -
+
)} {children}
diff --git a/front/packages/primitives/src/image/image.web.tsx b/front/packages/primitives/src/image/image.web.tsx index 77fb650b..9f26e178 100644 --- a/front/packages/primitives/src/image/image.web.tsx +++ b/front/packages/primitives/src/image/image.web.tsx @@ -25,7 +25,7 @@ import { useYoshiki } from "yoshiki/native"; import { imageBorderRadius } from "../constants"; import { Skeleton } from "../skeleton"; import type { ImageLayout, Props } from "./base-image"; -import { BlurhashContainer } from "./blurhash.web"; +import { BlurhashContainer, useRenderType } from "./blurhash.web"; export const Image = ({ src, @@ -54,18 +54,25 @@ export const Image = ({ return ( - setState("finished")} onError={() => setState("errored")} suppressHydrationWarning