From fac062a100d224b45f6b724198638313f5d33a25 Mon Sep 17 00:00:00 2001 From: just_stuff_tm <133525672+just-stuff-tm@users.noreply.github.com> Date: Thu, 12 Feb 2026 15:46:28 -0500 Subject: [PATCH] Refine device info layout and add collapsible map legend (#164) --- lib/screens/map_screen.dart | 143 ++++++++++++++++++++----------- lib/screens/settings_screen.dart | 140 ++++++++++++++++++++---------- 2 files changed, 190 insertions(+), 93 deletions(-) diff --git a/lib/screens/map_screen.dart b/lib/screens/map_screen.dart index f522407..bc213f9 100644 --- a/lib/screens/map_screen.dart +++ b/lib/screens/map_screen.dart @@ -51,6 +51,7 @@ class _MapScreenState extends State { bool _isSelectingPoi = false; bool _hasInitializedMap = false; bool _removedMarkersLoaded = false; + bool _legendExpanded = false; @override void initState() { @@ -503,60 +504,102 @@ class _MapScreenState extends State { top: 16, right: 16, child: Card( - child: Padding( - padding: const EdgeInsets.all(12.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Text( - context.l10n.map_nodesCount(nodeCount), - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + InkWell( + borderRadius: BorderRadius.circular(12), + onTap: () { + setState(() { + _legendExpanded = !_legendExpanded; + }); + }, + child: Padding( + padding: const EdgeInsets.fromLTRB(12, 10, 12, 10), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + context.l10n.map_nodesCount(nodeCount), + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 14, + ), + ), + Text( + context.l10n.map_pinsCount(markerCount), + style: const TextStyle( + fontWeight: FontWeight.w600, + fontSize: 12, + ), + ), + ], + ), + const SizedBox(width: 8), + AnimatedRotation( + turns: _legendExpanded ? 0.5 : 0, + duration: const Duration(milliseconds: 200), + child: const Icon(Icons.expand_more, size: 20), + ), + ], ), ), - Text( - context.l10n.map_pinsCount(markerCount), - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 12, + ), + AnimatedCrossFade( + firstChild: const SizedBox.shrink(), + secondChild: Padding( + padding: const EdgeInsets.fromLTRB(12, 0, 12, 12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 6), + _buildLegendItem( + Icons.person, + context.l10n.map_chat, + Colors.blue, + ), + _buildLegendItem( + Icons.router, + context.l10n.map_repeater, + Colors.green, + ), + _buildLegendItem( + Icons.meeting_room, + context.l10n.map_room, + Colors.purple, + ), + _buildLegendItem( + Icons.sensors, + context.l10n.map_sensor, + Colors.orange, + ), + _buildLegendItem( + Icons.flag, + context.l10n.map_pinDm, + Colors.blue, + ), + _buildLegendItem( + Icons.flag, + context.l10n.map_pinPrivate, + Colors.purple, + ), + _buildLegendItem( + Icons.flag, + context.l10n.map_pinPublic, + Colors.orange, + ), + ], ), ), - const SizedBox(height: 8), - _buildLegendItem( - Icons.person, - context.l10n.map_chat, - Colors.blue, - ), - _buildLegendItem( - Icons.router, - context.l10n.map_repeater, - Colors.green, - ), - _buildLegendItem( - Icons.meeting_room, - context.l10n.map_room, - Colors.purple, - ), - _buildLegendItem( - Icons.sensors, - context.l10n.map_sensor, - Colors.orange, - ), - _buildLegendItem(Icons.flag, context.l10n.map_pinDm, Colors.blue), - _buildLegendItem( - Icons.flag, - context.l10n.map_pinPrivate, - Colors.purple, - ), - _buildLegendItem( - Icons.flag, - context.l10n.map_pinPublic, - Colors.orange, - ), - ], - ), + crossFadeState: _legendExpanded + ? CrossFadeState.showSecond + : CrossFadeState.showFirst, + duration: const Duration(milliseconds: 200), + ), + ], ), ), ); diff --git a/lib/screens/settings_screen.dart b/lib/screens/settings_screen.dart index 2212b8d..4943284 100644 --- a/lib/screens/settings_screen.dart +++ b/lib/screens/settings_screen.dart @@ -21,6 +21,7 @@ class SettingsScreen extends StatefulWidget { class _SettingsScreenState extends State { bool _showBatteryVoltage = false; + bool _deviceInfoExpanded = false; String _appVersion = ''; @override @@ -74,43 +75,84 @@ class _SettingsScreenState extends State { MeshCoreConnector connector, ) { final l10n = context.l10n; + return Card( - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - l10n.settings_deviceInfo, - style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), - ), - const SizedBox(height: 16), - _buildInfoRow(l10n.settings_infoName, connector.deviceDisplayName), - _buildInfoRow(l10n.settings_infoId, connector.deviceIdLabel), - _buildInfoRow( - l10n.settings_infoStatus, - connector.isConnected - ? l10n.common_connected - : l10n.common_disconnected, - ), - _buildBatteryInfoRow(context, connector), - if (connector.selfName != null) - _buildInfoRow(l10n.settings_nodeName, connector.selfName!), - if (connector.selfPublicKey != null) - _buildInfoRow( - l10n.settings_infoPublicKey, - '${pubKeyToHex(connector.selfPublicKey!).substring(0, 16)}...', + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + InkWell( + borderRadius: BorderRadius.circular(12), + onTap: () { + setState(() { + _deviceInfoExpanded = !_deviceInfoExpanded; + }); + }, + child: Padding( + padding: const EdgeInsets.fromLTRB(16, 16, 16, 16), + child: Row( + children: [ + Expanded( + child: Text( + l10n.settings_deviceInfo, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + ), + AnimatedRotation( + turns: _deviceInfoExpanded ? 0.5 : 0, + duration: const Duration(milliseconds: 200), + child: const Icon(Icons.expand_more), + ), + ], ), - _buildInfoRow( - l10n.settings_infoContactsCount, - '${connector.contacts.length}', ), - _buildInfoRow( - l10n.settings_infoChannelCount, - '${connector.channels.length}', + ), + + AnimatedCrossFade( + firstChild: const SizedBox.shrink(), + secondChild: Padding( + padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildInfoRow( + l10n.settings_infoName, + connector.deviceDisplayName, + ), + _buildInfoRow(l10n.settings_infoId, connector.deviceIdLabel), + _buildInfoRow( + l10n.settings_infoStatus, + connector.isConnected + ? l10n.common_connected + : l10n.common_disconnected, + ), + _buildBatteryInfoRow(context, connector), + if (connector.selfName != null) + _buildInfoRow(l10n.settings_nodeName, connector.selfName!), + if (connector.selfPublicKey != null) + _buildInfoRow( + l10n.settings_infoPublicKey, + '${pubKeyToHex(connector.selfPublicKey!).substring(0, 16)}...', + ), + _buildInfoRow( + l10n.settings_infoContactsCount, + '${connector.contacts.length}', + ), + _buildInfoRow( + l10n.settings_infoChannelCount, + '${connector.channels.length}', + ), + ], + ), ), - ], - ), + crossFadeState: _deviceInfoExpanded + ? CrossFadeState.showSecond + : CrossFadeState.showFirst, + duration: const Duration(milliseconds: 200), + ), + ], ), ); } @@ -355,22 +397,33 @@ class _SettingsScreenState extends State { Color? valueColor, VoidCallback? onTap, }) { + final theme = Theme.of(context); + final row = Padding( - padding: const EdgeInsets.symmetric(vertical: 4), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + padding: const EdgeInsets.symmetric(vertical: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ if (leading != null) ...[leading, const SizedBox(width: 8)], - Text(label, style: TextStyle(color: Colors.grey[600])), + Expanded( + child: Text( + label, + style: theme.textTheme.bodySmall?.copyWith( + color: theme.colorScheme.onSurfaceVariant, + fontWeight: FontWeight.w500, + ), + ), + ), ], ), - Flexible( - child: Text( - value, - style: TextStyle(fontWeight: FontWeight.w500, color: valueColor), - overflow: TextOverflow.ellipsis, + const SizedBox(height: 4), + Text( + value, + style: theme.textTheme.bodyLarge?.copyWith( + color: valueColor, + fontWeight: FontWeight.w500, ), ), ], @@ -379,11 +432,12 @@ class _SettingsScreenState extends State { if (onTap != null) { return InkWell( + borderRadius: BorderRadius.circular(6), onTap: onTap, - borderRadius: BorderRadius.circular(4), child: row, ); } + return row; }