diff options
| author | Adam <[email protected]> | 2026-02-11 07:17:01 -0600 |
|---|---|---|
| committer | Adam <[email protected]> | 2026-02-11 07:19:33 -0600 |
| commit | ef5ec5dc28ce668585f11c76d89622d6c13724f0 (patch) | |
| tree | 5ca651cde3c1850293afa4c91fe010966fdb33bc /packages/app/src/components | |
| parent | c426cb0f14f1b130b7819c4f0ef1a33a327c1444 (diff) | |
| download | opencode-ef5ec5dc28ce668585f11c76d89622d6c13724f0.tar.gz opencode-ef5ec5dc28ce668585f11c76d89622d6c13724f0.zip | |
fix(app): terminal copy/paste
Diffstat (limited to 'packages/app/src/components')
| -rw-r--r-- | packages/app/src/components/terminal.tsx | 55 |
1 files changed, 25 insertions, 30 deletions
diff --git a/packages/app/src/components/terminal.tsx b/packages/app/src/components/terminal.tsx index 7a1b81f0c..2527c74ec 100644 --- a/packages/app/src/components/terminal.tsx +++ b/packages/app/src/components/terminal.tsx @@ -130,11 +130,12 @@ export const Terminal = (props: TerminalProps) => { const t = term if (!t) return t.focus() + t.textarea?.focus() setTimeout(() => t.textarea?.focus(), 0) } const handlePointerDown = () => { const activeElement = document.activeElement - if (activeElement instanceof HTMLElement && activeElement !== container) { + if (activeElement instanceof HTMLElement && activeElement !== container && !container.contains(activeElement)) { activeElement.blur() } focusTerminal() @@ -204,44 +205,32 @@ export const Terminal = (props: TerminalProps) => { ghostty = g term = t - const copy = () => { + const handleCopy = (event: ClipboardEvent) => { const selection = t.getSelection() - if (!selection) return false - - const body = document.body - if (body) { - const textarea = document.createElement("textarea") - textarea.value = selection - textarea.setAttribute("readonly", "") - textarea.style.position = "fixed" - textarea.style.opacity = "0" - body.appendChild(textarea) - textarea.select() - const copied = document.execCommand("copy") - body.removeChild(textarea) - if (copied) return true - } + if (!selection) return - const clipboard = navigator.clipboard - if (clipboard?.writeText) { - clipboard.writeText(selection).catch(() => {}) - return true - } + const clipboard = event.clipboardData + if (!clipboard) return + + event.preventDefault() + clipboard.setData("text/plain", selection) + } + + const handlePaste = (event: ClipboardEvent) => { + const clipboard = event.clipboardData + const text = clipboard?.getData("text/plain") ?? clipboard?.getData("text") ?? "" + if (!text) return - return false + event.preventDefault() + event.stopPropagation() + t.paste(text) } t.attachCustomKeyEventHandler((event) => { const key = event.key.toLowerCase() if (event.ctrlKey && event.shiftKey && !event.metaKey && key === "c") { - copy() - return true - } - - if (event.metaKey && !event.ctrlKey && !event.altKey && key === "c") { - if (!t.hasSelection()) return true - copy() + document.execCommand("copy") return true } @@ -252,6 +241,12 @@ export const Terminal = (props: TerminalProps) => { return matchKeybind(keybinds, event) }) + container.addEventListener("copy", handleCopy, true) + cleanups.push(() => container.removeEventListener("copy", handleCopy, true)) + + container.addEventListener("paste", handlePaste, true) + cleanups.push(() => container.removeEventListener("paste", handlePaste, true)) + const fit = new mod.FitAddon() const serializer = new SerializeAddon() cleanups.push(() => disposeIfDisposable(fit)) |
