Files
tripz-llc/apps/driver/lib/features/trip/data/fcm_service.dart
T

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 (_) {}
}
}