diff --git a/src-tauri/migrations/20230804083544_add_network_to_account.sql b/src-tauri/migrations/20230804083544_add_network_to_account.sql new file mode 100644 index 00000000..3fac9cfd --- /dev/null +++ b/src-tauri/migrations/20230804083544_add_network_to_account.sql @@ -0,0 +1,2 @@ +-- Add migration script here +ALTER TABLE accounts ADD network JSON; \ No newline at end of file diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 4052417b..43a99a62 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -89,6 +89,12 @@ fn main() { sql: include_str!("../migrations/20230725010250_update_default_relays.sql"), kind: MigrationKind::Up, }, + Migration { + version: 20230804083544, + description: "add network to accounts", + sql: include_str!("../migrations/20230804083544_add_network_to_account.sql"), + kind: MigrationKind::Up, + }, ], ) .build(), diff --git a/src/app.tsx b/src/app.tsx index 0c32dfed..1001d0aa 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -18,7 +18,7 @@ import { WelcomeScreen } from '@app/auth/welcome'; import { ChannelScreen } from '@app/channel'; import { ChatScreen } from '@app/chats'; import { ErrorScreen } from '@app/error'; -import { NoteScreen } from '@app/note'; +import { EventScreen } from '@app/events'; import { Root } from '@app/root'; import { AccountSettingsScreen } from '@app/settings/account'; import { GeneralSettingsScreen } from '@app/settings/general'; @@ -85,7 +85,7 @@ const router = createBrowserRouter([ children: [ { path: 'space', element: }, { path: 'trending', element: }, - { path: 'note/:id', element: }, + { path: 'events/:id', element: }, { path: 'users/:pubkey', element: }, { path: 'chats/:pubkey', element: }, { path: 'channel/:id', element: }, diff --git a/src/app/events/index.tsx b/src/app/events/index.tsx new file mode 100644 index 00000000..7538c04f --- /dev/null +++ b/src/app/events/index.tsx @@ -0,0 +1,51 @@ +import { useParams } from 'react-router-dom'; + +import { + NoteActions, + NoteContent, + NoteReplyForm, + NoteStats, + ThreadUser, +} from '@shared/notes'; +import { RepliesList } from '@shared/notes/replies/list'; +import { NoteSkeleton } from '@shared/notes/skeleton'; + +import { useAccount } from '@utils/hooks/useAccount'; +import { useEvent } from '@utils/hooks/useEvent'; + +export function EventScreen() { + const { id } = useParams(); + const { account } = useAccount(); + const { status, data } = useEvent(id); + + return ( +
+
+ {status === 'loading' ? ( +
+
+ +
+
+ ) : ( +
+
+ +
+ +
+
+ + +
+
+
+ )} +
+ + +
+
+
+ ); +} diff --git a/src/app/note/index.tsx b/src/app/note/index.tsx deleted file mode 100644 index 36433de4..00000000 --- a/src/app/note/index.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { useParams } from 'react-router-dom'; - -import { useLiveThread } from '@app/space/hooks/useLiveThread'; - -import { NoteMetadata } from '@shared/notes/metadata'; -import { NoteReplyForm } from '@shared/notes/replies/form'; -import { RepliesList } from '@shared/notes/replies/list'; -import { NoteSkeleton } from '@shared/notes/skeleton'; -import { User } from '@shared/user'; - -import { useAccount } from '@utils/hooks/useAccount'; -import { useEvent } from '@utils/hooks/useEvent'; - -export function NoteScreen() { - const { id } = useParams(); - const { account } = useAccount(); - const { status, data } = useEvent(id); - - useLiveThread(id); - - return ( -
-
- {status === 'loading' ? ( -
-
- -
-
- ) : ( -
-
- -
- -
-
-
- {account && } -
-
- )} -
- -
-
-
- ); -} diff --git a/src/app/root.tsx b/src/app/root.tsx index 83070cae..43f8fee4 100644 --- a/src/app/root.tsx +++ b/src/app/root.tsx @@ -27,27 +27,39 @@ export function Root() { const { ndk, relayUrls, fetcher } = useNDK(); const { status, account } = useAccount(); - async function getFollows() { - const authors: string[] = []; + async function fetchNetwork() { + const network = new Set(); + // fetch user's follows const user = ndk.getUser({ hexpubkey: account.pubkey }); const follows = await user.follows(); - follows.forEach((follow: NDKUser) => { - authors.push(nip19.decode(follow.npub).data as string); + network.add(nip19.decode(follow.npub).data as string); }); - // update follows in db - await updateAccount('follows', authors, account.pubkey); + // update user's follows in db + await updateAccount('follows', [...network]); - return authors; + // fetch network + for (const item of network) { + const user = ndk.getUser({ hexpubkey: item }); + const follows = await user.follows(); + follows.forEach((follow: NDKUser) => { + network.add(nip19.decode(follow.npub).data as string); + }); + } + + // update user's network in db + await updateAccount('network', [...network]); + + return [...network]; } async function fetchNotes() { try { - const follows = await getFollows(); + const network = await fetchNetwork(); - if (follows.length > 0) { + if (network.length > 0) { let since: number; if (totalNotes === 0 || lastLogin === 0) { since = nHoursAgo(48); @@ -57,7 +69,7 @@ export function Root() { const events = fetcher.allEventsIterator( relayUrls, - { kinds: [1], authors: follows }, + { kinds: [1], authors: network }, { since: since }, { skipVerification: true } ); diff --git a/src/app/space/components/blocks/following.tsx b/src/app/space/components/blocks/network.tsx similarity index 98% rename from src/app/space/components/blocks/following.tsx rename to src/app/space/components/blocks/network.tsx index 9a6aff52..1461c2c0 100644 --- a/src/app/space/components/blocks/following.tsx +++ b/src/app/space/components/blocks/network.tsx @@ -16,7 +16,7 @@ import { LumeEvent } from '@utils/types'; const ITEM_PER_PAGE = 10; -export function FollowingBlock() { +export function NetworkBlock() { // subscribe for live update useNewsfeed(); @@ -130,7 +130,7 @@ export function FollowingBlock() { ref={parentRef} className="scrollbar-hide relative h-full w-[400px] shrink-0 overflow-y-auto bg-white/10 pb-20" > - +
{status === 'loading' ? (
diff --git a/src/app/space/index.tsx b/src/app/space/index.tsx index c74a9fc9..ee131071 100644 --- a/src/app/space/index.tsx +++ b/src/app/space/index.tsx @@ -2,9 +2,9 @@ import { useQuery } from '@tanstack/react-query'; import { useCallback } from 'react'; import { FeedBlock } from '@app/space/components/blocks/feed'; -import { FollowingBlock } from '@app/space/components/blocks/following'; import { HashtagBlock } from '@app/space/components/blocks/hashtag'; import { ImageBlock } from '@app/space/components/blocks/image'; +import { NetworkBlock } from '@app/space/components/blocks/network'; import { ThreadBlock } from '@app/space/components/blocks/thread'; import { UserBlock } from '@app/space/components/blocks/user'; import { FeedModal } from '@app/space/components/modals/feed'; @@ -53,7 +53,7 @@ export function SpaceScreen() { return (
- + {status === 'loading' ? (
diff --git a/src/libs/ndk/cache.tsx b/src/libs/ndk/cache.tsx index 273fa72b..96a408c9 100644 --- a/src/libs/ndk/cache.tsx +++ b/src/libs/ndk/cache.tsx @@ -14,8 +14,6 @@ export default class TauriAdapter implements NDKCacheAdapter { public async query(subscription: NDKSubscription): Promise { const { filter } = subscription; - // if this filter uses both authors and kinds, then we need to query for each combination of author and kind - // and then combine the results if (filter.authors && filter.kinds) { const promises = []; diff --git a/src/libs/storage.tsx b/src/libs/storage.tsx index 51e6157f..744df69e 100644 --- a/src/libs/storage.tsx +++ b/src/libs/storage.tsx @@ -63,15 +63,12 @@ export async function createAccount( } // update account -export async function updateAccount( - column: string, - value: string | string[], - pubkey: string -) { +export async function updateAccount(column: string, value: string | string[]) { const db = await connect(); - return await db.execute(`UPDATE accounts SET ${column} = ? WHERE pubkey = ?;`, [ + const account = await getActiveAccount(); + return await db.execute(`UPDATE accounts SET ${column} = ? WHERE id = ?;`, [ value, - pubkey, + account.id, ]); } diff --git a/src/shared/composer/modal.tsx b/src/shared/composer/modal.tsx index 446f4248..12560670 100644 --- a/src/shared/composer/modal.tsx +++ b/src/shared/composer/modal.tsx @@ -18,14 +18,10 @@ export function ComposerModal() { const { account } = useAccount(); const [toggle, open] = useComposer((state) => [state.toggleModal, state.open]); - const closeModal = () => { - toggle(false); - }; - useHotkeys(COMPOSE_SHORTCUT, () => toggle(true)); return ( - +
closeModal()} + onClick={() => toggle(false)} className="inline-flex h-8 w-8 items-center justify-center rounded-md hover:bg-zinc-800" > diff --git a/src/shared/notes/actions/more.tsx b/src/shared/notes/actions/more.tsx index 16de4ecf..8b79a3d8 100644 --- a/src/shared/notes/actions/more.tsx +++ b/src/shared/notes/actions/more.tsx @@ -8,14 +8,15 @@ import { Link } from 'react-router-dom'; import { HorizontalDotsIcon } from '@shared/icons'; export function MoreActions({ id, pubkey }: { id: string; pubkey: string }) { - const nevent = nip19.neventEncode(id as unknown as EventPointer); - const copyID = async () => { - await writeText(nevent); + await writeText(nip19.neventEncode({ id: id, author: pubkey } as EventPointer)); }; const copyLink = async () => { - await writeText('https://nostr.com/' + nevent); + await writeText( + 'https://nostr.com/' + + nip19.neventEncode({ id: id, author: pubkey } as EventPointer) + ); }; return ( @@ -41,12 +42,12 @@ export function MoreActions({ id, pubkey }: { id: string; pubkey: string }) {
- + diff --git a/src/utils/types.d.ts b/src/utils/types.d.ts index dd78f4ad..00b5c92d 100644 --- a/src/utils/types.d.ts +++ b/src/utils/types.d.ts @@ -20,9 +20,10 @@ export interface Account extends NDKUserProfile { id: number; npub: string; pubkey: string; - privkey: string; follows: string[] | string; + network: string[] | string; is_active: number; + privkey?: string; // deprecated } export interface Profile extends NDKUserProfile {