diff --git a/package.json b/package.json index 0029eb3b..79ae2de6 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "dependencies": { "@floating-ui/react": "^0.23.1", "@headlessui/react": "^1.7.15", - "@nostr-dev-kit/ndk": "^0.4.4", + "@nostr-dev-kit/ndk": "^0.4.5", "@tanstack/react-virtual": "3.0.0-beta.54", "@tauri-apps/api": "^1.3.0", "@vidstack/react": "^0.4.5", @@ -24,7 +24,7 @@ "immer": "^10.0.2", "light-bolt11-decoder": "^3.0.0", "nostr-relaypool": "^0.6.28", - "nostr-tools": "^1.11.1", + "nostr-tools": "^1.11.2", "react": "^18.2.0", "react-dom": "^18.2.0", "react-hook-form": "^7.44.3", @@ -36,7 +36,7 @@ "slate-history": "^0.93.0", "slate-react": "^0.94.2", "swr": "^2.1.5", - "tailwind-merge": "^1.13.0", + "tailwind-merge": "^1.13.1", "tauri-plugin-sql-api": "github:tauri-apps/tauri-plugin-sql", "vidstack": "^0.4.5", "zustand": "^4.3.8" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7f3b7d87..e4186ea1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,8 +8,8 @@ dependencies: specifier: ^1.7.15 version: 1.7.15(react-dom@18.2.0)(react@18.2.0) '@nostr-dev-kit/ndk': - specifier: ^0.4.4 - version: 0.4.4(typescript@4.9.5) + specifier: ^0.4.5 + version: 0.4.5(typescript@4.9.5) '@tanstack/react-virtual': specifier: 3.0.0-beta.54 version: 3.0.0-beta.54(react@18.2.0) @@ -35,8 +35,8 @@ dependencies: specifier: ^0.6.28 version: 0.6.28(ws@8.13.0) nostr-tools: - specifier: ^1.11.1 - version: 1.11.1 + specifier: ^1.11.2 + version: 1.11.2 react: specifier: ^18.2.0 version: 18.2.0 @@ -71,8 +71,8 @@ dependencies: specifier: ^2.1.5 version: 2.1.5(react@18.2.0) tailwind-merge: - specifier: ^1.13.0 - version: 1.13.0 + specifier: ^1.13.1 + version: 1.13.1 tauri-plugin-sql-api: specifier: github:tauri-apps/tauri-plugin-sql version: github.com/tauri-apps/tauri-plugin-sql/312c4d39ac5eb1c6c75e8ecee1c4bc89ed799675 @@ -161,23 +161,23 @@ packages: engines: {node: '>=10'} dev: true - /@babel/code-frame@7.21.4: - resolution: {integrity: sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==} + /@babel/code-frame@7.22.5: + resolution: {integrity: sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==} engines: {node: '>=6.9.0'} dependencies: - '@babel/highlight': 7.18.6 + '@babel/highlight': 7.22.5 dev: false - /@babel/helper-validator-identifier@7.19.1: - resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} + /@babel/helper-validator-identifier@7.22.5: + resolution: {integrity: sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==} engines: {node: '>=6.9.0'} dev: false - /@babel/highlight@7.18.6: - resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} + /@babel/highlight@7.22.5: + resolution: {integrity: sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-validator-identifier': 7.19.1 + '@babel/helper-validator-identifier': 7.22.5 chalk: 2.4.2 js-tokens: 4.0.0 dev: false @@ -566,8 +566,8 @@ packages: '@nodelib/fs.scandir': 2.1.5 fastq: 1.15.0 - /@nostr-dev-kit/ndk@0.4.4(typescript@4.9.5): - resolution: {integrity: sha512-hzXWAlUO1LEmHv3W0Nj0gLmbpZ0gC4WmtDFKdOMnKkFMno0bMobGk8S4hrHHTThigA+OHtkjkPl1vr8fx+a03w==} + /@nostr-dev-kit/ndk@0.4.5(typescript@4.9.5): + resolution: {integrity: sha512-iiWWOHjejt5uBKh0q38hN/jBM2rJsgZn3T0fe9AwQCRTm2PkXYDbfT5uYz+VHaovkJx8WLYeV4Ol9nz4p7b8aA==} dependencies: '@noble/secp256k1': 2.0.0 '@scure/base': 1.1.1 @@ -583,7 +583,7 @@ packages: eventemitter3: 5.0.1 light-bolt11-decoder: 3.0.0 node-fetch: 3.3.1 - nostr-tools: 1.11.1 + nostr-tools: 1.11.2 tsd: 0.28.1 typedoc: 0.24.8(typescript@4.9.5) utf8-buffer: 1.0.0 @@ -3507,14 +3507,14 @@ packages: dependencies: '@jest/source-map': 29.4.3 isomorphic-ws: 5.0.0(ws@8.13.0) - nostr-tools: 1.11.1 + nostr-tools: 1.11.2 safe-stable-stringify: 2.4.3 transitivePeerDependencies: - ws dev: false - /nostr-tools@1.11.1: - resolution: {integrity: sha512-b8BpCiD3wxjBZwrn0wc+CkVj6/7s4sQxp+Az7UkCG80mJu7xTspZsOoUP/geBNwZVYETzEwj+CPBvW8WIP8mBQ==} + /nostr-tools@1.11.2: + resolution: {integrity: sha512-ezN+QwPlFTRZLjstUJw9xacI7/rKKOn18bRitKcArj5YFLaxA2xDIvkryapYZ1IBsJzFYcODmygKIrHdZXsJjw==} dependencies: '@noble/curves': 1.0.0 '@noble/hashes': 1.3.0 @@ -3672,7 +3672,7 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} dependencies: - '@babel/code-frame': 7.21.4 + '@babel/code-frame': 7.22.5 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -4472,8 +4472,8 @@ packages: resolution: {integrity: sha512-qCN98uP7i9z0fIS4amQ5zbGBOq+OSigYeGvPy7NDk8Y9yncqDZ9pRPgfsc2PJIVM9RrJj7GIfuRgmjoUU9zTHQ==} dev: false - /tailwind-merge@1.13.0: - resolution: {integrity: sha512-mUTmDbcU+IhOvJ0c42eLQ/nRkvolTqfpVaVQRSxfJAv9TabS6Y2zW/1wKpKLdKzyL3Gh8j6NTLl6MWNmvOM6kA==} + /tailwind-merge@1.13.1: + resolution: {integrity: sha512-tRtRN22TDokGi2TuYSvuHQuuW6BJ/zlUEG+iYpAQ9i66msc/0eU/+HPccbPnNNH0mCPp0Ob8thaC8Uy9CxHitQ==} dev: false /tailwindcss@3.3.2: diff --git a/src/app/channel/hooks/useChannelProfile.tsx b/src/app/channel/hooks/useChannelProfile.tsx index 53d32280..16c87b41 100644 --- a/src/app/channel/hooks/useChannelProfile.tsx +++ b/src/app/channel/hooks/useChannelProfile.tsx @@ -1,9 +1,5 @@ import { RelayContext } from "@shared/relayProvider"; - -import { READONLY_RELAYS } from "@stores/constants"; - import { getChannel, updateChannelMetadata } from "@utils/storage"; - import { useContext } from "react"; import useSWR, { useSWRConfig } from "swr"; import useSWRSubscription from "swr/subscription"; @@ -18,7 +14,7 @@ const fetcher = async ([, id]) => { }; export function useChannelProfile(id: string, channelPubkey: string) { - const pool: any = useContext(RelayContext); + const ndk = useContext(RelayContext); const { mutate } = useSWRConfig(); const { data, isLoading } = useSWR(["channel-metadata", id], fetcher); @@ -27,30 +23,26 @@ export function useChannelProfile(id: string, channelPubkey: string) { !isLoading && data ? ["channel-metadata", id] : null, ([, key]) => { // subscribe to channel - const unsubscribe = pool.subscribe( - [ - { - "#e": [key], - authors: [channelPubkey], - kinds: [41], - }, - ], - READONLY_RELAYS, - (event: { content: string }) => { - // update in local database - updateChannelMetadata(key, event.content); - // revaildate - mutate(["channel-metadata", key]); - }, - undefined, - undefined, + const sub = ndk.subscribe( { - unsubscribeOnEose: true, + "#e": [key], + authors: [channelPubkey], + kinds: [41], + }, + { + closeOnEose: true, }, ); + sub.addListener("event", (event: { content: string }) => { + // update in local database + updateChannelMetadata(key, event.content); + // revaildate + mutate(["channel-metadata", key]); + }); + return () => { - unsubscribe(); + sub.stop(); }; }, ); diff --git a/src/app/note/components/preview/link.tsx b/src/app/note/components/preview/link.tsx index 00969f18..578b316e 100644 --- a/src/app/note/components/preview/link.tsx +++ b/src/app/note/components/preview/link.tsx @@ -8,7 +8,7 @@ export function LinkPreview({ urls }: { urls: string[] }) { return (
{error &&

failed to load

} - {isLoading && !data ? ( + {isLoading || !data ? (

Loading...

) : ( { createNote( event.id, @@ -66,91 +62,6 @@ export function Page() { } } - async function fetchChannelBlacklist() { - try { - const filter: NDKFilter = { - authors: [account.pubkey], - kinds: [43, 44], - since: lastLogin, - }; - - const events = await ndk.fetchEvents(filter); - events.forEach((event) => { - switch (event.kind) { - case 43: - if (event.tags[0][0] === "e") { - addToBlacklist(account.id, event.tags[0][1], 43, 1); - } - break; - case 44: - if (event.tags[0][0] === "p") { - addToBlacklist(account.id, event.tags[0][1], 44, 1); - } - break; - default: - break; - } - }); - - return true; - } catch (e) { - console.log("error: ", e); - } - } - - async function fetchReceiveMessages() { - try { - const filter: NDKFilter = { - kinds: [4], - "#p": [account.pubkey], - since: lastLogin, - }; - - const events = await ndk.fetchEvents(filter); - events.forEach((event) => { - createChat( - event.id, - account.pubkey, - event.pubkey, - event.content, - event.tags, - event.created_at, - ); - }); - - return true; - } catch (e) { - console.log("error: ", e); - } - } - - async function fetchSendMessages() { - try { - const filter: NDKFilter = { - kinds: [4], - authors: [account.pubkey], - since: lastLogin, - }; - - const events = await ndk.fetchEvents(filter); - events.forEach((event) => { - const receiver = event.tags.find((t) => t[0] === "p")[1]; - createChat( - event.id, - receiver, - account.pubkey, - event.content, - event.tags, - event.created_at, - ); - }); - - return true; - } catch (e) { - console.log("error: ", e); - } - } - useEffect(() => { async function prefetch() { const notes = await fetchNotes(); @@ -158,7 +69,6 @@ export function Page() { navigate("/app/space", { overwriteLastHistoryEntry: true }); } } - prefetch(); }, []); diff --git a/src/libs/ndk.tsx b/src/libs/ndk.tsx index 2b9edc74..f4457b0d 100644 --- a/src/libs/ndk.tsx +++ b/src/libs/ndk.tsx @@ -1,4 +1,10 @@ -import NDK, { NDKConstructorParams } from "@nostr-dev-kit/ndk"; +import NDK, { + NDKConstructorParams, + NDKEvent, + NDKFilter, + NDKFilterOptions, + NDKRelaySet, +} from "@nostr-dev-kit/ndk"; import { FULL_RELAYS } from "@stores/constants"; export async function initNDK( @@ -13,3 +19,25 @@ export async function initNDK( return ndk; } + +export async function prefetchEvents( + ndk: NDK, + filter: NDKFilter, +): Promise> { + return new Promise((resolve) => { + const events: Map = new Map(); + + const relaySetSubscription = ndk.subscribe(filter, { + closeOnEose: true, + }); + + relaySetSubscription.on("event", (event: NDKEvent) => { + event.ndk = ndk; + events.set(event.tagId(), event); + }); + + relaySetSubscription.on("eose", () => { + setTimeout(() => resolve(new Set(events.values())), 2000); + }); + }); +} diff --git a/src/stores/constants.tsx b/src/stores/constants.tsx index 2011a8cc..087df62b 100644 --- a/src/stores/constants.tsx +++ b/src/stores/constants.tsx @@ -7,28 +7,10 @@ export const DEFAULT_CHANNEL_BANNER = export const OPENGRAPH_KEY = "9EJG4SY-19Q4M5J-H8R29C9-091XPCC"; -// read-only relay list -export const READONLY_RELAYS = [ - "wss://welcome.nostr.wine", - "wss://relay.nostr.band", - "wss://relay.damus.io", -]; - -// write-only relay list -export const WRITEONLY_RELAYS = [ - "wss://relay.damus.io", - "wss://relay.nostr.band", -]; - -// metadata relay -export const METADATA_RELAY = ["wss://relay.nostr.band"]; - -// full-relay list export const FULL_RELAYS = [ "wss://welcome.nostr.wine", "wss://relay.nostr.band", "wss://relay.damus.io", - "wss://relay.snort.social", "wss://relayable.org", "wss://nostr.mutinywallet.com", ];