Scrapboard.org client

fix: timeline

+101 -28
+101 -28
src/lib/hooks/useTimeline.tsx
··· 23 } 24 25 export function useFetchTimeline() { 26 - const { agent } = useAuth(); 27 const { 28 timeline, 29 appendTimeline, ··· 38 const pendingFeedRequests = useRef<Set<string>>(new Set()); 39 // Use a ref to track the latest agent value 40 const agentRef = useRef(agent); 41 // Track processing state to avoid loops 42 const isProcessingRequests = useRef(false); 43 const processingRetries = useRef(0); 44 45 - // Update the ref when agent changes 46 useEffect(() => { 47 agentRef.current = agent; 48 - }, [agent]); 49 50 const fetchFeed = useCallback( 51 async (feed?: string | undefined) => { ··· 54 // Use the latest agent from the ref 55 const currentAgent = agentRef.current; 56 57 - // If not ready, queue the request for later 58 - if (!currentAgent) { 59 console.log( 60 - "Agent not available, queuing feed request for later:", 61 - feed || "main" 62 ); 63 pendingFeedRequests.current.add(feed || "main"); 64 return; ··· 132 appendTimeline, 133 setTimelineLoading, 134 setCustomFeedLoading, 135 ] 136 ); 137 ··· 143 return; 144 } 145 146 - // If agent isn't ready, try again later 147 - if (!agentRef.current) { 148 if (processingRetries.current < 5) { 149 processingRetries.current++; 150 console.log( 151 - `Agent not ready for processing, will retry (${processingRetries.current}/5)` 152 ); 153 setTimeout(() => processPendingRequests(), 1000); 154 } else { ··· 178 } finally { 179 isProcessingRequests.current = false; 180 } 181 - }, [fetchFeed]); 182 183 - // Effect to initialize feed once agent is available 184 useEffect(() => { 185 if (!agent) { 186 console.log("Waiting for agent to become available"); 187 return; 188 } 189 190 - console.log("Agent detected, setting ready state"); 191 setIsReady(true); 192 193 // Give a small delay for agent to fully initialize ··· 200 201 const loadMinimum = async () => { 202 setIsInitialized(true); 203 - console.log("Agent available, loading initial feed"); 204 205 - // Process any pending requests first 206 - await processPendingRequests(); 207 208 - // Then load the minimum required images 209 - let attempts = 0; 210 - while ( 211 - timeline.posts.flatMap( 212 - (p) => (p.post.embed as AppBskyEmbedImages.View)?.images || [] 213 - ).length < 30 && 214 - attempts < 3 215 - ) { 216 - await fetchFeed(); 217 - attempts++; 218 - if (!timeline.cursor) break; 219 } 220 }; 221 222 loadMinimum(); 223 }, 500); // Small delay to ensure agent is fully initialized 224 - }, [agent, isInitialized, processPendingRequests, fetchFeed, timeline.posts]); 225 226 return { fetchFeed, isReady }; 227 }
··· 23 } 24 25 export function useFetchTimeline() { 26 + const { agent, session } = useAuth(); 27 const { 28 timeline, 29 appendTimeline, ··· 38 const pendingFeedRequests = useRef<Set<string>>(new Set()); 39 // Use a ref to track the latest agent value 40 const agentRef = useRef(agent); 41 + const sessionRef = useRef(session); 42 // Track processing state to avoid loops 43 const isProcessingRequests = useRef(false); 44 const processingRetries = useRef(0); 45 + const authenticationRetries = useRef(0); 46 + const [forceRetry, setForceRetry] = useState(0); 47 48 + // Update the refs when agent or session changes 49 useEffect(() => { 50 agentRef.current = agent; 51 + sessionRef.current = session; 52 + 53 + // If session exists but agent doesn't have session, trigger a retry 54 + if (session && agent && !agent.did) { 55 + console.log( 56 + "Session exists but agent doesn't have it attached yet, scheduling retry" 57 + ); 58 + const retryTimeout = setTimeout(() => { 59 + setForceRetry((prev) => prev + 1); 60 + }, 500); 61 + return () => clearTimeout(retryTimeout); 62 + } 63 + }, [agent, session]); 64 + 65 + const isAuthenticated = useCallback(() => { 66 + // Check both ways: either agent has session or we have separate session 67 + return ( 68 + (agentRef.current && agentRef.current.did) || 69 + (agentRef.current && sessionRef.current) 70 + ); 71 + }, []); 72 73 const fetchFeed = useCallback( 74 async (feed?: string | undefined) => { ··· 77 // Use the latest agent from the ref 78 const currentAgent = agentRef.current; 79 80 + // Enhanced authentication check 81 + const authenticated = isAuthenticated(); 82 + 83 + // If not ready or not authenticated, queue the request for later 84 + if (!currentAgent || !authenticated) { 85 console.log( 86 + `Agent not available or not authenticated, queuing feed request for later: ${ 87 + feed || "main" 88 + }`, 89 + `Agent: ${!!currentAgent}, Auth: ${authenticated}` 90 ); 91 pendingFeedRequests.current.add(feed || "main"); 92 return; ··· 160 appendTimeline, 161 setTimelineLoading, 162 setCustomFeedLoading, 163 + isAuthenticated, 164 ] 165 ); 166 ··· 172 return; 173 } 174 175 + // Enhanced authentication check 176 + const authenticated = isAuthenticated(); 177 + 178 + // If agent isn't ready or not authenticated, try again later 179 + if (!agentRef.current || !authenticated) { 180 if (processingRetries.current < 5) { 181 processingRetries.current++; 182 console.log( 183 + `Agent not ready or not authenticated for processing, will retry (${processingRetries.current}/5)`, 184 + `Agent: ${!!agentRef.current}, Auth: ${authenticated}` 185 ); 186 setTimeout(() => processPendingRequests(), 1000); 187 } else { ··· 211 } finally { 212 isProcessingRequests.current = false; 213 } 214 + }, [fetchFeed, isAuthenticated]); 215 + 216 + // Try to load feeds even if there are authentication issues 217 + useEffect(() => { 218 + if (authenticationRetries.current >= 3) return; 219 + 220 + if (agent && session && !isReady) { 221 + console.log( 222 + "Attempting to force feed load despite authentication issues" 223 + ); 224 + authenticationRetries.current++; 225 + 226 + setTimeout(() => { 227 + setIsReady(true); 228 + processPendingRequests(); 229 + }, 1000 * authenticationRetries.current); 230 + } 231 + }, [agent, session, isReady, processPendingRequests, forceRetry]); 232 233 + // Effect to initialize feed once agent is available and authenticated 234 useEffect(() => { 235 if (!agent) { 236 console.log("Waiting for agent to become available"); 237 return; 238 } 239 240 + // Enhanced authentication check 241 + const authenticated = isAuthenticated(); 242 + 243 + if (!authenticated) { 244 + console.log( 245 + `Agent available but not authenticated, waiting for session. Session ref: ${!!sessionRef.current}` 246 + ); 247 + return; 248 + } 249 + 250 + console.log("Authenticated agent detected, setting ready state"); 251 setIsReady(true); 252 253 // Give a small delay for agent to fully initialize ··· 260 261 const loadMinimum = async () => { 262 setIsInitialized(true); 263 + console.log("Authenticated agent available, loading initial feed"); 264 265 + try { 266 + // Process any pending requests first 267 + await processPendingRequests(); 268 269 + // Then load the minimum required images 270 + let attempts = 0; 271 + while ( 272 + timeline.posts.flatMap( 273 + (p) => (p.post.embed as AppBskyEmbedImages.View)?.images || [] 274 + ).length < 30 && 275 + attempts < 3 276 + ) { 277 + await fetchFeed(); 278 + attempts++; 279 + if (!timeline.cursor) break; 280 + } 281 + } catch (err) { 282 + console.error("Error during initial feed loading:", err); 283 } 284 }; 285 286 loadMinimum(); 287 }, 500); // Small delay to ensure agent is fully initialized 288 + }, [ 289 + agent, 290 + agent?.did, 291 + isInitialized, 292 + processPendingRequests, 293 + fetchFeed, 294 + timeline.posts, 295 + isAuthenticated, 296 + forceRetry, 297 + ]); 298 299 return { fetchFeed, isReady }; 300 }