diff --git a/README.md b/README.md index ba64a5b58..364cf0fb5 100644 --- a/README.md +++ b/README.md @@ -59,3 +59,15 @@ Start the development server: ```bash pnpm dev ``` + +### Updating Protobufs + +To update to the latest protobufs go to https://buf.build/meshtastic/protobufs/sdks and select plugin version `1.10`. + +The version should look something like this: `1.10.0-20240906232734-3da561588c55.1` + +Where the version is *always* `1.10.0` followed by a timestamp and a commit hash. Updating to an SDK version higher than 1.10.0 has breaking changes. + +Use that version to updated your `package.json` file. + +*Ensure to keep the `meshtastic/js` protobufs in step with web* \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9e91a4c51..80a4428b4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1343,6 +1343,70 @@ packages: cpu: [x64] os: [win32] + '@serialport/binding-mock@10.2.2': + resolution: {integrity: sha512-HAFzGhk9OuFMpuor7aT5G1ChPgn5qSsklTFOTUX72Rl6p0xwcSVsRtG/xaGp6bxpN7fI9D/S8THLBWbBgS6ldw==} + engines: {node: '>=12.0.0'} + + '@serialport/bindings-cpp@12.0.1': + resolution: {integrity: sha512-r2XOwY2dDvbW7dKqSPIk2gzsr6M6Qpe9+/Ngs94fNaNlcTRCV02PfaoDmRgcubpNVVcLATlxSxPTIDw12dbKOg==} + engines: {node: '>=16.0.0'} + + '@serialport/bindings-interface@1.2.2': + resolution: {integrity: sha512-CJaUd5bLvtM9c5dmO9rPBHPXTa9R2UwpkJ0wdh9JCYcbrPWsKz+ErvR0hBLeo7NPeiFdjFO4sonRljiw4d2XiA==} + engines: {node: ^12.22 || ^14.13 || >=16} + + '@serialport/parser-byte-length@12.0.0': + resolution: {integrity: sha512-0ei0txFAj+s6FTiCJFBJ1T2hpKkX8Md0Pu6dqMrYoirjPskDLJRgZGLqoy3/lnU1bkvHpnJO+9oJ3PB9v8rNlg==} + engines: {node: '>=12.0.0'} + + '@serialport/parser-cctalk@12.0.0': + resolution: {integrity: sha512-0PfLzO9t2X5ufKuBO34DQKLXrCCqS9xz2D0pfuaLNeTkyGUBv426zxoMf3rsMRodDOZNbFblu3Ae84MOQXjnZw==} + engines: {node: '>=12.0.0'} + + '@serialport/parser-delimiter@11.0.0': + resolution: {integrity: sha512-aZLJhlRTjSmEwllLG7S4J8s8ctRAS0cbvCpO87smLvl3e4BgzbVgF6Z6zaJd3Aji2uSiYgfedCdNc4L6W+1E2g==} + engines: {node: '>=12.0.0'} + + '@serialport/parser-delimiter@12.0.0': + resolution: {integrity: sha512-gu26tVt5lQoybhorLTPsH2j2LnX3AOP2x/34+DUSTNaUTzu2fBXw+isVjQJpUBFWu6aeQRZw5bJol5X9Gxjblw==} + engines: {node: '>=12.0.0'} + + '@serialport/parser-inter-byte-timeout@12.0.0': + resolution: {integrity: sha512-GnCh8K0NAESfhCuXAt+FfBRz1Cf9CzIgXfp7SdMgXwrtuUnCC/yuRTUFWRvuzhYKoAo1TL0hhUo77SFHUH1T/w==} + engines: {node: '>=12.0.0'} + + '@serialport/parser-packet-length@12.0.0': + resolution: {integrity: sha512-p1hiCRqvGHHLCN/8ZiPUY/G0zrxd7gtZs251n+cfNTn+87rwcdUeu9Dps3Aadx30/sOGGFL6brIRGK4l/t7MuQ==} + engines: {node: '>=8.6.0'} + + '@serialport/parser-readline@11.0.0': + resolution: {integrity: sha512-rRAivhRkT3YO28WjmmG4FQX6L+KMb5/ikhyylRfzWPw0nSXy97+u07peS9CbHqaNvJkMhH1locp2H36aGMOEIA==} + engines: {node: '>=12.0.0'} + + '@serialport/parser-readline@12.0.0': + resolution: {integrity: sha512-O7cywCWC8PiOMvo/gglEBfAkLjp/SENEML46BXDykfKP5mTPM46XMaX1L0waWU6DXJpBgjaL7+yX6VriVPbN4w==} + engines: {node: '>=12.0.0'} + + '@serialport/parser-ready@12.0.0': + resolution: {integrity: sha512-ygDwj3O4SDpZlbrRUraoXIoIqb8sM7aMKryGjYTIF0JRnKeB1ys8+wIp0RFMdFbO62YriUDextHB5Um5cKFSWg==} + engines: {node: '>=12.0.0'} + + '@serialport/parser-regex@12.0.0': + resolution: {integrity: sha512-dCAVh4P/pZrLcPv9NJ2mvPRBg64L5jXuiRxIlyxxdZGH4WubwXVXY/kBTihQmiAMPxbT3yshSX8f2+feqWsxqA==} + engines: {node: '>=12.0.0'} + + '@serialport/parser-slip-encoder@12.0.0': + resolution: {integrity: sha512-0APxDGR9YvJXTRfY+uRGhzOhTpU5akSH183RUcwzN7QXh8/1jwFsFLCu0grmAUfi+fItCkR+Xr1TcNJLR13VNA==} + engines: {node: '>=12.0.0'} + + '@serialport/parser-spacepacket@12.0.0': + resolution: {integrity: sha512-dozONxhPC/78pntuxpz/NOtVps8qIc/UZzdc/LuPvVsqCoJXiRxOg6ZtCP/W58iibJDKPZPAWPGYeZt9DJxI+Q==} + engines: {node: '>=12.0.0'} + + '@serialport/stream@12.0.0': + resolution: {integrity: sha512-9On64rhzuqKdOQyiYLYv2lQOh3TZU/D3+IWCR5gk0alPel2nwpp4YwDEGiUBfrQZEdQ6xww0PWkzqth4wqwX3Q==} + engines: {node: '>=12.0.0'} + '@stablelib/binary@1.0.1': resolution: {integrity: sha512-ClJWvmL6UBM/wjkvv/7m5VP3GMr9t0osr4yVgLZsLCOz4hGN9gIAFEqnJ0TsSMAN+n840nf2cHZnA5/KFqHC7Q==} @@ -2038,6 +2102,15 @@ packages: d3-voronoi@1.1.2: resolution: {integrity: sha512-RhGS1u2vavcO7ay7ZNAPo4xeDh/VYeGof3x5ZLJBQgYhLegxr3s5IykvWmJ94FTU6mcbtp4sloqZ54mP6R4Utw==} + debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + debug@4.3.5: resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==} engines: {node: '>=6.0'} @@ -2620,6 +2693,13 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + node-addon-api@7.0.0: + resolution: {integrity: sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA==} + + node-gyp-build@4.6.0: + resolution: {integrity: sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==} + hasBin: true + node-releases@2.0.14: resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} @@ -3024,6 +3104,10 @@ packages: resolution: {integrity: sha512-owllqNuDDEimQat7EPG0tH7JjO090xKNzUtYz6X+Sk2BXDnOCilDdNLwjWeFywG9xkJul1ULvtUQa9O4pUaY0w==} engines: {node: '>=4.0.0'} + serialport@12.0.0: + resolution: {integrity: sha512-AmH3D9hHPFmnF/oq/rvigfiAouAKyK/TjnrkwZRYSFZxNggJxwvbAbfYrLeuvq7ktUdhuHdVdSjj852Z55R+uA==} + engines: {node: '>=16.0.0'} + set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} @@ -3805,10 +3889,12 @@ snapshots: '@meshtastic/js@2.3.7-5': dependencies: crc: 4.3.2 + serialport: 12.0.0 ste-simple-events: 3.0.11 tslog: 4.9.3 transitivePeerDependencies: - buffer + - supports-color '@noble/curves@1.5.0': dependencies: @@ -4542,6 +4628,60 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.18.0': optional: true + '@serialport/binding-mock@10.2.2': + dependencies: + '@serialport/bindings-interface': 1.2.2 + debug: 4.3.5 + transitivePeerDependencies: + - supports-color + + '@serialport/bindings-cpp@12.0.1': + dependencies: + '@serialport/bindings-interface': 1.2.2 + '@serialport/parser-readline': 11.0.0 + debug: 4.3.4 + node-addon-api: 7.0.0 + node-gyp-build: 4.6.0 + transitivePeerDependencies: + - supports-color + + '@serialport/bindings-interface@1.2.2': {} + + '@serialport/parser-byte-length@12.0.0': {} + + '@serialport/parser-cctalk@12.0.0': {} + + '@serialport/parser-delimiter@11.0.0': {} + + '@serialport/parser-delimiter@12.0.0': {} + + '@serialport/parser-inter-byte-timeout@12.0.0': {} + + '@serialport/parser-packet-length@12.0.0': {} + + '@serialport/parser-readline@11.0.0': + dependencies: + '@serialport/parser-delimiter': 11.0.0 + + '@serialport/parser-readline@12.0.0': + dependencies: + '@serialport/parser-delimiter': 12.0.0 + + '@serialport/parser-ready@12.0.0': {} + + '@serialport/parser-regex@12.0.0': {} + + '@serialport/parser-slip-encoder@12.0.0': {} + + '@serialport/parser-spacepacket@12.0.0': {} + + '@serialport/stream@12.0.0': + dependencies: + '@serialport/bindings-interface': 1.2.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + '@stablelib/binary@1.0.1': dependencies: '@stablelib/int': 1.0.1 @@ -5795,6 +5935,10 @@ snapshots: d3-voronoi@1.1.2: {} + debug@4.3.4: + dependencies: + ms: 2.1.2 + debug@4.3.5: dependencies: ms: 2.1.2 @@ -6433,6 +6577,10 @@ snapshots: nanoid@3.3.7: {} + node-addon-api@7.0.0: {} + + node-gyp-build@4.6.0: {} + node-releases@2.0.14: {} node-stdlib-browser@1.2.0: @@ -6867,6 +7015,25 @@ snapshots: serialize-to-js@3.1.2: {} + serialport@12.0.0: + dependencies: + '@serialport/binding-mock': 10.2.2 + '@serialport/bindings-cpp': 12.0.1 + '@serialport/parser-byte-length': 12.0.0 + '@serialport/parser-cctalk': 12.0.0 + '@serialport/parser-delimiter': 12.0.0 + '@serialport/parser-inter-byte-timeout': 12.0.0 + '@serialport/parser-packet-length': 12.0.0 + '@serialport/parser-readline': 12.0.0 + '@serialport/parser-ready': 12.0.0 + '@serialport/parser-regex': 12.0.0 + '@serialport/parser-slip-encoder': 12.0.0 + '@serialport/parser-spacepacket': 12.0.0 + '@serialport/stream': 12.0.0 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 diff --git a/src/components/PageComponents/ModuleConfig/CannedMessage.tsx b/src/components/PageComponents/ModuleConfig/CannedMessage.tsx index 1ab3da317..bc120023a 100644 --- a/src/components/PageComponents/ModuleConfig/CannedMessage.tsx +++ b/src/components/PageComponents/ModuleConfig/CannedMessage.tsx @@ -4,7 +4,8 @@ import { useDevice } from "@core/stores/deviceStore.js"; import { Protobuf } from "@meshtastic/js"; export const CannedMessage = (): JSX.Element => { - const { moduleConfig, setWorkingModuleConfig } = useDevice(); + const { moduleConfig, cannedMessagesConfig, setWorkingModuleConfig, setWorkingCannedMessages } = + useDevice(); const onSubmit = (data: CannedMessageValidation) => { setWorkingModuleConfig( @@ -15,12 +16,23 @@ export const CannedMessage = (): JSX.Element => { }, }), ); + + setWorkingCannedMessages( + new Protobuf.CannedMessages.CannedMessageModuleConfig({ + messages: data.messages, + }), + ); }; return ( onSubmit={onSubmit} - defaultValues={moduleConfig.cannedMessage} + defaultValues={{ + ...moduleConfig.cannedMessage, + ...{ + messages: cannedMessagesConfig.messages + } + }} fieldGroups={[ { label: "Canned Message Settings", @@ -32,6 +44,12 @@ export const CannedMessage = (): JSX.Element => { label: "Module Enabled", description: "Enable Canned Message", }, + { + type: "text", + name: "messages", + label: "Messages", + description: "Separate messages with |", + }, { type: "toggle", name: "rotary1Enabled", diff --git a/src/core/stores/deviceStore.ts b/src/core/stores/deviceStore.ts index a716a85bc..a1f086bbb 100644 --- a/src/core/stores/deviceStore.ts +++ b/src/core/stores/deviceStore.ts @@ -33,8 +33,10 @@ export interface Device { channels: Map; config: Protobuf.LocalOnly.LocalConfig; moduleConfig: Protobuf.LocalOnly.LocalModuleConfig; + cannedMessagesConfig: Protobuf.CannedMessages.CannedMessageModuleConfig; workingConfig: Protobuf.Config.Config[]; workingModuleConfig: Protobuf.ModuleConfig.ModuleConfig[]; + workingCannedMessagesConfig: Protobuf.CannedMessages.CannedMessageModuleConfig[]; hardware: Protobuf.Mesh.MyNodeInfo; nodes: Map; metadata: Map; @@ -69,6 +71,8 @@ export interface Device { setWorkingModuleConfig: (config: Protobuf.ModuleConfig.ModuleConfig) => void; setHardware: (hardware: Protobuf.Mesh.MyNodeInfo) => void; // setMetrics: (metrics: Types.PacketMetadata) => void; + setCannedMessages: (config: Protobuf.CannedMessages.CannedMessageModuleConfig) => void; + setWorkingCannedMessages: (config: Protobuf.CannedMessages.CannedMessageModuleConfig) => void; setActivePage: (page: Page) => void; setActiveNode: (node: number) => void; setPendingSettingsChanges: (state: boolean) => void; @@ -120,8 +124,10 @@ export const useDeviceStore = create((set, get) => ({ channels: new Map(), config: new Protobuf.LocalOnly.LocalConfig(), moduleConfig: new Protobuf.LocalOnly.LocalModuleConfig(), + cannedMessagesConfig: new Protobuf.CannedMessages.CannedMessageModuleConfig(), workingConfig: [], workingModuleConfig: [], + workingCannedMessagesConfig: [], hardware: new Protobuf.Mesh.MyNodeInfo(), nodes: new Map(), metadata: new Map(), @@ -153,7 +159,7 @@ export const useDeviceStore = create((set, get) => ({ if (device) { device.status = status; } - }), + }) ); }, setConfig: (config: Protobuf.Config.Config) => { @@ -196,7 +202,7 @@ export const useDeviceStore = create((set, get) => ({ } } } - }), + }) ); }, setModuleConfig: (config: Protobuf.ModuleConfig.ModuleConfig) => { @@ -265,7 +271,7 @@ export const useDeviceStore = create((set, get) => ({ } } } - }), + }) ); }, setWorkingConfig: (config: Protobuf.Config.Config) => { @@ -276,18 +282,18 @@ export const useDeviceStore = create((set, get) => ({ return; } const workingConfigIndex = device?.workingConfig.findIndex( - (wc) => wc.payloadVariant.case === config.payloadVariant.case, + (wc) => wc.payloadVariant.case === config.payloadVariant.case ); if (workingConfigIndex !== -1) { device.workingConfig[workingConfigIndex] = config; } else { device?.workingConfig.push(config); } - }), + }) ); }, setWorkingModuleConfig: ( - moduleConfig: Protobuf.ModuleConfig.ModuleConfig, + moduleConfig: Protobuf.ModuleConfig.ModuleConfig ) => { set( produce((draft) => { @@ -295,19 +301,35 @@ export const useDeviceStore = create((set, get) => ({ if (!device) { return; } - const workingModuleConfigIndex = - device?.workingModuleConfig.findIndex( - (wmc) => - wmc.payloadVariant.case === - moduleConfig.payloadVariant.case, - ); + const workingModuleConfigIndex = device?.workingModuleConfig.findIndex( + (wmc) => wmc.payloadVariant.case === + moduleConfig.payloadVariant.case + ); if (workingModuleConfigIndex !== -1) { device.workingModuleConfig[workingModuleConfigIndex] = moduleConfig; } else { device?.workingModuleConfig.push(moduleConfig); } - }), + }) + ); + }, + setWorkingCannedMessages: ( + cannedConfig: Protobuf.CannedMessages.CannedMessageModuleConfig + ) => { + set( + produce((draft) => { + const device = draft.devices.get(id); + if (!device) { + return; + } + if (device?.workingCannedMessagesConfig) { + device?.workingCannedMessagesConfig.pop(); + device?.workingCannedMessagesConfig.push(cannedConfig); + } else { + device?.workingCannedMessagesConfig.push(cannedConfig); + } + }) ); }, setHardware: (hardware: Protobuf.Mesh.MyNodeInfo) => { @@ -317,7 +339,7 @@ export const useDeviceStore = create((set, get) => ({ if (device) { device.hardware = hardware; } - }), + }) ); }, // setMetrics: (metrics: Types.PacketMetadata) => { @@ -364,6 +386,16 @@ export const useDeviceStore = create((set, get) => ({ // }) // ); // }, + setCannedMessages: (messages) => { + set( + produce((draft) => { + const device = draft.devices.get(id); + if (device) { + device.setCannedMessages(messages); + } + }) + ); + }, setActivePage: (page) => { set( produce((draft) => { @@ -371,7 +403,7 @@ export const useDeviceStore = create((set, get) => ({ if (device) { device.activePage = page; } - }), + }) ); }, setPendingSettingsChanges: (state) => { @@ -381,7 +413,7 @@ export const useDeviceStore = create((set, get) => ({ if (device) { device.pendingSettingsChanges = state; } - }), + }) ); }, addChannel: (channel: Protobuf.Channel.Channel) => { @@ -392,7 +424,7 @@ export const useDeviceStore = create((set, get) => ({ return; } device.channels.set(channel.index, channel); - }), + }) ); }, addWaypoint: (waypoint: Protobuf.Mesh.Waypoint) => { @@ -401,7 +433,7 @@ export const useDeviceStore = create((set, get) => ({ const device = draft.devices.get(id); if (device) { const waypointIndex = device.waypoints.findIndex( - (wp) => wp.id === waypoint.id, + (wp) => wp.id === waypoint.id ); if (waypointIndex !== -1) { @@ -410,7 +442,7 @@ export const useDeviceStore = create((set, get) => ({ device.waypoints.push(waypoint); } } - }), + }) ); }, addNodeInfo: (nodeInfo) => { @@ -421,7 +453,7 @@ export const useDeviceStore = create((set, get) => ({ return; } device.nodes.set(nodeInfo.num, nodeInfo); - }), + }) ); }, setActiveNode: (node) => { @@ -431,7 +463,7 @@ export const useDeviceStore = create((set, get) => ({ if (device) { device.activeNode = node; } - }), + }) ); }, addUser: (user) => { @@ -441,11 +473,10 @@ 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) ?? new Protobuf.Mesh.NodeInfo(); currentNode.user = user.data; device.nodes.set(user.from, currentNode); - }), + }) ); }, addPosition: (position) => { @@ -455,12 +486,11 @@ export const useDeviceStore = create((set, get) => ({ if (!device) { return; } - const currentNode = - device.nodes.get(position.from) ?? + const currentNode = device.nodes.get(position.from) ?? new Protobuf.Mesh.NodeInfo(); currentNode.position = position.data; device.nodes.set(position.from, currentNode); - }), + }) ); }, addConnection: (connection) => { @@ -470,7 +500,7 @@ export const useDeviceStore = create((set, get) => ({ if (device) { device.connection = connection; } - }), + }) ); }, addMessage: (message) => { @@ -481,12 +511,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) { @@ -495,7 +524,7 @@ export const useDeviceStore = create((set, get) => ({ } else { messageGroup.set(messageIndex, [message]); } - }), + }) ); }, @@ -507,7 +536,7 @@ export const useDeviceStore = create((set, get) => ({ return; } device.metadata.set(from, metadata); - }), + }) ); }, addTraceRoute: (traceroute) => { @@ -527,7 +556,7 @@ export const useDeviceStore = create((set, get) => ({ } else { device.traceroutes.set(traceroute.from, [traceroute]); } - }), + }) ); }, removeNode: (nodeNum) => { @@ -538,7 +567,7 @@ export const useDeviceStore = create((set, get) => ({ return; } device.nodes.delete(nodeNum); - }), + }) ); }, setMessageState: ( @@ -547,7 +576,7 @@ export const useDeviceStore = create((set, get) => ({ to: number, from: number, messageId: number, - state: MessageState, + state: MessageState ) => { set( produce((draft) => { @@ -559,12 +588,11 @@ 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) { @@ -579,9 +607,9 @@ export const useDeviceStore = create((set, get) => ({ msg.state = state; } return msg; - }), + }) ); - }), + }) ); }, setDialogOpen: (dialog: DialogVariant, open: boolean) => { @@ -592,7 +620,7 @@ export const useDeviceStore = create((set, get) => ({ return; } device.dialog[dialog] = open; - }), + }) ); }, processPacket(data: ProcessPacketParams) { @@ -616,10 +644,10 @@ export const useDeviceStore = create((set, get) => ({ num: data.from, lastHeard: data.time, snr: data.snr, - }), + }) ); } - }), + }) ); }, setMessageDraft: (message: string) => { @@ -629,7 +657,7 @@ export const useDeviceStore = create((set, get) => ({ if (device) { device.messageDraft = message; } - }), + }) ); }, }); diff --git a/src/pages/Config/index.tsx b/src/pages/Config/index.tsx index c568670ab..a31c53a0a 100644 --- a/src/pages/Config/index.tsx +++ b/src/pages/Config/index.tsx @@ -10,7 +10,7 @@ import { BoxesIcon, SaveIcon, SettingsIcon } from "lucide-react"; import { useState } from "react"; export const ConfigPage = (): JSX.Element => { - const { workingConfig, workingModuleConfig, connection } = useDevice(); + const { workingConfig, workingModuleConfig, workingCannedMessagesConfig, connection } = useDevice(); const [activeConfigSection, setActiveConfigSection] = useState< "device" | "module" >("device"); @@ -55,9 +55,14 @@ export const ConfigPage = (): JSX.Element => { workingModuleConfig.map( async (moduleConfig) => await connection?.setModuleConfig(moduleConfig).then(() => - toast({ - title: `Config ${moduleConfig.payloadVariant.case} saved`, - }), + workingCannedMessagesConfig.map( + async (cannedConfig) => + await connection?.setCannedMessages(cannedConfig).then(() => + toast({ + title: `Config ${moduleConfig.payloadVariant.case} saved`, + }), + ) + ) ), ); } diff --git a/src/validation/moduleConfig/cannedMessage.ts b/src/validation/moduleConfig/cannedMessage.ts index 85c8d6a71..a40680a1f 100644 --- a/src/validation/moduleConfig/cannedMessage.ts +++ b/src/validation/moduleConfig/cannedMessage.ts @@ -1,6 +1,6 @@ import type { Message } from "@bufbuild/protobuf"; import { Protobuf } from "@meshtastic/js"; -import { IsBoolean, IsEnum, IsInt, Length } from "class-validator"; +import { IsBoolean, IsEnum, IsInt, IsString, Length } from "class-validator"; export class CannedMessageValidation implements @@ -38,4 +38,7 @@ export class CannedMessageValidation @IsBoolean() sendBell: boolean; + + @IsString() + messages: string; }