diff --git a/dist/index.html b/dist/index.html index fc95f5c6..d8e767ea 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 6fabcbd7..37d08f73 100644 --- a/node_modules/.package-lock.json +++ b/node_modules/.package-lock.json @@ -1921,6 +1921,22 @@ "url": "lightning:nostrudel@geyser.fund" } }, + "node_modules/applesauce-loaders": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/applesauce-loaders/-/applesauce-loaders-3.1.0.tgz", + "integrity": "sha512-9IY5RYqoXcIgAAdJNuMjMBr+CI85z1yj708C92UiP9YMQ4mrIIEvZbMmWLApBzRn5XsmmEa00a/iNlXpkRg9Sw==", + "license": "MIT", + "dependencies": { + "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-react": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/applesauce-react/-/applesauce-react-3.1.0.tgz", diff --git a/package-lock.json b/package-lock.json index 8b88ee21..3b71fd53 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "applesauce-accounts": "^3.1.0", "applesauce-core": "^3.1.0", + "applesauce-loaders": "^3.1.0", "applesauce-react": "^3.1.0", "applesauce-relay": "^3.1.0", "nostr-tools": "^2.4.0", @@ -1903,6 +1904,22 @@ "url": "lightning:nostrudel@geyser.fund" } }, + "node_modules/applesauce-loaders": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/applesauce-loaders/-/applesauce-loaders-3.1.0.tgz", + "integrity": "sha512-9IY5RYqoXcIgAAdJNuMjMBr+CI85z1yj708C92UiP9YMQ4mrIIEvZbMmWLApBzRn5XsmmEa00a/iNlXpkRg9Sw==", + "license": "MIT", + "dependencies": { + "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-react": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/applesauce-react/-/applesauce-react-3.1.0.tgz", diff --git a/package.json b/package.json index e6b16501..24fa5f95 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "dependencies": { "applesauce-accounts": "^3.1.0", "applesauce-core": "^3.1.0", + "applesauce-loaders": "^3.1.0", "applesauce-react": "^3.1.0", "applesauce-relay": "^3.1.0", "nostr-tools": "^2.4.0", diff --git a/src/App.tsx b/src/App.tsx index 59a599e9..9fcdbb5c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,6 +3,7 @@ import { EventStoreProvider, AccountsProvider } from 'applesauce-react' import { EventStore } from 'applesauce-core' import { AccountManager } from 'applesauce-accounts' import { RelayPool } from 'applesauce-relay' +import { Loaders } from 'applesauce-loaders' import Login from './components/Login' import Bookmarks from './components/Bookmarks' @@ -10,6 +11,7 @@ function App() { const [eventStore, setEventStore] = useState(null) const [accountManager, setAccountManager] = useState(null) const [relayPool, setRelayPool] = useState(null) + const [addressLoader, setAddressLoader] = useState(null) const [isAuthenticated, setIsAuthenticated] = useState(false) useEffect(() => { @@ -23,12 +25,21 @@ function App() { pool.relay('wss://nos.lol') pool.relay('wss://relay.snort.social') + // Create address loader for fetching replaceable events (like bookmarks) + const loader = Loaders.createAddressLoader(pool, { + eventStore: store, + bufferTime: 1000, + followRelayHints: true, + extraRelays: ['wss://relay.damus.io', 'wss://nos.lol', 'wss://relay.snort.social'] + }) + setEventStore(store) setAccountManager(accounts) setRelayPool(pool) + setAddressLoader(loader) }, []) - if (!eventStore || !accountManager || !relayPool) { + if (!eventStore || !accountManager || !relayPool || !addressLoader) { return
Loading...
} @@ -44,7 +55,10 @@ function App() { {!isAuthenticated ? ( setIsAuthenticated(true)} /> ) : ( - setIsAuthenticated(false)} /> + setIsAuthenticated(false)} + /> )} diff --git a/src/components/Bookmarks.tsx b/src/components/Bookmarks.tsx index 5fe16507..a93a22f4 100644 --- a/src/components/Bookmarks.tsx +++ b/src/components/Bookmarks.tsx @@ -1,7 +1,6 @@ -import { useState, useEffect, useContext } from 'react' -import { EventStoreContext, Hooks } from 'applesauce-react' +import { useState, useEffect } from 'react' +import { Hooks } from 'applesauce-react' import { NostrEvent } from 'nostr-tools' -import { takeUntil, timer } from 'rxjs' interface Bookmark { id: string @@ -13,65 +12,56 @@ interface Bookmark { } interface BookmarksProps { + addressLoader: any onLogout: () => void } -const Bookmarks: React.FC = ({ onLogout }) => { +const Bookmarks: React.FC = ({ addressLoader, onLogout }) => { const [bookmarks, setBookmarks] = useState([]) const [loading, setLoading] = useState(true) - const eventStore = useContext(EventStoreContext) const activeAccount = Hooks.useActiveAccount() useEffect(() => { - if (eventStore && activeAccount) { + if (addressLoader && activeAccount) { fetchBookmarks() } - }, [eventStore, activeAccount]) + }, [addressLoader, activeAccount]) const fetchBookmarks = async () => { - if (!eventStore || !activeAccount) return + if (!addressLoader || !activeAccount) return try { setLoading(true) - // Subscribe to bookmark events from relays - // According to NIP-51, we need kind 10003 events (bookmark lists) - const events: NostrEvent[] = [] + // Use applesauce address loader to fetch bookmark lists (kind 10003) + // This is the proper way according to NIP-51 and applesauce documentation + const bookmarkList: Bookmark[] = [] - const subscription = eventStore.filters([ - { - kinds: [10003], - authors: [activeAccount.pubkey] - } - ]).pipe( - takeUntil(timer(5000)) // Wait up to 5 seconds for events - ).subscribe({ - next: (event) => { - events.push(event) + const subscription = addressLoader({ + kind: 10003, // Bookmark list according to NIP-51 + pubkey: activeAccount.pubkey, + relays: ['wss://relay.damus.io', 'wss://nos.lol', 'wss://relay.snort.social'] + }).subscribe({ + next: (event: NostrEvent) => { + const bookmarkData = parseBookmarkEvent(event) + if (bookmarkData) { + bookmarkList.push(bookmarkData) + } }, - error: (error) => { + error: (error: any) => { console.error('Error fetching bookmarks:', error) + setLoading(false) }, 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 + // Set timeout to prevent hanging setTimeout(() => { subscription.unsubscribe() - if (events.length === 0) { + if (bookmarkList.length === 0) { setBookmarks([]) setLoading(false) }