openThread(e)}
- className="relative z-10 flex h-min min-h-min w-full select-text flex-col border-b border-zinc-800 py-5 px-3 hover:bg-black/20"
+ className="relative z-10 m-0 flex h-min min-h-min w-full select-text flex-col border-b border-zinc-800 py-5 px-3 hover:bg-black/20"
>
<>{getParent}>
diff --git a/src/pages/newsfeed/following.tsx b/src/pages/newsfeed/following.tsx
index d9dbc998..39ac11cf 100644
--- a/src/pages/newsfeed/following.tsx
+++ b/src/pages/newsfeed/following.tsx
@@ -5,48 +5,109 @@ import FormBase from '@components/form/base';
import { NoteBase } from '@components/note/base';
import { Placeholder } from '@components/note/placeholder';
-import { notesAtom } from '@stores/note';
+import { hasNewerNoteAtom } from '@stores/note';
-import { useVirtualizer } from '@tanstack/react-virtual';
+import { dateToUnix } from '@utils/getDate';
+import { getLatestNotes, getNotes } from '@utils/storage';
+
+import { ArrowUpIcon } from '@radix-ui/react-icons';
import { useAtom } from 'jotai';
-import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, Suspense, useRef } from 'react';
+import {
+ JSXElementConstructor,
+ ReactElement,
+ ReactFragment,
+ ReactPortal,
+ useCallback,
+ useEffect,
+ useRef,
+ useState,
+} from 'react';
+import { Virtuoso } from 'react-virtuoso';
export default function Page() {
- const [data]: any = useAtom(notesAtom);
- const parentRef = useRef(null);
+ const [data, setData] = useState([]);
+ const [hasNewerNote, setHasNewerNote] = useAtom(hasNewerNoteAtom);
- const virtualizer = useVirtualizer({
- count: data.length,
- estimateSize: () => 500,
- getScrollElement: () => parentRef.current,
- getItemKey: (index) => data[index].id,
- });
- const items = virtualizer.getVirtualItems();
+ const virtuosoRef = useRef(null);
+ const now = useRef(new Date());
+ const limit = useRef(20);
+ const offset = useRef(0);
+
+ const itemContent: any = useCallback(
+ (index: string | number) => {
+ return
;
+ },
+ [data]
+ );
+
+ const computeItemKey = useCallback(
+ (index: string | number) => {
+ return data[index].id;
+ },
+ [data]
+ );
+
+ const initialData = useCallback(async () => {
+ const result: any = await getNotes(dateToUnix(now.current), limit.current, offset.current);
+ setData((data) => [...data, ...result]);
+ }, []);
+
+ const loadMore = useCallback(async () => {
+ offset.current += limit.current;
+ // next query
+ const result: any = await getNotes(dateToUnix(now.current), limit.current, offset.current);
+ setData((data) => [...data, ...result]);
+ }, []);
+
+ const loadLatest = useCallback(async () => {
+ offset.current += limit.current;
+ // next query
+ const result: any = await getLatestNotes(dateToUnix(now.current));
+ // update data
+ setData((data) => [...result, ...data]);
+ // hide newer trigger
+ setHasNewerNote(false);
+ // scroll to top
+ virtuosoRef.current.scrollToIndex({ index: 0 });
+ }, [setHasNewerNote]);
+
+ useEffect(() => {
+ initialData().catch(console.error);
+ }, [initialData]);
return (
-
-
-
-
-
}>
-
- {items.length > 0 && (
-
-
- {items.map((virtualRow) => (
-
-
-
- ))}
-
-
- )}
+
+ {hasNewerNote && (
+
+
-
+ )}
+
);
}
+const COMPONENTS = {
+ Header: () =>
,
+ EmptyPlaceholder: () =>
,
+ ScrollSeekPlaceholder: () =>
,
+};
+
Page.getLayout = function getLayout(
page:
| string
diff --git a/src/stores/note.tsx b/src/stores/note.tsx
index 443ebc38..920ab931 100644
--- a/src/stores/note.tsx
+++ b/src/stores/note.tsx
@@ -1,24 +1,7 @@
-import { isSSR } from '@utils/ssr';
-import { getAllNotes } from '@utils/storage';
-
import { atom } from 'jotai';
-import { atomsWithQuery } from 'jotai-tanstack-query';
import { atomWithReset } from 'jotai/utils';
// note content
export const noteContentAtom = atomWithReset('');
// notify user that connector has receive newer note
export const hasNewerNoteAtom = atom(false);
-// query notes from database
-export const [notesAtom] = atomsWithQuery(() => ({
- queryKey: ['notes'],
- queryFn: async ({ queryKey: [] }) => {
- const res = isSSR ? [] : await getAllNotes();
- return res;
- },
- refetchInterval: 1000000,
- refetchOnReconnect: true,
- refetchOnWindowFocus: true,
- refetchOnMount: true,
- keepPreviousData: false,
-}));
diff --git a/src/utils/storage.tsx b/src/utils/storage.tsx
index 708aa4a1..e9a5a812 100644
--- a/src/utils/storage.tsx
+++ b/src/utils/storage.tsx
@@ -89,9 +89,19 @@ export async function getCacheProfile(id) {
}
// get all notes
-export async function getAllNotes() {
+export async function getNotes(time, limit, offset) {
const db = await connect();
- return await db.select(`SELECT * FROM cache_notes GROUP BY parent_id ORDER BY created_at DESC LIMIT 500`);
+ return await db.select(
+ `SELECT * FROM cache_notes WHERE created_at <= "${time}" GROUP BY parent_id ORDER BY created_at DESC LIMIT "${limit}" OFFSET "${offset}"`
+ );
+}
+
+// get all latest notes
+export async function getLatestNotes(time) {
+ const db = await connect();
+ return await db.select(
+ `SELECT * FROM cache_notes WHERE created_at > "${time}" GROUP BY parent_id ORDER BY created_at DESC`
+ );
}
// get note by id