mirror of https://github.com/jetkvm/kvm.git
refactor: replace console.log with tslog
This commit is contained in:
parent
c1d771cced
commit
fc28ecb19c
|
@ -62,6 +62,7 @@ module.exports = defineConfig([{
|
||||||
allowConstantExport: true,
|
allowConstantExport: true,
|
||||||
}],
|
}],
|
||||||
|
|
||||||
|
"no-console": ["warn", {}],
|
||||||
"import/order": ["error", {
|
"import/order": ["error", {
|
||||||
groups: ["builtin", "external", "internal", "parent", "sibling"],
|
groups: ["builtin", "external", "internal", "parent", "sibling"],
|
||||||
"newlines-between": "always",
|
"newlines-between": "always",
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
"react-xtermjs": "^1.0.10",
|
"react-xtermjs": "^1.0.10",
|
||||||
"recharts": "^2.15.3",
|
"recharts": "^2.15.3",
|
||||||
"tailwind-merge": "^3.3.0",
|
"tailwind-merge": "^3.3.0",
|
||||||
|
"tslog": "^4.9.3",
|
||||||
"usehooks-ts": "^3.1.1",
|
"usehooks-ts": "^3.1.1",
|
||||||
"validator": "^13.15.0",
|
"validator": "^13.15.0",
|
||||||
"zustand": "^4.5.2"
|
"zustand": "^4.5.2"
|
||||||
|
@ -6533,6 +6534,17 @@
|
||||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||||
"license": "0BSD"
|
"license": "0BSD"
|
||||||
},
|
},
|
||||||
|
"node_modules/tslog": {
|
||||||
|
"version": "4.9.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslog/-/tslog-4.9.3.tgz",
|
||||||
|
"integrity": "sha512-oDWuGVONxhVEBtschLf2cs/Jy8i7h1T+CpdkTNWQgdAF7DhRo2G8vMCgILKe7ojdEkLhICWgI1LYSSKaJsRgcw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fullstack-build/tslog?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/type-check": {
|
"node_modules/type-check": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
"react-xtermjs": "^1.0.10",
|
"react-xtermjs": "^1.0.10",
|
||||||
"recharts": "^2.15.3",
|
"recharts": "^2.15.3",
|
||||||
"tailwind-merge": "^3.3.0",
|
"tailwind-merge": "^3.3.0",
|
||||||
|
"tslog": "^4.9.3",
|
||||||
"usehooks-ts": "^3.1.1",
|
"usehooks-ts": "^3.1.1",
|
||||||
"validator": "^13.15.0",
|
"validator": "^13.15.0",
|
||||||
"zustand": "^4.5.2"
|
"zustand": "^4.5.2"
|
||||||
|
|
|
@ -19,7 +19,7 @@ import WakeOnLanModal from "@/components/popovers/WakeOnLan/Index";
|
||||||
import MountPopopover from "@/components/popovers/MountPopover";
|
import MountPopopover from "@/components/popovers/MountPopover";
|
||||||
import ExtensionPopover from "@/components/popovers/ExtensionPopover";
|
import ExtensionPopover from "@/components/popovers/ExtensionPopover";
|
||||||
import { useDeviceUiNavigation } from "@/hooks/useAppNavigation";
|
import { useDeviceUiNavigation } from "@/hooks/useAppNavigation";
|
||||||
|
import { logger } from "@/log";
|
||||||
export default function Actionbar({
|
export default function Actionbar({
|
||||||
requestFullscreen,
|
requestFullscreen,
|
||||||
}: {
|
}: {
|
||||||
|
@ -48,7 +48,7 @@ export default function Actionbar({
|
||||||
if (!open) {
|
if (!open) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setDisableFocusTrap(false);
|
setDisableFocusTrap(false);
|
||||||
console.log("Popover is closing. Returning focus trap to video");
|
logger.info("Popover is closing. Returning focus trap to video");
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
|
||||||
import { useFeatureFlag } from "../hooks/useFeatureFlag";
|
import { logger } from "@/log";
|
||||||
|
|
||||||
|
import { useFeatureFlag } from "../hooks/useFeatureFlag";
|
||||||
export function FeatureFlag({
|
export function FeatureFlag({
|
||||||
minAppVersion,
|
minAppVersion,
|
||||||
name = "unnamed",
|
name = "unnamed",
|
||||||
|
@ -17,7 +18,7 @@ export function FeatureFlag({
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!appVersion) return;
|
if (!appVersion) return;
|
||||||
console.log(
|
logger.info(
|
||||||
`Feature '${name}' ${isEnabled ? "ENABLED" : "DISABLED"}: ` +
|
`Feature '${name}' ${isEnabled ? "ENABLED" : "DISABLED"}: ` +
|
||||||
`Current version: ${appVersion}, ` +
|
`Current version: ${appVersion}, ` +
|
||||||
`Required min version: ${minAppVersion || "N/A"}`,
|
`Required min version: ${minAppVersion || "N/A"}`,
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {
|
||||||
useVideoStore,
|
useVideoStore,
|
||||||
} from "@/hooks/stores";
|
} from "@/hooks/stores";
|
||||||
import { keys, modifiers } from "@/keyboardMappings";
|
import { keys, modifiers } from "@/keyboardMappings";
|
||||||
|
import { logger } from "@/log";
|
||||||
|
|
||||||
export default function InfoBar() {
|
export default function InfoBar() {
|
||||||
const activeKeys = useHidStore(state => state.activeKeys);
|
const activeKeys = useHidStore(state => state.activeKeys);
|
||||||
|
@ -31,9 +32,9 @@ export default function InfoBar() {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!rpcDataChannel) return;
|
if (!rpcDataChannel) return;
|
||||||
rpcDataChannel.onclose = () => console.log("rpcDataChannel has closed");
|
rpcDataChannel.onclose = () => logger.info("rpcDataChannel has closed");
|
||||||
rpcDataChannel.onerror = e =>
|
rpcDataChannel.onerror = e =>
|
||||||
console.log(`Error on DataChannel '${rpcDataChannel.label}': ${e}`);
|
logger.error(`Error on DataChannel '${rpcDataChannel.label}': ${e}`);
|
||||||
}, [rpcDataChannel]);
|
}, [rpcDataChannel]);
|
||||||
|
|
||||||
const keyboardLedState = useHidStore(state => state.keyboardLedState);
|
const keyboardLedState = useHidStore(state => state.keyboardLedState);
|
||||||
|
|
|
@ -5,6 +5,7 @@ import KeyboardAndMouseConnectedIcon from "@/assets/keyboard-and-mouse-connected
|
||||||
import LoadingSpinner from "@components/LoadingSpinner";
|
import LoadingSpinner from "@components/LoadingSpinner";
|
||||||
import StatusCard from "@components/StatusCards";
|
import StatusCard from "@components/StatusCards";
|
||||||
import { HidState } from "@/hooks/stores";
|
import { HidState } from "@/hooks/stores";
|
||||||
|
import { logger } from "@/log";
|
||||||
|
|
||||||
type USBStates = HidState["usbState"];
|
type USBStates = HidState["usbState"];
|
||||||
|
|
||||||
|
@ -67,7 +68,7 @@ export default function USBStateStatus({
|
||||||
};
|
};
|
||||||
const props = StatusCardProps[state];
|
const props = StatusCardProps[state];
|
||||||
if (!props) {
|
if (!props) {
|
||||||
console.log("Unsupported USB state: ", state);
|
logger.error("Unsupported USB state: ", { state });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import { useCallback , useEffect, useState } from "react";
|
import { useCallback , useEffect, useState } from "react";
|
||||||
|
|
||||||
|
import { logger } from "@/log";
|
||||||
|
|
||||||
import { useJsonRpc } from "../hooks/useJsonRpc";
|
import { useJsonRpc } from "../hooks/useJsonRpc";
|
||||||
import notifications from "../notifications";
|
import notifications from "../notifications";
|
||||||
import { SettingsItem } from "../routes/devices.$id.settings";
|
import { SettingsItem } from "../routes/devices.$id.settings";
|
||||||
|
@ -9,6 +11,7 @@ import { Button } from "./Button";
|
||||||
import { SelectMenuBasic } from "./SelectMenuBasic";
|
import { SelectMenuBasic } from "./SelectMenuBasic";
|
||||||
import { SettingsSectionHeader } from "./SettingsSectionHeader";
|
import { SettingsSectionHeader } from "./SettingsSectionHeader";
|
||||||
import Fieldset from "./Fieldset";
|
import Fieldset from "./Fieldset";
|
||||||
|
|
||||||
export interface USBConfig {
|
export interface USBConfig {
|
||||||
vendor_id: string;
|
vendor_id: string;
|
||||||
product_id: string;
|
product_id: string;
|
||||||
|
@ -69,7 +72,7 @@ export function UsbDeviceSetting() {
|
||||||
const syncUsbDeviceConfig = useCallback(() => {
|
const syncUsbDeviceConfig = useCallback(() => {
|
||||||
send("getUsbDevices", {}, resp => {
|
send("getUsbDevices", {}, resp => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
console.error("Failed to load USB devices:", resp.error);
|
logger.error("Failed to load USB devices:", resp.error);
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to load USB devices: ${resp.error.data || "Unknown error"}`,
|
`Failed to load USB devices: ${resp.error.data || "Unknown error"}`,
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { useMemo , useCallback , useEffect, useState } from "react";
|
import { useMemo , useCallback , useEffect, useState } from "react";
|
||||||
|
|
||||||
import { Button } from "@components/Button";
|
import { Button } from "@components/Button";
|
||||||
|
import { jsonRpcLogger, logger } from "@/log";
|
||||||
|
|
||||||
import { UsbConfigState } from "../hooks/stores";
|
import { UsbConfigState } from "../hooks/stores";
|
||||||
import { useJsonRpc } from "../hooks/useJsonRpc";
|
import { useJsonRpc } from "../hooks/useJsonRpc";
|
||||||
|
@ -96,12 +96,12 @@ export function UsbInfoSetting() {
|
||||||
const syncUsbConfigProduct = useCallback(() => {
|
const syncUsbConfigProduct = useCallback(() => {
|
||||||
send("getUsbConfig", {}, resp => {
|
send("getUsbConfig", {}, resp => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
console.error("Failed to load USB Config:", resp.error);
|
jsonRpcLogger.error("Failed to load USB Config:", resp.error);
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to load USB Config: ${resp.error.data || "Unknown error"}`,
|
`Failed to load USB Config: ${resp.error.data || "Unknown error"}`,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
console.log("syncUsbConfigProduct#getUsbConfig result:", resp.result);
|
jsonRpcLogger.info("syncUsbConfigProduct#getUsbConfig result:", resp.result);
|
||||||
const usbConfigState = resp.result as UsbConfigState;
|
const usbConfigState = resp.result as UsbConfigState;
|
||||||
const product = usbConfigs.map(u => u.value).includes(usbConfigState.product)
|
const product = usbConfigs.map(u => u.value).includes(usbConfigState.product)
|
||||||
? usbConfigState.product
|
? usbConfigState.product
|
||||||
|
@ -210,7 +210,7 @@ function USBConfigDialog({
|
||||||
const syncUsbConfig = useCallback(() => {
|
const syncUsbConfig = useCallback(() => {
|
||||||
send("getUsbConfig", {}, resp => {
|
send("getUsbConfig", {}, resp => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
console.error("Failed to load USB Config:", resp.error);
|
logger.error("Failed to load USB Config:", resp.error);
|
||||||
} else {
|
} else {
|
||||||
setUsbConfigState(resp.result as UsbConfigState);
|
setUsbConfigState(resp.result as UsbConfigState);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import InfoBar from "@components/InfoBar";
|
||||||
import useKeyboard from "@/hooks/useKeyboard";
|
import useKeyboard from "@/hooks/useKeyboard";
|
||||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
||||||
import notifications from "@/notifications";
|
import notifications from "@/notifications";
|
||||||
|
import { logger } from "@/log";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
HDMIErrorOverlay,
|
HDMIErrorOverlay,
|
||||||
|
@ -445,7 +446,7 @@ export default function WebRTCVideo() {
|
||||||
// Fix only works in chrome based browsers.
|
// Fix only works in chrome based browsers.
|
||||||
if (e.code === "Space") {
|
if (e.code === "Space") {
|
||||||
if (videoElm.current?.paused == true) {
|
if (videoElm.current?.paused == true) {
|
||||||
console.log("Force playing video");
|
logger.info("Force playing video");
|
||||||
videoElm.current?.play();
|
videoElm.current?.play();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -487,7 +488,7 @@ export default function WebRTCVideo() {
|
||||||
useEffect(
|
useEffect(
|
||||||
function updateVideoStream() {
|
function updateVideoStream() {
|
||||||
if (!mediaStream) return;
|
if (!mediaStream) return;
|
||||||
console.log("Updating video stream from mediaStream");
|
logger.info("Updating video stream from mediaStream");
|
||||||
// We set the as early as possible
|
// We set the as early as possible
|
||||||
addStreamToVideoElm(mediaStream);
|
addStreamToVideoElm(mediaStream);
|
||||||
},
|
},
|
||||||
|
|
|
@ -6,6 +6,7 @@ import Card from "@components/Card";
|
||||||
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
||||||
import notifications from "@/notifications";
|
import notifications from "@/notifications";
|
||||||
import LoadingSpinner from "@/components/LoadingSpinner";
|
import LoadingSpinner from "@/components/LoadingSpinner";
|
||||||
|
import { logger } from "@/log";
|
||||||
|
|
||||||
import { useJsonRpc } from "../../hooks/useJsonRpc";
|
import { useJsonRpc } from "../../hooks/useJsonRpc";
|
||||||
|
|
||||||
|
@ -53,7 +54,7 @@ export function ATXPowerControl() {
|
||||||
// Start long press timer
|
// Start long press timer
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
// Send long press action
|
// Send long press action
|
||||||
console.log("Sending long press ATX power action");
|
logger.info("Sending long press ATX power action");
|
||||||
send("setATXPowerAction", { action: "power-long" }, resp => {
|
send("setATXPowerAction", { action: "power-long" }, resp => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
|
@ -74,7 +75,7 @@ export function ATXPowerControl() {
|
||||||
setPowerPressTimer(null);
|
setPowerPressTimer(null);
|
||||||
|
|
||||||
// Send short press action
|
// Send short press action
|
||||||
console.log("Sending short press ATX power action");
|
logger.info("Sending short press ATX power action");
|
||||||
send("setATXPowerAction", { action: "power-short" }, resp => {
|
send("setATXPowerAction", { action: "power-short" }, resp => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
|
|
|
@ -69,7 +69,7 @@ export function SerialConsole() {
|
||||||
text="Open Console"
|
text="Open Console"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setTerminalType("serial");
|
setTerminalType("serial");
|
||||||
console.log("Opening serial console with settings: ", settings);
|
logger.info("Opening serial console with settings: ", settings);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { useHidStore, useRTCStore, useUiStore, useSettingsStore } from "@/hooks/
|
||||||
import { keys, modifiers } from "@/keyboardMappings";
|
import { keys, modifiers } from "@/keyboardMappings";
|
||||||
import { layouts, chars } from "@/keyboardLayouts";
|
import { layouts, chars } from "@/keyboardLayouts";
|
||||||
import notifications from "@/notifications";
|
import notifications from "@/notifications";
|
||||||
|
import { logger } from "@/log";
|
||||||
const hidKeyboardPayload = (keys: number[], modifier: number) => {
|
const hidKeyboardPayload = (keys: number[], modifier: number) => {
|
||||||
return { keys, modifier };
|
return { keys, modifier };
|
||||||
};
|
};
|
||||||
|
@ -95,7 +95,7 @@ export default function PasteModal() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
logger.error("Failed to paste text", error);
|
||||||
notifications.error("Failed to paste text");
|
notifications.error("Failed to paste text");
|
||||||
}
|
}
|
||||||
}, [rpcDataChannel?.readyState, send, setDisableVideoFocusTrap, setPasteMode, keyboardLayout]);
|
}, [rpcDataChannel?.readyState, send, setDisableVideoFocusTrap, setPasteMode, keyboardLayout]);
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { SettingsPageHeader } from "@components/SettingsPageheader";
|
||||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
||||||
import { useRTCStore, useUiStore } from "@/hooks/stores";
|
import { useRTCStore, useUiStore } from "@/hooks/stores";
|
||||||
import notifications from "@/notifications";
|
import notifications from "@/notifications";
|
||||||
|
import { logger } from "@/log";
|
||||||
|
|
||||||
import EmptyStateCard from "./EmptyStateCard";
|
import EmptyStateCard from "./EmptyStateCard";
|
||||||
import DeviceList, { StoredDevice } from "./DeviceList";
|
import DeviceList, { StoredDevice } from "./DeviceList";
|
||||||
|
@ -56,7 +57,7 @@ export default function WakeOnLanModal() {
|
||||||
if ("result" in resp) {
|
if ("result" in resp) {
|
||||||
setStoredDevices(resp.result as StoredDevice[]);
|
setStoredDevices(resp.result as StoredDevice[]);
|
||||||
} else {
|
} else {
|
||||||
console.error("Failed to load Wake-on-LAN devices:", resp.error);
|
logger.error("Failed to load Wake-on-LAN devices:", resp.error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, [send, setStoredDevices]);
|
}, [send, setStoredDevices]);
|
||||||
|
@ -72,7 +73,7 @@ export default function WakeOnLanModal() {
|
||||||
|
|
||||||
send("setWakeOnLanDevices", { params: { devices: updatedDevices } }, resp => {
|
send("setWakeOnLanDevices", { params: { devices: updatedDevices } }, resp => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
console.error("Failed to update Wake-on-LAN devices:", resp.error);
|
logger.error("Failed to update Wake-on-LAN devices:", resp.error);
|
||||||
} else {
|
} else {
|
||||||
syncStoredDevices();
|
syncStoredDevices();
|
||||||
}
|
}
|
||||||
|
@ -85,10 +86,10 @@ export default function WakeOnLanModal() {
|
||||||
(name: string, macAddress: string) => {
|
(name: string, macAddress: string) => {
|
||||||
if (!name || !macAddress) return;
|
if (!name || !macAddress) return;
|
||||||
const updatedDevices = [...storedDevices, { name, macAddress }];
|
const updatedDevices = [...storedDevices, { name, macAddress }];
|
||||||
console.log("updatedDevices", updatedDevices);
|
logger.info("updatedDevices", updatedDevices);
|
||||||
send("setWakeOnLanDevices", { params: { devices: updatedDevices } }, resp => {
|
send("setWakeOnLanDevices", { params: { devices: updatedDevices } }, resp => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
console.error("Failed to add Wake-on-LAN device:", resp.error);
|
logger.error("Failed to add Wake-on-LAN device:", { error: resp.error });
|
||||||
setAddDeviceErrorMessage("Failed to add device");
|
setAddDeviceErrorMessage("Failed to add device");
|
||||||
} else {
|
} else {
|
||||||
setShowAddForm(false);
|
setShowAddForm(false);
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {
|
||||||
MAX_TOTAL_MACROS,
|
MAX_TOTAL_MACROS,
|
||||||
MAX_KEYS_PER_STEP,
|
MAX_KEYS_PER_STEP,
|
||||||
} from "@/constants/macros";
|
} from "@/constants/macros";
|
||||||
|
import { logger } from "@/log";
|
||||||
|
|
||||||
// Define the JsonRpc types for better type checking
|
// Define the JsonRpc types for better type checking
|
||||||
interface JsonRpcResponse {
|
interface JsonRpcResponse {
|
||||||
|
@ -744,7 +745,7 @@ export const useNetworkStateStore = create<NetworkState>((set, get) => ({
|
||||||
setDhcpLeaseExpiry: (expiry: Date) => {
|
setDhcpLeaseExpiry: (expiry: Date) => {
|
||||||
const lease = get().dhcp_lease;
|
const lease = get().dhcp_lease;
|
||||||
if (!lease) {
|
if (!lease) {
|
||||||
console.warn("No lease found");
|
logger.warn("No lease found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -807,7 +808,7 @@ export const useMacrosStore = create<MacrosState>((set, get) => ({
|
||||||
|
|
||||||
const { sendFn } = get();
|
const { sendFn } = get();
|
||||||
if (!sendFn) {
|
if (!sendFn) {
|
||||||
console.warn("JSON-RPC send function not available.");
|
logger.warn("JSON-RPC send function not available.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -817,7 +818,7 @@ export const useMacrosStore = create<MacrosState>((set, get) => ({
|
||||||
await new Promise<void>((resolve, reject) => {
|
await new Promise<void>((resolve, reject) => {
|
||||||
sendFn("getKeyboardMacros", {}, response => {
|
sendFn("getKeyboardMacros", {}, response => {
|
||||||
if (response.error) {
|
if (response.error) {
|
||||||
console.error("Error loading macros:", response.error);
|
logger.error("Error loading macros:", response.error);
|
||||||
reject(new Error(response.error.message));
|
reject(new Error(response.error.message));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -842,7 +843,7 @@ export const useMacrosStore = create<MacrosState>((set, get) => ({
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to load macros:", error);
|
logger.error("Failed to load macros:", error);
|
||||||
} finally {
|
} finally {
|
||||||
set({ loading: false });
|
set({ loading: false });
|
||||||
}
|
}
|
||||||
|
@ -851,18 +852,18 @@ export const useMacrosStore = create<MacrosState>((set, get) => ({
|
||||||
saveMacros: async (macros: KeySequence[]) => {
|
saveMacros: async (macros: KeySequence[]) => {
|
||||||
const { sendFn } = get();
|
const { sendFn } = get();
|
||||||
if (!sendFn) {
|
if (!sendFn) {
|
||||||
console.warn("JSON-RPC send function not available.");
|
logger.warn("JSON-RPC send function not available.");
|
||||||
throw new Error("JSON-RPC send function not available");
|
throw new Error("JSON-RPC send function not available");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (macros.length > MAX_TOTAL_MACROS) {
|
if (macros.length > MAX_TOTAL_MACROS) {
|
||||||
console.error(`Cannot save: exceeded maximum of ${MAX_TOTAL_MACROS} macros`);
|
logger.error(`Cannot save: exceeded maximum of ${MAX_TOTAL_MACROS} macros`);
|
||||||
throw new Error(`Cannot save: exceeded maximum of ${MAX_TOTAL_MACROS} macros`);
|
throw new Error(`Cannot save: exceeded maximum of ${MAX_TOTAL_MACROS} macros`);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const macro of macros) {
|
for (const macro of macros) {
|
||||||
if (macro.steps.length > MAX_STEPS_PER_MACRO) {
|
if (macro.steps.length > MAX_STEPS_PER_MACRO) {
|
||||||
console.error(
|
logger.error(
|
||||||
`Cannot save: macro "${macro.name}" exceeds maximum of ${MAX_STEPS_PER_MACRO} steps`,
|
`Cannot save: macro "${macro.name}" exceeds maximum of ${MAX_STEPS_PER_MACRO} steps`,
|
||||||
);
|
);
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
@ -873,7 +874,7 @@ export const useMacrosStore = create<MacrosState>((set, get) => ({
|
||||||
for (let i = 0; i < macro.steps.length; i++) {
|
for (let i = 0; i < macro.steps.length; i++) {
|
||||||
const step = macro.steps[i];
|
const step = macro.steps[i];
|
||||||
if (step.keys && step.keys.length > MAX_KEYS_PER_STEP) {
|
if (step.keys && step.keys.length > MAX_KEYS_PER_STEP) {
|
||||||
console.error(
|
logger.error(
|
||||||
`Cannot save: macro "${macro.name}" step ${i + 1} exceeds maximum of ${MAX_KEYS_PER_STEP} keys`,
|
`Cannot save: macro "${macro.name}" step ${i + 1} exceeds maximum of ${MAX_KEYS_PER_STEP} keys`,
|
||||||
);
|
);
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
@ -902,7 +903,7 @@ export const useMacrosStore = create<MacrosState>((set, get) => ({
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.error) {
|
if (response.error) {
|
||||||
console.error("Error saving macros:", response.error);
|
logger.error("Error saving macros:", response.error);
|
||||||
const errorMessage =
|
const errorMessage =
|
||||||
typeof response.error.data === "string"
|
typeof response.error.data === "string"
|
||||||
? response.error.data
|
? response.error.data
|
||||||
|
@ -913,7 +914,7 @@ export const useMacrosStore = create<MacrosState>((set, get) => ({
|
||||||
// Only update the store if the request was successful
|
// Only update the store if the request was successful
|
||||||
set({ macros: macrosWithSortOrder });
|
set({ macros: macrosWithSortOrder });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to save macros:", error);
|
logger.error("Failed to save macros:", error);
|
||||||
throw error;
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
set({ loading: false });
|
set({ loading: false });
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import { useNavigate, useParams, NavigateOptions } from "react-router-dom";
|
import { useNavigate, useParams, NavigateOptions } from "react-router-dom";
|
||||||
import { useCallback, useMemo } from "react";
|
import { useCallback, useMemo } from "react";
|
||||||
|
|
||||||
|
import { logger } from "@/log";
|
||||||
|
|
||||||
import { isOnDevice } from "../main";
|
import { isOnDevice } from "../main";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,7 +23,7 @@ export function getDeviceUiPath(path: string, deviceId?: string): string {
|
||||||
return normalizedPath;
|
return normalizedPath;
|
||||||
} else {
|
} else {
|
||||||
if (!deviceId) {
|
if (!deviceId) {
|
||||||
console.error("No device ID provided when generating path in cloud mode");
|
logger.error("No device ID provided when generating path in cloud mode");
|
||||||
throw new Error("Device ID is required for cloud mode path generation");
|
throw new Error("Device ID is required for cloud mode path generation");
|
||||||
}
|
}
|
||||||
return `/devices/${deviceId}${normalizedPath}`;
|
return `/devices/${deviceId}${normalizedPath}`;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { useCallback, useEffect } from "react";
|
import { useCallback, useEffect } from "react";
|
||||||
|
|
||||||
import { useRTCStore } from "@/hooks/stores";
|
import { useRTCStore } from "@/hooks/stores";
|
||||||
|
import { jsonRpcLogger } from "@/log";
|
||||||
export interface JsonRpcRequest {
|
export interface JsonRpcRequest {
|
||||||
jsonrpc: string;
|
jsonrpc: string;
|
||||||
method: string;
|
method: string;
|
||||||
|
@ -61,7 +61,7 @@ export function useJsonRpc(onRequest?: (payload: JsonRpcRequest) => void) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("error" in payload) console.error(payload.error);
|
if ("error" in payload) jsonRpcLogger.error(payload.error);
|
||||||
if (!payload.id) return;
|
if (!payload.id) return;
|
||||||
|
|
||||||
const callback = callbackStore.get(payload.id);
|
const callback = callbackStore.get(payload.id);
|
||||||
|
|
|
@ -16,6 +16,7 @@ import { User } from "@/hooks/stores";
|
||||||
import { checkAuth } from "@/main";
|
import { checkAuth } from "@/main";
|
||||||
import Fieldset from "@components/Fieldset";
|
import Fieldset from "@components/Fieldset";
|
||||||
import { CLOUD_API } from "@/ui.config";
|
import { CLOUD_API } from "@/ui.config";
|
||||||
|
import { logger } from "@/log";
|
||||||
|
|
||||||
interface LoaderData {
|
interface LoaderData {
|
||||||
device: { id: string; name: string; user: { googleId: string } };
|
device: { id: string; name: string; user: { googleId: string } };
|
||||||
|
@ -37,7 +38,7 @@ const action = async ({ request }: ActionFunctionArgs) => {
|
||||||
return { message: "There was an error renaming your device. Please try again." };
|
return { message: "There was an error renaming your device. Please try again." };
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
logger.error("Error deregistering device", e);
|
||||||
return { message: "There was an error renaming your device. Please try again." };
|
return { message: "There was an error renaming your device. Please try again." };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +62,7 @@ const loader = async ({ params }: LoaderFunctionArgs) => {
|
||||||
|
|
||||||
return { device, user };
|
return { device, user };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
logger.error("Error deregistering device", e);
|
||||||
return { devices: [] };
|
return { devices: [] };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,6 +26,7 @@ import ArchIcon from "@/assets/arch-icon.png";
|
||||||
import NetBootIcon from "@/assets/netboot-icon.svg";
|
import NetBootIcon from "@/assets/netboot-icon.svg";
|
||||||
import Fieldset from "@/components/Fieldset";
|
import Fieldset from "@/components/Fieldset";
|
||||||
import { DEVICE_API } from "@/ui.config";
|
import { DEVICE_API } from "@/ui.config";
|
||||||
|
import { logger } from "@/log";
|
||||||
|
|
||||||
import { useJsonRpc } from "../hooks/useJsonRpc";
|
import { useJsonRpc } from "../hooks/useJsonRpc";
|
||||||
import notifications from "../notifications";
|
import notifications from "../notifications";
|
||||||
|
@ -86,7 +87,7 @@ export function Dialog({ onClose }: { onClose: () => void }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleUrlMount(url: string, mode: RemoteVirtualMediaState["mode"]) {
|
function handleUrlMount(url: string, mode: RemoteVirtualMediaState["mode"]) {
|
||||||
console.log(`Mounting ${url} as ${mode}`);
|
logger.info(`Mounting ${url} as ${mode}`);
|
||||||
|
|
||||||
setMountInProgress(true);
|
setMountInProgress(true);
|
||||||
send("mountWithHTTP", { url, mode }, async resp => {
|
send("mountWithHTTP", { url, mode }, async resp => {
|
||||||
|
@ -105,7 +106,7 @@ export function Dialog({ onClose }: { onClose: () => void }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleStorageMount(fileName: string, mode: RemoteVirtualMediaState["mode"]) {
|
function handleStorageMount(fileName: string, mode: RemoteVirtualMediaState["mode"]) {
|
||||||
console.log(`Mounting ${fileName} as ${mode}`);
|
logger.info(`Mounting ${fileName} as ${mode}`);
|
||||||
|
|
||||||
setMountInProgress(true);
|
setMountInProgress(true);
|
||||||
send("mountWithStorage", { filename: fileName, mode }, async resp => {
|
send("mountWithStorage", { filename: fileName, mode }, async resp => {
|
||||||
|
@ -132,7 +133,7 @@ export function Dialog({ onClose }: { onClose: () => void }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleBrowserMount(file: File, mode: RemoteVirtualMediaState["mode"]) {
|
function handleBrowserMount(file: File, mode: RemoteVirtualMediaState["mode"]) {
|
||||||
console.log(`Mounting ${file.name} as ${mode}`);
|
logger.info(`Mounting ${file.name} as ${mode}`);
|
||||||
|
|
||||||
setMountInProgress(true);
|
setMountInProgress(true);
|
||||||
send(
|
send(
|
||||||
|
@ -419,7 +420,7 @@ function BrowserFileView({
|
||||||
|
|
||||||
const handleMount = () => {
|
const handleMount = () => {
|
||||||
if (selectedFile) {
|
if (selectedFile) {
|
||||||
console.log(`Mounting ${selectedFile.name} as ${setUsbMode}`);
|
logger.info(`Mounting ${selectedFile.name} as ${setUsbMode}`);
|
||||||
onMountFile(selectedFile, usbMode);
|
onMountFile(selectedFile, usbMode);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -756,7 +757,7 @@ function DeviceFileView({
|
||||||
}, [syncStorage]);
|
}, [syncStorage]);
|
||||||
|
|
||||||
function handleDeleteFile(file: { name: string; size: string; createdAt: string }) {
|
function handleDeleteFile(file: { name: string; size: string; createdAt: string }) {
|
||||||
console.log("Deleting file:", file);
|
logger.info("Deleting file:", file);
|
||||||
send("deleteStorageFile", { filename: file.name }, res => {
|
send("deleteStorageFile", { filename: file.name }, res => {
|
||||||
if ("error" in res) {
|
if ("error" in res) {
|
||||||
notifications.error(`Error deleting file: ${res.error}`);
|
notifications.error(`Error deleting file: ${res.error}`);
|
||||||
|
@ -986,6 +987,8 @@ function UploadFileView({
|
||||||
onCancelUpload: () => void;
|
onCancelUpload: () => void;
|
||||||
incompleteFileName?: string;
|
incompleteFileName?: string;
|
||||||
}) {
|
}) {
|
||||||
|
const l = logger.getSubLogger({ name: "file-upload" });
|
||||||
|
|
||||||
const [uploadState, setUploadState] = useState<"idle" | "uploading" | "success">(
|
const [uploadState, setUploadState] = useState<"idle" | "uploading" | "success">(
|
||||||
"idle",
|
"idle",
|
||||||
);
|
);
|
||||||
|
@ -1002,7 +1005,7 @@ function UploadFileView({
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const ref = rtcDataChannelRef.current;
|
const ref = rtcDataChannelRef.current;
|
||||||
return () => {
|
return () => {
|
||||||
console.log("unmounting");
|
logger.info("unmounting");
|
||||||
if (ref) {
|
if (ref) {
|
||||||
ref.onopen = null;
|
ref.onopen = null;
|
||||||
ref.onerror = null;
|
ref.onerror = null;
|
||||||
|
@ -1023,10 +1026,10 @@ function UploadFileView({
|
||||||
.peerConnection?.createDataChannel(dataChannel);
|
.peerConnection?.createDataChannel(dataChannel);
|
||||||
|
|
||||||
if (!rtcDataChannel) {
|
if (!rtcDataChannel) {
|
||||||
console.error("Failed to create data channel for file upload");
|
l.error("Failed to create data channel for file upload");
|
||||||
notifications.error("Failed to create data channel for file upload");
|
notifications.error("Failed to create data channel for file upload");
|
||||||
setUploadState("idle");
|
setUploadState("idle");
|
||||||
console.log("Upload state set to 'idle'");
|
l.info("Upload state set to 'idle'");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1072,7 +1075,7 @@ function UploadFileView({
|
||||||
lastUploadedBytes = AlreadyUploadedBytes;
|
lastUploadedBytes = AlreadyUploadedBytes;
|
||||||
lastUpdateTime = now;
|
lastUpdateTime = now;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Error processing RTC Data channel message:", e);
|
l.error("Error processing RTC Data channel message:", e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1099,24 +1102,24 @@ function UploadFileView({
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += buffer.byteLength;
|
offset += buffer.byteLength;
|
||||||
console.log(`Chunk sent: ${offset} / ${file.size} bytes`);
|
l.info(`Chunk sent: ${offset} / ${file.size} bytes`);
|
||||||
sendNextChunk();
|
sendNextChunk();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
sendNextChunk();
|
sendNextChunk();
|
||||||
rtcDataChannel.onbufferedamountlow = () => {
|
rtcDataChannel.onbufferedamountlow = () => {
|
||||||
console.log("RTC Data channel buffered amount low");
|
l.info("RTC Data channel buffered amount low");
|
||||||
pauseSending = false; // Now the data channel is ready to send more data
|
pauseSending = false; // Now the data channel is ready to send more data
|
||||||
sendNextChunk();
|
sendNextChunk();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
rtcDataChannel.onerror = error => {
|
rtcDataChannel.onerror = error => {
|
||||||
console.error("RTC Data channel error:", error);
|
l.error("RTC Data channel error:", error);
|
||||||
notifications.error(`Upload failed: ${error}`);
|
notifications.error(`Upload failed: ${error}`);
|
||||||
setUploadState("idle");
|
setUploadState("idle");
|
||||||
console.log("Upload state set to 'idle'");
|
l.info("Upload state set to 'idle'");
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1169,14 +1172,14 @@ function UploadFileView({
|
||||||
if (xhr.status === 200) {
|
if (xhr.status === 200) {
|
||||||
setUploadState("success");
|
setUploadState("success");
|
||||||
} else {
|
} else {
|
||||||
console.error("Upload error:", xhr.statusText);
|
l.error("Upload error:", xhr.statusText);
|
||||||
setUploadError(xhr.statusText);
|
setUploadError(xhr.statusText);
|
||||||
setUploadState("idle");
|
setUploadState("idle");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
xhr.onerror = () => {
|
xhr.onerror = () => {
|
||||||
console.error("XHR error:", xhr.statusText);
|
l.error("XHR error:", xhr.statusText);
|
||||||
setUploadError(xhr.statusText);
|
setUploadError(xhr.statusText);
|
||||||
setUploadState("idle");
|
setUploadState("idle");
|
||||||
};
|
};
|
||||||
|
@ -1205,19 +1208,19 @@ function UploadFileView({
|
||||||
}
|
}
|
||||||
|
|
||||||
setFileError(null);
|
setFileError(null);
|
||||||
console.log(`File selected: ${file.name}, size: ${file.size} bytes`);
|
l.info(`File selected: ${file.name}, size: ${file.size} bytes`);
|
||||||
setUploadedFileName(file.name);
|
setUploadedFileName(file.name);
|
||||||
setUploadedFileSize(file.size);
|
setUploadedFileSize(file.size);
|
||||||
setUploadState("uploading");
|
setUploadState("uploading");
|
||||||
console.log("Upload state set to 'uploading'");
|
l.info("Upload state set to 'uploading'");
|
||||||
|
|
||||||
send("startStorageFileUpload", { filename: file.name, size: file.size }, resp => {
|
send("startStorageFileUpload", { filename: file.name, size: file.size }, resp => {
|
||||||
console.log("startStorageFileUpload response:", resp);
|
l.info("startStorageFileUpload response:", resp);
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
console.error("Upload error:", resp.error.message);
|
l.error("Upload error:", resp.error.message);
|
||||||
setUploadError(resp.error.data || resp.error.message);
|
setUploadError(resp.error.data || resp.error.message);
|
||||||
setUploadState("idle");
|
setUploadState("idle");
|
||||||
console.log("Upload state set to 'idle'");
|
l.info("Upload state set to 'idle'");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1226,7 +1229,7 @@ function UploadFileView({
|
||||||
dataChannel: string;
|
dataChannel: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log(
|
l.info(
|
||||||
`Already uploaded bytes: ${alreadyUploadedBytes}, Data channel: ${dataChannel}`,
|
`Already uploaded bytes: ${alreadyUploadedBytes}, Data channel: ${dataChannel}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import { User } from "@/hooks/stores";
|
||||||
import { checkAuth } from "@/main";
|
import { checkAuth } from "@/main";
|
||||||
import Fieldset from "@components/Fieldset";
|
import Fieldset from "@components/Fieldset";
|
||||||
import { CLOUD_API } from "@/ui.config";
|
import { CLOUD_API } from "@/ui.config";
|
||||||
|
import { logger } from "@/log";
|
||||||
|
|
||||||
import api from "../api";
|
import api from "../api";
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ const action = async ({ params, request }: ActionFunctionArgs) => {
|
||||||
return { message: "There was an error renaming your device. Please try again." };
|
return { message: "There was an error renaming your device. Please try again." };
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
logger.error("Error renaming device", e);
|
||||||
return { message: "There was an error renaming your device. Please try again." };
|
return { message: "There was an error renaming your device. Please try again." };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +66,7 @@ const loader = async ({ params }: LoaderFunctionArgs) => {
|
||||||
|
|
||||||
return { device, user };
|
return { device, user };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
logger.error("Error renaming device", e);
|
||||||
return { devices: [] };
|
return { devices: [] };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,6 +15,7 @@ import { DEVICE_API } from "@/ui.config";
|
||||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
||||||
import { isOnDevice } from "@/main";
|
import { isOnDevice } from "@/main";
|
||||||
import { TextAreaWithLabel } from "@components/TextArea";
|
import { TextAreaWithLabel } from "@components/TextArea";
|
||||||
|
import { logger } from "@/log";
|
||||||
|
|
||||||
import { LocalDevice } from "./devices.$id";
|
import { LocalDevice } from "./devices.$id";
|
||||||
import { SettingsItem } from "./devices.$id.settings";
|
import { SettingsItem } from "./devices.$id.settings";
|
||||||
|
@ -57,7 +58,7 @@ export default function SettingsAccessIndexRoute() {
|
||||||
|
|
||||||
const getCloudState = useCallback(() => {
|
const getCloudState = useCallback(() => {
|
||||||
send("getCloudState", {}, resp => {
|
send("getCloudState", {}, resp => {
|
||||||
if ("error" in resp) return console.error(resp.error);
|
if ("error" in resp) return logger.error("Error getting cloud state", resp.error);
|
||||||
const cloudState = resp.result as CloudState;
|
const cloudState = resp.result as CloudState;
|
||||||
setAdopted(cloudState.connected);
|
setAdopted(cloudState.connected);
|
||||||
setCloudApiUrl(cloudState.url);
|
setCloudApiUrl(cloudState.url);
|
||||||
|
@ -78,7 +79,7 @@ export default function SettingsAccessIndexRoute() {
|
||||||
|
|
||||||
const getTLSState = useCallback(() => {
|
const getTLSState = useCallback(() => {
|
||||||
send("getTLSState", {}, resp => {
|
send("getTLSState", {}, resp => {
|
||||||
if ("error" in resp) return console.error(resp.error);
|
if ("error" in resp) return logger.error("Error getting TLS state", resp.error);
|
||||||
const tlsState = resp.result as TLSState;
|
const tlsState = resp.result as TLSState;
|
||||||
|
|
||||||
setTlsMode(tlsState.mode);
|
setTlsMode(tlsState.mode);
|
||||||
|
@ -199,7 +200,7 @@ export default function SettingsAccessIndexRoute() {
|
||||||
getTLSState();
|
getTLSState();
|
||||||
|
|
||||||
send("getDeviceID", {}, async resp => {
|
send("getDeviceID", {}, async resp => {
|
||||||
if ("error" in resp) return console.error(resp.error);
|
if ("error" in resp) return logger.error("Error getting device ID", resp.error);
|
||||||
setDeviceId(resp.result as string);
|
setDeviceId(resp.result as string);
|
||||||
});
|
});
|
||||||
}, [send, getCloudState, getTLSState]);
|
}, [send, getCloudState, getTLSState]);
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { InputFieldWithLabel } from "@/components/InputField";
|
||||||
import api from "@/api";
|
import api from "@/api";
|
||||||
import { useLocalAuthModalStore } from "@/hooks/stores";
|
import { useLocalAuthModalStore } from "@/hooks/stores";
|
||||||
import { useDeviceUiNavigation } from "@/hooks/useAppNavigation";
|
import { useDeviceUiNavigation } from "@/hooks/useAppNavigation";
|
||||||
|
import { logger } from "@/log";
|
||||||
|
|
||||||
export default function SecurityAccessLocalAuthRoute() {
|
export default function SecurityAccessLocalAuthRoute() {
|
||||||
const { setModalView } = useLocalAuthModalStore();
|
const { setModalView } = useLocalAuthModalStore();
|
||||||
|
@ -54,7 +55,7 @@ export function Dialog({ onClose }: { onClose: () => void }) {
|
||||||
setError(data.error || "An error occurred while setting the password");
|
setError(data.error || "An error occurred while setting the password");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
logger.error("An error occurred while setting the password", error);
|
||||||
setError("An error occurred while setting the password");
|
setError("An error occurred while setting the password");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -94,7 +95,7 @@ export function Dialog({ onClose }: { onClose: () => void }) {
|
||||||
setError(data.error || "An error occurred while changing the password");
|
setError(data.error || "An error occurred while changing the password");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
logger.error("An error occurred while changing the password", error);
|
||||||
setError("An error occurred while changing the password");
|
setError("An error occurred while changing the password");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -116,7 +117,7 @@ export function Dialog({ onClose }: { onClose: () => void }) {
|
||||||
setError(data.error || "An error occurred while disabling the password");
|
setError(data.error || "An error occurred while disabling the password");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
logger.error("An error occurred while disabling the password", error);
|
||||||
setError("An error occurred while disabling the password");
|
setError("An error occurred while disabling the password");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { UpdateState, useDeviceStore, useUpdateStore } from "@/hooks/stores";
|
||||||
import notifications from "@/notifications";
|
import notifications from "@/notifications";
|
||||||
import LoadingSpinner from "@/components/LoadingSpinner";
|
import LoadingSpinner from "@/components/LoadingSpinner";
|
||||||
import { useDeviceUiNavigation } from "@/hooks/useAppNavigation";
|
import { useDeviceUiNavigation } from "@/hooks/useAppNavigation";
|
||||||
|
import { logger } from "@/log";
|
||||||
|
|
||||||
export default function SettingsGeneralUpdateRoute() {
|
export default function SettingsGeneralUpdateRoute() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
@ -184,7 +185,7 @@ function LoadingState({
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
if (!signal.aborted) {
|
if (!signal.aborted) {
|
||||||
console.error("LoadingState: Error fetching version info", error);
|
logger.error("LoadingState: Error fetching version info", error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -240,7 +241,7 @@ function UpdatingDeviceState({
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(
|
logger.info(
|
||||||
`For ${type}:\n` +
|
`For ${type}:\n` +
|
||||||
` Download Progress: ${downloadProgress}% (${otaState[`${type}DownloadProgress`]})\n` +
|
` Download Progress: ${downloadProgress}% (${otaState[`${type}DownloadProgress`]})\n` +
|
||||||
` Update Progress: ${updateProgress}% (${otaState[`${type}UpdateProgress`]})\n` +
|
` Update Progress: ${updateProgress}% (${otaState[`${type}UpdateProgress`]})\n` +
|
||||||
|
|
|
@ -22,6 +22,7 @@ import { SettingsPageHeader } from "@/components/SettingsPageheader";
|
||||||
import Fieldset from "@/components/Fieldset";
|
import Fieldset from "@/components/Fieldset";
|
||||||
import { ConfirmDialog } from "@/components/ConfirmDialog";
|
import { ConfirmDialog } from "@/components/ConfirmDialog";
|
||||||
import notifications from "@/notifications";
|
import notifications from "@/notifications";
|
||||||
|
import { logger } from "@/log";
|
||||||
|
|
||||||
import Ipv6NetworkCard from "../components/Ipv6NetworkCard";
|
import Ipv6NetworkCard from "../components/Ipv6NetworkCard";
|
||||||
import EmptyCard from "../components/EmptyCard";
|
import EmptyCard from "../components/EmptyCard";
|
||||||
|
@ -29,7 +30,6 @@ import AutoHeight from "../components/AutoHeight";
|
||||||
import DhcpLeaseCard from "../components/DhcpLeaseCard";
|
import DhcpLeaseCard from "../components/DhcpLeaseCard";
|
||||||
|
|
||||||
import { SettingsItem } from "./devices.$id.settings";
|
import { SettingsItem } from "./devices.$id.settings";
|
||||||
|
|
||||||
dayjs.extend(relativeTime);
|
dayjs.extend(relativeTime);
|
||||||
|
|
||||||
const defaultNetworkSettings: NetworkSettings = {
|
const defaultNetworkSettings: NetworkSettings = {
|
||||||
|
@ -105,7 +105,7 @@ export default function SettingsNetworkRoute() {
|
||||||
setNetworkSettingsLoaded(false);
|
setNetworkSettingsLoaded(false);
|
||||||
send("getNetworkSettings", {}, resp => {
|
send("getNetworkSettings", {}, resp => {
|
||||||
if ("error" in resp) return;
|
if ("error" in resp) return;
|
||||||
console.log(resp.result);
|
logger.trace("getNetworkSettings result:", resp.result);
|
||||||
setNetworkSettings(resp.result as NetworkSettings);
|
setNetworkSettings(resp.result as NetworkSettings);
|
||||||
|
|
||||||
if (!firstNetworkSettings.current) {
|
if (!firstNetworkSettings.current) {
|
||||||
|
@ -118,7 +118,7 @@ export default function SettingsNetworkRoute() {
|
||||||
const getNetworkState = useCallback(() => {
|
const getNetworkState = useCallback(() => {
|
||||||
send("getNetworkState", {}, resp => {
|
send("getNetworkState", {}, resp => {
|
||||||
if ("error" in resp) return;
|
if ("error" in resp) return;
|
||||||
console.log(resp.result);
|
logger.trace("getNetworkState result:", resp.result);
|
||||||
setNetworkState(resp.result as NetworkState);
|
setNetworkState(resp.result as NetworkState);
|
||||||
});
|
});
|
||||||
}, [send, setNetworkState]);
|
}, [send, setNetworkState]);
|
||||||
|
|
|
@ -20,11 +20,11 @@ import { LinkButton } from "@/components/Button";
|
||||||
import LoadingSpinner from "@/components/LoadingSpinner";
|
import LoadingSpinner from "@/components/LoadingSpinner";
|
||||||
import { useUiStore } from "@/hooks/stores";
|
import { useUiStore } from "@/hooks/stores";
|
||||||
import useKeyboard from "@/hooks/useKeyboard";
|
import useKeyboard from "@/hooks/useKeyboard";
|
||||||
|
import { logger } from "@/log";
|
||||||
|
|
||||||
import { FeatureFlag } from "../components/FeatureFlag";
|
import { FeatureFlag } from "../components/FeatureFlag";
|
||||||
import { cx } from "../cva.config";
|
import { cx } from "../cva.config";
|
||||||
|
|
||||||
|
|
||||||
/* TODO: Migrate to using URLs instead of the global state. To simplify the refactoring, we'll keep the global state for now. */
|
/* TODO: Migrate to using URLs instead of the global state. To simplify the refactoring, we'll keep the global state for now. */
|
||||||
export default function SettingsRoute() {
|
export default function SettingsRoute() {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
@ -73,7 +73,7 @@ export default function SettingsRoute() {
|
||||||
// For some reason, the focus trap is not disabled immediately
|
// For some reason, the focus trap is not disabled immediately
|
||||||
// so we need to blur the active element
|
// so we need to blur the active element
|
||||||
(document.activeElement as HTMLElement)?.blur();
|
(document.activeElement as HTMLElement)?.blur();
|
||||||
console.log("Just disabled focus trap");
|
logger.info("Just disabled focus trap");
|
||||||
}, 300);
|
}, 300);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
|
|
@ -28,6 +28,7 @@ import {
|
||||||
useNetworkStateStore,
|
useNetworkStateStore,
|
||||||
User,
|
User,
|
||||||
useRTCStore,
|
useRTCStore,
|
||||||
|
useSettingsStore,
|
||||||
useUiStore,
|
useUiStore,
|
||||||
useUpdateStore,
|
useUpdateStore,
|
||||||
useVideoStore,
|
useVideoStore,
|
||||||
|
@ -40,6 +41,7 @@ import ConnectionStatsSidebar from "@/components/sidebar/connectionStats";
|
||||||
import { JsonRpcRequest, useJsonRpc } from "@/hooks/useJsonRpc";
|
import { JsonRpcRequest, useJsonRpc } from "@/hooks/useJsonRpc";
|
||||||
import Terminal from "@components/Terminal";
|
import Terminal from "@components/Terminal";
|
||||||
import { CLOUD_API, DEVICE_API } from "@/ui.config";
|
import { CLOUD_API, DEVICE_API } from "@/ui.config";
|
||||||
|
import { logger, enableDebugMode, disableDebugMode } from "@/log";
|
||||||
|
|
||||||
import UpdateInProgressStatusCard from "../components/UpdateInProgressStatusCard";
|
import UpdateInProgressStatusCard from "../components/UpdateInProgressStatusCard";
|
||||||
import api from "../api";
|
import api from "../api";
|
||||||
|
@ -130,6 +132,16 @@ export default function KvmIdRoute() {
|
||||||
const sidebarView = useUiStore(state => state.sidebarView);
|
const sidebarView = useUiStore(state => state.sidebarView);
|
||||||
const [queryParams, setQueryParams] = useSearchParams();
|
const [queryParams, setQueryParams] = useSearchParams();
|
||||||
|
|
||||||
|
// Enable dev mode if the user is in debug mode
|
||||||
|
const isDebugMode = useSettingsStore(state => state.debugMode);
|
||||||
|
useEffect(() => {
|
||||||
|
if (isDebugMode) {
|
||||||
|
enableDebugMode();
|
||||||
|
} else {
|
||||||
|
disableDebugMode();
|
||||||
|
}
|
||||||
|
}, [isDebugMode]);
|
||||||
|
|
||||||
const setIsTurnServerInUse = useRTCStore(state => state.setTurnServerInUse);
|
const setIsTurnServerInUse = useRTCStore(state => state.setTurnServerInUse);
|
||||||
const peerConnection = useRTCStore(state => state.peerConnection);
|
const peerConnection = useRTCStore(state => state.peerConnection);
|
||||||
const setPeerConnectionState = useRTCStore(state => state.setPeerConnectionState);
|
const setPeerConnectionState = useRTCStore(state => state.setPeerConnectionState);
|
||||||
|
@ -151,7 +163,7 @@ export default function KvmIdRoute() {
|
||||||
const [loadingMessage, setLoadingMessage] = useState("Connecting to device...");
|
const [loadingMessage, setLoadingMessage] = useState("Connecting to device...");
|
||||||
const cleanupAndStopReconnecting = useCallback(
|
const cleanupAndStopReconnecting = useCallback(
|
||||||
function cleanupAndStopReconnecting() {
|
function cleanupAndStopReconnecting() {
|
||||||
console.log("Closing peer connection");
|
logger.info("Closing peer connection");
|
||||||
|
|
||||||
setConnectionFailed(true);
|
setConnectionFailed(true);
|
||||||
if (peerConnection) {
|
if (peerConnection) {
|
||||||
|
@ -187,15 +199,14 @@ export default function KvmIdRoute() {
|
||||||
) {
|
) {
|
||||||
setLoadingMessage("Setting remote description");
|
setLoadingMessage("Setting remote description");
|
||||||
|
|
||||||
|
const l = logger.getSubLogger({ name: "setRemoteSessionDescription" });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await pc.setRemoteDescription(new RTCSessionDescription(remoteDescription));
|
await pc.setRemoteDescription(new RTCSessionDescription(remoteDescription));
|
||||||
console.log("[setRemoteSessionDescription] Remote description set successfully");
|
l.info("Remote description set successfully");
|
||||||
setLoadingMessage("Establishing secure connection...");
|
setLoadingMessage("Establishing secure connection...");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(
|
l.error("Failed to set remote description", { error });
|
||||||
"[setRemoteSessionDescription] Failed to set remote description:",
|
|
||||||
error,
|
|
||||||
);
|
|
||||||
cleanupAndStopReconnecting();
|
cleanupAndStopReconnecting();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -207,12 +218,12 @@ export default function KvmIdRoute() {
|
||||||
|
|
||||||
// When vivaldi has disabled "Broadcast IP for Best WebRTC Performance", this never connects
|
// When vivaldi has disabled "Broadcast IP for Best WebRTC Performance", this never connects
|
||||||
if (pc.sctp?.state === "connected") {
|
if (pc.sctp?.state === "connected") {
|
||||||
console.log("[setRemoteSessionDescription] Remote description set");
|
l.info("Remote description set");
|
||||||
clearInterval(checkInterval);
|
clearInterval(checkInterval);
|
||||||
setLoadingMessage("Connection established");
|
setLoadingMessage("Connection established");
|
||||||
} else if (attempts >= 10) {
|
} else if (attempts >= 10) {
|
||||||
console.log(
|
l.error(
|
||||||
"[setRemoteSessionDescription] Failed to establish connection after 10 attempts",
|
"Failed to establish connection after 10 attempts",
|
||||||
{
|
{
|
||||||
connectionState: pc.connectionState,
|
connectionState: pc.connectionState,
|
||||||
iceConnectionState: pc.iceConnectionState,
|
iceConnectionState: pc.iceConnectionState,
|
||||||
|
@ -221,7 +232,7 @@ export default function KvmIdRoute() {
|
||||||
cleanupAndStopReconnecting();
|
cleanupAndStopReconnecting();
|
||||||
clearInterval(checkInterval);
|
clearInterval(checkInterval);
|
||||||
} else {
|
} else {
|
||||||
console.log("[setRemoteSessionDescription] Waiting for connection, state:", {
|
l.info("[setRemoteSessionDescription] Waiting for connection, state:", {
|
||||||
connectionState: pc.connectionState,
|
connectionState: pc.connectionState,
|
||||||
iceConnectionState: pc.iceConnectionState,
|
iceConnectionState: pc.iceConnectionState,
|
||||||
});
|
});
|
||||||
|
@ -236,6 +247,7 @@ export default function KvmIdRoute() {
|
||||||
const makingOffer = useRef(false);
|
const makingOffer = useRef(false);
|
||||||
|
|
||||||
const wsProtocol = window.location.protocol === "https:" ? "wss:" : "ws:";
|
const wsProtocol = window.location.protocol === "https:" ? "wss:" : "ws:";
|
||||||
|
const wsLogger = logger.getSubLogger({ name: "websocket" });
|
||||||
|
|
||||||
const { sendMessage, getWebSocket } = useWebSocket(
|
const { sendMessage, getWebSocket } = useWebSocket(
|
||||||
isOnDevice
|
isOnDevice
|
||||||
|
@ -247,27 +259,27 @@ export default function KvmIdRoute() {
|
||||||
reconnectAttempts: 15,
|
reconnectAttempts: 15,
|
||||||
reconnectInterval: 1000,
|
reconnectInterval: 1000,
|
||||||
onReconnectStop: () => {
|
onReconnectStop: () => {
|
||||||
console.log("Reconnect stopped");
|
wsLogger.info("Reconnect stopped");
|
||||||
cleanupAndStopReconnecting();
|
cleanupAndStopReconnecting();
|
||||||
},
|
},
|
||||||
|
|
||||||
shouldReconnect(event) {
|
shouldReconnect(event) {
|
||||||
console.log("[Websocket] shouldReconnect", event);
|
wsLogger.info("shouldReconnect", event);
|
||||||
// TODO: Why true?
|
// TODO: Why true?
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
onClose(event) {
|
onClose(event) {
|
||||||
console.log("[Websocket] onClose", event);
|
wsLogger.info("onClose", event);
|
||||||
// We don't want to close everything down, we wait for the reconnect to stop instead
|
// We don't want to close everything down, we wait for the reconnect to stop instead
|
||||||
},
|
},
|
||||||
|
|
||||||
onError(event) {
|
onError(event) {
|
||||||
console.log("[Websocket] onError", event);
|
wsLogger.error("onError", event);
|
||||||
// We don't want to close everything down, we wait for the reconnect to stop instead
|
// We don't want to close everything down, we wait for the reconnect to stop instead
|
||||||
},
|
},
|
||||||
onOpen() {
|
onOpen() {
|
||||||
console.log("[Websocket] onOpen");
|
wsLogger.info("onOpen");
|
||||||
},
|
},
|
||||||
|
|
||||||
onMessage: message => {
|
onMessage: message => {
|
||||||
|
@ -289,18 +301,18 @@ export default function KvmIdRoute() {
|
||||||
const parsedMessage = JSON.parse(message.data);
|
const parsedMessage = JSON.parse(message.data);
|
||||||
if (parsedMessage.type === "device-metadata") {
|
if (parsedMessage.type === "device-metadata") {
|
||||||
const { deviceVersion } = parsedMessage.data;
|
const { deviceVersion } = parsedMessage.data;
|
||||||
console.log("[Websocket] Received device-metadata message");
|
wsLogger.info("Received device-metadata message");
|
||||||
console.log("[Websocket] Device version", deviceVersion);
|
wsLogger.info("Device version", deviceVersion);
|
||||||
// If the device version is not set, we can assume the device is using the legacy signaling
|
// If the device version is not set, we can assume the device is using the legacy signaling
|
||||||
if (!deviceVersion) {
|
if (!deviceVersion) {
|
||||||
console.log("[Websocket] Device is using legacy signaling");
|
wsLogger.info("Device is using legacy signaling");
|
||||||
|
|
||||||
// Now we don't need the websocket connection anymore, as we've established that we need to use the legacy signaling
|
// Now we don't need the websocket connection anymore, as we've established that we need to use the legacy signaling
|
||||||
// which does everything over HTTP(at least from the perspective of the client)
|
// which does everything over HTTP(at least from the perspective of the client)
|
||||||
isLegacySignalingEnabled.current = true;
|
isLegacySignalingEnabled.current = true;
|
||||||
getWebSocket()?.close();
|
getWebSocket()?.close();
|
||||||
} else {
|
} else {
|
||||||
console.log("[Websocket] Device is using new signaling");
|
wsLogger.info("Device is using new signaling");
|
||||||
isLegacySignalingEnabled.current = false;
|
isLegacySignalingEnabled.current = false;
|
||||||
}
|
}
|
||||||
setupPeerConnection();
|
setupPeerConnection();
|
||||||
|
@ -308,7 +320,7 @@ export default function KvmIdRoute() {
|
||||||
|
|
||||||
if (!peerConnection) return;
|
if (!peerConnection) return;
|
||||||
if (parsedMessage.type === "answer") {
|
if (parsedMessage.type === "answer") {
|
||||||
console.log("[Websocket] Received answer");
|
wsLogger.info("Received answer");
|
||||||
const readyForOffer =
|
const readyForOffer =
|
||||||
// If we're making an offer, we don't want to accept an answer
|
// If we're making an offer, we don't want to accept an answer
|
||||||
!makingOffer &&
|
!makingOffer &&
|
||||||
|
@ -322,10 +334,7 @@ export default function KvmIdRoute() {
|
||||||
|
|
||||||
// Set so we don't accept an answer while we're setting the remote description
|
// Set so we don't accept an answer while we're setting the remote description
|
||||||
isSettingRemoteAnswerPending.current = parsedMessage.type === "answer";
|
isSettingRemoteAnswerPending.current = parsedMessage.type === "answer";
|
||||||
console.log(
|
wsLogger.info("Setting remote answer pending", isSettingRemoteAnswerPending.current);
|
||||||
"[Websocket] Setting remote answer pending",
|
|
||||||
isSettingRemoteAnswerPending.current,
|
|
||||||
);
|
|
||||||
|
|
||||||
const sd = atob(parsedMessage.data);
|
const sd = atob(parsedMessage.data);
|
||||||
const remoteSessionDescription = JSON.parse(sd);
|
const remoteSessionDescription = JSON.parse(sd);
|
||||||
|
@ -338,8 +347,8 @@ export default function KvmIdRoute() {
|
||||||
// Reset the remote answer pending flag
|
// Reset the remote answer pending flag
|
||||||
isSettingRemoteAnswerPending.current = false;
|
isSettingRemoteAnswerPending.current = false;
|
||||||
} else if (parsedMessage.type === "new-ice-candidate") {
|
} else if (parsedMessage.type === "new-ice-candidate") {
|
||||||
console.log("[Websocket] Received new-ice-candidate");
|
|
||||||
const candidate = parsedMessage.data;
|
const candidate = parsedMessage.data;
|
||||||
|
wsLogger.info("Received new-ice-candidate", { candidate});
|
||||||
peerConnection.addIceCandidate(candidate);
|
peerConnection.addIceCandidate(candidate);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -366,7 +375,7 @@ export default function KvmIdRoute() {
|
||||||
// In device mode, old devices wont server this JS, and on newer devices legacy mode wont be enabled
|
// In device mode, old devices wont server this JS, and on newer devices legacy mode wont be enabled
|
||||||
const sessionUrl = `${CLOUD_API}/webrtc/session`;
|
const sessionUrl = `${CLOUD_API}/webrtc/session`;
|
||||||
|
|
||||||
console.log("Trying to get remote session description");
|
logger.info("Trying to get remote session description");
|
||||||
setLoadingMessage(
|
setLoadingMessage(
|
||||||
`Getting remote session description... ${signalingAttempts.current > 0 ? `(attempt ${signalingAttempts.current + 1})` : ""}`,
|
`Getting remote session description... ${signalingAttempts.current > 0 ? `(attempt ${signalingAttempts.current + 1})` : ""}`,
|
||||||
);
|
);
|
||||||
|
@ -379,12 +388,12 @@ export default function KvmIdRoute() {
|
||||||
const json = await res.json();
|
const json = await res.json();
|
||||||
if (res.status === 401) return navigate(isOnDevice ? "/login-local" : "/login");
|
if (res.status === 401) return navigate(isOnDevice ? "/login-local" : "/login");
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
console.error("Error getting SDP", { status: res.status, json });
|
logger.error("Error getting SDP", { status: res.status, json });
|
||||||
cleanupAndStopReconnecting();
|
cleanupAndStopReconnecting();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Successfully got Remote Session Description. Setting.");
|
logger.info("Successfully got Remote Session Description. Setting.");
|
||||||
setLoadingMessage("Setting remote session description...");
|
setLoadingMessage("Setting remote session description...");
|
||||||
|
|
||||||
const decodedSd = atob(json.sd);
|
const decodedSd = atob(json.sd);
|
||||||
|
@ -395,13 +404,15 @@ export default function KvmIdRoute() {
|
||||||
);
|
);
|
||||||
|
|
||||||
const setupPeerConnection = useCallback(async () => {
|
const setupPeerConnection = useCallback(async () => {
|
||||||
console.log("[setupPeerConnection] Setting up peer connection");
|
const l = logger.getSubLogger({ name: "setupPeerConnection" });
|
||||||
|
|
||||||
|
l.info("Setting up peer connection");
|
||||||
setConnectionFailed(false);
|
setConnectionFailed(false);
|
||||||
setLoadingMessage("Connecting to device...");
|
setLoadingMessage("Connecting to device...");
|
||||||
|
|
||||||
let pc: RTCPeerConnection;
|
let pc: RTCPeerConnection;
|
||||||
try {
|
try {
|
||||||
console.log("[setupPeerConnection] Creating peer connection");
|
l.info("Creating peer connection");
|
||||||
setLoadingMessage("Creating peer connection...");
|
setLoadingMessage("Creating peer connection...");
|
||||||
pc = new RTCPeerConnection({
|
pc = new RTCPeerConnection({
|
||||||
// We only use STUN or TURN servers if we're in the cloud
|
// We only use STUN or TURN servers if we're in the cloud
|
||||||
|
@ -411,10 +422,10 @@ export default function KvmIdRoute() {
|
||||||
});
|
});
|
||||||
|
|
||||||
setPeerConnectionState(pc.connectionState);
|
setPeerConnectionState(pc.connectionState);
|
||||||
console.log("[setupPeerConnection] Peer connection created", pc);
|
l.info("Peer connection created", pc);
|
||||||
setLoadingMessage("Setting up connection to device...");
|
setLoadingMessage("Setting up connection to device...");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`[setupPeerConnection] Error creating peer connection: ${e}`);
|
l.error(`Error creating peer connection: ${e}`);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
cleanupAndStopReconnecting();
|
cleanupAndStopReconnecting();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
@ -423,13 +434,13 @@ export default function KvmIdRoute() {
|
||||||
|
|
||||||
// Set up event listeners and data channels
|
// Set up event listeners and data channels
|
||||||
pc.onconnectionstatechange = () => {
|
pc.onconnectionstatechange = () => {
|
||||||
console.log("[setupPeerConnection] Connection state changed", pc.connectionState);
|
l.info("Connection state changed", pc.connectionState);
|
||||||
setPeerConnectionState(pc.connectionState);
|
setPeerConnectionState(pc.connectionState);
|
||||||
};
|
};
|
||||||
|
|
||||||
pc.onnegotiationneeded = async () => {
|
pc.onnegotiationneeded = async () => {
|
||||||
try {
|
try {
|
||||||
console.log("[setupPeerConnection] Creating offer");
|
l.info("Creating offer");
|
||||||
makingOffer.current = true;
|
makingOffer.current = true;
|
||||||
|
|
||||||
const offer = await pc.createOffer();
|
const offer = await pc.createOffer();
|
||||||
|
@ -439,13 +450,10 @@ export default function KvmIdRoute() {
|
||||||
if (isNewSignalingEnabled) {
|
if (isNewSignalingEnabled) {
|
||||||
sendWebRTCSignal("offer", { sd: sd });
|
sendWebRTCSignal("offer", { sd: sd });
|
||||||
} else {
|
} else {
|
||||||
console.log("Legacy signanling. Waiting for ICE Gathering to complete...");
|
l.info("Legacy signanling. Waiting for ICE Gathering to complete...");
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(
|
l.error(`Error creating offer`, { date: new Date().toISOString(), error: e });
|
||||||
`[setupPeerConnection] Error creating offer: ${e}`,
|
|
||||||
new Date().toISOString(),
|
|
||||||
);
|
|
||||||
cleanupAndStopReconnecting();
|
cleanupAndStopReconnecting();
|
||||||
} finally {
|
} finally {
|
||||||
makingOffer.current = false;
|
makingOffer.current = false;
|
||||||
|
@ -461,7 +469,7 @@ export default function KvmIdRoute() {
|
||||||
pc.onicegatheringstatechange = event => {
|
pc.onicegatheringstatechange = event => {
|
||||||
const pc = event.currentTarget as RTCPeerConnection;
|
const pc = event.currentTarget as RTCPeerConnection;
|
||||||
if (pc.iceGatheringState === "complete") {
|
if (pc.iceGatheringState === "complete") {
|
||||||
console.log("ICE Gathering completed");
|
l.info("ICE Gathering completed");
|
||||||
setLoadingMessage("ICE Gathering completed");
|
setLoadingMessage("ICE Gathering completed");
|
||||||
|
|
||||||
if (isLegacySignalingEnabled.current) {
|
if (isLegacySignalingEnabled.current) {
|
||||||
|
@ -469,7 +477,7 @@ export default function KvmIdRoute() {
|
||||||
legacyHTTPSignaling(pc);
|
legacyHTTPSignaling(pc);
|
||||||
}
|
}
|
||||||
} else if (pc.iceGatheringState === "gathering") {
|
} else if (pc.iceGatheringState === "gathering") {
|
||||||
console.log("ICE Gathering Started");
|
l.info("ICE Gathering Started");
|
||||||
setLoadingMessage("Gathering ICE candidates...");
|
setLoadingMessage("Gathering ICE candidates...");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -506,7 +514,7 @@ export default function KvmIdRoute() {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (peerConnectionState === "failed") {
|
if (peerConnectionState === "failed") {
|
||||||
console.log("Connection failed, closing peer connection");
|
logger.info("Connection failed, closing peer connection");
|
||||||
cleanupAndStopReconnecting();
|
cleanupAndStopReconnecting();
|
||||||
}
|
}
|
||||||
}, [peerConnectionState, cleanupAndStopReconnecting]);
|
}, [peerConnectionState, cleanupAndStopReconnecting]);
|
||||||
|
@ -609,13 +617,13 @@ export default function KvmIdRoute() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resp.method === "networkState") {
|
if (resp.method === "networkState") {
|
||||||
console.log("Setting network state", resp.params);
|
logger.info("Setting network state", resp.params);
|
||||||
setNetworkState(resp.params as NetworkState);
|
setNetworkState(resp.params as NetworkState);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resp.method === "keyboardLedState") {
|
if (resp.method === "keyboardLedState") {
|
||||||
const ledState = resp.params as KeyboardLedState;
|
const ledState = resp.params as KeyboardLedState;
|
||||||
console.log("Setting keyboard led state", ledState);
|
logger.info("Setting keyboard led state", ledState);
|
||||||
setKeyboardLedState(ledState);
|
setKeyboardLedState(ledState);
|
||||||
setKeyboardLedStateSyncAvailable(true);
|
setKeyboardLedStateSyncAvailable(true);
|
||||||
}
|
}
|
||||||
|
@ -660,20 +668,20 @@ export default function KvmIdRoute() {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (rpcDataChannel?.readyState !== "open") return;
|
if (rpcDataChannel?.readyState !== "open") return;
|
||||||
if (keyboardLedState !== undefined) return;
|
if (keyboardLedState !== undefined) return;
|
||||||
console.log("Requesting keyboard led state");
|
logger.info("Requesting keyboard led state");
|
||||||
|
|
||||||
send("getKeyboardLedState", {}, resp => {
|
send("getKeyboardLedState", {}, resp => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
// -32601 means the method is not supported
|
// -32601 means the method is not supported
|
||||||
if (resp.error.code === -32601) {
|
if (resp.error.code === -32601) {
|
||||||
setKeyboardLedStateSyncAvailable(false);
|
setKeyboardLedStateSyncAvailable(false);
|
||||||
console.error("Failed to get keyboard led state, disabling sync", resp.error);
|
logger.error("Failed to get keyboard led state, disabling sync", resp.error);
|
||||||
} else {
|
} else {
|
||||||
console.error("Failed to get keyboard led state", resp.error);
|
logger.error("Failed to get keyboard led state", resp.error);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log("Keyboard led state", resp.result);
|
logger.info("Keyboard led state", resp.result);
|
||||||
setKeyboardLedState(resp.result as KeyboardLedState);
|
setKeyboardLedState(resp.result as KeyboardLedState);
|
||||||
setKeyboardLedStateSyncAvailable(true);
|
setKeyboardLedStateSyncAvailable(true);
|
||||||
});
|
});
|
||||||
|
@ -691,7 +699,7 @@ export default function KvmIdRoute() {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!diskChannel || !file) return;
|
if (!diskChannel || !file) return;
|
||||||
diskChannel.onmessage = async e => {
|
diskChannel.onmessage = async e => {
|
||||||
console.log("Received", e.data);
|
logger.info("Received", e.data);
|
||||||
const data = JSON.parse(e.data);
|
const data = JSON.parse(e.data);
|
||||||
const blob = file.slice(data.start, data.end);
|
const blob = file.slice(data.start, data.end);
|
||||||
const buf = await blob.arrayBuffer();
|
const buf = await blob.arrayBuffer();
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { LinkButton } from "@components/Button";
|
||||||
import { User } from "@/hooks/stores";
|
import { User } from "@/hooks/stores";
|
||||||
import { checkAuth } from "@/main";
|
import { checkAuth } from "@/main";
|
||||||
import { CLOUD_API } from "@/ui.config";
|
import { CLOUD_API } from "@/ui.config";
|
||||||
|
import { logger } from "@/log";
|
||||||
interface LoaderData {
|
interface LoaderData {
|
||||||
devices: { id: string; name: string; online: boolean; lastSeen: string }[];
|
devices: { id: string; name: string; online: boolean; lastSeen: string }[];
|
||||||
user: User;
|
user: User;
|
||||||
|
@ -29,7 +29,7 @@ const loader = async () => {
|
||||||
const { devices } = await res.json();
|
const { devices } = await res.json();
|
||||||
return { devices, user };
|
return { devices, user };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
logger.error("Error loading devices", e);
|
||||||
return { devices: [] };
|
return { devices: [] };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,12 +11,12 @@ import { Button } from "@components/Button";
|
||||||
import LogoBlueIcon from "@/assets/logo-blue.png";
|
import LogoBlueIcon from "@/assets/logo-blue.png";
|
||||||
import LogoWhiteIcon from "@/assets/logo-white.svg";
|
import LogoWhiteIcon from "@/assets/logo-white.svg";
|
||||||
import { DEVICE_API } from "@/ui.config";
|
import { DEVICE_API } from "@/ui.config";
|
||||||
|
import { logger } from "@/log";
|
||||||
|
|
||||||
import api from "../api";
|
import api from "../api";
|
||||||
import ExtLink from "../components/ExtLink";
|
import ExtLink from "../components/ExtLink";
|
||||||
|
|
||||||
import { DeviceStatus } from "./welcome-local";
|
import { DeviceStatus } from "./welcome-local";
|
||||||
|
|
||||||
const loader = async () => {
|
const loader = async () => {
|
||||||
const res = await api
|
const res = await api
|
||||||
.GET(`${DEVICE_API}/device/status`)
|
.GET(`${DEVICE_API}/device/status`)
|
||||||
|
@ -44,7 +44,7 @@ const action = async ({ request }: ActionFunctionArgs) => {
|
||||||
return { error: "Invalid password" };
|
return { error: "Invalid password" };
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
logger.error("An error occurred while logging in", error);
|
||||||
return { error: "An error occurred while logging in" };
|
return { error: "An error occurred while logging in" };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,13 +7,13 @@ import { Button } from "@components/Button";
|
||||||
import LogoBlueIcon from "@/assets/logo-blue.png";
|
import LogoBlueIcon from "@/assets/logo-blue.png";
|
||||||
import LogoWhiteIcon from "@/assets/logo-white.svg";
|
import LogoWhiteIcon from "@/assets/logo-white.svg";
|
||||||
import { DEVICE_API } from "@/ui.config";
|
import { DEVICE_API } from "@/ui.config";
|
||||||
|
import { logger } from "@/log";
|
||||||
|
|
||||||
import { GridCard } from "../components/Card";
|
import { GridCard } from "../components/Card";
|
||||||
import { cx } from "../cva.config";
|
import { cx } from "../cva.config";
|
||||||
import api from "../api";
|
import api from "../api";
|
||||||
|
|
||||||
import { DeviceStatus } from "./welcome-local";
|
import { DeviceStatus } from "./welcome-local";
|
||||||
|
|
||||||
const loader = async () => {
|
const loader = async () => {
|
||||||
const res = await api
|
const res = await api
|
||||||
.GET(`${DEVICE_API}/device/status`)
|
.GET(`${DEVICE_API}/device/status`)
|
||||||
|
@ -39,7 +39,7 @@ const action = async ({ request }: ActionFunctionArgs) => {
|
||||||
});
|
});
|
||||||
return redirect("/");
|
return redirect("/");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error setting authentication mode:", error);
|
logger.error("Error setting authentication mode:", error);
|
||||||
return { error: "An error occurred while setting the authentication mode" };
|
return { error: "An error occurred while setting the authentication mode" };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,11 @@ import { Button } from "@components/Button";
|
||||||
import LogoBlueIcon from "@/assets/logo-blue.png";
|
import LogoBlueIcon from "@/assets/logo-blue.png";
|
||||||
import LogoWhiteIcon from "@/assets/logo-white.svg";
|
import LogoWhiteIcon from "@/assets/logo-white.svg";
|
||||||
import { DEVICE_API } from "@/ui.config";
|
import { DEVICE_API } from "@/ui.config";
|
||||||
|
import { logger } from "@/log";
|
||||||
|
|
||||||
import api from "../api";
|
import api from "../api";
|
||||||
|
|
||||||
import { DeviceStatus } from "./welcome-local";
|
import { DeviceStatus } from "./welcome-local";
|
||||||
|
|
||||||
const loader = async () => {
|
const loader = async () => {
|
||||||
const res = await api
|
const res = await api
|
||||||
.GET(`${DEVICE_API}/device/status`)
|
.GET(`${DEVICE_API}/device/status`)
|
||||||
|
@ -45,7 +45,7 @@ const action = async ({ request }: ActionFunctionArgs) => {
|
||||||
return { error: "Failed to set password" };
|
return { error: "Failed to set password" };
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error setting password:", error);
|
logger.error("Error setting password:", error);
|
||||||
return { error: "An error occurred while setting the password" };
|
return { error: "An error occurred while setting the password" };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue