From db08fc8d5c86ed3d5da747c0f88e9efcf684876f Mon Sep 17 00:00:00 2001 From: fiatcode Date: Thu, 30 Apr 2026 11:18:39 +0700 Subject: [PATCH] feat: add MainScreen with tracking toggle and status display --- lib/main_screen.dart | 158 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 lib/main_screen.dart diff --git a/lib/main_screen.dart b/lib/main_screen.dart new file mode 100644 index 0000000..04f136d --- /dev/null +++ b/lib/main_screen.dart @@ -0,0 +1,158 @@ +import 'package:flutter/material.dart'; +import 'package:traccar_client/bridge/location_bridge.dart'; +import 'package:traccar_client/preferences.dart'; +import 'package:traccar_client/settings_screen.dart'; +import 'package:traccar_client/status_screen.dart'; + +class MainScreen extends StatefulWidget { + const MainScreen({super.key}); + + @override + State createState() => _MainScreenState(); +} + +class _MainScreenState extends State { + bool _isTracking = false; + String _lastLat = '--'; + String _lastLon = '--'; + String _lastSpeed = '--'; + String _lastTime = '--'; + + @override + void initState() { + super.initState(); + _initLocationStream(); + } + + void _initLocationStream() { + LocationBridge.locationUpdates.listen((location) { + if (mounted) { + setState(() { + _lastLat = location['latitude']?.toStringAsFixed(4) ?? '--'; + _lastLon = location['longitude']?.toStringAsFixed(4) ?? '--'; + _lastSpeed = location['speed'] != null + ? '${(location['speed'] * 3.6).toStringAsFixed(0)} km/h' + : '--'; + _lastTime = location['timestamp'] != null + ? _formatTime(DateTime.fromMillisecondsSinceEpoch(location['timestamp'])) + : '--'; + }); + } + }); + } + + String _formatTime(DateTime dt) { + return '${dt.hour.toString().padLeft(2, '0')}:${dt.minute.toString().padLeft(2, '0')}:${dt.second.toString().padLeft(2, '0')}'; + } + + Future _toggleTracking() async { + if (_isTracking) { + await LocationBridge.stopTracking(); + } else { + await LocationBridge.startTracking(); + } + setState(() { + _isTracking = !_isTracking; + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Traccar Client'), + centerTitle: true, + ), + body: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + _buildStatusCard(), + const SizedBox(height: 24), + _buildTrackingToggle(), + const Spacer(), + _buildActionButtons(), + ], + ), + ), + ); + } + + Widget _buildStatusCard() { + return Card( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Last Location', + style: Theme.of(context).textTheme.titleMedium, + ), + const SizedBox(height: 16), + _buildInfoRow('Lat', _lastLat), + _buildInfoRow('Lon', _lastLon), + _buildInfoRow('Speed', _lastSpeed), + _buildInfoRow('Time', _lastTime), + ], + ), + ), + ); + } + + Widget _buildInfoRow(String label, String value) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 4.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(label), + Text(value, style: const TextStyle(fontWeight: FontWeight.bold)), + ], + ), + ); + } + + Widget _buildTrackingToggle() { + return SwitchListTile( + title: Text(_isTracking ? 'Tracking: ON' : 'Tracking: OFF'), + subtitle: Text(_isTracking ? 'Location updates active' : 'Tap to start tracking'), + value: _isTracking, + onChanged: (_) => _toggleTracking(), + activeColor: Colors.green, + ); + } + + Widget _buildActionButtons() { + return Row( + children: [ + Expanded( + child: ElevatedButton.icon( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute(builder: (_) => const SettingsScreen()), + ); + }, + icon: const Icon(Icons.settings), + label: const Text('Settings'), + ), + ), + const SizedBox(width: 16), + Expanded( + child: ElevatedButton.icon( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute(builder: (_) => const StatusScreen()), + ); + }, + icon: const Icon(Icons.logs), + label: const Text('Status/Logs'), + ), + ), + ], + ); + } +}