- siro_admin: added FlutterSecureStorage write alongside GetStorage - siro_service: added FlutterSecureStorage write in login + guest JWT flows - siro_rider: added FlutterSecureStorage write in guest + token-refresh flows (full-credential login already wrote to both) - siro_driver: already wrote to both (no change needed) - All apps now write JWT to both GetStorage and FlutterSecureStorage
إليك التقرير الفني الشامل لمشروع Siro Passenger App، مكتوباً بصيغة توثيق تقني (Technical Documentation) موجهة لفريق التطوير، بناءً على تحليل الكود المصدري.
📘 Siro Passenger App - Technical Documentation Report
Prepared by: CTO Office Target Audience: Mobile Engineering Team Version: 1.0
1. 🚀 بداية التشغيل (Initialization & Startup)
تعتمد مرحلة الإقلاع على تهيئة الخدمات الأساسية قبل عرض واجهة المستخدم لضمان استقرار التطبيق.
أ. نقطة الدخول (main.dart)
- المسار:
lib/main.dart - الوظيفة:
- يستخدم
runZonedGuardedلالتقاط الأخطاء العامة (Global Error Handling) وإرسالها للسيرفر عبرCRUD.addError. - تهيئة الخدمات: يتم تهيئة
GetStorage(للتخزين المحلي)،WakelockPlus(لمنع انطفاء الشاشة)، وFirebase(للإشعارات) قبل استدعاءrunApp. - إعدادات التوجيه: يتم تحديد الاتجاه العمودي فقط (
portraitUp) للجهاز. - حقن التبعيات (DI): يتم استدعاء
AppBindingsكـinitialBindingلتهيئة المتحكمات الأساسية.
- يستخدم
ب. إدارة التبعيات (AppBindings)
- المسار:
lib/app_bindings.dart - الآلية:
- يتم حقن
LocaleControllerوDeepLinkControllerبشكل دائم (permanent: true) لضمان تواجدهم طوال دورة حياة التطبيق. - يتم استخدام
Get.lazyPutمعfenix: trueللمتحكمات الأخرى (مثلLoginController) ليتم إنشاؤها عند الحاجة وإعادة إنشائها إذا تم التخلص منها.
- يتم حقن
ج. شاشة البداية (Splash Screen)
- المسار:
lib/splash_screen_page.dartوlib/controller/home/splash_screen_controlle.dart - المنطق:
- يتم عرض انيميشن باستخدام
AnimatedTextKitوFadeTransition. - العمليات الخلفية: يقوم
SplashScreenControllerبتنفيذ_initializeBackgroundServicesلتهيئة خدمات التشفير (EncryptionHelper) والإشعارات. - التوجيه الذكي: تتحقق الدالة
_performNavigationLogicمن وجود بيانات المستخدم فيBoxName. إذا كان المستخدم مسجلاً ومفعلاً (isVerified == '1')، يتم توجيهه تلقائياً للصفحة الرئيسية، وإلا يتم توجيهه لصفحة الدخول أو الترحيب (OnBoarding).
- يتم عرض انيميشن باستخدام
2. 🔐 دورة المصادقة (Authentication Cycle)
يعتمد النظام على مصادقة هجينة (Token-based + Social Auth) مع تخزين آمن.
أ. التسجيل والدخول (Sign Up & Login)
- المسار:
lib/controller/auth/login_controller.dartوregister_controller.dart - الآلية:
- Social Login: يتم استخدام
GoogleSignInHelperأوAuthController(Apple). عند النجاح، يتم إرسال التوكن للسيرفر للتحقق. - Credentials: في حالة الدخول التقليدي، يتم استدعاء
loginUsingCredentialsالتي تتحقق من البيانات عبر API. - التحقق (Verification): إذا رد السيرفر بأن الحساب غير مفعل، يتم تحويل المستخدم لصفحة
PhoneNumberScreenللتحقق عبر OTP.
- Social Login: يتم استخدام
ب. التحقق عبر الهاتف (OTP)
- المسار:
lib/controller/auth/otp_controller.dart - المنطق: يستخدم كلاس
PhoneAuthHelperلإرسال OTP (غالباً عبر WhatsApp أو SMS حسب الدولة) ثم التحقق منه عبر الـ EndpointverifyOtp.php.
ج. إدارة الجلسة والتوكن
- المخزن: يتم تخزين الـ JWT في
GetStorageتحت مفتاحBoxName.jwt. - التشفير: يتم استخدام
EncryptionHelperلتشفير البيانات الحساسة محلياً. - التجديد التلقائي: في كلاس
CRUD، إذا رد السيرفر بـ401 Token expired، يتم استدعاءgetJWTتلقائياً لتجديد التوكن دون تسجيل خروج المستخدم.
3. 🗺️ الشاشة الرئيسية والخريطة (Home & Map Logic)
تعتبر MapPagePassenger هي الواجهة المركزية التي تديرها MapPassengerController.
أ. تحميل الخريطة والموقع
- المسار:
lib/controller/home/map_passenger_controller.dart - المتحكم:
MapPassengerController - المنطق:
- يتم استخدام
location.getLocation()لجلب موقع الراكب الحالي عند البدء. - يتم تحديد المنطقة الجغرافية (سوريا، مصر، الأردن) عبر دالة
getLocationAreaالتي تفحص وقوع الإحداثيات داخل مضلعات (Polygons) محددة مسبقاً.
- يتم استخدام
ب. السيارات القريبة (Real-time Updates)
- الدالة:
getCarsLocationByPassengerAndReloadMarker. - الآلية: تقوم بطلب API (مثل
getSpeed.php) بناءً على نوع السيارة المختار (Speed, Comfort, Lady). يتم تحديث الـmarkersعلى الخريطة، ويتم استخدام دالة_smoothlyUpdateMarkerلتحريك أيقونة السيارة بسلاسة بدلاً من القفز المفاجئ.
ج. القائمة الجانبية (Drawer)
- المسار:
lib/views/home/map_widget.dart/map_menu_widget.dart - المتحكم:
MyMenuController - الوظيفة: تدير حالة القائمة (مفتوحة/مغلقة) وتوفر روابط لصفحات الملف الشخصي، المحفظة، والسجل.
4. 🚕 دورة طلب الرحلة (Ride Request Flow)
هذا هو الجزء الأكثر تعقيداً في التطبيق، حيث يدار عبر آلة حالة (State Machine).
أ. اختيار الوجهة ورسم المسار
- المسار:
lib/controller/home/map_passenger_controller.dart - الوظيفة:
getDirectionMap. - المنطق:
- يتم إرسال نقطة البداية والنهاية إلى خدمة التوجيه (OSRM/Google).
- يتم استلام نقاط المسار (Polyline Points) وفك تشفيرها في
Isolateمنفصل (decodePolylineIsolate) لتحسين الأداء. - يتم رسم المسار على الخريطة وضبط الكاميرا لتشمل النقطتين.
ب. اختيار نوع السيارة والسعر
- المسار:
lib/views/home/map_widget.dart/car_details_widget_to_go.dart - الآلية: يتم عرض قائمة أنواع السيارات (Fixed Price, Comfort, etc.). عند الاختيار، يتم حساب السعر المتوقع بناءً على المسافة والوقت والتعرفة الخاصة بكل نوع والمخزنة في المتحكم (
totalPassengerSpeed,totalPassengerComfort).
ج. إرسال الطلب (البحث عن سائق)
- الدالة:
startSearchingForDriver. - العمليات:
- تغيير الحالة إلى
RideState.searching. - استدعاء
postRideDetailsToServerلإنشاء سجل الرحلة في قاعدة البيانات. - تشغيل المؤقت
_startMasterTimerالذي يدير دورة البحث. - يتم توسيع نطاق البحث (Radius) تدريجياً (مراحل: 2400م -> 3000م -> 3100م) عبر
_findAndNotifyNearestDrivers.
- تغيير الحالة إلى
د. انتظار السائق
- الواجهة:
SearchingCaptainWindow. - المنطق: يظهر رادار بحث. يتم التحقق دورياً (
Polling) من حالة الرحلة في السيرفر. إذا مر الوقت المحدد (90 ثانية) دون قبول، يظهر خيار "زيادة السعر" (_showIncreaseFeeDialog).
5. 🚘 أثناء الرحلة (Active Ride)
يتم إدارة هذه المرحلة عبر تحديثات الحالة في _handleRideState.
أ. قبول السائق
- الحدث: وصول إشعار FCM أو تغيير الحالة في السيرفر إلى
Apply. - الإجراء: يتم استدعاء
processRideAcceptance.- يتم جلب بيانات السائق وموقعه.
- يتم تفعيل تتبع السائق
startTimerFromDriverToPassengerAfterApplied. - تتغير الواجهة لعرض معلومات السائق والوقت المقدر للوصول.
ب. بدء الرحلة وميزات الأمان
- بدء الرحلة: عند وصول حالة
Begin، يتم استدعاءprocessRideBegin. - SOS: زر الاستغاثة يستدعي
makePhoneCallمع رقم الشرطة أو جهة اتصال الطوارئ المخزنة. - مشاركة الرحلة: الدالة
shareTripWithFamilyتولد رابط تتبع مشفر وترسله عبر واتساب. - تسجيل الصوت: يتم استخدام
AudioRecorderControllerلتسجيل ما يدور في الرحلة لأغراض الأمان.
ج. إلغاء الرحلة
- الدالة:
cancelRide. - المنطق:
- يتم إرسال طلب
cancelللسيرفر لتحديث حالة الرحلة. - يتم إرسال إشعار للسائق بالإلغاء.
- يتم تصفير الواجهة والعودة للخريطة.
- يتم إرسال طلب
6. 🏁 ما بعد الرحلة (Post-Ride)
أ. شاشة الدفع
- المسار:
lib/controller/payment/payment_controller.dart - المنطق:
- يتم الخصم من المحفظة (
addPassengerWallet) أو الدفع النقدي. - يتم التعامل مع بوابات الدفع الخارجية (مثل Paymob, Stripe) إذا اختار العميل الدفع الإلكتروني.
- يتم الخصم من المحفظة (
ب. التقييم
- المسار:
lib/views/Rate/rate_captain.dartوRateController. - الآلية: يقوم الراكب باختيار عدد النجوم وإضافة تعليق. يتم إرسال البيانات عبر
addRateToDriver.
ج. تقديم الشكاوى
- المسار:
lib/views/home/profile/complaint_page.dart - المتحكم:
ComplaintController. - الميزة: يمكن للراكب تسجيل رسالة صوتية وإرفاقها مع الشكوى، ثم يتم إرسالها للسيرفر عبر
submitComplaintToServer.
7. ⚙️ الإعدادات والملف الشخصي
أ. تعديل البيانات
- المسار:
lib/views/home/profile/passenger_profile_page.dart. - المتحكم:
ProfileController. - يسمح بتعديل الاسم، الجنس، ورقم الطوارئ.
ب. المحفظة
- المسار:
lib/views/home/my_wallet/passenger_wallet.dart. - يعرض الرصيد الحالي وسجل المعاملات (
PassengerWalletHistoryController).
ج. اللغة
- المتحكم:
LocaleController. - يقوم بتغيير لغة التطبيق وتحديث
Get.updateLocaleوحفظ التفضيل في التخزين المحلي.