Skip to content

Commit 43917e3

Browse files
committed
feat: add process notification action and update handle notification
1 parent ff63c3d commit 43917e3

File tree

3 files changed

+60
-10
lines changed

3 files changed

+60
-10
lines changed

lib/action/notification_action.dart

+44
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,47 @@ class GetDeviceTokenAction extends EnsembleAction {
4545
}
4646
}
4747
}
48+
49+
class ProcessNotificationAction extends EnsembleAction {
50+
ProcessNotificationAction(
51+
{super.initiator, required this.onNotification, this.onNoNotification});
52+
53+
EnsembleAction? onNotification;
54+
EnsembleAction? onNoNotification;
55+
56+
factory ProcessNotificationAction.fromMap({dynamic payload}) {
57+
if (payload is Map) {
58+
EnsembleAction? onNotification =
59+
EnsembleAction.fromYaml(payload['onNotification']);
60+
if (onNotification == null) {
61+
throw LanguageError(
62+
"onNotification() is required for Process Notification Action");
63+
}
64+
return ProcessNotificationAction(
65+
onNotification: onNotification,
66+
onNoNotification: EnsembleAction.fromYaml(payload['onError']));
67+
}
68+
throw LanguageError("Missing inputs for getDeviceToken.}");
69+
}
70+
71+
@override
72+
Future execute(BuildContext context, ScopeManager scopeManager) async {
73+
final remoteNotification = await NotificationManager().getInitialMessage();
74+
final data = {
75+
'notification': {
76+
'title': remoteNotification?.notification?.title,
77+
'body': remoteNotification?.notification?.body,
78+
},
79+
'data': remoteNotification?.data,
80+
};
81+
if (remoteNotification != null && onNotification != null) {
82+
return ScreenController().executeAction(context, onNotification!,
83+
event: EnsembleEvent(initiator, data: data));
84+
}
85+
if (remoteNotification == null && onNoNotification != null) {
86+
return ScreenController().executeAction(context, onNoNotification!,
87+
event: EnsembleEvent(initiator,
88+
error: 'Unable to get the remote notification message.'));
89+
}
90+
}
91+
}

lib/framework/action.dart

+3
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,7 @@ enum ActionType {
945945
saveKeychain,
946946
clearKeychain,
947947
getDeviceToken,
948+
processNotification,
948949
receiveIntent,
949950
connectSocket,
950951
disconnectSocket,
@@ -1074,6 +1075,8 @@ abstract class EnsembleAction {
10741075
return RateAppAction.from(payload: payload);
10751076
} else if (actionType == ActionType.getDeviceToken) {
10761077
return GetDeviceTokenAction.fromMap(payload: payload);
1078+
} else if (actionType == ActionType.processNotification) {
1079+
return ProcessNotificationAction.fromMap(payload: payload);
10771080
} else if (actionType == ActionType.openPlaidLink) {
10781081
return PlaidLinkAction.fromYaml(initiator: initiator, payload: payload);
10791082
} else if (actionType == ActionType.openAppSettings) {

lib/framework/notification_manager.dart

+13-10
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ class NotificationManager {
3737
}
3838
}
3939

40+
// Returns the remote notification only when the app is opened from terminated state otherwise it'll be null
41+
Future<RemoteMessage?> getInitialMessage() {
42+
return FirebaseMessaging.instance.getInitialMessage();
43+
}
44+
4045
/// get the device token. This guarantees the token (if available)
4146
/// is the latest correct token
4247
Future<String?> getDeviceToken() async {
@@ -101,8 +106,8 @@ class NotificationManager {
101106
}
102107

103108
void initGetInitialMessage() {
104-
// This is called when the user taps on the notification and the app is opened from the terminated state
105-
FirebaseMessaging.instance.getInitialMessage().then((message) {
109+
// Returns the remote notification only when the app is opened from the terminated state or else it'll be null
110+
getInitialMessage().then((message) {
106111
if (message == null) return;
107112

108113
Ensemble.externalDataContext.addAll({
@@ -120,17 +125,15 @@ class NotificationManager {
120125

121126
Future<void> _handleNotification() async {
122127
Map<String, dynamic>? messageData = Ensemble.externalDataContext['data'];
123-
if (messageData?['screenId'] != null ||
124-
messageData?['screenName'] != null) {
125-
ScreenController().navigateToScreen(
126-
Utils.globalAppKey.currentContext!,
128+
// If there is a screen, it navigates to that page
129+
// or else it'll open the app with the root screen and clears all the previous screens
130+
final screenNotFound =
131+
messageData?['screenId'] == null && messageData?['screenName'] == null;
132+
ScreenController().navigateToScreen(Utils.globalAppKey.currentContext!,
127133
screenId: messageData!['screenId'],
128134
screenName: messageData['screenName'],
129135
pageArgs: messageData,
130-
);
131-
} else {
132-
log('No screenId nor screenName provided on the notification. Ignoring ...');
133-
}
136+
routeOption: screenNotFound ? RouteOption.clearAllScreens : null);
134137
}
135138
}
136139

0 commit comments

Comments
 (0)