diff --git a/siro_rider/lib/controller/home/map/map_socket_controller.dart b/siro_rider/lib/controller/home/map/map_socket_controller.dart index 2f7a20fd..837be14a 100644 --- a/siro_rider/lib/controller/home/map/map_socket_controller.dart +++ b/siro_rider/lib/controller/home/map/map_socket_controller.dart @@ -225,11 +225,26 @@ class MapSocketController extends GetxController { /// (الحدث يُفقد نهائياً في تلك الحالة — لا طابور في غرف Socket.IO). /// لا يُفشل إنشاء الرحلة أبداً: عند انتهاء المهلة نكمل ونتّكل على /// الـ FCM/polling كشبكة احتياطية. + /// آخر مرة فشل فيها الاتصال — حتى لا نُبطئ كل طلب رحلة بانتظارٍ عقيم إذا كان + /// السوكيت غير قابل للوصول أصلاً (منفذ مغلق/TLS غير مُنهى/سيرفر واقف). + static DateTime? _lastConnectFailure; + static const Duration _failureCooldown = Duration(minutes: 2); + Future ensureConnectedBeforeRide({ - Duration timeout = const Duration(seconds: 4), + Duration timeout = const Duration(seconds: 2), }) async { if (isReadyForEvents) return true; + final lastFail = _lastConnectFailure; + if (lastFail != null && + DateTime.now().difference(lastFail) < _failureCooldown) { + // فشل قريباً — نبدأ محاولة الاتصال في الخلفية ولا نُعطّل الطلب إطلاقاً + initConnectionWithSocket(); + Log.print( + "⏭️ Skipping socket wait (recent failure). Ride proceeds on FCM/polling."); + return false; + } + await initConnectionWithSocket(); final deadline = DateTime.now().add(timeout); @@ -238,11 +253,13 @@ class MapSocketController extends GetxController { } if (isSocketConnected) { + _lastConnectFailure = null; Log.print("✅ Socket ready before ride creation."); return true; } + _lastConnectFailure = DateTime.now(); Log.print( - "⚠️ Socket not ready within ${timeout.inSeconds}s — continuing; FCM/polling will cover."); + "⚠️ Socket not ready within ${timeout.inMilliseconds}ms — continuing; FCM/polling will cover."); return false; } diff --git a/siro_rider/lib/controller/home/map/ride_lifecycle_controller.dart b/siro_rider/lib/controller/home/map/ride_lifecycle_controller.dart index 0fd1a236..46761780 100644 --- a/siro_rider/lib/controller/home/map/ride_lifecycle_controller.dart +++ b/siro_rider/lib/controller/home/map/ride_lifecycle_controller.dart @@ -3917,13 +3917,20 @@ class RideLifecycleController extends GetxController { PipService.enablePip(); - if (source == "Socket" && mapSocket.isSocketConnected) { - Log.print( - "🧠 Smart Mode: Socket accepted ride. Skipping polling, relying on WebSocket."); - } else { - Log.print("🔄 Fallback Mode: $source accepted ride. Starting polling."); - _startDriverLocationPollingWithTimer(); - } + // ⚠️ لا نثق بالسوكيت قبل أن **يُثبت** أنه يوصّل المواقع فعلاً. + // كان هنا شرط "Smart Mode" يتخطّى الـ polling كلياً إذا جاء القبول من + // السوكيت — وهو خطأ: وصول حدث القبول لا يعني أن تدفّق المواقع يعمل. + // تدفّق المواقع له شرط مستقل تماماً: تطبيق السائق يحقن passenger_id في + // update_location فقط إذا كان rideStatus نشطاً و BoxName.passengerID + // مكتوباً — وهو لا يُكتب إلا بعد فتح صفحة خريطة السائق. فبين القبول وفتح + // الصفحة لا يوجّه driver_socket أي موقع، وبلا polling لا يظهر الماركر أبداً. + // + // نشغّل الـ polling دائماً، و handleDriverLocationUpdate يوقفه تلقائياً + // بعد 3 تحديثات ناجحة من السوكيت (المنطق موجود هناك أصلاً). هكذا يبقى + // السوكيت هو المسار السريع بلا أن نفقد شبكة الأمان. + Log.print("🔄 Starting driver-location polling (source: $source). " + "Socket will take over and stop it once it proves delivery."); + _startDriverLocationPollingWithTimer(); } void _fillDriverDataLocally(Map data) {