Skip to content

Commit

Permalink
feat: Add a set of methods to receive notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
naipaka committed Aug 15, 2024
1 parent 7a50c06 commit e0c459f
Show file tree
Hide file tree
Showing 4 changed files with 353 additions and 3 deletions.
2 changes: 1 addition & 1 deletion packages/altfire_messenger/lib/altfire_messenger.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
library;

export 'package:firebase_messaging/firebase_messaging.dart'
show AuthorizationStatus;
show AuthorizationStatus, RemoteMessage;

export 'src/messenger.dart';
170 changes: 169 additions & 1 deletion packages/altfire_messenger/lib/src/messenger.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import 'dart:convert';

import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:timezone/data/latest.dart' as tz;

/// A class that wraps package for sending notifications and messages.
/// Its role is to "send necessary notifications and messages to the user".
Expand All @@ -8,10 +13,14 @@ import 'package:firebase_messaging/firebase_messaging.dart';
class Messenger {
Messenger({
FirebaseMessaging? messaging,
}) : _messaging = messaging ?? FirebaseMessaging.instance;
FlutterLocalNotificationsPlugin? notifications,
}) : _messaging = messaging ?? FirebaseMessaging.instance,
_notifications = notifications ?? FlutterLocalNotificationsPlugin();

final FirebaseMessaging _messaging;

final FlutterLocalNotificationsPlugin _notifications;

/// Requests notification permissions.
///
/// On iOS, sets the foreground notification presentation options using
Expand All @@ -31,4 +40,163 @@ class Messenger {
final settings = await _messaging.requestPermission();
return settings;
}

/// Returns the current notification settings.
Future<NotificationSettings> getNotificationSettings() {
return _messaging.getNotificationSettings();
}

/// Receives messages when the app is in the foreground.
///
/// Listens to incoming messages and triggers the callback with new data.
void onForegroundMessage(ValueChanged<RemoteMessage> onData) {
FirebaseMessaging.onMessage.listen(onData);
}

/// Activated when a message is tapped and the app is opened.
///
/// This listener handles the event when the app is brought to foreground via a notification tap.
void onMessageOpenedApp(ValueChanged<RemoteMessage> onData) {
FirebaseMessaging.onMessageOpenedApp.listen(onData);
}

/// Handles receiving messages when the app is in the background.
///
/// Must provide a function to process the message data.
void onBackgroundMessage(
Future<void> Function(RemoteMessage message) handler,
) {
FirebaseMessaging.onBackgroundMessage(handler);
}

/// Returns the initial message when the app is opened from a terminated state.
///
/// This is useful for handling messages that were received while the app was closed.
Future<RemoteMessage?> getInitialMessage() {
return _messaging.getInitialMessage();
}

/// Returns the latest FCM token that can be used for device specific messages.
Future<String?> getToken() {
return _messaging.getToken();
}

/// Listens for token updates and triggers the callback with the new token.
///
/// This is important for maintaining a current token for receiving messages.
void onTokenRefresh(ValueChanged<String> onData) {
_messaging.onTokenRefresh.listen(onData);
}

/// Subscribes the device to a specific topic for grouped messages.
Future<void> subscribeToTopic(String topic) {
return _messaging.subscribeToTopic(topic);
}

/// Initializes local notifications settings for Android and iOS.
///
/// Parameters allow for setting default icon and request permissions.
/// Callbacks can be set for handling notification taps.
Future<void> initializeNotifications({
required String androidDefaultIcon,
bool requestAlertPermission = false,
bool requestBadgePermission = false,
bool requestSoundPermission = false,
void Function(int, String?, String?, String?)?
onDidReceiveLocalNotification,
ValueChanged<Map<String, Object?>>? onNotificationTapped,
}) async {
tz.initializeTimeZones();

final androidInitializationSettings =
AndroidInitializationSettings(androidDefaultIcon);

final iOSInitializationSettings = DarwinInitializationSettings(
requestAlertPermission: requestAlertPermission,
requestBadgePermission: requestBadgePermission,
requestSoundPermission: requestSoundPermission,
// This property is only applicable to iOS versions older than 10.
onDidReceiveLocalNotification: onDidReceiveLocalNotification,
);

final macOSInitializationSettings = DarwinInitializationSettings(
requestAlertPermission: requestAlertPermission,
requestBadgePermission: requestBadgePermission,
requestSoundPermission: requestSoundPermission,
);

await _notifications.initialize(
// Settings for how the app appears when it is in the foreground
InitializationSettings(
android: androidInitializationSettings,
iOS: iOSInitializationSettings,
macOS: macOSInitializationSettings,
),
onDidReceiveNotificationResponse: (response) {
onForegroundNotificationTapped(
notificationResponse: response,
onNotificationTapped: onNotificationTapped,
);
},
);
}

/// Executes when a notification is tapped while the app is in the foreground.
///
/// Parses the payload to JSON and triggers the provided callback with the data.
@visibleForTesting
Future<void> onForegroundNotificationTapped({
required NotificationResponse notificationResponse,
ValueChanged<Map<String, Object?>>? onNotificationTapped,
}) async {
final payload = notificationResponse.payload;
debugPrint('Notification tapped in foreground. payload: $payload');
if (payload != null && onNotificationTapped != null) {
final jsonMap = jsonDecode(payload) as Map<String, dynamic>;
onNotificationTapped(jsonMap);
}
}

/// Displays a notification with customizable settings.
///
/// Can specify the notification channel, description, icon, and color among others.
Future<void> showNotification({
required String channelId,
required String channelName,
required String channelDescription,
required String icon,
required Color color,
required int id,
String? title,
String? body,
Map<String, dynamic>? payloadJsonMap,
}) async {
final androidPlatformChannelSpecifics = AndroidNotificationDetails(
channelId,
channelName,
channelDescription: channelDescription,
icon: icon,
importance: Importance.max,
priority: Priority.high,
color: color,
);

final iOSPlatformChannelSpecifics = DarwinNotificationDetails();

final macOSPlatformChannelSpecifics = DarwinNotificationDetails();

final platformChannelSpecifics = NotificationDetails(
android: androidPlatformChannelSpecifics,
iOS: iOSPlatformChannelSpecifics,
macOS: macOSPlatformChannelSpecifics,
);

await _notifications.show(
id,
title,
body,
platformChannelSpecifics,
payload: jsonEncode(payloadJsonMap),
);
}
}
2 changes: 2 additions & 0 deletions packages/altfire_messenger/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ dependencies:
firebase_messaging: ^15.0.3
flutter:
sdk: flutter
flutter_local_notifications: ^17.2.2
timezone: ^0.9.4

dev_dependencies:
altive_lints: ^1.10.0
Expand Down
Loading

0 comments on commit e0c459f

Please sign in to comment.