From 26e90aa39eef14620529af0922215a5765058c4a Mon Sep 17 00:00:00 2001 From: MacRimi Date: Mon, 16 Mar 2026 23:13:13 +0100 Subject: [PATCH] Update terminal panel --- AppImage/components/lxc-terminal-modal.tsx | 21 ++++++++++++------ AppImage/components/terminal-panel.tsx | 25 ++++++++++++++++++++-- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/AppImage/components/lxc-terminal-modal.tsx b/AppImage/components/lxc-terminal-modal.tsx index 985ebd8c..7c2c387f 100644 --- a/AppImage/components/lxc-terminal-modal.tsx +++ b/AppImage/components/lxc-terminal-modal.tsx @@ -327,13 +327,20 @@ export function LxcTerminalModal({ term.write(lastPromptMatch[0]) } - // Send an extra Enter for Alpine containers (ash shell) - // This forces the prompt to refresh properly - setTimeout(() => { - if (ws.readyState === WebSocket.OPEN) { - ws.send('\r') - } - }, 100) + // Detect if this is Alpine/ash shell by checking prompt format + // Alpine uses: [root@hostname ~]# or [root@hostname /]# + // Other distros use: root@hostname:/# or root@hostname:~# + const isAlpine = afterPctEnter.match(/\[[^\]]+@[^\]]+\s+[^\]]*\][#$]/) + + if (isAlpine) { + // Send an extra Enter ONLY for Alpine containers (ash shell) + // This forces the prompt to refresh properly + setTimeout(() => { + if (ws.readyState === WebSocket.OPEN) { + ws.send('\r') + } + }, 100) + } return } diff --git a/AppImage/components/terminal-panel.tsx b/AppImage/components/terminal-panel.tsx index aa1d14ea..19edc69f 100644 --- a/AppImage/components/terminal-panel.tsx +++ b/AppImage/components/terminal-panel.tsx @@ -430,7 +430,28 @@ export const TerminalPanel: React.FC = ({ websocketUrl, onCl delete containerRefs.current[id] } + // Callback ref handler that initializes terminal when container becomes available + const setContainerRef = useCallback((terminalId: string, el: HTMLDivElement | null) => { + containerRefs.current[terminalId] = el + + // If element is available and terminal needs initialization, do it now + if (el) { + const terminal = terminals.find(t => t.id === terminalId) + if (terminal && !terminal.term) { + // Small delay to ensure React has finished rendering + setTimeout(() => { + const currentTerminal = terminals.find(t => t.id === terminalId) + if (currentTerminal && !currentTerminal.term && el) { + initializeTerminal(currentTerminal, el) + } + }, 50) + } + } + }, [terminals]) + useEffect(() => { + // Also try to initialize any pending terminals + // This handles cases where state updates after ref assignment terminals.forEach((terminal) => { const container = containerRefs.current[terminal.id] if (!terminal.term && container) { @@ -859,7 +880,7 @@ const handleClose = () => { className={`flex-1 h-full mt-0 ${activeTerminalId === terminal.id ? "block" : "hidden"}`} >
(containerRefs.current[terminal.id] = el)} + ref={(el) => setContainerRef(terminal.id, el)} className="w-full h-full flex-1 bg-black overflow-hidden" /> @@ -890,7 +911,7 @@ const handleClose = () => { )}
(containerRefs.current[terminal.id] = el)} + ref={(el) => setContainerRef(terminal.id, el)} onClick={() => setActiveTerminalId(terminal.id)} className="flex-1 w-full max-w-full bg-black overflow-hidden cursor-pointer" data-terminal-container