Browse Source

update dependencies

pull/476/head
Sacha Weatherstone 1 year ago
parent
commit
a5589e232b
Failed to extract signature
  1. 2
      .npmrc
  2. 40
      package.json
  3. 30
      src/App.tsx
  4. 3
      src/components/Dialog/DeviceNameDialog.tsx
  5. 29
      src/components/Dialog/ImportDialog.tsx
  6. 18
      src/components/Dialog/QRDialog.tsx
  7. 68
      src/components/PageComponents/Channel.tsx
  8. 8
      src/components/PageComponents/Config/Bluetooth.tsx
  9. 3
      src/components/PageComponents/Config/Device.tsx
  10. 3
      src/components/PageComponents/Config/Display.tsx
  11. 3
      src/components/PageComponents/Config/LoRa.tsx
  12. 18
      src/components/PageComponents/Config/Network.tsx
  13. 3
      src/components/PageComponents/Config/Position.tsx
  14. 3
      src/components/PageComponents/Config/Power.tsx
  15. 16
      src/components/PageComponents/Config/Security/Security.tsx
  16. 3
      src/components/PageComponents/ModuleConfig/AmbientLighting.tsx
  17. 3
      src/components/PageComponents/ModuleConfig/Audio.tsx
  18. 18
      src/components/PageComponents/ModuleConfig/CannedMessage.tsx
  19. 3
      src/components/PageComponents/ModuleConfig/DetectionSensor.tsx
  20. 3
      src/components/PageComponents/ModuleConfig/ExternalNotification.tsx
  21. 63
      src/components/PageComponents/ModuleConfig/MQTT.tsx
  22. 3
      src/components/PageComponents/ModuleConfig/NeighborInfo.tsx
  23. 3
      src/components/PageComponents/ModuleConfig/Paxcounter.tsx
  24. 3
      src/components/PageComponents/ModuleConfig/RangeTest.tsx
  25. 3
      src/components/PageComponents/ModuleConfig/Serial.tsx
  26. 3
      src/components/PageComponents/ModuleConfig/StoreForward.tsx
  27. 3
      src/components/PageComponents/ModuleConfig/Telemetry.tsx
  28. 51
      src/core/stores/deviceStore.ts
  29. 29
      src/pages/Map/index.tsx
  30. 4
      tsconfig.json

2
.npmrc

@ -1 +1 @@
@buf:registry=https://buf.build/gen/npm/v1 @jsr:registry=https://npm.jsr.io

40
package.json

@ -37,8 +37,8 @@
}, },
"homepage": "https://meshtastic.org", "homepage": "https://meshtastic.org",
"dependencies": { "dependencies": {
"@bufbuild/protobuf": "^1.10.0", "@bufbuild/protobuf": "^2.2.3",
"@meshtastic/js": "2.3.7-5", "@meshtastic/js": "npm:@jsr/[email protected]",
"@noble/curves": "^1.8.1", "@noble/curves": "^1.8.1",
"@radix-ui/react-accordion": "^1.2.3", "@radix-ui/react-accordion": "^1.2.3",
"@radix-ui/react-checkbox": "^1.1.4", "@radix-ui/react-checkbox": "^1.1.4",
@ -63,44 +63,44 @@
"crypto-random-string": "^5.0.0", "crypto-random-string": "^5.0.0",
"immer": "^10.1.1", "immer": "^10.1.1",
"js-cookie": "^3.0.5", "js-cookie": "^3.0.5",
"lucide-react": "^0.475.0", "lucide-react": "^0.477.0",
"mapbox-gl": "^3.9.4", "mapbox-gl": "^3.10.0",
"maplibre-gl": "4.1.2", "maplibre-gl": "5.1.1",
"react": "^19.0.0", "react": "^19.0.0",
"react-dom": "^19.0.0", "react-dom": "^19.0.0",
"react-hook-form": "^7.54.2", "react-hook-form": "^7.54.2",
"react-map-gl": "7.1.9", "react-map-gl": "8.0.1",
"react-qrcode-logo": "^3.0.0", "react-qrcode-logo": "^3.0.0",
"react-scan": "^0.2.4", "react-scan": "^0.2.8",
"rfc4648": "^1.5.4", "rfc4648": "^1.5.4",
"vite-plugin-node-polyfills": "^0.23.0", "vite-plugin-node-polyfills": "^0.23.0",
"zustand": "5.0.3" "zustand": "5.0.3"
}, },
"devDependencies": { "devDependencies": {
"@biomejs/biome": "^1.9.4", "@biomejs/biome": "^1.9.4",
"@tailwindcss/postcss": "^4.0.7", "@tailwindcss/postcss": "^4.0.9",
"@testing-library/react": "^16.2.0", "@testing-library/react": "^16.2.0",
"@types/chrome": "^0.0.304", "@types/chrome": "^0.0.307",
"@types/js-cookie": "^3.0.6", "@types/js-cookie": "^3.0.6",
"@types/node": "^22.13.4", "@types/node": "^22.13.7",
"@types/react": "^19.0.10", "@types/react": "^19.0.10",
"@types/react-dom": "^19.0.4", "@types/react-dom": "^19.0.4",
"@types/serviceworker": "^0.0.122", "@types/serviceworker": "^0.0.123",
"@types/w3c-web-serial": "^1.0.7", "@types/w3c-web-serial": "^1.0.8",
"@types/web-bluetooth": "^0.0.20", "@types/web-bluetooth": "^0.0.21",
"@vitejs/plugin-react": "^4.3.4", "@vitejs/plugin-react": "^4.3.4",
"autoprefixer": "^10.4.20", "autoprefixer": "^10.4.20",
"gzipper": "^8.2.0", "gzipper": "^8.2.0",
"happy-dom": "^17.1.4", "happy-dom": "^17.1.8",
"postcss": "^8.5.1", "postcss": "^8.5.3",
"simple-git-hooks": "^2.11.1", "simple-git-hooks": "^2.11.1",
"tailwind-merge": "^3.0.1", "tailwind-merge": "^3.0.2",
"tailwindcss": "^4.0.7", "tailwindcss": "^4.0.9",
"tailwindcss-animate": "^1.0.7", "tailwindcss-animate": "^1.0.7",
"tar": "^7.4.3", "tar": "^7.4.3",
"typescript": "^5.7.3", "typescript": "^5.8.2",
"vite": "^6.1.1", "vite": "^6.2.0",
"vite-plugin-pwa": "^0.21.1", "vite-plugin-pwa": "^0.21.1",
"vitest": "^3.0.6" "vitest": "^3.0.7"
} }
} }

