aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/mobile/components/bookmarks/BookmarkList.tsx31
-rw-r--r--apps/web/app/dashboard/lists/[listId]/page.tsx2
-rw-r--r--apps/web/app/dashboard/search/page.tsx2
-rw-r--r--apps/web/app/dashboard/tags/[tagName]/page.tsx2
-rw-r--r--apps/web/components/dashboard/bookmarks/Bookmarks.tsx2
-rw-r--r--apps/web/components/dashboard/bookmarks/BookmarksGrid.tsx47
6 files changed, 66 insertions, 20 deletions
diff --git a/apps/mobile/components/bookmarks/BookmarkList.tsx b/apps/mobile/components/bookmarks/BookmarkList.tsx
index e7b5e5f2..8a19c045 100644
--- a/apps/mobile/components/bookmarks/BookmarkList.tsx
+++ b/apps/mobile/components/bookmarks/BookmarkList.tsx
@@ -1,5 +1,5 @@
import { useEffect, useRef, useState } from "react";
-import { Keyboard, Text, View } from "react-native";
+import { ActivityIndicator, Keyboard, Text, View } from "react-native";
import Animated, { LinearTransition } from "react-native-reanimated";
import { api } from "@/lib/trpc";
import { useScrollToTop } from "@react-navigation/native";
@@ -20,13 +20,26 @@ export default function BookmarkList({
const [refreshing, setRefreshing] = useState(false);
const flatListRef = useRef(null);
useScrollToTop(flatListRef);
- const { data, isPending, isPlaceholderData } =
- api.bookmarks.getBookmarks.useQuery(query);
+ const {
+ data,
+ isPending,
+ isPlaceholderData,
+ error,
+ fetchNextPage,
+ isFetchingNextPage,
+ } = api.bookmarks.getBookmarks.useInfiniteQuery(query, {
+ initialCursor: null,
+ getNextPageParam: (lastPage) => lastPage.nextCursor,
+ });
useEffect(() => {
setRefreshing(isPending || isPlaceholderData);
}, [isPending, isPlaceholderData]);
+ if (error) {
+ return <Text>{JSON.stringify(error)}</Text>;
+ }
+
if (isPending || !data) {
return <FullPageSpinner />;
}
@@ -51,11 +64,21 @@ export default function BookmarkList({
<Text className="text-xl">No Bookmarks</Text>
</View>
}
- data={data.bookmarks}
+ data={data.pages.flatMap((p) => p.bookmarks)}
refreshing={refreshing}
onRefresh={onRefresh}
onScrollBeginDrag={Keyboard.dismiss}
keyExtractor={(b) => b.id}
+ onEndReached={() => fetchNextPage()}
+ ListFooterComponent={
+ isFetchingNextPage ? (
+ <View className="items-center">
+ <ActivityIndicator />
+ </View>
+ ) : (
+ <View />
+ )
+ }
/>
);
}
diff --git a/apps/web/app/dashboard/lists/[listId]/page.tsx b/apps/web/app/dashboard/lists/[listId]/page.tsx
index b9a26053..a8ba4feb 100644
--- a/apps/web/app/dashboard/lists/[listId]/page.tsx
+++ b/apps/web/app/dashboard/lists/[listId]/page.tsx
@@ -43,7 +43,7 @@ export default async function ListPage({
<hr />
<BookmarksGrid
query={{ listId: list.id, archived: false }}
- bookmarks={bookmarks.bookmarks}
+ bookmarks={bookmarks}
/>
</div>
);
diff --git a/apps/web/app/dashboard/search/page.tsx b/apps/web/app/dashboard/search/page.tsx
index 38099c18..62d42a43 100644
--- a/apps/web/app/dashboard/search/page.tsx
+++ b/apps/web/app/dashboard/search/page.tsx
@@ -24,7 +24,7 @@ function SearchComp() {
{data ? (
<BookmarksGrid
query={{ ids: data.bookmarks.map((b) => b.id) }}
- bookmarks={data.bookmarks}
+ bookmarks={data}
/>
) : (
<Loading />
diff --git a/apps/web/app/dashboard/tags/[tagName]/page.tsx b/apps/web/app/dashboard/tags/[tagName]/page.tsx
index dee29c5e..f06062c3 100644
--- a/apps/web/app/dashboard/tags/[tagName]/page.tsx
+++ b/apps/web/app/dashboard/tags/[tagName]/page.tsx
@@ -38,7 +38,7 @@ export default async function TagPage({
<div className="container flex flex-col gap-3">
<span className="pt-4 text-2xl">{tagName}</span>
<hr />
- <BookmarksGrid query={query} bookmarks={bookmarks.bookmarks} />
+ <BookmarksGrid query={query} bookmarks={bookmarks} />
</div>
);
}
diff --git a/apps/web/components/dashboard/bookmarks/Bookmarks.tsx b/apps/web/components/dashboard/bookmarks/Bookmarks.tsx
index 601b1627..96e5c067 100644
--- a/apps/web/components/dashboard/bookmarks/Bookmarks.tsx
+++ b/apps/web/components/dashboard/bookmarks/Bookmarks.tsx
@@ -35,7 +35,7 @@ export default async function Bookmarks({
{showDivider && <hr />}
<BookmarksGrid
query={query}
- bookmarks={bookmarks.bookmarks}
+ bookmarks={bookmarks}
showEditorCard={showEditorCard}
/>
</div>
diff --git a/apps/web/components/dashboard/bookmarks/BookmarksGrid.tsx b/apps/web/components/dashboard/bookmarks/BookmarksGrid.tsx
index 644991bb..b689a192 100644
--- a/apps/web/components/dashboard/bookmarks/BookmarksGrid.tsx
+++ b/apps/web/components/dashboard/bookmarks/BookmarksGrid.tsx
@@ -1,6 +1,7 @@
"use client";
import { useMemo } from "react";
+import { ActionButton } from "@/components/ui/action-button";
import { api } from "@/lib/trpc";
import tailwindConfig from "@/tailwind.config";
import { Slot } from "@radix-ui/react-slot";
@@ -10,6 +11,7 @@ import resolveConfig from "tailwindcss/resolveConfig";
import type {
ZBookmark,
ZGetBookmarksRequest,
+ ZGetBookmarksResponse,
} from "@hoarder/trpc/types/bookmarks";
import EditorCard from "./EditorCard";
@@ -55,24 +57,45 @@ export default function BookmarksGrid({
showEditorCard = false,
}: {
query: ZGetBookmarksRequest;
- bookmarks: ZBookmark[];
+ bookmarks: ZGetBookmarksResponse;
showEditorCard?: boolean;
+ itemsPerPage?: number;
}) {
- const { data } = api.bookmarks.getBookmarks.useQuery(query, {
- initialData: { bookmarks: initialBookmarks },
- });
+ const { data, fetchNextPage, hasNextPage, isFetchingNextPage } =
+ api.bookmarks.getBookmarks.useInfiniteQuery(query, {
+ initialData: () => ({
+ pages: [initialBookmarks],
+ pageParams: [query.cursor],
+ }),
+ initialCursor: null,
+ getNextPageParam: (lastPage) => lastPage.nextCursor,
+ });
+
const breakpointConfig = useMemo(() => getBreakpointConfig(), []);
- if (data.bookmarks.length == 0) {
+ const bookmarks = data!.pages.flatMap((b) => b.bookmarks);
+ if (bookmarks.length == 0) {
return <p>No bookmarks</p>;
}
return (
- <Masonry className="flex gap-4" breakpointCols={breakpointConfig}>
- {showEditorCard && (
- <BookmarkCard>
- <EditorCard />
- </BookmarkCard>
+ <>
+ <Masonry className="flex gap-4" breakpointCols={breakpointConfig}>
+ {showEditorCard && (
+ <BookmarkCard>
+ <EditorCard />
+ </BookmarkCard>
+ )}
+ {bookmarks.map((b) => renderBookmark(b))}
+ </Masonry>
+ {hasNextPage && (
+ <ActionButton
+ loading={isFetchingNextPage}
+ onClick={() => fetchNextPage()}
+ className="mx-auto w-min"
+ variant="ghost"
+ >
+ Load More
+ </ActionButton>
)}
- {data.bookmarks.map((b) => renderBookmark(b))}
- </Masonry>
+ </>
);
}