| .. | .. |
|---|
| 18 | 18 | // Track the last message's content so transcript reflections trigger a scroll |
|---|
| 19 | 19 | const lastContent = messages.length > 0 ? messages[messages.length - 1].content : ""; |
|---|
| 20 | 20 | |
|---|
| 21 | + // Flag: when true, every content size change triggers a scroll to bottom. |
|---|
| 22 | + // Used for bulk loads (restart, session switch) where FlatList renders lazily. |
|---|
| 23 | + const bulkScrollRef = useRef(false); |
|---|
| 24 | + |
|---|
| 21 | 25 | useEffect(() => { |
|---|
| 22 | 26 | if (messages.length > 0) { |
|---|
| 23 | 27 | const delta = Math.abs(messages.length - prevLengthRef.current); |
|---|
| 24 | 28 | if (delta > 1) { |
|---|
| 25 | | - // Bulk load (restart, session switch) — FlatList renders lazily, |
|---|
| 26 | | - // so fire multiple scroll attempts to catch late renders. |
|---|
| 27 | | - for (const delay of [100, 300, 700]) { |
|---|
| 28 | | - setTimeout(() => { |
|---|
| 29 | | - listRef.current?.scrollToEnd({ animated: false }); |
|---|
| 30 | | - }, delay); |
|---|
| 31 | | - } |
|---|
| 29 | + // Bulk load — let onContentSizeChange handle scrolling |
|---|
| 30 | + bulkScrollRef.current = true; |
|---|
| 31 | + setTimeout(() => { bulkScrollRef.current = false; }, 3000); |
|---|
| 32 | 32 | } else { |
|---|
| 33 | 33 | // Single new message — smooth scroll |
|---|
| 34 | 34 | setTimeout(() => { |
|---|
| .. | .. |
|---|
| 38 | 38 | } |
|---|
| 39 | 39 | prevLengthRef.current = messages.length; |
|---|
| 40 | 40 | }, [messages.length, isTyping, lastContent]); |
|---|
| 41 | + |
|---|
| 42 | + const handleContentSizeChange = useCallback(() => { |
|---|
| 43 | + if (bulkScrollRef.current) { |
|---|
| 44 | + listRef.current?.scrollToEnd({ animated: false }); |
|---|
| 45 | + } |
|---|
| 46 | + }, []); |
|---|
| 41 | 47 | |
|---|
| 42 | 48 | // Play from a voice message and auto-chain all consecutive assistant voice messages after it |
|---|
| 43 | 49 | const handlePlayVoice = useCallback(async (messageId: string) => { |
|---|
| .. | .. |
|---|
| 77 | 83 | onPlayVoice={handlePlayVoice} |
|---|
| 78 | 84 | /> |
|---|
| 79 | 85 | )} |
|---|
| 86 | + onContentSizeChange={handleContentSizeChange} |
|---|
| 80 | 87 | contentContainerStyle={{ paddingVertical: 12 }} |
|---|
| 81 | 88 | showsVerticalScrollIndicator={false} |
|---|
| 82 | 89 | ListFooterComponent={ |
|---|