perf(keyboard): track KeyboardState per property with @Observable

- KeyboardState moves from ObservableObject/@Published to @Observable, so a view re-renders only for the properties it reads. Previously unpublished state and injected action hooks are @ObservationIgnored.
- KeyboardViewController replaces the $phase/$surface Combine sinks with Observations loops tied to the same cancellables.
- AIKeyboardView reads the 200 ms mic level and live ASR partials in small child views (AssistantWaveform, LiveTranscriptReader), so those ticks no longer rebuild the whole assistant surface.
- Tests observe changes with withObservationTracking instead of Combine publishers.
This commit is contained in:
2026-10-21 06:12:21 +02:00
parent 6e64f96dce
commit cfe14f67d4
17 changed files with 220 additions and 173 deletions
@@ -10,7 +10,7 @@ struct KeyboardSurfaceRoot: View {
@Environment(\.colorScheme) private var colorScheme
@Namespace private var keyboardTabSelectionNamespace
@ObservedObject var state: KeyboardState
var state: KeyboardState
@ObservedObject var typing: TypingSessionController
var onInsert: (String) -> Void
+1 -1
View File
@@ -38,7 +38,7 @@ enum TypingLayoutMetrics {
struct TypingRootView: View {
@Environment(\.colorScheme) private var colorScheme
@ObservedObject var state: KeyboardState
var state: KeyboardState
@ObservedObject var typing: TypingSessionController
var onInsert: (String) -> Void