From 71e5c6489427150599223d3f61fd99aff7d0b402 Mon Sep 17 00:00:00 2001 From: srikary12 Date: Sun, 12 Oct 2025 21:10:27 +0530 Subject: [PATCH 1/2] feat: add clipboard support for terminal input and output --- view/app/terminal/utils/useTerminal.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/view/app/terminal/utils/useTerminal.ts b/view/app/terminal/utils/useTerminal.ts index 7f10b472c..ad2f7b9ca 100644 --- a/view/app/terminal/utils/useTerminal.ts +++ b/view/app/terminal/utils/useTerminal.ts @@ -160,6 +160,32 @@ export const useTerminal = ( if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 'j') { return false; } + + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 'c') { + if (event.shiftKey) { + sendJsonMessage({ + action: 'terminal', + data: { value: CTRL_C, terminalId } + }); + return false; + } + const selection = term.getSelection(); + if (selection) { + navigator.clipboard.writeText(selection); + } + return false; + } + + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 'v') { + navigator.clipboard.readText().then((text) => { + sendJsonMessage({ + action: 'terminal', + data: { value: text, terminalId } + }); + }); + return false; + } + return true; }); From 7654d441c589f62c084b0fed30d02599209dfe64 Mon Sep 17 00:00:00 2001 From: srikary12 Date: Mon, 20 Oct 2025 07:57:07 +0530 Subject: [PATCH 2/2] fixes multiple paste issues and clears selection after copying --- docker-compose-dev.yml | 2 +- view/app/terminal/utils/stopExecution.ts | 2 +- view/app/terminal/utils/useTerminal.ts | 45 ++++++++++-------------- 3 files changed, 20 insertions(+), 29 deletions(-) diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index dcea5aefc..88cc9237d 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -105,7 +105,7 @@ services: timeout: 5s retries: 20 - supertokens: + nixopus-supertokens: image: registry.supertokens.io/supertokens/supertokens-postgresql:latest container_name: supertokens diff --git a/view/app/terminal/utils/stopExecution.ts b/view/app/terminal/utils/stopExecution.ts index b279903c1..8a3c6d5af 100644 --- a/view/app/terminal/utils/stopExecution.ts +++ b/view/app/terminal/utils/stopExecution.ts @@ -4,7 +4,7 @@ export const StopExecution = () => { const [isStopped, setIsStopped] = useState(false); useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { - if (e.key === 'c' && (e.metaKey || e.ctrlKey)) { + if (e.key === 'c' && (e.metaKey || e.ctrlKey) && e.shiftKey) { e.preventDefault(); console.log('Stopped execution'); setIsStopped(true); diff --git a/view/app/terminal/utils/useTerminal.ts b/view/app/terminal/utils/useTerminal.ts index ad2f7b9ca..e7ab8b4d2 100644 --- a/view/app/terminal/utils/useTerminal.ts +++ b/view/app/terminal/utils/useTerminal.ts @@ -19,8 +19,8 @@ type TerminalOutput = { }; export const useTerminal = ( - isTerminalOpen: boolean, - width: number, + isTerminalOpen: boolean, + width: number, height: number, allowInput: boolean = true, terminalId: string = 'terminal_id' @@ -157,38 +157,29 @@ export const useTerminal = ( if (allowInput) { term.attachCustomKeyEventHandler((event: KeyboardEvent) => { - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 'j') { + const key = event.key.toLowerCase(); + if (key === 'j' && (event.ctrlKey || event.metaKey)) { return false; } - - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 'c') { - if (event.shiftKey) { - sendJsonMessage({ - action: 'terminal', - data: { value: CTRL_C, terminalId } - }); - return false; - } - const selection = term.getSelection(); - if (selection) { - navigator.clipboard.writeText(selection); + else if (key === 'c' && (event.ctrlKey || event.metaKey) && !event.shiftKey) { + if (event.type === 'keydown' ) { + try { + const selection = term.getSelection(); + if (selection) { + navigator.clipboard.writeText(selection) + .then(() => { + term.clearSelection(); // Clear selection after successful copy + }) + return false; + } + } catch (error) { + console.error('Error in Ctrl+C handler:', error); + } } return false; } - - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 'v') { - navigator.clipboard.readText().then((text) => { - sendJsonMessage({ - action: 'terminal', - data: { value: text, terminalId } - }); - }); - return false; - } - return true; }); - term.onData((data) => { sendJsonMessage({ action: 'terminal',