mirror of
				https://github.com/zoriya/Kyoo.git
				synced 2025-11-03 19:17:16 -05:00 
			
		
		
		
	Fix browse layout switch
This commit is contained in:
		
							parent
							
								
									0ad9c86756
								
							
						
					
					
						commit
						552926d2cb
					
				@ -187,7 +187,7 @@ ItemGrid.Loader = (props: object) => {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
ItemGrid.layout = {
 | 
			
		||||
	size: px(150),
 | 
			
		||||
	size: 150,
 | 
			
		||||
	numColumns: { xs: 3, sm: 4, md: 5, lg: 6, xl: 8 },
 | 
			
		||||
	gap: { xs: ts(1), sm: ts(2), md: ts(4) },
 | 
			
		||||
	layout: "grid",
 | 
			
		||||
 | 
			
		||||
@ -3,6 +3,7 @@ import { Platform, View } from "react-native";
 | 
			
		||||
import { percent, px, rem, useYoshiki } from "yoshiki/native";
 | 
			
		||||
import type { KImage, WatchStatusV } from "~/models";
 | 
			
		||||
import {
 | 
			
		||||
	ContrastArea,
 | 
			
		||||
	GradientImageBackground,
 | 
			
		||||
	Heading,
 | 
			
		||||
	important,
 | 
			
		||||
@ -39,10 +40,11 @@ export const ItemList = ({
 | 
			
		||||
	watchStatus: WatchStatusV | null;
 | 
			
		||||
	unseenEpisodesCount: number | null;
 | 
			
		||||
}) => {
 | 
			
		||||
	const { css } = useYoshiki("line");
 | 
			
		||||
	const [moreOpened, setMoreOpened] = useState(false);
 | 
			
		||||
 | 
			
		||||
	return (
 | 
			
		||||
		<ContrastArea>
 | 
			
		||||
			{({ css }) => (
 | 
			
		||||
				<Link
 | 
			
		||||
					href={moreOpened ? undefined : href}
 | 
			
		||||
					onLongPress={() => setMoreOpened(true)}
 | 
			
		||||
@ -61,22 +63,22 @@ export const ItemList = ({
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					})}
 | 
			
		||||
					{...props}
 | 
			
		||||
				>
 | 
			
		||||
					<GradientImageBackground
 | 
			
		||||
						src={thumbnail}
 | 
			
		||||
						alt={name}
 | 
			
		||||
						quality="medium"
 | 
			
		||||
						layout={{ width: percent(100), height: ItemList.layout.size }}
 | 
			
		||||
				{...(css(
 | 
			
		||||
					{
 | 
			
		||||
						gradientStyle={{
 | 
			
		||||
							alignItems: "center",
 | 
			
		||||
							justifyContent: "space-evenly",
 | 
			
		||||
							flexDirection: "row",
 | 
			
		||||
						}}
 | 
			
		||||
						{...(css({
 | 
			
		||||
							borderRadius: px(10),
 | 
			
		||||
							overflow: "hidden",
 | 
			
		||||
					},
 | 
			
		||||
					props,
 | 
			
		||||
				) as any)}
 | 
			
		||||
						}) as any)}
 | 
			
		||||
					>
 | 
			
		||||
						<View
 | 
			
		||||
							{...css({
 | 
			
		||||
@ -147,6 +149,8 @@ export const ItemList = ({
 | 
			
		||||
						</PosterBackground>
 | 
			
		||||
					</GradientImageBackground>
 | 
			
		||||
				</Link>
 | 
			
		||||
			)}
 | 
			
		||||
		</ContrastArea>
 | 
			
		||||
	);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -52,7 +52,9 @@ export const PosterBackground = ({
 | 
			
		||||
	...props
 | 
			
		||||
}: Omit<ComponentProps<typeof ImageBackground>, "layout"> & {
 | 
			
		||||
	style?: ImageStyle;
 | 
			
		||||
	layout: YoshikiEnhanced<{ width: ImageStyle["width"] } | { height: ImageStyle["height"] }>;
 | 
			
		||||
	layout: YoshikiEnhanced<
 | 
			
		||||
		{ width: ImageStyle["width"] } | { height: ImageStyle["height"] }
 | 
			
		||||
	>;
 | 
			
		||||
}) => {
 | 
			
		||||
	const { css } = useYoshiki();
 | 
			
		||||
 | 
			
		||||
@ -67,10 +69,12 @@ export const PosterBackground = ({
 | 
			
		||||
 | 
			
		||||
export const GradientImageBackground = ({
 | 
			
		||||
	gradient,
 | 
			
		||||
	gradientStyle,
 | 
			
		||||
	children,
 | 
			
		||||
	...props
 | 
			
		||||
}: ComponentProps<typeof ImageBackground> & {
 | 
			
		||||
	gradient?: Partial<LinearGradientProps>;
 | 
			
		||||
	gradientStyle?: Parameters<ReturnType<typeof useYoshiki>["css"]>[0];
 | 
			
		||||
}) => {
 | 
			
		||||
	const { css, theme } = useYoshiki();
 | 
			
		||||
 | 
			
		||||
@ -81,6 +85,7 @@ export const GradientImageBackground = ({
 | 
			
		||||
				end={{ x: 0, y: 1 }}
 | 
			
		||||
				colors={["transparent", theme.darkOverlay]}
 | 
			
		||||
				{...css(
 | 
			
		||||
					[
 | 
			
		||||
						{
 | 
			
		||||
							position: "absolute",
 | 
			
		||||
							top: 0,
 | 
			
		||||
@ -88,6 +93,8 @@ export const GradientImageBackground = ({
 | 
			
		||||
							left: 0,
 | 
			
		||||
							right: 0,
 | 
			
		||||
						},
 | 
			
		||||
						gradientStyle,
 | 
			
		||||
					],
 | 
			
		||||
					typeof gradient === "object" ? gradient : undefined,
 | 
			
		||||
				)}
 | 
			
		||||
			>
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
import { useRouter } from "expo-router";
 | 
			
		||||
import { type ReactNode, forwardRef } from "react";
 | 
			
		||||
import type { ReactNode } from "react";
 | 
			
		||||
import {
 | 
			
		||||
	Linking,
 | 
			
		||||
	Platform,
 | 
			
		||||
@ -7,7 +7,6 @@ import {
 | 
			
		||||
	type PressableProps,
 | 
			
		||||
	Text,
 | 
			
		||||
	type TextProps,
 | 
			
		||||
	type View,
 | 
			
		||||
} from "react-native";
 | 
			
		||||
import { useTheme, useYoshiki } from "yoshiki/native";
 | 
			
		||||
import { alpha } from "./theme";
 | 
			
		||||
@ -26,7 +25,9 @@ function useLinkTo({
 | 
			
		||||
		onPress: (e) => {
 | 
			
		||||
			if (e?.defaultPrevented) return;
 | 
			
		||||
			if (href.startsWith("http")) {
 | 
			
		||||
				Platform.OS === "web" ? window.open(href, "_blank") : Linking.openURL(href);
 | 
			
		||||
				Platform.OS === "web"
 | 
			
		||||
					? window.open(href, "_blank")
 | 
			
		||||
					: Linking.openURL(href);
 | 
			
		||||
			} else {
 | 
			
		||||
				replace ? router.replace(href) : router.push(href);
 | 
			
		||||
			}
 | 
			
		||||
@ -65,25 +66,26 @@ export const A = ({
 | 
			
		||||
	);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const PressableFeedback = forwardRef<View, PressableProps>(function Feedback(
 | 
			
		||||
	{ children, ...props },
 | 
			
		||||
	ref,
 | 
			
		||||
) {
 | 
			
		||||
export const PressableFeedback = ({ children, ...props }: PressableProps) => {
 | 
			
		||||
	const theme = useTheme();
 | 
			
		||||
 | 
			
		||||
	return (
 | 
			
		||||
		<Pressable
 | 
			
		||||
			ref={ref}
 | 
			
		||||
			// TODO: Enable ripple on tv. Waiting for https://github.com/react-native-tvos/react-native-tvos/issues/440
 | 
			
		||||
			{...(Platform.isTV
 | 
			
		||||
				? {}
 | 
			
		||||
				: { android_ripple: { foreground: true, color: alpha(theme.contrast, 0.5) as any } })}
 | 
			
		||||
				: {
 | 
			
		||||
						android_ripple: {
 | 
			
		||||
							foreground: true,
 | 
			
		||||
							color: alpha(theme.contrast, 0.5) as any,
 | 
			
		||||
						},
 | 
			
		||||
					})}
 | 
			
		||||
			{...props}
 | 
			
		||||
		>
 | 
			
		||||
			{children}
 | 
			
		||||
		</Pressable>
 | 
			
		||||
	);
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const Link = ({
 | 
			
		||||
	href,
 | 
			
		||||
 | 
			
		||||
@ -48,11 +48,19 @@ export const InfiniteFetch = <Data, Props, _, Kind extends number | string>({
 | 
			
		||||
	const { numColumns, size, gap } = useBreakpointMap(layout);
 | 
			
		||||
	const [setOffline, clearOffline] = useSetError("offline");
 | 
			
		||||
	const oldItems = useRef<Data[] | undefined>(undefined);
 | 
			
		||||
	let { items, isPaused, error, fetchNextPage, isFetching, refetch, isRefetching } =
 | 
			
		||||
		useInfiniteFetch(query);
 | 
			
		||||
	let {
 | 
			
		||||
		items,
 | 
			
		||||
		isPaused,
 | 
			
		||||
		error,
 | 
			
		||||
		fetchNextPage,
 | 
			
		||||
		isFetching,
 | 
			
		||||
		refetch,
 | 
			
		||||
		isRefetching,
 | 
			
		||||
	} = useInfiniteFetch(query);
 | 
			
		||||
	if (incremental && items) oldItems.current = items;
 | 
			
		||||
 | 
			
		||||
	if (!query.infinite) console.warn("A non infinite query was passed to an InfiniteFetch.");
 | 
			
		||||
	if (!query.infinite)
 | 
			
		||||
		console.warn("A non infinite query was passed to an InfiniteFetch.");
 | 
			
		||||
 | 
			
		||||
	if (isPaused) setOffline();
 | 
			
		||||
	else clearOffline();
 | 
			
		||||
@ -60,10 +68,13 @@ export const InfiniteFetch = <Data, Props, _, Kind extends number | string>({
 | 
			
		||||
	if (error) return <ErrorView error={error} />;
 | 
			
		||||
 | 
			
		||||
	if (incremental) items ??= oldItems.current;
 | 
			
		||||
	const count = items ? numColumns - (items.length % numColumns) : placeholderCount;
 | 
			
		||||
	console.log(numColumns, count);
 | 
			
		||||
	const count = items
 | 
			
		||||
		? numColumns - (items.length % numColumns)
 | 
			
		||||
		: placeholderCount;
 | 
			
		||||
	const placeholders = [...Array(count === 0 ? numColumns : count)].fill(null);
 | 
			
		||||
	const data = isFetching || !items ? [...(items || []), ...placeholders] : items;
 | 
			
		||||
	const data =
 | 
			
		||||
		isFetching || !items ? [...(items || []), ...placeholders] : items;
 | 
			
		||||
 | 
			
		||||
	return (
 | 
			
		||||
		<LegendList
 | 
			
		||||
			data={data}
 | 
			
		||||
@ -71,9 +82,8 @@ export const InfiniteFetch = <Data, Props, _, Kind extends number | string>({
 | 
			
		||||
			renderItem={({ item, index }) =>
 | 
			
		||||
				item ? <Render index={index} item={item} /> : <Loader index={index} />
 | 
			
		||||
			}
 | 
			
		||||
			// keyExtractor={(item: any, index) => (item ? item.id : index)}
 | 
			
		||||
			// estimatedItemSize={size}
 | 
			
		||||
 | 
			
		||||
			keyExtractor={(item: any, index) => (item ? item.id : index)}
 | 
			
		||||
			estimatedItemSize={size}
 | 
			
		||||
			horizontal={layout.layout === "horizontal"}
 | 
			
		||||
			numColumns={layout.layout === "horizontal" ? 1 : numColumns}
 | 
			
		||||
			onEndReached={fetchMore ? () => fetchNextPage() : undefined}
 | 
			
		||||
@ -81,7 +91,9 @@ export const InfiniteFetch = <Data, Props, _, Kind extends number | string>({
 | 
			
		||||
			onRefresh={layout.layout !== "horizontal" ? refetch : undefined}
 | 
			
		||||
			refreshing={isRefetching}
 | 
			
		||||
			ListHeaderComponent={Header}
 | 
			
		||||
			ItemSeparatorComponent={divider === true ? HR : (divider as any) || undefined}
 | 
			
		||||
			ItemSeparatorComponent={
 | 
			
		||||
				divider === true ? HR : (divider as any) || undefined
 | 
			
		||||
			}
 | 
			
		||||
			ListEmptyComponent={Empty}
 | 
			
		||||
			contentContainerStyle={{ gap, marginHorizontal: gap }}
 | 
			
		||||
			{...props}
 | 
			
		||||
 | 
			
		||||
@ -149,7 +149,9 @@ export const BrowseSettings = ({
 | 
			
		||||
					{Object.keys(MediaTypeIcons).map((x) => (
 | 
			
		||||
						<Menu.Item
 | 
			
		||||
							key={x}
 | 
			
		||||
							label={t(`browse.mediatypekey.${x}`)}
 | 
			
		||||
							label={t(
 | 
			
		||||
								`browse.mediatypekey.${x as keyof typeof MediaTypeIcons}`,
 | 
			
		||||
							)}
 | 
			
		||||
							selected={mediaType === x}
 | 
			
		||||
							icon={MediaTypeIcons[x as keyof typeof MediaTypeIcons]}
 | 
			
		||||
							onSelect={() => setMediaType(x)}
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,3 @@
 | 
			
		||||
import { useState } from "react";
 | 
			
		||||
import { ItemGrid, ItemList, itemMap } from "~/components/items";
 | 
			
		||||
import { Show } from "~/models";
 | 
			
		||||
import { InfiniteFetch, type QueryIdentifier } from "~/query";
 | 
			
		||||
@ -17,6 +16,7 @@ export const BrowsePage = () => {
 | 
			
		||||
 | 
			
		||||
	return (
 | 
			
		||||
		<InfiniteFetch
 | 
			
		||||
			key={layout}
 | 
			
		||||
			query={BrowsePage.query(filter, sortBy, sortOrd)}
 | 
			
		||||
			layout={LayoutComponent.layout}
 | 
			
		||||
			Header={
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user