@@ -64,7 +64,7 @@ export function GroupForm({ id }: { id: number }) {
key={item}
type="button"
onClick={() => toggleUser(item)}
- className="inline-flex items-center justify-between px-3 py-2 rounded-xl bg-neutral-50 dark:bg-neutral-950 hover:bg-neutral-100 dark:hover:bg-neutral-900"
+ className="inline-flex items-center justify-between px-3 py-2 rounded-lg bg-neutral-50 dark:bg-neutral-950 hover:bg-neutral-100 dark:hover:bg-neutral-900"
>
{users.includes(item) ? (
diff --git a/packages/@columns/group/src/event.tsx b/packages/@columns/group/src/event.tsx
new file mode 100644
index 00000000..1174c079
--- /dev/null
+++ b/packages/@columns/group/src/event.tsx
@@ -0,0 +1,29 @@
+import { ThreadNote } from "@lume/ark";
+import { ArrowLeftIcon } from "@lume/icons";
+import { ReplyList } from "@lume/ui";
+import { useNavigate, useParams } from "react-router-dom";
+import { WVList } from "virtua";
+
+export function EventRoute() {
+ const { id } = useParams();
+ const navigate = useNavigate();
+
+ return (
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/packages/@columns/group/src/home.tsx b/packages/@columns/group/src/home.tsx
index ada62adb..f92e2686 100644
--- a/packages/@columns/group/src/home.tsx
+++ b/packages/@columns/group/src/home.tsx
@@ -31,7 +31,7 @@ export function HomeRoute({
signal: AbortSignal;
pageParam: number;
}) => {
- const authors = JSON.parse(content);
+ const authors: string[] = JSON.parse(content);
const events = await ark.getInfiniteEvents({
filter: {
kinds: [NDKKind.Text, NDKKind.Repost],
diff --git a/packages/@columns/group/src/index.tsx b/packages/@columns/group/src/index.tsx
index bbbafd16..5ca24d6b 100644
--- a/packages/@columns/group/src/index.tsx
+++ b/packages/@columns/group/src/index.tsx
@@ -2,7 +2,9 @@ import { Column } from "@lume/ark";
import { GroupFeedsIcon } from "@lume/icons";
import { IColumn } from "@lume/types";
import { GroupForm } from "./components/form";
+import { EventRoute } from "./event";
import { HomeRoute } from "./home";
+import { UserRoute } from "./user";
export function Group({ column }: { column: IColumn }) {
const colKey = `group-${column.id}`;
@@ -22,6 +24,8 @@ export function Group({ column }: { column: IColumn }) {
path="/"
element={
}
/>
+
} />
+
} />
>
) : (
diff --git a/packages/@columns/group/src/user.tsx b/packages/@columns/group/src/user.tsx
new file mode 100644
index 00000000..8d46f957
--- /dev/null
+++ b/packages/@columns/group/src/user.tsx
@@ -0,0 +1,213 @@
+import {
+ RepostNote,
+ TextNote,
+ useArk,
+ useProfile,
+ useStorage,
+} from "@lume/ark";
+import { ArrowLeftIcon, ArrowRightCircleIcon, LoaderIcon } from "@lume/icons";
+import { NIP05 } from "@lume/ui";
+import { FETCH_LIMIT, displayNpub } from "@lume/utils";
+import { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk";
+import { useInfiniteQuery } from "@tanstack/react-query";
+import { useEffect, useMemo, useState } from "react";
+import { Link, useNavigate, useParams } from "react-router-dom";
+import { toast } from "sonner";
+import { WVList } from "virtua";
+
+export function UserRoute() {
+ const ark = useArk();
+ const storage = useStorage();
+ const navigate = useNavigate();
+
+ const { id } = useParams();
+ const { user } = useProfile(id);
+ const { data, hasNextPage, isLoading, isFetchingNextPage, fetchNextPage } =
+ useInfiniteQuery({
+ queryKey: ["user-posts", id],
+ initialPageParam: 0,
+ queryFn: async ({
+ signal,
+ pageParam,
+ }: {
+ signal: AbortSignal;
+ pageParam: number;
+ }) => {
+ const events = await ark.getInfiniteEvents({
+ filter: {
+ kinds: [NDKKind.Text, NDKKind.Repost],
+ authors: [id],
+ },
+ limit: FETCH_LIMIT,
+ pageParam,
+ signal,
+ });
+
+ return events;
+ },
+ getNextPageParam: (lastPage) => {
+ const lastEvent = lastPage.at(-1);
+ if (!lastEvent) return;
+ return lastEvent.created_at - 1;
+ },
+ refetchOnWindowFocus: false,
+ });
+
+ const [followed, setFollowed] = useState(false);
+
+ const allEvents = useMemo(
+ () => (data ? data.pages.flatMap((page) => page) : []),
+ [data],
+ );
+
+ const follow = async (pubkey: string) => {
+ try {
+ const add = await ark.createContact({ pubkey });
+ if (add) {
+ setFollowed(true);
+ } else {
+ toast.success("You already follow this user");
+ }
+ } catch (error) {
+ console.log(error);
+ }
+ };
+
+ const unfollow = async (pubkey: string) => {
+ try {
+ const remove = await ark.deleteContact({ pubkey });
+ if (remove) {
+ setFollowed(false);
+ }
+ } catch (error) {
+ console.log(error);
+ }
+ };
+
+ const renderItem = (event: NDKEvent) => {
+ switch (event.kind) {
+ case NDKKind.Text:
+ return
;
+ case NDKKind.Repost:
+ return
;
+ default:
+ return
;
+ }
+ };
+
+ useEffect(() => {
+ if (storage.account.contacts.includes(id)) {
+ setFollowed(true);
+ }
+ }, []);
+
+ return (
+
+
+
+
+
+
+
+

+
+ {followed ? (
+
+ ) : (
+
+ )}
+
+ Message
+
+
+
+
+
+
+ {user?.name ||
+ user?.display_name ||
+ user?.displayName ||
+ "Anon"}
+
+ {user?.nip05 ? (
+
+ ) : (
+
+ {displayNpub(id, 16)}
+
+ )}
+
+
+ {user?.about}
+
+
+
+
+
+ Latest posts
+
+
+ {isLoading ? (
+
+
+
+ ) : (
+ allEvents.map((item) => renderItem(item))
+ )}
+
+ {hasNextPage ? (
+
+ ) : null}
+
+
+
+
+
+ );
+}
diff --git a/packages/@columns/hashtag/package.json b/packages/@columns/hashtag/package.json
index a1ef1154..43f8d126 100644
--- a/packages/@columns/hashtag/package.json
+++ b/packages/@columns/hashtag/package.json
@@ -13,7 +13,7 @@
"react": "^18.2.0",
"react-router-dom": "^6.21.1",
"sonner": "^1.3.1",
- "virtua": "^0.18.0"
+ "virtua": "^0.18.1"
},
"devDependencies": {
"@lume/tailwindcss": "workspace:^",
diff --git a/packages/@columns/notification/package.json b/packages/@columns/notification/package.json
index 220889d3..a2372483 100644
--- a/packages/@columns/notification/package.json
+++ b/packages/@columns/notification/package.json
@@ -10,7 +10,7 @@
"@nostr-dev-kit/ndk": "^2.3.2",
"@tanstack/react-query": "^5.17.0",
"react": "^18.2.0",
- "virtua": "^0.18.0"
+ "virtua": "^0.18.1"
},
"devDependencies": {
"@lume/tailwindcss": "workspace:^",
diff --git a/packages/@columns/thread/package.json b/packages/@columns/thread/package.json
index 39fd0a1e..0eceea8e 100644
--- a/packages/@columns/thread/package.json
+++ b/packages/@columns/thread/package.json
@@ -13,7 +13,7 @@
"react": "^18.2.0",
"react-router-dom": "^6.21.1",
"sonner": "^1.3.1",
- "virtua": "^0.18.0"
+ "virtua": "^0.18.1"
},
"devDependencies": {
"@lume/tailwindcss": "workspace:^",
diff --git a/packages/@columns/timeline/package.json b/packages/@columns/timeline/package.json
index b7597be8..e3e2b59e 100644
--- a/packages/@columns/timeline/package.json
+++ b/packages/@columns/timeline/package.json
@@ -13,7 +13,7 @@
"react": "^18.2.0",
"react-router-dom": "^6.21.1",
"sonner": "^1.3.1",
- "virtua": "^0.18.0"
+ "virtua": "^0.18.1"
},
"devDependencies": {
"@lume/tailwindcss": "workspace:^",
diff --git a/packages/@columns/user/package.json b/packages/@columns/user/package.json
index 741f7d40..673a6566 100644
--- a/packages/@columns/user/package.json
+++ b/packages/@columns/user/package.json
@@ -13,7 +13,7 @@
"react": "^18.2.0",
"react-router-dom": "^6.21.1",
"sonner": "^1.3.1",
- "virtua": "^0.18.0"
+ "virtua": "^0.18.1"
},
"devDependencies": {
"@lume/tailwindcss": "workspace:^",
diff --git a/packages/ark/package.json b/packages/ark/package.json
index 09ca25be..58e87b92 100644
--- a/packages/ark/package.json
+++ b/packages/ark/package.json
@@ -33,7 +33,7 @@
"@tiptap/react": "^2.1.13",
"@vidstack/react": "^1.9.8",
"get-urls": "^12.1.0",
- "markdown-to-jsx": "^7.3.2",
+ "markdown-to-jsx": "^7.4.0",
"minidenticons": "^4.2.0",
"nanoid": "^5.0.4",
"nostr-fetch": "^0.14.1",
diff --git a/packages/icons/src/antenas.tsx b/packages/icons/src/antenas.tsx
new file mode 100644
index 00000000..cf9efb8c
--- /dev/null
+++ b/packages/icons/src/antenas.tsx
@@ -0,0 +1,19 @@
+export function AntenasIcon(props: JSX.IntrinsicElements["svg"]) {
+ return (
+
+ );
+}
diff --git a/packages/utils/src/constants.ts b/packages/utils/src/constants.ts
index b1f2a2fc..9d65e920 100644
--- a/packages/utils/src/constants.ts
+++ b/packages/utils/src/constants.ts
@@ -34,16 +34,13 @@ export const HASHTAGS = [
export const COL_TYPES = {
user: 1,
thread: 2,
- group: 3,
- article: 4,
- file: 5,
- trendingNotes: 6,
- trendingAccounts: 7,
- topic: 8,
- hashtag: 9,
- notification: 9998,
+ hashtag: 3,
+ group: 4,
+ antenas: 5,
+ topic: 6,
+ trendingNotes: 9000,
+ trendingAccounts: 9001,
newsfeed: 9999,
- list: 10000,
};
export const TOPICS = [
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index a5a8b096..2c1a4b36 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -20,6 +20,9 @@ importers:
apps/desktop:
dependencies:
+ '@columns/antenas':
+ specifier: workspace:^
+ version: link:../../packages/@columns/antenas
'@columns/group':
specifier: workspace:^
version: link:../../packages/@columns/group
@@ -189,8 +192,8 @@ importers:
specifier: ^10.1.0
version: 10.1.0
markdown-to-jsx:
- specifier: ^7.3.2
- version: 7.3.2(react@18.2.0)
+ specifier: ^7.4.0
+ version: 7.4.0(react@18.2.0)
minidenticons:
specifier: ^4.2.0
version: 4.2.0
@@ -240,8 +243,8 @@ importers:
specifier: ^0.8.8
version: 0.8.8(@tiptap/core@2.1.13)
virtua:
- specifier: ^0.18.0
- version: 0.18.0(react-dom@18.2.0)(react@18.2.0)
+ specifier: ^0.18.1
+ version: 0.18.1(react-dom@18.2.0)(react@18.2.0)
devDependencies:
'@lume/tailwindcss':
specifier: workspace:^
@@ -292,6 +295,58 @@ importers:
specifier: ^4.2.3
version: 4.2.3(typescript@5.3.3)(vite@4.5.1)
+ packages/@columns/antenas:
+ dependencies:
+ '@lume/ark':
+ specifier: workspace:^
+ version: link:../../ark
+ '@lume/icons':
+ specifier: workspace:^
+ version: link:../../icons
+ '@lume/ui':
+ specifier: workspace:^
+ version: link:../../ui
+ '@lume/utils':
+ specifier: workspace:^
+ version: link:../../utils
+ '@nostr-dev-kit/ndk':
+ specifier: ^2.3.2
+ version: 2.3.2(typescript@5.3.3)
+ '@tanstack/react-query':
+ specifier: ^5.17.0
+ version: 5.17.0(react@18.2.0)
+ react:
+ specifier: ^18.2.0
+ version: 18.2.0
+ react-router-dom:
+ specifier: ^6.21.1
+ version: 6.21.1(react-dom@18.2.0)(react@18.2.0)
+ sonner:
+ specifier: ^1.3.1
+ version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
+ virtua:
+ specifier: ^0.18.1
+ version: 0.18.1(react-dom@18.2.0)(react@18.2.0)
+ devDependencies:
+ '@lume/tailwindcss':
+ specifier: workspace:^
+ version: link:../../tailwindcss
+ '@lume/tsconfig':
+ specifier: workspace:^
+ version: link:../../tsconfig
+ '@lume/types':
+ specifier: workspace:^
+ version: link:../../types
+ '@types/react':
+ specifier: ^18.2.46
+ version: 18.2.46
+ tailwind:
+ specifier: ^4.0.0
+ version: 4.0.0
+ typescript:
+ specifier: ^5.3.3
+ version: 5.3.3
+
packages/@columns/group:
dependencies:
'@lume/ark':
@@ -322,8 +377,8 @@ importers:
specifier: ^1.3.1
version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
virtua:
- specifier: ^0.18.0
- version: 0.18.0(react-dom@18.2.0)(react@18.2.0)
+ specifier: ^0.18.1
+ version: 0.18.1(react-dom@18.2.0)(react@18.2.0)
devDependencies:
'@lume/tailwindcss':
specifier: workspace:^
@@ -374,8 +429,8 @@ importers:
specifier: ^1.3.1
version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
virtua:
- specifier: ^0.18.0
- version: 0.18.0(react-dom@18.2.0)(react@18.2.0)
+ specifier: ^0.18.1
+ version: 0.18.1(react-dom@18.2.0)(react@18.2.0)
devDependencies:
'@lume/tailwindcss':
specifier: workspace:^
@@ -417,8 +472,8 @@ importers:
specifier: ^18.2.0
version: 18.2.0
virtua:
- specifier: ^0.18.0
- version: 0.18.0(react-dom@18.2.0)(react@18.2.0)
+ specifier: ^0.18.1
+ version: 0.18.1(react-dom@18.2.0)(react@18.2.0)
devDependencies:
'@lume/tailwindcss':
specifier: workspace:^
@@ -466,8 +521,8 @@ importers:
specifier: ^1.3.1
version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
virtua:
- specifier: ^0.18.0
- version: 0.18.0(react-dom@18.2.0)(react@18.2.0)
+ specifier: ^0.18.1
+ version: 0.18.1(react-dom@18.2.0)(react@18.2.0)
devDependencies:
'@lume/tailwindcss':
specifier: workspace:^
@@ -518,8 +573,8 @@ importers:
specifier: ^1.3.1
version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
virtua:
- specifier: ^0.18.0
- version: 0.18.0(react-dom@18.2.0)(react@18.2.0)
+ specifier: ^0.18.1
+ version: 0.18.1(react-dom@18.2.0)(react@18.2.0)
devDependencies:
'@lume/tailwindcss':
specifier: workspace:^
@@ -570,8 +625,8 @@ importers:
specifier: ^1.3.1
version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
virtua:
- specifier: ^0.18.0
- version: 0.18.0(react-dom@18.2.0)(react@18.2.0)
+ specifier: ^0.18.1
+ version: 0.18.1(react-dom@18.2.0)(react@18.2.0)
devDependencies:
'@lume/tailwindcss':
specifier: workspace:^
@@ -682,8 +737,8 @@ importers:
specifier: ^12.1.0
version: 12.1.0
markdown-to-jsx:
- specifier: ^7.3.2
- version: 7.3.2(react@18.2.0)
+ specifier: ^7.4.0
+ version: 7.4.0(react@18.2.0)
minidenticons:
specifier: ^4.2.0
version: 4.2.0
@@ -2369,8 +2424,8 @@ packages:
resolution: {integrity: sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==}
dependencies:
'@noble/curves': 1.1.0
- '@noble/hashes': 1.3.1
- '@scure/base': 1.1.1
+ '@noble/hashes': 1.3.3
+ '@scure/base': 1.1.5
dev: false
/@scure/bip39@1.2.1:
@@ -4672,8 +4727,8 @@ packages:
uc.micro: 2.0.0
dev: false
- /markdown-to-jsx@7.3.2(react@18.2.0):
- resolution: {integrity: sha512-B+28F5ucp83aQm+OxNrPkS8z0tMKaeHiy0lHJs3LqCyDQFtWuenaIrkaVTgAm1pf1AU85LXltva86hlaT17i8Q==}
+ /markdown-to-jsx@7.4.0(react@18.2.0):
+ resolution: {integrity: sha512-zilc+MIkVVXPyTb4iIUTIz9yyqfcWjszGXnwF9K/aiBWcHXFcmdEMTkG01/oQhwSCH7SY1BnG6+ev5BzWmbPrg==}
engines: {node: '>= 10'}
peerDependencies:
react: '>= 0.14.0'
@@ -6285,8 +6340,8 @@ packages:
engines: {node: '>= 0.8'}
dev: true
- /virtua@0.18.0(react-dom@18.2.0)(react@18.2.0):
- resolution: {integrity: sha512-ztDBzTbzSluK//xvcXhCfjDbwkuBFSPD43ZO2SR5tNI46/BEb1oNBI/lu6CAE8MmlXr10ZdaFOdbm6LtC0hvlQ==}
+ /virtua@0.18.1(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-Viyg7r6zeHJO/upSgTXmykRAWHKOhnEjso9eUPVfLc1BEf4SWdGeq2dhD9CdsNpSXwkhQ7GyNepVu6L8DG7wow==}
peerDependencies:
react: '>=16.14.0'
react-dom: '>=16.14.0'