Merge branch 'master' into feat/add-error-boundary

This commit is contained in:
Dan Ditomaso
2025-03-01 09:09:57 -05:00
committed by GitHub
75 changed files with 401 additions and 343 deletions
+3 -2
View File
@@ -1,8 +1,9 @@
import type { ChannelValidation } from "@app/validation/channel.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useToast } from "@core/hooks/useToast.ts";
import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js";
import { Protobuf } from "@meshtastic/core";
import { fromByteArray, toByteArray } from "base64-js";
import cryptoRandomString from "crypto-random-string";
import { useState } from "react";
@@ -27,7 +28,7 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => {
useState<boolean>(false);
const onSubmit = (data: ChannelValidation) => {
const channel = new Protobuf.Channel.Channel({
const channel = create(Protobuf.Channel.ChannelSchema, {
...data,
settings: {
...data.settings,
@@ -1,8 +1,9 @@
import { useAppStore } from "@app/core/stores/appStore";
import type { BluetoothValidation } from "@app/validation/config/bluetooth.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js";
import { Protobuf } from "@meshtastic/core";
import { useState } from "react";
export const Bluetooth = () => {
@@ -53,7 +54,7 @@ export const Bluetooth = () => {
}
setWorkingConfig(
new Protobuf.Config.Config({
create(Protobuf.Config.ConfigSchema, {
payloadVariant: {
case: "bluetooth",
value: data,
@@ -1,14 +1,15 @@
import type { DeviceValidation } from "@app/validation/config/device.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js";
import { Protobuf } from "@meshtastic/core";
export const Device = (): JSX.Element => {
const { config, setWorkingConfig } = useDevice();
const onSubmit = (data: DeviceValidation) => {
setWorkingConfig(
new Protobuf.Config.Config({
create(Protobuf.Config.ConfigSchema, {
payloadVariant: {
case: "device",
value: data,
@@ -1,14 +1,15 @@
import type { DisplayValidation } from "@app/validation/config/display.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js";
import { Protobuf } from "@meshtastic/core";
export const Display = (): JSX.Element => {
const { config, setWorkingConfig } = useDevice();
const onSubmit = (data: DisplayValidation) => {
setWorkingConfig(
new Protobuf.Config.Config({
create(Protobuf.Config.ConfigSchema, {
payloadVariant: {
case: "display",
value: data,
@@ -1,14 +1,15 @@
import type { LoRaValidation } from "@app/validation/config/lora.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js";
import { Protobuf } from "@meshtastic/core";
export const LoRa = (): JSX.Element => {
const { config, setWorkingConfig } = useDevice();
const onSubmit = (data: LoRaValidation) => {
setWorkingConfig(
new Protobuf.Config.Config({
create(Protobuf.Config.ConfigSchema, {
payloadVariant: {
case: "lora",
value: data,
@@ -1,28 +1,32 @@
import type { NetworkValidation } from "@app/validation/config/network.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts";
import {
convertIntToIpAddress,
convertIpAddressToInt,
} from "@core/utils/ip.ts";
import { Protobuf } from "@meshtastic/js";
import { Protobuf } from "@meshtastic/core";
export const Network = (): JSX.Element => {
const { config, setWorkingConfig } = useDevice();
const onSubmit = (data: NetworkValidation) => {
setWorkingConfig(
new Protobuf.Config.Config({
create(Protobuf.Config.ConfigSchema, {
payloadVariant: {
case: "network",
value: {
...data,
ipv4Config: new Protobuf.Config.Config_NetworkConfig_IpV4Config({
ip: convertIpAddressToInt(data.ipv4Config.ip) ?? 0,
gateway: convertIpAddressToInt(data.ipv4Config.gateway) ?? 0,
subnet: convertIpAddressToInt(data.ipv4Config.subnet) ?? 0,
dns: convertIpAddressToInt(data.ipv4Config.dns) ?? 0,
}),
ipv4Config: create(
Protobuf.Config.Config_NetworkConfig_IpV4ConfigSchema,
{
ip: convertIpAddressToInt(data.ipv4Config.ip) ?? 0,
gateway: convertIpAddressToInt(data.ipv4Config.gateway) ?? 0,
subnet: convertIpAddressToInt(data.ipv4Config.subnet) ?? 0,
dns: convertIpAddressToInt(data.ipv4Config.dns) ?? 0,
},
),
},
},
}),
@@ -3,9 +3,10 @@ import {
usePositionFlags,
} from "@app/core/hooks/usePositionFlags";
import type { PositionValidation } from "@app/validation/config/position.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js";
import { Protobuf } from "@meshtastic/core";
import { useCallback } from "react";
export const Position = () => {
@@ -16,7 +17,7 @@ export const Position = () => {
const onSubmit = (data: PositionValidation) => {
return setWorkingConfig(
new Protobuf.Config.Config({
create(Protobuf.Config.ConfigSchema, {
payloadVariant: {
case: "position",
value: { ...data, positionFlags: flagsValue },
@@ -1,14 +1,15 @@
import type { PowerValidation } from "@app/validation/config/power.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js";
import { Protobuf } from "@meshtastic/core";
export const Power = (): JSX.Element => {
const { config, setWorkingConfig } = useDevice();
const onSubmit = (data: PowerValidation) => {
setWorkingConfig(
new Protobuf.Config.Config({
create(Protobuf.Config.ConfigSchema, {
payloadVariant: {
case: "power",
value: data,
@@ -6,8 +6,9 @@ import {
getX25519PublicKey,
} from "@app/core/utils/x25519";
import type { SecurityValidation } from "@app/validation/config/security.tsx";
import { create } from "@bufbuild/protobuf";
import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js";
import { Protobuf } from "@meshtastic/core";
import { fromByteArray, toByteArray } from "base64-js";
import { Eye, EyeOff } from "lucide-react";
import { useReducer } from "react";
@@ -57,7 +58,9 @@ export const Security = () => {
if (input.length % 4 !== 0) {
addError(
fieldName,
`${fieldName === "privateKey" ? "Private" : "Admin"} Key is required to be a 256 bit pre-shared key (PSK)`,
`${
fieldName === "privateKey" ? "Private" : "Admin"
} Key is required to be a 256 bit pre-shared key (PSK)`,
);
return;
}
@@ -71,7 +74,9 @@ export const Security = () => {
console.error(e);
addError(
fieldName,
`Invalid ${fieldName === "privateKey" ? "Private" : "Admin"} Key format`,
`Invalid ${
fieldName === "privateKey" ? "Private" : "Admin"
} Key format`,
);
}
};
@@ -83,7 +88,7 @@ export const Security = () => {
console.log(toByteArray(state.adminKey));
setWorkingConfig(
new Protobuf.Config.Config({
create(Protobuf.Config.ConfigSchema, {
payloadVariant: {
case: "security",
value: {
@@ -164,6 +169,7 @@ export const Security = () => {
fields: [
{
type: "passwordGenerator",
id: "pskInput",
name: "privateKey",
label: "Private Key",
description: "Used to create a shared key with a remote device",
@@ -234,6 +240,7 @@ export const Security = () => {
{
type: "passwordGenerator",
name: "adminKey",
id: "adminKeyInput",
label: "Admin Key",
description:
"The public key authorized to send admin messages to this node",
@@ -241,7 +248,7 @@ export const Security = () => {
? getErrorMessage("adminKey")
: "",
inputChange: adminKeyInputChangeEvent,
selectChange: () => { },
selectChange: () => {},
bits: [{ text: "256 bit", value: "32", key: "bit256" }],
devicePSKBitCount: state.privateKeyBitCount,
hide: !state.adminKeyVisible,
@@ -7,7 +7,8 @@ import { useAppStore } from "@core/stores/appStore.ts";
import { useDeviceStore } from "@core/stores/deviceStore.ts";
import { subscribeAll } from "@core/subscriptions.ts";
import { randId } from "@core/utils/randId.ts";
import { HttpConnection } from "@meshtastic/js";
import { MeshDevice } from "@meshtastic/core";
import { TransportHTTP } from "@meshtastic/transport-http";
import { type JSX, useState } from "react";
import { Controller, useForm } from "react-hook-form";
@@ -36,13 +37,9 @@ export const HTTP = ({ closeDialog }: TabElementProps): JSX.Element => {
const id = randId();
const device = addDevice(id);
const connection = new HttpConnection(id);
// TODO: Promise never resolves
await connection.connect({
address: data.ip,
fetchInterval: 2000,
tls: data.tls,
});
const transport = await TransportHTTP.create(data.ip, data.tls);
const connection = new MeshDevice(transport, id);
connection.configure();
setSelectedDevice(id);
device.addConnection(connection);
@@ -5,7 +5,8 @@ import { useAppStore } from "@core/stores/appStore.ts";
import { useDeviceStore } from "@core/stores/deviceStore.ts";
import { subscribeAll } from "@core/subscriptions.ts";
import { randId } from "@core/utils/randId.ts";
import { SerialConnection } from "@meshtastic/js";
import { MeshDevice } from "@meshtastic/core";
import { TransportWebSerial } from "@meshtastic/transport-web-serial";
import { useCallback, useEffect, useState } from "react";
export const Serial = ({ closeDialog }: TabElementProps): JSX.Element => {
@@ -31,14 +32,9 @@ export const Serial = ({ closeDialog }: TabElementProps): JSX.Element => {
const id = randId();
const device = addDevice(id);
setSelectedDevice(id);
const connection = new SerialConnection(id);
await connection
.connect({
port,
baudRate: undefined,
concurrentLogOutput: true,
})
.catch((e: Error) => console.log(`Unable to Connect: ${e.message}`));
const transport = await TransportWebSerial.createFromPort(port);
const connection = new MeshDevice(transport, id);
connection.configure();
device.addConnection(connection);
subscribeAll(device, connection);
@@ -5,8 +5,8 @@ import { formatQuantity } from "@app/core/utils/string";
import { Avatar } from "@components/UI/Avatar";
import { Mono } from "@components/generic/Mono.tsx";
import { TimeAgo } from "@components/generic/TimeAgo.tsx";
import { Protobuf } from "@meshtastic/js";
import type { Protobuf as ProtobufType } from "@meshtastic/js";
import { Protobuf } from "@meshtastic/core";
import type { Protobuf as ProtobufType } from "@meshtastic/core";
import { numberToHexUnpadded } from "@noble/curves/abstract/utils";
import {
BatteryChargingIcon,
@@ -4,7 +4,7 @@ import {
} from "@app/core/stores/deviceStore.ts";
import { Message } from "@components/PageComponents/Messages/Message.tsx";
import { MessageInput } from "@components/PageComponents/Messages/MessageInput.tsx";
import type { Types } from "@meshtastic/js";
import type { Types } from "@meshtastic/core";
import { InboxIcon } from "lucide-react";
import { useCallback, useEffect, useRef } from "react";
import type { JSX } from "react";
@@ -11,7 +11,7 @@ import {
} from "@app/core/stores/deviceStore.ts";
import { cn } from "@app/core/utils/cn";
import { Avatar } from "@components/UI/Avatar";
import type { Protobuf } from "@meshtastic/js";
import type { Protobuf } from "@meshtastic/core";
import { AlertCircle, CheckCircle2, CircleEllipsis } from "lucide-react";
import type { LucideIcon } from "lucide-react";
import { useMemo } from "react";
@@ -2,7 +2,7 @@ import { debounce } from "@app/core/utils/debounce";
import { Button } from "@components/UI/Button.tsx";
import { Input } from "@components/UI/Input.tsx";
import { useDevice } from "@core/stores/deviceStore.ts";
import type { Types } from "@meshtastic/js";
import type { Types } from "@meshtastic/core";
import { SendIcon } from "lucide-react";
import {
type JSX,
@@ -1,5 +1,5 @@
import { useDevice } from "@app/core/stores/deviceStore.ts";
import type { Protobuf } from "@meshtastic/js";
import type { Protobuf } from "@meshtastic/core";
import { numberToHexUnpadded } from "@noble/curves/abstract/utils";
import type { JSX } from "react";
@@ -1,14 +1,15 @@
import { useDevice } from "@app/core/stores/deviceStore.ts";
import type { AmbientLightingValidation } from "@app/validation/moduleConfig/ambientLighting.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { Protobuf } from "@meshtastic/js";
import { Protobuf } from "@meshtastic/core";
export const AmbientLighting = (): JSX.Element => {
const { moduleConfig, setWorkingModuleConfig } = useDevice();
const onSubmit = (data: AmbientLightingValidation) => {
setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({
create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: {
case: "ambientLighting",
value: data,
@@ -1,14 +1,15 @@
import type { AudioValidation } from "@app/validation/moduleConfig/audio.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js";
import { Protobuf } from "@meshtastic/core";
export const Audio = (): JSX.Element => {
const { moduleConfig, setWorkingModuleConfig } = useDevice();
const onSubmit = (data: AudioValidation) => {
setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({
create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: {
case: "audio",
value: data,
@@ -1,14 +1,15 @@
import type { CannedMessageValidation } from "@app/validation/moduleConfig/cannedMessage.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js";
import { Protobuf } from "@meshtastic/core";
export const CannedMessage = (): JSX.Element => {
const { moduleConfig, setWorkingModuleConfig } = useDevice();
const onSubmit = (data: CannedMessageValidation) => {
setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({
create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: {
case: "cannedMessage",
value: data,
@@ -1,14 +1,15 @@
import { useDevice } from "@app/core/stores/deviceStore.ts";
import type { DetectionSensorValidation } from "@app/validation/moduleConfig/detectionSensor.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { Protobuf } from "@meshtastic/js";
import { Protobuf } from "@meshtastic/core";
export const DetectionSensor = (): JSX.Element => {
const { moduleConfig, setWorkingModuleConfig } = useDevice();
const onSubmit = (data: DetectionSensorValidation) => {
setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({
create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: {
case: "detectionSensor",
value: data,
@@ -1,14 +1,15 @@
import type { ExternalNotificationValidation } from "@app/validation/moduleConfig/externalNotification.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js";
import { Protobuf } from "@meshtastic/core";
export const ExternalNotification = (): JSX.Element => {
const { moduleConfig, setWorkingModuleConfig } = useDevice();
const onSubmit = (data: ExternalNotificationValidation) => {
setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({
create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: {
case: "externalNotification",
value: data,
@@ -1,22 +1,23 @@
import { useDevice } from "@app/core/stores/deviceStore.ts";
import type { MqttValidation } from "@app/validation/moduleConfig/mqtt.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { Protobuf } from "@meshtastic/js";
import { Protobuf } from "@meshtastic/core";
export const MQTT = (): JSX.Element => {
const { config, moduleConfig, setWorkingModuleConfig } = useDevice();
const onSubmit = (data: MqttValidation) => {
setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({
create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: {
case: "mqtt",
value: {
...data,
mapReportSettings:
new Protobuf.ModuleConfig.ModuleConfig_MapReportSettings(
data.mapReportSettings,
),
mapReportSettings: create(
Protobuf.ModuleConfig.ModuleConfig_MapReportSettingsSchema,
data.mapReportSettings,
),
},
},
}),
@@ -1,14 +1,15 @@
import { useDevice } from "@app/core/stores/deviceStore.ts";
import type { NeighborInfoValidation } from "@app/validation/moduleConfig/neighborInfo.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { Protobuf } from "@meshtastic/js";
import { Protobuf } from "@meshtastic/core";
export const NeighborInfo = (): JSX.Element => {
const { moduleConfig, setWorkingModuleConfig } = useDevice();
const onSubmit = (data: NeighborInfoValidation) => {
setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({
create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: {
case: "neighborInfo",
value: data,
@@ -1,14 +1,15 @@
import type { PaxcounterValidation } from "@app/validation/moduleConfig/paxcounter.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js";
import { Protobuf } from "@meshtastic/core";
export const Paxcounter = (): JSX.Element => {
const { moduleConfig, setWorkingModuleConfig } = useDevice();
const onSubmit = (data: PaxcounterValidation) => {
setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({
create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: {
case: "paxcounter",
value: data,
@@ -1,14 +1,15 @@
import type { RangeTestValidation } from "@app/validation/moduleConfig/rangeTest.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js";
import { Protobuf } from "@meshtastic/core";
export const RangeTest = (): JSX.Element => {
const { moduleConfig, setWorkingModuleConfig } = useDevice();
const onSubmit = (data: RangeTestValidation) => {
setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({
create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: {
case: "rangeTest",
value: data,
@@ -1,14 +1,15 @@
import type { SerialValidation } from "@app/validation/moduleConfig/serial.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js";
import { Protobuf } from "@meshtastic/core";
export const Serial = (): JSX.Element => {
const { moduleConfig, setWorkingModuleConfig } = useDevice();
const onSubmit = (data: SerialValidation) => {
setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({
create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: {
case: "serial",
value: data,
@@ -1,14 +1,15 @@
import type { StoreForwardValidation } from "@app/validation/moduleConfig/storeForward.ts";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js";
import { Protobuf } from "@meshtastic/core";
export const StoreForward = (): JSX.Element => {
const { moduleConfig, setWorkingModuleConfig } = useDevice();
const onSubmit = (data: StoreForwardValidation) => {
setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({
create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: {
case: "storeForward",
value: data,
@@ -1,14 +1,15 @@
import type { TelemetryValidation } from "@app/validation/moduleConfig/telemetry.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js";
import { Protobuf } from "@meshtastic/core";
export const Telemetry = (): JSX.Element => {
const { moduleConfig, setWorkingModuleConfig } = useDevice();
const onSubmit = (data: TelemetryValidation) => {
setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({
create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: {
case: "telemetry",
value: data,