|
|
|
@ -125,7 +125,7 @@ export default function Profile({ |
|
|
|
|
|
|
|
|
|
|
|
const { profile, isFetching } = useFetchProfile(id) |
|
|
|
const { profile, isFetching } = useFetchProfile(id) |
|
|
|
profilePubkeyRef.current = profile?.pubkey ?? null |
|
|
|
profilePubkeyRef.current = profile?.pubkey ?? null |
|
|
|
const { pubkey: accountPubkey, publish, checkLogin } = useNostr() |
|
|
|
const { pubkey: accountPubkey, profileEvent: accountProfileEvent, publish, checkLogin } = useNostr() |
|
|
|
const [paymentInfo, setPaymentInfo] = useState<ReturnType<typeof getPaymentInfoFromEvent> | null>(null) |
|
|
|
const [paymentInfo, setPaymentInfo] = useState<ReturnType<typeof getPaymentInfoFromEvent> | null>(null) |
|
|
|
const [profileEvent, setProfileEvent] = useState<NostrEvent | undefined>(undefined) |
|
|
|
const [profileEvent, setProfileEvent] = useState<NostrEvent | undefined>(undefined) |
|
|
|
const [openZapDialog, setOpenZapDialog] = useState(false) |
|
|
|
const [openZapDialog, setOpenZapDialog] = useState(false) |
|
|
|
@ -140,9 +140,20 @@ export default function Profile({ |
|
|
|
const { relayUrls: currentBrowsingRelayUrls } = useCurrentRelays() |
|
|
|
const { relayUrls: currentBrowsingRelayUrls } = useCurrentRelays() |
|
|
|
const { relaySets, favoriteRelays } = useFavoriteRelays() |
|
|
|
const { relaySets, favoriteRelays } = useFavoriteRelays() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const isSelf = accountPubkey === profile?.pubkey |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const effectiveProfileEvent = useMemo(() => { |
|
|
|
|
|
|
|
if (!isSelf || !accountProfileEvent) return profileEvent |
|
|
|
|
|
|
|
if (!profileEvent) return accountProfileEvent |
|
|
|
|
|
|
|
return accountProfileEvent.created_at >= profileEvent.created_at ? accountProfileEvent : profileEvent |
|
|
|
|
|
|
|
}, [isSelf, profileEvent, accountProfileEvent]) |
|
|
|
|
|
|
|
|
|
|
|
const mergedPaymentMethods = useMemo( |
|
|
|
const mergedPaymentMethods = useMemo( |
|
|
|
() => sortMergedPaymentMethods(mergePaymentMethods(paymentInfo, profile ?? null, profileEvent)), |
|
|
|
() => |
|
|
|
[paymentInfo, profile, profileEvent] |
|
|
|
sortMergedPaymentMethods( |
|
|
|
|
|
|
|
mergePaymentMethods(paymentInfo, profile ?? null, effectiveProfileEvent) |
|
|
|
|
|
|
|
), |
|
|
|
|
|
|
|
[paymentInfo, profile, effectiveProfileEvent] |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
const paymentMethodsByType = useMemo( |
|
|
|
const paymentMethodsByType = useMemo( |
|
|
|
@ -151,30 +162,36 @@ export default function Profile({ |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
const hasTipDialog = useMemo( |
|
|
|
const hasTipDialog = useMemo( |
|
|
|
() => recipientHasAnyPaymentOptions(paymentInfo, profile ?? null, profileEvent), |
|
|
|
() => recipientHasAnyPaymentOptions(paymentInfo, profile ?? null, effectiveProfileEvent), |
|
|
|
[paymentInfo, profile, profileEvent] |
|
|
|
[paymentInfo, profile, effectiveProfileEvent] |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
const prefetchedZapPayment = useMemo( |
|
|
|
const prefetchedZapPayment = useMemo( |
|
|
|
() => |
|
|
|
() => |
|
|
|
profile?.pubkey |
|
|
|
profile?.pubkey |
|
|
|
? buildRecipientZapPaymentData(paymentInfo, profile ?? null, profileEvent ?? null) |
|
|
|
? buildRecipientZapPaymentData(paymentInfo, profile ?? null, effectiveProfileEvent ?? null) |
|
|
|
: null, |
|
|
|
: null, |
|
|
|
[paymentInfo, profile, profileEvent] |
|
|
|
[paymentInfo, profile, effectiveProfileEvent] |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
const syncAuthorReplaceablesFromCache = useCallback(async (pubkey: string) => { |
|
|
|
const syncAuthorReplaceablesFromCache = useCallback( |
|
|
|
try { |
|
|
|
async (pubkey: string, options?: { bustCache?: boolean }) => { |
|
|
|
const [paymentEvent, metaEvent] = await Promise.all([ |
|
|
|
try { |
|
|
|
client.fetchPaymentInfoEvent(pubkey), |
|
|
|
if (options?.bustCache) { |
|
|
|
replaceableEventService.fetchReplaceableEvent(pubkey, kinds.Metadata) |
|
|
|
replaceableEventService.clearAuthorViewPaymentAndMetadataLoaders(pubkey) |
|
|
|
]) |
|
|
|
} |
|
|
|
setPaymentInfo(paymentEvent ? getPaymentInfoFromEvent(paymentEvent) : null) |
|
|
|
const [paymentEvent, metaEvent] = await Promise.all([ |
|
|
|
setProfileEvent(metaEvent ?? undefined) |
|
|
|
client.fetchPaymentInfoEvent(pubkey), |
|
|
|
} catch (error) { |
|
|
|
replaceableEventService.fetchReplaceableEvent(pubkey, kinds.Metadata) |
|
|
|
logger.error('Failed to sync author replaceables from cache', { error, pubkey }) |
|
|
|
]) |
|
|
|
} |
|
|
|
setPaymentInfo(paymentEvent ? getPaymentInfoFromEvent(paymentEvent) : null) |
|
|
|
}, []) |
|
|
|
setProfileEvent(metaEvent ?? undefined) |
|
|
|
|
|
|
|
} catch (error) { |
|
|
|
|
|
|
|
logger.error('Failed to sync author replaceables from cache', { error, pubkey }) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
[] |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
useEffect(() => { |
|
|
|
if (!profile?.pubkey) { |
|
|
|
if (!profile?.pubkey) { |
|
|
|
@ -195,13 +212,21 @@ export default function Profile({ |
|
|
|
void client.refreshAuthorPublishedReplaceablesOnProfileView(profile.pubkey) |
|
|
|
void client.refreshAuthorPublishedReplaceablesOnProfileView(profile.pubkey) |
|
|
|
}, [profile?.pubkey]) |
|
|
|
}, [profile?.pubkey]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
|
|
|
|
if (!isSelf || !profile?.pubkey || !accountProfileEvent) return |
|
|
|
|
|
|
|
setProfileEvent((prev) => |
|
|
|
|
|
|
|
!prev || accountProfileEvent.created_at >= prev.created_at ? accountProfileEvent : prev |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
void syncAuthorReplaceablesFromCache(profile.pubkey, { bustCache: true }) |
|
|
|
|
|
|
|
}, [isSelf, accountProfileEvent, profile?.pubkey, syncAuthorReplaceablesFromCache]) |
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
useEffect(() => { |
|
|
|
if (!profile?.pubkey) return |
|
|
|
if (!profile?.pubkey) return |
|
|
|
const pk = profile.pubkey.toLowerCase() |
|
|
|
const pk = profile.pubkey.toLowerCase() |
|
|
|
const onAuthorReplaceablesRefreshed: EventListener = (domEvt) => { |
|
|
|
const onAuthorReplaceablesRefreshed: EventListener = (domEvt) => { |
|
|
|
const detailPk = (domEvt as CustomEvent<{ pubkey?: string }>).detail?.pubkey?.toLowerCase() |
|
|
|
const detailPk = (domEvt as CustomEvent<{ pubkey?: string }>).detail?.pubkey?.toLowerCase() |
|
|
|
if (detailPk !== pk) return |
|
|
|
if (detailPk !== pk) return |
|
|
|
void syncAuthorReplaceablesFromCache(profile.pubkey) |
|
|
|
void syncAuthorReplaceablesFromCache(profile.pubkey, { bustCache: true }) |
|
|
|
} |
|
|
|
} |
|
|
|
window.addEventListener( |
|
|
|
window.addEventListener( |
|
|
|
ReplaceableEventService.AUTHOR_REPLACEABLES_REFRESHED_EVENT, |
|
|
|
ReplaceableEventService.AUTHOR_REPLACEABLES_REFRESHED_EVENT, |
|
|
|
@ -222,8 +247,6 @@ export default function Profile({ |
|
|
|
() => (profile?.pubkey ? generateImageByPubkey(profile?.pubkey) : ''), |
|
|
|
() => (profile?.pubkey ? generateImageByPubkey(profile?.pubkey) : ''), |
|
|
|
[profile] |
|
|
|
[profile] |
|
|
|
) |
|
|
|
) |
|
|
|
const isSelf = accountPubkey === profile?.pubkey |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** All available relays: current feed, favorites, relay sets, defaults (FAST_READ, FAST_WRITE). */ |
|
|
|
/** All available relays: current feed, favorites, relay sets, defaults (FAST_READ, FAST_WRITE). */ |
|
|
|
const allAvailableRelayUrls = useMemo(() => { |
|
|
|
const allAvailableRelayUrls = useMemo(() => { |
|
|
|
const urls = [ |
|
|
|
const urls = [ |
|
|
|
|