diff --git a/package.json b/package.json
index 1c055073..26e9d0a8 100644
--- a/package.json
+++ b/package.json
@@ -6,6 +6,7 @@
"license": "GPL-3.0-only",
"scripts": {
"build": "pnpm check && rsbuild build",
+ "build:analyze": "BUNDLE_ANALYZE=true rsbuild build",
"check": "biome check src/",
"check:fix": "pnpm check --write src/",
"format": "biome format --write src/",
@@ -17,6 +18,9 @@
"simple-git-hooks": {
"pre-commit": "npm run check:fix && npm run format"
},
+ "lint-staged": {
+ "*.{ts,tsx}": ["npm run check:fix", "npm run format"]
+ },
"repository": {
"type": "git",
"url": "git+https://github.com/meshtastic/web.git"
diff --git a/src/components/PageComponents/Config/Device.tsx b/src/components/PageComponents/Config/Device.tsx
index 9ef11904..17ee8cb2 100644
--- a/src/components/PageComponents/Config/Device.tsx
+++ b/src/components/PageComponents/Config/Device.tsx
@@ -46,7 +46,7 @@ export const Device = (): JSX.Element => {
"Lost and Found":
Protobuf.Config.Config_DeviceConfig_Role.LOST_AND_FOUND,
"TAK Tracker":
- Protobuf.Config.Config_DeviceConfig_Role.SENSOR,
+ Protobuf.Config.Config_DeviceConfig_Role.TAK_TRACKER,
},
formatEnumName: true,
},
diff --git a/src/components/PageComponents/Messages/ChannelChat.tsx b/src/components/PageComponents/Messages/ChannelChat.tsx
index 47c9095c..08d79832 100644
--- a/src/components/PageComponents/Messages/ChannelChat.tsx
+++ b/src/components/PageComponents/Messages/ChannelChat.tsx
@@ -80,7 +80,7 @@ export const ChannelChat = ({
-
+
);
diff --git a/src/components/PageComponents/Messages/MessageInput.tsx b/src/components/PageComponents/Messages/MessageInput.tsx
index 079cb448..2e7954c9 100644
--- a/src/components/PageComponents/Messages/MessageInput.tsx
+++ b/src/components/PageComponents/Messages/MessageInput.tsx
@@ -9,11 +9,13 @@ import { type JSX, useCallback, useMemo, useState } from "react";
export interface MessageInputProps {
to: Types.Destination;
channel: Types.ChannelNumber;
+ maxBytes: number;
}
export const MessageInput = ({
to,
channel,
+ maxBytes,
}: MessageInputProps): JSX.Element => {
const {
connection,
@@ -24,6 +26,7 @@ export const MessageInput = ({
} = useDevice();
const myNodeNum = hardware.myNodeNum;
const [localDraft, setLocalDraft] = useState(messageDraft);
+ const [messageBytes, setMessageBytes] = useState(maxBytes);
const debouncedSetMessageDraft = useMemo(
() => debounce(setMessageDraft, 300),
@@ -60,8 +63,12 @@ export const MessageInput = ({
const handleInputChange = (e: React.ChangeEvent) => {
const newValue = e.target.value;
- setLocalDraft(newValue);
- debouncedSetMessageDraft(newValue);
+ const byteLength = new Blob([newValue]).size;
+ if (byteLength <= maxBytes) {
+ setLocalDraft(newValue);
+ debouncedSetMessageDraft(newValue);
+ setMessageBytes(maxBytes - byteLength);
+ }
};
return (
@@ -85,6 +92,9 @@ export const MessageInput = ({
onChange={handleInputChange}
/>
+
+ {messageBytes}/{maxBytes}
+
diff --git a/src/components/PageLayout.tsx b/src/components/PageLayout.tsx
index f25eecab..81ec4915 100644
--- a/src/components/PageLayout.tsx
+++ b/src/components/PageLayout.tsx
@@ -35,7 +35,7 @@ export const PageLayout = ({
{actions?.map((action, index) => (
+
);
})}
diff --git a/src/pages/Messages.tsx b/src/pages/Messages.tsx
index 533c7c48..02ce37c6 100644
--- a/src/pages/Messages.tsx
+++ b/src/pages/Messages.tsx
@@ -20,9 +20,12 @@ const MessagesPage = () => {
const [activeChat, setActiveChat] = useState(
Types.ChannelNumber.Primary,
);
- const filteredNodes = Array.from(nodes.values()).filter(
- (n) => n.num !== hardware.myNodeNum,
- );
+ const [searchTerm, setSearchTerm] = useState("");
+ const filteredNodes = Array.from(nodes.values()).filter((node) => {
+ if (node.num === hardware.myNodeNum) return false;
+ const nodeName = node.user?.longName ?? `!${numberToHexUnpadded(node.num)}`;
+ return nodeName.toLowerCase().includes(searchTerm.toLowerCase());
+ });
const allChannels = Array.from(channels.values());
const filteredChannels = allChannels.filter(
(ch) => ch.role !== Protobuf.Channel.Channel_Role.DISABLED,
@@ -56,6 +59,15 @@ const MessagesPage = () => {
))}
+
+ setSearchTerm(e.target.value)}
+ className="w-full p-2 border border-gray-300 rounded bg-white text-black"
+ />
+
{filteredNodes.map((node) => (
{
const { nodes, hardware, setDialogOpen } = useDevice();
const { setNodeNumToBeRemoved } = useAppStore();
+ const [searchTerm, setSearchTerm] = useState("");
- const filteredNodes = Array.from(nodes.values()).filter(
- (n) => n.num !== hardware.myNodeNum,
- );
+ const filteredNodes = Array.from(nodes.values()).filter((node) => {
+ if (node.num === hardware.myNodeNum) return false;
+ const nodeName = node.user?.longName ?? `!${numberToHexUnpadded(node.num)}`;
+ return nodeName.toLowerCase().includes(searchTerm.toLowerCase());
+ });
return (
<>