mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2025-12-14 16:16:21 +00:00
Update script-terminal-modal.tsx
This commit is contained in:
@@ -54,7 +54,6 @@ export function ScriptTerminalModal({
|
|||||||
|
|
||||||
const [connectionStatus, setConnectionStatus] = useState<"connecting" | "online" | "offline">("connecting")
|
const [connectionStatus, setConnectionStatus] = useState<"connecting" | "online" | "offline">("connecting")
|
||||||
const [isComplete, setIsComplete] = useState(false)
|
const [isComplete, setIsComplete] = useState(false)
|
||||||
const [exitCode, setExitCode] = useState<number | null>(null)
|
|
||||||
const [currentInteraction, setCurrentInteraction] = useState<WebInteraction | null>(null)
|
const [currentInteraction, setCurrentInteraction] = useState<WebInteraction | null>(null)
|
||||||
const [interactionInput, setInteractionInput] = useState("")
|
const [interactionInput, setInteractionInput] = useState("")
|
||||||
const checkConnectionInterval = useRef<NodeJS.Timeout | null>(null)
|
const checkConnectionInterval = useRef<NodeJS.Timeout | null>(null)
|
||||||
@@ -69,7 +68,7 @@ export function ScriptTerminalModal({
|
|||||||
const [modalHeight, setModalHeight] = useState(600)
|
const [modalHeight, setModalHeight] = useState(600)
|
||||||
const [isResizing, setIsResizing] = useState(false)
|
const [isResizing, setIsResizing] = useState(false)
|
||||||
const resizeBarRef = useRef<HTMLDivElement>(null)
|
const resizeBarRef = useRef<HTMLDivElement>(null)
|
||||||
const modalHeightRef = useRef(600) // Ref para mantener el valor actualizado
|
const modalHeightRef = useRef(600)
|
||||||
|
|
||||||
const terminalContainerRef = useRef<HTMLDivElement>(null)
|
const terminalContainerRef = useRef<HTMLDivElement>(null)
|
||||||
|
|
||||||
@@ -87,12 +86,10 @@ export function ScriptTerminalModal({
|
|||||||
|
|
||||||
reconnectTimeoutRef.current = setTimeout(() => {
|
reconnectTimeoutRef.current = setTimeout(() => {
|
||||||
if (wsRef.current?.readyState !== WebSocket.OPEN && termRef.current) {
|
if (wsRef.current?.readyState !== WebSocket.OPEN && termRef.current) {
|
||||||
// Cerrar conexión anterior si existe
|
|
||||||
if (wsRef.current) {
|
if (wsRef.current) {
|
||||||
wsRef.current.close()
|
wsRef.current.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crear nueva conexión
|
|
||||||
const wsUrl = getScriptWebSocketUrl(sessionIdRef.current)
|
const wsUrl = getScriptWebSocketUrl(sessionIdRef.current)
|
||||||
const ws = new WebSocket(wsUrl)
|
const ws = new WebSocket(wsUrl)
|
||||||
wsRef.current = ws
|
wsRef.current = ws
|
||||||
@@ -101,7 +98,6 @@ export function ScriptTerminalModal({
|
|||||||
setConnectionStatus("online")
|
setConnectionStatus("online")
|
||||||
reconnectAttemptsRef.current = 0
|
reconnectAttemptsRef.current = 0
|
||||||
|
|
||||||
// Reiniciar el script
|
|
||||||
const initMessage = {
|
const initMessage = {
|
||||||
script_path: scriptPath,
|
script_path: scriptPath,
|
||||||
params: {
|
params: {
|
||||||
@@ -110,7 +106,6 @@ export function ScriptTerminalModal({
|
|||||||
}
|
}
|
||||||
ws.send(JSON.stringify(initMessage))
|
ws.send(JSON.stringify(initMessage))
|
||||||
|
|
||||||
// Redimensionar terminal
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (fitAddonRef.current && termRef.current && ws.readyState === WebSocket.OPEN) {
|
if (fitAddonRef.current && termRef.current && ws.readyState === WebSocket.OPEN) {
|
||||||
const cols = termRef.current.cols
|
const cols = termRef.current.cols
|
||||||
@@ -157,11 +152,9 @@ export function ScriptTerminalModal({
|
|||||||
ws.onclose = (event) => {
|
ws.onclose = (event) => {
|
||||||
setConnectionStatus("offline")
|
setConnectionStatus("offline")
|
||||||
if (!isComplete && reconnectAttemptsRef.current < 3) {
|
if (!isComplete && reconnectAttemptsRef.current < 3) {
|
||||||
// Intentar reconectar después de 2 segundos
|
|
||||||
reconnectTimeoutRef.current = setTimeout(attemptReconnect, 2000)
|
reconnectTimeoutRef.current = setTimeout(attemptReconnect, 2000)
|
||||||
} else {
|
} else {
|
||||||
setIsComplete(true)
|
setIsComplete(true)
|
||||||
setExitCode(event.code === 1000 ? 0 : 1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,17 +167,17 @@ export function ScriptTerminalModal({
|
|||||||
const keyMap: Record<string, string> = {
|
const keyMap: Record<string, string> = {
|
||||||
escape: "\x1b",
|
escape: "\x1b",
|
||||||
tab: "\t",
|
tab: "\t",
|
||||||
up: "\x1b[A",
|
up: "\x1bOA",
|
||||||
down: "\x1b[B",
|
down: "\x1bOB",
|
||||||
left: "\x1b[D",
|
left: "\x1bOD",
|
||||||
right: "\x1b[C",
|
right: "\x1bOC",
|
||||||
enter: "\r",
|
enter: "\r",
|
||||||
ctrlc: "\x03",
|
ctrlc: "\x03",
|
||||||
}
|
}
|
||||||
|
|
||||||
const sequence = keyMap[key]
|
const sequence = keyMap[key]
|
||||||
if (sequence && wsRef.current?.readyState === WebSocket.OPEN) {
|
if (sequence && wsRef.current?.readyState === WebSocket.OPEN) {
|
||||||
wsRef.current.send(JSON.stringify({ type: "input", data: sequence }))
|
wsRef.current.send(sequence)
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
@@ -325,7 +318,6 @@ export function ScriptTerminalModal({
|
|||||||
|
|
||||||
if (!isComplete) {
|
if (!isComplete) {
|
||||||
setIsComplete(true)
|
setIsComplete(true)
|
||||||
setExitCode(event.code === 1000 ? 0 : 1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,7 +367,7 @@ export function ScriptTerminalModal({
|
|||||||
if (savedHeight) {
|
if (savedHeight) {
|
||||||
const height = Number.parseInt(savedHeight, 10)
|
const height = Number.parseInt(savedHeight, 10)
|
||||||
setModalHeight(height)
|
setModalHeight(height)
|
||||||
modalHeightRef.current = height // Sincronizar el ref
|
modalHeightRef.current = height
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
@@ -402,7 +394,6 @@ export function ScriptTerminalModal({
|
|||||||
sessionIdRef.current = Math.random().toString(36).substring(2, 8)
|
sessionIdRef.current = Math.random().toString(36).substring(2, 8)
|
||||||
reconnectAttemptsRef.current = 0
|
reconnectAttemptsRef.current = 0
|
||||||
setIsComplete(false)
|
setIsComplete(false)
|
||||||
setExitCode(null)
|
|
||||||
setInteractionInput("")
|
setInteractionInput("")
|
||||||
setCurrentInteraction(null)
|
setCurrentInteraction(null)
|
||||||
setIsWaitingNextInteraction(false)
|
setIsWaitingNextInteraction(false)
|
||||||
@@ -424,17 +415,14 @@ export function ScriptTerminalModal({
|
|||||||
const handleResize = () => updateDeviceType()
|
const handleResize = () => updateDeviceType()
|
||||||
window.addEventListener("resize", handleResize)
|
window.addEventListener("resize", handleResize)
|
||||||
|
|
||||||
// Detectar cuando la app vuelve a estar visible (desbloqueo de pantalla)
|
|
||||||
const handleVisibilityChange = () => {
|
const handleVisibilityChange = () => {
|
||||||
if (!document.hidden && isOpen) {
|
if (!document.hidden && isOpen) {
|
||||||
// La pantalla se desbloqueó, verificar conexión
|
|
||||||
if (wsRef.current?.readyState !== WebSocket.OPEN && !isComplete) {
|
if (wsRef.current?.readyState !== WebSocket.OPEN && !isComplete) {
|
||||||
attemptReconnect()
|
attemptReconnect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detectar cuando la app vuelve desde background
|
|
||||||
const handleFocus = () => {
|
const handleFocus = () => {
|
||||||
if (isOpen && wsRef.current?.readyState !== WebSocket.OPEN && !isComplete) {
|
if (isOpen && wsRef.current?.readyState !== WebSocket.OPEN && !isComplete) {
|
||||||
attemptReconnect()
|
attemptReconnect()
|
||||||
@@ -525,7 +513,6 @@ export function ScriptTerminalModal({
|
|||||||
const deltaY = currentY - startY
|
const deltaY = currentY - startY
|
||||||
const newHeight = Math.max(300, Math.min(window.innerHeight - 50, startHeight + deltaY))
|
const newHeight = Math.max(300, Math.min(window.innerHeight - 50, startHeight + deltaY))
|
||||||
|
|
||||||
// Actualizar directamente sin requestAnimationFrame para mayor fluidez
|
|
||||||
modalHeightRef.current = newHeight
|
modalHeightRef.current = newHeight
|
||||||
setModalHeight(newHeight)
|
setModalHeight(newHeight)
|
||||||
}
|
}
|
||||||
@@ -542,7 +529,6 @@ export function ScriptTerminalModal({
|
|||||||
|
|
||||||
localStorage.setItem("scriptModalHeight", finalHeight.toString())
|
localStorage.setItem("scriptModalHeight", finalHeight.toString())
|
||||||
|
|
||||||
// Ajustar terminal al final del resize
|
|
||||||
if (fitAddonRef.current && termRef.current && wsRef.current?.readyState === WebSocket.OPEN) {
|
if (fitAddonRef.current && termRef.current && wsRef.current?.readyState === WebSocket.OPEN) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
fitAddonRef.current?.fit()
|
fitAddonRef.current?.fit()
|
||||||
@@ -566,7 +552,7 @@ export function ScriptTerminalModal({
|
|||||||
|
|
||||||
const sendCommand = (command: string) => {
|
const sendCommand = (command: string) => {
|
||||||
if (wsRef.current?.readyState === WebSocket.OPEN) {
|
if (wsRef.current?.readyState === WebSocket.OPEN) {
|
||||||
wsRef.current.send(JSON.stringify({ type: "input", data: command }))
|
wsRef.current.send(command)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -583,12 +569,14 @@ export function ScriptTerminalModal({
|
|||||||
onEscapeKeyDown={(e) => e.preventDefault()}
|
onEscapeKeyDown={(e) => e.preventDefault()}
|
||||||
hideClose
|
hideClose
|
||||||
>
|
>
|
||||||
<DialogTitle className="sr-only">{title}</DialogTitle>
|
<DialogTitle className="sr-only">{scriptName || title}</DialogTitle>
|
||||||
|
|
||||||
<div className="flex items-center gap-2 p-4 border-b">
|
<div className="flex items-center gap-2 p-4 border-b">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-lg font-semibold">{title}</h2>
|
<h2 className="text-lg font-semibold">{scriptName || title}</h2>
|
||||||
{description && <p className="text-sm text-muted-foreground">{description}</p>}
|
{(scriptDescription || description) && (
|
||||||
|
<p className="text-sm text-muted-foreground">{scriptDescription || description}</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -605,7 +593,6 @@ export function ScriptTerminalModal({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Resize bar - visible en tablet y escritorio */}
|
|
||||||
{!isMobile && (
|
{!isMobile && (
|
||||||
<div
|
<div
|
||||||
ref={resizeBarRef}
|
ref={resizeBarRef}
|
||||||
@@ -622,7 +609,6 @@ export function ScriptTerminalModal({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Mobile/Tablet button toolbar */}
|
|
||||||
{(isMobile || isTablet) && (
|
{(isMobile || isTablet) && (
|
||||||
<div className="flex items-center justify-center gap-1.5 px-1 py-2 border-t bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
<div className="flex items-center justify-center gap-1.5 px-1 py-2 border-t bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
||||||
<Button
|
<Button
|
||||||
@@ -653,7 +639,7 @@ export function ScriptTerminalModal({
|
|||||||
onPointerDown={(e) => {
|
onPointerDown={(e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
sendCommand("\x1b[A")
|
sendCommand("\x1bOA")
|
||||||
}}
|
}}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
@@ -665,7 +651,7 @@ export function ScriptTerminalModal({
|
|||||||
onPointerDown={(e) => {
|
onPointerDown={(e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
sendCommand("\x1b[B")
|
sendCommand("\x1bOB")
|
||||||
}}
|
}}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
@@ -677,7 +663,7 @@ export function ScriptTerminalModal({
|
|||||||
onPointerDown={(e) => {
|
onPointerDown={(e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
sendCommand("\x1b[D")
|
sendCommand("\x1bOD")
|
||||||
}}
|
}}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
@@ -689,7 +675,7 @@ export function ScriptTerminalModal({
|
|||||||
onPointerDown={(e) => {
|
onPointerDown={(e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
sendCommand("\x1b[C")
|
sendCommand("\x1bOC")
|
||||||
}}
|
}}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
@@ -724,7 +710,6 @@ export function ScriptTerminalModal({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Footer with connection status and close button */}
|
|
||||||
<div className="flex items-center justify-between px-4 py-3 border-t bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
<div className="flex items-center justify-between px-4 py-3 border-t bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<Activity className="h-5 w-5 text-blue-500" />
|
<Activity className="h-5 w-5 text-blue-500" />
|
||||||
|
|||||||
Reference in New Issue
Block a user