You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
136 lines
4.0 KiB
136 lines
4.0 KiB
import { useEffect, useState } from "react";
|
|
import { toByteArray } from "base64-js";
|
|
import { Checkbox } from "@components/form/Checkbox.js";
|
|
import { Input } from "@components/form/Input.js";
|
|
import { Dialog } from "@components/generic/Dialog.js";
|
|
import { Protobuf } from "@meshtastic/meshtasticjs";
|
|
import { Select } from "@components/form/Select.js";
|
|
import { renderOptions } from "@core/utils/selectEnumOptions.js";
|
|
import { Toggle } from "@components/form/Toggle.js";
|
|
import { Button } from "@components/form/Button.js";
|
|
import { useDevice } from "@core/providers/useDevice.js";
|
|
|
|
export interface ImportDialogProps {
|
|
isOpen: boolean;
|
|
close: () => void;
|
|
loraConfig?: Protobuf.Config_LoRaConfig;
|
|
channels: Protobuf.Channel[];
|
|
}
|
|
|
|
export const ImportDialog = ({
|
|
isOpen,
|
|
close
|
|
}: ImportDialogProps): JSX.Element => {
|
|
const [QRCodeURL, setQRCodeURL] = useState<string>("");
|
|
const [channelSet, setChannelSet] = useState<Protobuf.ChannelSet>();
|
|
const [validURL, setValidURL] = useState<boolean>(false);
|
|
|
|
const { connection } = useDevice();
|
|
|
|
useEffect(() => {
|
|
const base64String = QRCodeURL.split("e/#")[1]
|
|
?.replace(/-/g, "+")
|
|
.replace(/_/g, "/")
|
|
.padEnd(QRCodeURL.length + ((4 - (QRCodeURL.length % 4)) % 4), "=");
|
|
try {
|
|
setChannelSet(Protobuf.ChannelSet.fromBinary(toByteArray(base64String)));
|
|
setValidURL(true);
|
|
} catch (error) {
|
|
setValidURL(false);
|
|
setChannelSet(undefined);
|
|
}
|
|
}, [QRCodeURL]);
|
|
|
|
const apply = () => {
|
|
channelSet?.settings.map((ch, index) => {
|
|
connection?.setChannel(
|
|
new Protobuf.Channel({
|
|
index,
|
|
role:
|
|
index === 0
|
|
? Protobuf.Channel_Role.PRIMARY
|
|
: Protobuf.Channel_Role.SECONDARY,
|
|
settings: ch
|
|
})
|
|
);
|
|
});
|
|
|
|
if (channelSet?.loraConfig) {
|
|
connection?.setConfig(
|
|
new Protobuf.Config({
|
|
payloadVariant: {
|
|
case: "lora",
|
|
value: channelSet.loraConfig
|
|
}
|
|
})
|
|
);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Dialog
|
|
title={"Import Channel Set"}
|
|
description={"The current LoRa configuration will be overridden."}
|
|
isOpen={isOpen}
|
|
close={close}
|
|
>
|
|
<div className="flex flex-col gap-3">
|
|
<Input
|
|
label="Channel Set/QR Code URL"
|
|
value={QRCodeURL}
|
|
suffix={validURL ? "✅" : "❌"}
|
|
onChange={(e) => {
|
|
setQRCodeURL(e.target.value);
|
|
}}
|
|
/>
|
|
{validURL && (
|
|
<div className="flex flex-col gap-3">
|
|
<div className="flex w-full gap-2">
|
|
<div className="w-36">
|
|
<Toggle
|
|
className="flex-col gap-2"
|
|
label="Use Preset?"
|
|
disabled
|
|
checked={channelSet?.loraConfig?.usePreset ?? true}
|
|
/>
|
|
</div>
|
|
<Select
|
|
label="Modem Preset"
|
|
disabled
|
|
value={channelSet?.loraConfig?.modemPreset}
|
|
>
|
|
{renderOptions(Protobuf.Config_LoRaConfig_ModemPreset)}
|
|
</Select>
|
|
</div>
|
|
<Select
|
|
label="Region"
|
|
disabled
|
|
value={channelSet?.loraConfig?.region}
|
|
>
|
|
{renderOptions(Protobuf.Config_LoRaConfig_RegionCode)}
|
|
</Select>
|
|
|
|
<span className="text-md block font-medium text-textPrimary">
|
|
Channels:
|
|
</span>
|
|
<div className="flex w-40 flex-col gap-1">
|
|
{channelSet?.settings.map((channel, index) => (
|
|
<Checkbox
|
|
key={index}
|
|
label={
|
|
channel.name.length
|
|
? channel.name
|
|
: `Channel: ${channel.id}`
|
|
}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
<Button onClick={() => apply()} disabled={!validURL}>
|
|
Apply
|
|
</Button>
|
|
</div>
|
|
</Dialog>
|
|
);
|
|
};
|
|
|