diff --git a/.npmrc b/.npmrc index 8dd477af..41583e36 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1 @@ -@buf:registry=https://buf.build/gen/npm/v1 +@jsr:registry=https://npm.jsr.io diff --git a/package.json b/package.json index 0ea7e064..6b060bcb 100644 --- a/package.json +++ b/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/meshtastic__js@2.6.0-0", "@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" } } diff --git a/src/App.tsx b/src/App.tsx index eb5bb1bd..a7c278fb 100644 --- a/src/App.tsx +++ b/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 => {
- {device ? ( -
- - - - -
- ) : ( - <> - -
diff --git a/src/components/Dialog/DeviceNameDialog.tsx b/src/components/Dialog/DeviceNameDialog.tsx index 1b27ed8d..d6146972 100644 --- a/src/components/Dialog/DeviceNameDialog.tsx +++ b/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, }), diff --git a/src/components/Dialog/ImportDialog.tsx b/src/components/Dialog/ImportDialog.tsx index 5ea39e1c..5d9e22e1 100644 --- a/src/components/Dialog/ImportDialog.tsx +++ b/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} /> - {/* */} + */ + } - {/* */} + */ + } Channels: diff --git a/src/components/Dialog/QRDialog.tsx b/src/components/Dialog/QRDialog.tsx index 825464ec..2f4be9a5 100644 --- a/src/components/Dialog/QRDialog.tsx +++ b/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}`} { if (selectedChannels.includes(channel.index)) { setSelectedChannels( - selectedChannels.filter((c) => c !== channel.index), + selectedChannels.filter((c) => + c !== channel.index + ), ); } else { setSelectedChannels([ diff --git a/src/components/PageComponents/Channel.tsx b/src/components/PageComponents/Channel.tsx index dcd69c17..5ae88160 100644 --- a/src/components/PageComponents/Channel.tsx +++ b/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(); - const [preSharedDialogOpen, setPreSharedDialogOpen] = - useState(false); + const [preSharedDialogOpen, setPreSharedDialogOpen] = useState( + 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, + }, }, }, ], diff --git a/src/components/PageComponents/Config/Bluetooth.tsx b/src/components/PageComponents/Config/Bluetooth.tsx index 21bc7c4e..474663bd 100644 --- a/src/components/PageComponents/Config/Bluetooth.tsx +++ b/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, }, { diff --git a/src/components/PageComponents/Config/Device.tsx b/src/components/PageComponents/Config/Device.tsx index 17ee8cb2..c06fe178 100644 --- a/src/components/PageComponents/Config/Device.tsx +++ b/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, diff --git a/src/components/PageComponents/Config/Display.tsx b/src/components/PageComponents/Config/Display.tsx index 5589a8a7..64b5b368 100644 --- a/src/components/PageComponents/Config/Display.tsx +++ b/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, diff --git a/src/components/PageComponents/Config/LoRa.tsx b/src/components/PageComponents/Config/LoRa.tsx index 80665f6c..8dfb81c9 100644 --- a/src/components/PageComponents/Config/LoRa.tsx +++ b/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, diff --git a/src/components/PageComponents/Config/Network.tsx b/src/components/PageComponents/Config/Network.tsx index afda4eb5..76f1d54d 100644 --- a/src/components/PageComponents/Config/Network.tsx +++ b/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, + }, + ), }, }, }), diff --git a/src/components/PageComponents/Config/Position.tsx b/src/components/PageComponents/Config/Position.tsx index e81af178..4aa3abba 100644 --- a/src/components/PageComponents/Config/Position.tsx +++ b/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 }, diff --git a/src/components/PageComponents/Config/Power.tsx b/src/components/PageComponents/Config/Power.tsx index 4f52be5f..e49d7ff6 100644 --- a/src/components/PageComponents/Config/Power.tsx +++ b/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, diff --git a/src/components/PageComponents/Config/Security/Security.tsx b/src/components/PageComponents/Config/Security/Security.tsx index 85ba36fd..6047381b 100644 --- a/src/components/PageComponents/Config/Security/Security.tsx +++ b/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 = () => { - dispatch({ type: "SHOW_PRIVATE_KEY_DIALOG", payload: false }) - } + dispatch({ type: "SHOW_PRIVATE_KEY_DIALOG", payload: false })} onSubmit={pkiRegenerate} /> diff --git a/src/components/PageComponents/ModuleConfig/AmbientLighting.tsx b/src/components/PageComponents/ModuleConfig/AmbientLighting.tsx index 978ef633..f7853710 100644 --- a/src/components/PageComponents/ModuleConfig/AmbientLighting.tsx +++ b/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, diff --git a/src/components/PageComponents/ModuleConfig/Audio.tsx b/src/components/PageComponents/ModuleConfig/Audio.tsx index c68bd9bf..46d2176c 100644 --- a/src/components/PageComponents/ModuleConfig/Audio.tsx +++ b/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, diff --git a/src/components/PageComponents/ModuleConfig/CannedMessage.tsx b/src/components/PageComponents/ModuleConfig/CannedMessage.tsx index 5fb1046a..672bbbb5 100644 --- a/src/components/PageComponents/ModuleConfig/CannedMessage.tsx +++ b/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, }, }, { diff --git a/src/components/PageComponents/ModuleConfig/DetectionSensor.tsx b/src/components/PageComponents/ModuleConfig/DetectionSensor.tsx index c7ec3c98..e547fab1 100644 --- a/src/components/PageComponents/ModuleConfig/DetectionSensor.tsx +++ b/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, diff --git a/src/components/PageComponents/ModuleConfig/ExternalNotification.tsx b/src/components/PageComponents/ModuleConfig/ExternalNotification.tsx index f6b52662..dfe61fad 100644 --- a/src/components/PageComponents/ModuleConfig/ExternalNotification.tsx +++ b/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, diff --git a/src/components/PageComponents/ModuleConfig/MQTT.tsx b/src/components/PageComponents/ModuleConfig/MQTT.tsx index bb9b1527..4b6bfe25 100644 --- a/src/components/PageComponents/ModuleConfig/MQTT.tsx +++ b/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: [ { diff --git a/src/components/PageComponents/ModuleConfig/NeighborInfo.tsx b/src/components/PageComponents/ModuleConfig/NeighborInfo.tsx index 9c878911..1dfa9532 100644 --- a/src/components/PageComponents/ModuleConfig/NeighborInfo.tsx +++ b/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, diff --git a/src/components/PageComponents/ModuleConfig/Paxcounter.tsx b/src/components/PageComponents/ModuleConfig/Paxcounter.tsx index e31a298c..d4118b8e 100644 --- a/src/components/PageComponents/ModuleConfig/Paxcounter.tsx +++ b/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, diff --git a/src/components/PageComponents/ModuleConfig/RangeTest.tsx b/src/components/PageComponents/ModuleConfig/RangeTest.tsx index a661805d..6c98d45a 100644 --- a/src/components/PageComponents/ModuleConfig/RangeTest.tsx +++ b/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, diff --git a/src/components/PageComponents/ModuleConfig/Serial.tsx b/src/components/PageComponents/ModuleConfig/Serial.tsx index 92db0d9a..e7afd3eb 100644 --- a/src/components/PageComponents/ModuleConfig/Serial.tsx +++ b/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, diff --git a/src/components/PageComponents/ModuleConfig/StoreForward.tsx b/src/components/PageComponents/ModuleConfig/StoreForward.tsx index 6fe5c585..dbd17c28 100644 --- a/src/components/PageComponents/ModuleConfig/StoreForward.tsx +++ b/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, diff --git a/src/components/PageComponents/ModuleConfig/Telemetry.tsx b/src/components/PageComponents/ModuleConfig/Telemetry.tsx index 24074f48..c6e9f4fb 100644 --- a/src/components/PageComponents/ModuleConfig/Telemetry.tsx +++ b/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, diff --git a/src/core/stores/deviceStore.ts b/src/core/stores/deviceStore.ts index a4ad7b69..74c4453b 100644 --- a/src/core/stores/deviceStore.ts +++ b/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((set, get) => ({ +export const useDeviceStore = createStore((set, get) => ({ devices: new Map(), remoteDevices: new Map(), @@ -122,11 +121,11 @@ export const useDeviceStore = create((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((set, get) => ({ activePage: "messages", activeNode: 0, waypoints: [], - // currentMetrics: new Protobuf.DeviceMetrics(), dialog: { import: false, QR: false, @@ -301,11 +299,11 @@ export const useDeviceStore = create((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((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((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((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((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((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, diff --git a/src/pages/Map/index.tsx b/src/pages/Map/index.tsx index 481b88c7..bb69825c 100644 --- a/src/pages/Map/index.tsx +++ b/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(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 => { ))} {markers} - {selectedNode ? ( - setSelectedNode(null)} - > - - - ) : null} + {selectedNode + ? ( + setSelectedNode(null)} + > + + + ) + : null} diff --git a/tsconfig.json b/tsconfig.json index 9f4e8d3f..91f1dff3 100644 --- a/tsconfig.json +++ b/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,