mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-09 03:04:20 -04:00
Disable empty genre list during ssr
This commit is contained in:
parent
11712b5b13
commit
fc598838c4
@ -22,7 +22,7 @@ import { Page, QueryIdentifier, useInfiniteFetch } from "@kyoo/models";
|
||||
import { useBreakpointMap, HR } from "@kyoo/primitives";
|
||||
import { FlashList } from "@shopify/flash-list";
|
||||
import { ComponentType, isValidElement, ReactElement, useRef } from "react";
|
||||
import { EmptyView, ErrorView, Layout, WithLoading } from "./fetch";
|
||||
import { EmptyView, ErrorView, Layout, WithLoading, addHeader } from "./fetch";
|
||||
|
||||
export const InfiniteFetch = <Data, Props, _>({
|
||||
query,
|
||||
@ -33,7 +33,7 @@ export const InfiniteFetch = <Data, Props, _>({
|
||||
empty,
|
||||
divider = false,
|
||||
Header,
|
||||
headerProps,
|
||||
headerProps: hprops,
|
||||
getItemType,
|
||||
...props
|
||||
}: {
|
||||
@ -48,7 +48,7 @@ export const InfiniteFetch = <Data, Props, _>({
|
||||
empty?: string | JSX.Element;
|
||||
incremental?: boolean;
|
||||
divider?: boolean | ComponentType;
|
||||
Header?: ComponentType<Props & { children: JSX.Element }> | ReactElement;
|
||||
Header?: ComponentType<Props & { children: JSX.Element; empty: boolean }> | ReactElement;
|
||||
headerProps?: Props;
|
||||
getItemType?: (item: Data, index: number) => string | number;
|
||||
}): JSX.Element | null => {
|
||||
@ -65,9 +65,13 @@ export const InfiniteFetch = <Data, Props, _>({
|
||||
if (incremental && items) oldItems.current = items;
|
||||
|
||||
if (error) return <ErrorView error={error} />;
|
||||
// @ts-ignore
|
||||
const headerProps: Props & { empty: boolean } = hprops
|
||||
? { ...hprops, empty: items?.length === 0 }
|
||||
: { empty: items?.length === 0 };
|
||||
if (empty && items && items.length === 0) {
|
||||
if (typeof empty !== "string") return empty;
|
||||
return <EmptyView message={empty} />;
|
||||
if (typeof empty !== "string") return addHeader(Header, empty, headerProps);
|
||||
return addHeader(Header, <EmptyView message={empty} />, headerProps);
|
||||
}
|
||||
|
||||
if (incremental) items ??= oldItems.current;
|
||||
|
@ -30,7 +30,7 @@ import {
|
||||
useRef,
|
||||
} from "react";
|
||||
import { Stylable, useYoshiki, ysMap } from "yoshiki";
|
||||
import { EmptyView, ErrorView, Layout, WithLoading } from "./fetch";
|
||||
import { EmptyView, ErrorView, Layout, WithLoading, addHeader } from "./fetch";
|
||||
|
||||
const InfiniteScroll = <Props,>({
|
||||
children,
|
||||
@ -139,7 +139,7 @@ export const InfiniteFetch = <Data, _, HeaderProps>({
|
||||
empty,
|
||||
divider: Divider = false,
|
||||
Header,
|
||||
headerProps,
|
||||
headerProps: hprops,
|
||||
getItemType,
|
||||
...props
|
||||
}: {
|
||||
@ -165,10 +165,14 @@ export const InfiniteFetch = <Data, _, HeaderProps>({
|
||||
});
|
||||
if (incremental && items) oldItems.current = items;
|
||||
|
||||
// @ts-ignore
|
||||
const headerProps: HeaderProps & { empty: boolean } = hprops
|
||||
? { ...hprops, empty: items?.length === 0 }
|
||||
: { empty: items?.length === 0 };
|
||||
if (error) return addHeader(Header, <ErrorView error={error} />, headerProps);
|
||||
if (empty && items && items.length === 0) {
|
||||
if (typeof empty !== "string") return empty;
|
||||
return <EmptyView message={empty} />;
|
||||
if (typeof empty !== "string") return addHeader(Header, empty, headerProps);
|
||||
return addHeader(Header, <EmptyView message={empty} />, headerProps);
|
||||
}
|
||||
|
||||
return (
|
||||
@ -196,20 +200,3 @@ export const InfiniteFetch = <Data, _, HeaderProps>({
|
||||
</InfiniteScroll>
|
||||
);
|
||||
};
|
||||
|
||||
const addHeader = <Props,>(
|
||||
Header: ComponentType<{ children: JSX.Element } & Props> | ReactElement | undefined,
|
||||
children: ReactElement,
|
||||
headerProps?: Props,
|
||||
) => {
|
||||
if (!Header) return children;
|
||||
return !isValidElement(Header) ? (
|
||||
// @ts-ignore
|
||||
<Header {...(headerProps ?? {})}>{children}</Header>
|
||||
) : (
|
||||
<>
|
||||
{Header}
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
import { Page, QueryIdentifier, useFetch, KyooErrors } from "@kyoo/models";
|
||||
import { Breakpoint, P } from "@kyoo/primitives";
|
||||
import { ComponentType, ReactElement, isValidElement } from "react";
|
||||
import { View } from "react-native";
|
||||
import { useYoshiki } from "yoshiki/native";
|
||||
|
||||
@ -130,3 +131,20 @@ export const EmptyView = ({ message }: { message: string }) => {
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export const addHeader = <Props,>(
|
||||
Header: ComponentType<{ children: JSX.Element } & Props> | ReactElement | undefined,
|
||||
children: ReactElement,
|
||||
headerProps?: Props,
|
||||
) => {
|
||||
if (!Header) return children;
|
||||
return !isValidElement(Header) ? (
|
||||
// @ts-ignore
|
||||
<Header {...(headerProps ?? {})}>{children}</Header>
|
||||
) : (
|
||||
<>
|
||||
{Header}
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -23,45 +23,63 @@ import {
|
||||
ItemKind,
|
||||
LibraryItem,
|
||||
LibraryItemP,
|
||||
Page,
|
||||
Paged,
|
||||
QueryIdentifier,
|
||||
getDisplayDate,
|
||||
} from "@kyoo/models";
|
||||
import { H3, IconButton, ts } from "@kyoo/primitives";
|
||||
import { useRef } from "react";
|
||||
import { ScrollView, View } from "react-native";
|
||||
import { ReactElement, forwardRef, useRef } from "react";
|
||||
import { View } from "react-native";
|
||||
import { useYoshiki } from "yoshiki/native";
|
||||
import { Fetch } from "../fetch";
|
||||
import { ItemGrid } from "../browse/grid";
|
||||
import ChevronLeft from "@material-symbols/svg-400/rounded/chevron_left-fill.svg";
|
||||
import ChevronRight from "@material-symbols/svg-400/rounded/chevron_right-fill.svg";
|
||||
import { InfiniteFetch } from "../fetch-infinite";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export const GenreGrid = ({ genre }: { genre: Genre }) => {
|
||||
const ref = useRef<ScrollView>(null);
|
||||
const Header = forwardRef<
|
||||
View,
|
||||
{ empty: boolean; displayEmpty: boolean; genre: Genre; children: ReactElement }
|
||||
>(function Header({ empty, displayEmpty, genre, children }, ref) {
|
||||
const { css } = useYoshiki();
|
||||
|
||||
return (
|
||||
<View>
|
||||
<View {...css({ marginX: ts(1), flexDirection: "row", justifyContent: "space-between" })}>
|
||||
<H3>{genre}</H3>
|
||||
<View {...css({ flexDirection: "row" })}>
|
||||
<IconButton
|
||||
icon={ChevronLeft}
|
||||
onPress={() => ref.current?.scrollTo({ x: 0, animated: true })}
|
||||
/>
|
||||
<IconButton
|
||||
icon={ChevronRight}
|
||||
onPress={() => ref.current?.scrollTo({ x: 0, animated: true })}
|
||||
/>
|
||||
<View ref={ref}>
|
||||
{!(empty && !displayEmpty) && (
|
||||
<View {...css({ marginX: ts(1), flexDirection: "row", justifyContent: "space-between" })}>
|
||||
<H3>{genre}</H3>
|
||||
<View {...css({ flexDirection: "row" })}>
|
||||
<IconButton
|
||||
icon={ChevronLeft}
|
||||
// onPress={() => ref.current?.scrollTo({ x: 0, animated: true })}
|
||||
/>
|
||||
<IconButton
|
||||
icon={ChevronRight}
|
||||
// onPress={() => ref.current?.scrollTo({ x: 0, animated: true })}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<InfiniteFetch
|
||||
query={GenreGrid.query(genre)}
|
||||
layout={{ ...ItemGrid.layout, layout: "horizontal" }}
|
||||
>
|
||||
{(x, i) => (
|
||||
)}
|
||||
{children}
|
||||
</View>
|
||||
);
|
||||
});
|
||||
|
||||
export const GenreGrid = ({ genre }: { genre: Genre }) => {
|
||||
const displayEmpty = useRef(false);
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<InfiniteFetch
|
||||
query={GenreGrid.query(genre)}
|
||||
layout={{ ...ItemGrid.layout, layout: "horizontal" }}
|
||||
empty={displayEmpty.current ? t("home.none") : undefined}
|
||||
Header={Header}
|
||||
headerProps={{ genre, displayEmpty: displayEmpty.current }}
|
||||
>
|
||||
{(x, i) => {
|
||||
// only display empty list if a loading as been displayed (not durring ssr)
|
||||
if (x.isLoading) displayEmpty.current = true;
|
||||
return (
|
||||
<ItemGrid
|
||||
key={x.id ?? i}
|
||||
isLoading={x.isLoading as any}
|
||||
@ -72,9 +90,9 @@ export const GenreGrid = ({ genre }: { genre: Genre }) => {
|
||||
}
|
||||
poster={x.poster}
|
||||
/>
|
||||
)}
|
||||
</InfiniteFetch>
|
||||
</View>
|
||||
);
|
||||
}}
|
||||
</InfiniteFetch>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
{
|
||||
"home": {
|
||||
"recommanded": "Recommanded",
|
||||
"info": "See more"
|
||||
"info": "See more",
|
||||
"none": "No episodes"
|
||||
},
|
||||
"show": {
|
||||
"play": "Play",
|
||||
|
@ -1,7 +1,8 @@
|
||||
{
|
||||
"home": {
|
||||
"recommanded": "Recommandé",
|
||||
"info": "Voir plus"
|
||||
"info": "Voir plus",
|
||||
"none": "Aucun episode"
|
||||
},
|
||||
"show": {
|
||||
"play": "Lecture",
|
||||
|
Loading…
x
Reference in New Issue
Block a user