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",
"dependencies": {
"@bufbuild/protobuf": "^1.10.0",
"@meshtastic/js": "2.3.7-5",
"@bufbuild/protobuf": "^2.2.3",
"@meshtastic/js": "npm:@jsr/[email protected]",
"@noble/curves": "^1.8.1",
"@radix-ui/react-accordion": "^1.2.3",
"@radix-ui/react-checkbox": "^1.1.4",
@ -63,44 +63,44 @@
"crypto-random-string": "^5.0.0",
"immer": "^10.1.1",
"js-cookie": "^3.0.5",
"lucide-react": "^0.475.0",
"mapbox-gl": "^3.9.4",
"maplibre-gl": "4.1.2",
"lucide-react": "^0.477.0",
"mapbox-gl": "^3.10.0",
"maplibre-gl": "5.1.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"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-scan": "^0.2.4",
"react-scan": "^0.2.8",
"rfc4648": "^1.5.4",
"vite-plugin-node-polyfills": "^0.23.0",
"zustand": "5.0.3"
},
"devDependencies": {
"@biomejs/biome": "^1.9.4",
"@tailwindcss/postcss": "^4.0.7",
"@tailwindcss/postcss": "^4.0.9",
"@testing-library/react": "^16.2.0",
"@types/chrome": "^0.0.304",
"@types/chrome": "^0.0.307",
"@types/js-cookie": "^3.0.6",
"@types/node": "^22.13.4",
"@types/node": "^22.13.7",
"@types/react": "^19.0.10",
"@types/react-dom": "^19.0.4",
"@types/serviceworker": "^0.0.122",
"@types/w3c-web-serial": "^1.0.7",
"@types/web-bluetooth": "^0.0.20",
"@types/serviceworker": "^0.0.123",
"@types/w3c-web-serial": "^1.0.8",
"@types/web-bluetooth": "^0.0.21",
"@vitejs/plugin-react": "^4.3.4",
"autoprefixer": "^10.4.20",
"gzipper": "^8.2.0",
"happy-dom": "^17.1.4",
"postcss": "^8.5.1",
"happy-dom": "^17.1.8",
"postcss": "^8.5.3",
"simple-git-hooks": "^2.11.1",
"tailwind-merge": "^3.0.1",
"tailwindcss": "^4.0.7",
"tailwind-merge": "^3.0.2",
"tailwindcss": "^4.0.9",
"tailwindcss-animate": "^1.0.7",
"tar": "^7.4.3",
"typescript": "^5.7.3",
"vite": "^6.1.1",
"typescript": "^5.8.2",
"vite": "^6.2.0",
"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 { Dashboard } from "@pages/Dashboard/index.tsx";
import type { JSX } from "react";
import { MapProvider } from "react-map-gl";
import { MapProvider } from "react-map-gl/maplibre";
export const App = (): JSX.Element => {
const { getDevice } = useDeviceStore();
@ -36,19 +36,21 @@ export const App = (): JSX.Element => {
<div className="flex grow">
<DeviceSelector />
<div className="flex grow flex-col">
{device ? (
<div className="flex h-screen">
<DialogManager />
<KeyBackupReminder />
<CommandPalette />
<PageRouter />
</div>
) : (
<>
<Dashboard />
<Footer />
</>
)}
{device
? (
<div className="flex h-screen">
<DialogManager />
<KeyBackupReminder />
<CommandPalette />
<PageRouter />
</div>
)
: (
<>
<Dashboard />
<Footer />
</>
)}
</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 { Protobuf } from "@meshtastic/js";
import { useForm } from "react-hook-form";
import { create } from "@bufbuild/protobuf";
export interface User {
longName: string;
@ -40,7 +41,7 @@ export const DeviceNameDialog = ({
const onSubmit = handleSubmit((data) => {
connection?.setOwner(
new Protobuf.Mesh.User({
create(Protobuf.Mesh.UserSchema, {
...myNode?.user,
...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 { Checkbox } from "@components/UI/Checkbox.tsx";
import {
@ -55,7 +56,10 @@ export const ImportDialog = ({
.replace(/-/g, "+")
.replace(/_/g, "/");
setChannelSet(
Protobuf.AppOnly.ChannelSet.fromBinary(toByteArray(paddedString)),
fromBinary(
Protobuf.AppOnly.ChannelSetSchema,
toByteArray(paddedString),
),
);
setValidUrl(true);
} catch (error) {
@ -67,12 +71,11 @@ export const ImportDialog = ({
const apply = () => {
channelSet?.settings.map((ch: unknown, index: number) => {
connection?.setChannel(
new Protobuf.Channel.Channel({
create(Protobuf.Channel.ChannelSchema, {
index,
role:
index === 0
? Protobuf.Channel.Channel_Role.PRIMARY
: Protobuf.Channel.Channel_Role.SECONDARY,
role: index === 0
? Protobuf.Channel.Channel_Role.PRIMARY
: Protobuf.Channel.Channel_Role.SECONDARY,
settings: ch,
}),
);
@ -80,7 +83,7 @@ export const ImportDialog = ({
if (channelSet?.loraConfig) {
connection?.setConfig(
new Protobuf.Config.Config({
create(Protobuf.Config.ConfigSchema, {
payloadVariant: {
case: "lora",
value: channelSet.loraConfig,
@ -119,21 +122,25 @@ export const ImportDialog = ({
checked={channelSet?.loraConfig?.usePreset ?? true}
/>
</div>
{/* <Select
{
/* <Select
label="Modem Preset"
disabled
value={channelSet?.loraConfig?.modemPreset}
>
{renderOptions(Protobuf.Config_LoRaConfig_ModemPreset)}
</Select> */}
</Select> */
}
</div>
{/* <Select
{
/* <Select
label="Region"
disabled
value={channelSet?.loraConfig?.region}
>
{renderOptions(Protobuf.Config_LoRaConfig_RegionCode)}
</Select> */}
</Select> */
}
<span className="text-md block font-medium text-text-primary">
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 {
Dialog,
@ -39,13 +40,16 @@ export const QRDialog = ({
.filter((ch) => selectedChannels.includes(ch.index))
.map((channel) => channel.settings)
.filter((ch): ch is Protobuf.Channel.ChannelSettings => !!ch);
const encoded = new Protobuf.AppOnly.ChannelSet(
new Protobuf.AppOnly.ChannelSet({
const encoded = create(
Protobuf.AppOnly.ChannelSetSchema,
create(Protobuf.AppOnly.ChannelSetSchema, {
loraConfig,
settings: channelsToEncode,
}),
);
const base64 = fromByteArray(encoded.toBinary())
const base64 = fromByteArray(
toBinary(Protobuf.AppOnly.ChannelSetSchema, encoded),
)
.replace(/=/g, "")
.replace(/\+/g, "-")
.replace(/\//g, "_");
@ -73,8 +77,8 @@ export const QRDialog = ({
{channel.settings?.name.length
? channel.settings.name
: channel.role === Protobuf.Channel.Channel_Role.PRIMARY
? "Primary"
: `Channel: ${channel.index}`}
? "Primary"
: `Channel: ${channel.index}`}
</Label>
<Checkbox
key={channel.index}
@ -82,7 +86,9 @@ export const QRDialog = ({
onCheckedChange={() => {
if (selectedChannels.includes(channel.index)) {
setSelectedChannels(
selectedChannels.filter((c) => c !== channel.index),
selectedChannels.filter((c) =>
c !== channel.index
),
);
} else {
setSelectedChannels([

68
src/components/PageComponents/Channel.tsx

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

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

@ -1,5 +1,6 @@
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";
@ -53,7 +54,7 @@ export const Bluetooth = () => {
}
setWorkingConfig(
new Protobuf.Config.Config({
create(Protobuf.Config.ConfigSchema, {
payloadVariant: {
case: "bluetooth",
value: data,
@ -110,9 +111,8 @@ export const Bluetooth = () => {
disabledBy: [
{
fieldName: "mode",
selector:
Protobuf.Config.Config_BluetoothConfig_PairingMode
.FIXED_PIN,
selector: Protobuf.Config.Config_BluetoothConfig_PairingMode
.FIXED_PIN,
invert: true,
},
{

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

@ -1,4 +1,5 @@
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";
@ -8,7 +9,7 @@ export const Device = (): JSX.Element => {
const onSubmit = (data: DeviceValidation) => {
setWorkingConfig(
new Protobuf.Config.Config({
create(Protobuf.Config.ConfigSchema, {
payloadVariant: {
case: "device",
value: data,

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

@ -1,4 +1,5 @@
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";
@ -8,7 +9,7 @@ export const Display = (): JSX.Element => {
const onSubmit = (data: DisplayValidation) => {
setWorkingConfig(
new Protobuf.Config.Config({
create(Protobuf.Config.ConfigSchema, {
payloadVariant: {
case: "display",
value: data,

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

@ -1,4 +1,5 @@
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";
@ -8,7 +9,7 @@ export const LoRa = (): JSX.Element => {
const onSubmit = (data: LoRaValidation) => {
setWorkingConfig(
new Protobuf.Config.Config({
create(Protobuf.Config.ConfigSchema, {
payloadVariant: {
case: "lora",
value: data,

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

@ -1,4 +1,5 @@
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 {
@ -12,17 +13,20 @@ export const Network = (): JSX.Element => {
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
src/components/PageComponents/Config/Position.tsx

@ -3,6 +3,7 @@ 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";
@ -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 },

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

@ -1,4 +1,5 @@
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";
@ -8,7 +9,7 @@ export const Power = (): JSX.Element => {
const onSubmit = (data: PowerValidation) => {
setWorkingConfig(
new Protobuf.Config.Config({
create(Protobuf.Config.ConfigSchema, {
payloadVariant: {
case: "power",
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 { useReducer } from "react";
import { securityReducer } from "./securityReducer";
import { create } from "@bufbuild/protobuf";
export const Security = () => {
const { config, setWorkingConfig, setDialogOpen } = useDevice();
@ -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: {
@ -243,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,
@ -303,8 +308,7 @@ export const Security = () => {
<PkiRegenerateDialog
open={state.privateKeyDialogOpen}
onOpenChange={() =>
dispatch({ type: "SHOW_PRIVATE_KEY_DIALOG", payload: false })
}
dispatch({ type: "SHOW_PRIVATE_KEY_DIALOG", payload: false })}
onSubmit={pkiRegenerate}
/>
</>

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

@ -1,5 +1,6 @@
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";
@ -8,7 +9,7 @@ export const AmbientLighting = (): JSX.Element => {
const onSubmit = (data: AmbientLightingValidation) => {
setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({
create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: {
case: "ambientLighting",
value: data,

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

@ -1,4 +1,5 @@
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";
@ -8,7 +9,7 @@ export const Audio = (): JSX.Element => {
const onSubmit = (data: AudioValidation) => {
setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({
create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: {
case: "audio",
value: data,

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

@ -1,4 +1,5 @@
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";
@ -8,7 +9,7 @@ export const CannedMessage = (): JSX.Element => {
const onSubmit = (data: CannedMessageValidation) => {
setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({
create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: {
case: "cannedMessage",
value: data,
@ -62,9 +63,8 @@ export const CannedMessage = (): JSX.Element => {
label: "Clockwise event",
description: "Select input event.",
properties: {
enumValue:
Protobuf.ModuleConfig
.ModuleConfig_CannedMessageConfig_InputEventChar,
enumValue: Protobuf.ModuleConfig
.ModuleConfig_CannedMessageConfig_InputEventChar,
},
},
{
@ -73,9 +73,8 @@ export const CannedMessage = (): JSX.Element => {
label: "Counter Clockwise event",
description: "Select input event.",
properties: {
enumValue:
Protobuf.ModuleConfig
.ModuleConfig_CannedMessageConfig_InputEventChar,
enumValue: Protobuf.ModuleConfig
.ModuleConfig_CannedMessageConfig_InputEventChar,
},
},
{
@ -84,9 +83,8 @@ export const CannedMessage = (): JSX.Element => {
label: "Press event",
description: "Select input event",
properties: {
enumValue:
Protobuf.ModuleConfig
.ModuleConfig_CannedMessageConfig_InputEventChar,
enumValue: Protobuf.ModuleConfig
.ModuleConfig_CannedMessageConfig_InputEventChar,
},
},
{

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

@ -1,5 +1,6 @@
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";
@ -8,7 +9,7 @@ export const DetectionSensor = (): JSX.Element => {
const onSubmit = (data: DetectionSensorValidation) => {
setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({
create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: {
case: "detectionSensor",
value: data,

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

@ -1,4 +1,5 @@
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";
@ -8,7 +9,7 @@ export const ExternalNotification = (): JSX.Element => {
const onSubmit = (data: ExternalNotificationValidation) => {
setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({
create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: {
case: "externalNotification",
value: data,

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

@ -1,5 +1,6 @@
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";
@ -8,15 +9,16 @@ export const MQTT = (): JSX.Element => {
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,
),
},
},
}),
@ -164,32 +166,31 @@ export const MQTT = (): JSX.Element => {
description:
"Position shared will be accurate within this distance",
properties: {
enumValue:
config.display?.units === 0
? {
"Within 23 km": 10,
"Within 12 km": 11,
"Within 5.8 km": 12,
"Within 2.9 km": 13,
"Within 1.5 km": 14,
"Within 700 m": 15,
"Within 350 m": 16,
"Within 200 m": 17,
"Within 90 m": 18,
"Within 50 m": 19,
}
: {
"Within 15 miles": 10,
"Within 7.3 miles": 11,
"Within 3.6 miles": 12,
"Within 1.8 miles": 13,
"Within 0.9 miles": 14,
"Within 0.5 miles": 15,
"Within 0.2 miles": 16,
"Within 600 feet": 17,
"Within 300 feet": 18,
"Within 150 feet": 19,
},
enumValue: config.display?.units === 0
? {
"Within 23 km": 10,
"Within 12 km": 11,
"Within 5.8 km": 12,
"Within 2.9 km": 13,
"Within 1.5 km": 14,
"Within 700 m": 15,
"Within 350 m": 16,
"Within 200 m": 17,
"Within 90 m": 18,
"Within 50 m": 19,
}
: {
"Within 15 miles": 10,
"Within 7.3 miles": 11,
"Within 3.6 miles": 12,
"Within 1.8 miles": 13,
"Within 0.9 miles": 14,
"Within 0.5 miles": 15,
"Within 0.2 miles": 16,
"Within 600 feet": 17,
"Within 300 feet": 18,
"Within 150 feet": 19,
},
},
disabledBy: [
{

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

@ -1,5 +1,6 @@
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";
@ -8,7 +9,7 @@ export const NeighborInfo = (): JSX.Element => {
const onSubmit = (data: NeighborInfoValidation) => {
setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({
create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: {
case: "neighborInfo",
value: data,

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

@ -1,4 +1,5 @@
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";
@ -8,7 +9,7 @@ export const Paxcounter = (): JSX.Element => {
const onSubmit = (data: PaxcounterValidation) => {
setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({
create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: {
case: "paxcounter",
value: data,

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

@ -1,4 +1,5 @@
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";
@ -8,7 +9,7 @@ export const RangeTest = (): JSX.Element => {
const onSubmit = (data: RangeTestValidation) => {
setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({
create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: {
case: "rangeTest",
value: data,

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

@ -1,4 +1,5 @@
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";
@ -8,7 +9,7 @@ export const Serial = (): JSX.Element => {
const onSubmit = (data: SerialValidation) => {
setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({
create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: {
case: "serial",
value: data,

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

@ -1,4 +1,5 @@
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";
@ -8,7 +9,7 @@ export const StoreForward = (): JSX.Element => {
const onSubmit = (data: StoreForwardValidation) => {
setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({
create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: {
case: "storeForward",
value: data,

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

@ -1,4 +1,5 @@
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";
@ -8,7 +9,7 @@ export const Telemetry = (): JSX.Element => {
const onSubmit = (data: TelemetryValidation) => {
setWorkingModuleConfig(
new Protobuf.ModuleConfig.ModuleConfig({
create(Protobuf.ModuleConfig.ModuleConfigSchema, {
payloadVariant: {
case: "telemetry",
value: data,

51
src/core/stores/deviceStore.ts

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

29
src/pages/Map/index.tsx

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

4
tsconfig.json

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

Loading…
Cancel
Save