Food: single-source tracking, mode exclusivity, in-app navigation
This commit is contained in:
@@ -16,6 +16,7 @@ import '../../main.dart';
|
||||
import '../../print.dart';
|
||||
import '../../views/food_delivery/food_offer_page.dart';
|
||||
import '../../views/widgets/error_snakbar.dart';
|
||||
import '../functions/location_controller.dart';
|
||||
import '../voice_call_controller.dart';
|
||||
import 'food_delivery_models.dart';
|
||||
import 'food_delivery_service.dart';
|
||||
@@ -235,6 +236,26 @@ class FoodDeliveryController extends GetxController {
|
||||
await _fetchPendingOffers();
|
||||
}
|
||||
await fetchActiveTasks(silent: true);
|
||||
await _broadcastLocation();
|
||||
}
|
||||
|
||||
// موقع السائق يُبثّ فقط ما دامت هناك مهمة نشطة — لا شيء يُرسل قبل الإسناد
|
||||
// ولا بعد التسليم، والخادم يرفضه في الحالتين أصلاً كطبقة ثانية.
|
||||
Future<void> _broadcastLocation() async {
|
||||
if (activeTasks.isEmpty) return;
|
||||
if (!Get.isRegistered<LocationController>()) return;
|
||||
|
||||
final loc = Get.find<LocationController>();
|
||||
if (loc.myLocation.latitude == 0 && loc.myLocation.longitude == 0) return;
|
||||
|
||||
for (final task in activeTasks) {
|
||||
await FoodDeliveryService.sendLocation(
|
||||
orderId: task.id,
|
||||
lat: loc.myLocation.latitude,
|
||||
lng: loc.myLocation.longitude,
|
||||
heading: loc.heading,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _fetchPendingOffers() async {
|
||||
@@ -253,9 +274,42 @@ class FoodDeliveryController extends GetxController {
|
||||
final res = await FoodDeliveryService.getActiveTasks();
|
||||
isLoadingTasks = false;
|
||||
if (res.success) activeTasks = res.data ?? [];
|
||||
_syncRideAvailability();
|
||||
update();
|
||||
}
|
||||
|
||||
// ── مهمة واحدة في الوقت الواحد ──────────────────────────────────────────
|
||||
// السائق أثناء التوصيل «مشغول» في نظام الرحلات تماماً كما لو كان في رحلة:
|
||||
// نكتب statusDriverLocation='on' فينقله driver_socket من geo:drivers:available
|
||||
// إلى geo:drivers:busy، فيتوقف توزيع الرحلات عليه — ويتوقف معه توزيع طلبات
|
||||
// طعام إضافية، لأن مطابقة الطعام تتقاطع مع نفس المجموعة المتاحة.
|
||||
// نعيده متاحاً بعد التسليم، وبشرطين: أن نكون نحن من شغَله، وألا تكون هناك
|
||||
// رحلة جارية فعلاً (وإلا أفرغنا انشغالاً ليس لنا).
|
||||
bool _markedBusyForDelivery = false;
|
||||
|
||||
void _syncRideAvailability() {
|
||||
final hasDelivery = activeTasks.isNotEmpty;
|
||||
|
||||
if (hasDelivery && !_markedBusyForDelivery) {
|
||||
_markedBusyForDelivery = true;
|
||||
box.write(BoxName.statusDriverLocation, 'on');
|
||||
Log.print('🍔 [FoodDelivery] السائق مشغول بتوصيل — أُوقف استقبال الرحلات');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hasDelivery && _markedBusyForDelivery) {
|
||||
_markedBusyForDelivery = false;
|
||||
final rideStatus = (box.read(BoxName.rideStatus) ?? '').toString();
|
||||
final onRide = rideStatus == 'Begin' || rideStatus == 'Apply' || rideStatus == 'Arrived';
|
||||
final blocked = box.read(BoxName.statusDriverLocation) == 'blocked';
|
||||
|
||||
if (!onRide && !blocked) {
|
||||
box.write(BoxName.statusDriverLocation, 'off');
|
||||
Log.print('🍔 [FoodDelivery] انتهى التوصيل — عاد استقبال الرحلات');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isRespondingToOffer(int orderId) => _respondingOfferIds.contains(orderId);
|
||||
bool isTaskBusy(int orderId) => _busyTaskIds.contains(orderId);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user