import { SettingsPageHeader } from "@components/SettingsPageheader"; import { SettingsItem } from "./devices.$id.settings"; import { useLoaderData } from "react-router-dom"; import { Button, LinkButton } from "../components/Button"; import { CLOUD_APP, DEVICE_API } from "../ui.config"; import api from "../api"; import { LocalDevice } from "./devices.$id"; import { useDeviceUiNavigation } from "../hooks/useAppNavigation"; import { isOnDevice } from "../main"; import { GridCard } from "../components/Card"; import { ShieldCheckIcon } from "@heroicons/react/24/outline"; import notifications from "../notifications"; import { useCallback, useEffect, useState } from "react"; import { useJsonRpc } from "../hooks/useJsonRpc"; import { InputFieldWithLabel } from "../components/InputField"; import { SelectMenuBasic } from "../components/SelectMenuBasic"; import { SettingsSectionHeader } from "../components/SettingsSectionHeader"; export const loader = async () => { const status = await api .GET(`${DEVICE_API}/device`) .then(res => res.json() as Promise); return status; }; export default function SettingsAccessIndexRoute() { const { authMode } = useLoaderData() as LocalDevice; const { navigateTo } = useDeviceUiNavigation(); const [send] = useJsonRpc(); const [isAdopted, setAdopted] = useState(false); const [deviceId, setDeviceId] = useState(null); const [cloudUrl, setCloudUrl] = useState(""); const [cloudProviders, setCloudProviders] = useState< { value: string; label: string }[] | null >([{ value: "https://api.jetkvm.com", label: "JetKVM Cloud" }]); // The default value is just there so it doesn't flicker while we fetch the default Cloud URL and available providers const [selectedUrlOption, setSelectedUrlOption] = useState( "https://api.jetkvm.com", ); const [defaultCloudUrl, setDefaultCloudUrl] = useState(""); const syncCloudUrl = useCallback(() => { send("getCloudUrl", {}, resp => { if ("error" in resp) return; const url = resp.result as string; setCloudUrl(url); // Check if the URL matches any predefined option if (cloudProviders?.some(provider => provider.value === url)) { setSelectedUrlOption(url); } else { setSelectedUrlOption("custom"); // setCustomCloudUrl(url); } }); }, [cloudProviders, send]); const getCloudState = useCallback(() => { send("getCloudState", {}, resp => { if ("error" in resp) return console.error(resp.error); const cloudState = resp.result as { connected: boolean }; setAdopted(cloudState.connected); }); }, [send]); const deregisterDevice = async () => { send("deregisterDevice", {}, resp => { if ("error" in resp) { notifications.error( `Failed to de-register device: ${resp.error.data || "Unknown error"}`, ); return; } getCloudState(); return; }); }; const onCloudAdoptClick = useCallback( (url: string) => { if (!deviceId) { notifications.error("No device ID available"); return; } send("setCloudUrl", { url }, resp => { if ("error" in resp) { notifications.error( `Failed to update cloud URL: ${resp.error.data || "Unknown error"}`, ); return; } syncCloudUrl(); notifications.success("Cloud URL updated successfully"); const returnTo = new URL(window.location.href); returnTo.pathname = "/adopt"; returnTo.search = ""; returnTo.hash = ""; window.location.href = CLOUD_APP + "/signup?deviceId=" + deviceId + `&returnTo=${returnTo.toString()}`; }); }, [deviceId, syncCloudUrl, send], ); useEffect(() => { if (!defaultCloudUrl) return; setSelectedUrlOption(defaultCloudUrl); setCloudProviders([ { value: defaultCloudUrl, label: "JetKVM Cloud" }, { value: "custom", label: "Custom" }, ]); }, [defaultCloudUrl]); useEffect(() => { getCloudState(); send("getDeviceID", {}, async resp => { if ("error" in resp) return console.error(resp.error); setDeviceId(resp.result as string); }); }, [send, getCloudState]); useEffect(() => { send("getDefaultCloudUrl", {}, resp => { if ("error" in resp) return console.error(resp.error); setDefaultCloudUrl(resp.result as string); }); }, [cloudProviders, syncCloudUrl, send]); useEffect(() => { if (!cloudProviders?.length) return; syncCloudUrl(); }, [cloudProviders, syncCloudUrl]); console.log("is adopted:", isAdopted); return (
{authMode === "password" ? (
{isOnDevice && ( <>
{!isAdopted && ( <> { const value = e.target.value; setSelectedUrlOption(value); }} options={cloudProviders ?? []} /> {selectedUrlOption === "custom" && (
setCloudUrl(e.target.value)} placeholder="https://api.example.com" />
)} )} {/* We do the harcoding here to avoid flickering when the default Cloud URL being fetched. I've tried to avoid harcoding api.jetkvm.com, but it's the only reasonable way I could think of to avoid flickering for now. */} {selectedUrlOption === (defaultCloudUrl || "https://api.jetkvm.com") && (

Cloud Security

  • End-to-end encryption using WebRTC (DTLS and SRTP)
  • Zero Trust security model
  • OIDC (OpenID Connect) authentication
  • All streams encrypted in transit
All cloud components are open-source and available on{" "} GitHub .

)} {!isAdopted ? (
) : (

Your device is adopted to JetKVM Cloud

)}
)}
); }