|
|
|
@ -2,6 +2,7 @@ import NormalFeed from '@/components/NormalFeed' |
|
|
|
import type { TNoteListRef } from '@/components/NoteList' |
|
|
|
import type { TNoteListRef } from '@/components/NoteList' |
|
|
|
import { ensureHomeFeedTrendingRelay } from '@/lib/home-feed-relays' |
|
|
|
import { ensureHomeFeedTrendingRelay } from '@/lib/home-feed-relays' |
|
|
|
import { checkAlgoRelay } from '@/lib/relay' |
|
|
|
import { checkAlgoRelay } from '@/lib/relay' |
|
|
|
|
|
|
|
import { dedupeNormalizeRelayUrlsOrdered } from '@/lib/relay-url-priority' |
|
|
|
import { normalizeUrl } from '@/lib/url' |
|
|
|
import { normalizeUrl } from '@/lib/url' |
|
|
|
import { useFeed } from '@/providers/feed-context' |
|
|
|
import { useFeed } from '@/providers/feed-context' |
|
|
|
import { useKindFilterOrDefaults } from '@/providers/KindFilterProvider' |
|
|
|
import { useKindFilterOrDefaults } from '@/providers/KindFilterProvider' |
|
|
|
@ -21,7 +22,8 @@ const RelaysFeed = forwardRef< |
|
|
|
const { relayUrls, replyRelayUrls } = useFeed() |
|
|
|
const { relayUrls, replyRelayUrls } = useFeed() |
|
|
|
const { showKinds } = useKindFilterOrDefaults() |
|
|
|
const { showKinds } = useKindFilterOrDefaults() |
|
|
|
const [areAlgoRelays, setAreAlgoRelays] = useState(false) |
|
|
|
const [areAlgoRelays, setAreAlgoRelays] = useState(false) |
|
|
|
const [relayCapabilityReady, setRelayCapabilityReady] = useState(false) |
|
|
|
/** Timeline REQs must not wait on NIP-11; cache/IDB serves algo detection in the background. */ |
|
|
|
|
|
|
|
const [relayCapabilityReady, setRelayCapabilityReady] = useState(true) |
|
|
|
|
|
|
|
|
|
|
|
const relayUrlsKey = useMemo( |
|
|
|
const relayUrlsKey = useMemo( |
|
|
|
() => |
|
|
|
() => |
|
|
|
@ -41,47 +43,40 @@ const RelaysFeed = forwardRef< |
|
|
|
.join('|'), |
|
|
|
.join('|'), |
|
|
|
[replyRelayUrls] |
|
|
|
[replyRelayUrls] |
|
|
|
) |
|
|
|
) |
|
|
|
const stableRelayUrls = useMemo(() => relayUrls, [relayUrlsKey]) |
|
|
|
const stableRelayUrls = useMemo( |
|
|
|
const stableReplyRelayUrls = useMemo(() => replyRelayUrls, [replyRelayUrlsKey]) |
|
|
|
() => dedupeNormalizeRelayUrlsOrdered(relayUrls), |
|
|
|
|
|
|
|
[relayUrlsKey] |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
const stableReplyRelayUrls = useMemo( |
|
|
|
|
|
|
|
() => dedupeNormalizeRelayUrlsOrdered(replyRelayUrls), |
|
|
|
|
|
|
|
[replyRelayUrlsKey] |
|
|
|
|
|
|
|
) |
|
|
|
const homeFeedSeenOnAllowlistOp = useMemo(() => stableRelayUrls, [relayUrlsKey]) |
|
|
|
const homeFeedSeenOnAllowlistOp = useMemo(() => stableRelayUrls, [relayUrlsKey]) |
|
|
|
const homeFeedSeenOnAllowlistReplies = useMemo(() => stableReplyRelayUrls, [replyRelayUrlsKey]) |
|
|
|
const homeFeedSeenOnAllowlistReplies = useMemo(() => stableReplyRelayUrls, [replyRelayUrlsKey]) |
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
useEffect(() => { |
|
|
|
if (relayUrls.length === 0) { |
|
|
|
if (stableRelayUrls.length === 0) { |
|
|
|
setAreAlgoRelays(false) |
|
|
|
setAreAlgoRelays(false) |
|
|
|
setRelayCapabilityReady(false) |
|
|
|
setRelayCapabilityReady(false) |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
let cancelled = false |
|
|
|
setRelayCapabilityReady(true) |
|
|
|
setRelayCapabilityReady(false) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const init = async () => { |
|
|
|
|
|
|
|
const timeoutPromise = new Promise<never>((_, reject) => { |
|
|
|
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
|
|
reject(new Error('getRelayInfos timeout after 8 seconds')) |
|
|
|
|
|
|
|
}, 8000) |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let cancelled = false |
|
|
|
|
|
|
|
void (async () => { |
|
|
|
try { |
|
|
|
try { |
|
|
|
const relayInfos = await Promise.race([ |
|
|
|
// Memory + IndexedDB cache first; network only for stale/missing (see relay-info.service).
|
|
|
|
relayInfoService.getRelayInfos(relayUrls), |
|
|
|
const relayInfos = await relayInfoService.getRelayInfos(stableRelayUrls) |
|
|
|
timeoutPromise |
|
|
|
|
|
|
|
]) |
|
|
|
|
|
|
|
if (cancelled) return |
|
|
|
if (cancelled) return |
|
|
|
const areAlgo = relayInfos.every((relayInfo) => checkAlgoRelay(relayInfo)) |
|
|
|
setAreAlgoRelays(relayInfos.every((relayInfo) => checkAlgoRelay(relayInfo))) |
|
|
|
setAreAlgoRelays(areAlgo) |
|
|
|
|
|
|
|
} catch { |
|
|
|
} catch { |
|
|
|
if (!cancelled) setAreAlgoRelays(false) |
|
|
|
if (!cancelled) setAreAlgoRelays(false) |
|
|
|
} finally { |
|
|
|
|
|
|
|
if (!cancelled) setRelayCapabilityReady(true) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
})() |
|
|
|
|
|
|
|
|
|
|
|
void init() |
|
|
|
|
|
|
|
return () => { |
|
|
|
return () => { |
|
|
|
cancelled = true |
|
|
|
cancelled = true |
|
|
|
} |
|
|
|
} |
|
|
|
}, [relayUrlsKey, relayUrls.length]) |
|
|
|
}, [relayUrlsKey, stableRelayUrls]) |
|
|
|
|
|
|
|
|
|
|
|
/** Stable identity when kind filter is empty so `subRequests` does not invalidate every render. */ |
|
|
|
/** Stable identity when kind filter is empty so `subRequests` does not invalidate every render. */ |
|
|
|
const fallbackNoteKinds = useMemo(() => [kinds.ShortTextNote], []) |
|
|
|
const fallbackNoteKinds = useMemo(() => [kinds.ShortTextNote], []) |
|
|
|
@ -92,14 +87,14 @@ const RelaysFeed = forwardRef< |
|
|
|
}, [kindsOverride, showKinds, fallbackNoteKinds]) |
|
|
|
}, [kindsOverride, showKinds, fallbackNoteKinds]) |
|
|
|
const defaultKindsKey = useMemo(() => JSON.stringify(defaultKinds), [defaultKinds]) |
|
|
|
const defaultKindsKey = useMemo(() => JSON.stringify(defaultKinds), [defaultKinds]) |
|
|
|
|
|
|
|
|
|
|
|
const canRenderFeed = relayUrls.length > 0 |
|
|
|
const canRenderFeed = stableRelayUrls.length > 0 |
|
|
|
|
|
|
|
|
|
|
|
// Hooks must run every render — never place useMemo after conditional returns.
|
|
|
|
// Hooks must run every render — never place useMemo after conditional returns.
|
|
|
|
const subRequests = useMemo(() => { |
|
|
|
const subRequests = useMemo(() => { |
|
|
|
if (!canRenderFeed) return [] |
|
|
|
if (!canRenderFeed) return [] |
|
|
|
return [ |
|
|
|
return [ |
|
|
|
{ |
|
|
|
{ |
|
|
|
urls: ensureHomeFeedTrendingRelay(stableRelayUrls), |
|
|
|
urls: dedupeNormalizeRelayUrlsOrdered(ensureHomeFeedTrendingRelay(stableRelayUrls)), |
|
|
|
filter: { |
|
|
|
filter: { |
|
|
|
kinds: defaultKinds |
|
|
|
kinds: defaultKinds |
|
|
|
} |
|
|
|
} |
|
|
|
@ -112,7 +107,7 @@ const RelaysFeed = forwardRef< |
|
|
|
stableReplyRelayUrls.length > 0 ? stableReplyRelayUrls : stableRelayUrls |
|
|
|
stableReplyRelayUrls.length > 0 ? stableReplyRelayUrls : stableRelayUrls |
|
|
|
return [ |
|
|
|
return [ |
|
|
|
{ |
|
|
|
{ |
|
|
|
urls: ensureHomeFeedTrendingRelay(replyUrls), |
|
|
|
urls: dedupeNormalizeRelayUrlsOrdered(ensureHomeFeedTrendingRelay(replyUrls)), |
|
|
|
filter: { |
|
|
|
filter: { |
|
|
|
kinds: defaultKinds |
|
|
|
kinds: defaultKinds |
|
|
|
} |
|
|
|
} |
|
|
|
|