fix: improve button layout and event log readability

This commit is contained in:
fiatcode 2026-04-30 15:56:16 +07:00
parent 02040081ce
commit c781fc5079
No known key found for this signature in database
2 changed files with 165 additions and 141 deletions

View file

@ -144,16 +144,19 @@ class _MainScreenState extends State<MainScreen> with TickerProviderStateMixin {
children: [ children: [
_buildHeader(), _buildHeader(),
Expanded( Expanded(
child: Padding( child: SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 20), padding: const EdgeInsets.symmetric(horizontal: 20),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
const SizedBox(height: 16), const SizedBox(height: 16),
_buildStatusCard(), _buildStatusCard(),
const SizedBox(height: 16), const SizedBox(height: 16),
_buildTrackingToggle(), _buildTrackingToggle(),
const Spacer(), const SizedBox(height: 12),
_buildActionButtons(), _buildSendButton(),
const SizedBox(height: 12),
_buildNavButtons(),
const SizedBox(height: 20), const SizedBox(height: 20),
], ],
), ),
@ -367,74 +370,65 @@ class _MainScreenState extends State<MainScreen> with TickerProviderStateMixin {
); );
} }
Widget _buildActionButtons() { Widget _buildSendButton() {
return Column( if (!_isTracking) return const SizedBox.shrink();
children: [ return SizedBox(
if (_isTracking) height: 44,
Padding( child: OutlinedButton.icon(
padding: const EdgeInsets.only(bottom: 12), onPressed: () async {
child: SizedBox( final success = await LocationBridge.reportLocation();
width: double.infinity, if (mounted) {
height: 44, ScaffoldMessenger.of(context).showSnackBar(
child: OutlinedButton.icon( SnackBar(
onPressed: () async { content: Text(
final success = await LocationBridge.reportLocation(); success ? 'Location sent to server' : 'Failed — check logs',
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
success
? 'Location sent to server'
: 'Failed — check logs',
),
backgroundColor: const Color(0xFF1a1a1a),
),
);
}
},
style: OutlinedButton.styleFrom(
foregroundColor: const Color(0xFF00bcd4),
side: const BorderSide(color: Color(0xFF00bcd4), width: 1),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4),
),
),
icon: const Icon(Icons.arrow_upward, size: 16),
label: const Text(
'SEND LOCATION',
style: TextStyle(
fontFamily: 'monospace',
letterSpacing: 1,
fontSize: 13,
),
), ),
backgroundColor: const Color(0xFF1a1a1a),
), ),
);
}
},
style: OutlinedButton.styleFrom(
foregroundColor: const Color(0xFF00bcd4),
side: const BorderSide(color: Color(0xFF00bcd4), width: 1),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(4)),
),
icon: const Icon(Icons.arrow_upward, size: 16),
label: const Text(
'SEND LOCATION',
style: TextStyle(
fontFamily: 'monospace',
letterSpacing: 1,
fontSize: 13,
),
),
),
);
}
Widget _buildNavButtons() {
return Row(
children: [
Expanded(
child: _buildNavButton(
icon: Icons.tune,
label: 'SETTINGS',
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => const SettingsScreen()),
), ),
), ),
Row( ),
children: [ const SizedBox(width: 12),
Expanded( Expanded(
child: _buildNavButton( child: _buildNavButton(
icon: Icons.tune, icon: Icons.terminal,
label: 'SETTINGS', label: 'LOGS',
onTap: () => Navigator.push( onTap: () => Navigator.push(
context, context,
MaterialPageRoute(builder: (_) => const SettingsScreen()), MaterialPageRoute(builder: (_) => const StatusScreen()),
),
),
), ),
const SizedBox(width: 12), ),
Expanded(
child: _buildNavButton(
icon: Icons.terminal,
label: 'LOGS',
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => const StatusScreen()),
),
),
),
],
), ),
], ],
); );

View file

