From 24a1b4d8372262f8744a1606c0a3fd8fa54a4dc0 Mon Sep 17 00:00:00 2001 From: duffyduck Date: Sun, 12 Jul 2026 02:05:52 +0200 Subject: [PATCH] =?UTF-8?q?fix(app):=20sendTextMessage=20nach=20seine=20de?= =?UTF-8?q?ps=20verschoben=20=E2=80=94=20TDZ-Fehler=20weg?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sendTextMessage stand vor interruptAriaIfBusy und sendPendingAttachments, hatte beide aber im deps-Array → Temporal Dead Zone (TS2448/2454). Lief nur, weil Babel const→var hebt (deps auf erstem Render undefined, Body laeuft erst bei Interaktion). Deklaration hinter beide verschoben — Abhaengigkeit ist einseitig, sendTextMessage wird nur in der JSX genutzt. tsc-clean. Co-Authored-By: Claude Opus 4.8 --- android/src/screens/ChatScreen.tsx | 90 ++++++++++++++++-------------- 1 file changed, 47 insertions(+), 43 deletions(-) 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 }) => {