fix: Remove relay labels, add signal bars #123

This commit is contained in:
Janez T
2026-03-16 22:01:41 +01:00
parent 9b14ff4e1a
commit cfd233d38e
5 changed files with 50 additions and 81 deletions

View File

@@ -402,6 +402,30 @@ class _HomeScreenState extends State<HomeScreen>
);
}
Widget _buildMiniSignalBars({
required int activeBars,
required Color color,
}) {
final inactive = Colors.grey.withValues(alpha: 0.3);
return Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
for (var i = 0; i < 5; i++) ...[
if (i > 0) const SizedBox(width: 1.5),
Container(
width: 2.5,
height: 4.0 + (i * 2),
decoration: BoxDecoration(
color: i < activeBars ? color : inactive,
borderRadius: BorderRadius.circular(1.5),
),
),
],
],
);
}
Widget _buildCompactActivityIndicator({
required bool rxActive,
required bool txActive,
@@ -1008,17 +1032,11 @@ class _HomeScreenState extends State<HomeScreen>
if (!isTcpConnected &&
deviceInfo.signalRssi != null) ...[
const SizedBox(width: 4),
SizedBox(
width: 28,
child: Text(
'${deviceInfo.signalRssi}',
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.w600,
color: signalColor,
),
maxLines: 1,
_buildMiniSignalBars(
activeBars: BatteryDisplayHelper.getSignalBars(
deviceInfo.signalRssi!,
),
color: signalColor,
),
],
if (deviceInfo.batteryPercent != null) ...[
@@ -1033,20 +1051,16 @@ class _HomeScreenState extends State<HomeScreen>
deviceInfo.batteryPercent!,
),
),
const SizedBox(width: 4),
SizedBox(
width: 30,
child: Text(
'${deviceInfo.batteryPercent!.round()}%',
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.w600,
color:
BatteryDisplayHelper.getBatteryColor(
deviceInfo.batteryPercent!,
),
),
const SizedBox(width: 2),
Text(
'${deviceInfo.batteryPercent!.round()}%',
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.w600,
color:
BatteryDisplayHelper.getBatteryColor(
deviceInfo.batteryPercent!,
),
),
),
],

View File

@@ -24,4 +24,14 @@ class BatteryDisplayHelper {
if (rssi > -70) return Colors.orange;
return Colors.red;
}
/// Number of active signal bars (0-5) for a BLE RSSI value.
static int getSignalBars(int rssi) {
if (rssi > -50) return 5;
if (rssi > -60) return 4;
if (rssi > -70) return 3;
if (rssi > -80) return 2;
if (rssi > -90) return 1;
return 0;
}
}

View File

@@ -265,7 +265,7 @@ class _ContactTraceSheetState extends State<ContactTraceSheet> {
),
title: Text(entry.value.label),
subtitle: Text(
'Relay${entry.value.keyLabel == null ? '' : '${entry.value.keyLabel}'}${entry.value.matchSummary == null ? '' : '${entry.value.matchSummary}'}${entry.value.resolved.cycleSummary == null ? '' : '${entry.value.resolved.cycleSummary}'}',
'Path node${entry.value.keyLabel == null ? '' : '${entry.value.keyLabel}'}${entry.value.matchSummary == null ? '' : '${entry.value.matchSummary}'}${entry.value.resolved.cycleSummary == null ? '' : '${entry.value.resolved.cycleSummary}'}',
),
trailing: entry.value.resolved.canCycle
? const Icon(Icons.sync_alt)

View File

@@ -905,12 +905,6 @@ class _MessageBubbleState extends State<MessageBubble> {
label: l10n.floodFallback,
value: l10n.yes,
),
if (routeMetadata?.relayName case final relayName?)
_detailRow(
sheetContext,
label: 'Relay',
value: relayName,
),
if (routeMetadata?.canonicalPath
case final routePath?)
_detailRow(

View File

@@ -149,8 +149,6 @@ class _MessageTraceSheetState extends State<MessageTraceSheet> {
.map((n) => LatLng(n.latitude, n.longitude))
.toList();
final hasMapPath = mapPoints.length >= 2;
final relayNodes = _relayNodes(trace);
return SizedBox(
height: MediaQuery.of(context).size.height * 0.75,
child: Column(
@@ -317,41 +315,13 @@ class _MessageTraceSheetState extends State<MessageTraceSheet> {
),
title: Text(entry.value.label),
subtitle: Text(
'Relay${entry.value.keyLabel == null ? '' : '${entry.value.keyLabel}'}${entry.value.matchSummary == null ? '' : '${entry.value.matchSummary}'}${entry.value.resolved.cycleSummary == null ? '' : '${entry.value.resolved.cycleSummary}'}',
'Path node${entry.value.keyLabel == null ? '' : '${entry.value.keyLabel}'}${entry.value.matchSummary == null ? '' : '${entry.value.matchSummary}'}${entry.value.resolved.cycleSummary == null ? '' : '${entry.value.resolved.cycleSummary}'}',
),
trailing: entry.value.resolved.canCycle
? const Icon(Icons.sync_alt)
: null,
),
),
const SizedBox(height: 12),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Text(
'Relays (${relayNodes.length})',
style: Theme.of(context).textTheme.titleMedium,
),
),
if (relayNodes.isEmpty)
const Padding(
padding: EdgeInsets.symmetric(
horizontal: 16,
vertical: 8,
),
child: Text(
'No relay nodes could be matched for this message.',
),
),
...relayNodes.map(
(node) => ListTile(
leading: const Icon(Icons.router),
title: Text(node.name),
subtitle: Text(
'${node.publicKey.substring(0, math.min(12, node.publicKey.length))}'
'${node.latitude.toStringAsFixed(5)}, ${node.longitude.toStringAsFixed(5)}',
),
),
),
],
),
),
@@ -363,25 +333,6 @@ class _MessageTraceSheetState extends State<MessageTraceSheet> {
);
}
List<MeshMapNode> _relayNodes(_TraceResult trace) {
final concrete = trace.matchedPathNodes
.map((entry) => entry.node)
.whereType<MeshMapNode>()
.toList();
if (concrete.isEmpty) return const [];
if (trace.mode == TraceMode.packetPath) {
if (widget.message == null) {
return concrete;
}
if (concrete.length <= 1) return const [];
return concrete.sublist(1);
}
if (concrete.length <= 2) return const [];
return concrete.sublist(1, concrete.length - 1);
}
List<_RouteDisplayEntry> _displayRouteEntries(_TraceResult trace) {
if (trace.mode == TraceMode.packetPath) {
return trace.matchedPathNodes.asMap().entries.map((entry) {