feat(channels): apply modem-preset display name to per-source channels view#3093
Conversation
…s view The Source Channels tab in the UI was still rendering empty-name slot 0 as "Primary" — a synthetic localization fallback — even though the unified channels picker now shows the firmware-derived label (`MediumFast`, `LongFast`, etc.) for the same channel. Apply the same logic to per-source channel responses so the two views agree, and so the displayed name matches what MQTT gateways actually publish on the wire. - `transformChannel` (`src/server/utils/channelView.ts`) now emits a new `displayName` field alongside the raw `name` column. Computed via a new `computeChannelDisplayName` helper: trimmed `name` if set, otherwise the modem preset's pascal-case label for slot 0 (when a `presetName` option is passed), otherwise the legacy `"Primary"` fallback. The raw `name` column is unchanged so channel-config edits still round-trip to the firmware untouched. New `TransformChannelOptions.presetName` carries the hint. - `/api/sources/:id/channels` (`src/server/routes/sourceRoutes.ts`) and `/api/channels?sourceId=` (`src/server/server.ts`) both look up the source's persisted modem preset (`lora.preset.<sourceId>` setting, written by `meshtasticManager` on each LoRa config response) and pass the firmware-derived name into `transformChannel`. Cross-source listings with no `sourceId` query param fall back to `"Primary"` as before. - `Channel` type (`src/types/device.ts`) gains optional `displayName`, documented as the field the frontend should prefer for rendering. - `ChannelsTab.getChannelName` prefers `displayName` when present so the Source Channels tab matches the unified picker. Tests: 4 new channelView.test cases covering preset-derived display name, empty-slot-0 fallback to "Primary", non-slot-0 empty handling, and the existing whitelist updated to include `displayName`. Full suite green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Claude finished @Yeraze's task —— View job 🔍 Code Review: Channel Preset Display Name AlignmentI've completed a thorough review of PR #3093. This is a well-implemented feature that aligns channel display names between the unified channels picker and per-source views. ✅ Strengths1. Architecture & Design
2. Security & Permissions
3. Code Quality
🎯 Implementation DetailsCore Logic (channelView.ts:74-82) export function computeChannelDisplayName(
channel: { id: number; name?: string | null },
presetName?: string | null,
): string {
const trimmed = (channel.name ?? '').trim();
if (trimmed) return trimmed;
if (channel.id === 0) return presetName ?? PRIMARY_CHANNEL_NAME;
return trimmed;
}
Frontend Integration (ChannelsTab.tsx:333-341) if (channel.displayName && channel.displayName.trim()) {
return channel.displayName;
}
if (!channel.name?.trim() && channelNum === 0) {
return t('channels.primary');
}
return channel.name;
📋 Test CoverageComprehensive test cases added:
🔍 Potential Areas for Improvement1. Minor: Error Handling Enhancement // Current (sourceRoutes.ts:772)
} catch (err) {
logger.debug(`Failed to load preset for source ${source.id}:`, err);
}
// Suggestion: Consider differentiating error types
} catch (err) {
if (err instanceof DatabaseError) {
logger.warn(`Database error loading preset for ${source.id}:`, err);
} else {
logger.debug(`Failed to load preset for ${source.id}:`, err);
}
}2. Minor: Cache Optimization Opportunity 3. Documentation Enhancement 🚀 Performance & Scalability
🔒 Security Assessment
✅ Compliance with Repo Standards
🎉 Final AssessmentThis is a high-quality implementation that:
The code is production-ready and demonstrates strong understanding of the codebase architecture. Recommendation: ✅ Approve |
Patch release covering the MQTT-ingest rework (#3089) and follow-on UX fixes (#3093 channel display-name, #3091 Channel Database move to Global) plus the usual dependency bumps and minor fixes. Version bumps across all five canonical files: package.json, package-lock.json (regenerated), helm/meshmonitor/Chart.yaml, desktop/package.json, desktop/src-tauri/tauri.conf.json. CHANGELOG: organized under [4.6.2] with the user-visible MQTT/channel items called out as the headline changes. CLAUDE.md: - Migration count 62+ → 63+ (latest: 063_drop_source_id_from_channel_database) - "Every row carries a sourceId" rule gains an exception note for channel_database — it's intentionally global (decryption service tries every enabled row regardless of source) and migration 063 dropped the dead sourceId column. Blog post + news.json: "MeshMonitor v4.6.2 — MQTT in the Unified views & cleaner channel names" — three things users will notice immediately (slot-0 channel renamed from "Primary" to the modem-preset label, Channel Database moved to Global Settings, MQTT sources now participate in Unified Messages and Unified Telemetry) plus action items after upgrade. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Follow-up to #3089. The unified channels picker now renders empty-name slot 0 with the firmware-derived label (
MediumFast,LongFast, etc.) drawn from the device's modem preset, but the per-source Source Channels tab was still showing the synthetic"Primary"fallback. This PR applies the same logic to the per-source channel responses so the two views agree and match what MQTT gateways actually publish on the wire.Changes
transformChannel(src/server/utils/channelView.ts) now emits a newdisplayNamefield alongside the rawname. Computed by a newcomputeChannelDisplayNamehelper:nameif setpresetNameoption is passed, otherwise the legacy"Primary"fallbackThe raw
namecolumn is intentionally unchanged so channel-config edits still round-trip to firmware untouched./api/sources/:id/channelsand/api/channels?sourceId=...now look up the source's persisted modem preset (lora.preset.<sourceId>setting, written bymeshtasticManageron each LoRa config response) and pass the firmware-derived name intotransformChannel. Cross-source listings without asourceIdquery param fall back to"Primary"as before.Channeltype (src/types/device.ts) gains optionaldisplayName, documented as the field the frontend should prefer.ChannelsTab.getChannelNameprefersdisplayNamewhen present so the Source Channels tab matches the unified picker.Test plan
npx tsc --noEmit -p tsconfig.json— cleannpx vitest run— full suite passes (4 new channelView cases for preset-derived display name, empty-slot-0 fallback, non-slot-0 handling, and the whitelist updated to includedisplayName)/api/sources/<sandbox-id>/channelsreturns{ id: 0, name: "", displayName: "MediumFast", role: 1, roleName: "Primary" }(preset persisted fromMEDIUM_FAST= 4)/api/channels?sourceId=<sandbox-id>returns the samedisplayName🤖 Generated with Claude Code