Skip to content

feat(desktop): copy/edit overlay, msg history nav, IME guard, card collapse#1645

Merged
esengine merged 2 commits into
esengine:mainfrom
CVEngineer66:feat/desktop-ux-improvements
May 24, 2026
Merged

feat(desktop): copy/edit overlay, msg history nav, IME guard, card collapse#1645
esengine merged 2 commits into
esengine:mainfrom
CVEngineer66:feat/desktop-ux-improvements

Conversation

@CVEngineer66

Copy link
Copy Markdown
Contributor

Summary

Desktop UX improvements addressing daily pain points.

Motivation

Several issues noticed during daily desktop usage:

  • No way to edit a sent message — had to retype everything or use /retry (a CLI command, not suitable for the desktop UI)
  • Copy button sat below the message, wasting vertical space with an empty line
  • Code blocks had no one-click copy button — had to manually select code then press Cmd+C
  • No message history navigation — could not recover a previously sent message with arrow keys
  • Chinese/Japanese IME users: pressing Enter to confirm a composition candidate accidentally sent the message
  • Reasoning cards and completed shell execution cards were expanded by default, taking up unnecessary space
  • Homebrew Node 26 on macOS (arm64, ~68 KB) was rejected by the hard-coded 100 KB threshold in find_real_node(), causing a false node not found error

Changes

File Change
desktop/src-tauri/src/rpc.rs Lower Node binary size threshold from 100 KB to 50 KB on macOS/Linux
desktop/src/App.tsx Wire onEdit callback to UserMsg
desktop/src/Markdown.tsx Fix pre renderer text extraction for react-markdown v9; add copy button to CodeBlock
desktop/src/styles.css Overlay copy/edit buttons (bottom-right, hover); code block copy button styles
desktop/src/ui/cards.tsx ReasoningCard defaultOpen=false; ShellCard defaultOpen=state !== done
desktop/src/ui/composer.tsx Message history (up/down arrow, 100-entry cap); IME guard (composingRef + timestamp)
desktop/src/ui/thread.tsx Add pencil edit button to UserMsg
desktop/src/i18n/en.ts, zh-CN.ts Add editMessage locale keys

Verification

  • npm run verify passes (build, lint, typecheck, 3582 tests)
  • Manually tested in Tauri desktop app

@esengine esengine left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the comprehensive pass — the Markdown v9 fix, the IME composition guard, and the Node threshold are all solid catches.

One blocker before this can land:

Arrow-key history nav clobbers cursor movement in multi-line drafts. In composer.tsx the handler intercepts every ArrowUp/ArrowDown whenever no popup is open, so a user writing a long message who hits ↑ to move the cursor up a line will instead see their entire draft replaced by a prior message. That's a real regression on the most common editing path.

The typical fix is to only navigate history when the action is unambiguous:

  • textarea is empty, OR
  • cursor is on the first line (for ↑) / last line (for ↓), OR
  • modifier-gated (Cmd+↑ / Ctrl+↑)

A few other things to address before merge:

  • CI hasn't run yet — the action_required status is GitHub's first-contributor gate. Once the cursor regression is fixed I'll approve the workflow run.
  • Tests are missing for every new behavior (history nav, IME guard, flattenChildText, edit-button wiring). 147 lines of behavior change with zero coverage is a real gap — small vitest cases on the pure helpers would have caught the cursor regression above.
  • ReasoningCard defaultOpen={false} changes streaming visibility (was open while streaming, now collapsed). Confirm this is intentional — some users rely on seeing the reasoning land live.

The bundling (7 unrelated fixes in one PR) is fine for this round, but please split future ones — Rust threshold, Markdown fix, and the UX changes each belong in their own PR.

Once the cursor issue is fixed, push and I'll approve CI.

@esengine

Copy link
Copy Markdown
Owner

Nice first PR — solid bundle of real fixes (the arm64 Homebrew Node detection and the IME guard in particular). Merging.

@esengine esengine merged commit e170db3 into esengine:main May 24, 2026
4 checks passed
@CVEngineer66 CVEngineer66 deleted the feat/desktop-ux-improvements branch May 24, 2026 04:34
esengine added a commit that referenced this pull request May 24, 2026
#1651)

* chore(desktop): tidy follow-ups from #1645

Three small cleanups landed alongside the desktop UX bundle:

- composer: extract `recordSendAndReset` so the history-push + browse-
  index reset logic is one helper, not duplicated between the Enter key
  path and the send-button onClick.
- composer: drop the duplicate IME-quirk comment at the use site; the
  ref declaration block at the top of the component already documents
  the macOS Chinese IME ordering quirk.
- App: hoist the inline `onEdit` arrow into a useCallback so UserMsg's
  memo isn't busted by a fresh function identity on every render of the
  message list.

* test(server-dashboard): isolate from real \$HOME/.reasonix

The v0.13 panels suite uses mkdtempSync for cfgPath and usagePath but
the handlers it exercises (/api/health, listSessions) still call
homedir() under the hood. On a dev machine with thousands of session
jsonl files in ~/.reasonix/sessions the readdir + per-file statSync
walk blows past the 5 s default test timeout, even though the same
test runs in ms on a clean CI box.

Redirect HOME and USERPROFILE inside the suite's beforeEach so the
walks land in the suite's already-empty temp dir, and restore the
originals in afterEach. No production-code change — the handlers'
homedir() coupling is a separate cleanup.

Whole file now runs in 1.7 s.

---------

Co-authored-by: reasonix <reasonix@deepseek.com>
esengine pushed a commit that referenced this pull request May 24, 2026
…moved, persisted usage stats, plan dispatch gate

Headline themes:
- Desktop: bundle the CLI-hosted React dashboard, retire Tauri+Preact duplicate (#1418)
- Config: drop preset abstraction; flash/pro are direct model selections (#1657, #1630)
- Stats: persist cumulative usage to session meta + auto-restore on startup (#1667, #1680, #1643, #1628)
- Plans: editMode="plan" enforced at the ToolRegistry dispatch gate (#1681); step advance fix (#1629)
- Context: fold once at turn start, drop pre-flight + byte-ceiling (#1642, #1646); collapsible compacted card (#1649)
- Subagents: per-skill flash/pro override + Settings UI (#1632)
- Desktop polish: sidebar drag-resize (#1688), responsive collapse (#1585), copy/edit overlay + msg-history nav (#1645), Esc closes modal not turn (#1685), QQ tab isolation (#1672), DiffCard for edits (#1662), theme-aware highlighting (#1655), system events toggle (#1654/#1650), macOS TCC inheritance (#1614), dashboard.enabled (#1612)
- Dashboard polish: persistent session URL (#1586, #1589, #1599), theme-aware highlighting (#1664), IME confirm-enter guard (#1689), code-fence lang fix (#1677), vendor chunk split (#1587), markdown table h-scroll (#1562)
- TUI: Alt+S input stash/recall; static history isolated from input rerenders (#1635); legacy mouse drop (#1637, #1648); multi-edit gated in review (#1647)
- Diff: SplitDiff column border holds under CJK (#1686)
- MCP: workspace roots passed to servers (#1625); codeCommand honors mcpServers (#1603)
- Config plumbing: (baseUrl, apiKey) resolved as a tuple (#1658); stale model id self-heal (#1663)

See CHANGELOG for the full list.
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