story-research-zapwall/hooks/useAuthorsProfiles.ts
2026-01-10 09:41:57 +01:00

67 lines
2.0 KiB
TypeScript

import { useEffect, useState, useMemo } from 'react'
import type { NostrProfile } from '@/types/nostr'
import { nostrService } from '@/lib/nostr'
interface AuthorProfile extends NostrProfile {
pubkey: string
}
export function useAuthorsProfiles(authorPubkeys: string[]): {
profiles: Map<string, AuthorProfile>
loading: boolean
} {
const [profiles, setProfiles] = useState<Map<string, AuthorProfile>>(new Map())
const [loading, setLoading] = useState(true)
const pubkeysKey = useMemo(() => [...authorPubkeys].sort().join(','), [authorPubkeys])
useEffect(() => {
void loadAndSetProfiles({ authorPubkeys, setProfiles, setLoading })
}, [pubkeysKey, authorPubkeys])
return { profiles, loading }
}
async function loadAndSetProfiles(params: {
authorPubkeys: string[]
setProfiles: (value: Map<string, AuthorProfile>) => void
setLoading: (value: boolean) => void
}): Promise<void> {
if (params.authorPubkeys.length === 0) {
params.setProfiles(new Map())
params.setLoading(false)
return
}
params.setLoading(true)
const profilesMap = await loadProfilesMap(params.authorPubkeys)
params.setProfiles(profilesMap)
params.setLoading(false)
}
async function loadProfilesMap(authorPubkeys: string[]): Promise<Map<string, AuthorProfile>> {
const results = await Promise.all(authorPubkeys.map(loadSingleProfile))
const map = new Map<string, AuthorProfile>()
results.forEach(({ pubkey, profile }) => {
map.set(pubkey, profile)
})
return map
}
async function loadSingleProfile(pubkey: string): Promise<{ pubkey: string; profile: AuthorProfile }> {
try {
const profile = await nostrService.getProfile(pubkey)
return { pubkey, profile: ensureAuthorProfile(pubkey, profile) }
} catch (loadError) {
console.error(`Error loading profile for ${pubkey}:`, loadError)
return { pubkey, profile: { pubkey } }
}
}
function ensureAuthorProfile(pubkey: string, profile: NostrProfile | null): AuthorProfile {
if (!profile) {
return { pubkey }
}
return { ...profile, pubkey }
}