import { FormEvent, useEffect, useMemo, useState } from "react"; import { invoke } from "@tauri-apps/api/core"; type EnrollmentState = { assignedIp: string; resources: string[]; profileRevision: number; gatewayEndpoint: string; profilePath: string; lastSyncTime: string; tunnelStrategy: string; }; type TunnelMetrics = { active: boolean; rxBytes: number; txBytes: number; }; 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"; } 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)`; } function formatDataSize(bytes: number) { if (!bytes) { return "0 B"; } const units = ["B", "KB", "MB", "GB", "TB"]; let value = bytes; let unitIndex = 0; while (value >= 1024 && unitIndex < units.length - 1) { value /= 1024; unitIndex += 1; } return `${value >= 100 || unitIndex === 0 ? value.toFixed(0) : value.toFixed(1)} ${units[unitIndex]}`; } 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 [error, setError] = useState(null); const [connected, setConnected] = useState(false); const [state, setState] = useState(null); const [metrics, setMetrics] = useState({ active: false, rxBytes: 0, txBytes: 0 }); async function refreshTunnelMetrics() { try { const value = await invoke("tunnel_metrics"); setMetrics(value); setConnected(value.active); } catch { try { const active = await invoke("tunnel_status"); setConnected(active); setMetrics((current) => ({ ...current, active })); } catch { setMetrics({ active: false, rxBytes: 0, txBytes: 0 }); setConnected(false); } } } useEffect(() => { void invoke("load_state") .then(async (value) => { if (value) { setState(value); await refreshTunnelMetrics(); } }) .catch(() => undefined); }, []); useEffect(() => { if (!state) { setMetrics({ active: false, rxBytes: 0, txBytes: 0 }); return undefined; } void refreshTunnelMetrics(); const timer = window.setInterval(() => { void refreshTunnelMetrics(); }, 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) { await refreshTunnelMetrics(); return active; } } catch { if (!expected) { setMetrics({ active: false, rxBytes: 0, txBytes: 0 }); setConnected(false); return false; } } await new Promise((resolve) => window.setTimeout(resolve, 500)); } return invoke("tunnel_status") .then(async (active) => { setConnected(active); await refreshTunnelMetrics(); 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); setMetrics({ active: false, rxBytes: 0, txBytes: 0 }); } 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 refreshTunnelMetrics(); } catch (err) { setError(formatInvokeError(err, "Profile sync failed")); } finally { setSyncing(false); } } async function toggleConnection() { const command = connected ? "disconnect_tunnel" : "connect_tunnel"; 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")); } } async function resetEnrollment() { try { await invoke("clear_session"); setConnected(false); setState(null); setMetrics({ active: false, rxBytes: 0, txBytes: 0 }); setError(null); } catch (err) { setError(formatInvokeError(err, "Unable to clear local profile")); } } return (
NexaVPN

NexaVPN

VPN Client

{state ? "Private access client" : "Sign in to add this device"}

{state ? ( ) : null} {state ? ( ) : null}
{!state ? (

Sign in

Provision device

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

Status

{connected ? "Connected" : "Disconnected"}

{connected ? "Tunnel active" : "Ready"}

Connection

Overview

Assigned VPN IP {state.assignedIp}
Gateway endpoint {state.gatewayEndpoint}
Access {profileLabel}
Last sync {state.lastSyncTime}
Received {formatDataSize(metrics.rxBytes)}
Sent {formatDataSize(metrics.txBytes)}
{error ?
{error}
: null}
)}
); }