@ -102,29 +102,13 @@ class _StatusScreenState extends State<StatusScreen> {
appBar: AppBar( appBar: AppBar(
backgroundColor: const Color(0xFF161616), backgroundColor: const Color(0xFF161616),
elevation: 0, elevation: 0,
title: Row( leading: IconButton(
children: [ icon: const Icon(
const Icon(Icons.terminal, color: Color(0xFF00bcd4), size: 18), Icons.arrow_back,
const SizedBox(width: 10), color: Color(0xFF9e9e9e),
const Text( size: 20,
'EVENT LOG', ),
style: TextStyle( onPressed: () => Navigator.pop(context),
fontFamily: 'monospace',
fontSize: 14,
fontWeight: FontWeight.w700,
letterSpacing: 2,
color: Color(0xFFe0e0e0),
),
),
const Spacer(),
_buildFilterChip('ALL', null),
const SizedBox(width: 6),
_buildFilterChip('LOG', 'LOCATION'),
const SizedBox(width: 6),
_buildFilterChip('SYNC', 'SYNC'),
const SizedBox(width: 6),
_buildFilterChip('ERR', 'ERROR'),
],
), ),
actions: [ actions: [
IconButton( IconButton(
@ -133,8 +117,44 @@ class _StatusScreenState extends State<StatusScreen> {
), ),
], ],
bottom: PreferredSize( bottom: PreferredSize(
preferredSize: const Size.fromHeight(1), preferredSize: const Size.fromHeight(60),
child: Container(height: 1, color: const Color(0xFF2a2a2a)), child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(left: 16, top: 8),
child: Row(
children: [
const Icon(
Icons.terminal,
color: Color(0xFF00bcd4),
size: 16,
),
const SizedBox(width: 8),
const Text(
'EVENT LOG',
style: TextStyle(
fontFamily: 'monospace',
fontSize: 13,
fontWeight: FontWeight.w700,
letterSpacing: 2,
color: Color(0xFFe0e0e0),
),
),
const SizedBox(width: 16),
_buildFilterChip('ALL', null),
const SizedBox(width: 6),
_buildFilterChip('LOG', 'LOCATION'),
const SizedBox(width: 6),
_buildFilterChip('SYNC', 'SYNC'),
const SizedBox(width: 6),
_buildFilterChip('ERR', 'ERROR'),
],
),
),
Container(height: 1, color: const Color(0xFF2a2a2a)),
],
),
), ),
), ),
body: _filteredLogs.isEmpty body: _filteredLogs.isEmpty
@ -142,10 +162,10 @@ class _StatusScreenState extends State<StatusScreen> {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon( const Icon(
Icons.inbox_outlined, Icons.inbox_outlined,
size: 48, size: 48,
color: const Color(0xFF2a2a2a), color: Color(0xFF2a2a2a),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
@ -176,7 +196,7 @@ class _StatusScreenState extends State<StatusScreen> {
itemCount: _filteredLogs.length, itemCount: _filteredLogs.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final log = _filteredLogs[index]; final log = _filteredLogs[index];
return _buildLogEntry(log); return _buildLogEntry(log, index);
}, },
), ),
); );
@ -216,7 +236,7 @@ class _StatusScreenState extends State<StatusScreen> {
); );
} }
Widget _buildLogEntry(Map<String, dynamic> log) { Widget _buildLogEntry(Map<String, dynamic> log, int index) {
final time = _formatTimestamp(log['timestamp'] as int? ?? 0); final time = _formatTimestamp(log['timestamp'] as int? ?? 0);
final type = log['eventType'] as String? ?? 'UNKNOWN'; final type = log['eventType'] as String? ?? 'UNKNOWN';
final msg = log['message'] as String? ?? ''; final msg = log['message'] as String? ?? '';
@ -224,58 +244,68 @@ class _StatusScreenState extends State<StatusScreen> {
final icon = _getLogIcon(type); final icon = _getLogIcon(type);
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 2), padding: EdgeInsets.only(
child: Row( left: 12,
right: 12,
top: index == 0 ? 6 : 8,
bottom: 6,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
SizedBox( // Line 1: timestamp
width: 100, Text(
child: Text( time,
time, style: const TextStyle(
style: const TextStyle( fontFamily: 'monospace',
fontFamily: 'monospace', fontSize: 10,
fontSize: 10, color: Color(0xFF546e7a),
color: Color(0xFF546e7a),
),
), ),
), ),
Container( const SizedBox(height: 4),
width: 20, // Line 2: type badge + icon + message
height: 20, Row(
decoration: BoxDecoration( crossAxisAlignment: CrossAxisAlignment.start,
color: color.withOpacity(0.15), children: [
borderRadius: BorderRadius.circular(3), Container(
), width: 18,
child: Icon(icon, size: 12, color: color), height: 18,
), decoration: BoxDecoration(
const SizedBox(width: 8), color: color.withOpacity(0.15),
Container( borderRadius: BorderRadius.circular(3),
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 1), ),
decoration: BoxDecoration( child: Icon(icon, size: 11, color: color),
color: color.withOpacity(0.1),
borderRadius: BorderRadius.circular(2),
),
child: Text(
type,
style: TextStyle(
fontFamily: 'monospace',
fontSize: 9,
fontWeight: FontWeight.w700,
letterSpacing: 1,
color: color,
), ),
), const SizedBox(width: 7),
), Container(
const SizedBox(width: 10), padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 2),
Expanded( decoration: BoxDecoration(
child: Text( color: color.withOpacity(0.1),
msg, borderRadius: BorderRadius.circular(2),
style: const TextStyle( ),
fontFamily: 'monospace', child: Text(
fontSize: 11, type,
color: Color(0xFF9e9e9e), style: TextStyle(
fontFamily: 'monospace',
fontSize: 9,
fontWeight: FontWeight.w700,
letterSpacing: 1,
color: color,
),
),
), ),
), const SizedBox(width: 10),
Expanded(
child: Text(
msg,
style: const TextStyle(
fontFamily: 'monospace',
fontSize: 11,
color: Color(0xFF9e9e9e),
),
),
),
],
), ),
], ],
), ),