Update lxc-terminal-modal.tsx

This commit is contained in:
MacRimi
2026-02-01 00:50:53 +01:00
parent 08f435597a
commit fc8bf841bf

View File

@@ -54,10 +54,7 @@ export function LxcTerminalModal({
const [connectionStatus, setConnectionStatus] = useState<"connecting" | "online" | "offline">("connecting") const [connectionStatus, setConnectionStatus] = useState<"connecting" | "online" | "offline">("connecting")
const [isMobile, setIsMobile] = useState(false) const [isMobile, setIsMobile] = useState(false)
const [isTablet, setIsTablet] = useState(false) const [isTablet, setIsTablet] = useState(false)
const isInsideLxcRef = useRef(false)
// Track host prompt to detect when user exits LXC
const hostPromptRef = useRef<string>("")
const insideLxcRef = useRef(false)
const outputBufferRef = useRef<string>("") const outputBufferRef = useRef<string>("")
const [modalHeight, setModalHeight] = useState(500) const [modalHeight, setModalHeight] = useState(500)
@@ -65,6 +62,13 @@ export function LxcTerminalModal({
const resizeBarRef = useRef<HTMLDivElement>(null) const resizeBarRef = useRef<HTMLDivElement>(null)
const modalHeightRef = useRef(500) const modalHeightRef = useRef(500)
const [showLoginModal, setShowLoginModal] = useState(false)
const [loginUsername, setLoginUsername] = useState("")
const [loginPassword, setLoginPassword] = useState("")
const [loginError, setLoginError] = useState("")
const [isLoggingIn, setIsLoggingIn] = useState(false)
const waitingForPasswordRef = useRef(false)
// Detect mobile/tablet // Detect mobile/tablet
useEffect(() => { useEffect(() => {
const checkDevice = () => { const checkDevice = () => {
@@ -93,8 +97,7 @@ export function LxcTerminalModal({
termRef.current = null termRef.current = null
} }
setConnectionStatus("connecting") setConnectionStatus("connecting")
hostPromptRef.current = "" isInsideLxcRef.current = false
insideLxcRef.current = false
outputBufferRef.current = "" outputBufferRef.current = ""
} }
}, [isOpen]) }, [isOpen])
@@ -227,53 +230,45 @@ export function LxcTerminalModal({
return return
} }
const data = event.data // Buffer output until we detect we're inside the LXC
// pct enter always enters directly without login prompt when run as root
// Buffer output until we're inside the LXC if (!isInsideLxcRef.current) {
if (!insideLxcRef.current) { outputBufferRef.current += event.data
outputBufferRef.current += data
// Capture host prompt (pattern like "root@hostname" or "[user@hostname") // Detect when we're inside the LXC container
if (!hostPromptRef.current) { // The LXC prompt will NOT contain "constructor" (the host name)
const hostMatch = outputBufferRef.current.match(/\[?(\w+@[\w-]+)/) // It will be something like "root@plex:/#" or "user@containername:~$"
if (hostMatch) { const buffer = outputBufferRef.current
hostPromptRef.current = hostMatch[1]
}
}
// Detect when we're inside the LXC // Look for a prompt that:
// Look for a prompt that is different from the host prompt after pct enter // 1. Comes after pct enter command
if (hostPromptRef.current && outputBufferRef.current.includes(`pct enter ${vmid}`)) { // 2. Has @ followed by container name (not host name)
const hostName = hostPromptRef.current.split('@')[1] // 3. Ends with # or $
// Look for a new prompt line that doesn't contain the host name const pctEnterMatch = buffer.match(/pct enter \d+\r?\n/)
const lines = outputBufferRef.current.split('\n') if (pctEnterMatch) {
for (let i = lines.length - 1; i >= 0; i--) { const afterPctEnter = buffer.substring(buffer.indexOf(pctEnterMatch[0]) + pctEnterMatch[0].length)
const line = lines[i]
// Check if this line has a prompt (@) but NOT the host name // Find the LXC prompt - it should be a line ending with :~# :~$ :/# or similar
if (line.includes('@') && !line.includes(hostName) && (line.includes('#') || line.includes('$'))) { // and NOT containing the host name "constructor"
// Found LXC prompt - we're inside const lxcPromptMatch = afterPctEnter.match(/\r?\n?([^\r\n]*@(?!constructor)[^\r\n]*[#$]\s*)$/)
insideLxcRef.current = true
// Only show from this prompt onwards if (lxcPromptMatch) {
term.write(line) // Successfully inside LXC - only show from the LXC prompt onwards
break isInsideLxcRef.current = true
// Find where the LXC prompt line starts
const promptStart = afterPctEnter.lastIndexOf(lxcPromptMatch[1])
if (promptStart !== -1) {
// Only show the LXC prompt itself
term.write(lxcPromptMatch[1])
} }
return
} }
} }
return } else {
// Already inside LXC, write directly
term.write(event.data)
} }
// Already inside LXC - write directly
// But check if user exited (host prompt appears again)
if (hostPromptRef.current && data.includes(hostPromptRef.current)) {
// User exited LXC, close modal after short delay
term.write(data)
setTimeout(() => {
onClose()
}, 500)
return
}
term.write(data)
} }
} }