Files
2026-10-16 01:25:50 +05:30

103 lines
2.9 KiB
Dart

import 'dart:async';
import 'dart:io';
import 'package:firebase_messaging/firebase_messaging.dart';
typedef FcmTokenCallback = Future<void> Function(String token, String platform);
class PushService {
PushService({required this.firebaseReady});
final bool firebaseReady;
final _subscriptions = <StreamSubscription<dynamic>>[];
bool _listening = false;
Future<void> listen({
required void Function(String ticketId) onOpenTicket,
required void Function(RemoteMessage message) onForegroundMessage,
required FcmTokenCallback onToken,
required bool Function() isSignedIn,
}) async {
if (!firebaseReady || _listening) {
return;
}
_listening = true;
_subscriptions
..add(
FirebaseMessaging.instance.onTokenRefresh.listen((token) async {
try {
if (!isSignedIn()) {
return;
}
final settings = await FirebaseMessaging.instance
.getNotificationSettings();
if (!_allowsNotifications(settings.authorizationStatus)) {
return;
}
await onToken(token, _platform);
} on Object {
// Keep the previous registration when a token refresh cannot be saved.
}
}),
)
..add(FirebaseMessaging.onMessage.listen(onForegroundMessage))
..add(
FirebaseMessaging.onMessageOpenedApp.listen((message) {
final ticketId = _ticketId(message);
if (ticketId != null) {
onOpenTicket(ticketId);
}
}),
);
try {
final initial = await FirebaseMessaging.instance.getInitialMessage();
if (initial != null) {
final ticketId = _ticketId(initial);
if (ticketId != null) {
onOpenTicket(ticketId);
}
}
} on Object {
// Opening from a notification can wait until the next tap.
}
}
Future<void> register(FcmTokenCallback onToken) async {
if (!firebaseReady) {
return;
}
try {
final settings = await FirebaseMessaging.instance.requestPermission(
alert: true,
badge: true,
sound: true,
);
if (!_allowsNotifications(settings.authorizationStatus)) {
return;
}
final token = await FirebaseMessaging.instance.getToken();
if (token == null || token.isEmpty) {
return;
}
await onToken(token, _platform);
} on Object {
// Denied permission or a missing Firebase file should not block the inbox.
}
}
String? _ticketId(RemoteMessage message) {
final value = message.data['ticketId'];
if (value is String && value.isNotEmpty) {
return value;
}
return null;
}
bool _allowsNotifications(AuthorizationStatus status) {
return status == AuthorizationStatus.authorized ||
status == AuthorizationStatus.provisional;
}
String get _platform => Platform.isIOS ? 'ios' : 'android';
}