From 7a3a4d1413bb64c9cf7a39b788a5b319f481c684 Mon Sep 17 00:00:00 2001 From: MacRimi Date: Sat, 28 Mar 2026 22:04:47 +0100 Subject: [PATCH] Update terminal-panel.tsx --- AppImage/components/terminal-panel.tsx | 64 ++++++++------------------ 1 file changed, 20 insertions(+), 44 deletions(-) diff --git a/AppImage/components/terminal-panel.tsx b/AppImage/components/terminal-panel.tsx index 1455dca4..255e8410 100644 --- a/AppImage/components/terminal-panel.tsx +++ b/AppImage/components/terminal-panel.tsx @@ -16,7 +16,6 @@ import { Grid2X2, GripHorizontal, ChevronDown, - Clipboard, } from "lucide-react" import { DropdownMenu, @@ -493,6 +492,8 @@ export const TerminalPanel: React.FC = ({ websocketUrl, onCl customGlyphs: true, fontWeight: "500", fontWeightBold: "700", + rightClickSelectsWord: true, + allowProposedApi: true, theme: { background: "#000000", foreground: "#ffffff", @@ -523,6 +524,20 @@ export const TerminalPanel: React.FC = ({ websocketUrl, onCl term.open(container) fitAddon.fit() + + // Enable native paste on mobile - handle paste event from clipboard + const handlePaste = (e: ClipboardEvent) => { + e.preventDefault() + const text = e.clipboardData?.getData('text') + if (text) { + // Will be sent through WebSocket once connected + const currentTerminal = terminals.find(t => t.id === terminal.id) + if (currentTerminal?.ws && currentTerminal.ws.readyState === WebSocket.OPEN) { + currentTerminal.ws.send(text) + } + } + } + container.addEventListener('paste', handlePaste) const wsUrl = websocketUrl || getWebSocketUrl() @@ -580,17 +595,14 @@ export const TerminalPanel: React.FC = ({ websocketUrl, onCl ) syncSizeWithBackend() - // Auto-refresh for mobile/VPN: send a newline after 1 second to ensure connection is active - // This fixes the issue where mobile connections sometimes don't fully initialize + // Mobile fix: additional fit after short delay to ensure proper rendering + // This helps with VPN/slow connections where initial render may not complete const isMobileDevice = window.innerWidth < 768 || ('ontouchstart' in window && navigator.maxTouchPoints > 0) if (isMobileDevice) { setTimeout(() => { - if (ws.readyState === WebSocket.OPEN) { - // Send empty string to trigger a refresh without executing any command - ws.send('\n') - } - }, 1000) + syncSizeWithBackend() + }, 500) } } @@ -745,32 +757,6 @@ const handleClose = () => { } } - // Paste from clipboard - essential for mobile devices - const handlePaste = async (e?: React.MouseEvent | React.TouchEvent) => { - if (e) { - e.preventDefault() - e.stopPropagation() - } - - try { - const text = await navigator.clipboard.readText() - if (text) { - const activeTerminal = terminals.find((t) => t.id === activeTerminalId) - if (activeTerminal?.ws && activeTerminal.ws.readyState === WebSocket.OPEN) { - // Send text character by character to handle special characters properly - activeTerminal.ws.send(text) - } - } - } catch (err) { - console.warn('[Terminal] Clipboard access denied:', err) - // Fallback: show a message in terminal - const activeTerminal = terminals.find((t) => t.id === activeTerminalId) - if (activeTerminal?.term) { - activeTerminal.term.writeln('\r\n\x1b[33m[INFO] Clipboard access denied. Please allow clipboard permissions.\x1b[0m') - } - } - } - const getLayoutClass = () => { const count = terminals.length if (isMobile || count === 1) return "grid grid-cols-1" @@ -1072,16 +1058,6 @@ const handleClose = () => { - )}