Files
boris/src/hooks/useBookmarksData.ts
Gigi b055294afc feat: add relay rebroadcast settings for caching and propagation
- Add two new settings:
  - Use local relay(s) as cache (default: enabled)
  - Rebroadcast events to all relays (default: disabled)
- Create rebroadcastService to handle rebroadcasting events
- Hook into article, bookmark, and highlight fetching services
- Automatically rebroadcast fetched events based on settings:
  - Articles when opened
  - Bookmarks when fetched
  - Highlights when fetched
- Add RelayRebroadcastSettings component with plane/globe icons
- Benefits:
  - Local caching for offline access
  - Content propagation across nostr network
  - User control over bandwidth usage
2025-10-09 13:01:38 +01:00

128 lines
4.3 KiB
TypeScript

import { useState, useEffect, useCallback } from 'react'
import { RelayPool } from 'applesauce-relay'
import { Bookmark } from '../types/bookmarks'
import { Highlight } from '../types/highlights'
import { fetchBookmarks } from '../services/bookmarkService'
import { fetchHighlights, fetchHighlightsForArticle } from '../services/highlightService'
import { fetchContacts } from '../services/contactService'
import { UserSettings } from '../services/settingsService'
interface UseBookmarksDataParams {
relayPool: RelayPool | null
// eslint-disable-next-line @typescript-eslint/no-explicit-any
activeAccount: any
// eslint-disable-next-line @typescript-eslint/no-explicit-any
accountManager: any
naddr?: string
currentArticleCoordinate?: string
currentArticleEventId?: string
settings?: UserSettings
}
export const useBookmarksData = ({
relayPool,
activeAccount,
accountManager,
naddr,
currentArticleCoordinate,
currentArticleEventId,
settings
}: UseBookmarksDataParams) => {
const [bookmarks, setBookmarks] = useState<Bookmark[]>([])
const [bookmarksLoading, setBookmarksLoading] = useState(true)
const [highlights, setHighlights] = useState<Highlight[]>([])
const [highlightsLoading, setHighlightsLoading] = useState(true)
const [followedPubkeys, setFollowedPubkeys] = useState<Set<string>>(new Set())
const [isRefreshing, setIsRefreshing] = useState(false)
const handleFetchContacts = useCallback(async () => {
if (!relayPool || !activeAccount) return
const contacts = await fetchContacts(relayPool, activeAccount.pubkey)
setFollowedPubkeys(contacts)
}, [relayPool, activeAccount])
const handleFetchBookmarks = useCallback(async () => {
if (!relayPool || !activeAccount) return
setBookmarksLoading(true)
try {
const fullAccount = accountManager.getActive()
await fetchBookmarks(relayPool, fullAccount || activeAccount, setBookmarks, settings)
} finally {
setBookmarksLoading(false)
}
}, [relayPool, activeAccount, accountManager, settings])
const handleFetchHighlights = useCallback(async () => {
if (!relayPool) return
setHighlightsLoading(true)
try {
if (currentArticleCoordinate) {
const highlightsMap = new Map<string, Highlight>()
await fetchHighlightsForArticle(
relayPool,
currentArticleCoordinate,
currentArticleEventId,
(highlight) => {
// Deduplicate highlights by ID as they arrive
if (!highlightsMap.has(highlight.id)) {
highlightsMap.set(highlight.id, highlight)
const highlightsList = Array.from(highlightsMap.values())
setHighlights(highlightsList.sort((a, b) => b.created_at - a.created_at))
}
},
settings
)
console.log(`🔄 Refreshed ${highlightsMap.size} highlights for article`)
} else if (activeAccount) {
const fetchedHighlights = await fetchHighlights(relayPool, activeAccount.pubkey, undefined, settings)
setHighlights(fetchedHighlights)
}
} catch (err) {
console.error('Failed to fetch highlights:', err)
} finally {
setHighlightsLoading(false)
}
}, [relayPool, activeAccount, currentArticleCoordinate, currentArticleEventId, settings])
const handleRefreshAll = useCallback(async () => {
if (!relayPool || !activeAccount || isRefreshing) return
setIsRefreshing(true)
try {
await handleFetchBookmarks()
await handleFetchHighlights()
await handleFetchContacts()
} catch (err) {
console.error('Failed to refresh data:', err)
} finally {
setIsRefreshing(false)
}
}, [relayPool, activeAccount, isRefreshing, handleFetchBookmarks, handleFetchHighlights, handleFetchContacts])
// Load initial data
useEffect(() => {
if (!relayPool || !activeAccount) return
handleFetchBookmarks()
if (!naddr) {
handleFetchHighlights()
}
handleFetchContacts()
}, [relayPool, activeAccount?.pubkey, naddr, handleFetchBookmarks, handleFetchHighlights, handleFetchContacts])
return {
bookmarks,
bookmarksLoading,
highlights,
setHighlights,
highlightsLoading,
setHighlightsLoading,
followedPubkeys,
isRefreshing,
handleFetchBookmarks,
handleFetchHighlights,
handleRefreshAll
}
}