mirror of https://github.com/jetkvm/kvm.git
Compare commits
12 Commits
b8ba55c889
...
c9ab3774bd
Author | SHA1 | Date |
---|---|---|
|
c9ab3774bd | |
|
d952480c2a | |
|
57fbee1490 | |
|
0e65c0a9a9 | |
|
2dafb5c9c1 | |
|
566305549f | |
|
1505c37e4c | |
|
564eee9b00 | |
|
fab575dbe0 | |
|
97958e7b86 | |
|
2f7042df18 | |
|
2cadda4e00 |
|
@ -0,0 +1,126 @@
|
||||||
|
name: Push
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
contents: read
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-22.04]
|
||||||
|
go: [1.21, 1.23.4]
|
||||||
|
node: [21]
|
||||||
|
goos: [linux]
|
||||||
|
goarch: [arm]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Node
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node }}
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
working-directory: ui
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Build UI
|
||||||
|
working-directory: ui
|
||||||
|
run: npm run build:device
|
||||||
|
|
||||||
|
- name: Setup Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: ${{ matrix.go }}
|
||||||
|
|
||||||
|
- name: Install Go Dependencies
|
||||||
|
run: |
|
||||||
|
go mod download
|
||||||
|
|
||||||
|
- name: Build Binaries
|
||||||
|
env:
|
||||||
|
GOOS: ${{ matrix.goos }}
|
||||||
|
GOARCH: ${{ matrix.goarch }}
|
||||||
|
run: |
|
||||||
|
GOOS=linux GOARCH=arm GOARM=7 go build -ldflags="-s -w -X kvm.builtAppVersion=dev-${GIT_COMMIT:0:7}" -o bin/jetkvm_app cmd/main.go
|
||||||
|
chmod 755 bin/jetkvm_app
|
||||||
|
|
||||||
|
- name: Upload Debug Artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
if: ${{ (github.ref == 'refs/heads/main' || github.event_name == 'pull_request') && matrix.go == '1.21' }}
|
||||||
|
with:
|
||||||
|
name: jetkvm_app_debug
|
||||||
|
path: bin/jetkvm_app
|
||||||
|
|
||||||
|
comment:
|
||||||
|
name: Comment
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Generate Links
|
||||||
|
id: linksa
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
ARTIFACT_ID=$(gh api repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts --jq '.artifacts[0].id')
|
||||||
|
echo "ARTIFACT_URL=https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts/$ARTIFACT_ID" >> $GITHUB_ENV
|
||||||
|
echo "LATEST_COMMIT=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Comment on PR
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
|
||||||
|
TITLE="${{ github.event.pull_request.title }}"
|
||||||
|
PR_NUMBER=${{ github.event.pull_request.number }}
|
||||||
|
else
|
||||||
|
TITLE="main branch"
|
||||||
|
fi
|
||||||
|
|
||||||
|
COMMENT=$(cat << EOF
|
||||||
|
✅ **Build successfully for $TITLE!**
|
||||||
|
|
||||||
|
| Name | Link |
|
||||||
|
|------------------|----------------------------------------------------------------------|
|
||||||
|
| 🔗 Debug Binary | [Download](${{ env.ARTIFACT_URL }}) |
|
||||||
|
| 🔗 Latest commit | [${{ env.LATEST_COMMIT }}](https://github.com/${{ github.repository }}/commit/${{ github.sha }}) |
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
|
||||||
|
# Post Comment
|
||||||
|
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
|
||||||
|
# Look for an existing comment
|
||||||
|
COMMENT_ID=$(gh api repos/${{ github.repository }}/issues/$PR_NUMBER/comments \
|
||||||
|
--jq '.[] | select(.body | contains("✅ **Build successfully for")) | .id')
|
||||||
|
|
||||||
|
if [ -z "$COMMENT_ID" ]; then
|
||||||
|
# Create a new comment if none exists
|
||||||
|
gh pr comment $PR_NUMBER --body "$COMMENT"
|
||||||
|
else
|
||||||
|
# Update the existing comment
|
||||||
|
gh api repos/${{ github.repository }}/issues/comments/$COMMENT_ID \
|
||||||
|
--method PATCH \
|
||||||
|
-f body="$COMMENT"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Log the comment for main branch
|
||||||
|
echo "$COMMENT"
|
||||||
|
fi
|
|
@ -0,0 +1,91 @@
|
||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "v*"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
name: Release
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
packages: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Node
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 21
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
working-directory: ui
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Build UI
|
||||||
|
working-directory: ui
|
||||||
|
run: npm run build:device
|
||||||
|
|
||||||
|
- name: Setup Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: 1.21
|
||||||
|
|
||||||
|
- name: Build Release Binaries
|
||||||
|
env:
|
||||||
|
REF: ${{ github.ref }}
|
||||||
|
run: |
|
||||||
|
GOOS=linux GOARCH=arm GOARM=7 go build -ldflags="-s -w -X kvm.builtAppVersion=${REF:11}" -o bin/jetkvm_app cmd/main.go
|
||||||
|
chmod 755 bin/jetkvm_app
|
||||||
|
|
||||||
|
- name: Create checksum
|
||||||
|
env:
|
||||||
|
REF: ${{ github.ref }}
|
||||||
|
run: |
|
||||||
|
SUM=$(shasum -a 256 bin/jetkvm_app | cut -d ' ' -f 1)
|
||||||
|
echo -e "\n#### SHA256 Checksum\n\`\`\`\n$SUM bin/jetkvm_app\n\`\`\`\n" >> ./RELEASE_CHANGELOG
|
||||||
|
echo -e "$SUM bin/jetkvm_app\n" > checksums.txt
|
||||||
|
|
||||||
|
- name: Create Release Branch
|
||||||
|
env:
|
||||||
|
REF: ${{ github.ref }}
|
||||||
|
run: |
|
||||||
|
BRANCH=release/${REF:10}
|
||||||
|
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
|
git config --local user.name "github-actions[bot]"
|
||||||
|
git checkout -b ${BRANCH}
|
||||||
|
git push -u origin ${BRANCH}
|
||||||
|
|
||||||
|
- name: Create Release
|
||||||
|
id: create_release
|
||||||
|
uses: softprops/action-gh-release@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
draft: true
|
||||||
|
prerelease: ${{ contains(github.ref, 'rc') || contains(github.ref, 'beta') || contains(github.ref, 'alpha') }}
|
||||||
|
body_path: ./RELEASE_CHANGELOG
|
||||||
|
|
||||||
|
- name: Upload JetKVM binary
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: bin/jetkvm_app
|
||||||
|
asset_name: jetkvm_app
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
- name: Upload checksum
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: ./checksums.txt
|
||||||
|
asset_name: checksums.txt
|
||||||
|
asset_content_type: text/plain
|
|
@ -2,7 +2,7 @@ import { useEffect, useMemo, useState } from "react";
|
||||||
import { LuExternalLink } from "react-icons/lu";
|
import { LuExternalLink } from "react-icons/lu";
|
||||||
|
|
||||||
import { Button, LinkButton } from "@components/Button";
|
import { Button, LinkButton } from "@components/Button";
|
||||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc";
|
||||||
|
|
||||||
import { InputFieldWithLabel } from "./InputField";
|
import { InputFieldWithLabel } from "./InputField";
|
||||||
import { SelectMenuBasic } from "./SelectMenuBasic";
|
import { SelectMenuBasic } from "./SelectMenuBasic";
|
||||||
|
@ -34,7 +34,7 @@ export function JigglerSetting({
|
||||||
const [timezones, setTimezones] = useState<string[]>([]);
|
const [timezones, setTimezones] = useState<string[]>([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
send("getTimezones", {}, resp => {
|
send("getTimezones", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) return;
|
if ("error" in resp) return;
|
||||||
setTimezones(resp.result as string[]);
|
setTimezones(resp.result as string[]);
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { useJsonRpc } from "@/hooks/useJsonRpc";
|
||||||
export default function MacroBar() {
|
export default function MacroBar() {
|
||||||
const { macros, initialized, loadMacros, setSendFn } = useMacrosStore();
|
const { macros, initialized, loadMacros, setSendFn } = useMacrosStore();
|
||||||
const { executeMacro } = useKeyboard();
|
const { executeMacro } = useKeyboard();
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSendFn(send);
|
setSendFn(send);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { useCallback , useEffect, useState } from "react";
|
import { useCallback , useEffect, useState } from "react";
|
||||||
|
|
||||||
import { useJsonRpc } from "../hooks/useJsonRpc";
|
import { JsonRpcResponse, 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";
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ const usbPresets = [
|
||||||
];
|
];
|
||||||
|
|
||||||
export function UsbDeviceSetting() {
|
export function UsbDeviceSetting() {
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
const [usbDeviceConfig, setUsbDeviceConfig] =
|
const [usbDeviceConfig, setUsbDeviceConfig] =
|
||||||
|
@ -67,7 +67,7 @@ export function UsbDeviceSetting() {
|
||||||
const [selectedPreset, setSelectedPreset] = useState<string>("default");
|
const [selectedPreset, setSelectedPreset] = useState<string>("default");
|
||||||
|
|
||||||
const syncUsbDeviceConfig = useCallback(() => {
|
const syncUsbDeviceConfig = useCallback(() => {
|
||||||
send("getUsbDevices", {}, resp => {
|
send("getUsbDevices", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
console.error("Failed to load USB devices:", resp.error);
|
console.error("Failed to load USB devices:", resp.error);
|
||||||
notifications.error(
|
notifications.error(
|
||||||
|
@ -97,7 +97,7 @@ export function UsbDeviceSetting() {
|
||||||
const handleUsbConfigChange = useCallback(
|
const handleUsbConfigChange = useCallback(
|
||||||
(devices: UsbDeviceConfig) => {
|
(devices: UsbDeviceConfig) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
send("setUsbDevices", { devices }, async resp => {
|
send("setUsbDevices", { devices }, async (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to set usb devices: ${resp.error.data || "Unknown error"}`,
|
`Failed to set usb devices: ${resp.error.data || "Unknown error"}`,
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { Button } from "@components/Button";
|
||||||
|
|
||||||
|
|
||||||
import { UsbConfigState } from "../hooks/stores";
|
import { UsbConfigState } from "../hooks/stores";
|
||||||
import { useJsonRpc } from "../hooks/useJsonRpc";
|
import { JsonRpcResponse, 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";
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ const usbConfigs = [
|
||||||
type UsbConfigMap = Record<string, USBConfig>;
|
type UsbConfigMap = Record<string, USBConfig>;
|
||||||
|
|
||||||
export function UsbInfoSetting() {
|
export function UsbInfoSetting() {
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
const [usbConfigProduct, setUsbConfigProduct] = useState("");
|
const [usbConfigProduct, setUsbConfigProduct] = useState("");
|
||||||
|
@ -94,7 +94,7 @@ export function UsbInfoSetting() {
|
||||||
);
|
);
|
||||||
|
|
||||||
const syncUsbConfigProduct = useCallback(() => {
|
const syncUsbConfigProduct = useCallback(() => {
|
||||||
send("getUsbConfig", {}, resp => {
|
send("getUsbConfig", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
console.error("Failed to load USB Config:", resp.error);
|
console.error("Failed to load USB Config:", resp.error);
|
||||||
notifications.error(
|
notifications.error(
|
||||||
|
@ -114,7 +114,7 @@ export function UsbInfoSetting() {
|
||||||
const handleUsbConfigChange = useCallback(
|
const handleUsbConfigChange = useCallback(
|
||||||
(usbConfig: USBConfig) => {
|
(usbConfig: USBConfig) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
send("setUsbConfig", { usbConfig }, async resp => {
|
send("setUsbConfig", { usbConfig }, async (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to set usb config: ${resp.error.data || "Unknown error"}`,
|
`Failed to set usb config: ${resp.error.data || "Unknown error"}`,
|
||||||
|
@ -137,7 +137,7 @@ export function UsbInfoSetting() {
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
send("getDeviceID", {}, async resp => {
|
send("getDeviceID", {}, async (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
return notifications.error(
|
return notifications.error(
|
||||||
`Failed to get device ID: ${resp.error.data || "Unknown error"}`,
|
`Failed to get device ID: ${resp.error.data || "Unknown error"}`,
|
||||||
|
@ -205,10 +205,10 @@ function USBConfigDialog({
|
||||||
product: "",
|
product: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
|
|
||||||
const syncUsbConfig = useCallback(() => {
|
const syncUsbConfig = useCallback(() => {
|
||||||
send("getUsbConfig", {}, resp => {
|
send("getUsbConfig", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
console.error("Failed to load USB Config:", resp.error);
|
console.error("Failed to load USB Config:", resp.error);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -74,7 +74,7 @@ export default function WebRTCVideo() {
|
||||||
const [blockWheelEvent, setBlockWheelEvent] = useState(false);
|
const [blockWheelEvent, setBlockWheelEvent] = useState(false);
|
||||||
|
|
||||||
// Misc states and hooks
|
// Misc states and hooks
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
|
|
||||||
// Video-related
|
// Video-related
|
||||||
useResizeObserver({
|
useResizeObserver({
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { SettingsPageHeader } from "@components/SettingsPageheader";
|
||||||
import notifications from "@/notifications";
|
import notifications from "@/notifications";
|
||||||
import LoadingSpinner from "@/components/LoadingSpinner";
|
import LoadingSpinner from "@/components/LoadingSpinner";
|
||||||
|
|
||||||
import { useJsonRpc } from "../../hooks/useJsonRpc";
|
import { JsonRpcResponse, useJsonRpc } from "../../hooks/useJsonRpc";
|
||||||
|
|
||||||
const LONG_PRESS_DURATION = 3000; // 3 seconds for long press
|
const LONG_PRESS_DURATION = 3000; // 3 seconds for long press
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ export function ATXPowerControl() {
|
||||||
> | null>(null);
|
> | null>(null);
|
||||||
const [atxState, setAtxState] = useState<ATXState | null>(null);
|
const [atxState, setAtxState] = useState<ATXState | null>(null);
|
||||||
|
|
||||||
const [send] = useJsonRpc(function onRequest(resp) {
|
const { send } = useJsonRpc(function onRequest(resp) {
|
||||||
if (resp.method === "atxState") {
|
if (resp.method === "atxState") {
|
||||||
setAtxState(resp.params as ATXState);
|
setAtxState(resp.params as ATXState);
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ export function ATXPowerControl() {
|
||||||
|
|
||||||
// Request initial state
|
// Request initial state
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
send("getATXState", {}, resp => {
|
send("getATXState", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to get ATX state: ${resp.error.data || "Unknown error"}`,
|
`Failed to get ATX state: ${resp.error.data || "Unknown error"}`,
|
||||||
|
@ -54,7 +54,7 @@ export function ATXPowerControl() {
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
// Send long press action
|
// Send long press action
|
||||||
console.log("Sending long press ATX power action");
|
console.log("Sending long press ATX power action");
|
||||||
send("setATXPowerAction", { action: "power-long" }, resp => {
|
send("setATXPowerAction", { action: "power-long" }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to send ATX power action: ${resp.error.data || "Unknown error"}`,
|
`Failed to send ATX power action: ${resp.error.data || "Unknown error"}`,
|
||||||
|
@ -75,7 +75,7 @@ export function ATXPowerControl() {
|
||||||
|
|
||||||
// Send short press action
|
// Send short press action
|
||||||
console.log("Sending short press ATX power action");
|
console.log("Sending short press ATX power action");
|
||||||
send("setATXPowerAction", { action: "power-short" }, resp => {
|
send("setATXPowerAction", { action: "power-short" }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to send ATX power action: ${resp.error.data || "Unknown error"}`,
|
`Failed to send ATX power action: ${resp.error.data || "Unknown error"}`,
|
||||||
|
@ -127,7 +127,7 @@ export function ATXPowerControl() {
|
||||||
LeadingIcon={LuRotateCcw}
|
LeadingIcon={LuRotateCcw}
|
||||||
text="Reset"
|
text="Reset"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
send("setATXPowerAction", { action: "reset" }, resp => {
|
send("setATXPowerAction", { action: "reset" }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to send ATX power action: ${resp.error.data || "Unknown error"}`,
|
`Failed to send ATX power action: ${resp.error.data || "Unknown error"}`,
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { useCallback, useEffect, useState } from "react";
|
||||||
import { Button } from "@components/Button";
|
import { Button } from "@components/Button";
|
||||||
import Card from "@components/Card";
|
import Card from "@components/Card";
|
||||||
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
||||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc";
|
||||||
import notifications from "@/notifications";
|
import notifications from "@/notifications";
|
||||||
import FieldLabel from "@components/FieldLabel";
|
import FieldLabel from "@components/FieldLabel";
|
||||||
import LoadingSpinner from "@components/LoadingSpinner";
|
import LoadingSpinner from "@components/LoadingSpinner";
|
||||||
|
@ -19,11 +19,11 @@ interface DCPowerState {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DCPowerControl() {
|
export function DCPowerControl() {
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
const [powerState, setPowerState] = useState<DCPowerState | null>(null);
|
const [powerState, setPowerState] = useState<DCPowerState | null>(null);
|
||||||
|
|
||||||
const getDCPowerState = useCallback(() => {
|
const getDCPowerState = useCallback(() => {
|
||||||
send("getDCPowerState", {}, resp => {
|
send("getDCPowerState", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to get DC power state: ${resp.error.data || "Unknown error"}`,
|
`Failed to get DC power state: ${resp.error.data || "Unknown error"}`,
|
||||||
|
@ -35,7 +35,7 @@ export function DCPowerControl() {
|
||||||
}, [send]);
|
}, [send]);
|
||||||
|
|
||||||
const handlePowerToggle = (enabled: boolean) => {
|
const handlePowerToggle = (enabled: boolean) => {
|
||||||
send("setDCPowerState", { enabled }, resp => {
|
send("setDCPowerState", { enabled }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to set DC power state: ${resp.error.data || "Unknown error"}`,
|
`Failed to set DC power state: ${resp.error.data || "Unknown error"}`,
|
||||||
|
@ -47,7 +47,7 @@ export function DCPowerControl() {
|
||||||
};
|
};
|
||||||
const handleRestoreChange = (state: number) => {
|
const handleRestoreChange = (state: number) => {
|
||||||
// const state = powerState?.restoreState === 0 ? 1 : powerState?.restoreState === 1 ? 2 : 0;
|
// const state = powerState?.restoreState === 0 ? 1 : powerState?.restoreState === 1 ? 2 : 0;
|
||||||
send("setDCRestoreState", { state }, resp => {
|
send("setDCRestoreState", { state }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to set DC power state: ${resp.error.data || "Unknown error"}`,
|
`Failed to set DC power state: ${resp.error.data || "Unknown error"}`,
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { useEffect, useState } from "react";
|
||||||
import { Button } from "@components/Button";
|
import { Button } from "@components/Button";
|
||||||
import Card from "@components/Card";
|
import Card from "@components/Card";
|
||||||
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
||||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc";
|
||||||
import notifications from "@/notifications";
|
import notifications from "@/notifications";
|
||||||
import { useUiStore } from "@/hooks/stores";
|
import { useUiStore } from "@/hooks/stores";
|
||||||
import { SelectMenuBasic } from "@components/SelectMenuBasic";
|
import { SelectMenuBasic } from "@components/SelectMenuBasic";
|
||||||
|
@ -17,7 +17,7 @@ interface SerialSettings {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SerialConsole() {
|
export function SerialConsole() {
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
const [settings, setSettings] = useState<SerialSettings>({
|
const [settings, setSettings] = useState<SerialSettings>({
|
||||||
baudRate: "9600",
|
baudRate: "9600",
|
||||||
dataBits: "8",
|
dataBits: "8",
|
||||||
|
@ -26,7 +26,7 @@ export function SerialConsole() {
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
send("getSerialSettings", {}, resp => {
|
send("getSerialSettings", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to get serial settings: ${resp.error.data || "Unknown error"}`,
|
`Failed to get serial settings: ${resp.error.data || "Unknown error"}`,
|
||||||
|
@ -39,7 +39,7 @@ export function SerialConsole() {
|
||||||
|
|
||||||
const handleSettingChange = (setting: keyof SerialSettings, value: string) => {
|
const handleSettingChange = (setting: keyof SerialSettings, value: string) => {
|
||||||
const newSettings = { ...settings, [setting]: value };
|
const newSettings = { ...settings, [setting]: value };
|
||||||
send("setSerialSettings", { settings: newSettings }, resp => {
|
send("setSerialSettings", { settings: newSettings }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to update serial settings: ${resp.error.data || "Unknown error"}`,
|
`Failed to update serial settings: ${resp.error.data || "Unknown error"}`,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { LuPower, LuTerminal, LuPlugZap } from "react-icons/lu";
|
import { LuPower, LuTerminal, LuPlugZap } from "react-icons/lu";
|
||||||
|
|
||||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc";
|
||||||
import Card, { GridCard } from "@components/Card";
|
import Card, { GridCard } from "@components/Card";
|
||||||
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
||||||
import { ATXPowerControl } from "@components/extensions/ATXPowerControl";
|
import { ATXPowerControl } from "@components/extensions/ATXPowerControl";
|
||||||
|
@ -39,12 +39,12 @@ const AVAILABLE_EXTENSIONS: Extension[] = [
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function ExtensionPopover() {
|
export default function ExtensionPopover() {
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
const [activeExtension, setActiveExtension] = useState<Extension | null>(null);
|
const [activeExtension, setActiveExtension] = useState<Extension | null>(null);
|
||||||
|
|
||||||
// Load active extension on component mount
|
// Load active extension on component mount
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
send("getActiveExtension", {}, resp => {
|
send("getActiveExtension", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) return;
|
if ("error" in resp) return;
|
||||||
const extensionId = resp.result as string;
|
const extensionId = resp.result as string;
|
||||||
if (extensionId) {
|
if (extensionId) {
|
||||||
|
@ -57,7 +57,7 @@ export default function ExtensionPopover() {
|
||||||
}, [send]);
|
}, [send]);
|
||||||
|
|
||||||
const handleSetActiveExtension = (extension: Extension | null) => {
|
const handleSetActiveExtension = (extension: Extension | null) => {
|
||||||
send("setActiveExtension", { extensionId: extension?.id || "" }, resp => {
|
send("setActiveExtension", { extensionId: extension?.id || "" }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to set active extension: ${resp.error.data || "Unknown error"}`,
|
`Failed to set active extension: ${resp.error.data || "Unknown error"}`,
|
||||||
|
|
|
@ -16,13 +16,13 @@ import Card, { GridCard } from "@components/Card";
|
||||||
import { formatters } from "@/utils";
|
import { formatters } from "@/utils";
|
||||||
import { RemoteVirtualMediaState, useMountMediaStore, useRTCStore } from "@/hooks/stores";
|
import { RemoteVirtualMediaState, useMountMediaStore, useRTCStore } from "@/hooks/stores";
|
||||||
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
||||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc";
|
||||||
import { useDeviceUiNavigation } from "@/hooks/useAppNavigation";
|
import { useDeviceUiNavigation } from "@/hooks/useAppNavigation";
|
||||||
import notifications from "@/notifications";
|
import notifications from "@/notifications";
|
||||||
|
|
||||||
const MountPopopover = forwardRef<HTMLDivElement, object>((_props, ref) => {
|
const MountPopopover = forwardRef<HTMLDivElement, object>((_props, ref) => {
|
||||||
const diskDataChannelStats = useRTCStore(state => state.diskDataChannelStats);
|
const diskDataChannelStats = useRTCStore(state => state.diskDataChannelStats);
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
const { remoteVirtualMediaState, setModalView, setRemoteVirtualMediaState } =
|
const { remoteVirtualMediaState, setModalView, setRemoteVirtualMediaState } =
|
||||||
useMountMediaStore();
|
useMountMediaStore();
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ const MountPopopover = forwardRef<HTMLDivElement, object>((_props, ref) => {
|
||||||
}, [diskDataChannelStats]);
|
}, [diskDataChannelStats]);
|
||||||
|
|
||||||
const syncRemoteVirtualMediaState = useCallback(() => {
|
const syncRemoteVirtualMediaState = useCallback(() => {
|
||||||
send("getVirtualMediaState", {}, response => {
|
send("getVirtualMediaState", {}, (response: JsonRpcResponse) => {
|
||||||
if ("error" in response) {
|
if ("error" in response) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to get virtual media state: ${response.error.message}`,
|
`Failed to get virtual media state: ${response.error.message}`,
|
||||||
|
@ -59,7 +59,7 @@ const MountPopopover = forwardRef<HTMLDivElement, object>((_props, ref) => {
|
||||||
}, [send, setRemoteVirtualMediaState]);
|
}, [send, setRemoteVirtualMediaState]);
|
||||||
|
|
||||||
const handleUnmount = () => {
|
const handleUnmount = () => {
|
||||||
send("unmountImage", {}, response => {
|
send("unmountImage", {}, (response: JsonRpcResponse) => {
|
||||||
if ("error" in response) {
|
if ("error" in response) {
|
||||||
notifications.error(`Failed to unmount image: ${response.error.message}`);
|
notifications.error(`Failed to unmount image: ${response.error.message}`);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { Button } from "@components/Button";
|
||||||
import { GridCard } from "@components/Card";
|
import { GridCard } from "@components/Card";
|
||||||
import { TextAreaWithLabel } from "@components/TextArea";
|
import { TextAreaWithLabel } from "@components/TextArea";
|
||||||
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
||||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc";
|
||||||
import { useHidStore, useRTCStore, useUiStore, useSettingsStore } from "@/hooks/stores";
|
import { useHidStore, useRTCStore, useUiStore, useSettingsStore } from "@/hooks/stores";
|
||||||
import { keys, modifiers } from "@/keyboardMappings";
|
import { keys, modifiers } from "@/keyboardMappings";
|
||||||
import { KeyStroke, KeyboardLayout, selectedKeyboard } from "@/keyboardLayouts";
|
import { KeyStroke, KeyboardLayout, selectedKeyboard } from "@/keyboardLayouts";
|
||||||
|
@ -28,7 +28,7 @@ export default function PasteModal() {
|
||||||
const setPasteMode = useHidStore(state => state.setPasteModeEnabled);
|
const setPasteMode = useHidStore(state => state.setPasteModeEnabled);
|
||||||
const setDisableVideoFocusTrap = useUiStore(state => state.setDisableVideoFocusTrap);
|
const setDisableVideoFocusTrap = useUiStore(state => state.setDisableVideoFocusTrap);
|
||||||
|
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
const rpcDataChannel = useRTCStore(state => state.rpcDataChannel);
|
const rpcDataChannel = useRTCStore(state => state.rpcDataChannel);
|
||||||
|
|
||||||
const [invalidChars, setInvalidChars] = useState<string[]>([]);
|
const [invalidChars, setInvalidChars] = useState<string[]>([]);
|
||||||
|
@ -47,7 +47,7 @@ export default function PasteModal() {
|
||||||
}, [keyboardLayout]);
|
}, [keyboardLayout]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
send("getKeyboardLayout", {}, resp => {
|
send("getKeyboardLayout", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) return;
|
if ("error" in resp) return;
|
||||||
setKeyboardLayout(resp.result as string);
|
setKeyboardLayout(resp.result as string);
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { useClose } from "@headlessui/react";
|
||||||
|
|
||||||
import { GridCard } from "@components/Card";
|
import { GridCard } from "@components/Card";
|
||||||
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
||||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc";
|
||||||
import { useRTCStore, useUiStore } from "@/hooks/stores";
|
import { useRTCStore, useUiStore } from "@/hooks/stores";
|
||||||
import notifications from "@/notifications";
|
import notifications from "@/notifications";
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ export default function WakeOnLanModal() {
|
||||||
|
|
||||||
const rpcDataChannel = useRTCStore(state => state.rpcDataChannel);
|
const rpcDataChannel = useRTCStore(state => state.rpcDataChannel);
|
||||||
|
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
const close = useClose();
|
const close = useClose();
|
||||||
const [errorMessage, setErrorMessage] = useState<string | null>(null);
|
const [errorMessage, setErrorMessage] = useState<string | null>(null);
|
||||||
const [addDeviceErrorMessage, setAddDeviceErrorMessage] = useState<string | null>(null);
|
const [addDeviceErrorMessage, setAddDeviceErrorMessage] = useState<string | null>(null);
|
||||||
|
@ -33,7 +33,7 @@ export default function WakeOnLanModal() {
|
||||||
setErrorMessage(null);
|
setErrorMessage(null);
|
||||||
if (rpcDataChannel?.readyState !== "open") return;
|
if (rpcDataChannel?.readyState !== "open") return;
|
||||||
|
|
||||||
send("sendWOLMagicPacket", { macAddress }, resp => {
|
send("sendWOLMagicPacket", { macAddress }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
const isInvalid = resp.error.data?.includes("invalid MAC address");
|
const isInvalid = resp.error.data?.includes("invalid MAC address");
|
||||||
if (isInvalid) {
|
if (isInvalid) {
|
||||||
|
@ -52,7 +52,7 @@ export default function WakeOnLanModal() {
|
||||||
);
|
);
|
||||||
|
|
||||||
const syncStoredDevices = useCallback(() => {
|
const syncStoredDevices = useCallback(() => {
|
||||||
send("getWakeOnLanDevices", {}, resp => {
|
send("getWakeOnLanDevices", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("result" in resp) {
|
if ("result" in resp) {
|
||||||
setStoredDevices(resp.result as StoredDevice[]);
|
setStoredDevices(resp.result as StoredDevice[]);
|
||||||
} else {
|
} else {
|
||||||
|
@ -70,7 +70,7 @@ export default function WakeOnLanModal() {
|
||||||
(index: number) => {
|
(index: number) => {
|
||||||
const updatedDevices = storedDevices.filter((_, i) => i !== index);
|
const updatedDevices = storedDevices.filter((_, i) => i !== index);
|
||||||
|
|
||||||
send("setWakeOnLanDevices", { params: { devices: updatedDevices } }, resp => {
|
send("setWakeOnLanDevices", { params: { devices: updatedDevices } }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
console.error("Failed to update Wake-on-LAN devices:", resp.error);
|
console.error("Failed to update Wake-on-LAN devices:", resp.error);
|
||||||
} else {
|
} else {
|
||||||
|
@ -86,7 +86,7 @@ export default function WakeOnLanModal() {
|
||||||
if (!name || !macAddress) return;
|
if (!name || !macAddress) return;
|
||||||
const updatedDevices = [...storedDevices, { name, macAddress }];
|
const updatedDevices = [...storedDevices, { name, macAddress }];
|
||||||
console.log("updatedDevices", updatedDevices);
|
console.log("updatedDevices", updatedDevices);
|
||||||
send("setWakeOnLanDevices", { params: { devices: updatedDevices } }, resp => {
|
send("setWakeOnLanDevices", { params: { devices: updatedDevices } }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
console.error("Failed to add Wake-on-LAN device:", resp.error);
|
console.error("Failed to add Wake-on-LAN device:", resp.error);
|
||||||
setAddDeviceErrorMessage("Failed to add device");
|
setAddDeviceErrorMessage("Failed to add device");
|
||||||
|
|
|
@ -833,7 +833,7 @@ export const useMacrosStore = create<MacrosState>((set, get) => ({
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await new Promise<void>((resolve, reject) => {
|
await new Promise<void>((resolve, reject) => {
|
||||||
sendFn("getKeyboardMacros", {}, response => {
|
sendFn("getKeyboardMacros", {}, (response: JsonRpcResponse) => {
|
||||||
if (response.error) {
|
if (response.error) {
|
||||||
console.error("Error loading macros:", response.error);
|
console.error("Error loading macros:", response.error);
|
||||||
reject(new Error(response.error.message));
|
reject(new Error(response.error.message));
|
||||||
|
|
|
@ -78,5 +78,5 @@ export function useJsonRpc(onRequest?: (payload: JsonRpcRequest) => void) {
|
||||||
};
|
};
|
||||||
}, [rpcDataChannel, onRequest]);
|
}, [rpcDataChannel, onRequest]);
|
||||||
|
|
||||||
return [send];
|
return { send };
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { useJsonRpc } from "@/hooks/useJsonRpc";
|
||||||
import { keys, modifiers } from "@/keyboardMappings";
|
import { keys, modifiers } from "@/keyboardMappings";
|
||||||
|
|
||||||
export default function useKeyboard() {
|
export default function useKeyboard() {
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
|
|
||||||
const rpcDataChannel = useRTCStore(state => state.rpcDataChannel);
|
const rpcDataChannel = useRTCStore(state => state.rpcDataChannel);
|
||||||
const updateActiveKeysAndModifiers = useHidStore(
|
const updateActiveKeysAndModifiers = useHidStore(
|
||||||
|
|
|
@ -27,7 +27,7 @@ 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 { useJsonRpc } from "../hooks/useJsonRpc";
|
import { JsonRpcResponse, useJsonRpc } from "../hooks/useJsonRpc";
|
||||||
import notifications from "../notifications";
|
import notifications from "../notifications";
|
||||||
import { isOnDevice } from "../main";
|
import { isOnDevice } from "../main";
|
||||||
import { cx } from "../cva.config";
|
import { cx } from "../cva.config";
|
||||||
|
@ -64,10 +64,10 @@ export function Dialog({ onClose }: { onClose: () => void }) {
|
||||||
setRemoteVirtualMediaState(null);
|
setRemoteVirtualMediaState(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
async function syncRemoteVirtualMediaState() {
|
async function syncRemoteVirtualMediaState() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
send("getVirtualMediaState", {}, resp => {
|
send("getVirtualMediaState", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
reject(new Error(resp.error.message));
|
reject(new Error(resp.error.message));
|
||||||
} else {
|
} else {
|
||||||
|
@ -89,7 +89,7 @@ export function Dialog({ onClose }: { onClose: () => void }) {
|
||||||
console.log(`Mounting ${url} as ${mode}`);
|
console.log(`Mounting ${url} as ${mode}`);
|
||||||
|
|
||||||
setMountInProgress(true);
|
setMountInProgress(true);
|
||||||
send("mountWithHTTP", { url, mode }, async resp => {
|
send("mountWithHTTP", { url, mode }, async (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) triggerError(resp.error.message);
|
if ("error" in resp) triggerError(resp.error.message);
|
||||||
|
|
||||||
clearMountMediaState();
|
clearMountMediaState();
|
||||||
|
@ -108,7 +108,7 @@ export function Dialog({ onClose }: { onClose: () => void }) {
|
||||||
console.log(`Mounting ${fileName} as ${mode}`);
|
console.log(`Mounting ${fileName} as ${mode}`);
|
||||||
|
|
||||||
setMountInProgress(true);
|
setMountInProgress(true);
|
||||||
send("mountWithStorage", { filename: fileName, mode }, async resp => {
|
send("mountWithStorage", { filename: fileName, mode }, async (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) triggerError(resp.error.message);
|
if ("error" in resp) triggerError(resp.error.message);
|
||||||
|
|
||||||
clearMountMediaState();
|
clearMountMediaState();
|
||||||
|
@ -689,7 +689,7 @@ function DeviceFileView({
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
const filesPerPage = 5;
|
const filesPerPage = 5;
|
||||||
|
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
|
|
||||||
interface StorageSpace {
|
interface StorageSpace {
|
||||||
bytesUsed: number;
|
bytesUsed: number;
|
||||||
|
@ -718,12 +718,12 @@ function DeviceFileView({
|
||||||
}, [storageSpace]);
|
}, [storageSpace]);
|
||||||
|
|
||||||
const syncStorage = useCallback(() => {
|
const syncStorage = useCallback(() => {
|
||||||
send("listStorageFiles", {}, res => {
|
send("listStorageFiles", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in res) {
|
if ("error" in resp) {
|
||||||
notifications.error(`Error listing storage files: ${res.error}`);
|
notifications.error(`Error listing storage files: ${resp.error}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { files } = res.result as StorageFiles;
|
const { files } = resp.result as StorageFiles;
|
||||||
const formattedFiles = files.map(file => ({
|
const formattedFiles = files.map(file => ({
|
||||||
name: file.filename,
|
name: file.filename,
|
||||||
size: formatters.bytes(file.size),
|
size: formatters.bytes(file.size),
|
||||||
|
@ -733,13 +733,13 @@ function DeviceFileView({
|
||||||
setOnStorageFiles(formattedFiles);
|
setOnStorageFiles(formattedFiles);
|
||||||
});
|
});
|
||||||
|
|
||||||
send("getStorageSpace", {}, res => {
|
send("getStorageSpace", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in res) {
|
if ("error" in resp) {
|
||||||
notifications.error(`Error getting storage space: ${res.error}`);
|
notifications.error(`Error getting storage space: ${resp.error}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const space = res.result as StorageSpace;
|
const space = resp.result as StorageSpace;
|
||||||
setStorageSpace(space);
|
setStorageSpace(space);
|
||||||
});
|
});
|
||||||
}, [send, setOnStorageFiles, setStorageSpace]);
|
}, [send, setOnStorageFiles, setStorageSpace]);
|
||||||
|
@ -762,9 +762,9 @@ function DeviceFileView({
|
||||||
|
|
||||||
function handleDeleteFile(file: { name: string; size: string; createdAt: string }) {
|
function handleDeleteFile(file: { name: string; size: string; createdAt: string }) {
|
||||||
console.log("Deleting file:", file);
|
console.log("Deleting file:", file);
|
||||||
send("deleteStorageFile", { filename: file.name }, res => {
|
send("deleteStorageFile", { filename: file.name }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in res) {
|
if ("error" in resp) {
|
||||||
notifications.error(`Error deleting file: ${res.error}`);
|
notifications.error(`Error deleting file: ${resp.error}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1001,7 +1001,7 @@ function UploadFileView({
|
||||||
const [fileError, setFileError] = useState<string | null>(null);
|
const [fileError, setFileError] = useState<string | null>(null);
|
||||||
const [uploadError, setUploadError] = useState<string | null>(null);
|
const [uploadError, setUploadError] = useState<string | null>(null);
|
||||||
|
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
const rtcDataChannelRef = useRef<RTCDataChannel | null>(null);
|
const rtcDataChannelRef = useRef<RTCDataChannel | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -1216,7 +1216,7 @@ function UploadFileView({
|
||||||
setUploadState("uploading");
|
setUploadState("uploading");
|
||||||
console.log("Upload state set to 'uploading'");
|
console.log("Upload state set to 'uploading'");
|
||||||
|
|
||||||
send("startStorageFileUpload", { filename: file.name, size: file.size }, resp => {
|
send("startStorageFileUpload", { filename: file.name, size: file.size }, (resp: JsonRpcResponse) => {
|
||||||
console.log("startStorageFileUpload response:", resp);
|
console.log("startStorageFileUpload response:", resp);
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
console.error("Upload error:", resp.error.message);
|
console.error("Upload error:", resp.error.message);
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { SettingsSectionHeader } from "@/components/SettingsSectionHeader";
|
||||||
import { useDeviceUiNavigation } from "@/hooks/useAppNavigation";
|
import { useDeviceUiNavigation } from "@/hooks/useAppNavigation";
|
||||||
import notifications from "@/notifications";
|
import notifications from "@/notifications";
|
||||||
import { DEVICE_API } from "@/ui.config";
|
import { DEVICE_API } from "@/ui.config";
|
||||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc";
|
||||||
import { isOnDevice } from "@/main";
|
import { isOnDevice } from "@/main";
|
||||||
import { TextAreaWithLabel } from "@components/TextArea";
|
import { TextAreaWithLabel } from "@components/TextArea";
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ export default function SettingsAccessIndexRoute() {
|
||||||
const { navigateTo } = useDeviceUiNavigation();
|
const { navigateTo } = useDeviceUiNavigation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
|
|
||||||
const [isAdopted, setAdopted] = useState(false);
|
const [isAdopted, setAdopted] = useState(false);
|
||||||
const [deviceId, setDeviceId] = useState<string | null>(null);
|
const [deviceId, setDeviceId] = useState<string | null>(null);
|
||||||
|
@ -56,7 +56,7 @@ export default function SettingsAccessIndexRoute() {
|
||||||
const [tlsKey, setTlsKey] = useState<string>("");
|
const [tlsKey, setTlsKey] = useState<string>("");
|
||||||
|
|
||||||
const getCloudState = useCallback(() => {
|
const getCloudState = useCallback(() => {
|
||||||
send("getCloudState", {}, resp => {
|
send("getCloudState", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) return console.error(resp.error);
|
if ("error" in resp) return console.error(resp.error);
|
||||||
const cloudState = resp.result as CloudState;
|
const cloudState = resp.result as CloudState;
|
||||||
setAdopted(cloudState.connected);
|
setAdopted(cloudState.connected);
|
||||||
|
@ -77,7 +77,7 @@ export default function SettingsAccessIndexRoute() {
|
||||||
}, [send]);
|
}, [send]);
|
||||||
|
|
||||||
const getTLSState = useCallback(() => {
|
const getTLSState = useCallback(() => {
|
||||||
send("getTLSState", {}, resp => {
|
send("getTLSState", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) return console.error(resp.error);
|
if ("error" in resp) return console.error(resp.error);
|
||||||
const tlsState = resp.result as TLSState;
|
const tlsState = resp.result as TLSState;
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ export default function SettingsAccessIndexRoute() {
|
||||||
}, [send]);
|
}, [send]);
|
||||||
|
|
||||||
const deregisterDevice = async () => {
|
const deregisterDevice = async () => {
|
||||||
send("deregisterDevice", {}, resp => {
|
send("deregisterDevice", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to de-register device: ${resp.error.data || "Unknown error"}`,
|
`Failed to de-register device: ${resp.error.data || "Unknown error"}`,
|
||||||
|
@ -110,7 +110,7 @@ export default function SettingsAccessIndexRoute() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
send("setCloudUrl", { apiUrl: cloudApiUrl, appUrl: cloudAppUrl }, resp => {
|
send("setCloudUrl", { apiUrl: cloudApiUrl, appUrl: cloudAppUrl }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to update cloud URL: ${resp.error.data || "Unknown error"}`,
|
`Failed to update cloud URL: ${resp.error.data || "Unknown error"}`,
|
||||||
|
@ -156,7 +156,7 @@ export default function SettingsAccessIndexRoute() {
|
||||||
state.privateKey = key;
|
state.privateKey = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
send("setTLSState", { state }, resp => {
|
send("setTLSState", { state }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to update TLS settings: ${resp.error.data || "Unknown error"}`,
|
`Failed to update TLS settings: ${resp.error.data || "Unknown error"}`,
|
||||||
|
@ -198,7 +198,7 @@ export default function SettingsAccessIndexRoute() {
|
||||||
getCloudState();
|
getCloudState();
|
||||||
getTLSState();
|
getTLSState();
|
||||||
|
|
||||||
send("getDeviceID", {}, async resp => {
|
send("getDeviceID", {}, async (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) return console.error(resp.error);
|
if ("error" in resp) return console.error(resp.error);
|
||||||
setDeviceId(resp.result as string);
|
setDeviceId(resp.result as string);
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,14 +8,14 @@ import { ConfirmDialog } from "../components/ConfirmDialog";
|
||||||
import { SettingsPageHeader } from "../components/SettingsPageheader";
|
import { SettingsPageHeader } from "../components/SettingsPageheader";
|
||||||
import { TextAreaWithLabel } from "../components/TextArea";
|
import { TextAreaWithLabel } from "../components/TextArea";
|
||||||
import { useSettingsStore } from "../hooks/stores";
|
import { useSettingsStore } from "../hooks/stores";
|
||||||
import { useJsonRpc } from "../hooks/useJsonRpc";
|
import { JsonRpcResponse, useJsonRpc } from "../hooks/useJsonRpc";
|
||||||
import { isOnDevice } from "../main";
|
import { isOnDevice } from "../main";
|
||||||
import notifications from "../notifications";
|
import notifications from "../notifications";
|
||||||
|
|
||||||
import { SettingsItem } from "./devices.$id.settings";
|
import { SettingsItem } from "./devices.$id.settings";
|
||||||
|
|
||||||
export default function SettingsAdvancedRoute() {
|
export default function SettingsAdvancedRoute() {
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
|
|
||||||
const [sshKey, setSSHKey] = useState<string>("");
|
const [sshKey, setSSHKey] = useState<string>("");
|
||||||
const setDeveloperMode = useSettingsStore(state => state.setDeveloperMode);
|
const setDeveloperMode = useSettingsStore(state => state.setDeveloperMode);
|
||||||
|
@ -27,35 +27,35 @@ export default function SettingsAdvancedRoute() {
|
||||||
const settings = useSettingsStore();
|
const settings = useSettingsStore();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
send("getDevModeState", {}, resp => {
|
send("getDevModeState", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) return;
|
if ("error" in resp) return;
|
||||||
const result = resp.result as { enabled: boolean };
|
const result = resp.result as { enabled: boolean };
|
||||||
setDeveloperMode(result.enabled);
|
setDeveloperMode(result.enabled);
|
||||||
});
|
});
|
||||||
|
|
||||||
send("getSSHKeyState", {}, resp => {
|
send("getSSHKeyState", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) return;
|
if ("error" in resp) return;
|
||||||
setSSHKey(resp.result as string);
|
setSSHKey(resp.result as string);
|
||||||
});
|
});
|
||||||
|
|
||||||
send("getUsbEmulationState", {}, resp => {
|
send("getUsbEmulationState", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) return;
|
if ("error" in resp) return;
|
||||||
setUsbEmulationEnabled(resp.result as boolean);
|
setUsbEmulationEnabled(resp.result as boolean);
|
||||||
});
|
});
|
||||||
|
|
||||||
send("getDevChannelState", {}, resp => {
|
send("getDevChannelState", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) return;
|
if ("error" in resp) return;
|
||||||
setDevChannel(resp.result as boolean);
|
setDevChannel(resp.result as boolean);
|
||||||
});
|
});
|
||||||
|
|
||||||
send("getLocalLoopbackOnly", {}, resp => {
|
send("getLocalLoopbackOnly", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) return;
|
if ("error" in resp) return;
|
||||||
setLocalLoopbackOnly(resp.result as boolean);
|
setLocalLoopbackOnly(resp.result as boolean);
|
||||||
});
|
});
|
||||||
}, [send, setDeveloperMode]);
|
}, [send, setDeveloperMode]);
|
||||||
|
|
||||||
const getUsbEmulationState = useCallback(() => {
|
const getUsbEmulationState = useCallback(() => {
|
||||||
send("getUsbEmulationState", {}, resp => {
|
send("getUsbEmulationState", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) return;
|
if ("error" in resp) return;
|
||||||
setUsbEmulationEnabled(resp.result as boolean);
|
setUsbEmulationEnabled(resp.result as boolean);
|
||||||
});
|
});
|
||||||
|
@ -63,7 +63,7 @@ export default function SettingsAdvancedRoute() {
|
||||||
|
|
||||||
const handleUsbEmulationToggle = useCallback(
|
const handleUsbEmulationToggle = useCallback(
|
||||||
(enabled: boolean) => {
|
(enabled: boolean) => {
|
||||||
send("setUsbEmulationState", { enabled: enabled }, resp => {
|
send("setUsbEmulationState", { enabled: enabled }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to ${enabled ? "enable" : "disable"} USB emulation: ${resp.error.data || "Unknown error"}`,
|
`Failed to ${enabled ? "enable" : "disable"} USB emulation: ${resp.error.data || "Unknown error"}`,
|
||||||
|
@ -78,7 +78,7 @@ export default function SettingsAdvancedRoute() {
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleResetConfig = useCallback(() => {
|
const handleResetConfig = useCallback(() => {
|
||||||
send("resetConfig", {}, resp => {
|
send("resetConfig", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to reset configuration: ${resp.error.data || "Unknown error"}`,
|
`Failed to reset configuration: ${resp.error.data || "Unknown error"}`,
|
||||||
|
@ -90,7 +90,7 @@ export default function SettingsAdvancedRoute() {
|
||||||
}, [send]);
|
}, [send]);
|
||||||
|
|
||||||
const handleUpdateSSHKey = useCallback(() => {
|
const handleUpdateSSHKey = useCallback(() => {
|
||||||
send("setSSHKeyState", { sshKey }, resp => {
|
send("setSSHKeyState", { sshKey }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to update SSH key: ${resp.error.data || "Unknown error"}`,
|
`Failed to update SSH key: ${resp.error.data || "Unknown error"}`,
|
||||||
|
@ -103,7 +103,7 @@ export default function SettingsAdvancedRoute() {
|
||||||
|
|
||||||
const handleDevModeChange = useCallback(
|
const handleDevModeChange = useCallback(
|
||||||
(developerMode: boolean) => {
|
(developerMode: boolean) => {
|
||||||
send("setDevModeState", { enabled: developerMode }, resp => {
|
send("setDevModeState", { enabled: developerMode }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to set dev mode: ${resp.error.data || "Unknown error"}`,
|
`Failed to set dev mode: ${resp.error.data || "Unknown error"}`,
|
||||||
|
@ -118,7 +118,7 @@ export default function SettingsAdvancedRoute() {
|
||||||
|
|
||||||
const handleDevChannelChange = useCallback(
|
const handleDevChannelChange = useCallback(
|
||||||
(enabled: boolean) => {
|
(enabled: boolean) => {
|
||||||
send("setDevChannelState", { enabled }, resp => {
|
send("setDevChannelState", { enabled }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to set dev channel state: ${resp.error.data || "Unknown error"}`,
|
`Failed to set dev channel state: ${resp.error.data || "Unknown error"}`,
|
||||||
|
@ -133,7 +133,7 @@ export default function SettingsAdvancedRoute() {
|
||||||
|
|
||||||
const applyLoopbackOnlyMode = useCallback(
|
const applyLoopbackOnlyMode = useCallback(
|
||||||
(enabled: boolean) => {
|
(enabled: boolean) => {
|
||||||
send("setLocalLoopbackOnly", { enabled }, resp => {
|
send("setLocalLoopbackOnly", { enabled }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to ${enabled ? "enable" : "disable"} loopback-only mode: ${resp.error.data || "Unknown error"}`,
|
`Failed to ${enabled ? "enable" : "disable"} loopback-only mode: ${resp.error.data || "Unknown error"}`,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
import { useState , useEffect } from "react";
|
import { useState , useEffect } from "react";
|
||||||
|
|
||||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc";
|
||||||
|
|
||||||
import { SettingsPageHeader } from "../components/SettingsPageheader";
|
import { SettingsPageHeader } from "../components/SettingsPageheader";
|
||||||
import { Button } from "../components/Button";
|
import { Button } from "../components/Button";
|
||||||
|
@ -13,7 +13,7 @@ import { useDeviceStore } from "../hooks/stores";
|
||||||
import { SettingsItem } from "./devices.$id.settings";
|
import { SettingsItem } from "./devices.$id.settings";
|
||||||
|
|
||||||
export default function SettingsGeneralRoute() {
|
export default function SettingsGeneralRoute() {
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
const { navigateTo } = useDeviceUiNavigation();
|
const { navigateTo } = useDeviceUiNavigation();
|
||||||
const [autoUpdate, setAutoUpdate] = useState(true);
|
const [autoUpdate, setAutoUpdate] = useState(true);
|
||||||
|
|
||||||
|
@ -24,14 +24,14 @@ export default function SettingsGeneralRoute() {
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
send("getAutoUpdateState", {}, resp => {
|
send("getAutoUpdateState", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) return;
|
if ("error" in resp) return;
|
||||||
setAutoUpdate(resp.result as boolean);
|
setAutoUpdate(resp.result as boolean);
|
||||||
});
|
});
|
||||||
}, [send]);
|
}, [send]);
|
||||||
|
|
||||||
const handleAutoUpdateChange = (enabled: boolean) => {
|
const handleAutoUpdateChange = (enabled: boolean) => {
|
||||||
send("setAutoUpdateState", { enabled }, resp => {
|
send("setAutoUpdateState", { enabled }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to set auto-update: ${resp.error.data || "Unknown error"}`,
|
`Failed to set auto-update: ${resp.error.data || "Unknown error"}`,
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { Button } from "@components/Button";
|
||||||
|
|
||||||
export default function SettingsGeneralRebootRoute() {
|
export default function SettingsGeneralRebootRoute() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
|
|
||||||
const onConfirmUpdate = useCallback(() => {
|
const onConfirmUpdate = useCallback(() => {
|
||||||
// This is where we send the RPC to the golang binary
|
// This is where we send the RPC to the golang binary
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { useCallback, useEffect, useRef, useState } from "react";
|
||||||
import { CheckCircleIcon } from "@heroicons/react/20/solid";
|
import { CheckCircleIcon } from "@heroicons/react/20/solid";
|
||||||
|
|
||||||
import Card from "@/components/Card";
|
import Card from "@/components/Card";
|
||||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc";
|
||||||
import { Button } from "@components/Button";
|
import { Button } from "@components/Button";
|
||||||
import { UpdateState, useDeviceStore, useUpdateStore } from "@/hooks/stores";
|
import { UpdateState, useDeviceStore, useUpdateStore } from "@/hooks/stores";
|
||||||
import notifications from "@/notifications";
|
import notifications from "@/notifications";
|
||||||
|
@ -16,7 +16,7 @@ export default function SettingsGeneralUpdateRoute() {
|
||||||
const { updateSuccess } = location.state || {};
|
const { updateSuccess } = location.state || {};
|
||||||
|
|
||||||
const { setModalView, otaState } = useUpdateStore();
|
const { setModalView, otaState } = useUpdateStore();
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
|
|
||||||
const onConfirmUpdate = useCallback(() => {
|
const onConfirmUpdate = useCallback(() => {
|
||||||
send("tryUpdate", {});
|
send("tryUpdate", {});
|
||||||
|
@ -134,14 +134,14 @@ function LoadingState({
|
||||||
}) {
|
}) {
|
||||||
const [progressWidth, setProgressWidth] = useState("0%");
|
const [progressWidth, setProgressWidth] = useState("0%");
|
||||||
const abortControllerRef = useRef<AbortController | null>(null);
|
const abortControllerRef = useRef<AbortController | null>(null);
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
|
|
||||||
const setAppVersion = useDeviceStore(state => state.setAppVersion);
|
const setAppVersion = useDeviceStore(state => state.setAppVersion);
|
||||||
const setSystemVersion = useDeviceStore(state => state.setSystemVersion);
|
const setSystemVersion = useDeviceStore(state => state.setSystemVersion);
|
||||||
|
|
||||||
const getVersionInfo = useCallback(() => {
|
const getVersionInfo = useCallback(() => {
|
||||||
return new Promise<SystemVersionInfo>((resolve, reject) => {
|
return new Promise<SystemVersionInfo>((resolve, reject) => {
|
||||||
send("getUpdateStatus", {}, async resp => {
|
send("getUpdateStatus", {}, async (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(`Failed to check for updates: ${resp.error}`);
|
notifications.error(`Failed to check for updates: ${resp.error}`);
|
||||||
reject(new Error("Failed to check for updates"));
|
reject(new Error("Failed to check for updates"));
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { useEffect } from "react";
|
||||||
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
||||||
import { SettingsItem } from "@routes/devices.$id.settings";
|
import { SettingsItem } from "@routes/devices.$id.settings";
|
||||||
import { BacklightSettings, useSettingsStore } from "@/hooks/stores";
|
import { BacklightSettings, useSettingsStore } from "@/hooks/stores";
|
||||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc";
|
||||||
import { SelectMenuBasic } from "@components/SelectMenuBasic";
|
import { SelectMenuBasic } from "@components/SelectMenuBasic";
|
||||||
import { UsbDeviceSetting } from "@components/UsbDeviceSetting";
|
import { UsbDeviceSetting } from "@components/UsbDeviceSetting";
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import { UsbInfoSetting } from "../components/UsbInfoSetting";
|
||||||
import { FeatureFlag } from "../components/FeatureFlag";
|
import { FeatureFlag } from "../components/FeatureFlag";
|
||||||
|
|
||||||
export default function SettingsHardwareRoute() {
|
export default function SettingsHardwareRoute() {
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
const settings = useSettingsStore();
|
const settings = useSettingsStore();
|
||||||
|
|
||||||
const setDisplayRotation = useSettingsStore(state => state.setDisplayRotation);
|
const setDisplayRotation = useSettingsStore(state => state.setDisplayRotation);
|
||||||
|
@ -23,7 +23,7 @@ export default function SettingsHardwareRoute() {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDisplayRotationSave = () => {
|
const handleDisplayRotationSave = () => {
|
||||||
send("setDisplayRotation", { params: { rotation: settings.displayRotation } }, resp => {
|
send("setDisplayRotation", { params: { rotation: settings.displayRotation } }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to set display orientation: ${resp.error.data || "Unknown error"}`,
|
`Failed to set display orientation: ${resp.error.data || "Unknown error"}`,
|
||||||
|
@ -48,7 +48,7 @@ export default function SettingsHardwareRoute() {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleBacklightSettingsSave = () => {
|
const handleBacklightSettingsSave = () => {
|
||||||
send("setBacklightSettings", { params: settings.backlightSettings }, resp => {
|
send("setBacklightSettings", { params: settings.backlightSettings }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to set backlight settings: ${resp.error.data || "Unknown error"}`,
|
`Failed to set backlight settings: ${resp.error.data || "Unknown error"}`,
|
||||||
|
@ -60,7 +60,7 @@ export default function SettingsHardwareRoute() {
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
send("getBacklightSettings", {}, resp => {
|
send("getBacklightSettings", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
return notifications.error(
|
return notifications.error(
|
||||||
`Failed to get backlight settings: ${resp.error.data || "Unknown error"}`,
|
`Failed to get backlight settings: ${resp.error.data || "Unknown error"}`,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { useCallback, useEffect, useMemo } from "react";
|
import { useCallback, useEffect, useMemo } from "react";
|
||||||
|
|
||||||
import { KeyboardLedSync, useSettingsStore } from "@/hooks/stores";
|
import { KeyboardLedSync, useSettingsStore } from "@/hooks/stores";
|
||||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc";
|
||||||
import notifications from "@/notifications";
|
import notifications from "@/notifications";
|
||||||
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
||||||
import { keyboardOptions } from "@/keyboardLayouts";
|
import { keyboardOptions } from "@/keyboardLayouts";
|
||||||
|
@ -39,10 +39,10 @@ export default function SettingsKeyboardRoute() {
|
||||||
{ value: "host", label: "Host Only" },
|
{ value: "host", label: "Host Only" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
send("getKeyboardLayout", {}, resp => {
|
send("getKeyboardLayout", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) return;
|
if ("error" in resp) return;
|
||||||
setKeyboardLayout(resp.result as string);
|
setKeyboardLayout(resp.result as string);
|
||||||
});
|
});
|
||||||
|
@ -51,7 +51,7 @@ export default function SettingsKeyboardRoute() {
|
||||||
const onKeyboardLayoutChange = useCallback(
|
const onKeyboardLayoutChange = useCallback(
|
||||||
(e: React.ChangeEvent<HTMLSelectElement>) => {
|
(e: React.ChangeEvent<HTMLSelectElement>) => {
|
||||||
const layout = e.target.value;
|
const layout = e.target.value;
|
||||||
send("setKeyboardLayout", { layout }, resp => {
|
send("setKeyboardLayout", { layout }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to set keyboard layout: ${resp.error.data || "Unknown error"}`,
|
`Failed to set keyboard layout: ${resp.error.data || "Unknown error"}`,
|
||||||
|
|
|
@ -6,7 +6,7 @@ import PointingFinger from "@/assets/pointing-finger.svg";
|
||||||
import { GridCard } from "@/components/Card";
|
import { GridCard } from "@/components/Card";
|
||||||
import { Checkbox } from "@/components/Checkbox";
|
import { Checkbox } from "@/components/Checkbox";
|
||||||
import { useSettingsStore } from "@/hooks/stores";
|
import { useSettingsStore } from "@/hooks/stores";
|
||||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc";
|
||||||
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
||||||
import { SelectMenuBasic } from "@components/SelectMenuBasic";
|
import { SelectMenuBasic } from "@components/SelectMenuBasic";
|
||||||
import { JigglerSetting } from "@components/JigglerSetting";
|
import { JigglerSetting } from "@components/JigglerSetting";
|
||||||
|
@ -87,17 +87,17 @@ export default function SettingsMouseRoute() {
|
||||||
{ value: "100", label: "Very High" },
|
{ value: "100", label: "Very High" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
|
|
||||||
const syncJigglerSettings = useCallback(() => {
|
const syncJigglerSettings = useCallback(() => {
|
||||||
send("getJigglerState", {}, resp => {
|
send("getJigglerState", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) return;
|
if ("error" in resp) return;
|
||||||
const isEnabled = resp.result as boolean;
|
const isEnabled = resp.result as boolean;
|
||||||
|
|
||||||
// If the jiggler is disabled, set the selected option to "disabled" and nothing else
|
// If the jiggler is disabled, set the selected option to "disabled" and nothing else
|
||||||
if (!isEnabled) return setSelectedJigglerOption("disabled");
|
if (!isEnabled) return setSelectedJigglerOption("disabled");
|
||||||
|
|
||||||
send("getJigglerConfig", {}, resp => {
|
send("getJigglerConfig", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) return;
|
if ("error" in resp) return;
|
||||||
const result = resp.result as JigglerConfig;
|
const result = resp.result as JigglerConfig;
|
||||||
setCurrentJigglerConfig(result);
|
setCurrentJigglerConfig(result);
|
||||||
|
@ -121,7 +121,7 @@ export default function SettingsMouseRoute() {
|
||||||
const saveJigglerConfig = useCallback(
|
const saveJigglerConfig = useCallback(
|
||||||
(jigglerConfig: JigglerConfig) => {
|
(jigglerConfig: JigglerConfig) => {
|
||||||
// We assume the jiggler should be set to enabled if the config is being updated
|
// We assume the jiggler should be set to enabled if the config is being updated
|
||||||
send("setJigglerState", { enabled: true }, async resp => {
|
send("setJigglerState", { enabled: true }, async (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
return notifications.error(
|
return notifications.error(
|
||||||
`Failed to set jiggler state: ${resp.error.data || "Unknown error"}`,
|
`Failed to set jiggler state: ${resp.error.data || "Unknown error"}`,
|
||||||
|
@ -129,7 +129,7 @@ export default function SettingsMouseRoute() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
send("setJigglerConfig", { jigglerConfig }, async resp => {
|
send("setJigglerConfig", { jigglerConfig }, async (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
const errorMsg = resp.error.data || "Unknown error";
|
const errorMsg = resp.error.data || "Unknown error";
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ export default function SettingsMouseRoute() {
|
||||||
|
|
||||||
// We don't need to update the device jiggler state when the option is "disabled"
|
// We don't need to update the device jiggler state when the option is "disabled"
|
||||||
if (option === "disabled") {
|
if (option === "disabled") {
|
||||||
send("setJigglerState", { enabled: false }, async resp => {
|
send("setJigglerState", { enabled: false }, async (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
return notifications.error(
|
return notifications.error(
|
||||||
`Failed to set jiggler state: ${resp.error.data || "Unknown error"}`,
|
`Failed to set jiggler state: ${resp.error.data || "Unknown error"}`,
|
||||||
|
|
|
@ -13,7 +13,7 @@ import {
|
||||||
TimeSyncMode,
|
TimeSyncMode,
|
||||||
useNetworkStateStore,
|
useNetworkStateStore,
|
||||||
} from "@/hooks/stores";
|
} from "@/hooks/stores";
|
||||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc";
|
||||||
import { Button } from "@components/Button";
|
import { Button } from "@components/Button";
|
||||||
import { GridCard } from "@components/Card";
|
import { GridCard } from "@components/Card";
|
||||||
import InputField, { InputFieldWithLabel } from "@components/InputField";
|
import InputField, { InputFieldWithLabel } from "@components/InputField";
|
||||||
|
@ -72,7 +72,7 @@ export function LifeTimeLabel({ lifetime }: { lifetime: string }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function SettingsNetworkRoute() {
|
export default function SettingsNetworkRoute() {
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
const [networkState, setNetworkState] = useNetworkStateStore(state => [
|
const [networkState, setNetworkState] = useNetworkStateStore(state => [
|
||||||
state,
|
state,
|
||||||
state.setNetworkState,
|
state.setNetworkState,
|
||||||
|
@ -104,7 +104,7 @@ export default function SettingsNetworkRoute() {
|
||||||
|
|
||||||
const getNetworkSettings = useCallback(() => {
|
const getNetworkSettings = useCallback(() => {
|
||||||
setNetworkSettingsLoaded(false);
|
setNetworkSettingsLoaded(false);
|
||||||
send("getNetworkSettings", {}, resp => {
|
send("getNetworkSettings", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) return;
|
if ("error" in resp) return;
|
||||||
console.log(resp.result);
|
console.log(resp.result);
|
||||||
setNetworkSettings(resp.result as NetworkSettings);
|
setNetworkSettings(resp.result as NetworkSettings);
|
||||||
|
@ -117,7 +117,7 @@ export default function SettingsNetworkRoute() {
|
||||||
}, [send]);
|
}, [send]);
|
||||||
|
|
||||||
const getNetworkState = useCallback(() => {
|
const getNetworkState = useCallback(() => {
|
||||||
send("getNetworkState", {}, resp => {
|
send("getNetworkState", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) return;
|
if ("error" in resp) return;
|
||||||
console.log(resp.result);
|
console.log(resp.result);
|
||||||
setNetworkState(resp.result as NetworkState);
|
setNetworkState(resp.result as NetworkState);
|
||||||
|
@ -127,7 +127,7 @@ export default function SettingsNetworkRoute() {
|
||||||
const setNetworkSettingsRemote = useCallback(
|
const setNetworkSettingsRemote = useCallback(
|
||||||
(settings: NetworkSettings) => {
|
(settings: NetworkSettings) => {
|
||||||
setNetworkSettingsLoaded(false);
|
setNetworkSettingsLoaded(false);
|
||||||
send("setNetworkSettings", { settings }, resp => {
|
send("setNetworkSettings", { settings }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
"Failed to save network settings: " +
|
"Failed to save network settings: " +
|
||||||
|
@ -148,7 +148,7 @@ export default function SettingsNetworkRoute() {
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleRenewLease = useCallback(() => {
|
const handleRenewLease = useCallback(() => {
|
||||||
send("renewDHCPLease", {}, resp => {
|
send("renewDHCPLease", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error("Failed to renew lease: " + resp.error.message);
|
notifications.error("Failed to renew lease: " + resp.error.message);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { useState, useEffect } from "react";
|
||||||
|
|
||||||
import { Button } from "@/components/Button";
|
import { Button } from "@/components/Button";
|
||||||
import { TextAreaWithLabel } from "@/components/TextArea";
|
import { TextAreaWithLabel } from "@/components/TextArea";
|
||||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc";
|
||||||
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
||||||
import { useSettingsStore } from "@/hooks/stores";
|
import { useSettingsStore } from "@/hooks/stores";
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ const streamQualityOptions = [
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function SettingsVideoRoute() {
|
export default function SettingsVideoRoute() {
|
||||||
const [send] = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
const [streamQuality, setStreamQuality] = useState("1");
|
const [streamQuality, setStreamQuality] = useState("1");
|
||||||
const [customEdidValue, setCustomEdidValue] = useState<string | null>(null);
|
const [customEdidValue, setCustomEdidValue] = useState<string | null>(null);
|
||||||
const [edid, setEdid] = useState<string | null>(null);
|
const [edid, setEdid] = useState<string | null>(null);
|
||||||
|
@ -55,12 +55,12 @@ export default function SettingsVideoRoute() {
|
||||||
const setVideoContrast = useSettingsStore(state => state.setVideoContrast);
|
const setVideoContrast = useSettingsStore(state => state.setVideoContrast);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
send("getStreamQualityFactor", {}, resp => {
|
send("getStreamQualityFactor", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) return;
|
if ("error" in resp) return;
|
||||||
setStreamQuality(String(resp.result));
|
setStreamQuality(String(resp.result));
|
||||||
});
|
});
|
||||||
|
|
||||||
send("getEDID", {}, resp => {
|
send("getEDID", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(`Failed to get EDID: ${resp.error.data || "Unknown error"}`);
|
notifications.error(`Failed to get EDID: ${resp.error.data || "Unknown error"}`);
|
||||||
return;
|
return;
|
||||||
|
@ -85,7 +85,7 @@ export default function SettingsVideoRoute() {
|
||||||
}, [send]);
|
}, [send]);
|
||||||
|
|
||||||
const handleStreamQualityChange = (factor: string) => {
|
const handleStreamQualityChange = (factor: string) => {
|
||||||
send("setStreamQualityFactor", { factor: Number(factor) }, resp => {
|
send("setStreamQualityFactor", { factor: Number(factor) }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
`Failed to set stream quality: ${resp.error.data || "Unknown error"}`,
|
`Failed to set stream quality: ${resp.error.data || "Unknown error"}`,
|
||||||
|
@ -99,7 +99,7 @@ export default function SettingsVideoRoute() {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleEDIDChange = (newEdid: string) => {
|
const handleEDIDChange = (newEdid: string) => {
|
||||||
send("setEDID", { edid: newEdid }, resp => {
|
send("setEDID", { edid: newEdid }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(`Failed to set EDID: ${resp.error.data || "Unknown error"}`);
|
notifications.error(`Failed to set EDID: ${resp.error.data || "Unknown error"}`);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -37,7 +37,7 @@ import WebRTCVideo from "@components/WebRTCVideo";
|
||||||
import { checkAuth, isInCloud, isOnDevice } from "@/main";
|
import { checkAuth, isInCloud, isOnDevice } from "@/main";
|
||||||
import DashboardNavbar from "@components/Header";
|
import DashboardNavbar from "@components/Header";
|
||||||
import ConnectionStatsSidebar from "@/components/sidebar/connectionStats";
|
import ConnectionStatsSidebar from "@/components/sidebar/connectionStats";
|
||||||
import { JsonRpcRequest, useJsonRpc } from "@/hooks/useJsonRpc";
|
import { JsonRpcRequest, JsonRpcResponse, 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";
|
||||||
|
|
||||||
|
@ -646,11 +646,11 @@ export default function KvmIdRoute() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const rpcDataChannel = useRTCStore(state => state.rpcDataChannel);
|
const rpcDataChannel = useRTCStore(state => state.rpcDataChannel);
|
||||||
const [send] = useJsonRpc(onJsonRpcRequest);
|
const { send } = useJsonRpc(onJsonRpcRequest);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (rpcDataChannel?.readyState !== "open") return;
|
if (rpcDataChannel?.readyState !== "open") return;
|
||||||
send("getVideoState", {}, resp => {
|
send("getVideoState", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) return;
|
if ("error" in resp) return;
|
||||||
setHdmiState(resp.result as Parameters<VideoState["setHdmiState"]>[0]);
|
setHdmiState(resp.result as Parameters<VideoState["setHdmiState"]>[0]);
|
||||||
});
|
});
|
||||||
|
@ -662,7 +662,7 @@ export default function KvmIdRoute() {
|
||||||
if (keyboardLedState !== undefined) return;
|
if (keyboardLedState !== undefined) return;
|
||||||
console.log("Requesting keyboard led state");
|
console.log("Requesting keyboard led state");
|
||||||
|
|
||||||
send("getKeyboardLedState", {}, resp => {
|
send("getKeyboardLedState", {}, (resp: JsonRpcResponse) => {
|
||||||
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) {
|
||||||
|
@ -735,7 +735,7 @@ export default function KvmIdRoute() {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (appVersion) return;
|
if (appVersion) return;
|
||||||
|
|
||||||
send("getUpdateStatus", {}, async resp => {
|
send("getUpdateStatus", {}, async (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(`Failed to get device version: ${resp.error}`);
|
notifications.error(`Failed to get device version: ${resp.error}`);
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue