Browse Source

reveal avatars

imwald
Silberengel 1 day ago
parent
commit
085e4e57a2
  1. 36
      src/components/UserAvatar/index.tsx
  2. 16
      src/hooks/useFetchProfile.tsx

36
src/components/UserAvatar/index.tsx

@ -163,18 +163,30 @@ function useDeferRemoteProfileAvatar( @@ -163,18 +163,30 @@ function useDeferRemoteProfileAvatar(
setAllowRemote(true)
return
}
const el = containerRef.current
if (!el) return
const io = new IntersectionObserver(
(entries) => {
if (entries.some((e) => e.isIntersecting)) {
setAllowRemote(true)
}
},
{ root: null, rootMargin: `${AVATAR_VIEWPORT_MARGIN_PX}px`, threshold: 0.01 }
)
io.observe(el)
return () => io.disconnect()
let io: IntersectionObserver | null = null
let raf = 0
const attach = () => {
const el = containerRef.current
if (!el || io) return
io = new IntersectionObserver(
(entries) => {
if (entries.some((e) => e.isIntersecting)) {
setAllowRemote(true)
}
},
{ root: null, rootMargin: `${AVATAR_VIEWPORT_MARGIN_PX}px`, threshold: 0.01 }
)
io.observe(el)
}
attach()
// Ref can still be null on the first effect tick (layout ordering); retry once after paint.
if (!containerRef.current) {
raf = window.requestAnimationFrame(() => attach())
}
return () => {
if (raf) cancelAnimationFrame(raf)
io?.disconnect()
}
}, [remoteHttp, allowRemote, containerRef, deferRemote])
if (sizeBlocked) return fallbackSrc

16
src/hooks/useFetchProfile.tsx

@ -89,9 +89,23 @@ export function useFetchProfile(id?: string, skipCache = false) { @@ -89,9 +89,23 @@ export function useFetchProfile(id?: string, skipCache = false) {
return null
}
// CRITICAL: Check cooldown period first to prevent cascade of duplicate fetches after timeout
// CRITICAL: Check cooldown period first to prevent cascade of duplicate fetches after timeout.
// Still hydrate from session/IndexedDB — otherwise new rows remount after a timeout and stay on
// identicons until cooldown ends with no effect re-run (deps unchanged).
const cooldownExpiry = globalFetchCooldowns.get(pubkey)
if (cooldownExpiry && Date.now() < cooldownExpiry) {
const cachedDuringCooldown = await tryHydrateProfileFromLocalCaches(pubkey, skipCache)
if (!cancelled.current && cachedDuringCooldown) {
setProfile(cachedDuringCooldown)
setIsFetching(false)
initializedPubkeysRef.current.add(pubkey)
if (checkIntervalRef.current) {
clearInterval(checkIntervalRef.current)
checkIntervalRef.current = null
}
effectRunCountRef.current.delete(pubkey)
return cachedDuringCooldown
}
logger.debug('[useFetchProfile] In cooldown period after timeout, skipping fetch', {
pubkey: pubkey.substring(0, 8),
remainingMs: cooldownExpiry - Date.now()

Loading…
Cancel
Save