diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart index 14c5135..7932ba3 100644 --- a/lib/screens/home_screen.dart +++ b/lib/screens/home_screen.dart @@ -402,6 +402,30 @@ class _HomeScreenState extends State ); } + 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 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 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!, + ), ), ), ], diff --git a/lib/utils/battery_display_helper.dart b/lib/utils/battery_display_helper.dart index c222c0c..0e7e2b4 100644 --- a/lib/utils/battery_display_helper.dart +++ b/lib/utils/battery_display_helper.dart @@ -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; + } } diff --git a/lib/widgets/contacts/contact_trace_sheet.dart b/lib/widgets/contacts/contact_trace_sheet.dart index 543a49b..4dcaa06 100644 --- a/lib/widgets/contacts/contact_trace_sheet.dart +++ b/lib/widgets/contacts/contact_trace_sheet.dart @@ -265,7 +265,7 @@ class _ContactTraceSheetState extends State { ), 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) diff --git a/lib/widgets/messages/message_bubble.dart b/lib/widgets/messages/message_bubble.dart index 635837f..fbe2d0f 100644 --- a/lib/widgets/messages/message_bubble.dart +++ b/lib/widgets/messages/message_bubble.dart @@ -905,12 +905,6 @@ class _MessageBubbleState extends State { 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( diff --git a/lib/widgets/messages/message_trace_sheet.dart b/lib/widgets/messages/message_trace_sheet.dart index 5638353..8fa48a3 100644 --- a/lib/widgets/messages/message_trace_sheet.dart +++ b/lib/widgets/messages/message_trace_sheet.dart @@ -149,8 +149,6 @@ class _MessageTraceSheetState extends State { .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 { ), 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 { ); } - List _relayNodes(_TraceResult trace) { - final concrete = trace.matchedPathNodes - .map((entry) => entry.node) - .whereType() - .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) {