import React, { useCallback, useEffect, useRef } from "react"; import { FlatList, View } from "react-native"; import { Message } from "../../types"; import { MessageBubble } from "./MessageBubble"; import { TypingIndicator } from "./TypingIndicator"; import { stopPlayback, playAudio } from "../../services/audio"; interface MessageListProps { messages: Message[]; isTyping?: boolean; onDeleteMessage?: (id: string) => void; } export function MessageList({ messages, isTyping, onDeleteMessage }: MessageListProps) { const listRef = useRef>(null); const prevLengthRef = useRef(0); // Track the last message's content so transcript reflections trigger a scroll const lastContent = messages.length > 0 ? messages[messages.length - 1].content : ""; useEffect(() => { if (messages.length > 0) { // If the message count changed by more than 1, it's a session switch or // initial load — snap to bottom instantly instead of visibly scrolling. const delta = Math.abs(messages.length - prevLengthRef.current); const animated = delta === 1; const delay = delta > 1 ? 200 : 50; setTimeout(() => { listRef.current?.scrollToEnd({ animated }); }, delay); } prevLengthRef.current = messages.length; }, [messages.length, isTyping, lastContent]); // Play from a voice message and auto-chain all consecutive assistant voice messages after it const handlePlayVoice = useCallback(async (messageId: string) => { const idx = messages.findIndex((m) => m.id === messageId); if (idx === -1) return; // Collect this message + all consecutive assistant voice messages after it const chain: Message[] = []; for (let i = idx; i < messages.length; i++) { const m = messages[i]; if (m.role === "assistant" && m.type === "voice" && m.audioUri) { chain.push(m); } else if (i > idx) { // Stop at the first non-voice or non-assistant message break; } } if (chain.length === 0) return; // Stop current playback, then queue all chunks await stopPlayback(); for (const m of chain) { playAudio(m.audioUri!); } }, [messages]); return ( item.id} renderItem={({ item }) => ( )} contentContainerStyle={{ paddingVertical: 12 }} showsVerticalScrollIndicator={false} ListFooterComponent={ <> {isTyping && } } /> ); }