fix: 3 Bugs — agent_activity haengt, Such-Scroll, STT-Bubble-Timing
Bug 1: "ARIA denkt..." in der App bleibt stehen
_process_core_response setzte am Ende kein idle — die alten Aufrufe waren
in der OpenClaw-WS-Loop, in der Brain-HTTP-Variante fehlten sie. Plus
send_to_core schickte agent_activity direkt via _send_to_rvs ohne den
_last_activity_state-Cache zu pflegen → _emit_activity("idle") wurde
spaeter dedupliziert.
Fix:
- _emit_activity statt direktem _send_to_rvs fuer thinking
- _emit_activity("idle") am Ende von _process_core_response
- _last_chat_final_at bewusst NICHT setzen — die 3s-Cooldown war fuer
trailing OpenClaw-Events, wuerde bei Voice die naechste thinking-Welle
unterdruecken
Bug 2: App Chat-Suche scrollt nicht zur Stelle
scrollToIndex wurde zu fruh aufgerufen (Layout noch nicht fertig) und
viewPosition: 0.4 in inverted-FlatList war ungenau.
Fix:
- requestAnimationFrame um den Scroll-Aufruf
- viewPosition: 0.5 (mittig)
- onScrollToIndexFailed: erst grob scrollen via averageItemLength,
dann nach 250ms praeziser nachfassen
Bug 3: Voice-Bubble bekommt STT-Text erst mit ARIA-Antwort
_process_app_audio rief erst send_to_core (blockt synchron auf Brain,
kann 300s dauern), DANN STT-Broadcast. App sah den eigenen Text erst
wenn ARIA fertig war.
Fix: Reihenfolge getauscht — STT-Broadcast zuerst, dann send_to_core.
Voice-Bubble bekommt jetzt den erkannten Text sofort.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -920,17 +920,25 @@ const ChatScreen: React.FC = () => {
|
||||
setSearchIndex(0);
|
||||
}, [searchQuery]);
|
||||
|
||||
// Bei Index-Wechsel zu der entsprechenden Bubble scrollen
|
||||
// Bei Index-Wechsel zu der entsprechenden Bubble scrollen.
|
||||
// FlatList ist `inverted` → viewPosition 0.5 (mitte) ist beim inverted-Render
|
||||
// tatsaechlich die Mitte des sichtbaren Bereichs. Wir verzoegern minimal
|
||||
// damit Layout sicher fertig ist.
|
||||
useEffect(() => {
|
||||
if (!searchMatchIds.length) return;
|
||||
const id = searchMatchIds[searchIndex];
|
||||
if (!id) return;
|
||||
// invertedMessages → index in der angezeigten Liste finden
|
||||
const idx = invertedMessages.findIndex(m => m.id === id);
|
||||
if (idx < 0 || !flatListRef.current) return;
|
||||
try {
|
||||
flatListRef.current.scrollToIndex({ index: idx, animated: true, viewPosition: 0.4 });
|
||||
} catch {}
|
||||
const tryScroll = () => {
|
||||
try {
|
||||
flatListRef.current?.scrollToIndex({ index: idx, animated: true, viewPosition: 0.5 });
|
||||
} catch {
|
||||
// wird von onScrollToIndexFailed nochmal versucht
|
||||
}
|
||||
};
|
||||
// requestAnimationFrame statt setTimeout 0 — wartet auf naechsten Layout-Frame
|
||||
requestAnimationFrame(tryScroll);
|
||||
}, [searchIndex, searchMatchIds, invertedMessages]);
|
||||
|
||||
const activeSearchId = searchMatchIds[searchIndex] || '';
|
||||
@@ -1440,10 +1448,14 @@ const ChatScreen: React.FC = () => {
|
||||
inverted
|
||||
data={invertedMessages}
|
||||
onScrollToIndexFailed={(info) => {
|
||||
// Bei zu schnellem Aufruf vor Layout: einmal nachfassen
|
||||
// FlatList kennt das Item-Layout noch nicht. Zuerst grob in die
|
||||
// Naehe scrollen (Average-Item-Hoehe-Schaetzung), dann nach 250ms
|
||||
// praezise nochmal versuchen.
|
||||
const offset = info.averageItemLength * info.index;
|
||||
try { flatListRef.current?.scrollToOffset({ offset, animated: false }); } catch {}
|
||||
setTimeout(() => {
|
||||
try { flatListRef.current?.scrollToIndex({ index: info.index, animated: true, viewPosition: 0.4 }); } catch {}
|
||||
}, 200);
|
||||
try { flatListRef.current?.scrollToIndex({ index: info.index, animated: true, viewPosition: 0.5 }); } catch {}
|
||||
}, 250);
|
||||
}}
|
||||
keyExtractor={item => item.id}
|
||||
renderItem={renderMessage}
|
||||
|
||||
Reference in New Issue
Block a user