Scrapboard.org client
at main 79 lines 2.3 kB view raw
1import { useEffect, useState } from "react"; 2import { useAuth } from "@/lib/hooks/useAuth"; 3import { useFeedDefsStore } from "../stores/feedDefs"; 4import { AtUri } from "@atproto/api"; 5 6// How long the cache stays fresh (30 minutes by default) 7const CACHE_DURATION = 30 * 60 * 1000; 8 9export function useFeeds() { 10 const { agent } = useAuth(); 11 const store = useFeedDefsStore(); 12 const [isLoading, setLoading] = useState(store.feeds == null); 13 14 useEffect(() => { 15 if (agent == null) return; 16 17 // Use cached data immediately if available 18 if (store.feeds != null) { 19 setLoading(false); 20 } 21 22 // Check if we need to refresh the data 23 const lastFetchedAt = localStorage.getItem("feedsLastFetchedAt"); 24 const now = Date.now(); 25 const isStale = 26 !lastFetchedAt || now - parseInt(lastFetchedAt) > CACHE_DURATION; 27 28 // Skip fetching if data is fresh 29 if (!isStale && store.feeds != null) return; 30 31 const loadFeeds = async () => { 32 // Only show loading state if we have no cached data 33 const isBackgroundRefresh = store.feeds != null; 34 if (!isBackgroundRefresh) { 35 setLoading(true); 36 } 37 38 try { 39 const prefs = await agent.getPreferences(); 40 if (prefs?.savedFeeds == null) return; 41 42 for (const feed of prefs.savedFeeds) { 43 if (!feed.value.startsWith("at")) continue; 44 const urip = AtUri.make(feed.value); 45 46 if (!urip.host.startsWith("did:")) { 47 const res = await agent.resolveHandle({ handle: urip.host }); 48 urip.host = res.data.did; 49 } 50 51 if (feed.type == "feed") { 52 const feedDef = await agent.app.bsky.feed.getFeedGenerators({ 53 feeds: [urip.toString()], 54 }); 55 56 store.setFeedDef(feed.value, feedDef.data.feeds[0]); 57 } else if (feed.type == "list") { 58 const listDef = await agent.app.bsky.graph.getList({ 59 list: urip.toString(), 60 }); 61 62 store.setFeedDef(feed.value, { 63 displayName: listDef.data.list.name, 64 }); 65 } 66 } 67 68 // Update the last fetched timestamp 69 localStorage.setItem("feedsLastFetchedAt", now.toString()); 70 } finally { 71 setLoading(false); 72 } 73 }; 74 75 loadFeeds(); 76 }, [agent]); 77 78 return { isLoading }; 79}