perf(#281): fix PERF-13/14/15/16 — main-thread settings, 100Hz polling, leaked scope, WS disconnect (#359)

* perf(#281): fix PERF-13/14/15/16 — main-thread settings load, 100Hz polling, leaked scope, WS disconnect

* fix(#281): fix SettingsViewModelTest failures from async init dispatcher

---------

Co-authored-by: M57 <hy4ri@users.noreply.github.com>
This commit is contained in:
M57andM57 authored and GitHub committed 2026-06-25 20:39:52 +03:00
1 parent 9297413b2a
commit 3399880621
5 files changed
+81 -46

No files matched your search

@@ -797,10 +797,11 @@ private fun StreamingBubbleWithTypingEffect(
// Timer that ticks at the configured delay, incrementing the visible word
// count each tick. Stops ticking when streaming ends, then shows all words.
// Optimized: split is only called when waiting for new content, not per tick.
LaunchedEffect(Unit) {
var wordCount = 0
while (true) {
val words = currentContent.value.split(" ")
if (visibleWordCount < words.size) {
if (visibleWordCount < wordCount) {
delay(currentDelayMs.value.toLong())
visibleWordCount++
} else {
@@ -808,7 +809,11 @@ private fun StreamingBubbleWithTypingEffect(
onAnimationComplete()
break
}
delay(10)
// Only split when we need to check for new content arriving
val words = currentContent.value.split(" ")
wordCount = words.size
if (visibleWordCount < wordCount) continue
delay(100) // was 10 — reduced from 100Hz to 10Hz
}
}
visibleWordCount = Int.MAX_VALUE
@@ -1020,7 +1020,8 @@ class ChatViewModel(
override fun onCleared() {
super.onCleared()
pendingCleanupJob?.cancel()
wsClient.disconnect()
// PERF-16: Don't disconnect the global HermesWsClient singleton when
// leaving the Chat screen — it's used by background notification reply.
}
companion object {