diff --git a/dist/index.html b/dist/index.html index fb66ac2f..fc95f5c6 100644 --- a/dist/index.html +++ b/dist/index.html @@ -5,7 +5,7 @@ Markr - Nostr Bookmarks - + diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json index ec0c31f4..6fabcbd7 100644 --- a/node_modules/.package-lock.json +++ b/node_modules/.package-lock.json @@ -1943,6 +1943,23 @@ "url": "lightning:nostrudel@geyser.fund" } }, + "node_modules/applesauce-relay": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/applesauce-relay/-/applesauce-relay-3.1.0.tgz", + "integrity": "sha512-YseV51O3pc9IIX9MoP4XrVmkUq6a0u8h7n/B4zg0Y3bCQEs415LbM3UwIwZzF1DAEnphOu2xXgkH/9QCg5HvFg==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "^1.7.1", + "applesauce-core": "^3.1.0", + "nanoid": "^5.0.9", + "nostr-tools": "~2.15", + "rxjs": "^7.8.1" + }, + "funding": { + "type": "lightning", + "url": "lightning:nostrudel@geyser.fund" + } + }, "node_modules/applesauce-signers": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/applesauce-signers/-/applesauce-signers-3.1.0.tgz", diff --git a/package-lock.json b/package-lock.json index c8ec50b6..8b88ee21 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "applesauce-accounts": "^3.1.0", "applesauce-core": "^3.1.0", "applesauce-react": "^3.1.0", + "applesauce-relay": "^3.1.0", "nostr-tools": "^2.4.0", "react": "^18.2.0", "react-dom": "^18.2.0" @@ -1924,6 +1925,23 @@ "url": "lightning:nostrudel@geyser.fund" } }, + "node_modules/applesauce-relay": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/applesauce-relay/-/applesauce-relay-3.1.0.tgz", + "integrity": "sha512-YseV51O3pc9IIX9MoP4XrVmkUq6a0u8h7n/B4zg0Y3bCQEs415LbM3UwIwZzF1DAEnphOu2xXgkH/9QCg5HvFg==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "^1.7.1", + "applesauce-core": "^3.1.0", + "nanoid": "^5.0.9", + "nostr-tools": "~2.15", + "rxjs": "^7.8.1" + }, + "funding": { + "type": "lightning", + "url": "lightning:nostrudel@geyser.fund" + } + }, "node_modules/applesauce-signers": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/applesauce-signers/-/applesauce-signers-3.1.0.tgz", diff --git a/package.json b/package.json index 52c16f78..e6b16501 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "applesauce-accounts": "^3.1.0", "applesauce-core": "^3.1.0", "applesauce-react": "^3.1.0", + "applesauce-relay": "^3.1.0", "nostr-tools": "^2.4.0", "react": "^18.2.0", "react-dom": "^18.2.0" diff --git a/src/App.tsx b/src/App.tsx index ec84058d..59a599e9 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,23 +2,33 @@ import { useState, useEffect } from 'react' import { EventStoreProvider, AccountsProvider } from 'applesauce-react' import { EventStore } from 'applesauce-core' import { AccountManager } from 'applesauce-accounts' +import { RelayPool } from 'applesauce-relay' import Login from './components/Login' import Bookmarks from './components/Bookmarks' function App() { const [eventStore, setEventStore] = useState(null) const [accountManager, setAccountManager] = useState(null) + const [relayPool, setRelayPool] = useState(null) const [isAuthenticated, setIsAuthenticated] = useState(false) useEffect(() => { - // Initialize event store and account manager + // Initialize event store, account manager, and relay pool const store = new EventStore() const accounts = new AccountManager() + const pool = new RelayPool() + + // Connect to some popular nostr relays + pool.relay('wss://relay.damus.io') + pool.relay('wss://nos.lol') + pool.relay('wss://relay.snort.social') + setEventStore(store) setAccountManager(accounts) + setRelayPool(pool) }, []) - if (!eventStore || !accountManager) { + if (!eventStore || !accountManager || !relayPool) { return
Loading...
} diff --git a/src/components/Bookmarks.tsx b/src/components/Bookmarks.tsx index 454ce21f..5fe16507 100644 --- a/src/components/Bookmarks.tsx +++ b/src/components/Bookmarks.tsx @@ -1,6 +1,7 @@ import { useState, useEffect, useContext } from 'react' import { EventStoreContext, Hooks } from 'applesauce-react' import { NostrEvent } from 'nostr-tools' +import { takeUntil, timer } from 'rxjs' interface Bookmark { id: string @@ -33,30 +34,51 @@ const Bookmarks: React.FC = ({ onLogout }) => { try { setLoading(true) - // Fetch bookmarks according to NIP-51 - // Kind 10003: bookmark lists - // Kind 30003: parameterized replaceable events (bookmark lists with d-tag) - const events = eventStore.getByFilters([ + // Subscribe to bookmark events from relays + // According to NIP-51, we need kind 10003 events (bookmark lists) + const events: NostrEvent[] = [] + + const subscription = eventStore.filters([ { - kinds: [10003, 30003], + kinds: [10003], authors: [activeAccount.pubkey] } - ]) - - const bookmarkList: Bookmark[] = [] - - for (const event of events) { - // Parse bookmark data from event content and tags - const bookmarkData = parseBookmarkEvent(event) - if (bookmarkData) { - bookmarkList.push(bookmarkData) + ]).pipe( + takeUntil(timer(5000)) // Wait up to 5 seconds for events + ).subscribe({ + next: (event) => { + events.push(event) + }, + error: (error) => { + console.error('Error fetching bookmarks:', error) + }, + complete: () => { + // Process collected events + const bookmarkList: Bookmark[] = [] + + for (const event of events) { + const bookmarkData = parseBookmarkEvent(event) + if (bookmarkData) { + bookmarkList.push(bookmarkData) + } + } + + setBookmarks(bookmarkList) + setLoading(false) } - } + }) + + // Clean up subscription after timeout + setTimeout(() => { + subscription.unsubscribe() + if (events.length === 0) { + setBookmarks([]) + setLoading(false) + } + }, 5000) - setBookmarks(bookmarkList) } catch (error) { console.error('Failed to fetch bookmarks:', error) - } finally { setLoading(false) } }