Channel PSK generator
This commit is contained in:
+53
-14
@@ -1,13 +1,16 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { useForm } from 'react-hook-form';
|
import { fromByteArray, toByteArray } from 'base64-js';
|
||||||
|
import { useForm, useWatch } from 'react-hook-form';
|
||||||
import { FaQrcode } from 'react-icons/fa';
|
import { FaQrcode } from 'react-icons/fa';
|
||||||
import { FiEdit3, FiSave } from 'react-icons/fi';
|
import { FiEdit3, FiSave } from 'react-icons/fi';
|
||||||
|
import { MdRefresh, MdVisibility, MdVisibilityOff } from 'react-icons/md';
|
||||||
import QRCode from 'react-qr-code';
|
import QRCode from 'react-qr-code';
|
||||||
|
|
||||||
import { Card } from '@components/generic/Card';
|
import { Card } from '@components/generic/Card';
|
||||||
import { Checkbox } from '@components/generic/form/Checkbox';
|
import { Checkbox } from '@components/generic/form/Checkbox';
|
||||||
import { Input } from '@components/generic/form/Input';
|
import { Input } from '@components/generic/form/Input';
|
||||||
|
import { Select } from '@components/generic/form/Select';
|
||||||
import { IconButton } from '@components/generic/IconButton';
|
import { IconButton } from '@components/generic/IconButton';
|
||||||
import { Loading } from '@components/generic/Loading';
|
import { Loading } from '@components/generic/Loading';
|
||||||
import { Modal } from '@components/generic/Modal';
|
import { Modal } from '@components/generic/Modal';
|
||||||
@@ -16,18 +19,17 @@ import { Protobuf } from '@meshtastic/meshtasticjs';
|
|||||||
|
|
||||||
export interface ChannelProps {
|
export interface ChannelProps {
|
||||||
channel: Protobuf.Channel;
|
channel: Protobuf.Channel;
|
||||||
hideEnabled?: boolean;
|
isPrimary?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Channel = ({
|
export const Channel = ({ channel, isPrimary }: ChannelProps): JSX.Element => {
|
||||||
channel,
|
|
||||||
hideEnabled,
|
|
||||||
}: ChannelProps): JSX.Element => {
|
|
||||||
const [edit, setEdit] = React.useState(false);
|
const [edit, setEdit] = React.useState(false);
|
||||||
const [loading, setLoading] = React.useState(false);
|
const [loading, setLoading] = React.useState(false);
|
||||||
const [showQr, setShowQr] = React.useState(false);
|
const [showQr, setShowQr] = React.useState(false);
|
||||||
|
const [keySize, setKeySize] = React.useState<128 | 256>(256);
|
||||||
|
const [pskHidden, setPskHidden] = React.useState(true);
|
||||||
|
|
||||||
const { register, handleSubmit } = useForm<{
|
const { register, handleSubmit, setValue, control } = useForm<{
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
settings: {
|
settings: {
|
||||||
name: string;
|
name: string;
|
||||||
@@ -55,11 +57,17 @@ export const Channel = ({
|
|||||||
downlinkEnabled: channel.settings?.downlinkEnabled,
|
downlinkEnabled: channel.settings?.downlinkEnabled,
|
||||||
uplinkEnabled: channel.settings?.uplinkEnabled,
|
uplinkEnabled: channel.settings?.uplinkEnabled,
|
||||||
txPower: channel.settings?.txPower,
|
txPower: channel.settings?.txPower,
|
||||||
psk: new TextDecoder().decode(channel.settings?.psk),
|
psk: fromByteArray(channel.settings?.psk ?? new Uint8Array(0)),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const watchPsk = useWatch({
|
||||||
|
control,
|
||||||
|
name: 'settings.psk',
|
||||||
|
defaultValue: '',
|
||||||
|
});
|
||||||
|
|
||||||
const onSubmit = handleSubmit(async (data) => {
|
const onSubmit = handleSubmit(async (data) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const adminChannel = Protobuf.Channel.create({
|
const adminChannel = Protobuf.Channel.create({
|
||||||
@@ -72,7 +80,7 @@ export const Channel = ({
|
|||||||
index: channel.index,
|
index: channel.index,
|
||||||
settings: {
|
settings: {
|
||||||
...data.settings,
|
...data.settings,
|
||||||
psk: new TextEncoder().encode(data.settings.psk),
|
psk: toByteArray(data.settings.psk ?? ''),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -91,26 +99,57 @@ export const Channel = ({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Card>
|
<Card>
|
||||||
<QRCode className="rounded-md" value="test" />
|
<QRCode
|
||||||
|
className="rounded-md"
|
||||||
|
value={`https://www.meshtastic.org/d/#${watchPsk}`}
|
||||||
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
</Modal>
|
</Modal>
|
||||||
{edit ? (
|
{edit ? (
|
||||||
<>
|
<>
|
||||||
{loading && <Loading />}
|
{loading && <Loading />}
|
||||||
<div className="flex my-auto">
|
<div className="flex my-auto">
|
||||||
{/* TODO: get gap working */}
|
|
||||||
<form className="gap-3">
|
<form className="gap-3">
|
||||||
{/* @todo: change to disable & make primary buttons */}
|
{!isPrimary && (
|
||||||
{!hideEnabled && (
|
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label="Enabled"
|
label="Enabled"
|
||||||
{...register('enabled', { valueAsNumber: true })}
|
{...register('enabled', { valueAsNumber: true })}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Input label="Name" {...register('settings.name')} />
|
<Input label="Name" {...register('settings.name')} />
|
||||||
|
<Select
|
||||||
|
label="Key Size"
|
||||||
|
options={[
|
||||||
|
{ name: '128 Bit', value: 128 },
|
||||||
|
{ name: '256 Bit', value: 256 },
|
||||||
|
]}
|
||||||
|
value={keySize}
|
||||||
|
onChange={(e): void => {
|
||||||
|
setKeySize(parseInt(e.target.value) as 128 | 256);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<Input
|
<Input
|
||||||
label="Pre-Shared Key"
|
label="Pre-Shared Key"
|
||||||
type="password"
|
type={pskHidden ? 'password' : 'text'}
|
||||||
|
disabled
|
||||||
|
action={
|
||||||
|
<>
|
||||||
|
<IconButton
|
||||||
|
onClick={(): void => {
|
||||||
|
setPskHidden(!setPskHidden);
|
||||||
|
}}
|
||||||
|
icon={pskHidden ? <MdVisibility /> : <MdVisibilityOff />}
|
||||||
|
/>
|
||||||
|
<IconButton
|
||||||
|
onClick={(): void => {
|
||||||
|
const key = new Uint8Array(keySize);
|
||||||
|
crypto.getRandomValues(key);
|
||||||
|
setValue('settings.psk', fromByteArray(key));
|
||||||
|
}}
|
||||||
|
icon={<MdRefresh />}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
}
|
||||||
{...register('settings.psk')}
|
{...register('settings.psk')}
|
||||||
/>
|
/>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
|
|||||||
@@ -246,7 +246,7 @@ export const Channels = ({
|
|||||||
<Channel
|
<Channel
|
||||||
key={channel.channel.index}
|
key={channel.channel.index}
|
||||||
channel={channel.channel}
|
channel={channel.channel}
|
||||||
hideEnabled={channel.channel.index === 0}
|
isPrimary={channel.channel.index === 0}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user