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