Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ui/.env.development
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ VITE_SIGNAL_API=http://localhost:3000

VITE_CLOUD_APP=http://localhost:5173
VITE_CLOUD_API=http://localhost:3000

VITE_JETKVM_HEAD=
2 changes: 2 additions & 0 deletions ui/.env.device
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ VITE_SIGNAL_API= # Uses the KVM device's IP address as the signal API endpoint

VITE_CLOUD_APP=https://app.jetkvm.com
VITE_CLOUD_API=https://api.jetkvm.com

VITE_JETKVM_HEAD=<script src="/device/ui-config.js"></script>
4 changes: 3 additions & 1 deletion ui/.env.production
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
VITE_SIGNAL_API=https://api.jetkvm.com

VITE_CLOUD_APP=https://app.jetkvm.com
VITE_CLOUD_API=https://api.jetkvm.com
VITE_CLOUD_API=https://api.jetkvm.com

VITE_JETKVM_HEAD=
1 change: 1 addition & 0 deletions ui/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<title>JetKVM</title>
<link rel="stylesheet" href="/fonts/fonts.css" />
<link rel="icon" href="/favicon.png" />
%VITE_JETKVM_HEAD%
<script>
// Initial theme setup
document.documentElement.classList.toggle(
Expand Down
3 changes: 2 additions & 1 deletion ui/src/components/AuthLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useLocation, useNavigation, useSearchParams } from "react-router-dom";
import Fieldset from "@components/Fieldset";
import GridBackground from "@components/GridBackground";
import StepCounter from "@components/StepCounter";
import { CLOUD_API } from "@/ui.config";

