Food: single-source tracking, mode exclusivity, in-app navigation

This commit is contained in:
Hamza-Ayed
2026-08-04 02:41:54 +03:00
parent 788d3dcbe5
commit d695834d19
14 changed files with 607 additions and 83 deletions
@@ -13,6 +13,7 @@ import 'package:siro_driver/constant/box_name.dart';
import 'package:siro_driver/constant/links.dart';
import 'package:siro_driver/controller/car_platform_bridge.dart';
import 'package:siro_driver/controller/functions/crud.dart';
import 'package:siro_driver/controller/functions/location_controller.dart';
import 'package:siro_driver/controller/functions/tts.dart';
import 'package:siro_driver/controller/home/navigation/decode_polyline_isolate.dart';
import 'package:siro_driver/env/env.dart';
@@ -39,9 +40,6 @@ class RouteData {
class NavigationController extends GetxController
with GetSingleTickerProviderStateMixin {
static const Duration _recordInterval = Duration(seconds: 4);
static const Duration _uploadInterval = Duration(minutes: 2);
static const double _minMoveToRecord = 10.0;
static const double _minMoveToProcess = 2.0;
static const double _offRouteThresholdM = 25.0;
static const int _offRouteTriggerSeconds = 6;
@@ -164,11 +162,6 @@ class NavigationController extends GetxController
DateTime? _offRouteStartTime;
bool _autoRecalcInProgress = false;
final List<Map<String, dynamic>> _trackBuffer = [];
Timer? _recordTimer;
Timer? _uploadBatchTimer;
LatLng? _lastBufferedLocation;
DateTime? _lastBufferedTime;
LatLng? _lastDistanceLocation;
List<RouteData> routes = [];
@@ -364,13 +357,11 @@ class NavigationController extends GetxController
@override
void onClose() {
_locationStreamSubscription?.cancel();
_recordTimer?.cancel();
_uploadBatchTimer?.cancel();
_debounce?.cancel();
_animController?.dispose();
mapController = null;
placeDestinationController.dispose();
_flushBufferToServer();
_flushTracksViaCentral();
super.onClose();
}
@@ -475,7 +466,6 @@ class NavigationController extends GetxController
if (isStyleLoaded) animateCameraToPosition(myLocation!);
// Start the Location Stream for real-time updates
_startLocationStream();
_startBatchTimers();
} catch (e) {
Log.print("DEBUG: Error getting initial location: $e");
}
@@ -616,63 +606,16 @@ class NavigationController extends GetxController
}
}
void _startBatchTimers() {
_recordTimer?.cancel();
_uploadBatchTimer?.cancel();
_recordTimer = Timer.periodic(_recordInterval, (_) => _recordToBuffer());
_uploadBatchTimer =
Timer.periodic(_uploadInterval, (_) => _flushBufferToServer());
}
// ‏رفع مسار القيادة (add_batch) مركزيّ في LocationController وحده.
// ‏كان الملّاح يحتفظ بذاكرة ومؤقّتات رفع خاصة به ويُرسل إلى نفس الواجهة
// ‏ونفس الخادم، فيُكتب مسار السائق الواحد مرتين ما دامت شاشة الملاحة
// ‏مفتوحة — ولأن add_batch.php يراكم زمن العمل اليومي من نفس الجدول،
// ‏كان ذلك يضاعف ساعات العمل المحسوبة. مصدر الموقع واحد فالرفع واحد.
void _recordToBuffer() {
if (myLocation == null ||
(myLocation!.latitude == 0 && myLocation!.longitude == 0)) {
return;
}
final now = DateTime.now();
final distFromLast = _lastBufferedLocation == null
? 999.0
: Geolocator.distanceBetween(
_lastBufferedLocation!.latitude,
_lastBufferedLocation!.longitude,
myLocation!.latitude,
myLocation!.longitude);
final bool moved = distFromLast > _minMoveToRecord && currentSpeed > 0.5;
final bool timeForced = _lastBufferedTime == null ||
now.difference(_lastBufferedTime!).inSeconds >= 60;
if (!moved && !timeForced) return;
_lastBufferedLocation = myLocation;
_lastBufferedTime = now;
_trackBuffer.add({
'lat': double.parse(myLocation!.latitude.toStringAsFixed(6)),
'lng': double.parse(myLocation!.longitude.toStringAsFixed(6)),
'spd': double.parse(currentSpeed.toStringAsFixed(1)),
'head': _smoothedHeading.toStringAsFixed(0),
'dist': double.parse(totalDistance.toStringAsFixed(1)),
'ts': now.toIso8601String(),
});
}
Future<void> _flushBufferToServer() async {
if (_trackBuffer.isEmpty) return;
final batch = List<Map<String, dynamic>>.from(_trackBuffer);
_trackBuffer.clear();
final String passengerId = (box.read(BoxName.passengerID) ?? '').toString();
try {
await CRUD().post(
link: '${AppLink.locationServerSide}/add_batch.php',
payload: {
'driver_id': passengerId,
'batch_data': jsonEncode(batch),
'session_dist': totalDistance.toStringAsFixed(1),
},
);
} catch (e) {
_trackBuffer.insertAll(0, batch);
}
// ‏الرفع مركزيّ في LocationController — نطلب منه دفع ما تراكم فقط
void _flushTracksViaCentral() {
if (!Get.isRegistered<LocationController>()) return;
Get.find<LocationController>().flushTrackBufferNow();
}
Future<void> _updateCarMarker() async {
@@ -1179,7 +1122,7 @@ class NavigationController extends GetxController
isNavigating = false;
routes = [];
CarPlatformBridge.stopNavigation();
await _flushBufferToServer();
_flushTracksViaCentral();
}
routeSteps = [];
_fullRouteCoordinates = [];
@@ -1277,7 +1220,7 @@ class NavigationController extends GetxController
Get.find<TextToSpeechController>().speakText(currentInstruction);
}
CarPlatformBridge.stopNavigation();
_flushBufferToServer();
_flushTracksViaCentral();
update();
}