From 2fed4e3e852127e01d468b93c7fe6ea95bf3f074 Mon Sep 17 00:00:00 2001 From: Jure <44338+hoornet@users.noreply.github.com> Date: Sun, 29 Mar 2026 20:06:00 +0200 Subject: [PATCH] Add retry-on-empty for followers, articles, and hashtag feeds Same pattern as profile notes and notifications: if the first relay fetch returns empty, wait 3s and retry once. Prevents false "No X found" messages when relays are slow to connect. --- src/components/feed/HashtagFeed.tsx | 17 ++++++++++++++--- src/components/follows/FollowsView.tsx | 8 +++++++- src/components/profile/ProfileView.tsx | 15 ++++++++++++++- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/components/feed/HashtagFeed.tsx b/src/components/feed/HashtagFeed.tsx index 2eeb6bd..f1138be 100644 --- a/src/components/feed/HashtagFeed.tsx +++ b/src/components/feed/HashtagFeed.tsx @@ -13,11 +13,22 @@ export function HashtagFeed() { useEffect(() => { if (!tag) return; + let cancelled = false; setLoading(true); setNotes([]); - fetchHashtagFeed(tag) - .then(setNotes) - .finally(() => setLoading(false)); + (async () => { + let result = await fetchHashtagFeed(tag).catch(() => [] as NDKEvent[]); + if (result.length === 0 && !cancelled) { + await new Promise((r) => setTimeout(r, 3000)); + if (cancelled) return; + result = await fetchHashtagFeed(tag).catch(() => [] as NDKEvent[]); + } + if (!cancelled) { + setNotes(result); + setLoading(false); + } + })(); + return () => { cancelled = true; }; }, [tag]); return ( diff --git a/src/components/follows/FollowsView.tsx b/src/components/follows/FollowsView.tsx index 0325f2a..739b627 100644 --- a/src/components/follows/FollowsView.tsx +++ b/src/components/follows/FollowsView.tsx @@ -103,7 +103,13 @@ export function FollowsView() { (async () => { try { await ensureConnected(); - const result = await fetchFollowers(pubkey); + let result = await fetchFollowers(pubkey); + // Retry once if empty — relays may not be ready yet + if (result.length === 0) { + await new Promise((r) => setTimeout(r, 3000)); + if (cancelled) return; + result = await fetchFollowers(pubkey); + } if (!cancelled) { setFollowers(result); setFollowersFetched(true); diff --git a/src/components/profile/ProfileView.tsx b/src/components/profile/ProfileView.tsx index 97581e2..e0c6548 100644 --- a/src/components/profile/ProfileView.tsx +++ b/src/components/profile/ProfileView.tsx @@ -116,8 +116,21 @@ export function ProfileView() { useEffect(() => { if (profileTab !== "articles" || articles.length > 0) return; + let cancelled = false; setArticlesLoading(true); - fetchAuthorArticles(pubkey).then(setArticles).catch(() => setArticles([])).finally(() => setArticlesLoading(false)); + (async () => { + let result = await fetchAuthorArticles(pubkey).catch(() => [] as typeof articles); + if (result.length === 0 && !cancelled) { + await new Promise((r) => setTimeout(r, 3000)); + if (cancelled) return; + result = await fetchAuthorArticles(pubkey).catch(() => [] as typeof articles); + } + if (!cancelled) { + setArticles(result); + setArticlesLoading(false); + } + })(); + return () => { cancelled = true; }; }, [profileTab, pubkey]); return (