tracpulse/lib/main_screen.dart

158 lines
4.3 KiB
Dart

import 'package:flutter/material.dart';
import 'package:traccar_client/bridge/location_bridge.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<MainScreen> createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
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<void> _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(),
activeTrackColor: 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.history),
label: const Text('Status/Logs'),
),
),
],
);
}
}