diff --git a/src/app/inital-data/pages/index.page.tsx b/src/app/inital-data/pages/index.page.tsx
index f4f83831..8f74db3d 100644
--- a/src/app/inital-data/pages/index.page.tsx
+++ b/src/app/inital-data/pages/index.page.tsx
@@ -20,6 +20,15 @@ import { getParentID, nip02ToArray } from "@utils/transform";
import { useContext, useEffect, useRef } from "react";
import { navigate } from "vite-plugin-ssr/client/router";
+function isJSON(str: string) {
+ try {
+ JSON.parse(str);
+ } catch (e) {
+ return false;
+ }
+ return true;
+}
+
export function Page() {
const pool: any = useContext(RelayContext);
const now = useRef(new Date());
@@ -157,19 +166,23 @@ export function Page() {
);
break;
// long post
- case 30023:
+ case 30023: {
// insert event to local database
- createNote(
- event.id,
- account.id,
- event.pubkey,
- event.kind,
- event.tags,
- event.content,
- event.created_at,
- "",
- );
+ const verifyMetadata = isJSON(event.tags);
+ if (verifyMetadata) {
+ createNote(
+ event.id,
+ account.id,
+ event.pubkey,
+ event.kind,
+ event.tags,
+ event.content,
+ event.created_at,
+ "",
+ );
+ }
break;
+ }
default:
break;
}
diff --git a/src/app/threads/_default.page.tsx b/src/app/threads/_default.page.tsx
new file mode 100644
index 00000000..a2814770
--- /dev/null
+++ b/src/app/threads/_default.page.tsx
@@ -0,0 +1 @@
+export { LayoutNewsfeed as Layout } from "./layout";
diff --git a/src/app/threads/components/author.tsx b/src/app/threads/components/author.tsx
new file mode 100644
index 00000000..f1e351ff
--- /dev/null
+++ b/src/app/threads/components/author.tsx
@@ -0,0 +1,11 @@
+export function ThreadAuthor({
+ pubkey,
+ time,
+}: { pubkey: string; time: number }) {
+ return (
+
+ );
+}
diff --git a/src/app/threads/components/base.tsx b/src/app/threads/components/base.tsx
new file mode 100644
index 00000000..c8308bc9
--- /dev/null
+++ b/src/app/threads/components/base.tsx
@@ -0,0 +1,21 @@
+import { ThreadAuthor } from "@app/threads/components/author";
+
+export function ThreadBase({ event }: { event: any }) {
+ const metadata = JSON.parse(event.metadata);
+ const title = metadata.find((i: any) => i[0] === "title")[1];
+ const summary = metadata.find((i: any) => i[0] === "summary")[1] || "";
+
+ return (
+
+ );
+}
diff --git a/src/app/threads/layout.tsx b/src/app/threads/layout.tsx
new file mode 100644
index 00000000..42e6af95
--- /dev/null
+++ b/src/app/threads/layout.tsx
@@ -0,0 +1,31 @@
+import AppHeader from "@shared/appHeader";
+import MultiAccounts from "@shared/multiAccounts";
+import Navigation from "@shared/navigation";
+
+export function LayoutNewsfeed({ children }: { children: React.ReactNode }) {
+ return (
+
+ );
+}
diff --git a/src/app/threads/pages/index.page.tsx b/src/app/threads/pages/index.page.tsx
index 4e429c0d..bbabd391 100644
--- a/src/app/threads/pages/index.page.tsx
+++ b/src/app/threads/pages/index.page.tsx
@@ -1,7 +1,113 @@
+import { NoteSkeleton } from "@app/note/components/skeleton";
+import { ThreadBase } from "@app/threads/components/base";
+import { useInfiniteQuery } from "@tanstack/react-query";
+import { useVirtualizer } from "@tanstack/react-virtual";
+import { getLongNotes } from "@utils/storage";
+import { useEffect, useRef } from "react";
+
+const ITEM_PER_PAGE = 10;
+const TIME = Math.floor(Date.now() / 1000);
+
export function Page() {
+ const {
+ status,
+ error,
+ data,
+ fetchNextPage,
+ hasNextPage,
+ isFetching,
+ isFetchingNextPage,
+ }: any = useInfiniteQuery({
+ queryKey: ["threads"],
+ queryFn: async ({ pageParam = 0 }) => {
+ return await getLongNotes(TIME, ITEM_PER_PAGE, pageParam);
+ },
+ getNextPageParam: (lastPage) => lastPage.nextCursor,
+ });
+
+ const allRows = data ? data.pages.flatMap((d: { data: any }) => d.data) : [];
+ const parentRef = useRef();
+
+ const rowVirtualizer = useVirtualizer({
+ count: hasNextPage ? allRows.length + 1 : allRows.length,
+ getScrollElement: () => parentRef.current,
+ estimateSize: () => 500,
+ overscan: 2,
+ });
+
+ const itemsVirtualizer = rowVirtualizer.getVirtualItems();
+
+ useEffect(() => {
+ const [lastItem] = [...rowVirtualizer.getVirtualItems()].reverse();
+
+ if (!lastItem) {
+ return;
+ }
+
+ if (
+ lastItem.index >= allRows.length - 1 &&
+ hasNextPage &&
+ !isFetchingNextPage
+ ) {
+ fetchNextPage();
+ }
+ }, [fetchNextPage, allRows.length, rowVirtualizer.getVirtualItems()]);
+
return (
-
-
MySpace
+
+ {status === "loading" ? (
+
+ ) : status === "error" ? (
+
{error.message}
+ ) : (
+
+
+ {rowVirtualizer.getVirtualItems().map((virtualRow) => {
+ const note = allRows[virtualRow.index];
+ if (note) {
+ return (
+
+
+
+ );
+ }
+ })}
+
+
+ )}
+
+ {isFetching && !isFetchingNextPage ? (
+
+ ) : null}
+
);
}
diff --git a/src/app/today/pages/index.page.tsx b/src/app/today/pages/index.page.tsx
index 52b95f43..37de0cf6 100644
--- a/src/app/today/pages/index.page.tsx
+++ b/src/app/today/pages/index.page.tsx
@@ -55,7 +55,6 @@ export function Page() {
) {
fetchNextPage();
}
- // eslint-disable-next-line react-hooks/exhaustive-deps
}, [fetchNextPage, allRows.length, rowVirtualizer.getVirtualItems()]);
return (
diff --git a/src/shared/eventCollector.tsx b/src/shared/eventCollector.tsx
index 103f1066..c7a38056 100644
--- a/src/shared/eventCollector.tsx
+++ b/src/shared/eventCollector.tsx
@@ -14,6 +14,15 @@ import { useSetAtom } from "jotai";
import { useContext, useRef } from "react";
import useSWRSubscription from "swr/subscription";
+function isJSON(str: string) {
+ try {
+ JSON.parse(str);
+ } catch (e) {
+ return false;
+ }
+ return true;
+}
+
export default function EventCollector() {
const pool: any = useContext(RelayContext);
@@ -97,19 +106,23 @@ export default function EventCollector() {
);
break;
// long post
- case 30023:
- // insert event to local database
- createNote(
- event.id,
- account.id,
- event.pubkey,
- event.kind,
- event.tags,
- event.content,
- event.created_at,
- "",
- );
+ case 30023: {
+ const verifyMetadata = isJSON(event.tags);
+ if (verifyMetadata) {
+ // insert event to local database
+ createNote(
+ event.id,
+ account.id,
+ event.pubkey,
+ event.kind,
+ event.tags,
+ event.content,
+ event.created_at,
+ "",
+ );
+ }
break;
+ }
default:
break;
}
diff --git a/src/utils/storage.tsx b/src/utils/storage.tsx
index ecff58dc..5f3e7161 100644
--- a/src/utils/storage.tsx
+++ b/src/utils/storage.tsx
@@ -132,7 +132,7 @@ export async function getLongNotes(
const notes: any = { data: null, nextCursor: 0 };
const query: any = await db.select(
- `SELECT * FROM notes WHERE created_at <= "${time}" AND kind = 30023 GROUP BY parent_id ORDER BY created_at DESC LIMIT "${limit}" OFFSET "${offset}";`,
+ `SELECT * FROM notes WHERE created_at <= "${time}" AND kind = 30023 ORDER BY created_at DESC LIMIT "${limit}" OFFSET "${offset}";`,
);
notes["data"] = query;