Update AppImage

This commit is contained in:
MacRimi
2025-12-06 13:54:37 +01:00
parent fed242315d
commit 122ebb12f4
2 changed files with 896 additions and 942 deletions

View File

@@ -6,7 +6,7 @@ import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input" import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label" import { Label } from "@/components/ui/label"
import { X, CheckCircle2, XCircle, Loader2 } from "lucide-react" import { X, CheckCircle2, XCircle, Loader2 } from "lucide-react"
import { TerminalPanel, type TerminalPanelHandle } from "./terminal-panel" import { TerminalPanel } from "./terminal-panel"
import { API_PORT } from "@/lib/api-config" import { API_PORT } from "@/lib/api-config"
interface WebInteraction { interface WebInteraction {
@@ -42,36 +42,16 @@ export function ScriptTerminalModal({
const [exitCode, setExitCode] = useState<number | null>(null) 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 terminalRef = useRef<TerminalPanelHandle>(null) const wsRef = useRef<WebSocket | null>(null)
useEffect(() => {
console.log("[v0] currentInteraction changed:", currentInteraction)
if (currentInteraction) {
console.log("[v0] Interaction opened, type:", currentInteraction.type, "id:", currentInteraction.id)
} else {
console.log("[v0] Interaction closed/cleared")
console.trace("[v0] Stack trace for currentInteraction = null")
}
}, [currentInteraction])
useEffect(() => { useEffect(() => {
if (open) { if (open) {
console.log("[v0] ScriptTerminalModal opened with:", {
scriptPath,
scriptName,
params,
sessionId,
})
// Reset state only when modal opens
setIsComplete(false) setIsComplete(false)
setExitCode(null) setExitCode(null)
setInteractionInput("") setInteractionInput("")
// Don't clear currentInteraction here - it causes issues
} else {
// Clear interaction when modal closes
setCurrentInteraction(null) setCurrentInteraction(null)
} }
}, [open]) // Only depend on 'open' to avoid unnecessary re-runs }, [open])
const getScriptWebSocketUrl = (): string => { const getScriptWebSocketUrl = (): string => {
if (typeof window === "undefined") { if (typeof window === "undefined") {
@@ -85,16 +65,16 @@ export function ScriptTerminalModal({
const wsUrl = getScriptWebSocketUrl() const wsUrl = getScriptWebSocketUrl()
const handleWebSocketCreated = (ws: WebSocket) => {
wsRef.current = ws
}
const handleWebInteraction = (interaction: WebInteraction) => { const handleWebInteraction = (interaction: WebInteraction) => {
console.log("[v0] handleWebInteraction called with:", interaction)
setCurrentInteraction(interaction) setCurrentInteraction(interaction)
console.log("[v0] currentInteraction set to:", interaction.type, interaction.id)
} }
const handleInteractionResponse = (value: string) => { const handleInteractionResponse = (value: string) => {
console.log("[v0] handleInteractionResponse called with value:", value) if (!wsRef.current || !currentInteraction) {
if (!terminalRef.current || !currentInteraction) {
console.log("[v0] Cannot send response - no terminal ref or interaction")
return return
} }
@@ -104,12 +84,10 @@ export function ScriptTerminalModal({
value: value, value: value,
}) })
console.log("[v0] Sending interaction response:", response) if (wsRef.current.readyState === WebSocket.OPEN) {
wsRef.current.send(response)
}
terminalRef.current.sendMessage(response)
console.log("[v0] Response sent successfully")
console.log("[v0] Clearing currentInteraction after response")
setCurrentInteraction(null) setCurrentInteraction(null)
setInteractionInput("") setInteractionInput("")
} }
@@ -144,13 +122,13 @@ export function ScriptTerminalModal({
<div className="flex-1 overflow-hidden"> <div className="flex-1 overflow-hidden">
<TerminalPanel <TerminalPanel
ref={terminalRef}
websocketUrl={wsUrl} websocketUrl={wsUrl}
initMessage={{ initMessage={{
script_path: scriptPath, script_path: scriptPath,
params: params, params: params,
}} }}
onWebInteraction={handleWebInteraction} onWebInteraction={handleWebInteraction}
onWebSocketCreated={handleWebSocketCreated}
/> />
</div> </div>
@@ -163,17 +141,11 @@ export function ScriptTerminalModal({
</Dialog> </Dialog>
{currentInteraction && ( {currentInteraction && (
<Dialog open={true} modal={true}> <Dialog open={true}>
<DialogContent <DialogContent
className="max-w-4xl max-h-[80vh] overflow-y-auto" className="max-w-4xl max-h-[80vh] overflow-y-auto"
onInteractOutside={(e) => { onInteractOutside={(e) => e.preventDefault()}
console.log("[v0] onInteractOutside triggered - preventing close") onEscapeKeyDown={(e) => e.preventDefault()}
e.preventDefault()
}}
onEscapeKeyDown={(e) => {
console.log("[v0] onEscapeKeyDown triggered - preventing close")
e.preventDefault()
}}
> >
<DialogTitle>{currentInteraction.title}</DialogTitle> <DialogTitle>{currentInteraction.title}</DialogTitle>
<div className="space-y-4"> <div className="space-y-4">
@@ -212,8 +184,7 @@ export function ScriptTerminalModal({
</div> </div>
)} )}
{currentInteraction.type === "input" || {(currentInteraction.type === "input" || currentInteraction.type === "inputbox") && (
(currentInteraction.type === "inputbox" && (
<div className="space-y-2"> <div className="space-y-2">
<Label>Your input:</Label> <Label>Your input:</Label>
<Input <Input
@@ -230,7 +201,7 @@ export function ScriptTerminalModal({
Submit Submit
</Button> </Button>
</div> </div>
))} )}
{currentInteraction.type === "msgbox" && ( {currentInteraction.type === "msgbox" && (
<Button onClick={() => handleInteractionResponse("ok")} className="w-full"> <Button onClick={() => handleInteractionResponse("ok")} className="w-full">

View File

@@ -1,7 +1,7 @@
"use client" "use client"
import type React from "react" import type React from "react"
import { useEffect, useRef, useState, forwardRef, useImperativeHandle } from "react" import { useEffect, useRef, useState } from "react"
import { API_PORT } from "../lib/api-config" import { API_PORT } from "../lib/api-config"
import { fetchApi } from "@/lib/api-config" // Cambiando import para usar fetchApi directamente import { fetchApi } from "@/lib/api-config" // Cambiando import para usar fetchApi directamente
import { import {
@@ -28,10 +28,7 @@ type TerminalPanelProps = {
onClose?: () => void onClose?: () => void
initMessage?: Record<string, any> initMessage?: Record<string, any>
onWebInteraction?: (interaction: any) => void onWebInteraction?: (interaction: any) => void
} onWebSocketCreated?: (ws: WebSocket) => void
export interface TerminalPanelHandle {
sendMessage: (message: string) => void
} }
interface TerminalInstance { interface TerminalInstance {
@@ -138,8 +135,13 @@ const proxmoxCommands = [
{ cmd: "clear", desc: "Clear terminal screen" }, { cmd: "clear", desc: "Clear terminal screen" },
] ]
const TerminalPanel = forwardRef<TerminalPanelHandle, TerminalPanelProps>( export const TerminalPanel: React.FC<TerminalPanelProps> = ({
({ websocketUrl, onClose, initMessage, onWebInteraction }, ref) => { websocketUrl,
onClose,
initMessage,
onWebInteraction,
onWebSocketCreated,
}) => {
const [terminals, setTerminals] = useState<TerminalInstance[]>([]) const [terminals, setTerminals] = useState<TerminalInstance[]>([])
const [activeTerminalId, setActiveTerminalId] = useState<string>("") const [activeTerminalId, setActiveTerminalId] = useState<string>("")
const [layout, setLayout] = useState<"single" | "grid">("grid") const [layout, setLayout] = useState<"single" | "grid">("grid")
@@ -155,24 +157,6 @@ const TerminalPanel = forwardRef<TerminalPanelHandle, TerminalPanelProps>(
const containerRefs = useRef<{ [key: string]: HTMLDivElement | null }>({}) const containerRefs = useRef<{ [key: string]: HTMLDivElement | null }>({})
useImperativeHandle(
ref,
() => ({
sendMessage: (message: string) => {
console.log("[v0] TerminalPanel.sendMessage called with:", message)
// Send to the first terminal (or active terminal if available)
const terminal = terminals.find((t) => t.id === activeTerminalId) || terminals[0]
if (terminal?.ws && terminal.ws.readyState === WebSocket.OPEN) {
console.log("[v0] Sending message via WebSocket")
terminal.ws.send(message)
} else {
console.log("[v0] Cannot send message - no active WebSocket")
}
},
}),
[terminals, activeTerminalId],
)
useEffect(() => { useEffect(() => {
const updateDeviceType = () => { const updateDeviceType = () => {
const width = window.innerWidth const width = window.innerWidth
@@ -453,6 +437,10 @@ const TerminalPanel = forwardRef<TerminalPanelHandle, TerminalPanelProps>(
prev.map((t) => (t.id === terminal.id ? { ...t, isConnected: true, term, ws, fitAddon } : t)), prev.map((t) => (t.id === terminal.id ? { ...t, isConnected: true, term, ws, fitAddon } : t)),
) )
if (onWebSocketCreated) {
onWebSocketCreated(ws)
}
if (initMessage) { if (initMessage) {
console.log("[v0] TerminalPanel: Sending init message:", initMessage) console.log("[v0] TerminalPanel: Sending init message:", initMessage)
ws.send(JSON.stringify(initMessage)) ws.send(JSON.stringify(initMessage))
@@ -1040,9 +1028,4 @@ const TerminalPanel = forwardRef<TerminalPanelHandle, TerminalPanelProps>(
</Dialog> </Dialog>
</div> </div>
) )
}, }
)
TerminalPanel.displayName = "TerminalPanel"
export default TerminalPanel