import { FormEvent, useEffect, useMemo, useState } from "react"; import { invoke } from "@tauri-apps/api/core"; import { AppHeader } from "./components/AppHeader"; import { ResourcePanel } from "./components/ResourcePanel"; import { StatusCard } from "./components/StatusCard"; type AccessProfile = { id: string; name: string; description: string; fullTunnel: boolean; destinations: string[]; }; type EnrollmentState = { assignedIp: string; resources: string[]; availableProfiles: AccessProfile[]; selectedProfileId: string | null; profileRevision: number; gatewayEndpoint: string; profilePath: string; lastSyncTime: string; tunnelStrategy: string; }; function formatInvokeError(err: unknown, fallback: string) { if (typeof err === "string" && err.trim().length > 0) { return err; } if (err instanceof Error && err.message.trim().length > 0) { return err.message; } return fallback; } function isAlreadyRunningError(err: unknown) { const message = formatInvokeError(err, ""); return message.toLowerCase().includes("already installed and running"); } function currentProfileLabel(state: EnrollmentState | null) { if (!state) { return "Not provisioned"; } const selectedProfile = state.availableProfiles.find((profile) => profile.id === state.selectedProfileId); if (selectedProfile) { return selectedProfile.name; } if (state.resources.includes("0.0.0.0/0")) { return "Full tunnel"; } if (state.resources.length === 1) { return "Single resource access"; } return `Split tunnel (${state.resources.length} resources)`; } export function App() { const [serverUrl, setServerUrl] = useState("http://localhost"); const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); const [loading, setLoading] = useState(false); const [syncing, setSyncing] = useState(false); const [selectingProfile, setSelectingProfile] = useState(false); const [tunnelActionPending, setTunnelActionPending] = useState(false); const [error, setError] = useState(null); const [connected, setConnected] = useState(false); const [state, setState] = useState(null); async function refreshTunnelStatus() { try { const active = await invoke("tunnel_status"); setConnected(active); } catch { setConnected(false); } } useEffect(() => { void invoke("load_state") .then(async (value) => { if (value) { setState(value); await refreshTunnelStatus(); } }) .catch(() => undefined); }, []); useEffect(() => { if (!state) { setConnected(false); return undefined; } void refreshTunnelStatus(); const timer = window.setInterval(() => { void refreshTunnelStatus(); }, 5000); return () => window.clearInterval(timer); }, [state]); const profileLabel = useMemo(() => currentProfileLabel(state), [state]); async function waitForTunnelStatus(expected: boolean) { for (let attempt = 0; attempt < 8; attempt += 1) { try { const active = await invoke("tunnel_status"); setConnected(active); if (active === expected) { return active; } } catch { if (!expected) { setConnected(false); return false; } } await new Promise((resolve) => window.setTimeout(resolve, 500)); } return invoke("tunnel_status") .then(async (active) => { setConnected(active); return active; }) .catch(() => false); } async function onSubmit(event: FormEvent) { event.preventDefault(); setLoading(true); setError(null); try { const result = await invoke("enroll_device", { payload: { serverUrl, username, password } }); setState(result); } catch (err) { setError(formatInvokeError(err, "Enrollment failed")); } finally { setLoading(false); } } async function onSyncProfile() { setSyncing(true); setError(null); try { const result = await invoke("sync_profile"); setState(result); await refreshTunnelStatus(); } catch (err) { setError(formatInvokeError(err, "Profile sync failed")); } finally { setSyncing(false); } } async function onSelectProfile(profileId: string) { if (!state || profileId === state.selectedProfileId) { return; } setSelectingProfile(true); setError(null); try { const result = await invoke("select_access_profile", { profileId }); setState(result); await refreshTunnelStatus(); } catch (err) { setError(formatInvokeError(err, "Profile selection failed")); } finally { setSelectingProfile(false); } } async function toggleConnection() { const command = connected ? "disconnect_tunnel" : "connect_tunnel"; setTunnelActionPending(true); try { if (!connected) { const syncedState = await invoke("connect_tunnel"); setState(syncedState); } else { await invoke(command); } const active = await waitForTunnelStatus(!connected); setConnected(active); if (!connected && !active) { setError("Tunnel was installed, but no active interface could be verified yet."); } else if (connected && active) { setError("Tunnel could not be stopped cleanly yet."); } else { setError(null); } } catch (err) { if (!connected && isAlreadyRunningError(err)) { const active = await waitForTunnelStatus(true); setConnected(active); if (active) { setError(null); return; } } setError(formatInvokeError(err, "Tunnel action failed")); } finally { setTunnelActionPending(false); } } async function resetEnrollment() { try { await invoke("clear_session"); setConnected(false); setState(null); setError(null); } catch (err) { setError(formatInvokeError(err, "Unable to clear local profile")); } } return (
{!state ? (

Sign in

Provision device

{error ?
{error}
: null}
) : (
{error ?
{error}
: null}
)}
); }