import React, { useState, useEffect, useRef, useCallback } from "react"; import { GuacamoleDisplay, type GuacamoleDisplayHandle, } from "@/features/guacamole/GuacamoleDisplay.tsx"; import { FullScreenAppWrapper } from "@/features/FullScreenAppWrapper.tsx"; import { getGuacamoleTokenFromHost, getGuacdStatus } from "@/main-axios.ts"; import { useTranslation } from "react-i18next"; import { AlertCircle, RefreshCw } from "lucide-react"; import { GuacamoleToolbar } from "@/features/guacamole/GuacamoleToolbar.tsx"; import { Button } from "@/components/button.tsx"; import { SimpleLoader } from "@/lib/SimpleLoader.tsx"; import type { SSHHost } from "@/types"; interface GuacamoleAppProps { hostId?: string; tabId?: string; protocol?: "rdp" | "vnc" | "telnet"; } const GuacamoleApp: React.FC = ({ hostId, tabId, protocol, }) => { const { t } = useTranslation(); return ( {(hostConfig, loading) => { if (loading) { return (
); } if (!hostConfig) { return (
{t("guacamole.hostNotFound")}
); } if (!hostId) { return (
{t("guacamole.hostNotFound")}
); } return ( ); }}
); }; interface GuacamoleAppInnerProps { hostId: number; hostConfig: Pick; tabId?: string; protocol?: "rdp" | "vnc" | "telnet"; } const GuacamoleAppInner: React.FC = ({ hostId, hostConfig, tabId, protocol, }) => { const { t } = useTranslation(); const [token, setToken] = useState(null); const [error, setError] = useState(null); const [connectionError, setConnectionError] = useState(null); const [retryCount, setRetryCount] = useState(0); const displayRef = useRef(null); useEffect(() => { setToken(null); setError(null); getGuacdStatus() .then((status) => { if (status.guacd.status !== "connected") { setError(t("guacamole.guacdUnavailable")); return; } return getGuacamoleTokenFromHost(hostId, protocol); }) .then((result) => { if (result) setToken(result.token); }) .catch((err) => setError(err?.message || t("guacamole.failedToConnect"))); }, [hostId, protocol, retryCount, t]); const handleReconnect = useCallback(() => { setConnectionError(null); setError(null); setToken(null); setRetryCount((c) => c + 1); }, []); useEffect(() => { if (!tabId) return; const handler = (e: Event) => { const { tabId: eventTabId } = (e as CustomEvent).detail; if (eventTabId === tabId) handleReconnect(); }; window.addEventListener("termix:refresh-guacamole", handler); return () => window.removeEventListener("termix:refresh-guacamole", handler); }, [tabId, handleReconnect]); if (error) { return (

{t("guacamole.connectionFailed")}

{error}

); } if (!token) { return (
); } const resolvedProtocol = (protocol ?? hostConfig.connectionType) as | "rdp" | "vnc" | "telnet"; return (
{connectionError && (

{t("guacamole.connectionFailed")}

{connectionError}

)} setConnectionError(err)} />
); }; export default GuacamoleApp;