feat: Enhance home screen status bar with connection indicators and improved layout

This commit is contained in:
Janez T
2025-10-16 14:54:25 +02:00
parent 4c8e0e5d61
commit 3a8eac2ec2

View File

@@ -579,140 +579,19 @@ class _HomeScreenState extends State<HomeScreen>
'🎨 [UI] Building status bar - isConnected: $isConnected, state: ${deviceInfo.connectionState}', '🎨 [UI] Building status bar - isConnected: $isConnected, state: ${deviceInfo.connectionState}',
); );
if (!isConnected) {
// Disconnected state: show connect button
return Row( return Row(
children: [ children: [
// LEFT SECTION: Name + BT/Battery status + Settings cog const Expanded(
Expanded(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
// Name and status group
Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
isConnected && deviceInfo.selfName != null
? deviceInfo.selfName!
: 'MeshCore',
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
overflow: TextOverflow.ellipsis,
),
if (isConnected)
Row(
mainAxisSize: MainAxisSize.min,
children: [
// BLE connection strength indicator with RSSI
Icon(
Icons.bluetooth_connected,
color: deviceInfo.signalRssi != null
? _getSignalColor(deviceInfo.signalRssi!)
: Colors.grey,
size: 14,
),
const SizedBox(width: 3),
if (deviceInfo.signalRssi != null)
Flexible(
child: Text( child: Text(
'${deviceInfo.signalRssi}', 'MeshCore',
style: TextStyle( style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
fontSize: 12,
color: _getSignalColor(deviceInfo.signalRssi!),
fontWeight: FontWeight.w500,
),
overflow: TextOverflow.ellipsis,
), ),
), ),
const SizedBox(width: 8),
// Battery indicator
if (deviceInfo.batteryPercent != null) ...[
Icon(
_getBatteryIcon(deviceInfo.batteryPercent!),
color: _getBatteryColor(deviceInfo.batteryPercent!),
size: 14,
),
const SizedBox(width: 3),
Flexible(
child: Text(
'${deviceInfo.batteryPercent!.round()}%',
style: TextStyle(
fontSize: 12,
color: _getBatteryColor(
deviceInfo.batteryPercent!,
),
),
overflow: TextOverflow.ellipsis,
),
),
],
],
)
else if (provider.isReconnecting)
Text(
'Reconnecting...',
style: TextStyle(fontSize: 12, color: Colors.orange[600]),
overflow: TextOverflow.ellipsis,
),
],
),
),
// Settings cog - part of left group
if (isConnected) ...[
const SizedBox(width: 8),
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const DeviceConfigScreen(),
),
);
},
onLongPress: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
PacketLogScreen(bleService: provider.bleService),
),
);
},
child: Container(
width: 36,
height: 36,
alignment: Alignment.center,
child: const Icon(Icons.settings, size: 20),
),
),
],
],
),
),
// CENTER SECTION: Broadcast button (when connected)
if (isConnected) ...[
FilledButton(
onPressed: () => _advertiseDevice(context),
style: FilledButton.styleFrom(
backgroundColor: Colors.blue.shade700,
foregroundColor: Colors.white,
padding: const EdgeInsets.all(10),
minimumSize: const Size(40, 40),
shape: const CircleBorder(),
),
child: const Icon(Icons.campaign, size: 20),
),
],
// RIGHT SECTION: Connect button OR RX/TX indicators
if (!isConnected)
Row(
mainAxisSize: MainAxisSize.min,
children: [
ElevatedButton.icon( ElevatedButton.icon(
onPressed: provider.isReconnecting onPressed: provider.isReconnecting
? null // Disable button during reconnection ? null
: () => _showConnectionDialog(context), : () => _showConnectionDialog(context),
icon: provider.isReconnecting icon: provider.isReconnecting
? const SizedBox( ? const SizedBox(
@@ -740,7 +619,6 @@ class _HomeScreenState extends State<HomeScreen>
), ),
), ),
), ),
// Cancel button during reconnection
if (provider.isReconnecting) ...[ if (provider.isReconnecting) ...[
const SizedBox(width: 8), const SizedBox(width: 8),
IconButton( IconButton(
@@ -755,8 +633,115 @@ class _HomeScreenState extends State<HomeScreen>
), ),
], ],
], ],
) );
else if (_showRxTxIndicators) }
// Connected state: LEFT | CENTER | RIGHT layout
return Row(
children: [
// LEFT: Name + BT/Battery + Cog
Expanded(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
deviceInfo.selfName ?? 'MeshCore',
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
overflow: TextOverflow.ellipsis,
),
Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.bluetooth_connected,
color: deviceInfo.signalRssi != null
? _getSignalColor(deviceInfo.signalRssi!)
: Colors.grey,
size: 13,
),
if (deviceInfo.signalRssi != null) ...[
const SizedBox(width: 3),
Text(
'${deviceInfo.signalRssi}',
style: TextStyle(
fontSize: 11,
color: _getSignalColor(deviceInfo.signalRssi!),
),
),
],
if (deviceInfo.batteryPercent != null) ...[
const SizedBox(width: 8),
Icon(
_getBatteryIcon(deviceInfo.batteryPercent!),
color: _getBatteryColor(deviceInfo.batteryPercent!),
size: 13,
),
const SizedBox(width: 3),
Text(
'${deviceInfo.batteryPercent!.round()}%',
style: TextStyle(
fontSize: 11,
color: _getBatteryColor(deviceInfo.batteryPercent!),
),
),
],
],
),
],
),
),
const SizedBox(width: 8),
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const DeviceConfigScreen(),
),
);
},
onLongPress: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
PacketLogScreen(bleService: provider.bleService),
),
);
},
child: Container(
width: 32,
height: 32,
alignment: Alignment.center,
child: const Icon(Icons.settings, size: 18),
),
),
],
),
),
// CENTER: Broadcast button
const SizedBox(width: 8),
FilledButton(
onPressed: () => _advertiseDevice(context),
style: FilledButton.styleFrom(
backgroundColor: Colors.blue.shade700,
foregroundColor: Colors.white,
padding: const EdgeInsets.all(10),
minimumSize: const Size(40, 40),
shape: const CircleBorder(),
),
child: const Icon(Icons.campaign, size: 20),
),
const SizedBox(width: 8),
// RIGHT: RX/TX indicators
if (_showRxTxIndicators)
GestureDetector( GestureDetector(
onLongPress: () { onLongPress: () {
Navigator.push( Navigator.push(
@@ -769,15 +754,14 @@ class _HomeScreenState extends State<HomeScreen>
}, },
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
// RX indicator
Row( Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Container( Container(
width: 8, width: 7,
height: 8, height: 7,
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
color: provider.rxActivity color: provider.rxActivity
@@ -785,24 +769,23 @@ class _HomeScreenState extends State<HomeScreen>
: Colors.grey.withOpacity(0.3), : Colors.grey.withOpacity(0.3),
), ),
), ),
const SizedBox(width: 4), const SizedBox(width: 3),
Text( Text(
'RX:${provider.rxPacketCount}', 'RX:${provider.rxPacketCount}',
style: const TextStyle( style: const TextStyle(
fontSize: 11, fontSize: 10,
color: Colors.grey, color: Colors.grey,
), ),
), ),
], ],
), ),
const SizedBox(height: 4), const SizedBox(height: 3),
// TX indicator
Row( Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Container( Container(
width: 8, width: 7,
height: 8, height: 7,
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
color: provider.txActivity color: provider.txActivity
@@ -810,11 +793,11 @@ class _HomeScreenState extends State<HomeScreen>
: Colors.grey.withOpacity(0.3), : Colors.grey.withOpacity(0.3),
), ),
), ),
const SizedBox(width: 4), const SizedBox(width: 3),
Text( Text(
'TX:${provider.txPacketCount}', 'TX:${provider.txPacketCount}',
style: const TextStyle( style: const TextStyle(
fontSize: 11, fontSize: 10,
color: Colors.grey, color: Colors.grey,
), ),
), ),
@@ -822,7 +805,9 @@ class _HomeScreenState extends State<HomeScreen>
), ),
], ],
), ),
), )
else
const SizedBox(width: 52), // Placeholder to maintain layout balance
], ],
); );
}, },