Skip to content

Chat UI polish: cross-client sync, auto-reload, voice/speaker toggle, scroll preservation#469

Merged
shanselman merged 3 commits into
openclaw:masterfrom
christineyan4:misc-ui-chat
May 20, 2026
Merged

Chat UI polish: cross-client sync, auto-reload, voice/speaker toggle, scroll preservation#469
shanselman merged 3 commits into
openclaw:masterfrom
christineyan4:misc-ui-chat

Conversation

@christineyan4
Copy link
Copy Markdown
Contributor

Summary

Chat UI improvements across 13 files (+761/-68 lines), covering cross-client sync, auto-reload on connect, voice/TTS controls, and scroll preservation.

Changes

Core Chat Data Provider

  • Cross-client user message sync: Messages sent from other clients (e.g. gateway web UI) now appear in the timeline instead of being silently dropped. Local echo suppression prevents duplicates.
  • Auto-reload on connect: When sessions arrive after the WebSocket connects, history is eagerly loaded so the chat auto-populates without requiring navigation.
  • LoadHistoryAsync retry: Failed history loads retry up to 3 times with 2s delay while connected.
  • Reconnect state cleanup: Clears stale _locallyInitiatedThreads, _localSentTexts, and retry counters on reconnect.

ToolCallId Matching (ChatTimelineReducer)

  • Tool output/error events now match by \ToolCallId\ for correct parallel tool call status updates.
  • \FindToolEntryId\ no longer falls back to \ActiveToolCallId\ when a specific \ToolCallId\ is provided but not found, preventing corruption of unrelated tool entries.

Voice & Speaker Controls

  • Speaker toggle: Read-aloud button toggles to a stop button while TTS is playing.
  • STT model check: Shows a light-dismiss dialog directing users to Voice settings when the STT model isn't installed.
  • Recording pill guard: Blue recording pill only appears after recording actually starts (not during dialog prompts).
  • VoiceServiceInstance: Lazy creation via \EnsureStandaloneVoiceService()\ so voice works without node service.

Scroll & UI

  • Scroll position preservation: Static \s_sessionOffsets\ cache (bounded to 50 entries) survives page navigation. Deferred restore handles layout timing.
  • No disconnect flash: Keeps existing chat host visible when provider is temporarily null during reconnect.
  • Compact dropdowns: Tray popup uses narrower dropdown widths.
  • Scroll-to-bottom on send: Chat auto-scrolls when user sends a message.

Tests

  • 9 new tests (1098 total, all passing):
    • \SessionsUpdated_WhileConnected_EagerlyLoadsHistory\
    • \SessionsUpdated_WhileDisconnected_DoesNotLoadHistory\
    • \StatusChanged_Connected_ClearsHistoryInFlightAndReloads\
    • \LoadHistoryAsync_WhenConnected_RetriesAfterFailure\
    • \ToolOutput_WithToolCallId_MatchesCorrectToolEntry\
    • \ToolError_WithToolCallId_MatchesCorrectToolEntry\
    • \ToolOutput_WithoutToolCallId_FallsBackToActiveToolCallId\
    • \ToolStart_StoresToolCallIdOnEntry\
    • \ToolOutput_WithUnknownToolCallId_DoesNotCorruptActiveEntry\

Review Notes

  • Dual-model adversarial review (Opus + Codex) completed — all HIGH consensus findings fixed.
  • Verified auto-reload fix is NOT redundant with master.

Christine Yan and others added 3 commits May 18, 2026 16:36
- Add MaxWidth=900 to 11 pages for consistent layout
- Fix page centering (wrapper Grid pattern for ScrollViewer pages)
- Fix tray menu showing wrong gateway port (use registry)
- Remove non-functional scheduler toggle, replace with status badge
- Add cached-data-first loading for cron and skills pages
- Add loading spinner to skills page

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… scroll preservation

- ToolCallId matching for parallel tool calls (ChatTimelineReducer)
- Cross-client user message sync (echo suppression + remote user display)
- Auto-reload on connect (eager history loading when sessions arrive)
- LoadHistoryAsync retry on failure with bounded retry count (max 3)
- Speaker toggle (read-aloud to stop) in timeline
- STT model-not-installed dialog with light-dismiss
- Recording pill guard (onRecordingStarted callback)
- VoiceServiceInstance lazy creation fix
- Scroll position preservation across page navigation (static cache, bounded)
- Compact dropdown sizing for tray popup
- No-disconnect-flash fix (keep existing host when provider null)
- Clear stale state on reconnect (_locallyInitiatedThreads, _localSentTexts)
- FindToolEntryId: don't fall back to ActiveToolCallId when provided ID not found
- 9 new tests covering auto-reload, retry, ToolCallId matching

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Resolve chat UI polish conflicts with current master and keep local echo suppression from hiding future remote messages after failed sends.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@shanselman shanselman merged commit 488f265 into openclaw:master May 20, 2026
11 checks passed
kenehong added a commit to kenehong/openclaw-windows-node that referenced this pull request May 21, 2026
Resolved conflicts:
- OpenClawComposer.cs: kept both new params (OnAttachmentPasted + IsCompact)
- OpenClawChatRoot.cs: pass both OnAttachmentPasted and IsCompact through
- OpenClawChatDataProvider.cs: accepted upstream cross-client user echo
  handling (openclaw#469) — supersedes our earlier rollback of that work.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants