mirror of
https://github.com/dergigi/boris.git
synced 2026-01-04 23:44:21 +01:00
- Create src/config/kinds.ts with named Nostr kind constants - Add streaming support to fetchAllReads and fetchLinks with onItem callbacks - Update all services to use KINDS constants instead of magic numbers - Add mergeReadItem utility for DRY state management - Add fallbackTitleFromUrl for external links without titles - Relax validation to allow external items without titles - Update Me.tsx to use streaming with Map-based state for reads/links - Fix refresh to merge new data instead of clearing state - Fix empty states for Reads and Links tabs (no more infinite skeletons) - Services updated: readsService, linksService, libraryService, bookmarkService, exploreService, highlights/fetchByAuthor
65 lines
2.4 KiB
TypeScript
65 lines
2.4 KiB
TypeScript
import { RelayPool, completeOnEose, onlyEvents } from 'applesauce-relay'
|
|
import { lastValueFrom, merge, Observable, takeUntil, timer, tap, toArray } from 'rxjs'
|
|
import { NostrEvent } from 'nostr-tools'
|
|
import { Highlight } from '../../types/highlights'
|
|
import { prioritizeLocalRelays, partitionRelays } from '../../utils/helpers'
|
|
import { eventToHighlight, dedupeHighlights, sortHighlights } from '../highlightEventProcessor'
|
|
import { UserSettings } from '../settingsService'
|
|
import { rebroadcastEvents } from '../rebroadcastService'
|
|
import { KINDS } from '../../config/kinds'
|
|
|
|
export const fetchHighlights = async (
|
|
relayPool: RelayPool,
|
|
pubkey: string,
|
|
onHighlight?: (highlight: Highlight) => void,
|
|
settings?: UserSettings
|
|
): Promise<Highlight[]> => {
|
|
try {
|
|
const relayUrls = Array.from(relayPool.relays.values()).map(relay => relay.url)
|
|
const ordered = prioritizeLocalRelays(relayUrls)
|
|
const { local: localRelays, remote: remoteRelays } = partitionRelays(ordered)
|
|
|
|
const seenIds = new Set<string>()
|
|
const local$ = localRelays.length > 0
|
|
? relayPool
|
|
.req(localRelays, { kinds: [KINDS.Highlights], authors: [pubkey] })
|
|
.pipe(
|
|
onlyEvents(),
|
|
tap((event: NostrEvent) => {
|
|
if (!seenIds.has(event.id)) {
|
|
seenIds.add(event.id)
|
|
if (onHighlight) onHighlight(eventToHighlight(event))
|
|
}
|
|
}),
|
|
completeOnEose(),
|
|
takeUntil(timer(1200))
|
|
)
|
|
: new Observable<NostrEvent>((sub) => sub.complete())
|
|
const remote$ = remoteRelays.length > 0
|
|
? relayPool
|
|
.req(remoteRelays, { kinds: [KINDS.Highlights], authors: [pubkey] })
|
|
.pipe(
|
|
onlyEvents(),
|
|
tap((event: NostrEvent) => {
|
|
if (!seenIds.has(event.id)) {
|
|
seenIds.add(event.id)
|
|
if (onHighlight) onHighlight(eventToHighlight(event))
|
|
}
|
|
}),
|
|
completeOnEose(),
|
|
takeUntil(timer(6000))
|
|
)
|
|
: new Observable<NostrEvent>((sub) => sub.complete())
|
|
const rawEvents: NostrEvent[] = await lastValueFrom(merge(local$, remote$).pipe(toArray()))
|
|
|
|
await rebroadcastEvents(rawEvents, relayPool, settings)
|
|
const uniqueEvents = dedupeHighlights(rawEvents)
|
|
const highlights = uniqueEvents.map(eventToHighlight)
|
|
return sortHighlights(highlights)
|
|
} catch {
|
|
return []
|
|
}
|
|
}
|
|
|
|
|