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)
}