diff --git a/android/src/screens/ChatScreen.tsx b/android/src/screens/ChatScreen.tsx index fd45fe8..4b23059 100644 --- a/android/src/screens/ChatScreen.tsx +++ b/android/src/screens/ChatScreen.tsx @@ -1995,49 +1995,6 @@ const ChatScreen: React.FC = () => { }, timeoutMs); }, []); - const sendTextMessage = useCallback(async () => { - const text = inputText.trim(); - - // Wenn pending Anhaenge vorhanden → Anhaenge + Text zusammen senden - if (pendingAttachments.length > 0) { - sendPendingAttachments(text); - return; - } - - if (!text) return; - - setInputText(''); - - // Barge-In: laufende ARIA-Aktivitaet abbrechen wenn welche da ist. - const wasInterrupted = interruptAriaIfBusy(); - const location = await getCurrentLocation(); - - const cmid = nextClientMsgId(); - const activePid = focusedProjectIdRef.current; - const userMsg: ChatMessage = { - id: nextId(), - sender: 'user', - text, - timestamp: Date.now(), - clientMsgId: cmid, - deliveryStatus: connectionStateRef.current === 'connected' ? 'sending' : 'queued', - sendAttempts: 1, - projectId: activePid, - }; - setMessages(prev => capMessages([...prev, userMsg])); - - console.log('[Chat] sende cmid=%s voice=%s speed=%s interrupted=%s project=%s', - cmid, localXttsVoiceRef.current || '(default)', ttsSpeedRef.current, wasInterrupted, activePid || '(main)'); - dispatchWithAck(cmid, 'chat', { - text, - voice: localXttsVoiceRef.current, - speed: ttsSpeedRef.current, - interrupted: wasInterrupted, - projectId: activePid, - ...(location && { location }), - }); - }, [inputText, getCurrentLocation, pendingAttachments, sendPendingAttachments, interruptAriaIfBusy, dispatchWithAck]); - // Anfrage abbrechen — nur den fokussierten Kontext (kontext-scoped Cancel). const cancelRequest = useCallback(() => { const pid = focusedProjectIdRef.current || ''; @@ -2244,6 +2201,53 @@ const ChatScreen: React.FC = () => { setInputText(''); }, [pendingAttachments, getCurrentLocation, dispatchWithAck]); + // Reine Text-Nachricht senden. Steht bewusst NACH interruptAriaIfBusy und + // sendPendingAttachments — beide stehen in seinem deps-Array, und wenn es + // davor deklariert waere, laendeten sie dort in der Temporal Dead Zone + // (tsc TS2448/2454; lief nur zufaellig, weil Babel const→var hebt). + const sendTextMessage = useCallback(async () => { + const text = inputText.trim(); + + // Wenn pending Anhaenge vorhanden → Anhaenge + Text zusammen senden + if (pendingAttachments.length > 0) { + sendPendingAttachments(text); + return; + } + + if (!text) return; + + setInputText(''); + + // Barge-In: laufende ARIA-Aktivitaet abbrechen wenn welche da ist. + const wasInterrupted = interruptAriaIfBusy(); + const location = await getCurrentLocation(); + + const cmid = nextClientMsgId(); + const activePid = focusedProjectIdRef.current; + const userMsg: ChatMessage = { + id: nextId(), + sender: 'user', + text, + timestamp: Date.now(), + clientMsgId: cmid, + deliveryStatus: connectionStateRef.current === 'connected' ? 'sending' : 'queued', + sendAttempts: 1, + projectId: activePid, + }; + setMessages(prev => capMessages([...prev, userMsg])); + + console.log('[Chat] sende cmid=%s voice=%s speed=%s interrupted=%s project=%s', + cmid, localXttsVoiceRef.current || '(default)', ttsSpeedRef.current, wasInterrupted, activePid || '(main)'); + dispatchWithAck(cmid, 'chat', { + text, + voice: localXttsVoiceRef.current, + speed: ttsSpeedRef.current, + interrupted: wasInterrupted, + projectId: activePid, + ...(location && { location }), + }); + }, [inputText, getCurrentLocation, pendingAttachments, sendPendingAttachments, interruptAriaIfBusy, dispatchWithAck]); + // --- Rendering --- const renderMessage = ({ item }: { item: ChatMessage }) => {