Food delivery driver module + masked calls + TURN

This commit is contained in:
Hamza-Ayed
2026-08-04 01:50:50 +03:00
parent 04c214bdf6
commit f01e408ba6
35 changed files with 3029 additions and 212 deletions
@@ -11,6 +11,7 @@ import '../../constant/links.dart';
import '../../main.dart';
import '../../print.dart';
import '../../services/signaling_service.dart';
import '../../services/turn_credentials_service.dart';
import '../../views/widgets/voice_call_bottom_sheet.dart';
import 'functions/crud.dart';
@@ -229,11 +230,16 @@ class VoiceCallController extends GetxController with WidgetsBindingObserver {
// EN: Initiates an outgoing call.
// AR: يبدأ مكالمة صادرة.
/// [sessionEndpoint] و [sessionPayload] يسمحان لوحدات أخرى (توصيل الطعام)
/// بإعادة استخدام نفس قناة WebRTC المقنّعة بواجهة إنشاء جلسة خاصة بها،
/// بدل تكرار منطق الإشارات والصوت. القيمة الافتراضية هي مكالمة الرحلة.
Future<void> startCall({
required String rideIdVal,
required String driverId,
required String passengerId,
required String remoteNameVal,
String? sessionEndpoint,
Map<String, String>? sessionPayload,
}) async {
if (state.value != VoiceCallState.idle) return;
@@ -268,8 +274,9 @@ class VoiceCallController extends GetxController with WidgetsBindingObserver {
// 2. EN: Call PHP Backend to create Node.js session & notify Passenger via FCM.
// AR: استدعاء واجهة PHP لإنشاء الجلسة على Node.js وإشعار الراكب عبر FCM.
final response = await CRUD().post(
link: "${AppLink.server}/ride/call/driver/create_call_session.php",
payload: {'ride_id': rideIdVal},
link: sessionEndpoint ??
"${AppLink.server}/ride/call/driver/create_call_session.php",
payload: sessionPayload ?? {'ride_id': rideIdVal},
);
if (response == null ||
@@ -281,8 +288,16 @@ class VoiceCallController extends GetxController with WidgetsBindingObserver {
return;
}
final data = response['data'];
sessionId.value = data['session_id'];
// واجهات الرحلات تُعيد الجلسة في 'data'، وواجهات وحدة الطعام تُعيدها في
// 'message' (غلاف jsonSuccess الموحّد) — نقبل الشكلين.
final data = response['data'] ?? response['message'];
if (data is! Map || data['session_id'] == null) {
errorMessage.value =
"Failed to initiate call session. Please try again.".tr;
_endCallInternal("session_creation_failed");
return;
}
sessionId.value = data['session_id'].toString();
// 3. EN: Connect to WebRTC signaling server / AR: الاتصال بخادم الإشارات
await _signaling.connect(sessionId.value, currentUserId);
@@ -492,8 +507,16 @@ class VoiceCallController extends GetxController with WidgetsBindingObserver {
});
}
}
} else {
// EN: Fallback STUN servers / AR: خوام STUN الاحتياطية
}
// خوادم TURN من الباك إند — بيانات اعتماد مؤقتة. بلا TURN تفشل المكالمة
// صامتةً حين يكون الطرفان خلف CGNAT (شبكة الجوال)، وهي الحالة الغالبة.
// نُضيفها قبل خوادم الإشارات: STUN يبقى أولاً في الترتيب داخل القائمة.
final turnServers = await TurnCredentialsService.getIceServers();
iceServers.addAll(turnServers);
if (iceServers.isEmpty) {
// EN: Fallback STUN servers / AR: خوادم STUN الاحتياطية
iceServers.addAll([
{"urls": "stun:stun.l.google.com:19302"},
{"urls": "stun:stun1.l.google.com:19302"},