|
|
|
|
@ -2,7 +2,7 @@
@@ -2,7 +2,7 @@
|
|
|
|
|
import { goto } from '$app/navigation'; |
|
|
|
|
import { nostrClient } from '../../services/nostr/nostr-client.js'; |
|
|
|
|
import { relayManager } from '../../services/nostr/relay-manager.js'; |
|
|
|
|
import { isParameterizedReplaceableKind } from '../../types/kind-lookup.js'; |
|
|
|
|
import { isParameterizedReplaceableKind, isReplaceableKind } from '../../types/kind-lookup.js'; |
|
|
|
|
import type { NostrEvent } from '../../types/nostr.js'; |
|
|
|
|
|
|
|
|
|
interface Props { |
|
|
|
|
@ -48,9 +48,61 @@
@@ -48,9 +48,61 @@
|
|
|
|
|
loadingKinds = new Set(); |
|
|
|
|
loadedKinds = new Set(); |
|
|
|
|
|
|
|
|
|
// Load events for all kinds in parallel |
|
|
|
|
const loadPromises = PROFILE_EVENT_KINDS.map(({ kind }) => loadEventForKind(kind)); |
|
|
|
|
await Promise.all(loadPromises); |
|
|
|
|
// Separate replaceable kinds from parameterized replaceable kinds |
|
|
|
|
const replaceableKinds = PROFILE_EVENT_KINDS |
|
|
|
|
.map(({ kind }) => kind) |
|
|
|
|
.filter(isReplaceableKind); |
|
|
|
|
|
|
|
|
|
const parameterizedKinds = PROFILE_EVENT_KINDS |
|
|
|
|
.map(({ kind }) => kind) |
|
|
|
|
.filter(isParameterizedReplaceableKind); |
|
|
|
|
|
|
|
|
|
// Mark all kinds as loading |
|
|
|
|
const allKinds = [...replaceableKinds, ...parameterizedKinds]; |
|
|
|
|
loadingKinds = new Set(allKinds); |
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
const relays = relayManager.getProfileReadRelays(); |
|
|
|
|
|
|
|
|
|
// Single fetch for all replaceable kinds |
|
|
|
|
if (replaceableKinds.length > 0) { |
|
|
|
|
const events = await nostrClient.fetchEvents( |
|
|
|
|
[{ kinds: replaceableKinds, authors: [pubkey], limit: replaceableKinds.length }], |
|
|
|
|
relays, |
|
|
|
|
{ useCache: true, cacheResults: true } |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
// Group events by kind and get the newest for each kind |
|
|
|
|
const eventsByKind = new Map<number, NostrEvent[]>(); |
|
|
|
|
for (const event of events) { |
|
|
|
|
if (!eventsByKind.has(event.kind)) { |
|
|
|
|
eventsByKind.set(event.kind, []); |
|
|
|
|
} |
|
|
|
|
eventsByKind.get(event.kind)!.push(event); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Get newest event for each kind |
|
|
|
|
const newMap = new Map(eventMap); |
|
|
|
|
for (const kind of replaceableKinds) { |
|
|
|
|
const kindEvents = eventsByKind.get(kind) || []; |
|
|
|
|
if (kindEvents.length > 0) { |
|
|
|
|
const newest = kindEvents.sort((a, b) => b.created_at - a.created_at)[0]; |
|
|
|
|
newMap.set(kind, newest); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
eventMap = newMap; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Load parameterized replaceable kinds separately (they need d-tag handling) |
|
|
|
|
const parameterizedPromises = parameterizedKinds.map(kind => loadEventForKind(kind)); |
|
|
|
|
await Promise.all(parameterizedPromises); |
|
|
|
|
} catch (error) { |
|
|
|
|
console.error('Error loading profile events:', error); |
|
|
|
|
} finally { |
|
|
|
|
// Mark all kinds as loaded |
|
|
|
|
loadedKinds = new Set(allKinds); |
|
|
|
|
loadingKinds = new Set(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async function loadEventForKind(kind: number) { |
|
|
|
|
|