// apps/mobile/app/(tabs)/talk.tsx // AI Chat tab — text+voice chat // Design ref: docs/v3/designs/talk.html import { useState, useRef } from 'react' import { View, ScrollView, TextInput, StyleSheet, Pressable, KeyboardAvoidingView, Platform } from 'react-native' import { useSafeAreaInsets } from 'react-native-safe-area-context' import { PhosphorText, Led, Header, AppStatusBar, d3roNativePalette, d3roNativeFonts } from '@d3ro/ui-native' import { useI18n } from '@d3ro/i18n' interface ChatMessage { id: string role: 'user' | 'assistant' content: string } export default function TalkScreen(): React.ReactElement { const insets = useSafeAreaInsets() const { t } = useI18n() const scrollRef = useRef(null) const [messages, setMessages] = useState([ { id: '1', role: 'assistant', content: t('mobile.talk.greeting') } ]) const [input, setInput] = useState('') function handleSend(): void { if (!input.trim()) return const userMsg: ChatMessage = { id: String(Date.now()), role: 'user', content: input.trim() } setMessages((prev) => [...prev, userMsg]) setInput('') // Phase M-5: actual AI response setTimeout(() => { scrollRef.current?.scrollToEnd({ animated: true }) }, 100) } return (
{t('mobile.talk.live')} } /> {/* Chat Messages */} {/* Date Badge */} {new Date().toLocaleDateString(undefined, { month: 'short', day: 'numeric' }).toUpperCase()} {messages.map((msg) => ( {msg.content} {msg.role === 'user' ? t('mobile.talk.you') : t('mobile.talk.claude')} ))} {/* Input Area */} ) } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: d3roNativePalette.bg.app }, headerRight: { flexDirection: 'row', alignItems: 'center', gap: 8 }, chatArea: { flex: 1 }, chatContent: { padding: 20, paddingBottom: 20, gap: 16 }, dateBadge: { alignSelf: 'center', backgroundColor: d3roNativePalette.bg.card, borderWidth: 1, borderColor: d3roNativePalette.border.default, borderRadius: 999, paddingHorizontal: 12, paddingVertical: 4, marginBottom: 8 }, bubble: { maxWidth: '85%', padding: 16, borderRadius: 16, marginBottom: 20 }, aiBubble: { alignSelf: 'flex-start', backgroundColor: d3roNativePalette.bg.card, borderWidth: 1, borderColor: d3roNativePalette.border.default, borderTopLeftRadius: 4 }, userBubble: { alignSelf: 'flex-end', backgroundColor: d3roNativePalette.accent.dim, borderWidth: 1, borderColor: 'rgba(255, 92, 53, 0.3)', borderTopRightRadius: 4 }, bubbleText: { fontFamily: d3roNativeFonts.sans }, bubbleLabel: { position: 'absolute', bottom: -16, fontSize: 9, letterSpacing: 1 }, inputArea: { backgroundColor: 'rgba(25, 25, 27, 0.95)', borderTopWidth: 1, borderTopColor: d3roNativePalette.border.default, paddingHorizontal: 12, paddingTop: 12, paddingBottom: 8 }, inputRow: { flexDirection: 'row', alignItems: 'center', backgroundColor: d3roNativePalette.bg.inset, borderRadius: 12, borderWidth: 1, borderColor: d3roNativePalette.border.default, padding: 8 }, textInput: { flex: 1, color: d3roNativePalette.text.primary, fontSize: 14, paddingHorizontal: 8, fontFamily: d3roNativeFonts.sans }, sendBtn: { width: 32, height: 32, borderRadius: 16, backgroundColor: d3roNativePalette.accent.dim, borderWidth: 1, borderColor: 'rgba(255, 92, 53, 0.3)', justifyContent: 'center', alignItems: 'center' }, sendArrow: { width: 0, height: 0, borderLeftWidth: 5, borderRightWidth: 5, borderBottomWidth: 8, borderLeftColor: 'transparent', borderRightColor: 'transparent', borderBottomColor: d3roNativePalette.accent.main }, inputStatus: { paddingVertical: 4 } })