fix: hoisted state to parent in order to coordinate connection
This commit is contained in:
@@ -22,9 +22,12 @@ import { Subtle } from "@components/UI/Typography/Subtle.tsx";
|
|||||||
import { AlertCircle } from "lucide-react";
|
import { AlertCircle } from "lucide-react";
|
||||||
import { Link } from "../UI/Typography/Link.tsx";
|
import { Link } from "../UI/Typography/Link.tsx";
|
||||||
import { Fragment } from "react/jsx-runtime";
|
import { Fragment } from "react/jsx-runtime";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
export interface TabElementProps {
|
export interface TabElementProps {
|
||||||
closeDialog: () => void;
|
closeDialog: () => void;
|
||||||
|
connectionInProgress: boolean;
|
||||||
|
setConnectionInProgress: (inProgress: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TabManifest {
|
export interface TabManifest {
|
||||||
@@ -111,25 +114,28 @@ export const NewDeviceDialog = ({
|
|||||||
open,
|
open,
|
||||||
onOpenChange,
|
onOpenChange,
|
||||||
}: NewDeviceProps) => {
|
}: NewDeviceProps) => {
|
||||||
|
const [connectionInProgress, setConnectionInProgress] =
|
||||||
|
useState(false);
|
||||||
const { unsupported } = useBrowserFeatureDetection();
|
const { unsupported } = useBrowserFeatureDetection();
|
||||||
|
|
||||||
|
|
||||||
const tabs: TabManifest[] = [
|
const tabs: TabManifest[] = [
|
||||||
{
|
{
|
||||||
label: "HTTP",
|
label: "HTTP",
|
||||||
element: HTTP,
|
element: HTTP,
|
||||||
isDisabled: false,
|
isDisabled: connectionInProgress,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Bluetooth",
|
label: "Bluetooth",
|
||||||
element: BLE,
|
element: BLE,
|
||||||
isDisabled: unsupported.includes("Web Bluetooth") ||
|
isDisabled: unsupported.includes("Web Bluetooth") ||
|
||||||
unsupported.includes("Secure Context"),
|
unsupported.includes("Secure Context") || connectionInProgress,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Serial",
|
label: "Serial",
|
||||||
element: Serial,
|
element: Serial,
|
||||||
isDisabled: unsupported.includes("Web Serial") ||
|
isDisabled: unsupported.includes("Web Serial") ||
|
||||||
unsupported.includes("Secure Context"),
|
unsupported.includes("Secure Context") || connectionInProgress,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -154,7 +160,7 @@ export const NewDeviceDialog = ({
|
|||||||
{tab.isDisabled
|
{tab.isDisabled
|
||||||
? <ErrorMessage missingFeatures={unsupported} />
|
? <ErrorMessage missingFeatures={unsupported} />
|
||||||
: null}
|
: null}
|
||||||
<tab.element closeDialog={() => onOpenChange(false)} />
|
<tab.element closeDialog={() => onOpenChange(false)} setConnectionInProgress={setConnectionInProgress} connectionInProgress={connectionInProgress} />
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { BleConnection, ServiceUuid } from "@meshtastic/js";
|
|||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { useMessageStore } from "@core/stores/messageStore.ts";
|
import { useMessageStore } from "@core/stores/messageStore.ts";
|
||||||
|
|
||||||
export const BLE = ({ closeDialog }: TabElementProps) => {
|
export const BLE = ({ setConnectionInProgress, closeDialog }: TabElementProps) => {
|
||||||
const [bleDevices, setBleDevices] = useState<BluetoothDevice[]>([]);
|
const [bleDevices, setBleDevices] = useState<BluetoothDevice[]>([]);
|
||||||
const { addDevice } = useDeviceStore();
|
const { addDevice } = useDeviceStore();
|
||||||
const messageStore = useMessageStore()
|
const messageStore = useMessageStore()
|
||||||
@@ -45,6 +45,7 @@ export const BLE = ({ closeDialog }: TabElementProps) => {
|
|||||||
key={device.id}
|
key={device.id}
|
||||||
className="dark:bg-slate-900 dark:text-white"
|
className="dark:bg-slate-900 dark:text-white"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
setConnectionInProgress(true);
|
||||||
onConnect(device);
|
onConnect(device);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -67,6 +68,11 @@ export const BLE = ({ closeDialog }: TabElementProps) => {
|
|||||||
if (exists === -1) {
|
if (exists === -1) {
|
||||||
setBleDevices(bleDevices.concat(device));
|
setBleDevices(bleDevices.concat(device));
|
||||||
}
|
}
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error("Error requesting device:", error);
|
||||||
|
setConnectionInProgress(false);
|
||||||
|
}).finally(() => {
|
||||||
|
setConnectionInProgress(false);
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -74,4 +80,4 @@ export const BLE = ({ closeDialog }: TabElementProps) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -20,7 +20,7 @@ interface FormData {
|
|||||||
tls: boolean;
|
tls: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const HTTP = ({ closeDialog }: TabElementProps) => {
|
export const HTTP = ({ closeDialog, setConnectionInProgress, connectionInProgress }: TabElementProps) => {
|
||||||
const isURLHTTPS = location.protocol === "https:";
|
const isURLHTTPS = location.protocol === "https:";
|
||||||
|
|
||||||
const { addDevice } = useDeviceStore();
|
const { addDevice } = useDeviceStore();
|
||||||
@@ -30,10 +30,10 @@ export const HTTP = ({ closeDialog }: TabElementProps) => {
|
|||||||
const { control, handleSubmit, register } = useForm<FormData>({
|
const { control, handleSubmit, register } = useForm<FormData>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
ip: ["client.meshtastic.org", "localhost"].includes(
|
ip: ["client.meshtastic.org", "localhost"].includes(
|
||||||
window.location.hostname,
|
globalThis.location.hostname,
|
||||||
)
|
)
|
||||||
? "meshtastic.local"
|
? "meshtastic.local"
|
||||||
: window.location.host,
|
: globalThis.location.host,
|
||||||
tls: isURLHTTPS ? true : false,
|
tls: isURLHTTPS ? true : false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -42,7 +42,6 @@ export const HTTP = ({ closeDialog }: TabElementProps) => {
|
|||||||
field: { value: tlsValue, onChange: setTLS },
|
field: { value: tlsValue, onChange: setTLS },
|
||||||
} = useController({ name: "tls", control });
|
} = useController({ name: "tls", control });
|
||||||
|
|
||||||
const [connectionInProgress, setConnectionInProgress] = useState(false);
|
|
||||||
const [connectionError, setConnectionError] = useState<{ host: string; secure: boolean } | null>(null);
|
const [connectionError, setConnectionError] = useState<{ host: string; secure: boolean } | null>(null);
|
||||||
|
|
||||||
const onSubmit = handleSubmit(async (data) => {
|
const onSubmit = handleSubmit(async (data) => {
|
||||||
@@ -76,14 +75,13 @@ export const HTTP = ({ closeDialog }: TabElementProps) => {
|
|||||||
prefix={tlsValue ? "https://" : "http://"}
|
prefix={tlsValue ? "https://" : "http://"}
|
||||||
placeholder="000.000.000.000 / meshtastic.local"
|
placeholder="000.000.000.000 / meshtastic.local"
|
||||||
className="text-slate-900 dark:text-slate-900"
|
className="text-slate-900 dark:text-slate-900"
|
||||||
disabled={connectionInProgress}
|
|
||||||
{...register("ip")}
|
{...register("ip")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2 mt-2">
|
<div className="flex items-center gap-2 mt-2">
|
||||||
<Switch
|
<Switch
|
||||||
onCheckedChange={setTLS}
|
onCheckedChange={setTLS}
|
||||||
disabled={isURLHTTPS || connectionInProgress}
|
disabled={isURLHTTPS}
|
||||||
checked={isURLHTTPS || tlsValue}
|
checked={isURLHTTPS || tlsValue}
|
||||||
{...register("tls")}
|
{...register("tls")}
|
||||||
/>
|
/>
|
||||||
@@ -122,7 +120,6 @@ export const HTTP = ({ closeDialog }: TabElementProps) => {
|
|||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={connectionInProgress}
|
|
||||||
className="dark:bg-slate-900 dark:text-white"
|
className="dark:bg-slate-900 dark:text-white"
|
||||||
>
|
>
|
||||||
<span>{connectionInProgress ? "Connecting..." : "Connect"}</span>
|
<span>{connectionInProgress ? "Connecting..." : "Connect"}</span>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { TransportWebSerial } from "@meshtastic/transport-web-serial";
|
|||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { useMessageStore } from "@core/stores/messageStore.ts";
|
import { useMessageStore } from "@core/stores/messageStore.ts";
|
||||||
|
|
||||||
export const Serial = ({ closeDialog }: TabElementProps) => {
|
export const Serial = ({ setConnectionInProgress, closeDialog }: TabElementProps) => {
|
||||||
const [serialPorts, setSerialPorts] = useState<SerialPort[]>([]);
|
const [serialPorts, setSerialPorts] = useState<SerialPort[]>([]);
|
||||||
const { addDevice } = useDeviceStore();
|
const { addDevice } = useDeviceStore();
|
||||||
const messageStore = useMessageStore()
|
const messageStore = useMessageStore()
|
||||||
@@ -54,6 +54,7 @@ export const Serial = ({ closeDialog }: TabElementProps) => {
|
|||||||
disabled={port.readable !== null}
|
disabled={port.readable !== null}
|
||||||
className="dark:bg-slate-900 dark:text-white"
|
className="dark:bg-slate-900 dark:text-white"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
|
setConnectionInProgress(true);
|
||||||
await onConnect(port);
|
await onConnect(port);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -71,6 +72,11 @@ export const Serial = ({ closeDialog }: TabElementProps) => {
|
|||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
await navigator.serial.requestPort().then((port) => {
|
await navigator.serial.requestPort().then((port) => {
|
||||||
setSerialPorts(serialPorts.concat(port));
|
setSerialPorts(serialPorts.concat(port));
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error("Error requesting port:", error);
|
||||||
|
setConnectionInProgress(false);
|
||||||
|
}).finally(() => {
|
||||||
|
setConnectionInProgress(false);
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user