A React Native app for the ultimate thinking partner.

fix: prevent messages from disappearing and show streaming status immediately

Fixed two critical streaming bugs:

1. Messages disappearing after streaming:
- Keep streaming content visible until reload completes
- Added 300ms delay before reloading to let server finalize
- Clear streaming state AFTER messages are loaded, not before
- Don't clear messages if reload returns empty (race condition)

2. Streaming status not showing immediately:
- Remove 300ms fade-in animation for statusFadeAnim
- Set opacity to 1 immediately when streaming starts
- This makes '(co is thinking)' visible right away

Changes:
- statusFadeAnim.setValue(1) instead of animating from 0
- Reordered stream completion: wait → reload → clear state
- Added safety check in loadMessages to preserve messages on empty reload
- Reduced delay from 500ms to 300ms for better responsiveness

The streaming content now remains visible during the transition from
streaming to finalized messages, preventing the UI from going blank.

+13 -15
+13 -15
App.tsx
··· 342 342 } 343 343 } 344 344 setHasMoreBefore(loadedMessages.length === (before ? PAGE_SIZE : INITIAL_LOAD_LIMIT)); 345 - } else { 345 + } else if (before) { 346 + // No more messages to load before 346 347 setHasMoreBefore(false); 347 348 } 349 + // If no messages and not loading before, keep existing messages (don't clear) 348 350 } catch (error: any) { 349 351 console.error('Failed to load messages:', error); 350 352 Alert.alert('Error', 'Failed to load messages: ' + (error.message || 'Unknown error')); ··· 599 601 // Clear streaming state 600 602 setCurrentStream({ reasoning: '', toolCalls: [], assistantMessage: '' }); 601 603 602 - // Fade in the status indicator 603 - statusFadeAnim.setValue(0); 604 - Animated.timing(statusFadeAnim, { 605 - toValue: 1, 606 - duration: 300, 607 - useNativeDriver: true, 608 - }).start(); 604 + // Make status indicator immediately visible 605 + statusFadeAnim.setValue(1); 609 606 610 607 // Animate spacer growing to push user message up (push previous content out of view) 611 608 const targetHeight = Math.max(containerHeight * 0.9, 450); ··· 694 691 }, 695 692 async (response) => { 696 693 console.log('Stream complete'); 697 - console.log('[STREAM COMPLETE] Clearing state and reloading messages'); 694 + console.log('[STREAM COMPLETE] Reloading messages from server'); 698 695 699 - // Clear streaming state 700 - setIsStreaming(false); 701 - setCurrentStream({ reasoning: '', toolCalls: [], assistantMessage: '' }); 702 - 703 - // Reload messages from server to get finalized versions 704 - loadMessages(); 696 + // Wait for server to finalize messages, then reload and clear streaming state 697 + setTimeout(async () => { 698 + await loadMessages(); 699 + // Clear streaming state after messages are loaded 700 + setIsStreaming(false); 701 + setCurrentStream({ reasoning: '', toolCalls: [], assistantMessage: '' }); 702 + }, 300); 705 703 }, 706 704 (error) => { 707 705 console.error('=== APP STREAMING ERROR CALLBACK ===');