90 lines
2.6 KiB
Dart
90 lines
2.6 KiB
Dart
import 'dart:async';
|
|
import 'dart:io' show Platform;
|
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
|
import '../../../core/api/api_client.dart';
|
|
import '../../../core/di.dart';
|
|
import 'trip_event_merger.dart';
|
|
|
|
/// القناة الثانية للزمن الحقيقي — FCM data-message (docs/23 §15).
|
|
///
|
|
/// للسائق: يستقبل عروض الرحلات (trip:offer) وتحديثات الحالة
|
|
/// عبر FCM كطبقة احتياطية للسوكت. أيّهما يسبق يفوز —
|
|
/// الـ merger يتكفّل بالتصفية الصامتة.
|
|
class DriverFcmService {
|
|
final DriverTripEventMerger _merger;
|
|
StreamSubscription<RemoteMessage>? _onMessageSub;
|
|
StreamSubscription<RemoteMessage>? _onOpenSub;
|
|
|
|
DriverFcmService(this._merger);
|
|
|
|
Future<void> init() async {
|
|
final messaging = FirebaseMessaging.instance;
|
|
|
|
await messaging.requestPermission(
|
|
alert: false,
|
|
badge: false,
|
|
sound: false,
|
|
provisional: false,
|
|
);
|
|
|
|
final token = await messaging.getToken();
|
|
if (token != null) {
|
|
_registerToken(token);
|
|
}
|
|
messaging.onTokenRefresh.listen(_registerToken);
|
|
|
|
_onMessageSub = FirebaseMessaging.onMessage.listen(_handleMessage);
|
|
_onOpenSub = FirebaseMessaging.onMessageOpenedApp.listen(_handleMessage);
|
|
}
|
|
|
|
void dispose() {
|
|
_onMessageSub?.cancel();
|
|
_onOpenSub?.cancel();
|
|
}
|
|
|
|
void _handleMessage(RemoteMessage message) {
|
|
final data = message.data;
|
|
final type = data['type'] as String?;
|
|
final tripId = data['tripId'] as String?;
|
|
|
|
if (type == null || tripId == null || tripId.isEmpty) return;
|
|
|
|
switch (type) {
|
|
case 'trip_offer':
|
|
// عرض رحلة وارد — سيُعالج عبر OffersBloc.
|
|
_merger.addNewTrip(tripId);
|
|
break;
|
|
case 'trip_offer_taken':
|
|
// العرض تم قبوله من سائق آخر.
|
|
_merger.addOfferTaken(tripId);
|
|
break;
|
|
default:
|
|
// تحديث حالة رحلة نشطة.
|
|
final status = type.startsWith('trip_') ? type.substring(5) : null;
|
|
if (status == null) return;
|
|
|
|
final extra = Map<String, dynamic>.from(data)
|
|
..remove('type')
|
|
..remove('tripId')
|
|
..remove('title')
|
|
..remove('body');
|
|
|
|
_merger.addUpdate(DriverTripUpdate(
|
|
tripId: tripId,
|
|
status: status,
|
|
extra: extra,
|
|
));
|
|
}
|
|
}
|
|
|
|
static Future<void> _registerToken(String token) async {
|
|
try {
|
|
final api = getIt<ApiClient>();
|
|
await api.dio.post('/notifications/token', data: {
|
|
'token': token,
|
|
'platform': Platform.isIOS ? 'ios' : 'android',
|
|
});
|
|
} catch (_) {}
|
|
}
|
|
}
|