Skip to content
This repository was archived by the owner on May 29, 2026. It is now read-only.

Commit 4382393

Browse files
staticoclaude
andcommitted
Fix UI bugs and update dependencies (ink 6.8.0, protobufs 2.7.18)
Dependencies: - ink 6.6.0 β†’ 6.8.0 (fixes keypress drops, MaxListenersExceeded, nested Text wrapping, synchronized output for less flickering) - @meshtastic/protobufs 2.7.8 β†’ 2.7.18 - @types/bun 1.3.4 β†’ 1.3.10 - @types/react 19.2.10 β†’ 19.2.14 Bug fixes: - ChatPanel: Fix crash when replyTo.text is null/undefined - ChatPanel: Fix text wrapping breakPoint check (<=0 should be <1) so a space at position 0 doesn't skip to textWidth - App: Fix showNotification setTimeout memory leak - previous timeout wasn't cleared when new notification arrived, stacking timeouts - App: Fix channel role cycling hardcoded to % 3, now dynamically reads enum size from Channel.Channel_Role - ResponseModal: Fix duplicate React keys in traceroute route.map when same node appears multiple times in route - LogPanel: Fix React.memo ignoring nodeStore prop changes - MeshViewPanel: Standardize coordinate precision to toFixed(6) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> (cherry picked from commit 3d19a55)
1 parent 1f4d658 commit 4382393

7 files changed

Lines changed: 50 additions & 29 deletions

File tree

β€Žbun.lockβ€Ž

Lines changed: 29 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

β€Žpackage.jsonβ€Ž

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77
"build": "bun build src/index.ts --outdir=dist --target=bun"
88
},
99
"dependencies": {
10-
"@meshtastic/protobufs": "^2.7.8",
11-
"ink": "^6.6.0",
10+
"@meshtastic/protobufs": "^2.7.18",
11+
"ink": "^6.8.0",
1212
"react": "^19.2.4",
1313
"serialport": "^13.0.0"
1414
},
1515
"devDependencies": {
16-
"@types/bun": "latest",
17-
"@types/react": "^19.2.10",
16+
"@types/bun": "^1.3.10",
17+
"@types/react": "^19.2.14",
1818
"react-devtools-core": "^7.0.1",
1919
"typescript": "^5.9.3"
2020
}

β€Žsrc/ui/App.tsxβ€Ž

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,9 +1101,16 @@ export function App({ address, packetStore, nodeStore, skipConfig = false, skipN
11011101
}
11021102
}, [transport]);
11031103

1104+
const notificationTimeoutRef = useRef<NodeJS.Timeout | null>(null);
11041105
const showNotification = useCallback((msg: string, color?: string) => {
1106+
if (notificationTimeoutRef.current) {
1107+
clearTimeout(notificationTimeoutRef.current);
1108+
}
11051109
setNotification({ message: msg, color });
1106-
setTimeout(() => setNotification(null), 2000);
1110+
notificationTimeoutRef.current = setTimeout(() => {
1111+
setNotification(null);
1112+
notificationTimeoutRef.current = null;
1113+
}, 2000);
11071114
}, []);
11081115

11091116
const sendMessage = useCallback(async (text: string, replyId?: number) => {
@@ -2937,7 +2944,8 @@ export function App({ address, packetStore, nodeStore, skipConfig = false, skipN
29372944
if (field.category === "channel") {
29382945
const match = field.key.match(/^channel(\d+)_role$/);
29392946
if (match) {
2940-
const nextRole = ((selectedRow.value as number) + 1) % 3;
2947+
const roleCount = Object.keys(Channel.Channel_Role).filter(k => isNaN(Number(k))).length;
2948+
const nextRole = ((selectedRow.value as number) + 1) % roleCount;
29412949
saveChannel(parseInt(match[1], 10), { role: nextRole });
29422950
}
29432951
} else if (field.enumMap && (field.category === "radio" || field.category === "module")) {

β€Žsrc/ui/components/ChatPanel.tsxβ€Ž

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ function ChatPanelComponent({
139139
let remaining = line;
140140
while (remaining.length > textWidth) {
141141
let breakPoint = remaining.lastIndexOf(" ", textWidth);
142-
if (breakPoint <= 0) breakPoint = textWidth;
142+
if (breakPoint < 1) breakPoint = textWidth;
143143
lineCount++;
144144
remaining = remaining.slice(breakPoint).trimStart();
145145
}
@@ -337,7 +337,7 @@ function ChatPanelComponent({
337337
<Box paddingX={1}>
338338
<Text color={theme.fg.muted}>replying to </Text>
339339
<Text color={theme.fg.accent}>{nodeStore.getNodeName(replyTo.fromNode)}</Text>
340-
<Text color={theme.fg.muted}>: "{replyTo.text.length > 30 ? replyTo.text.slice(0, 30) + "..." : replyTo.text}"</Text>
340+
<Text color={theme.fg.muted}>: "{(replyTo.text || "").length > 30 ? (replyTo.text || "").slice(0, 30) + "..." : replyTo.text || ""}"</Text>
341341
</Box>
342342
)}
343343

β€Žsrc/ui/components/LogPanel.tsxβ€Ž

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ export const LogPanel = React.memo(LogPanelComponent, (prevProps, nextProps) =>
7171
return (
7272
prevProps.responses.length === nextProps.responses.length &&
7373
prevProps.selectedIndex === nextProps.selectedIndex &&
74-
prevProps.height === nextProps.height
74+
prevProps.height === nextProps.height &&
75+
prevProps.nodeStore === nextProps.nodeStore
7576
);
7677
});
7778

β€Žsrc/ui/components/MeshViewPanel.tsxβ€Ž

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@ function renderPayloadSummary(payload: string, portnum: number, useFahrenheit: b
9393

9494
// Position data - convert latitudeI/longitudeI to real coordinates
9595
if (parsed.latitudeI !== undefined && parsed.longitudeI !== undefined) {
96-
const lat = (parsed.latitudeI / 1e7).toFixed(5);
97-
const lon = (parsed.longitudeI / 1e7).toFixed(5);
96+
const lat = (parsed.latitudeI / 1e7).toFixed(6);
97+
const lon = (parsed.longitudeI / 1e7).toFixed(6);
9898
return (
9999
<>
100100
<Text color={theme.data.coords}> {lat}</Text>

β€Žsrc/ui/components/ResponseModal.tsxβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ function TracerouteDetails({ data, nodeStore }: { data: unknown; nodeStore: Node
122122
const name = nodeStore.getNodeName(nodeNum);
123123
const snr = route.snrTowards?.[i];
124124
return (
125-
<Box key={nodeNum}>
125+
<Box key={`${nodeNum}-${i}`}>
126126
<Text color={theme.fg.muted}> {i + 1}. </Text>
127127
<Text color={theme.fg.accent}>{name}</Text>
128128
<Text color={theme.fg.muted}> ({formatNodeId(nodeNum)})</Text>

0 commit comments

Comments
Β (0)