import React, { useState, useEffect } from "react"; import { Button } from "@/components/button.tsx"; import { Input } from "@/components/input.tsx"; import { Label } from "@/components/label.tsx"; import { Alert, AlertTitle, AlertDescription } from "@/components/alert.tsx"; import { Switch } from "@/components/switch.tsx"; import { useTranslation } from "react-i18next"; import { getServerConfig, saveServerConfig, getEmbeddedServerStatus, setEmbeddedMode, type ServerConfig, } from "@/main-axios.ts"; import { Server, Monitor, Loader2 } from "lucide-react"; interface ServerConfigProps { onServerConfigured: (serverUrl: string) => void; onUseEmbedded?: () => void; onCancel?: () => void; isFirstTime?: boolean; } export function ElectronServerConfig({ onServerConfigured, onUseEmbedded, onCancel, isFirstTime = false, }: ServerConfigProps) { const { t } = useTranslation(); const [serverUrl, setServerUrl] = useState(""); const [allowInvalidCertificate, setAllowInvalidCertificate] = useState(false); const [loading, setLoading] = useState(false); const [embeddedLoading, setEmbeddedLoading] = useState(false); const [error, setError] = useState(null); const [embeddedAvailable, setEmbeddedAvailable] = useState( null, ); useEffect(() => { loadServerConfig(); checkEmbeddedBackend(); }, []); const loadServerConfig = async () => { try { const config = await getServerConfig(); if (config?.serverUrl) { setServerUrl(config.serverUrl); } setAllowInvalidCertificate(!!config?.allowInvalidCertificate); } catch (error) { console.error("Server config operation failed:", error); } }; const checkEmbeddedBackend = async () => { try { const status = await getEmbeddedServerStatus(); setEmbeddedAvailable(!!status?.embedded); } catch { setEmbeddedAvailable(true); } }; const probeBackend = async (): Promise => { const controller = new AbortController(); const timer = setTimeout(() => controller.abort(), 3000); try { const res = await fetch("http://localhost:30001/health", { signal: controller.signal, }); clearTimeout(timer); return res.ok; } catch { clearTimeout(timer); } const controller2 = new AbortController(); const timer2 = setTimeout(() => controller2.abort(), 3000); try { await fetch("http://localhost:30001/version", { signal: controller2.signal, }); clearTimeout(timer2); return true; } catch { clearTimeout(timer2); return false; } }; const handleUseEmbedded = async () => { setEmbeddedLoading(true); setError(null); try { await new Promise((r) => setTimeout(r, 1500)); const maxRetries = 15; for (let i = 0; i < maxRetries; i++) { if (await probeBackend()) { setEmbeddedMode(true); if (onUseEmbedded) { onUseEmbedded(); } else { onServerConfigured("http://localhost:30001"); } return; } if (i < maxRetries - 1) { await new Promise((r) => setTimeout(r, 2000)); } } setError(t("serverConfig.embeddedNotReady")); } catch (err) { setError( err instanceof Error ? err.message : t("serverConfig.embeddedNotReady"), ); } finally { setEmbeddedLoading(false); } }; const handleSaveConfig = async () => { if (!serverUrl.trim()) { setError(t("serverConfig.enterServerUrl")); return; } setLoading(true); setError(null); try { const normalizedUrl = serverUrl.trim(); if ( !normalizedUrl.startsWith("http://") && !normalizedUrl.startsWith("https://") ) { setError(t("serverConfig.mustIncludeProtocol")); setLoading(false); return; } const config: ServerConfig = { serverUrl: normalizedUrl, lastUpdated: new Date().toISOString(), allowInvalidCertificate: normalizedUrl.startsWith("https://") && allowInvalidCertificate, }; const success = await saveServerConfig(config); if (success) { onServerConfigured(normalizedUrl); } else { setError(t("serverConfig.saveFailed")); } } catch { setError(t("serverConfig.saveError")); } finally { setLoading(false); } }; const handleUrlChange = (value: string) => { setServerUrl(value); setError(null); }; return (

{t("serverConfig.title")}

{t("serverConfig.description")}

{embeddedAvailable !== false && ( <>

{t("serverConfig.embeddedDesc")}

{t("common.or") || "OR"}
)}
handleUrlChange(e.target.value)} disabled={loading || embeddedLoading} />
{serverUrl.trim().startsWith("https://") && (

{t("serverConfig.allowInvalidCertificateDesc")}

)} {error && ( {t("common.error")} {error} )}
{onCancel && !isFirstTime && ( )}

{t("serverConfig.helpText")}

); }