diff --git a/front/apps/web/package.json b/front/apps/web/package.json index 7b19a513..6a42a0b6 100644 --- a/front/apps/web/package.json +++ b/front/apps/web/package.json @@ -31,12 +31,10 @@ "next": "13.0.5", "next-fonts": "^1.5.1", "next-translate": "^1.6.0", - "next-transpile-modules": "^10.0.0", "raf": "^3.4.1", "react": "18.2.0", "react-dom": "18.2.0", "react-i18next": "^12.0.0", - "react-infinite-scroll-component": "^6.1.0", "react-native-reanimated": "^2.13.0", "react-native-web": "^0.18.10", "solito": "^2.0.5", diff --git a/front/packages/primitives/src/links.tsx b/front/packages/primitives/src/links.tsx index 221614c5..34a2c3f4 100644 --- a/front/packages/primitives/src/links.tsx +++ b/front/packages/primitives/src/links.tsx @@ -78,7 +78,7 @@ export const Link = ({ }, default: {}, }); - const Wrapper = radiusStyle ? View : Fragment; + const Wrapper = radiusStyle.style ? View : Fragment; return ( diff --git a/front/packages/ui/package.json b/front/packages/ui/package.json index d709c386..50a27de2 100644 --- a/front/packages/ui/package.json +++ b/front/packages/ui/package.json @@ -9,6 +9,7 @@ "react-native-svg": "^13.6.0" }, "devDependencies": { + "@shopify/flash-list": "^1.4.0", "@types/react": "^18.0.25", "typescript": "^4.9.3" }, diff --git a/front/packages/ui/src/fetch-infinite.tsx b/front/packages/ui/src/fetch-infinite.tsx index 59e727d4..86120a09 100644 --- a/front/packages/ui/src/fetch-infinite.tsx +++ b/front/packages/ui/src/fetch-infinite.tsx @@ -27,6 +27,7 @@ import { ErrorView, Layout, WithLoading } from "./fetch"; export const InfiniteFetch = ({ query, placeholderCount = 15, + horizontal = false, children, layout, ...props @@ -34,6 +35,7 @@ export const InfiniteFetch = ({ query: QueryIdentifier; placeholderCount?: number; layout: Layout; + horizontal?: boolean; children: ( item: Data extends Page ? WithLoading : WithLoading, key: string | undefined, @@ -65,6 +67,7 @@ export const InfiniteFetch = ({ ] : items } + horizontal={horizontal} keyExtractor={(item: any) => item.id?.toString()} numColumns={numColumns} estimatedItemSize={size} diff --git a/front/packages/ui/src/fetch-infinite.web.tsx b/front/packages/ui/src/fetch-infinite.web.tsx index 6f60ca44..4d40682d 100644 --- a/front/packages/ui/src/fetch-infinite.web.tsx +++ b/front/packages/ui/src/fetch-infinite.web.tsx @@ -19,22 +19,84 @@ */ import { Page, QueryIdentifier, useInfiniteFetch } from "@kyoo/models"; -import { useBreakpointValue } from "@kyoo/primitives"; -import { ReactElement } from "react"; -import InfiniteScroll from "react-infinite-scroll-component"; -import { useYoshiki } from "yoshiki"; +import { ReactElement, useRef } from "react"; +import { Stylable, useYoshiki } from "yoshiki"; import { ErrorView, Layout, WithLoading } from "./fetch"; +const InfiniteScroll = ({ + children, + loader, + layout = "vertical", + loadMore, + hasMore, + isFetching, + ...props +}: { + children?: ReactElement | (ReactElement | null)[] | null; + loader?: (ReactElement | null)[]; + layout?: "vertical" | "horizontal" | "grid"; + loadMore: () => void; + hasMore: boolean; + isFetching: boolean; +} & Stylable) => { + const ref = useRef(null); + const { css } = useYoshiki(); + + return ( +
{ + if (!ref.current || !hasMore || isFetching) return; + const scroll = + layout === "horizontal" + ? ref.current.scrollWidth - ref.current.scrollLeft + : ref.current.scrollHeight - ref.current.scrollTop; + const offset = layout === "horizontal" ? ref.current.offsetWidth : ref.current.offsetHeight; + + if (scroll <= offset * 1.2) loadMore(); + }} + {...css( + [ + { + display: "flex", + alignItems: "flex-start", + overflow: "overlay", + }, + layout == "vertical" && { + flexDirection: "column", + alignItems: "stretch", + }, + layout == "horizontal" && { + flexDirection: "row", + alignItems: "stretch", + }, + layout === "grid" && { + flexWrap: "wrap", + justifyContent: "center", + }, + ], + + props, + )} + > + {children} + {hasMore && isFetching && loader} +
+ ); +}; + export const InfiniteFetch = ({ query, placeholderCount = 15, children, layout, + horizontal = false, ...props }: { query: QueryIdentifier; placeholderCount?: number; layout: Layout; + horizontal?: boolean; children: ( item: Data extends Page ? WithLoading : WithLoading, key: string | undefined, @@ -43,38 +105,19 @@ export const InfiniteFetch = ({ }): JSX.Element | null => { if (!query.infinite) console.warn("A non infinite query was passed to an InfiniteFetch."); - const { items, error, fetchNextPage, hasNextPage } = useInfiniteFetch(query); - const { numColumns } = useBreakpointValue(layout); - const { css } = useYoshiki(); + const { items, error, fetchNextPage, hasNextPage, isFetching } = useInfiniteFetch(query); + const grid = layout.numColumns !== 1; if (error) return ; return ( children({ isLoading: true } as any, i.toString(), i))} - {...css( - [ - { - display: "flex", - alignItems: "flex-start", - justifyContent: "center", - overflow: "unset !important", - }, - numColumns === 1 && { - flexDirection: "column", - alignItems: "stretch", - }, - numColumns !== 1 && { - flexWrap: "wrap", - }, - ], - - props, - )} + {...props} > {items?.map((item, i) => children({ ...item, isLoading: false } as any, (item as any).id?.toString(), i), diff --git a/front/packages/ui/src/fetch.tsx b/front/packages/ui/src/fetch.tsx index efd3ad26..e912551c 100644 --- a/front/packages/ui/src/fetch.tsx +++ b/front/packages/ui/src/fetch.tsx @@ -48,12 +48,12 @@ export const Fetch = ({ const { data, error } = useFetch(query); if (error) return ; - if (placeholderCount === 1 || !isPage(data)) - return children(data ? { ...data, isLoading: false } : ({ isLoading: true } as any), 0); if (!data) return ( <>{[...Array(placeholderCount)].map((_, i) => children({ isLoading: true } as any, i))} ); + if (!isPage(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))}; }; diff --git a/front/yarn.lock b/front/yarn.lock index 921d8e87..0b9fb41f 100644 --- a/front/yarn.lock +++ b/front/yarn.lock @@ -2322,6 +2322,7 @@ __metadata: dependencies: "@kyoo/models": "workspace:^" "@kyoo/primitives": "workspace:^" + "@shopify/flash-list": ^1.4.0 "@types/react": ^18.0.25 react-native-svg: ^13.6.0 typescript: ^4.9.3 @@ -3156,6 +3157,20 @@ __metadata: languageName: node linkType: hard +"@shopify/flash-list@npm:^1.4.0": + version: 1.4.0 + resolution: "@shopify/flash-list@npm:1.4.0" + dependencies: + recyclerlistview: 4.2.0 + tslib: 2.4.0 + peerDependencies: + "@babel/runtime": "*" + react: "*" + react-native: "*" + checksum: c6510b0d6ae6404fe92ede0c918ba184bc2b27ed39c627eebad16a6542792cb34e750e2004e1a9ce165f9d729f1af0555cba1e4c224fd52bfd2a600fdc9e2a65 + languageName: node + linkType: hard + "@sideway/address@npm:^4.1.3": version: 4.1.4 resolution: "@sideway/address@npm:4.1.4" @@ -9834,15 +9849,6 @@ __metadata: languageName: node linkType: hard -"next-transpile-modules@npm:^10.0.0": - version: 10.0.0 - resolution: "next-transpile-modules@npm:10.0.0" - dependencies: - enhanced-resolve: ^5.10.0 - checksum: 3300fc7081f63b2c9487588db7cbe718f209dfd2111adec22d9c8af0e3c8ade2d95fd45f91e045546d78d98cafc78a49431de9a623360d33831b5e694bf007c9 - languageName: node - linkType: hard - "next@npm:13.0.5": version: 13.0.5 resolution: "next@npm:13.0.5" @@ -10923,17 +10929,6 @@ __metadata: languageName: node linkType: hard -"react-infinite-scroll-component@npm:^6.1.0": - version: 6.1.0 - resolution: "react-infinite-scroll-component@npm:6.1.0" - dependencies: - throttle-debounce: ^2.1.0 - peerDependencies: - react: ">=16.0.0" - checksum: 3708398934366df907dbad215247ebc1033221957ce7e32289ea31750cce70aa16513e2d03743e06c8b868ac7c542d12d5dbb6c830fd408433a4762f3cb5ecfb - languageName: node - linkType: hard - "react-is@npm:^16.12.0 || ^17.0.0 || ^18.0.0, react-is@npm:^18.2.0": version: 18.2.0 resolution: "react-is@npm:18.2.0" @@ -11234,6 +11229,20 @@ __metadata: languageName: node linkType: hard +"recyclerlistview@npm:4.2.0": + version: 4.2.0 + resolution: "recyclerlistview@npm:4.2.0" + dependencies: + lodash.debounce: 4.0.8 + prop-types: 15.8.1 + ts-object-utils: 0.0.5 + peerDependencies: + react: ">= 15.2.1" + react-native: ">= 0.30.0" + checksum: 6cba6a99fb487067c509112b94e3d4d3905d782bbcb7af2cffbd57c601a4650d670e4eee5fec18d195d58ff6ec01a47288c5510379a2f37da3c5fc0a58860441 + languageName: node + linkType: hard + "regenerate-unicode-properties@npm:^10.1.0": version: 10.1.0 resolution: "regenerate-unicode-properties@npm:10.1.0" @@ -12624,13 +12633,6 @@ __metadata: languageName: node linkType: hard -"throttle-debounce@npm:^2.1.0": - version: 2.3.0 - resolution: "throttle-debounce@npm:2.3.0" - checksum: 6d90aa2ddb294f8dad13d854a1cfcd88fdb757469669a096a7da10f515ee466857ac1e750649cb9da931165c6f36feb448318e7cb92570f0a3679d20e860a925 - languageName: node - linkType: hard - "through2@npm:^2.0.1": version: 2.0.5 resolution: "through2@npm:2.0.5" @@ -13307,12 +13309,10 @@ __metadata: next: 13.0.5 next-fonts: ^1.5.1 next-translate: ^1.6.0 - next-transpile-modules: ^10.0.0 raf: ^3.4.1 react: 18.2.0 react-dom: 18.2.0 react-i18next: ^12.0.0 - react-infinite-scroll-component: ^6.1.0 react-native-reanimated: ^2.13.0 react-native-web: ^0.18.10 solito: ^2.0.5