Update terminal panel

This commit is contained in:
MacRimi
2026-01-31 16:48:22 +01:00
parent e3d10495f3
commit 5e8b2bdb50
3 changed files with 65 additions and 23 deletions

View File

@@ -169,7 +169,7 @@ export function LxcTerminalModal({
} }
}, 25000) }, 25000)
// Sync terminal size // Sync terminal size first
fitAddon.fit() fitAddon.fit()
ws.send(JSON.stringify({ ws.send(JSON.stringify({
type: "resize", type: "resize",
@@ -177,12 +177,14 @@ export function LxcTerminalModal({
rows: term.rows, rows: term.rows,
})) }))
// Auto-execute pct enter command after a brief delay // Auto-execute pct enter command after terminal is ready
// Wait for shell prompt to appear before sending command
setTimeout(() => { setTimeout(() => {
if (ws.readyState === WebSocket.OPEN) { if (ws.readyState === WebSocket.OPEN) {
ws.send(`pct enter ${vmid}\n`) // Send the command as plain text like user would type
ws.send(`pct enter ${vmid}\r`)
} }
}, 500) }, 800)
} }
ws.onmessage = (event) => { ws.onmessage = (event) => {
@@ -287,13 +289,41 @@ export function LxcTerminalModal({
} }
}, []) }, [])
const sendCtrlC = useCallback(() => sendKey("\x03"), [sendKey]) const sendEsc = useCallback(() => sendKey("\x1b"), [sendKey])
const sendTab = useCallback(() => sendKey("\t"), [sendKey])
const sendArrowUp = useCallback(() => sendKey("\x1b[A"), [sendKey]) const sendArrowUp = useCallback(() => sendKey("\x1b[A"), [sendKey])
const sendArrowDown = useCallback(() => sendKey("\x1b[B"), [sendKey]) const sendArrowDown = useCallback(() => sendKey("\x1b[B"), [sendKey])
const sendArrowLeft = useCallback(() => sendKey("\x1b[D"), [sendKey]) const sendArrowLeft = useCallback(() => sendKey("\x1b[D"), [sendKey])
const sendArrowRight = useCallback(() => sendKey("\x1b[C"), [sendKey]) const sendArrowRight = useCallback(() => sendKey("\x1b[C"), [sendKey])
const sendEnter = useCallback(() => sendKey("\r"), [sendKey]) const sendEnter = useCallback(() => sendKey("\r"), [sendKey])
const sendTab = useCallback(() => sendKey("\t"), [sendKey]) const sendCtrlC = useCallback(() => sendKey("\x03"), [sendKey]) // Ctrl+C
// Ctrl key state - user presses Ctrl button, then types a letter
const [ctrlPressed, setCtrlPressed] = useState(false)
const handleCtrlPress = useCallback(() => {
setCtrlPressed(true)
setTimeout(() => setCtrlPressed(false), 3000)
}, [])
// Handle keyboard input when Ctrl is pressed
useEffect(() => {
if (!ctrlPressed || !isOpen) return
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key.length === 1) {
e.preventDefault()
const code = e.key.toLowerCase().charCodeAt(0) - 96
if (code >= 1 && code <= 26) {
sendKey(String.fromCharCode(code))
}
setCtrlPressed(false)
}
}
window.addEventListener("keydown", handleKeyDown)
return () => window.removeEventListener("keydown", handleKeyDown)
}, [ctrlPressed, isOpen, sendKey])
const showMobileControls = isMobile || isTablet const showMobileControls = isMobile || isTablet
@@ -302,6 +332,7 @@ export function LxcTerminalModal({
<DialogContent <DialogContent
className="max-w-4xl w-[95vw] p-0 gap-0 bg-black border-border overflow-hidden flex flex-col" className="max-w-4xl w-[95vw] p-0 gap-0 bg-black border-border overflow-hidden flex flex-col"
style={{ height: `${modalHeight}px` }} style={{ height: `${modalHeight}px` }}
hideClose
> >
{/* Resize bar */} {/* Resize bar */}
<div <div
@@ -358,10 +389,18 @@ export function LxcTerminalModal({
<Button <Button
variant="outline" variant="outline"
size="sm" size="sm"
onClick={sendCtrlC} onClick={sendEsc}
className="h-9 px-3 bg-red-600/20 border-red-600/50 text-red-400 hover:bg-red-600/30" className="h-9 px-3 bg-zinc-800 border-zinc-700 text-zinc-300"
> >
Ctrl+C ESC
</Button>
<Button
variant="outline"
size="sm"
onClick={sendTab}
className="h-9 px-3 bg-zinc-800 border-zinc-700 text-zinc-300"
>
TAB
</Button> </Button>
<Button <Button
variant="outline" variant="outline"
@@ -395,14 +434,6 @@ export function LxcTerminalModal({
> >
<ArrowRight className="h-4 w-4" /> <ArrowRight className="h-4 w-4" />
</Button> </Button>
<Button
variant="outline"
size="sm"
onClick={sendTab}
className="h-9 px-3 bg-zinc-800 border-zinc-700"
>
Tab
</Button>
<Button <Button
variant="outline" variant="outline"
size="sm" size="sm"
@@ -412,6 +443,16 @@ export function LxcTerminalModal({
<CornerDownLeft className="h-4 w-4 mr-1" /> <CornerDownLeft className="h-4 w-4 mr-1" />
Enter Enter
</Button> </Button>
<Button
variant="outline"
size="sm"
onClick={handleCtrlPress}
className={`h-9 px-3 ${ctrlPressed
? "bg-yellow-600/30 border-yellow-600/50 text-yellow-400"
: "bg-zinc-800 border-zinc-700 text-zinc-300"}`}
>
{ctrlPressed ? "Ctrl+?" : "Ctrl"}
</Button>
</div> </div>
</div> </div>
)} )}

View File

@@ -736,9 +736,10 @@ export function ScriptTerminalModal({
}} }}
variant="outline" variant="outline"
size="sm" size="sm"
className="h-8 px-2.5 text-xs bg-zinc-800 hover:bg-zinc-700 border-zinc-700 text-white" className="h-8 px-2.5 text-xs bg-blue-600/20 hover:bg-blue-600/30 border-blue-600/50 text-blue-400"
> >
<CornerDownLeft className="h-4 w-4" /> <CornerDownLeft className="h-4 w-4 mr-1" />
Enter
</Button> </Button>
<Button <Button
onPointerDown={(e) => { onPointerDown={(e) => {
@@ -750,7 +751,7 @@ export function ScriptTerminalModal({
size="sm" size="sm"
className="h-8 px-2 text-xs bg-zinc-800 hover:bg-zinc-700 border-zinc-700 text-white min-w-[65px]" className="h-8 px-2 text-xs bg-zinc-800 hover:bg-zinc-700 border-zinc-700 text-white min-w-[65px]"
> >
CTRL+C Ctrl
</Button> </Button>
</div> </div>
)} )}

View File

@@ -963,9 +963,9 @@ const handleClose = () => {
}} }}
variant="outline" variant="outline"
size="sm" size="sm"
className="h-8 px-3 text-xs" className="h-8 px-3 text-xs bg-blue-600/20 hover:bg-blue-600/30 border-blue-600/50 text-blue-400"
> >
Enter
</Button> </Button>
<Button <Button
onPointerDown={(e) => { onPointerDown={(e) => {
@@ -977,7 +977,7 @@ const handleClose = () => {
size="sm" size="sm"
className="h-8 px-2 text-xs" className="h-8 px-2 text-xs"
> >
CTRL+C Ctrl
</Button> </Button>
</div> </div>
)} )}