type AuthLayoutProps = {
title: string;
Expand Down Expand Up @@ -62,7 +63,7 @@ export default function AuthLayout({
<Fieldset className="space-y-12">
<div className="max-w-sm mx-auto space-y-4">
<form
action={`${import.meta.env.VITE_CLOUD_API}/oidc/google`}
action={`${CLOUD_API}/oidc/google`}
method="POST"
>
{/*This could be the KVM ID*/}
Expand Down
5 changes: 3 additions & 2 deletions ui/src/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import PeerConnectionStatusCard from "@components/PeerConnectionStatusCard";
import api from "../api";
import { isOnDevice } from "../main";
import { Button, LinkButton } from "./Button";
import { CLOUD_API, SIGNAL_API } from "@/ui.config";

interface NavbarProps {
isLoggedIn: boolean;
Expand All @@ -37,8 +38,8 @@ export default function DashboardNavbar({
const navigate = useNavigate();
const onLogout = useCallback(async () => {
const logoutUrl = isOnDevice
? `${import.meta.env.VITE_SIGNAL_API}/auth/logout`
: `${import.meta.env.VITE_CLOUD_API}/logout`;
? `${SIGNAL_API}/auth/logout`
: `${CLOUD_API}/logout`;
const res = await api.POST(logoutUrl);
if (!res.ok) return;

Expand Down
3 changes: 2 additions & 1 deletion ui/src/components/MountMediaDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { ExclamationTriangleIcon } from "@heroicons/react/20/solid";
import notifications from "../notifications";
import Fieldset from "./Fieldset";
import { isOnDevice } from "../main";
import { SIGNAL_API } from "@/ui.config";

export default function MountMediaModal({
open,
Expand Down Expand Up @@ -1108,7 +1109,7 @@ function UploadFileView({
alreadyUploadedBytes: number,
dataChannel: string,
) {
const uploadUrl = `${import.meta.env.VITE_SIGNAL_API}/storage/upload?uploadId=${dataChannel}`;
const uploadUrl = `${SIGNAL_API}/storage/upload?uploadId=${dataChannel}`;

const xhr = new XMLHttpRequest();
xhr.open("POST", uploadUrl, true);
Expand Down
5 changes: 3 additions & 2 deletions ui/src/components/sidebar/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import LocalAuthPasswordDialog from "@/components/LocalAuthPasswordDialog";
import { LocalDevice } from "@routes/devices.$id";
import { useRevalidator } from "react-router-dom";
import { ShieldCheckIcon } from "@heroicons/react/20/solid";
import { CLOUD_APP, SIGNAL_API } from "@/ui.config";

export function SettingsItem({
title,
Expand Down Expand Up @@ -331,7 +332,7 @@ export default function SettingsSidebar() {
const getDevice = useCallback(async () => {
try {
const status = await api
.GET(`${import.meta.env.VITE_SIGNAL_API}/device`)
.GET(`${SIGNAL_API}/device`)
.then(res => res.json() as Promise<LocalDevice>);
setLocalDevice(status);
} catch (error) {
Expand Down Expand Up @@ -642,7 +643,7 @@ export default function SettingsSidebar() {
<div>
<LinkButton
to={
import.meta.env.VITE_CLOUD_APP +
CLOUD_APP +
"/signup?deviceId=" +
deviceId +
`&returnTo=${location.href}adopt`
Expand Down
3 changes: 2 additions & 1 deletion ui/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@ import LoginLocalRoute from "./routes/login-local";
import WelcomeLocalModeRoute from "./routes/welcome-local.mode";
import WelcomeRoute from "./routes/welcome-local";
import WelcomeLocalPasswordRoute from "./routes/welcome-local.password";
import { CLOUD_API } from "./ui.config";

export const isOnDevice = import.meta.env.MODE === "device";
export const isInCloud = !isOnDevice;

export async function checkAuth() {
const res = await fetch(`${import.meta.env.VITE_CLOUD_API}/me`, {
const res = await fetch(`${CLOUD_API}/me`, {
mode: "cors",
credentials: "include",
headers: { "Content-Type": "application/json" },
Expand Down
7 changes: 4 additions & 3 deletions ui/src/routes/adopt.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { LoaderFunctionArgs, redirect } from "react-router-dom";
import api from "../api";
import { CLOUD_API, CLOUD_APP, SIGNAL_API } from "@/ui.config";

const loader = async ({ request }: LoaderFunctionArgs) => {
const url = new URL(request.url);
Expand All @@ -11,17 +12,17 @@ const loader = async ({ request }: LoaderFunctionArgs) => {
const clientId = searchParams.get("clientId");

const res = await api.POST(
`${import.meta.env.VITE_SIGNAL_API}/cloud/register`,
`${SIGNAL_API}/cloud/register`,
{
token: tempToken,
cloudApi: import.meta.env.VITE_CLOUD_API,
cloudApi: CLOUD_API,
oidcGoogle,
clientId,
},
);

if (!res.ok) throw new Error("Failed to register device");
return redirect(import.meta.env.VITE_CLOUD_APP + `/devices/${deviceId}/setup`);
return redirect(CLOUD_APP + `/devices/${deviceId}/setup`);
};

export default function AdoptRoute() {
Expand Down
5 changes: 3 additions & 2 deletions ui/src/routes/devices.$id.deregister.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { User } from "@/hooks/stores";
import { checkAuth } from "@/main";
import Fieldset from "@components/Fieldset";
import { ChevronLeftIcon } from "@heroicons/react/16/solid";
import { CLOUD_API } from "@/ui.config";

interface LoaderData {
device: { id: string; name: string; user: { googleId: string } };
Expand All @@ -24,7 +25,7 @@ const action = async ({ request }: ActionFunctionArgs) => {
const { deviceId } = Object.fromEntries(await request.formData());

try {
const res = await fetch(`${import.meta.env.VITE_CLOUD_API}/devices/${deviceId}`, {
const res = await fetch(`${CLOUD_API}/devices/${deviceId}`, {
method: "DELETE",
credentials: "include",
headers: { "Content-Type": "application/json" },
Expand All @@ -46,7 +47,7 @@ const loader = async ({ params }: LoaderFunctionArgs) => {
const { id } = params;

try {
const res = await fetch(`${import.meta.env.VITE_CLOUD_API}/devices/${id}`, {
const res = await fetch(`${CLOUD_API}/devices/${id}`, {
method: "GET",
credentials: "include",
mode: "cors",
Expand Down
5 changes: 3 additions & 2 deletions ui/src/routes/devices.$id.rename.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { User } from "@/hooks/stores";
import { checkAuth } from "@/main";
import Fieldset from "@components/Fieldset";
import api from "../api";
import { CLOUD_API } from "@/ui.config";

interface LoaderData {
device: { id: string; name: string; user: { googleId: string } };
Expand All @@ -31,7 +32,7 @@ const action = async ({ params, request }: ActionFunctionArgs) => {
}

try {
const res = await api.PUT(`${import.meta.env.VITE_CLOUD_API}/devices/${id}`, {
const res = await api.PUT(`${CLOUD_API}/devices/${id}`, {
name,
});
if (!res.ok) {
Expand All @@ -49,7 +50,7 @@ const loader = async ({ params }: LoaderFunctionArgs) => {
const { id } = params;

try {
const res = await fetch(`${import.meta.env.VITE_CLOUD_API}/devices/${id}`, {
const res = await fetch(`${CLOUD_API}/devices/${id}`, {
method: "GET",
credentials: "include",
mode: "cors",
Expand Down
5 changes: 3 additions & 2 deletions ui/src/routes/devices.$id.setup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ import { InputFieldWithLabel } from "@components/InputField";
import { Button } from "@components/Button";
import { checkAuth } from "@/main";
import api from "../api";
import { CLOUD_API } from "@/ui.config";

const loader = async ({ params }: LoaderFunctionArgs) => {
await checkAuth();
const res = await fetch(`${import.meta.env.VITE_CLOUD_API}/devices/${params.id}`, {
const res = await fetch(`${CLOUD_API}/devices/${params.id}`, {
method: "GET",
mode: "cors",
credentials: "include",
Expand All @@ -35,7 +36,7 @@ const loader = async ({ params }: LoaderFunctionArgs) => {
const action = async ({ request }: ActionFunctionArgs) => {
// Handle form submission
const { name, id, returnTo } = Object.fromEntries(await request.formData());
const res = await api.PUT(`${import.meta.env.VITE_CLOUD_API}/devices/${id}`, { name });
const res = await api.PUT(`${CLOUD_API}/devices/${id}`, { name });

if (res.ok) {
return redirect(returnTo?.toString() ?? `/devices/${id}`);
Expand Down
13 changes: 7 additions & 6 deletions ui/src/routes/devices.$id.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { DeviceStatus } from "./welcome-local";
import FocusTrap from "focus-trap-react";
import OtherSessionConnectedModal from "@/components/OtherSessionConnectedModal";
import TerminalWrapper from "../components/Terminal";
import { CLOUD_API, SIGNAL_API } from "@/ui.config";

interface LocalLoaderResp {
authMode: "password" | "noPassword" | null;
Expand All @@ -56,12 +57,12 @@ export interface LocalDevice {

const deviceLoader = async () => {
const res = await api
.GET(`${import.meta.env.VITE_SIGNAL_API}/device/status`)
.GET(`${SIGNAL_API}/device/status`)
.then(res => res.json() as Promise<DeviceStatus>);

if (!res.isSetup) return redirect("/welcome");

const deviceRes = await api.GET(`${import.meta.env.VITE_SIGNAL_API}/device`);
const deviceRes = await api.GET(`${SIGNAL_API}/device`);
if (deviceRes.status === 401) return redirect("/login-local");
if (deviceRes.ok) {
const device = (await deviceRes.json()) as LocalDevice;
Expand All @@ -74,11 +75,11 @@ const deviceLoader = async () => {
const cloudLoader = async (params: Params<string>): Promise<CloudLoaderResp> => {
const user = await checkAuth();

const iceResp = await api.POST(`${import.meta.env.VITE_CLOUD_API}/webrtc/ice_config`);
const iceResp = await api.POST(`${CLOUD_API}/webrtc/ice_config`);
const iceConfig = await iceResp.json();

const deviceResp = await api.GET(
`${import.meta.env.VITE_CLOUD_API}/devices/${params.id}`,
`${CLOUD_API}/devices/${params.id}`,
);

if (!deviceResp.ok) {
Expand Down Expand Up @@ -142,7 +143,7 @@ export default function KvmIdRoute() {

try {
const sd = btoa(JSON.stringify(pc.localDescription));
const res = await api.POST(`${import.meta.env.VITE_SIGNAL_API}/webrtc/session`, {
const res = await api.POST(`${SIGNAL_API}/webrtc/session`, {
sd,
// When on device, we don't need to specify the device id, as it's already known
...(isOnDevice ? {} : { id: params.id }),
Expand Down Expand Up @@ -317,7 +318,7 @@ export default function KvmIdRoute() {
}

// Fire and forget
api.POST(`${import.meta.env.VITE_CLOUD_API}/webrtc/turn_activity`, {
api.POST(`${CLOUD_API}/webrtc/turn_activity`, {
bytesReceived: bytesReceivedDelta,
bytesSent: bytesSentDelta,
});
Expand Down
3 changes: 2 additions & 1 deletion ui/src/routes/devices.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { User } from "@/hooks/stores";
import EmptyCard from "@components/EmptyCard";
import { LuMonitorSmartphone } from "react-icons/lu";
import { ArrowRightIcon } from "@heroicons/react/16/solid";
import { CLOUD_API } from "@/ui.config";

interface LoaderData {
devices: { id: string; name: string; online: boolean; lastSeen: string }[];
Expand All @@ -19,7 +20,7 @@ export const loader = async () => {
const user = await checkAuth();

try {
const res = await fetch(`${import.meta.env.VITE_CLOUD_API}/devices`, {
const res = await fetch(`${CLOUD_API}/devices`, {
method: "GET",
credentials: "include",
mode: "cors",
Expand Down
7 changes: 4 additions & 3 deletions ui/src/routes/login-local.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,16 @@ import LogoWhiteIcon from "@/assets/logo-white.svg";
import api from "../api";
import { DeviceStatus } from "./welcome-local";
import ExtLink from "../components/ExtLink";
import { SIGNAL_API } from "@/ui.config";

const loader = async () => {
const res = await api
.GET(`${import.meta.env.VITE_SIGNAL_API}/device/status`)
.GET(`${SIGNAL_API}/device/status`)
.then(res => res.json() as Promise<DeviceStatus>);

if (!res.isSetup) return redirect("/welcome");

const deviceRes = await api.GET(`${import.meta.env.VITE_SIGNAL_API}/device`);
const deviceRes = await api.GET(`${SIGNAL_API}/device`);
if (deviceRes.ok) return redirect("/");
return null;
};
Expand All @@ -31,7 +32,7 @@ const action = async ({ request }: ActionFunctionArgs) => {

try {
const response = await api.POST(
`${import.meta.env.VITE_SIGNAL_API}/auth/login-local`,
`${SIGNAL_API}/auth/login-local`,
{
password,
},
Expand Down
5 changes: 3 additions & 2 deletions ui/src/routes/welcome-local.mode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import LogoWhiteIcon from "@/assets/logo-white.svg";
import { cx } from "../cva.config";
import api from "../api";
import { DeviceStatus } from "./welcome-local";
import { SIGNAL_API } from "@/ui.config";

const loader = async () => {
const res = await api
.GET(`${import.meta.env.VITE_SIGNAL_API}/device/status`)
.GET(`${SIGNAL_API}/device/status`)
.then(res => res.json() as Promise<DeviceStatus>);

if (res.isSetup) return redirect("/login-local");
Expand All @@ -30,7 +31,7 @@ const action = async ({ request }: ActionFunctionArgs) => {

if (localAuthMode === "noPassword") {
try {
await api.POST(`${import.meta.env.VITE_SIGNAL_API}/device/setup`, {
await api.POST(`${SIGNAL_API}/device/setup`, {
localAuthMode,
});
return redirect("/");
Expand Down
5 changes: 3 additions & 2 deletions ui/src/routes/welcome-local.password.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ import LogoBlueIcon from "@/assets/logo-blue.png";
import LogoWhiteIcon from "@/assets/logo-white.svg";
import api from "../api";
import { DeviceStatus } from "./welcome-local";
import { SIGNAL_API } from "@/ui.config";

const loader = async () => {
const res = await api
.GET(`${import.meta.env.VITE_SIGNAL_API}/device/status`)
.GET(`${SIGNAL_API}/device/status`)
.then(res => res.json() as Promise<DeviceStatus>);

if (res.isSetup) return redirect("/login-local");
Expand All @@ -30,7 +31,7 @@ const action = async ({ request }: ActionFunctionArgs) => {
}

try {
const response = await api.POST(`${import.meta.env.VITE_SIGNAL_API}/device/setup`, {
const response = await api.POST(`${SIGNAL_API}/device/setup`, {
localAuthMode: "password",
password,
});
Expand Down
3 changes: 2 additions & 1 deletion ui/src/routes/welcome-local.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ import LogoMark from "@/assets/logo-mark.png";
import { cx } from "cva";
import api from "../api";
import { redirect } from "react-router-dom";
import { SIGNAL_API } from "@/ui.config";

export interface DeviceStatus {
isSetup: boolean;
}

const loader = async () => {
const res = await api
.GET(`${import.meta.env.VITE_SIGNAL_API}/device/status`)
.GET(`${SIGNAL_API}/device/status`)
.then(res => res.json() as Promise<DeviceStatus>);

if (res.isSetup) return redirect("/login-local");
Expand Down
Loading