From fed63b23446ad0619d732d1ab2728ff6e04a1c6e Mon Sep 17 00:00:00 2001 From: malice Date: Thu, 9 Jul 2026 10:55:29 -0600 Subject: [PATCH] fix(channels): dedupe Meshtastic channel list, un-bury MeshCore channels card (#105) The Meshtastic connection page listed channels twice (the pre-existing Observe-Channels selector plus a redundant read-only Index/Name/Role table); remove the redundant table and its now-unused getChannels() / MeshtasticChannel API helpers. On the MeshCore companion page, move the Channels (name/hash/key) card up to sit right after the Status card, above the Advertising settings, so it is no longer buried at the bottom. No behavior change; layout/UX only. Co-authored-by: Matt Johnson Co-authored-by: Claude Opus 4.8 (1M context) --- work/dashboard-frontend/src/lib/api.ts | 12 --- .../src/pages/MeshCoreCompanion.tsx | 79 ++++++++++--------- .../src/pages/MeshtasticConnection.tsx | 42 +--------- 3 files changed, 41 insertions(+), 92 deletions(-) diff --git a/work/dashboard-frontend/src/lib/api.ts b/work/dashboard-frontend/src/lib/api.ts index cd55c6d..510d919 100644 --- a/work/dashboard-frontend/src/lib/api.ts +++ b/work/dashboard-frontend/src/lib/api.ts @@ -606,18 +606,6 @@ export async function getMeshcoreChannelsDetail(): Promise('/api/meshcore/channels/detail') } -// Meshtastic radio channels (routes by channel index). -export interface MeshtasticChannel { - index: number - name: string - role: string - enabled: boolean -} - -export async function getChannels(): Promise { - return fetchJson('/api/channels') -} - export interface MeshcoreContact { name: string | null pubkey: string diff --git a/work/dashboard-frontend/src/pages/MeshCoreCompanion.tsx b/work/dashboard-frontend/src/pages/MeshCoreCompanion.tsx index f404457..38c19f9 100644 --- a/work/dashboard-frontend/src/pages/MeshCoreCompanion.tsx +++ b/work/dashboard-frontend/src/pages/MeshCoreCompanion.tsx @@ -240,45 +240,6 @@ export default function MeshCoreCompanion() { )} - {/* Advertising settings */} -
-
-

Advertising

-
-
-
- -
- - -
-

- AIDA sends a flood advertisement at this interval so it stays discoverable. - Stored in connection.meshcore_advert_interval_seconds. -

-
-
-
- {/* Channel list — Name · Hash · Key (read-only) */}
@@ -329,6 +290,46 @@ export default function MeshCoreCompanion() {
No channels
)}
+ + {/* Advertising settings */} +
+
+

Advertising

+
+
+
+ +
+ + +
+

+ AIDA sends a flood advertisement at this interval so it stays discoverable. + Stored in connection.meshcore_advert_interval_seconds. +

+
+
+
+ )}
diff --git a/work/dashboard-frontend/src/pages/MeshtasticConnection.tsx b/work/dashboard-frontend/src/pages/MeshtasticConnection.tsx index 303eae3..b969661 100644 --- a/work/dashboard-frontend/src/pages/MeshtasticConnection.tsx +++ b/work/dashboard-frontend/src/pages/MeshtasticConnection.tsx @@ -4,7 +4,7 @@ import { ConnectionSection, TextInput, NumberInput, Toggle, type ConnectionConfi import ChannelPicker from '@/components/ChannelPicker' import NodePicker from '@/components/NodePicker' import { notifyRestartRequired } from '@/components/RestartBanner' -import { fetchConfig as apiFetchConfig, updateConfig as apiUpdateConfig, sendTestMessage, getChannels, type MeshtasticChannel } from '@/lib/api' +import { fetchConfig as apiFetchConfig, updateConfig as apiUpdateConfig, sendTestMessage } from '@/lib/api' import { useDirty } from '@/context/DirtyContext' // Only the fields the "Bot behavior" section edits are typed explicitly; the @@ -37,9 +37,6 @@ export default function MeshtasticConnection() { const [success, setSuccess] = useState(null) const [hasChanges, setHasChanges] = useState(false) - // Read-only channel listing (index ↔ name ↔ role), fetched from the radio. - const [channels, setChannels] = useState([]) - // Test send state const [testChannel, setTestChannel] = useState(0) const [testText, setTestText] = useState('') @@ -89,9 +86,6 @@ export default function MeshtasticConnection() { useEffect(() => { document.title = 'Meshtastic Connection - MeshAI' fetchConfig() - getChannels() - .then(setChannels) - .catch(() => setChannels([])) }, [fetchConfig]) useEffect(() => { @@ -296,40 +290,6 @@ export default function MeshtasticConnection() { )} - {/* Channels card — read-only Index · Name · Role */} -
-
-

Channels

-

- Channels configured on the radio. Meshtastic routes by channel index. Read-only. -

-
- {channels.length > 0 ? ( -
- - - - - - - - - - {channels.map((ch) => ( - - - - - - ))} - -
IndexNameRole
{ch.index}{ch.name}{ch.role}
-
- ) : ( -
Node offline — channels unavailable
- )} -
- {/* Send test message card */}
Send Test Message