fix(audio): Auto-Removal von Sprachnachrichten ohne STT-Result nach 30s
Bug: Wenn eine Aufnahme leer war, nur Wake-Word-Echo enthielt oder STT sonstwie nichts erkannt hat, sendet die Bridge KEIN stt-Event zurueck — die Placeholder-Bubble "Spracheingabe wird verarbeitet" blieb fuer immer im Chat. Folge-Aufnahmen matchten dann via Substring-Fallback die ALTE Placeholder, der echte Text landete in der falschen Bubble. Fix: nach jedem audio-send einen 30s-Timer starten. Wenn nach Ablauf die Bubble (per audioRequestId identifiziert) immer noch "verarbeitet" ist, wird sie entfernt + Toast "nicht erkannt" zeigt das dem User. So bleibt der State sauber + audioRequestId-Match auf zukuenftige Aufnahmen findet die richtige Bubble (statt die hinterbliebene Placeholder). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -535,6 +535,7 @@ const ChatScreen: React.FC = () => {
|
|||||||
audioRequestId,
|
audioRequestId,
|
||||||
...(location && { location }),
|
...(location && { location }),
|
||||||
});
|
});
|
||||||
|
scheduleStaleAudioCleanup(audioRequestId);
|
||||||
// resume() wird durch onPlaybackFinished nach ARIAs Antwort getriggert.
|
// resume() wird durch onPlaybackFinished nach ARIAs Antwort getriggert.
|
||||||
} else {
|
} else {
|
||||||
// Kein Speech im Window → Konversation beenden (Ohr geht aus oder
|
// Kein Speech im Window → Konversation beenden (Ohr geht aus oder
|
||||||
@@ -656,6 +657,25 @@ const ChatScreen: React.FC = () => {
|
|||||||
|
|
||||||
// --- Nachricht senden ---
|
// --- Nachricht senden ---
|
||||||
|
|
||||||
|
// Aufraeumen von "verarbeitet"-Placeholder die nie ein STT-Result bekommen
|
||||||
|
// haben (leere Aufnahme, Wake-Word-Echo, STT-Fehler etc). Nach 30s werden
|
||||||
|
// sie automatisch entfernt damit nicht-erkannte Aufnahmen nicht den State
|
||||||
|
// verstopfen + naechste echte Aufnahmen die richtige Bubble ersetzen koennen.
|
||||||
|
const scheduleStaleAudioCleanup = useCallback((audioRequestId: string) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
setMessages(prev => {
|
||||||
|
const idx = prev.findIndex(m =>
|
||||||
|
m.audioRequestId === audioRequestId &&
|
||||||
|
m.text.includes('Spracheingabe wird verarbeitet')
|
||||||
|
);
|
||||||
|
if (idx < 0) return prev;
|
||||||
|
console.log('[Chat] Sprachnachricht ohne STT-Result entfernt: %s', audioRequestId);
|
||||||
|
ToastAndroid.show('Sprachnachricht nicht erkannt — entfernt', ToastAndroid.SHORT);
|
||||||
|
return prev.filter((_, i) => i !== idx);
|
||||||
|
});
|
||||||
|
}, 30000);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const sendTextMessage = useCallback(async () => {
|
const sendTextMessage = useCallback(async () => {
|
||||||
const text = inputText.trim();
|
const text = inputText.trim();
|
||||||
|
|
||||||
@@ -743,7 +763,8 @@ const ChatScreen: React.FC = () => {
|
|||||||
audioRequestId,
|
audioRequestId,
|
||||||
...(location && { location }),
|
...(location && { location }),
|
||||||
});
|
});
|
||||||
}, [getCurrentLocation, interruptAriaIfBusy]);
|
scheduleStaleAudioCleanup(audioRequestId);
|
||||||
|
}, [getCurrentLocation, interruptAriaIfBusy, scheduleStaleAudioCleanup]);
|
||||||
|
|
||||||
// Datei auswaehlen → zur Pending-Liste hinzufuegen
|
// Datei auswaehlen → zur Pending-Liste hinzufuegen
|
||||||
const handleFileSelected = useCallback(async (file: FileData) => {
|
const handleFileSelected = useCallback(async (file: FileData) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user