Skip to content

fix(tui): coalesce rapid selection copies - #44430

Closed
opencode-agent[bot] wants to merge 1 commit into
v2from
windows-copy-freeze
Closed

opencode-agent[bot] wants to merge 1 commit into
v2from
windows-copy-freeze

Conversation

@opencode-agent

Copy link
Copy Markdown
Contributor

Summary

  • keep at most one selection-triggered clipboard write active
  • coalesce rapid selections to the newest pending text
  • avoid filling OpenTUI's serialized native clipboard queue on Windows

Testing

  • bun test test/selection.test.ts test/clipboard.test.ts
  • bun typecheck

Validation needed

Filip will validate the original rapid mouse-selection freeze on Windows/PowerShell.

Requested by: @neriousy (Filip via Slack)

@Enough1122

Copy link
Copy Markdown

AI code review — automated review for reference, author can ignore or act on any point.

Clean fix for the queue-starvation problem — the single-flight loop with last-write-wins coalescing is the right shape, and it's covered by a focused concurrency test. Two small things:

  1. Highlight now clears even if the queued write fails — packages/tui/src/app.tsx:579-581 calls copySelection(text) (fire-and-forget) and then renderer.clearSelection() synchronously, whereas the old code awaited the write before clearing. A failed clipboard write therefore leaves the user with no highlight, no retry affordance, and only an async toast. Consider clearing inside the drain's completion path (or keeping the old ordering when there's no contention).

  2. Superseded-write errors are silently dropped — in packages/tui/src/util/selection.ts:38 the continue skips both the success and error toast for any write that got overtaken. That's presumably intended ("only the newest matters"), but a persistent environment failure (e.g. clipboard service down) will surface exactly one error per burst instead of per attempt; a brief comment stating the intent would prevent someone "fixing" it later. Also consider guarding the toast.* calls so an unexpected throw can't escape drain() as an unhandled rejection from the void drain() at line 51.

Minor: the new test exercises only the success path (packages/tui/test/selection.test.ts) — a case where the final write rejects (asserting toast.error fires once) would pin down branch at line 39.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants