|
|
|
@ -1,6 +1,7 @@ |
|
|
|
import type { TabElementProps } from "@components/Dialog/NewDeviceDialog.tsx"; |
|
|
|
import { Button } from "@components/UI/Button.tsx"; |
|
|
|
import { Input } from "@components/UI/Input.tsx"; |
|
|
|
import { Link } from "@components/UI/Typography/Link.tsx"; |
|
|
|
import { Label } from "@components/UI/Label.tsx"; |
|
|
|
import { Switch } from "@components/UI/Switch.tsx"; |
|
|
|
import { useAppStore } from "@core/stores/appStore.ts"; |
|
|
|
@ -11,6 +12,7 @@ import { MeshDevice } from "@meshtastic/core"; |
|
|
|
import { TransportHTTP } from "@meshtastic/transport-http"; |
|
|
|
import { useState } from "react"; |
|
|
|
import { useForm, useController } from "react-hook-form"; |
|
|
|
import { AlertTriangle } from "lucide-react"; |
|
|
|
|
|
|
|
interface FormData { |
|
|
|
ip: string; |
|
|
|
@ -39,23 +41,33 @@ export const HTTP = ({ closeDialog }: TabElementProps) => { |
|
|
|
} = useController({ name: "tls", control }); |
|
|
|
|
|
|
|
const [connectionInProgress, setConnectionInProgress] = useState(false); |
|
|
|
const [connectionError, setConnectionError] = useState<{ host: string; secure: boolean } | null>(null); |
|
|
|
|
|
|
|
const onSubmit = handleSubmit(async (data) => { |
|
|
|
setConnectionInProgress(true); |
|
|
|
const id = randId(); |
|
|
|
const device = addDevice(id); |
|
|
|
const transport = await TransportHTTP.create(data.ip, data.tls); |
|
|
|
const connection = new MeshDevice(transport, id); |
|
|
|
connection.configure(); |
|
|
|
setSelectedDevice(id); |
|
|
|
device.addConnection(connection); |
|
|
|
subscribeAll(device, connection); |
|
|
|
closeDialog(); |
|
|
|
setConnectionError(null); |
|
|
|
|
|
|
|
try { |
|
|
|
const id = randId(); |
|
|
|
const transport = await TransportHTTP.create(data.ip, data.tls); |
|
|
|
const device = addDevice(id); |
|
|
|
const connection = new MeshDevice(transport, id); |
|
|
|
connection.configure(); |
|
|
|
setSelectedDevice(id); |
|
|
|
device.addConnection(connection); |
|
|
|
subscribeAll(device, connection); |
|
|
|
closeDialog(); |
|
|
|
} catch (error) { |
|
|
|
console.error("Connection error:", error); |
|
|
|
// Capture all connection errors regardless of type
|
|
|
|
setConnectionError({ host: data.ip, secure: data.tls }); |
|
|
|
setConnectionInProgress(false); |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
return ( |
|
|
|
<form className="flex w-full flex-col gap-2 p-4" onSubmit={onSubmit}> |
|
|
|
<div className="flex h-48 flex-col gap-2"> |
|
|
|
<div className="flex flex-col gap-2" style={{ minHeight: "12rem" }}> |
|
|
|
<div> |
|
|
|
<Label>IP Address/Hostname</Label> |
|
|
|
<Input |
|
|
|
@ -74,8 +86,37 @@ export const HTTP = ({ closeDialog }: TabElementProps) => { |
|
|
|
{...register("tls")} |
|
|
|
/> |
|
|
|
<Label>Use HTTPS</Label> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
{connectionError && ( |
|
|
|
<div className="mt-2 mb-2 p-3 rounded-md bg-amber-100 border border-amber-300 dark:bg-amber-100 dark:border-amber-300"> |
|
|
|
<div className="flex gap-2 items-start"> |
|
|
|
<AlertTriangle className="shrink-0 mt-0.5 text-amber-600 dark:text-amber-600" size={20} /> |
|
|
|
<div> |
|
|
|
<p className="text-sm font-medium text-amber-800 dark:text-amber-800"> |
|
|
|
Connection Failed |
|
|
|
</p> |
|
|
|
<p className="text-xs mt-1 text-amber-700 dark:text-amber-700"> |
|
|
|
Could not connect to the device. {connectionError.secure && "If using HTTPS, you may need to accept a self-signed certificate first. "} |
|
|
|
Please open{" "} |
|
|
|
<Link |
|
|
|
href={`${connectionError.secure ? "https" : "http"}://${connectionError.host}`} |
|
|
|
className="underline font-medium text-amber-800 dark:text-amber-800" |
|
|
|
> |
|
|
|
{`${connectionError.secure ? "https" : "http"}://${connectionError.host}`} |
|
|
|
</Link>{" "} |
|
|
|
in a new tab{connectionError.secure ? ", accept any TLS warnings if prompted, then try again" : ""}.{" "} |
|
|
|
<Link |
|
|
|
href="https://meshtastic.org/docs/software/web-client/#http" |
|
|
|
className="underline font-medium text-amber-800 dark:text-amber-800" |
|
|
|
> |
|
|
|
Learn more |
|
|
|
</Link> |
|
|
|
</p> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
)} |
|
|
|
</div> |
|
|
|
<Button |
|
|
|
type="submit" |
|
|
|
|