let AI comment everything because well... yeah...

This commit is contained in:
Nico
2025-06-06 21:00:32 +02:00
parent 9c84d0c375
commit cc110ac104
44 changed files with 1230 additions and 646 deletions

View File

@@ -1,3 +1,12 @@
// * Widget for GPS tracking during wildlife monitoring excursions
// * Features:
// * - Real-time location tracking
// * - Track visualization on map
// * - Distance calculation
// * - Location accuracy monitoring
// * - Track recording controls (start/pause/stop)
// * - Track data persistence
import 'dart:async';
import 'package:fforte/l10n/app_localizations.dart';
@@ -11,27 +20,40 @@ import 'package:flutter_map_location_marker/flutter_map_location_marker.dart';
import 'package:geolocator/geolocator.dart';
import 'package:latlong2/latlong.dart';
/// Widget for managing GPS tracking functionality
/// Provides map visualization and tracking controls
class Tracking extends StatefulWidget {
/// Initial position for the tracking session
final Position startPosition;
/// Controller for storing the tracked path
final TextEditingController weg;
const Tracking({super.key, required this.startPosition, required this.weg});
@override
State<Tracking> createState() => _TrackingState();
}
/// State class for the tracking widget
class _TrackingState extends State<Tracking> {
/// Service for managing tracking functionality
final TrackingService _trackingService = TrackingService();
/// Current GPS position
Position? currentPosition;
/// Controller for the map widget
MapController mapController = MapController();
/// Subscription for position updates
StreamSubscription? _positionSubscription;
/// Subscription for tracking statistics updates
StreamSubscription? _statsSubscription;
/// Current tracking statistics
TrackingStats? _currentStats;
@override
void initState() {
super.initState();
// Load existing track if available
if (widget.weg.text.isNotEmpty) {
for (var element in widget.weg.text.split(";")) {
List<String> posSplit = element.split(",");
@@ -50,24 +72,27 @@ class _TrackingState extends State<Tracking> {
currentPosition = widget.startPosition;
// Initialisiere die Statistiken sofort
// Initialize tracking statistics
setState(() {
_currentStats = _trackingService.currentStats;
});
_trackingService.requestStatsUpdate();
// Subscribe to position updates
_positionSubscription = _trackingService.positionStream$.listen((position) {
setState(() {
currentPosition = position;
});
});
// Subscribe to statistics updates
_statsSubscription = _trackingService.statsStream$.listen((stats) {
setState(() {
_currentStats = stats;
});
});
// Check location permissions
GeolocatorService.alwaysPositionEnabled().then((value) {
if (!value && mounted) {
Navigator.of(context).pop();
@@ -84,6 +109,9 @@ class _TrackingState extends State<Tracking> {
super.dispose();
}
/// Format distance for display
/// @param meters Distance in meters
/// @return Formatted distance string with appropriate unit
String _formatDistance(double meters) {
if (meters >= 1000) {
return '${(meters / 1000).toStringAsFixed(2)} km';
@@ -99,6 +127,7 @@ class _TrackingState extends State<Tracking> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(AppLocalizations.of(context)!.tracking),
// Display tracking statistics if available
if (_currentStats != null)
DefaultTextStyle(
style: Theme.of(context).textTheme.bodySmall!,
@@ -125,6 +154,7 @@ class _TrackingState extends State<Tracking> {
icon: Icon(Icons.arrow_back_rounded)
),
actions: [
// Delete track button (only when not tracking)
if (!_trackingService.isTracking)
IconButton(
onPressed: () async {
@@ -140,6 +170,7 @@ class _TrackingState extends State<Tracking> {
color: Theme.of(context).colorScheme.errorContainer,
),
),
// Stop tracking button (only when tracking)
if (_trackingService.isTracking)
TextButton(
onPressed: () {
@@ -149,6 +180,7 @@ class _TrackingState extends State<Tracking> {
},
child: Text(AppLocalizations.of(context)!.trackingStop),
),
// Start/Pause tracking button
TextButton(
onPressed: () {
setState(() {
@@ -165,6 +197,7 @@ class _TrackingState extends State<Tracking> {
),
],
),
// Center on current location button
floatingActionButton: FloatingActionButton(
onPressed: () {
mapController.move(
@@ -177,6 +210,7 @@ class _TrackingState extends State<Tracking> {
},
child: Icon(Icons.my_location),
),
// Map display
body: FlutterMap(
mapController: mapController,
options: MapOptions(
@@ -192,10 +226,12 @@ class _TrackingState extends State<Tracking> {
initialZoom: 16.0,
),
children: [
// Base map layer
TileLayer(
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
userAgentPackageName: 'de.lupus.apps',
),
// Track path layer
if (_trackingService.pathList.isNotEmpty)
PolylineLayer(
polylines: [
@@ -206,6 +242,7 @@ class _TrackingState extends State<Tracking> {
),
],
),
// Current position accuracy circle
if (currentPosition != null)
CircleLayer(
circles: [
@@ -231,6 +268,7 @@ class _TrackingState extends State<Tracking> {
),
],
),
// Current location marker
CurrentLocationLayer(),
],
),