mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-31 20:24:27 -04:00
Adapt staff list to react native (first pass)
This commit is contained in:
parent
8c28df9517
commit
26f9cf646b
@ -57,7 +57,7 @@ const ThemedStack = () => {
|
|||||||
headerStyle: {
|
headerStyle: {
|
||||||
backgroundColor: theme.appbar,
|
backgroundColor: theme.appbar,
|
||||||
},
|
},
|
||||||
headerTintColor: "#fff",
|
headerTintColor: theme.colors.white,
|
||||||
headerTitleStyle: {
|
headerTitleStyle: {
|
||||||
fontWeight: "bold",
|
fontWeight: "bold",
|
||||||
},
|
},
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { MovieDetails } from "@kyoo/ui";
|
|
||||||
|
|
||||||
export default MovieDetails;
|
|
@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Avatar, Box, Skeleton, SxProps, Typography } from "@mui/material";
|
|
||||||
import { Person } from "~/models/resources/person";
|
|
||||||
import { Link } from "~/utils/link";
|
|
||||||
|
|
||||||
export const PersonAvatar = ({ person, sx }: { person?: Person; sx?: SxProps }) => {
|
|
||||||
if (!person) {
|
|
||||||
return (
|
|
||||||
<Box sx={sx}>
|
|
||||||
<Skeleton variant="circular" sx={{ width: "100%", aspectRatio: "1/1", height: "unset" }} />
|
|
||||||
<Typography align="center">
|
|
||||||
<Skeleton />
|
|
||||||
</Typography>
|
|
||||||
<Typography variant="body2" align="center">
|
|
||||||
<Skeleton />
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Link href={`/person/${person.slug}`} color="inherit" sx={sx}>
|
|
||||||
<Avatar
|
|
||||||
src={person.poster!}
|
|
||||||
alt={person.name}
|
|
||||||
sx={{ width: "100%", height: "unset", aspectRatio: "1/1" }}
|
|
||||||
/>
|
|
||||||
<Typography align="center">{person.name}</Typography>
|
|
||||||
{person.role && person.type && (
|
|
||||||
<Typography variant="body2" align="center">
|
|
||||||
{person.type} ({person.role})
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
{person.role && !person.type && (
|
|
||||||
<Typography variant="body2" align="center">
|
|
||||||
{person.role}
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
};
|
|
@ -18,26 +18,31 @@
|
|||||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { View, ViewStyle } from "react-native";
|
import { View } from "react-native";
|
||||||
import { Image } from "./image";
|
import { Image } from "./image";
|
||||||
import { useYoshiki, px } from "yoshiki/native";
|
import { useYoshiki, px, Stylable } from "yoshiki/native";
|
||||||
import { Icon } from "./icons";
|
import { Icon } from "./icons";
|
||||||
|
import { Skeleton } from "./skeleton";
|
||||||
|
|
||||||
export const Avatar = ({
|
export const Avatar = ({
|
||||||
src,
|
src,
|
||||||
alt,
|
alt,
|
||||||
size = px(24),
|
size = px(24),
|
||||||
|
isLoading = false,
|
||||||
|
...props
|
||||||
}: {
|
}: {
|
||||||
src?: string;
|
src?: string | null;
|
||||||
alt: string;
|
alt?: string;
|
||||||
size?: number;
|
size?: number;
|
||||||
}) => {
|
isLoading?: boolean;
|
||||||
|
} & Stylable) => {
|
||||||
const { css } = useYoshiki();
|
const { css } = useYoshiki();
|
||||||
|
|
||||||
|
if (isLoading) return <Skeleton variant="round" {...css({ width: size, height: size })} />;
|
||||||
return (
|
return (
|
||||||
<View {...css({ borderRadius: size / 2, width: size, height: size })}>
|
<View {...css({ borderRadius: size / 2, width: size, height: size }, props)}>
|
||||||
{src ? (
|
{src ? (
|
||||||
<Image src={src} alt={alt} width={size} height={size} />
|
<Image src={src} alt={alt} layout={{ width: size, height: size }} />
|
||||||
) : (
|
) : (
|
||||||
<Icon icon="account-circle" size={size} />
|
<Icon icon="account-circle" size={size} />
|
||||||
)}
|
)}
|
||||||
|
@ -18,15 +18,20 @@
|
|||||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { ComponentType } from "react";
|
||||||
import { View, ViewProps } from "react-native";
|
import { View, ViewProps } from "react-native";
|
||||||
import { percent, px, useYoshiki } from "yoshiki/native";
|
import { percent, px, useYoshiki } from "yoshiki/native";
|
||||||
|
|
||||||
export const Container = (props: ViewProps) => {
|
export const Container = <AsProps = ViewProps,>({
|
||||||
|
as,
|
||||||
|
...props
|
||||||
|
}: { as?: ComponentType<AsProps> } & AsProps) => {
|
||||||
const { css } = useYoshiki();
|
const { css } = useYoshiki();
|
||||||
|
|
||||||
|
const As = as ?? View;
|
||||||
return (
|
return (
|
||||||
<View
|
<As
|
||||||
{...css(
|
{...(css(
|
||||||
{
|
{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
paddingHorizontal: px(15),
|
paddingHorizontal: px(15),
|
||||||
@ -39,7 +44,7 @@ export const Container = (props: ViewProps) => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
props,
|
props,
|
||||||
)}
|
) as any)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -19,8 +19,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { HR as EHR } from "@expo/html-elements";
|
import { HR as EHR } from "@expo/html-elements";
|
||||||
import { percent, px, Stylable, useYoshiki } from "yoshiki/native";
|
import { px, Stylable, useYoshiki } from "yoshiki/native";
|
||||||
import { alpha, ts } from ".";
|
import { alpha } from "./themes";
|
||||||
|
import { ts } from "./utils";
|
||||||
|
|
||||||
export const HR = ({
|
export const HR = ({
|
||||||
orientation,
|
orientation,
|
||||||
|
@ -22,7 +22,7 @@ import MIcon from "@expo/vector-icons/MaterialIcons";
|
|||||||
import { ComponentProps, ComponentType } from "react";
|
import { ComponentProps, ComponentType } from "react";
|
||||||
import { PressableProps } from "react-native";
|
import { PressableProps } from "react-native";
|
||||||
import { Pressable, px, useYoshiki } from "yoshiki/native";
|
import { Pressable, px, useYoshiki } from "yoshiki/native";
|
||||||
import { Breakpoint, ts } from ".";
|
import { Breakpoint, ts } from "./utils";
|
||||||
|
|
||||||
export type IconProps = {
|
export type IconProps = {
|
||||||
icon: ComponentProps<typeof MIcon>["name"];
|
icon: ComponentProps<typeof MIcon>["name"];
|
||||||
|
@ -31,13 +31,4 @@ export * from "./container";
|
|||||||
export * from "./divider";
|
export * from "./divider";
|
||||||
|
|
||||||
export * from "./animated";
|
export * from "./animated";
|
||||||
|
export * from "./utils";
|
||||||
export * from "./utils/breakpoints";
|
|
||||||
export * from "./utils/nojs";
|
|
||||||
export * from "./utils/head";
|
|
||||||
|
|
||||||
import { px } from "yoshiki/native";
|
|
||||||
|
|
||||||
export const ts = (spacing: number) => {
|
|
||||||
return px(spacing * 8);
|
|
||||||
};
|
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ComponentType, ReactNode } from "react";
|
import { ViewStyle } from "@expo/html-elements/build/primitives/View";
|
||||||
|
import { ComponentType, Fragment, ReactNode } from "react";
|
||||||
import {
|
import {
|
||||||
Platform,
|
Platform,
|
||||||
TextProps,
|
TextProps,
|
||||||
@ -26,6 +27,7 @@ import {
|
|||||||
TouchableNativeFeedback,
|
TouchableNativeFeedback,
|
||||||
View,
|
View,
|
||||||
ViewProps,
|
ViewProps,
|
||||||
|
StyleSheet,
|
||||||
} from "react-native";
|
} from "react-native";
|
||||||
import { LinkCore, TextLink } from "solito/link";
|
import { LinkCore, TextLink } from "solito/link";
|
||||||
import { useYoshiki, Pressable } from "yoshiki/native";
|
import { useYoshiki, Pressable } from "yoshiki/native";
|
||||||
@ -70,26 +72,35 @@ export const Link = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const { onBlur, onFocus, onPressIn, onPressOut, ...noFocusProps } = props;
|
const { onBlur, onFocus, onPressIn, onPressOut, ...noFocusProps } = props;
|
||||||
const focusProps = { onBlur, onFocus, onPressIn, onPressOut };
|
const focusProps = { onBlur, onFocus, onPressIn, onPressOut };
|
||||||
|
const radiusStyle = Platform.select<ViewProps>({
|
||||||
|
android: {
|
||||||
|
style: { borderRadius: StyleSheet.flatten(props?.style).borderRadius, overflow: "hidden" },
|
||||||
|
},
|
||||||
|
default: {},
|
||||||
|
});
|
||||||
|
const Wrapper = radiusStyle ? View : Fragment;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LinkCore
|
<Wrapper {...radiusStyle}>
|
||||||
href={href}
|
<LinkCore
|
||||||
Component={Platform.select<ComponentType>({
|
href={href}
|
||||||
web: View,
|
Component={Platform.select<ComponentType>({
|
||||||
android: TouchableNativeFeedback,
|
web: View,
|
||||||
ios: TouchableOpacity,
|
android: TouchableNativeFeedback,
|
||||||
default: Pressable,
|
ios: TouchableOpacity,
|
||||||
})}
|
default: Pressable,
|
||||||
componentProps={Platform.select<object>({
|
})}
|
||||||
android: { useForeground: true, ...focusProps },
|
componentProps={Platform.select<object>({
|
||||||
default: props,
|
android: { useForeground: true, ...focusProps },
|
||||||
})}
|
default: props,
|
||||||
>
|
})}
|
||||||
{Platform.select<ReactNode>({
|
>
|
||||||
android: <View {...noFocusProps}>{children}</View>,
|
{Platform.select<ReactNode>({
|
||||||
ios: <View {...noFocusProps}>{children}</View>,
|
android: <View {...noFocusProps}>{children}</View>,
|
||||||
default: children,
|
ios: <View {...noFocusProps}>{children}</View>,
|
||||||
})}
|
default: children,
|
||||||
</LinkCore>
|
})}
|
||||||
|
</LinkCore>
|
||||||
|
</Wrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -31,7 +31,7 @@ import {
|
|||||||
P as EP,
|
P as EP,
|
||||||
LI as ELI,
|
LI as ELI,
|
||||||
} from "@expo/html-elements";
|
} from "@expo/html-elements";
|
||||||
import { ts } from ".";
|
import { ts } from "./utils/spacing";
|
||||||
|
|
||||||
const styleText = (
|
const styleText = (
|
||||||
Component: ComponentType<ComponentProps<typeof EP>>,
|
Component: ComponentType<ComponentProps<typeof EP>>,
|
||||||
@ -76,7 +76,7 @@ export const LI = ({ children, ...props }: TextProps) => {
|
|||||||
const { css } = useYoshiki();
|
const { css } = useYoshiki();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<P accessibilityRole="listitem" {...props}>
|
<P accessibilityRole={Platform.OS === "web" ? "listitem" : props.accessibilityRole} {...props}>
|
||||||
<Text
|
<Text
|
||||||
{...css({
|
{...css({
|
||||||
height: percent(100),
|
height: percent(100),
|
||||||
|
@ -39,11 +39,12 @@ import {
|
|||||||
A,
|
A,
|
||||||
ts,
|
ts,
|
||||||
} from "@kyoo/primitives";
|
} from "@kyoo/primitives";
|
||||||
|
import { ScrollView } from "moti";
|
||||||
|
import { Fragment } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { StyleSheet, View } from "react-native";
|
import { StyleSheet, View } from "react-native";
|
||||||
import {
|
import {
|
||||||
Theme,
|
Theme,
|
||||||
sm,
|
|
||||||
md,
|
md,
|
||||||
px,
|
px,
|
||||||
min,
|
min,
|
||||||
@ -229,16 +230,14 @@ const Description = ({
|
|||||||
>
|
>
|
||||||
{t("show.genre")}:{" "}
|
{t("show.genre")}:{" "}
|
||||||
{(isLoading ? [...Array(3)] : genres!).map((genre, i) => (
|
{(isLoading ? [...Array(3)] : genres!).map((genre, i) => (
|
||||||
<>
|
<Fragment key={genre?.slug ?? i.toString()}>
|
||||||
{i !== 0 && ", "}
|
<P>{i !== 0 && ", "}</P>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<Skeleton key={i} {...css({ width: rem(5) })} />
|
<Skeleton {...css({ width: rem(5) })} />
|
||||||
) : (
|
) : (
|
||||||
<A key={genre.slug} href={`/genres/${genre.slug}`}>
|
<A href={`/genres/${genre.slug}`}>{genre.name}</A>
|
||||||
{genre.name}
|
|
||||||
</A>
|
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</P>
|
</P>
|
||||||
|
|
||||||
@ -278,65 +277,52 @@ const Description = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ShowHeader = ({
|
export const Header = ({ query, slug }: { query: QueryIdentifier<Show | Movie>; slug: string }) => {
|
||||||
query,
|
|
||||||
slug,
|
|
||||||
}: {
|
|
||||||
query: QueryIdentifier<Show | Movie>;
|
|
||||||
slug: string;
|
|
||||||
}) => {
|
|
||||||
/* const scroll = useScroll(); */
|
|
||||||
const { css } = useYoshiki();
|
const { css } = useYoshiki();
|
||||||
// TODO: tweek the navbar color with the theme.
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Fetch query={query}>
|
||||||
<Navbar {...css({ bg: "transparent" })} />
|
{({ isLoading, ...data }) => (
|
||||||
<Fetch query={query}>
|
<ScrollView>
|
||||||
{({ isLoading, ...data }) => (
|
<Head title={data?.name} description={data?.overview} />
|
||||||
<Main {...css(StyleSheet.absoluteFillObject)}>
|
<ImageBackground
|
||||||
<Head title={data?.name} description={data?.overview} />
|
src={data?.thumbnail}
|
||||||
{/* TODO: Add a shadow on navbar items */}
|
alt=""
|
||||||
{/* TODO: Put the navbar outside of the scrollbox */}
|
containerStyle={{
|
||||||
<ImageBackground
|
height: {
|
||||||
src={data?.thumbnail}
|
xs: vh(40),
|
||||||
alt=""
|
sm: min(vh(60), px(750)),
|
||||||
containerStyle={{
|
md: min(vh(60), px(680)),
|
||||||
height: {
|
lg: vh(70),
|
||||||
xs: vh(40),
|
},
|
||||||
sm: min(vh(60), px(750)),
|
minHeight: { xs: px(350), sm: px(300), md: px(400), lg: px(600) },
|
||||||
md: min(vh(60), px(680)),
|
}}
|
||||||
lg: vh(70),
|
>
|
||||||
},
|
<TitleLine
|
||||||
minHeight: { xs: px(350), sm: px(300), md: px(400), lg: px(600) },
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<TitleLine
|
|
||||||
isLoading={isLoading}
|
|
||||||
slug={slug}
|
|
||||||
name={data?.name}
|
|
||||||
date={data ? getDisplayDate(data as any) : undefined}
|
|
||||||
poster={data?.poster}
|
|
||||||
studio={data?.studio}
|
|
||||||
{...css({
|
|
||||||
marginTop: {
|
|
||||||
xs: max(vh(20), px(200)),
|
|
||||||
sm: vh(45),
|
|
||||||
md: max(vh(30), px(150)),
|
|
||||||
lg: max(vh(35), px(200)),
|
|
||||||
},
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
</ImageBackground>
|
|
||||||
<Description
|
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
overview={data?.overview}
|
slug={slug}
|
||||||
genres={data?.genres}
|
name={data?.name}
|
||||||
{...css({ paddingTop: { xs: 0, md: ts(2) } })}
|
date={data ? getDisplayDate(data as any) : undefined}
|
||||||
|
poster={data?.poster}
|
||||||
|
studio={data?.studio}
|
||||||
|
{...css({
|
||||||
|
marginTop: {
|
||||||
|
xs: max(vh(20), px(200)),
|
||||||
|
sm: vh(45),
|
||||||
|
md: max(vh(30), px(150)),
|
||||||
|
lg: max(vh(35), px(200)),
|
||||||
|
},
|
||||||
|
})}
|
||||||
/>
|
/>
|
||||||
</Main>
|
</ImageBackground>
|
||||||
)}
|
<Description
|
||||||
</Fetch>
|
isLoading={isLoading}
|
||||||
</>
|
overview={data?.overview}
|
||||||
|
genres={data?.genres}
|
||||||
|
{...css({ paddingTop: { xs: 0, md: ts(2) } })}
|
||||||
|
/>
|
||||||
|
</ScrollView>
|
||||||
|
)}
|
||||||
|
</Fetch>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -19,7 +19,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Movie, MovieP, QueryIdentifier, QueryPage } from "@kyoo/models";
|
import { Movie, MovieP, QueryIdentifier, QueryPage } from "@kyoo/models";
|
||||||
import { ShowHeader } from "./header";
|
import { Navbar } from "../navbar";
|
||||||
|
import { DefaultLayout } from "../layout";
|
||||||
|
import { Header } from "./header";
|
||||||
|
import { Staff } from "./staff";
|
||||||
|
|
||||||
const query = (slug: string): QueryIdentifier<Movie> => ({
|
const query = (slug: string): QueryIdentifier<Movie> => ({
|
||||||
parser: MovieP,
|
parser: MovieP,
|
||||||
@ -32,16 +35,16 @@ const query = (slug: string): QueryIdentifier<Movie> => ({
|
|||||||
export const MovieDetails: QueryPage<{ slug: string }> = ({ slug }) => {
|
export const MovieDetails: QueryPage<{ slug: string }> = ({ slug }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* <Head> */}
|
<Header slug={slug} query={query(slug)} />
|
||||||
{/* <title>{makeTitle(data?.name)}</title> */}
|
{/* <Staff slug={slug} /> */}
|
||||||
{/* <meta name="description" content={data?.overview!} /> */}
|
|
||||||
{/* </Head> */}
|
|
||||||
<ShowHeader slug={slug} query={query(slug)} />
|
|
||||||
{/* <ShowStaff slug={slug} /> */}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
MovieDetails.getFetchUrls = ({ slug }) => [//query(slug),
|
MovieDetails.getFetchUrls = ({ slug }) => [
|
||||||
// ShowStaff.query(slug), Navbar.query()
|
query(slug),
|
||||||
|
// ShowStaff.query(slug),
|
||||||
|
Navbar.query(),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
MovieDetails.getLayout = DefaultLayout;
|
||||||
|
@ -18,30 +18,40 @@
|
|||||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export {}
|
import { Person, PersonP, QueryIdentifier } from "@kyoo/models";
|
||||||
// export const ShowStaff = ({ slug }: { slug: string }) => {
|
import { useTranslation } from "react-i18next";
|
||||||
// const { items, isError, error } = useInfiniteFetch(ShowStaff.query(slug));
|
import { InfiniteFetch } from "../fetch-infinite";
|
||||||
// const { t } = useTranslation("browse");
|
import { PersonAvatar } from "./person";
|
||||||
|
|
||||||
// // TODO: handle infinite scroll
|
export const Staff = ({ slug }: { slug: string }) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
// if (isError) return <ErrorComponent {...error} />;
|
// TODO: handle infinite scroll
|
||||||
|
|
||||||
// return (
|
return (
|
||||||
// <HorizontalList title={t("show.staff")} noContent={t("show.staff-none")}>
|
<InfiniteFetch
|
||||||
// {(items ?? [...Array(20)]).map((x, i) => (
|
query={Staff.query(slug)}
|
||||||
// <PersonAvatar
|
layout={{ numColumns: 0, size: PersonAvatar.width }}
|
||||||
// key={x ? x.id : i}
|
placeholderCount={20}
|
||||||
// person={x}
|
>
|
||||||
// sx={{ width: { xs: "7rem", lg: "10rem" }, flexShrink: 0, px: 2 }}
|
{/* <HorizontalList title={t("show.staff")} noContent={t("show.staff-none")}> */}
|
||||||
// />
|
{(item, key) => (
|
||||||
// ))}
|
<PersonAvatar
|
||||||
// </HorizontalList>
|
key={key}
|
||||||
// );
|
isLoading={item.isLoading}
|
||||||
// };
|
slug={item?.slug}
|
||||||
|
name={item?.name}
|
||||||
|
role={item?.type ? `${item?.type} (${item?.role})` : item?.role}
|
||||||
|
poster={item?.poster}
|
||||||
|
// sx={{ width: { xs: "7rem", lg: "10rem" }, flexShrink: 0, px: 2 }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</InfiniteFetch>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
// ShowStaff.query = (slug: string): QueryIdentifier<Person> => ({
|
Staff.query = (slug: string): QueryIdentifier<Person> => ({
|
||||||
// parser: PersonP,
|
parser: PersonP,
|
||||||
// path: ["shows", slug, "people"],
|
path: ["shows", slug, "people"],
|
||||||
// infinite: true,
|
infinite: true,
|
||||||
// });
|
});
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
import { Page, QueryIdentifier, useFetch, KyooErrors } from "@kyoo/models";
|
import { Page, QueryIdentifier, useFetch, KyooErrors } from "@kyoo/models";
|
||||||
import { Breakpoint, P } from "@kyoo/primitives";
|
import { Breakpoint, P } from "@kyoo/primitives";
|
||||||
|
import { Fragment } from "react";
|
||||||
import { View } from "react-native";
|
import { View } from "react-native";
|
||||||
import { useYoshiki } from "yoshiki/native";
|
import { useYoshiki } from "yoshiki/native";
|
||||||
|
|
||||||
@ -47,14 +48,12 @@ export const Fetch = <Data,>({
|
|||||||
const { data, error } = useFetch(query);
|
const { data, error } = useFetch(query);
|
||||||
|
|
||||||
if (error) return <ErrorView error={error} />;
|
if (error) return <ErrorView error={error} />;
|
||||||
|
if (placeholderCount === 1 || !isPage<object>(data))
|
||||||
|
return children(data ? { ...data, isLoading: false } : ({ isLoading: true } as any), 0);
|
||||||
if (!data)
|
if (!data)
|
||||||
return (
|
return (
|
||||||
<>{[...Array(placeholderCount)].map((_, i) => children({ isLoading: true } as any, i))}</>
|
<>{[...Array(placeholderCount)].map((_, i) => children({ isLoading: true } as any, i))}</>
|
||||||
);
|
);
|
||||||
if (!isPage<object>(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))}</>;
|
return <>{data.items.map((item, i) => children({ ...item, isLoading: false } as any, i))}</>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user