Files
fforte/lib/screens/excursion/widgets/tracking.dart

196 lines
5.7 KiB
Dart

import 'dart:async';
import 'dart:math';
import 'package:fforte/l10n/app_localizations.dart';
import 'package:fforte/screens/helper/snack_bar_helper.dart';
import 'package:fforte/services/notification_service.dart';
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:geolocator/geolocator.dart';
import 'package:latlong2/latlong.dart';
class Tracking extends StatefulWidget {
final LatLng startPosition;
final TextEditingController weg;
const Tracking({super.key, required this.startPosition, required this.weg});
@override
State<Tracking> createState() => _TrackingState();
}
class _TrackingState extends State<Tracking> {
List<LatLng> pathList = [];
StreamSubscription<Position>? positionStream;
bool positionStreamRunning = false;
MapController mapController = MapController();
Random rand = Random();
@override
void initState() {
// TODO debugging (i guess)
pathList.add(
LatLng(widget.startPosition.latitude, widget.startPosition.longitude),
);
if (widget.weg.text.isNotEmpty) {
for (var element in widget.weg.text.split(";")) {
List<String> posSplit = element.split(",");
try {
posSplit[0] = posSplit[0].substring(0, 9);
posSplit[1] = posSplit[1].substring(0, 9);
} on RangeError {
// ignore because the double is short enough then
}
pathList.add(
LatLng(double.parse(posSplit.first), double.parse(posSplit[1])),
);
}
}
super.initState();
}
@override
void dispose() {
if (positionStream != null) positionStream!.cancel();
bool isFirst = true;
if (pathList.isNotEmpty) {
for (var pos in pathList) {
if (!isFirst) {
widget.weg.text += ";";
} else {
isFirst = false;
}
widget.weg.text += "${pos.latitude},${pos.longitude}";
}
}
super.dispose();
}
final LocationSettings streamLocationSettings = LocationSettings(
accuracy: LocationAccuracy.high,
distanceFilter: 10,
);
void onTrackingStart() async {
// notification handling for tracking in background notification
await NotificationService().initNotification();
if (mounted)
NotificationService().showNotification(
title: AppLocalizations.of(context)!.trackingRunningInBackground,
);
positionStream = Geolocator.getPositionStream(
locationSettings: AndroidSettings(
accuracy: LocationAccuracy.high,
distanceFilter: 0,
// foregroundNotificationConfig:
// mounted
// ? ForegroundNotificationConfig(
// notificationTitle:
// AppLocalizations.of(context)!.trackingRunningInBackground,
// notificationText: "",
// )
// : null,
),
).listen((Position? position) {
if (position != null) {
// pathList.add(LatLng(position.latitude, position.longitude));
setState(() {
pathList.add(LatLng(rand.nextInt(5) + 40, position.longitude));
});
} else {
if (mounted) {
SnackBarHelper.showSnackBarMessage(
context,
AppLocalizations.of(context)!.couldntDeterminePosition,
);
}
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(AppLocalizations.of(context)!.tracking),
// leading: IconButton(onPressed: () {}, icon: Icon(Icons.arrow_back_rounded)),
actions: [
if (positionStreamRunning)
IconButton(
onPressed: () {
setState(() {
positionStreamRunning = false;
positionStream!.cancel();
NotificationService().deleteNotification();
});
},
icon: Icon(Icons.stop_rounded),
),
IconButton(
onPressed: () {
if (positionStreamRunning) {
positionStreamRunning = false;
positionStream?.pause();
} else {
positionStreamRunning = true;
onTrackingStart();
}
setState(() {});
},
icon:
positionStreamRunning
? Icon(Icons.pause)
: Icon(Icons.play_arrow),
),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
mapController.move(pathList.last, 16);
},
child: Icon(Icons.my_location),
),
body: FlutterMap(
mapController: mapController,
options: MapOptions(
interactionOptions: const InteractionOptions(
flags:
InteractiveFlag.pinchZoom |
InteractiveFlag.drag |
InteractiveFlag.pinchMove,
),
initialCenter: widget.startPosition,
initialZoom: 16.0,
),
children: [
TileLayer(
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
userAgentPackageName: 'com.example.app',
),
if (pathList.isNotEmpty)
PolylineLayer(
polylines: [
Polyline(strokeWidth: 2.0, points: pathList, color: Colors.red),
],
),
CircleLayer(
circles: [
CircleMarker(
color: Colors.blue,
point: pathList.isEmpty ? widget.startPosition : pathList.last,
radius: 5,
useRadiusInMeter: true,
),
],
),
],
),
);
}
}