flutter-freaccess-hub/lib/backend/push_notification/pushNotificationService.dart

255 lines
8.4 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'package:f_r_e_hub/app_state.dart';
import 'package:f_r_e_hub/backend/api_requests/api_calls.dart';
import 'package:flutter/material.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:rxdart/rxdart.dart';
import 'package:f_r_e_hub/components/templates_components/visit_request_template_component/visit_request_template_component_widget.dart';
class PushNotificationService {
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
final Subject<RemoteMessage> _onMessage = BehaviorSubject<RemoteMessage>();
final BehaviorSubject<BuildContext> _context =
BehaviorSubject<BuildContext>();
PushNotificationService() {
_initializeLocalNotifications(_context);
}
Future<void> initialize(BuildContext context) async {
_context.add(context);
await _requestPermissions();
_listenToForegroundMessages(context);
_listenToBackgroundMessages();
_listenToNotificationClicks(context);
await _updateDeviceToken();
}
Future<void> _requestPermissions() async {
NotificationSettings settings = await _firebaseMessaging.requestPermission(
alert: true,
badge: true,
sound: true,
);
if (settings.authorizationStatus == AuthorizationStatus.authorized) {
debugPrint('User granted permission');
} else {
debugPrint('User declined or has not accepted permission');
}
}
Map<String, dynamic> validJsonFromString(String? string) {
// Switch(string != null || string.isNotEmpty) {
// case true:
// debugPrint()
// break;
// }
String stringValidate = string!
.replaceAllMapped(RegExp(r'(\w+):'),
(match) => '"${match[1]}":') // Enclose keys in double quotes
.replaceAllMapped(RegExp(r':\s*(\w+)'), (match) => ': "${match[1]}"');
Map<String, dynamic> json = jsonDecode(stringValidate);
return json;
}
void _initializeLocalNotifications(
BehaviorSubject<BuildContext> context) async {
while (context.valueOrNull == null) {
await Future.delayed(Duration(milliseconds: 100));
}
var initializationSettingsAndroid =
AndroidInitializationSettings('mipmap/ic_fre_black');
var initializationSettingsIOS = DarwinInitializationSettings(
requestAlertPermission: true,
requestBadgePermission: true,
requestSoundPermission: true,
);
var initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsIOS,
);
_flutterLocalNotificationsPlugin.initialize(
initializationSettings,
onDidReceiveNotificationResponse: (NotificationResponse response) async {
debugPrint('Response payload:${response.payload}');
if (response.payload != null) {
// Preprocess the payload to ensure it's in a valid JSON format
String validJsonPayload = response.payload!
.replaceAllMapped(RegExp(r'(\w+):'),
(match) => '"${match[1]}":') // Enclose keys in double quotes
.replaceAllMapped(
RegExp(r':\s*(\w+)'),
(match) =>
': "${match[1]}"'); // Enclose string values in double quotes
try {
Map<String, dynamic> message = jsonDecode(validJsonPayload);
debugPrint('Notification payload: $message');
_handleNotificationClick(message);
} catch (e) {
debugPrint('Error decoding notification payload: $e');
}
}
},
);
_createNotificationChannel();
}
void _createNotificationChannel() {
_flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(
AndroidNotificationChannel(
'channelID',
'channelName',
description: 'Channel Description',
importance: Importance.max,
),
);
}
void _listenToForegroundMessages(BuildContext context) {
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
debugPrint('Got a message whilst in the foreground!');
debugPrint('Message data: ${message.toMap()}');
_onMessage.add(message);
_showNotification(message);
});
}
void _listenToBackgroundMessages() {
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
}
void _listenToNotificationClicks(BuildContext context) {
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
debugPrint('Notification clicked!');
_onMessage.add(message);
NotificationHandler().handleMessage(message.data, context);
});
}
Future<void> _updateDeviceToken() async {
ApiCallResponse? updToken;
///
NotificationSettings settings =
await _firebaseMessaging.requestPermission();
if (settings.authorizationStatus == AuthorizationStatus.authorized) {
debugPrint('User granted permission');
String? apnsToken = await _firebaseMessaging.getAPNSToken();
if (apnsToken != null) {
debugPrint('APNS Token: $apnsToken');
} else {
debugPrint('Failed to get APNS token');
}
} else {
debugPrint('User declined or has not accepted permission');
}
String? deviceToken = await FirebaseMessaging.instance.getToken();
FFAppState().token = deviceToken!;
updToken = await PhpGroup.updToken.call(
token: FFAppState().token,
devid: FFAppState().devUUID,
useruuid: FFAppState().userUUID,
);
if (PhpGroup.updToken.error(
(updToken.jsonBody ?? ''),
) ==
false) {
debugPrint('Token atualizado com sucesso');
debugPrint("Device Token: $deviceToken");
} else {
debugPrint('Erro ao atualizar token');
}
debugPrint('Push Messaging token: $deviceToken');
}
void _showNotification(RemoteMessage message) async {
var androidDetails = AndroidNotificationDetails(
'channelID',
'channelName',
channelDescription: 'Channel Description',
importance: Importance.max,
priority: Priority.high,
);
var iOSDetails = DarwinNotificationDetails();
var generalNotificationDetails =
NotificationDetails(android: androidDetails, iOS: iOSDetails);
await _flutterLocalNotificationsPlugin.show(
message.hashCode,
message.notification?.title,
message.notification?.body,
generalNotificationDetails,
payload: message.data.toString(),
);
}
_handleNotificationClick(Map<String, dynamic> payload) {
switch (payload.isNotEmpty) {
case true:
// Print the 'data' property
debugPrint('Notification payload: $payload');
// Handle the message data as needed
NotificationHandler().handleMessage(payload, _context.value);
// Access the 'data' property of 'RemoteMessage'
case false:
debugPrint('Notification payload is empty');
// Handle the message notification as needed
break;
}
}
static Future<void> _firebaseMessagingBackgroundHandler(
RemoteMessage message) async {
debugPrint('Handling a background message: ${message.messageId}');
}
}
class NotificationHandler {
void handleMessage(Map<String, dynamic> message, BuildContext context) {
debugPrint('Notification Received!');
message.forEach((key, value) {
debugPrint('$key: $value');
});
switch (message['type']) {
case 'visit_request':
_showVisitRequestDialog(message, context);
break;
case 'visit_response':
debugPrint('visit_response');
break;
default:
debugPrint('Notification type not recognized');
}
}
void _showVisitRequestDialog(
Map<String, dynamic> message, BuildContext context) {
showDialog(
context: context,
builder: (BuildContext context) {
return Dialog(
backgroundColor: Colors.transparent,
child: VisitRequestTemplateComponentWidget(
name: message['nome'] ?? 'Unknown',
reason: message['motivo'] ?? 'Unknown',
message: message['mensagem'] ?? 'Unknown',
document: message['documento'] ?? 'Unknown',
),
);
},
);
}
}