mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
- Added BleCommandQueue to manage command serialization and responses in BleCommandSender. - Updated writeData, writeDataAndWaitForAck, and writeDataAndWaitForResponse methods to utilize the command queue. - Enhanced BleResponseHandler to complete commands based on responses received from the BLE device. - Introduced new commands for channel management, including getChannel and setChannel. - Created LocationTrailLayer and TrailControls widgets for displaying and managing location trails on the map. - Added PermissionRequestDialog to handle location permission requests on app startup. - Updated LocationTrackingService to allow GPS tracking without a BLE connection.
156 lines
3.9 KiB
Dart
156 lines
3.9 KiB
Dart
import 'package:flutter/foundation.dart';
|
|
import 'package:latlong2/latlong.dart';
|
|
import '../models/location_trail.dart';
|
|
|
|
class MapProvider with ChangeNotifier {
|
|
LatLng? _targetLocation;
|
|
double? _targetZoom;
|
|
bool _shouldAnimate = false;
|
|
|
|
// Track which contact paths are currently visible
|
|
final Set<String> _visibleContactPaths = {};
|
|
|
|
// Location trail tracking
|
|
LocationTrail? _currentTrail;
|
|
bool _isTrailVisible = true;
|
|
final List<LocationTrail> _trailHistory = [];
|
|
|
|
LatLng? get targetLocation => _targetLocation;
|
|
double? get targetZoom => _targetZoom;
|
|
bool get shouldAnimate => _shouldAnimate;
|
|
Set<String> get visibleContactPaths => Set.unmodifiable(_visibleContactPaths);
|
|
|
|
// Trail getters
|
|
LocationTrail? get currentTrail => _currentTrail;
|
|
bool get isTrailVisible => _isTrailVisible;
|
|
List<LocationTrail> get trailHistory => List.unmodifiable(_trailHistory);
|
|
bool get isTrailActive => _currentTrail?.isActive ?? false;
|
|
|
|
void navigateToLocation({
|
|
required LatLng location,
|
|
double zoom = 15.0,
|
|
bool animate = true,
|
|
}) {
|
|
_targetLocation = location;
|
|
_targetZoom = zoom;
|
|
_shouldAnimate = animate;
|
|
notifyListeners();
|
|
}
|
|
|
|
void clearNavigation() {
|
|
_targetLocation = null;
|
|
_targetZoom = null;
|
|
_shouldAnimate = false;
|
|
// Don't notify listeners to avoid rebuilds
|
|
}
|
|
|
|
void updateZoom(double zoom) {
|
|
_targetZoom = zoom;
|
|
notifyListeners();
|
|
}
|
|
|
|
/// Toggle path visibility for a contact
|
|
void toggleContactPath(String publicKeyHex) {
|
|
if (_visibleContactPaths.contains(publicKeyHex)) {
|
|
_visibleContactPaths.remove(publicKeyHex);
|
|
} else {
|
|
_visibleContactPaths.add(publicKeyHex);
|
|
}
|
|
notifyListeners();
|
|
}
|
|
|
|
/// Check if a contact's path is visible
|
|
bool isContactPathVisible(String publicKeyHex) {
|
|
return _visibleContactPaths.contains(publicKeyHex);
|
|
}
|
|
|
|
/// Hide all contact paths
|
|
void hideAllPaths() {
|
|
_visibleContactPaths.clear();
|
|
notifyListeners();
|
|
}
|
|
|
|
/// Show path for specific contact (hide all others)
|
|
void showOnlyPath(String publicKeyHex) {
|
|
_visibleContactPaths.clear();
|
|
_visibleContactPaths.add(publicKeyHex);
|
|
notifyListeners();
|
|
}
|
|
|
|
/// Start a new location trail
|
|
void startTrail() {
|
|
// End current trail if active
|
|
if (_currentTrail != null && _currentTrail!.isActive) {
|
|
endTrail();
|
|
}
|
|
|
|
_currentTrail = LocationTrail(
|
|
id: DateTime.now().millisecondsSinceEpoch.toString(),
|
|
startTime: DateTime.now(),
|
|
);
|
|
_isTrailVisible = true;
|
|
notifyListeners();
|
|
}
|
|
|
|
/// Add a point to the current trail
|
|
void addTrailPoint(LatLng position, {double? accuracy, double? speed}) {
|
|
if (_currentTrail == null || !_currentTrail!.isActive) {
|
|
startTrail();
|
|
}
|
|
|
|
_currentTrail!.addPoint(TrailPoint(
|
|
position: position,
|
|
timestamp: DateTime.now(),
|
|
accuracy: accuracy,
|
|
speed: speed,
|
|
));
|
|
notifyListeners();
|
|
}
|
|
|
|
/// End the current trail
|
|
void endTrail() {
|
|
if (_currentTrail != null) {
|
|
_currentTrail!.isActive = false;
|
|
_currentTrail!.endTime = DateTime.now();
|
|
if (_currentTrail!.points.isNotEmpty) {
|
|
_trailHistory.add(_currentTrail!);
|
|
}
|
|
_currentTrail = null;
|
|
notifyListeners();
|
|
}
|
|
}
|
|
|
|
/// Toggle trail visibility
|
|
void toggleTrailVisibility() {
|
|
_isTrailVisible = !_isTrailVisible;
|
|
notifyListeners();
|
|
}
|
|
|
|
/// Clear the current trail
|
|
void clearCurrentTrail() {
|
|
if (_currentTrail != null) {
|
|
_currentTrail = null;
|
|
notifyListeners();
|
|
}
|
|
}
|
|
|
|
/// Clear all trail history
|
|
void clearAllTrails() {
|
|
_currentTrail = null;
|
|
_trailHistory.clear();
|
|
notifyListeners();
|
|
}
|
|
|
|
/// Get total trail distance in meters
|
|
double get totalTrailDistance {
|
|
if (_currentTrail == null) return 0;
|
|
return _currentTrail!.totalDistance;
|
|
}
|
|
|
|
/// Get trail duration
|
|
Duration get trailDuration {
|
|
if (_currentTrail == null) return Duration.zero;
|
|
return _currentTrail!.duration;
|
|
}
|
|
}
|