30
src/App.tsx

@ -12,7 +12,7 @@ import { useAppStore } from "@core/stores/appStore.ts";
import { useDeviceStore } from "@core/stores/deviceStore.ts"; import { useDeviceStore } from "@core/stores/deviceStore.ts";
import { Dashboard } from "@pages/Dashboard/index.tsx"; import { Dashboard } from "@pages/Dashboard/index.tsx";
import type { JSX } from "react"; import type { JSX } from "react";
import { MapProvider } from "react-map-gl"; import { MapProvider } from "react-map-gl/maplibre";
export const App = (): JSX.Element => { export const App = (): JSX.Element => {
const { getDevice } = useDeviceStore(); const { getDevice } = useDeviceStore();
@ -36,19 +36,21 @@ export const App = (): JSX.Element => {
<div className="flex grow"> <div className="flex grow">
<DeviceSelector /> <DeviceSelector />
<div className="flex grow flex-col"> <div className="flex grow flex-col">
{device ? ( {device
<div className="flex h-screen"> ? (
<DialogManager /> <div className="flex h-screen">
<KeyBackupReminder /> <DialogManager />
<CommandPalette /> <KeyBackupReminder />
<PageRouter /> <CommandPalette />
</div> <PageRouter />
) : ( </div>
<> )
<Dashboard /> : (
<Footer /> <>
</> <Dashboard />
)} <Footer />
</>
)}
</div> </div>
</div> </div>
</div> </div>

3
src/components/Dialog/DeviceNameDialog.tsx

@ -12,6 +12,7 @@ import { Input } from "@components/UI/Input.tsx";
import { Label } from "@components/UI/Label.tsx"; import { Label } from "@components/UI/Label.tsx";
import { Protobuf } from "@meshtastic/js"; import { Protobuf } from "@meshtastic/js";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { create } from "@bufbuild/protobuf";
export interface User { export interface User {
longName: string; longName: string;
@ -40,7 +41,7 @@ export const DeviceNameDialog = ({
const onSubmit = handleSubmit((data) => { const onSubmit = handleSubmit((data) => {
connection?.setOwner( connection?.setOwner(
new Protobuf.Mesh.User({ create(Protobuf.Mesh.UserSchema, {
...myNode?.user, ...myNode?.user,
...data, ...data,
}), }),

29
src/components/Dialog/ImportDialog.tsx

@ -1,3 +1,4 @@
import { create, fromBinary } from "@bufbuild/protobuf";
import { Button } from "@components/UI/Button.tsx"; import { Button } from "@components/UI/Button.tsx";
import { Checkbox } from "@components/UI/Checkbox.tsx"; import { Checkbox } from "@components/UI/Checkbox.tsx";
import { import {
@ -55,7 +56,10 @@ export const ImportDialog = ({
.replace(/-/g, "+") .replace(/-/g, "+")
.replace(/_/g, "/"); .replace(/_/g, "/");
setChannelSet( setChannelSet(
Protobuf.AppOnly.ChannelSet.fromBinary(toByteArray(paddedString)), fromBinary(
Protobuf.AppOnly.ChannelSetSchema,
toByteArray(paddedString),
),
); );
setValidUrl(true); setValidUrl(true);
} catch (error) { } catch (error) {
@ -67,12 +71,11 @@ export const ImportDialog = ({
const apply = () => { const apply = () => {
channelSet?.settings.map((ch: unknown, index: number) => { channelSet?.settings.map((ch: unknown, index: number) => {
connection?.setChannel( connection?.setChannel(
new Protobuf.Channel.Channel({ create(Protobuf.Channel.ChannelSchema, {
index, index,
role: role: index === 0
index === 0 ? Protobuf.Channel.Channel_Role.PRIMARY
? Protobuf.Channel.Channel_Role.PRIMARY : Protobuf.Channel.Channel_Role.SECONDARY,
: Protobuf.Channel.Channel_Role.SECONDARY,
settings: ch, settings: ch,
}), }),
); );
@ -80,7 +83,7 @@ export const ImportDialog = ({
if (channelSet?.loraConfig) { if (channelSet?.loraConfig) {
connection?.setConfig( connection?.setConfig(
new Protobuf.Config.Config({ create(Protobuf.Config.ConfigSchema, {
payloadVariant: { payloadVariant: {
case: "lora", case: "lora",
value: channelSet.loraConfig, value: channelSet.loraConfig,
@ -119,21 +122,25 @@ export const ImportDialog = ({
checked={channelSet?.loraConfig?.usePreset ?? true} checked={channelSet?.loraConfig?.usePreset ?? true}
/> />
</div> </div>
{/* <Select {
/* <Select
label="Modem Preset" label="Modem Preset"
disabled disabled
value={channelSet?.loraConfig?.modemPreset} value={channelSet?.loraConfig?.modemPreset}
> >
{renderOptions(Protobuf.Config_LoRaConfig_ModemPreset)} {renderOptions(Protobuf.Config_LoRaConfig_ModemPreset)}
</Select> */} </Select> */
}
</div> </div>
{/* <Select {
/* <Select
label="Region" label="Region"
disabled disabled
value={channelSet?.loraConfig?.region} value={channelSet?.loraConfig?.region}
> >
{renderOptions(Protobuf.Config_LoRaConfig_RegionCode)} {renderOptions(Protobuf.Config_LoRaConfig_RegionCode)}
</Select> */} </Select> */
}
<span className="text-md block font-medium text-text-primary"> <span className="text-md block font-medium text-text-primary">
Channels: Channels:

18
src/components/Dialog/QRDialog.tsx

@ -1,3 +1,4 @@
import { create, toBinary } from "@bufbuild/protobuf";
import { Checkbox } from "@components/UI/Checkbox.tsx"; import { Checkbox } from "@components/UI/Checkbox.tsx";
import { import {
Dialog, Dialog,
@ -39,13 +40,16 @@ export const QRDialog = ({
.filter((ch) => selectedChannels.includes(ch.index)) .filter((ch) => selectedChannels.includes(ch.index))
.map((channel) => channel.settings) .map((channel) => channel.settings)
.filter((ch): ch is Protobuf.Channel.ChannelSettings => !!ch); .filter((ch): ch is Protobuf.Channel.ChannelSettings => !!ch);
const encoded = new Protobuf.AppOnly.ChannelSet( const encoded = create(
new Protobuf.AppOnly.ChannelSet({ Protobuf.AppOnly.ChannelSetSchema,
create(Protobuf.AppOnly.ChannelSetSchema, {
loraConfig, loraConfig,
settings: channelsToEncode, settings: channelsToEncode,
}), }),
); );
const base64 = fromByteArray(encoded.toBinary()) const base64 = fromByteArray(
toBinary(Protobuf.AppOnly.ChannelSetSchema, encoded),
)
.replace(/=/g, "") .replace(/=/g, "")
.replace(/\+/g, "-") .replace(/\+/g, "-")
.replace(/\//g, "_"); .replace(/\//g, "_");
@ -73,8 +77,8 @@ export const QRDialog = ({
{channel.settings?.name.length {channel.settings?.name.length
? channel.settings.name ? channel.settings.name
: channel.role === Protobuf.Channel.Channel_Role.PRIMARY : channel.role === Protobuf.Channel.Channel_Role.PRIMARY
? "Primary" ? "Primary"
: `Channel: ${channel.index}`} : `Channel: ${channel.index}`}
</Label> </Label>
<Checkbox <Checkbox
key={channel.index} key={channel.index}
@ -82,7 +86,9 @@ export const QRDialog = ({
onCheckedChange={() => { onCheckedChange={() => {
if (selectedChannels.includes(channel.index)) { if (selectedChannels.includes(channel.index)) {
setSelectedChannels( setSelectedChannels(
selectedChannels.filter((c) => c !== channel.index), selectedChannels.filter((c) =>
c !== channel.index
),
); );
} else { } else {
setSelectedChannels([ setSelectedChannels([

68
src/components/PageComponents/Channel.tsx

@ -7,6 +7,7 @@ import { fromByteArray, toByteArray } from "base64-js";
import cryptoRandomString from "crypto-random-string"; import cryptoRandomString from "crypto-random-string";
import { useState } from "react"; import { useState } from "react";
import { PkiRegenerateDialog } from "../Dialog/PkiRegenerateDialog"; import { PkiRegenerateDialog } from "../Dialog/PkiRegenerateDialog";
import { create } from "@bufbuild/protobuf";
export interface SettingsPanelProps { export interface SettingsPanelProps {
channel: Protobuf.Channel.Channel; channel: Protobuf.Channel.Channel;
@ -23,11 +24,12 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => {
channel?.settings?.psk.length ?? 16, channel?.settings?.psk.length ?? 16,
); );
const [validationText, setValidationText] = useState<string>(); const [validationText, setValidationText] = useState<string>();
const [preSharedDialogOpen, setPreSharedDialogOpen] = const [preSharedDialogOpen, setPreSharedDialogOpen] = useState<boolean>(
useState<boolean>(false); false,
);
const onSubmit = (data: ChannelValidation) => { const onSubmit = (data: ChannelValidation) => {
const channel = new Protobuf.Channel.Channel({ const channel = create(Protobuf.Channel.ChannelSchema, {
...data, ...data,
settings: { settings: {
...data.settings, ...data.settings,
@ -106,7 +108,7 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => {
channel?.settings?.moduleSettings?.positionPrecision === 32, channel?.settings?.moduleSettings?.positionPrecision === 32,
positionPrecision: positionPrecision:
channel?.settings?.moduleSettings?.positionPrecision === channel?.settings?.moduleSettings?.positionPrecision ===
undefined undefined
? 10 ? 10
: channel?.settings?.moduleSettings?.positionPrecision, : channel?.settings?.moduleSettings?.positionPrecision,
}, },
@ -125,10 +127,9 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => {
description: description:
"Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed",
properties: { properties: {
enumValue: enumValue: channel.index === 0
channel.index === 0 ? { PRIMARY: 1 }
? { PRIMARY: 1 } : { DISABLED: 0, SECONDARY: 2 },
: { DISABLED: 0, SECONDARY: 2 },
}, },
}, },
{ {
@ -191,32 +192,31 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => {
description: description:
"If not sharing precise location, position shared on channel will be accurate within this distance", "If not sharing precise location, position shared on channel will be accurate within this distance",
properties: { properties: {
enumValue: enumValue: config.display?.units === 0
config.display?.units === 0 ? {
? { "Within 23 km": 10,
"Within 23 km": 10, "Within 12 km": 11,
"Within 12 km": 11, "Within 5.8 km": 12,
"Within 5.8 km": 12, "Within 2.9 km": 13,
"Within 2.9 km": 13, "Within 1.5 km": 14,
"Within 1.5 km": 14, "Within 700 m": 15,
"Within 700 m": 15, "Within 350 m": 16,
"Within 350 m": 16, "Within 200 m": 17,
"Within 200 m": 17, "Within 90 m": 18,
"Within 90 m": 18, "Within 50 m": 19,
"Within 50 m": 19, }
} : {
: { "Within 15 miles": 10,
"Within 15 miles": 10, "Within 7.3 miles": 11,
"Within 7.3 miles": 11, "Within 3.6 miles": 12,
"Within 3.6 miles": 12, "Within 1.8 miles": 13,
"Within 1.8 miles": 13, "Within 0.9 miles": 14,
"Within 0.9 miles": 14, "Within 0.5 miles": 15,
"Within 0.5 miles": 15, "Within 0.2 miles": 16,
"Within 0.2 miles": 16, "Within 600 feet": 17,
"Within 600 feet": 17, "Within 300 feet": 18,
"Within 300 feet": 18, "Within 150 feet": 19,
"Within 150 feet": 19, },
},
}, },
}, },
], ],

8
src/components/PageComponents/Config/Bluetooth.tsx

@ -1,5 +1,6 @@
import { useAppStore } from "@app/core/stores/appStore"; import { useAppStore } from "@app/core/stores/appStore";
import type { BluetoothValidation } from "@app/validation/config/bluetooth.tsx"; import type { BluetoothValidation } from "@app/validation/config/bluetooth.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx"; import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts"; import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js"; import { Protobuf } from "@meshtastic/js";
@ -53,7 +54,7 @@ export const Bluetooth = () => {
} }
setWorkingConfig( setWorkingConfig(
new Protobuf.Config.Config({ create(Protobuf.Config.ConfigSchema, {
payloadVariant: { payloadVariant: {
case: "bluetooth", case: "bluetooth",
value: data, value: data,
@ -110,9 +111,8 @@ export const Bluetooth = () => {
disabledBy: [ disabledBy: [
{ {
fieldName: "mode", fieldName: "mode",
selector: selector: Protobuf.Config.Config_BluetoothConfig_PairingMode
Protobuf.Config.Config_BluetoothConfig_PairingMode .FIXED_PIN,
.FIXED_PIN,
invert: true, invert: true,
}, },
{ {

3
src/components/PageComponents/Config/Device.tsx

@ -1,4 +1,5 @@
import type { DeviceValidation } from "@app/validation/config/device.tsx"; import type { DeviceValidation } from "@app/validation/config/device.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx"; import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts"; import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js"; import { Protobuf } from "@meshtastic/js";
@ -8,7 +9,7 @@ export const Device = (): JSX.Element => {
const onSubmit = (data: DeviceValidation) => { const onSubmit = (data: DeviceValidation) => {
setWorkingConfig( setWorkingConfig(
new Protobuf.Config.Config({ create(Protobuf.Config.ConfigSchema, {
payloadVariant: { payloadVariant: {
case: "device", case: "device",
value: data, value: data,

3
src/components/PageComponents/Config/Display.tsx

@ -1,4 +1,5 @@
import type { DisplayValidation } from "@app/validation/config/display.tsx"; import type { DisplayValidation } from "@app/validation/config/display.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx"; import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts"; import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js"; import { Protobuf } from "@meshtastic/js";
@ -8,7 +9,7 @@ export const Display = (): JSX.Element => {
const onSubmit = (data: DisplayValidation) => { const onSubmit = (data: DisplayValidation) => {
setWorkingConfig( setWorkingConfig(
new Protobuf.Config.Config({ create(Protobuf.Config.ConfigSchema, {
payloadVariant: { payloadVariant: {
case: "display", case: "display",
value: data, value: data,

3
src/components/PageComponents/Config/LoRa.tsx

@ -1,4 +1,5 @@
import type { LoRaValidation } from "@app/validation/config/lora.tsx"; import type { LoRaValidation } from "@app/validation/config/lora.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx"; import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts"; import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js"; import { Protobuf } from "@meshtastic/js";
@ -8,7 +9,7 @@ export const LoRa = (): JSX.Element => {
const onSubmit = (data: LoRaValidation) => { const onSubmit = (data: LoRaValidation) => {
setWorkingConfig( setWorkingConfig(
new Protobuf.Config.Config({ create(Protobuf.Config.ConfigSchema, {
payloadVariant: { payloadVariant: {
case: "lora", case: "lora",
value: data, value: data,

18
src/components/PageComponents/Config/Network.tsx

@ -1,4 +1,5 @@
import type { NetworkValidation } from "@app/validation/config/network.tsx"; import type { NetworkValidation } from "@app/validation/config/network.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx"; import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts"; import { useDevice } from "@core/stores/deviceStore.ts";
import { import {
@ -12,17 +13,20 @@ export const Network = (): JSX.Element => {
const onSubmit = (data: NetworkValidation) => { const onSubmit = (data: NetworkValidation) => {
setWorkingConfig( setWorkingConfig(
new Protobuf.Config.Config({ create(Protobuf.Config.ConfigSchema, {
payloadVariant: { payloadVariant: {
case: "network", case: "network",
value: { value: {
...data, ...data,
ipv4Config: new Protobuf.Config.Config_NetworkConfig_IpV4Config({ ipv4Config: create(
ip: convertIpAddressToInt(data.ipv4Config.ip) ?? 0, Protobuf.Config.Config_NetworkConfig_IpV4ConfigSchema,
gateway: convertIpAddressToInt(data.ipv4Config.gateway) ?? 0, {
subnet: convertIpAddressToInt(data.ipv4Config.subnet) ?? 0, ip: convertIpAddressToInt(data.ipv4Config.ip) ?? 0,
dns: convertIpAddressToInt(data.ipv4Config.dns) ?? 0, gateway: convertIpAddressToInt(data.ipv4Config.gateway) ?? 0,
}), subnet: convertIpAddressToInt(data.ipv4Config.subnet) ?? 0,
dns: convertIpAddressToInt(data.ipv4Config.dns) ?? 0,
},
),
}, },
}, },
}), }),

3
src/components/PageComponents/Config/Position.tsx

@ -3,6 +3,7 @@ import {
usePositionFlags, usePositionFlags,
} from "@app/core/hooks/usePositionFlags"; } from "@app/core/hooks/usePositionFlags";
import type { PositionValidation } from "@app/validation/config/position.tsx"; import type { PositionValidation } from "@app/validation/config/position.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx"; import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts"; import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js"; import { Protobuf } from "@meshtastic/js";
@ -16,7 +17,7 @@ export const Position = () => {
const onSubmit = (data: PositionValidation) => { const onSubmit = (data: PositionValidation) => {
return setWorkingConfig( return setWorkingConfig(
new Protobuf.Config.Config({ create(Protobuf.Config.ConfigSchema, {
payloadVariant: { payloadVariant: {
case: "position", case: "position",
value: { ...data, positionFlags: flagsValue }, value: { ...data, positionFlags: flagsValue },

3
src/components/PageComponents/Config/Power.tsx

@ -1,4 +1,5 @@
import type { PowerValidation } from "@app/validation/config/power.tsx"; import type { PowerValidation } from "@app/validation/config/power.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx"; import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts"; import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js"; import { Protobuf } from "@meshtastic/js";
@ -8,7 +9,7 @@ export const Power = (): JSX.Element => {
const onSubmit = (data: PowerValidation) => { const onSubmit = (data: PowerValidation) => {
setWorkingConfig( setWorkingConfig(
new Protobuf.Config.Config({ create(Protobuf.Config.ConfigSchema, {
payloadVariant: { payloadVariant: {
case: "power", case: "power",
value: data, value: data,

16
src/components/PageComponents/Config/Security/Security.tsx

@ -12,6 +12,7 @@ import { fromByteArray, toByteArray } from "base64-js";
import { Eye, EyeOff } from "lucide-react"; import { Eye, EyeOff } from "lucide-react";
import { useReducer } from "react"; import { useReducer } from "react";
import { securityReducer } from "./securityReducer"; import { securityReducer } from "./securityReducer";
import { create } from "@bufbuild/protobuf";
export const Security = () => { export const Security = () => {
const { config, setWorkingConfig, setDialogOpen } = useDevice(); const { config, setWorkingConfig, setDialogOpen } = useDevice();
@ -57,7 +58,9 @@ export const Security = () => {
if (input.length % 4 !== 0) { if (input.length % 4 !== 0) {
addError( addError(
fieldName, 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; return;
} }
@ -71,7 +74,9 @@ export const Security = () => {
console.error(e); console.error(e);
addError( addError(
fieldName, 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)); console.log(toByteArray(state.adminKey));
setWorkingConfig( setWorkingConfig(
new Protobuf.Config.Config({ create(Protobuf.Config.ConfigSchema, {
payloadVariant: { payloadVariant: {
case: "security", case: "security",
value: { value: {
@ -243,7 +248,7 @@ export const Security = () => {
? getErrorMessage("adminKey") ? getErrorMessage("adminKey")
: "", : "",
inputChange: adminKeyInputChangeEvent, inputChange: adminKeyInputChangeEvent,
selectChange: () => { }, selectChange: () => {},
bits: [{ text: "256 bit", value: "32", key: "bit256" }], bits: [{ text: "256 bit", value: "32", key: "bit256" }],
devicePSKBitCount: state.privateKeyBitCount, devicePSKBitCount: state.privateKeyBitCount,
hide: !state.adminKeyVisible, hide: !state.adminKeyVisible,
@ -303,8 +308,7 @@ export const Security = () => {
<PkiRegenerateDialog <PkiRegenerateDialog
open={state.privateKeyDialogOpen} open={state.privateKeyDialogOpen}
onOpenChange={() => onOpenChange={() =>
dispatch({ type: "SHOW_PRIVATE_KEY_DIALOG", payload: false }) dispatch({ type: "SHOW_PRIVATE_KEY_DIALOG", payload: false })}
}
onSubmit={pkiRegenerate} onSubmit={pkiRegenerate}
/> />
</> </>

3
src/components/PageComponents/ModuleConfig/AmbientLighting.tsx

@ -1,5 +1,6 @@
import { useDevice } from "@app/core/stores/deviceStore.ts"; import { useDevice } from "@app/core/stores/deviceStore.ts";
import type { AmbientLightingValidation } from "@app/validation/moduleConfig/ambientLighting.tsx"; import type { AmbientLightingValidation } from "@app/validation/moduleConfig/ambientLighting.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx"; import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { Protobuf } from "@meshtastic/js"; import { Protobuf } from "@meshtastic/js";
@ -8,7 +9,7 @@ export const AmbientLighting = (): JSX.Element => {
const onSubmit = (data: AmbientLightingValidation) => { const onSubmit = (data: AmbientLightingValidation) => {
setWorkingModuleConfig( setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({ create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: { payloadVariant: {
case: "ambientLighting", case: "ambientLighting",
value: data, value: data,

3
src/components/PageComponents/ModuleConfig/Audio.tsx

@ -1,4 +1,5 @@
import type { AudioValidation } from "@app/validation/moduleConfig/audio.tsx"; import type { AudioValidation } from "@app/validation/moduleConfig/audio.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx"; import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts"; import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js"; import { Protobuf } from "@meshtastic/js";
@ -8,7 +9,7 @@ export const Audio = (): JSX.Element => {
const onSubmit = (data: AudioValidation) => { const onSubmit = (data: AudioValidation) => {
setWorkingModuleConfig( setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({ create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: { payloadVariant: {
case: "audio", case: "audio",
value: data, value: data,

18
src/components/PageComponents/ModuleConfig/CannedMessage.tsx

@ -1,4 +1,5 @@
import type { CannedMessageValidation } from "@app/validation/moduleConfig/cannedMessage.tsx"; import type { CannedMessageValidation } from "@app/validation/moduleConfig/cannedMessage.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx"; import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts"; import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js"; import { Protobuf } from "@meshtastic/js";
@ -8,7 +9,7 @@ export const CannedMessage = (): JSX.Element => {
const onSubmit = (data: CannedMessageValidation) => { const onSubmit = (data: CannedMessageValidation) => {
setWorkingModuleConfig( setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({ create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: { payloadVariant: {
case: "cannedMessage", case: "cannedMessage",
value: data, value: data,
@ -62,9 +63,8 @@ export const CannedMessage = (): JSX.Element => {
label: "Clockwise event", label: "Clockwise event",
description: "Select input event.", description: "Select input event.",
properties: { properties: {
enumValue: enumValue: Protobuf.ModuleConfig
Protobuf.ModuleConfig .ModuleConfig_CannedMessageConfig_InputEventChar,
.ModuleConfig_CannedMessageConfig_InputEventChar,
}, },
}, },
{ {
@ -73,9 +73,8 @@ export const CannedMessage = (): JSX.Element => {
label: "Counter Clockwise event", label: "Counter Clockwise event",
description: "Select input event.", description: "Select input event.",
properties: { properties: {
enumValue: enumValue: Protobuf.ModuleConfig
Protobuf.ModuleConfig .ModuleConfig_CannedMessageConfig_InputEventChar,
.ModuleConfig_CannedMessageConfig_InputEventChar,
}, },
}, },
{ {
@ -84,9 +83,8 @@ export const CannedMessage = (): JSX.Element => {
label: "Press event", label: "Press event",
description: "Select input event", description: "Select input event",
properties: { properties: {
enumValue: enumValue: Protobuf.ModuleConfig
Protobuf.ModuleConfig .ModuleConfig_CannedMessageConfig_InputEventChar,
.ModuleConfig_CannedMessageConfig_InputEventChar,
}, },
}, },
{ {

3
src/components/PageComponents/ModuleConfig/DetectionSensor.tsx

@ -1,5 +1,6 @@
import { useDevice } from "@app/core/stores/deviceStore.ts"; import { useDevice } from "@app/core/stores/deviceStore.ts";
import type { DetectionSensorValidation } from "@app/validation/moduleConfig/detectionSensor.tsx"; import type { DetectionSensorValidation } from "@app/validation/moduleConfig/detectionSensor.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx"; import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { Protobuf } from "@meshtastic/js"; import { Protobuf } from "@meshtastic/js";
@ -8,7 +9,7 @@ export const DetectionSensor = (): JSX.Element => {
const onSubmit = (data: DetectionSensorValidation) => { const onSubmit = (data: DetectionSensorValidation) => {
setWorkingModuleConfig( setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({ create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: { payloadVariant: {
case: "detectionSensor", case: "detectionSensor",
value: data, value: data,

3
src/components/PageComponents/ModuleConfig/ExternalNotification.tsx

@ -1,4 +1,5 @@
import type { ExternalNotificationValidation } from "@app/validation/moduleConfig/externalNotification.tsx"; import type { ExternalNotificationValidation } from "@app/validation/moduleConfig/externalNotification.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx"; import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts"; import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js"; import { Protobuf } from "@meshtastic/js";
@ -8,7 +9,7 @@ export const ExternalNotification = (): JSX.Element => {
const onSubmit = (data: ExternalNotificationValidation) => { const onSubmit = (data: ExternalNotificationValidation) => {
setWorkingModuleConfig( setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({ create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: { payloadVariant: {
case: "externalNotification", case: "externalNotification",
value: data, value: data,

63
src/components/PageComponents/ModuleConfig/MQTT.tsx

@ -1,5 +1,6 @@
import { useDevice } from "@app/core/stores/deviceStore.ts"; import { useDevice } from "@app/core/stores/deviceStore.ts";
import type { MqttValidation } from "@app/validation/moduleConfig/mqtt.tsx"; import type { MqttValidation } from "@app/validation/moduleConfig/mqtt.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx"; import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { Protobuf } from "@meshtastic/js"; import { Protobuf } from "@meshtastic/js";
@ -8,15 +9,16 @@ export const MQTT = (): JSX.Element => {
const onSubmit = (data: MqttValidation) => { const onSubmit = (data: MqttValidation) => {
setWorkingModuleConfig( setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({ create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: { payloadVariant: {
case: "mqtt", case: "mqtt",
value: { value: {
...data, ...data,
mapReportSettings: mapReportSettings: create(
new Protobuf.ModuleConfig.ModuleConfig_MapReportSettings( Protobuf.ModuleConfig
data.mapReportSettings, .ModuleConfig_MapReportSettingsSchema,
), data.mapReportSettings,
),
}, },
}, },
}), }),
@ -164,32 +166,31 @@ export const MQTT = (): JSX.Element => {
description: description:
"Position shared will be accurate within this distance", "Position shared will be accurate within this distance",
properties: { properties: {
enumValue: enumValue: config.display?.units === 0
config.display?.units === 0 ? {
? { "Within 23 km": 10,
"Within 23 km": 10, "Within 12 km": 11,
"Within 12 km": 11, "Within 5.8 km": 12,
"Within 5.8 km": 12, "Within 2.9 km": 13,
"Within 2.9 km": 13, "Within 1.5 km": 14,
"Within 1.5 km": 14, "Within 700 m": 15,
"Within 700 m": 15, "Within 350 m": 16,
"Within 350 m": 16, "Within 200 m": 17,
"Within 200 m": 17, "Within 90 m": 18,
"Within 90 m": 18, "Within 50 m": 19,
"Within 50 m": 19, }
} : {
: { "Within 15 miles": 10,
"Within 15 miles": 10, "Within 7.3 miles": 11,
"Within 7.3 miles": 11, "Within 3.6 miles": 12,
"Within 3.6 miles": 12, "Within 1.8 miles": 13,
"Within 1.8 miles": 13, "Within 0.9 miles": 14,
"Within 0.9 miles": 14, "Within 0.5 miles": 15,
"Within 0.5 miles": 15, "Within 0.2 miles": 16,
"Within 0.2 miles": 16, "Within 600 feet": 17,
"Within 600 feet": 17, "Within 300 feet": 18,
"Within 300 feet": 18, "Within 150 feet": 19,
"Within 150 feet": 19, },
},
}, },
disabledBy: [ disabledBy: [
{ {

3
src/components/PageComponents/ModuleConfig/NeighborInfo.tsx

@ -1,5 +1,6 @@
import { useDevice } from "@app/core/stores/deviceStore.ts"; import { useDevice } from "@app/core/stores/deviceStore.ts";
import type { NeighborInfoValidation } from "@app/validation/moduleConfig/neighborInfo.tsx"; import type { NeighborInfoValidation } from "@app/validation/moduleConfig/neighborInfo.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx"; import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { Protobuf } from "@meshtastic/js"; import { Protobuf } from "@meshtastic/js";
@ -8,7 +9,7 @@ export const NeighborInfo = (): JSX.Element => {
const onSubmit = (data: NeighborInfoValidation) => { const onSubmit = (data: NeighborInfoValidation) => {
setWorkingModuleConfig( setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({ create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: { payloadVariant: {
case: "neighborInfo", case: "neighborInfo",
value: data, value: data,

3
src/components/PageComponents/ModuleConfig/Paxcounter.tsx

@ -1,4 +1,5 @@
import type { PaxcounterValidation } from "@app/validation/moduleConfig/paxcounter.tsx"; import type { PaxcounterValidation } from "@app/validation/moduleConfig/paxcounter.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx"; import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts"; import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js"; import { Protobuf } from "@meshtastic/js";
@ -8,7 +9,7 @@ export const Paxcounter = (): JSX.Element => {
const onSubmit = (data: PaxcounterValidation) => { const onSubmit = (data: PaxcounterValidation) => {
setWorkingModuleConfig( setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({ create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: { payloadVariant: {
case: "paxcounter", case: "paxcounter",
value: data, value: data,

3
src/components/PageComponents/ModuleConfig/RangeTest.tsx

@ -1,4 +1,5 @@
import type { RangeTestValidation } from "@app/validation/moduleConfig/rangeTest.tsx"; import type { RangeTestValidation } from "@app/validation/moduleConfig/rangeTest.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx"; import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts"; import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js"; import { Protobuf } from "@meshtastic/js";
@ -8,7 +9,7 @@ export const RangeTest = (): JSX.Element => {
const onSubmit = (data: RangeTestValidation) => { const onSubmit = (data: RangeTestValidation) => {
setWorkingModuleConfig( setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({ create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: { payloadVariant: {
case: "rangeTest", case: "rangeTest",
value: data, value: data,

3
src/components/PageComponents/ModuleConfig/Serial.tsx

@ -1,4 +1,5 @@
import type { SerialValidation } from "@app/validation/moduleConfig/serial.tsx"; import type { SerialValidation } from "@app/validation/moduleConfig/serial.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx"; import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts"; import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js"; import { Protobuf } from "@meshtastic/js";
@ -8,7 +9,7 @@ export const Serial = (): JSX.Element => {
const onSubmit = (data: SerialValidation) => { const onSubmit = (data: SerialValidation) => {
setWorkingModuleConfig( setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({ create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: { payloadVariant: {
case: "serial", case: "serial",
value: data, value: data,

3
src/components/PageComponents/ModuleConfig/StoreForward.tsx

@ -1,4 +1,5 @@
import type { StoreForwardValidation } from "@app/validation/moduleConfig/storeForward.ts"; import type { StoreForwardValidation } from "@app/validation/moduleConfig/storeForward.ts";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx"; import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts"; import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js"; import { Protobuf } from "@meshtastic/js";
@ -8,7 +9,7 @@ export const StoreForward = (): JSX.Element => {
const onSubmit = (data: StoreForwardValidation) => { const onSubmit = (data: StoreForwardValidation) => {
setWorkingModuleConfig( setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({ create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: { payloadVariant: {
case: "storeForward", case: "storeForward",
value: data, value: data,

3
src/components/PageComponents/ModuleConfig/Telemetry.tsx

@ -1,4 +1,5 @@
import type { TelemetryValidation } from "@app/validation/moduleConfig/telemetry.tsx"; import type { TelemetryValidation } from "@app/validation/moduleConfig/telemetry.tsx";
import { create } from "@bufbuild/protobuf";
import { DynamicForm } from "@components/Form/DynamicForm.tsx"; import { DynamicForm } from "@components/Form/DynamicForm.tsx";
import { useDevice } from "@core/stores/deviceStore.ts"; import { useDevice } from "@core/stores/deviceStore.ts";
import { Protobuf } from "@meshtastic/js"; import { Protobuf } from "@meshtastic/js";
@ -8,7 +9,7 @@ export const Telemetry = (): JSX.Element => {
const onSubmit = (data: TelemetryValidation) => { const onSubmit = (data: TelemetryValidation) => {
setWorkingModuleConfig( setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({ create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: { payloadVariant: {
case: "telemetry", case: "telemetry",
value: data, value: data,

51
src/core/stores/deviceStore.ts

@ -1,9 +1,8 @@
import { createContext, useContext } from "react"; import { createContext, useContext } from "react";
import { produce } from "immer"; import { produce } from "immer";
import { create } from "zustand"; import { create as createStore } from "zustand";
import { Protobuf, Types } from "@meshtastic/js"; import { Protobuf, Types } from "@meshtastic/js";
import { create } from "@bufbuild/protobuf";
export type Page = "messages" | "map" | "config" | "channels" | "nodes"; export type Page = "messages" | "map" | "config" | "channels" | "nodes";
@ -111,7 +110,7 @@ export interface DeviceState {
getDevice: (id: number) => Device | undefined; getDevice: (id: number) => Device | undefined;
} }
export const useDeviceStore = create<DeviceState>((set, get) => ({ export const useDeviceStore = createStore<DeviceState>((set, get) => ({
devices: new Map(), devices: new Map(),
remoteDevices: new Map(), remoteDevices: new Map(),
@ -122,11 +121,11 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
id, id,
status: Types.DeviceStatusEnum.DeviceDisconnected, status: Types.DeviceStatusEnum.DeviceDisconnected,
channels: new Map(), channels: new Map(),
config: new Protobuf.LocalOnly.LocalConfig(), config: create(Protobuf.LocalOnly.LocalConfigSchema),
moduleConfig: new Protobuf.LocalOnly.LocalModuleConfig(), moduleConfig: create(Protobuf.LocalOnly.LocalModuleConfigSchema),
workingConfig: [], workingConfig: [],
workingModuleConfig: [], workingModuleConfig: [],
hardware: new Protobuf.Mesh.MyNodeInfo(), hardware: create(Protobuf.Mesh.MyNodeInfoSchema),
nodes: new Map(), nodes: new Map(),
metadata: new Map(), metadata: new Map(),
messages: { messages: {
@ -138,7 +137,6 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
activePage: "messages", activePage: "messages",
activeNode: 0, activeNode: 0,
waypoints: [], waypoints: [],
// currentMetrics: new Protobuf.DeviceMetrics(),
dialog: { dialog: {
import: false, import: false,
QR: false, QR: false,
@ -301,11 +299,11 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
if (!device) { if (!device) {
return; return;
} }
const workingModuleConfigIndex = const workingModuleConfigIndex = device?.workingModuleConfig
device?.workingModuleConfig.findIndex( .findIndex(
(wmc) => (wmc) =>
wmc.payloadVariant.case === wmc.payloadVariant.case ===
moduleConfig.payloadVariant.case, moduleConfig.payloadVariant.case,
); );
if (workingModuleConfigIndex !== -1) { if (workingModuleConfigIndex !== -1) {
device.workingModuleConfig[workingModuleConfigIndex] = device.workingModuleConfig[workingModuleConfigIndex] =
@ -447,8 +445,8 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
if (!device) { if (!device) {
return; return;
} }
const currentNode = const currentNode = device.nodes.get(user.from) ??
device.nodes.get(user.from) ?? new Protobuf.Mesh.NodeInfo(); create(Protobuf.Mesh.NodeInfoSchema);
currentNode.user = user.data; currentNode.user = user.data;
device.nodes.set(user.from, currentNode); device.nodes.set(user.from, currentNode);
}), }),
@ -461,9 +459,8 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
if (!device) { if (!device) {
return; return;
} }
const currentNode = const currentNode = device.nodes.get(position.from) ??
device.nodes.get(position.from) ?? create(Protobuf.Mesh.NodeInfoSchema);
new Protobuf.Mesh.NodeInfo();
currentNode.position = position.data; currentNode.position = position.data;
device.nodes.set(position.from, currentNode); device.nodes.set(position.from, currentNode);
}), }),
@ -487,12 +484,11 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
return; return;
} }
const messageGroup = device.messages[message.type]; const messageGroup = device.messages[message.type];
const messageIndex = const messageIndex = message.type === "direct"
message.type === "direct" ? message.from === device.hardware.myNodeNum
? message.from === device.hardware.myNodeNum ? message.to
? message.to : message.from
: message.from : message.channel;
: message.channel;
const messages = messageGroup.get(messageIndex); const messages = messageGroup.get(messageIndex);
if (messages) { if (messages) {
@ -565,12 +561,9 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
} }
const messageGroup = device.messages[type]; const messageGroup = device.messages[type];
const messageIndex = const messageIndex = type === "direct"
type === "direct" ? from === device.hardware.myNodeNum ? to : from
? from === device.hardware.myNodeNum : channelIndex;
? to
: from
: channelIndex;
const messages = messageGroup.get(messageIndex); const messages = messageGroup.get(messageIndex);
if (!messages) { if (!messages) {
@ -618,7 +611,7 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
} else { } else {
device.nodes.set( device.nodes.set(
data.from, data.from,
new Protobuf.Mesh.NodeInfo({ create(Protobuf.Mesh.NodeInfoSchema, {
num: data.from, num: data.from,
lastHeard: data.time, lastHeard: data.time,
snr: data.snr, snr: data.snr,

29
src/pages/Map/index.tsx

@ -17,7 +17,7 @@ import {
Popup, Popup,
ScaleControl, ScaleControl,
useMap, useMap,
} from "react-map-gl"; } from "react-map-gl/maplibre";
import MapGl from "react-map-gl/maplibre"; import MapGl from "react-map-gl/maplibre";
type NodePosition = { type NodePosition = {
@ -40,8 +40,9 @@ const MapPage = (): JSX.Element => {
const darkMode = currentTheme === "dark"; const darkMode = currentTheme === "dark";
const [selectedNode, setSelectedNode] = const [selectedNode, setSelectedNode] = useState<
useState<Protobuf.Mesh.NodeInfo | null>(null); Protobuf.Mesh.NodeInfo | null
>(null);
// Filter out nodes without a valid position // Filter out nodes without a valid position
const validNodes = useMemo( const validNodes = useMemo(
@ -185,16 +186,18 @@ const MapPage = (): JSX.Element => {
</Marker> </Marker>
))} ))}
{markers} {markers}
{selectedNode ? ( {selectedNode
<Popup ? (
anchor="top" <Popup
longitude={convertToLatLng(selectedNode.position).longitude} anchor="top"
latitude={convertToLatLng(selectedNode.position).latitude} longitude={convertToLatLng(selectedNode.position).longitude}
onClose={() => setSelectedNode(null)} latitude={convertToLatLng(selectedNode.position).latitude}
> onClose={() => setSelectedNode(null)}
<NodeDetail node={selectedNode} /> >
</Popup> <NodeDetail node={selectedNode} />
) : null} </Popup>
)
: null}
</MapGl> </MapGl>
</PageLayout> </PageLayout>
</> </>

4
tsconfig.json

@ -10,8 +10,8 @@
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"strict": true, "strict": true,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"module": "ESNext", "module": "NodeNext",
"moduleResolution": "Node", "moduleResolution": "nodenext",
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"noEmit": true, "noEmit": true,

Loading…
Cancel
Save