103 lines
2.9 KiB
Dart
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';
|
|
}
|