import React, { useCallback, useState } from "react"; import { Image, Pressable, Text, View } from "react-native"; import { Message } from "../../types"; import { playAudio, stopPlayback } from "../../services/audio"; interface MessageBubbleProps { message: Message; } function formatDuration(ms?: number): string { if (!ms) return "0:00"; const totalSeconds = Math.floor(ms / 1000); const minutes = Math.floor(totalSeconds / 60); const seconds = totalSeconds % 60; return `${minutes}:${seconds.toString().padStart(2, "0")}`; } function formatTime(timestamp: number): string { const d = new Date(timestamp); return d.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }); } export function MessageBubble({ message }: MessageBubbleProps) { const [isPlaying, setIsPlaying] = useState(false); const isUser = message.role === "user"; const isSystem = message.role === "system"; const handleVoicePress = useCallback(async () => { if (!message.audioUri) return; if (isPlaying) { await stopPlayback(); setIsPlaying(false); } else { setIsPlaying(true); await playAudio(message.audioUri, () => setIsPlaying(false)); } }, [isPlaying, message.audioUri]); if (isSystem) { return ( {message.content} ); } return ( {message.type === "image" && message.imageBase64 ? ( /* Image message */ {message.content ? ( {message.content} ) : null} ) : message.type === "voice" ? ( {/* Play/pause icon */} {isPlaying ? "⏸" : "▶"} {/* Waveform placeholder */} {Array.from({ length: 20 }).map((_, i) => ( ))} {/* Duration */} {formatDuration(message.duration)} ) : ( {message.content} )} {/* Timestamp + status */} {formatTime(message.timestamp)} {isUser && message.status === "error" && ( ! )} ); }