fix: Copy + Paste Across Tabs - #2705
Open
camielvs wants to merge 1 commit into
Open
Conversation
🎩 PreviewA preview build has been created at: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Copying nodes in one tab and pasting them in another silently did nothing. Cross-instance transfer was already the intent — copy wrote a
tangle-pipeline-nodesJSON envelope to the system clipboard and paste read it back — but the read went throughnavigator.clipboard.readText(), which is gated behind theclipboard-readpermission in Chrome and is not freely available to pages in Firefox. Every failure was swallowed by a barecatch {}, and paste then fell back to the in-memory store, which is empty in a fresh tab. Result: nothing pasted, no feedback.Two changes:
1. Paste reads from the native
pasteevent.readEnvelopeFromPasteEventpulls the envelope out ofClipboardEvent.clipboardData, which needs no permission and works in every browser without a prompt.useClipboardShortcutsnow listens forpasteonwindow, ignores editable targets so text still pastes into inputs and Monaco normally, and pastes at the canvas centre as before.The Cmd+V keydown shortcut stays registered so it remains discoverable in the shortcut list, but its action returns
false— the mechanismShortcutDefinitionalready documents for "let the native event propagate" — so the listener skipspreventDefaultand the browser goes on to firepaste. Previously thatpreventDefaultsuppressed the paste event entirely, which is what madeclipboardDataunreachable in the first place.ClipboardStore.pastetreats a paste-event read as authoritative and skips the async read when it has one, so the permission prompt is gone on the normal path. It still falls back toreadText()if an event arrives withoutclipboardData.2. Clipboard failures surface.
writeToSystemClipboardnow rejects instead of swallowing, andpastereturns aPasteOutcomeofpasted/nothing-to-paste/clipboard-unavailable. All four copy call sites (editor shortcut and toolbar, run view shortcut and toolbar) and the paste handler report failures via toast.This also revives a
catchinDashboardComponentsV2View.handleCopyToPipelinethat could never fire before, becausewriteToSystemClipboardswallowed the error internally — "Copy to pipeline" reported success unconditionally, even when the clipboard write was refused.Two deliberate omissions:
clipboardDatadoing the work, the read-failure toast is a safety net rather than a common path — it fires only when an event arrives withoutclipboardDataand the async read is also refused. The copy-failure toast is the reachable one.Not in scope
Ctrl+C/Ctrl+Vare still unbound. The clipboard shortcuts register againstCMDALT, whichkeys.tsproduces only from Meta or Alt —Controlmaps to a separateCTRLconstant andmatchesPressedrequires an exact set match. On macOS that is fine (⌘C/⌘V). On Windows/Linux onlyAlt+C/Alt+Vwork, whileShortcutBadgerendersCMDALTas the literal string"Ctrl"— so the UI advertises a binding that does not exist. Worth a separate fix; it is a display/binding mismatch rather than a clipboard bug.Related Issue and Pull requests
None.
Type of Change
Checklist
Unit suite: 2485 passing across 232 files. Typecheck, lint and format clean. The Playwright E2E suite was not run — it has no coverage of copy/paste.
Screenshots (if applicable)
No visual change beyond the two error toasts, whose copy is in
clipboardMessages.ts:Couldn't copy to the clipboard. Check browser permissions and try again.Couldn't read the clipboard. Check browser permissions and try again.Test Instructions
Cross-tab paste (the actual bug):
Regressions to check:
Failure feedback (needs devtools):
document.body.dispatchEvent(new ClipboardEvent("paste", {bubbles: true, cancelable: true}))→ read-failure toast.
Additional Comments
Verified by driving the real app in Chromium against the dev server: an envelope placed on the system clipboard pasted into the V2 canvas as a task node, with the native paste event reaching the listener (
clipboardDatapresent, targetBODY); pasting into the component search field still inserted text with no node created; and both toasts appeared under a forced-failure clipboard.New tests: 11 for the envelope read/write paths (
clipboardEnvelope.test.ts) and 8 for the store (clipboardStore.test.ts), including that an envelope from another tab short-circuits the async read, that a denied read yieldsclipboard-unavailable, and that the paste offset does not advance when nothing is pasted.clipboardStore.test.tsmocks@/routes/v2/pages/Editor/nodes— the real node registry transitively imports the router, so the store cannot be unit-tested against it.