fix: terminal paste functionality

This commit is contained in:
Akhileshrangani4 2024-11-30 00:03:51 -05:00
parent 06dadf3a0b
commit 42305d67b9

View File

@ -7,7 +7,7 @@ import "./xterm.css"
import { debounce } from "@/lib/utils" import { debounce } from "@/lib/utils"
import { Loader2 } from "lucide-react" import { Loader2 } from "lucide-react"
import { useTheme } from "next-themes" import { useTheme } from "next-themes"
import { ElementRef, useEffect, useRef } from "react" import { ElementRef, useEffect, useRef, useCallback } from "react"
import { Socket } from "socket.io-client" import { Socket } from "socket.io-client"
export default function EditorTerminal({ export default function EditorTerminal({
socket, socket,
@ -28,7 +28,6 @@ export default function EditorTerminal({
useEffect(() => { useEffect(() => {
if (!terminalContainerRef.current) return if (!terminalContainerRef.current) return
// console.log("new terminal", id, term ? "reusing" : "creating");
const terminal = new Terminal({ const terminal = new Terminal({
cursorBlink: true, cursorBlink: true,
@ -37,13 +36,54 @@ export default function EditorTerminal({
fontSize: 14, fontSize: 14,
lineHeight: 1.5, lineHeight: 1.5,
letterSpacing: 0, letterSpacing: 0,
allowTransparency: true,
rightClickSelectsWord: true,
allowProposedApi: true, // for custom key events
})
// right-click paste handler
const handleContextMenu = (e: MouseEvent) => {
e.preventDefault()
navigator.clipboard.readText().then((text) => {
if (text) {
socket.emit("terminalData", { id, data: text })
}
})
}
terminalContainerRef.current.addEventListener(
"contextmenu",
handleContextMenu
)
// keyboard paste handler
terminal.attachCustomKeyEventHandler((event: KeyboardEvent) => {
if (event.type === "keydown") {
if (
(event.ctrlKey || event.metaKey) &&
event.key.toLowerCase() === "v"
) {
event.preventDefault()
navigator.clipboard.readText().then((text) => {
if (text) {
socket.emit("terminalData", { id, data: text })
}
})
return false
}
}
return true
}) })
setTerm(terminal) setTerm(terminal)
const dispose = () => {
return () => {
terminal.dispose() terminal.dispose()
terminalContainerRef.current?.removeEventListener(
"contextmenu",
handleContextMenu
)
} }
return dispose
}, []) }, [])
useEffect(() => { useEffect(() => {
@ -81,7 +121,6 @@ export default function EditorTerminal({
const { width, height } = entry.contentRect const { width, height } = entry.contentRect
// Only call fit if the size has actually changed
if ( if (
width !== terminalContainerRef.current.offsetWidth || width !== terminalContainerRef.current.offsetWidth ||
height !== terminalContainerRef.current.offsetHeight height !== terminalContainerRef.current.offsetHeight
@ -92,10 +131,9 @@ export default function EditorTerminal({
console.error("Error during fit:", err) console.error("Error during fit:", err)
} }
} }
}, 50) // Debounce for 50ms }, 50)
) )
// start observing for resize
resizeObserver.observe(terminalContainerRef.current) resizeObserver.observe(terminalContainerRef.current)
return () => { return () => {
disposableOnData.dispose() disposableOnData.dispose()
@ -124,6 +162,7 @@ export default function EditorTerminal({
ref={terminalContainerRef} ref={terminalContainerRef}
style={{ display: visible ? "block" : "none" }} style={{ display: visible ? "block" : "none" }}
className="w-full h-full text-left" className="w-full h-full text-left"
tabIndex={0}
> >
{term === null ? ( {term === null ? (
<div className="flex items-center text-muted-foreground p-2"> <div className="flex items-center text-muted-foreground p-2">