react-native-notification-sdk 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3082 -0
- package/dist/NotificationSDK.d.ts +6 -0
- package/dist/NotificationSDK.d.ts.map +1 -0
- package/dist/background/BackgroundHandler.d.ts +7 -0
- package/dist/background/BackgroundHandler.d.ts.map +1 -0
- package/dist/background/registerBackgroundHandler.d.ts +5 -0
- package/dist/background/registerBackgroundHandler.d.ts.map +1 -0
- package/dist/constants/SDK.d.ts +2 -0
- package/dist/constants/SDK.d.ts.map +1 -0
- package/dist/core/NotificationManager.d.ts +28 -0
- package/dist/core/NotificationManager.d.ts.map +1 -0
- package/dist/core/NotificationSDK.d.ts +25 -0
- package/dist/core/NotificationSDK.d.ts.map +1 -0
- package/dist/core/SDKContainer.d.ts +16 -0
- package/dist/core/SDKContainer.d.ts.map +1 -0
- package/dist/errors/FirebaseInitializationError.d.ts +5 -0
- package/dist/errors/FirebaseInitializationError.d.ts.map +1 -0
- package/dist/errors/InvalidNotificationError.d.ts +5 -0
- package/dist/errors/InvalidNotificationError.d.ts.map +1 -0
- package/dist/errors/NotifeeInitializationError.d.ts +5 -0
- package/dist/errors/NotifeeInitializationError.d.ts.map +1 -0
- package/dist/errors/NotificationSDKError.d.ts +4 -0
- package/dist/errors/NotificationSDKError.d.ts.map +1 -0
- package/dist/errors/PermissionDeniedError.d.ts +5 -0
- package/dist/errors/PermissionDeniedError.d.ts.map +1 -0
- package/dist/errors/SDKNotInitializedError.d.ts +5 -0
- package/dist/errors/SDKNotInitializedError.d.ts.map +1 -0
- package/dist/errors/index.d.ts +7 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/events/EventBus.d.ts +11 -0
- package/dist/events/EventBus.d.ts.map +1 -0
- package/dist/firebase/FirebaseListener.d.ts +28 -0
- package/dist/firebase/FirebaseListener.d.ts.map +1 -0
- package/dist/firebase/FirebaseService.d.ts +24 -0
- package/dist/firebase/FirebaseService.d.ts.map +1 -0
- package/dist/index.cjs +858 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +228 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +853 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/IEventManager.d.ts +18 -0
- package/dist/interfaces/IEventManager.d.ts.map +1 -0
- package/dist/interfaces/ILogger.d.ts +6 -0
- package/dist/interfaces/ILogger.d.ts.map +1 -0
- package/dist/logger/Logger.d.ts +9 -0
- package/dist/logger/Logger.d.ts.map +1 -0
- package/dist/logging/ConsoleLogger.d.ts +9 -0
- package/dist/logging/ConsoleLogger.d.ts.map +1 -0
- package/dist/mappers/NotificationMapper.d.ts +14 -0
- package/dist/mappers/NotificationMapper.d.ts.map +1 -0
- package/dist/notifee/NotifeeService.d.ts +52 -0
- package/dist/notifee/NotifeeService.d.ts.map +1 -0
- package/dist/permissions/PermissionService.d.ts +35 -0
- package/dist/permissions/PermissionService.d.ts.map +1 -0
- package/dist/sdk/NotificationContainer.d.ts +16 -0
- package/dist/sdk/NotificationContainer.d.ts.map +1 -0
- package/dist/sdk/NotificationManager.d.ts +30 -0
- package/dist/sdk/NotificationManager.d.ts.map +1 -0
- package/dist/sdk/NotificationSDK.d.ts +29 -0
- package/dist/sdk/NotificationSDK.d.ts.map +1 -0
- package/dist/types/AndroidNotificationOptions.d.ts +12 -0
- package/dist/types/AndroidNotificationOptions.d.ts.map +1 -0
- package/dist/types/DisplayNotification.d.ts +37 -0
- package/dist/types/DisplayNotification.d.ts.map +1 -0
- package/dist/types/IOSNotificationOptions.d.ts +6 -0
- package/dist/types/IOSNotificationOptions.d.ts.map +1 -0
- package/dist/types/NotificationAction.d.ts +9 -0
- package/dist/types/NotificationAction.d.ts.map +1 -0
- package/dist/types/NotificationChannel.d.ts +11 -0
- package/dist/types/NotificationChannel.d.ts.map +1 -0
- package/dist/types/NotificationConfig.d.ts +47 -0
- package/dist/types/NotificationConfig.d.ts.map +1 -0
- package/dist/types/NotificationEvents.d.ts +30 -0
- package/dist/types/NotificationEvents.d.ts.map +1 -0
- package/dist/types/NotificationPayload.d.ts +15 -0
- package/dist/types/NotificationPayload.d.ts.map +1 -0
- package/dist/types/NotificationSDKStatus.d.ts +11 -0
- package/dist/types/NotificationSDKStatus.d.ts.map +1 -0
- package/dist/types/NotificationTrigger.d.ts +20 -0
- package/dist/types/NotificationTrigger.d.ts.map +1 -0
- package/dist/types/PermissionStatus.d.ts +2 -0
- package/dist/types/PermissionStatus.d.ts.map +1 -0
- package/dist/types/ScheduledNotification.d.ts +6 -0
- package/dist/types/ScheduledNotification.d.ts.map +1 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/utils/NotificationMapper.d.ts +14 -0
- package/dist/utils/NotificationMapper.d.ts.map +1 -0
- package/dist/validators/DisplayNotificationValidator.d.ts +5 -0
- package/dist/validators/DisplayNotificationValidator.d.ts.map +1 -0
- package/dist/validators/NotificationActionValidator.d.ts +5 -0
- package/dist/validators/NotificationActionValidator.d.ts.map +1 -0
- package/dist/validators/NotificationChannelValidator.d.ts +5 -0
- package/dist/validators/NotificationChannelValidator.d.ts.map +1 -0
- package/dist/validators/ScheduledNotificationValidator.d.ts +5 -0
- package/dist/validators/ScheduledNotificationValidator.d.ts.map +1 -0
- package/dist/validators/ValidationAssertions.d.ts +6 -0
- package/dist/validators/ValidationAssertions.d.ts.map +1 -0
- package/package.json +77 -0
- package/plugins/android/withMaven.js +22 -0
- package/plugins/app.plugin.js +7 -0
- package/plugins/ios/withModularHeaders.js +16 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,858 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var reactNative = require('react-native');
|
|
6
|
+
var messaging = require('@react-native-firebase/messaging');
|
|
7
|
+
var notifee = require('@notifee/react-native');
|
|
8
|
+
|
|
9
|
+
class NotificationSDKError extends Error {
|
|
10
|
+
constructor(message) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.name = "NotificationSDKError";
|
|
13
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
class FirebaseInitializationError extends NotificationSDKError {
|
|
18
|
+
constructor() {
|
|
19
|
+
super("Firebase has not been initialized.");
|
|
20
|
+
this.name = "FirebaseInitializationError";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
class SDKNotInitializedError extends NotificationSDKError {
|
|
25
|
+
constructor() {
|
|
26
|
+
super("Notification SDK must be initialized before calling this method.");
|
|
27
|
+
this.name = "SDKNotInitializedError";
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
class EventBus {
|
|
32
|
+
listeners = {};
|
|
33
|
+
on(event, listener) {
|
|
34
|
+
if (!this.listeners[event]) {
|
|
35
|
+
//@ts-ignore
|
|
36
|
+
this.listeners[event] = new Set();
|
|
37
|
+
}
|
|
38
|
+
this.listeners[event].add(listener);
|
|
39
|
+
return () => {
|
|
40
|
+
this.off(event, listener);
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
off(event, listener) {
|
|
44
|
+
this.listeners[event]?.delete(listener);
|
|
45
|
+
}
|
|
46
|
+
emit(event, payload) {
|
|
47
|
+
this.listeners[event]?.forEach((listener) => listener(payload));
|
|
48
|
+
}
|
|
49
|
+
removeAll() {
|
|
50
|
+
Object.values(this.listeners).forEach((set) => set?.clear());
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
class NotificationMapper {
|
|
55
|
+
/**
|
|
56
|
+
* Converts a Firebase RemoteMessage into the SDK NotificationPayload.
|
|
57
|
+
*/
|
|
58
|
+
static fromRemoteMessage(remoteMessage) {
|
|
59
|
+
const rawData = remoteMessage.data ?? {};
|
|
60
|
+
const data = Object.keys(rawData).reduce((acc, key) => {
|
|
61
|
+
const value = rawData[key];
|
|
62
|
+
acc[key] =
|
|
63
|
+
typeof value === "string"
|
|
64
|
+
? value
|
|
65
|
+
: value == null
|
|
66
|
+
? ""
|
|
67
|
+
: JSON.stringify(value);
|
|
68
|
+
return acc;
|
|
69
|
+
}, {});
|
|
70
|
+
return {
|
|
71
|
+
id: remoteMessage.messageId ?? "",
|
|
72
|
+
title: remoteMessage.notification?.title ?? data.title,
|
|
73
|
+
body: remoteMessage.notification?.body ?? data.body,
|
|
74
|
+
data,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Converts NotificationPayload into DisplayNotification.
|
|
79
|
+
*/
|
|
80
|
+
static toDisplayNotification(notification) {
|
|
81
|
+
return {
|
|
82
|
+
id: notification.id,
|
|
83
|
+
title: notification.title ?? "",
|
|
84
|
+
body: notification.body ?? "",
|
|
85
|
+
data: notification.data,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const SDK_VERSION = "0.0.1";
|
|
91
|
+
|
|
92
|
+
class NotificationManager {
|
|
93
|
+
container;
|
|
94
|
+
eventBus;
|
|
95
|
+
constructor(container, eventBus) {
|
|
96
|
+
this.container = container;
|
|
97
|
+
this.eventBus = eventBus;
|
|
98
|
+
}
|
|
99
|
+
initialized = false;
|
|
100
|
+
async initializeFirebase() {
|
|
101
|
+
await this.container.firebaseService.initialize((token) => {
|
|
102
|
+
this.eventBus.emit("tokenRefresh", {
|
|
103
|
+
token,
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
this.container.firebaseListener.start();
|
|
107
|
+
}
|
|
108
|
+
registerListeners() {
|
|
109
|
+
this.container.firebaseListener.onMessage(async (notification) => {
|
|
110
|
+
this.eventBus.emit("notificationReceived", {
|
|
111
|
+
notification,
|
|
112
|
+
});
|
|
113
|
+
if (this.container.config.foreground?.displayNotifications) {
|
|
114
|
+
await this.container.notifeeService.displayNotification(NotificationMapper.toDisplayNotification(notification));
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
this.container.notifeeService.onNotificationPressed((notification) => {
|
|
118
|
+
this.container.logger.log("Local notification opened.");
|
|
119
|
+
this.eventBus.emit("notificationOpened", {
|
|
120
|
+
notification,
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
this.container.notifeeService.onNotificationDismissed((notification) => {
|
|
124
|
+
this.container.logger.log("Local notification dismissed.");
|
|
125
|
+
this.eventBus.emit("notificationDismissed", {
|
|
126
|
+
notification,
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
this.container.notifeeService.onNotificationActionPressed((notification, actionId, input) => {
|
|
130
|
+
this.eventBus.emit("notificationActionPressed", {
|
|
131
|
+
notification,
|
|
132
|
+
actionId,
|
|
133
|
+
input,
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
async initialize() {
|
|
138
|
+
if (this.initialized) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
this.container.logger.log("Initializing SDK...");
|
|
142
|
+
this.registerListeners();
|
|
143
|
+
await this.container.notifeeService.initialize(this.container.config.channels);
|
|
144
|
+
if (this.container.config.ios?.requestPermissionOnLaunch) {
|
|
145
|
+
await this.requestPermission();
|
|
146
|
+
}
|
|
147
|
+
await this.initializeFirebase();
|
|
148
|
+
this.eventBus.emit("initialized", undefined);
|
|
149
|
+
this.container.logger.log("SDK initialized.");
|
|
150
|
+
this.initialized = true;
|
|
151
|
+
}
|
|
152
|
+
async requestPermission() {
|
|
153
|
+
const status = await this.container.permissionService.requestPermission();
|
|
154
|
+
const granted = this.container.permissionService.isGranted(status);
|
|
155
|
+
this.eventBus.emit("permissionChanged", {
|
|
156
|
+
status,
|
|
157
|
+
granted,
|
|
158
|
+
});
|
|
159
|
+
if (granted) {
|
|
160
|
+
await this.initializeFirebase();
|
|
161
|
+
}
|
|
162
|
+
return status;
|
|
163
|
+
}
|
|
164
|
+
async getPermissionStatus() {
|
|
165
|
+
return this.container.permissionService.getPermissionStatus();
|
|
166
|
+
}
|
|
167
|
+
async getToken() {
|
|
168
|
+
await this.initializeFirebase();
|
|
169
|
+
const token = await this.container.firebaseService.getToken();
|
|
170
|
+
this.eventBus.emit("tokenGenerated", { token });
|
|
171
|
+
return token;
|
|
172
|
+
}
|
|
173
|
+
async deleteToken() {
|
|
174
|
+
await this.container.firebaseService.deleteToken();
|
|
175
|
+
}
|
|
176
|
+
async displayNotification(notification) {
|
|
177
|
+
await this.container.notifeeService.displayNotification(notification);
|
|
178
|
+
}
|
|
179
|
+
async cancelNotification(id) {
|
|
180
|
+
await this.container.notifeeService.cancelNotification(id);
|
|
181
|
+
}
|
|
182
|
+
async cancelAllNotifications() {
|
|
183
|
+
await this.container.notifeeService.cancelAllNotifications();
|
|
184
|
+
}
|
|
185
|
+
destroy() {
|
|
186
|
+
this.container.logger.log("Destroying SDK...");
|
|
187
|
+
this.container.firebaseListener.destroy();
|
|
188
|
+
this.container.firebaseService.destroy();
|
|
189
|
+
this.initialized = false;
|
|
190
|
+
}
|
|
191
|
+
async scheduleNotification(notification) {
|
|
192
|
+
return this.container.notifeeService.scheduleNotification(notification);
|
|
193
|
+
}
|
|
194
|
+
async cancelScheduledNotification(id) {
|
|
195
|
+
await this.container.notifeeService.cancelScheduledNotification(id);
|
|
196
|
+
}
|
|
197
|
+
async cancelAllScheduledNotifications() {
|
|
198
|
+
await this.container.notifeeService.cancelAllScheduledNotifications();
|
|
199
|
+
}
|
|
200
|
+
async getScheduledNotifications() {
|
|
201
|
+
return this.container.notifeeService.getScheduledNotifications();
|
|
202
|
+
}
|
|
203
|
+
async getStatus() {
|
|
204
|
+
const permission = await this.container.permissionService.getPermissionStatus();
|
|
205
|
+
let tokenAvailable = false;
|
|
206
|
+
try {
|
|
207
|
+
const token = await this.container.firebaseService.getToken();
|
|
208
|
+
tokenAvailable = !!token;
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
tokenAvailable = false;
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
initialized: this.initialized,
|
|
215
|
+
firebaseInitialized: this.container.firebaseService.isInitialized(),
|
|
216
|
+
notifeeInitialized: this.container.notifeeService.isInitialized(),
|
|
217
|
+
permission,
|
|
218
|
+
tokenAvailable,
|
|
219
|
+
platform: reactNative.Platform.OS === "android" ? "android" : "ios",
|
|
220
|
+
sdkVersion: SDK_VERSION,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
registerBackgroundHandler(handler) {
|
|
224
|
+
this.container.firebaseListener.registerBackgroundHandler(async (notification) => {
|
|
225
|
+
if (this.container.config.background?.displayNotifications !== false) {
|
|
226
|
+
await this.container.notifeeService.displayNotification(NotificationMapper.toDisplayNotification(notification));
|
|
227
|
+
}
|
|
228
|
+
await handler?.(notification);
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
class ConsoleLogger {
|
|
234
|
+
enabled;
|
|
235
|
+
constructor(enabled) {
|
|
236
|
+
this.enabled = enabled;
|
|
237
|
+
}
|
|
238
|
+
log(...args) {
|
|
239
|
+
if (!this.enabled)
|
|
240
|
+
return;
|
|
241
|
+
console.log("[NotificationSDK]", ...args);
|
|
242
|
+
}
|
|
243
|
+
warn(...args) {
|
|
244
|
+
if (!this.enabled)
|
|
245
|
+
return;
|
|
246
|
+
console.warn("[NotificationSDK]", ...args);
|
|
247
|
+
}
|
|
248
|
+
error(...args) {
|
|
249
|
+
if (!this.enabled)
|
|
250
|
+
return;
|
|
251
|
+
console.error("[NotificationSDK]", ...args);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
class FirebaseService {
|
|
256
|
+
logger;
|
|
257
|
+
tokenRefreshUnsubscribe;
|
|
258
|
+
initialized = false;
|
|
259
|
+
constructor(logger) {
|
|
260
|
+
this.logger = logger;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Initializes Firebase Messaging and starts token refresh tracking.
|
|
264
|
+
*/
|
|
265
|
+
async initialize(onTokenRefresh) {
|
|
266
|
+
if (this.initialized) {
|
|
267
|
+
this.logger.log("FirebaseService already initialized.");
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
// iOS requires explicit registration with APNs
|
|
271
|
+
if (reactNative.Platform.OS === "ios") {
|
|
272
|
+
const isRegistered = messaging().isDeviceRegisteredForRemoteMessages;
|
|
273
|
+
if (!isRegistered) {
|
|
274
|
+
this.logger.log("Registering device for remote messages...");
|
|
275
|
+
await messaging().registerDeviceForRemoteMessages();
|
|
276
|
+
this.logger.log("Device registered for remote messages.");
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
await messaging().setAutoInitEnabled(true);
|
|
280
|
+
this.tokenRefreshUnsubscribe = messaging().onTokenRefresh((token) => {
|
|
281
|
+
this.logger.log("Firebase token refreshed.");
|
|
282
|
+
onTokenRefresh(token);
|
|
283
|
+
});
|
|
284
|
+
this.initialized = true;
|
|
285
|
+
this.logger.log("FirebaseService initialized.");
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Gets the current Firebase Cloud Messaging token.
|
|
289
|
+
*/
|
|
290
|
+
async getToken() {
|
|
291
|
+
if (!this.initialized) {
|
|
292
|
+
throw new FirebaseInitializationError();
|
|
293
|
+
}
|
|
294
|
+
// Extra safety for iOS
|
|
295
|
+
if (reactNative.Platform.OS === "ios") {
|
|
296
|
+
const registered = messaging().isDeviceRegisteredForRemoteMessages;
|
|
297
|
+
if (!registered) {
|
|
298
|
+
try {
|
|
299
|
+
await messaging().registerDeviceForRemoteMessages();
|
|
300
|
+
}
|
|
301
|
+
catch (e) {
|
|
302
|
+
this.logger.warn("Unable to register for remote messages.");
|
|
303
|
+
throw e;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
const token = await messaging().getToken();
|
|
308
|
+
this.logger.log("FCM token generated.");
|
|
309
|
+
return token;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Deletes the current Firebase Cloud Messaging token.
|
|
313
|
+
*/
|
|
314
|
+
async deleteToken() {
|
|
315
|
+
await messaging().deleteToken();
|
|
316
|
+
this.logger.log("FCM token deleted.");
|
|
317
|
+
}
|
|
318
|
+
destroy() {
|
|
319
|
+
this.tokenRefreshUnsubscribe?.();
|
|
320
|
+
this.tokenRefreshUnsubscribe = undefined;
|
|
321
|
+
this.initialized = false;
|
|
322
|
+
}
|
|
323
|
+
isInitialized() {
|
|
324
|
+
return this.initialized;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
class PermissionService {
|
|
329
|
+
logger;
|
|
330
|
+
constructor(logger) {
|
|
331
|
+
this.logger = logger;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Requests notification permission.
|
|
335
|
+
*/
|
|
336
|
+
async requestPermission() {
|
|
337
|
+
try {
|
|
338
|
+
this.logger.log("Requesting notification permission...");
|
|
339
|
+
// Android
|
|
340
|
+
if (reactNative.Platform.OS === "android") {
|
|
341
|
+
if (reactNative.Platform.Version >= 33) {
|
|
342
|
+
const result = await reactNative.PermissionsAndroid.request(reactNative.PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS);
|
|
343
|
+
const status = result === reactNative.PermissionsAndroid.RESULTS.GRANTED
|
|
344
|
+
? "authorized"
|
|
345
|
+
: "denied";
|
|
346
|
+
this.logger.log(`Permission status: ${status}`);
|
|
347
|
+
return status;
|
|
348
|
+
}
|
|
349
|
+
this.logger.log("Android < 13 detected. Notification permission is granted by default.");
|
|
350
|
+
return "authorized";
|
|
351
|
+
}
|
|
352
|
+
// iOS
|
|
353
|
+
const authorizationStatus = await messaging().requestPermission();
|
|
354
|
+
const status = this.normalizeStatus(authorizationStatus);
|
|
355
|
+
this.logger.log(`Permission status: ${status}`);
|
|
356
|
+
if (this.isGranted(status) &&
|
|
357
|
+
!messaging().isDeviceRegisteredForRemoteMessages) {
|
|
358
|
+
this.logger.log("Registering device for remote messages...");
|
|
359
|
+
await messaging().registerDeviceForRemoteMessages();
|
|
360
|
+
this.logger.log("Device registered for remote messages.");
|
|
361
|
+
}
|
|
362
|
+
return status;
|
|
363
|
+
}
|
|
364
|
+
catch (error) {
|
|
365
|
+
this.logger.error("Failed to request notification permission.", error);
|
|
366
|
+
throw error;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Returns current notification permission status.
|
|
371
|
+
*/
|
|
372
|
+
async getPermissionStatus() {
|
|
373
|
+
try {
|
|
374
|
+
// Android
|
|
375
|
+
if (reactNative.Platform.OS === "android") {
|
|
376
|
+
if (reactNative.Platform.Version < 33) {
|
|
377
|
+
return "authorized";
|
|
378
|
+
}
|
|
379
|
+
const granted = await reactNative.PermissionsAndroid.check(reactNative.PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS);
|
|
380
|
+
return granted ? "authorized" : "denied";
|
|
381
|
+
}
|
|
382
|
+
// iOS
|
|
383
|
+
const authorizationStatus = await messaging().hasPermission();
|
|
384
|
+
return this.normalizeStatus(authorizationStatus);
|
|
385
|
+
}
|
|
386
|
+
catch (error) {
|
|
387
|
+
this.logger.error("Failed to get notification permission status.", error);
|
|
388
|
+
throw error;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Opens the application settings.
|
|
393
|
+
*/
|
|
394
|
+
async openSettings() {
|
|
395
|
+
this.logger.log("Opening application settings...");
|
|
396
|
+
await reactNative.Linking.openSettings();
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Returns true if permission is granted.
|
|
400
|
+
*/
|
|
401
|
+
isGranted(status) {
|
|
402
|
+
return status === "authorized" || status === "provisional";
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Registers device for remote messages (iOS only).
|
|
406
|
+
*/
|
|
407
|
+
async registerForRemoteMessages() {
|
|
408
|
+
if (reactNative.Platform.OS !== "ios") {
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
if (messaging().isDeviceRegisteredForRemoteMessages) {
|
|
412
|
+
this.logger.log("Device already registered for remote messages.");
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
this.logger.log("Registering device for remote messages...");
|
|
416
|
+
await messaging().registerDeviceForRemoteMessages();
|
|
417
|
+
this.logger.log("Device registered for remote messages.");
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Unregisters device for remote messages (iOS only).
|
|
421
|
+
*/
|
|
422
|
+
async unregisterForRemoteMessages() {
|
|
423
|
+
if (reactNative.Platform.OS !== "ios") {
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
if (!messaging().isDeviceRegisteredForRemoteMessages) {
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
this.logger.log("Unregistering device for remote messages...");
|
|
430
|
+
await messaging().unregisterDeviceForRemoteMessages();
|
|
431
|
+
this.logger.log("Device unregistered.");
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Converts Firebase authorization status.
|
|
435
|
+
*/
|
|
436
|
+
normalizeStatus(status) {
|
|
437
|
+
switch (status) {
|
|
438
|
+
case messaging.AuthorizationStatus.AUTHORIZED:
|
|
439
|
+
return "authorized";
|
|
440
|
+
case messaging.AuthorizationStatus.PROVISIONAL:
|
|
441
|
+
return "provisional";
|
|
442
|
+
case messaging.AuthorizationStatus.DENIED:
|
|
443
|
+
return "denied";
|
|
444
|
+
case messaging.AuthorizationStatus.NOT_DETERMINED:
|
|
445
|
+
return "notDetermined";
|
|
446
|
+
default:
|
|
447
|
+
return "unknown";
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
class FirebaseListener {
|
|
453
|
+
logger;
|
|
454
|
+
foregroundUnsubscribe;
|
|
455
|
+
notificationOpenedUnsubscribe;
|
|
456
|
+
messageListener;
|
|
457
|
+
notificationOpenedListener;
|
|
458
|
+
initialNotificationListener;
|
|
459
|
+
constructor(logger) {
|
|
460
|
+
this.logger = logger;
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Starts listening for foreground Firebase messages.
|
|
464
|
+
*/
|
|
465
|
+
start() {
|
|
466
|
+
if (this.foregroundUnsubscribe || this.notificationOpenedUnsubscribe) {
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
this.logger.log("Starting Firebase listeners...");
|
|
470
|
+
this.foregroundUnsubscribe = messaging().onMessage((remoteMessage) => {
|
|
471
|
+
this.logger.log("Foreground notification received.");
|
|
472
|
+
this.messageListener?.(NotificationMapper.fromRemoteMessage(remoteMessage));
|
|
473
|
+
});
|
|
474
|
+
this.notificationOpenedUnsubscribe = messaging().onNotificationOpenedApp((remoteMessage) => {
|
|
475
|
+
this.logger.log("Notification opened from background.");
|
|
476
|
+
this.notificationOpenedListener?.(NotificationMapper.fromRemoteMessage(remoteMessage));
|
|
477
|
+
});
|
|
478
|
+
void this.checkInitialNotification();
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Stops all Firebase listeners.
|
|
482
|
+
*/
|
|
483
|
+
destroy() {
|
|
484
|
+
this.foregroundUnsubscribe?.();
|
|
485
|
+
this.notificationOpenedUnsubscribe?.();
|
|
486
|
+
this.foregroundUnsubscribe = undefined;
|
|
487
|
+
this.notificationOpenedUnsubscribe = undefined;
|
|
488
|
+
}
|
|
489
|
+
onMessage(listener) {
|
|
490
|
+
this.messageListener = listener;
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Maps Firebase RemoteMessage to SDK NotificationPayload.
|
|
494
|
+
*/
|
|
495
|
+
async checkInitialNotification() {
|
|
496
|
+
try {
|
|
497
|
+
const remoteMessage = await messaging().getInitialNotification();
|
|
498
|
+
if (!remoteMessage) {
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
this.logger.log("Notification opened from terminated state.");
|
|
502
|
+
this.initialNotificationListener?.(NotificationMapper.fromRemoteMessage(remoteMessage));
|
|
503
|
+
}
|
|
504
|
+
catch (error) {
|
|
505
|
+
this.logger.error("Failed to get initial notification.", error);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
registerBackgroundHandler(handler) {
|
|
509
|
+
messaging().setBackgroundMessageHandler(async (remoteMessage) => {
|
|
510
|
+
const notification = NotificationMapper.fromRemoteMessage(remoteMessage);
|
|
511
|
+
await handler(notification);
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
class NotifeeService {
|
|
517
|
+
logger;
|
|
518
|
+
defaultChannelId;
|
|
519
|
+
mapImportance(importance) {
|
|
520
|
+
switch (importance) {
|
|
521
|
+
case "none":
|
|
522
|
+
return notifee.AndroidImportance.NONE;
|
|
523
|
+
case "min":
|
|
524
|
+
return notifee.AndroidImportance.MIN;
|
|
525
|
+
case "low":
|
|
526
|
+
return notifee.AndroidImportance.LOW;
|
|
527
|
+
case "default":
|
|
528
|
+
return notifee.AndroidImportance.DEFAULT;
|
|
529
|
+
case "high":
|
|
530
|
+
return notifee.AndroidImportance.HIGH;
|
|
531
|
+
case "max":
|
|
532
|
+
return notifee.AndroidImportance.HIGH;
|
|
533
|
+
default:
|
|
534
|
+
return notifee.AndroidImportance.HIGH;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
async createChannel(channel) {
|
|
538
|
+
return notifee.createChannel({
|
|
539
|
+
id: channel.id,
|
|
540
|
+
name: channel.name,
|
|
541
|
+
description: channel.description,
|
|
542
|
+
importance: this.mapImportance(channel.importance),
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
notificationPressedListener;
|
|
546
|
+
notificationDismissedListener;
|
|
547
|
+
handleForegroundEvent = ({ type, detail }) => {
|
|
548
|
+
if (!detail.notification) {
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
const notification = this.mapNotification(detail.notification);
|
|
552
|
+
switch (type) {
|
|
553
|
+
case notifee.EventType.PRESS:
|
|
554
|
+
this.logger.log("Local notification pressed.");
|
|
555
|
+
this.notificationPressedListener?.(notification);
|
|
556
|
+
break;
|
|
557
|
+
case notifee.EventType.DISMISSED:
|
|
558
|
+
this.logger.log("Local notification dismissed.");
|
|
559
|
+
this.notificationDismissedListener?.(notification);
|
|
560
|
+
break;
|
|
561
|
+
case notifee.EventType.ACTION_PRESS:
|
|
562
|
+
this.logger.log("Notification action pressed.");
|
|
563
|
+
this.notificationActionPressedListener?.(notification, detail.pressAction?.id ?? "", detail.input);
|
|
564
|
+
break;
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
mapNotification(notification) {
|
|
568
|
+
return {
|
|
569
|
+
id: notification?.id ?? "",
|
|
570
|
+
title: notification?.title ?? "",
|
|
571
|
+
body: notification?.body ?? "",
|
|
572
|
+
data: (notification?.data ?? {}),
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
initialized = false;
|
|
576
|
+
unsubscribeForeground;
|
|
577
|
+
buildTrigger(notification) {
|
|
578
|
+
const trigger = notification.trigger;
|
|
579
|
+
switch (trigger.type) {
|
|
580
|
+
case "timestamp":
|
|
581
|
+
return {
|
|
582
|
+
type: notifee.TriggerType.TIMESTAMP,
|
|
583
|
+
timestamp: trigger.timestamp,
|
|
584
|
+
};
|
|
585
|
+
case "interval":
|
|
586
|
+
return {
|
|
587
|
+
type: notifee.TriggerType.TIMESTAMP,
|
|
588
|
+
timestamp: Date.now() + trigger.interval * 1000,
|
|
589
|
+
repeatFrequency: trigger.repeat ? notifee.RepeatFrequency.DAILY : undefined,
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
buildAndroidNotification(notification) {
|
|
594
|
+
const android = {
|
|
595
|
+
channelId: notification.android?.channelId ?? this.defaultChannelId ?? "default",
|
|
596
|
+
autoCancel: notification.android?.autoCancel ?? true,
|
|
597
|
+
pressAction: {
|
|
598
|
+
id: notification.android?.pressActionId ?? "default",
|
|
599
|
+
},
|
|
600
|
+
};
|
|
601
|
+
if (notification.android?.smallIcon) {
|
|
602
|
+
android.smallIcon = notification.android.smallIcon;
|
|
603
|
+
}
|
|
604
|
+
if (notification.android?.largeIcon) {
|
|
605
|
+
android.largeIcon = notification.android.largeIcon;
|
|
606
|
+
}
|
|
607
|
+
if (notification.android?.color) {
|
|
608
|
+
android.color = notification.android.color;
|
|
609
|
+
}
|
|
610
|
+
if (notification.actions?.length) {
|
|
611
|
+
android.actions = notification.actions.map((action) => ({
|
|
612
|
+
title: action.title,
|
|
613
|
+
pressAction: {
|
|
614
|
+
id: action.id,
|
|
615
|
+
launchActivity: action.launchActivity === "default" ? "default" : undefined,
|
|
616
|
+
},
|
|
617
|
+
destructive: action.destructive,
|
|
618
|
+
input: action.allowInput ? true : undefined,
|
|
619
|
+
}));
|
|
620
|
+
}
|
|
621
|
+
return android;
|
|
622
|
+
}
|
|
623
|
+
buildIOSNotification(notification) {
|
|
624
|
+
const ios = {};
|
|
625
|
+
if (notification.ios?.badge !== undefined) {
|
|
626
|
+
ios.badgeCount = notification.ios.badge;
|
|
627
|
+
}
|
|
628
|
+
if (notification.ios?.sound) {
|
|
629
|
+
ios.sound = notification.ios.sound;
|
|
630
|
+
}
|
|
631
|
+
if (notification.ios?.categoryId) {
|
|
632
|
+
ios.categoryId = notification.ios.categoryId;
|
|
633
|
+
}
|
|
634
|
+
return ios;
|
|
635
|
+
}
|
|
636
|
+
buildNotification(notification) {
|
|
637
|
+
return {
|
|
638
|
+
title: notification.title,
|
|
639
|
+
subtitle: notification.subtitle,
|
|
640
|
+
body: notification.body,
|
|
641
|
+
data: notification.data,
|
|
642
|
+
android: reactNative.Platform.OS === "android"
|
|
643
|
+
? this.buildAndroidNotification(notification)
|
|
644
|
+
: undefined,
|
|
645
|
+
ios: reactNative.Platform.OS === "ios"
|
|
646
|
+
? this.buildIOSNotification(notification)
|
|
647
|
+
: undefined,
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
notificationActionPressedListener;
|
|
651
|
+
constructor(logger) {
|
|
652
|
+
this.logger = logger;
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* Initializes Notifee.
|
|
656
|
+
*/
|
|
657
|
+
async initialize(channels) {
|
|
658
|
+
if (this.initialized) {
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
this.unsubscribeForeground = notifee.onForegroundEvent(this.handleForegroundEvent);
|
|
662
|
+
if (reactNative.Platform.OS === "android") {
|
|
663
|
+
if (!channels?.length) {
|
|
664
|
+
await this.createDefaultChannel();
|
|
665
|
+
}
|
|
666
|
+
else {
|
|
667
|
+
for (const channel of channels) {
|
|
668
|
+
await this.createChannel(channel);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
this.initialized = true;
|
|
673
|
+
this.logger.log("Notifee initialized.");
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* Creates the SDK default notification channel.
|
|
677
|
+
*/
|
|
678
|
+
async createDefaultChannel() {
|
|
679
|
+
if (this.defaultChannelId) {
|
|
680
|
+
return this.defaultChannelId;
|
|
681
|
+
}
|
|
682
|
+
this.defaultChannelId = await notifee.createChannel({
|
|
683
|
+
id: "default",
|
|
684
|
+
name: "Default",
|
|
685
|
+
importance: notifee.AndroidImportance.HIGH,
|
|
686
|
+
});
|
|
687
|
+
this.logger.log(`Default notification channel created (${this.defaultChannelId})`);
|
|
688
|
+
return this.defaultChannelId;
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* Requests notification permission.
|
|
692
|
+
*/
|
|
693
|
+
async requestPermission() {
|
|
694
|
+
if (reactNative.Platform.OS === "android") {
|
|
695
|
+
return true;
|
|
696
|
+
}
|
|
697
|
+
const settings = await notifee.requestPermission();
|
|
698
|
+
return settings.authorizationStatus === notifee.AuthorizationStatus.AUTHORIZED;
|
|
699
|
+
}
|
|
700
|
+
/**
|
|
701
|
+
* Displays a local notification.
|
|
702
|
+
*/
|
|
703
|
+
async displayNotification(notification) {
|
|
704
|
+
if (reactNative.Platform.OS === "android" && !this.defaultChannelId) {
|
|
705
|
+
await this.createDefaultChannel();
|
|
706
|
+
}
|
|
707
|
+
await notifee.displayNotification(this.buildNotification(notification));
|
|
708
|
+
this.logger.log("Notification displayed.");
|
|
709
|
+
}
|
|
710
|
+
async cancelNotification(id) {
|
|
711
|
+
await notifee.cancelNotification(id);
|
|
712
|
+
}
|
|
713
|
+
async cancelAllNotifications() {
|
|
714
|
+
await notifee.cancelAllNotifications();
|
|
715
|
+
}
|
|
716
|
+
onNotificationPressed(listener) {
|
|
717
|
+
this.notificationPressedListener = listener;
|
|
718
|
+
}
|
|
719
|
+
onNotificationDismissed(listener) {
|
|
720
|
+
this.notificationDismissedListener = listener;
|
|
721
|
+
}
|
|
722
|
+
destroy() {
|
|
723
|
+
this.unsubscribeForeground?.();
|
|
724
|
+
this.unsubscribeForeground = undefined;
|
|
725
|
+
this.notificationPressedListener = undefined;
|
|
726
|
+
this.notificationDismissedListener = undefined;
|
|
727
|
+
this.initialized = false;
|
|
728
|
+
this.logger.log("Notifee destroyed.");
|
|
729
|
+
}
|
|
730
|
+
async scheduleNotification(notification) {
|
|
731
|
+
if (reactNative.Platform.OS === "android" && !this.defaultChannelId) {
|
|
732
|
+
await this.createDefaultChannel();
|
|
733
|
+
}
|
|
734
|
+
const trigger = this.buildTrigger(notification);
|
|
735
|
+
const id = await notifee.createTriggerNotification(this.buildNotification(notification), trigger);
|
|
736
|
+
this.logger.log(`Notification scheduled (${id})`);
|
|
737
|
+
return id;
|
|
738
|
+
}
|
|
739
|
+
async cancelScheduledNotification(id) {
|
|
740
|
+
await notifee.cancelTriggerNotification(id);
|
|
741
|
+
}
|
|
742
|
+
async cancelAllScheduledNotifications() {
|
|
743
|
+
await notifee.cancelTriggerNotifications();
|
|
744
|
+
}
|
|
745
|
+
async getScheduledNotifications() {
|
|
746
|
+
return notifee.getTriggerNotifications();
|
|
747
|
+
}
|
|
748
|
+
onNotificationActionPressed(listener) {
|
|
749
|
+
this.notificationActionPressedListener = listener;
|
|
750
|
+
}
|
|
751
|
+
isInitialized() {
|
|
752
|
+
return this.initialized;
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
class SDKContainer {
|
|
757
|
+
config;
|
|
758
|
+
logger;
|
|
759
|
+
permissionService;
|
|
760
|
+
firebaseService;
|
|
761
|
+
firebaseListener;
|
|
762
|
+
notifeeService;
|
|
763
|
+
// readonly deepLinkService: DeepLinkService;
|
|
764
|
+
constructor(config) {
|
|
765
|
+
this.config = Object.freeze({
|
|
766
|
+
...config,
|
|
767
|
+
});
|
|
768
|
+
this.logger = new ConsoleLogger(config.debug ?? false);
|
|
769
|
+
this.permissionService = new PermissionService(this.logger);
|
|
770
|
+
this.firebaseService = new FirebaseService(this.logger);
|
|
771
|
+
this.firebaseListener = new FirebaseListener(this.logger);
|
|
772
|
+
this.notifeeService = new NotifeeService(this.logger);
|
|
773
|
+
// this.deepLinkService = new DeepLinkService(this.logger);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
class NotificationSDK {
|
|
778
|
+
eventBus = new EventBus();
|
|
779
|
+
manager;
|
|
780
|
+
async initialize(config) {
|
|
781
|
+
if (this.manager) {
|
|
782
|
+
return;
|
|
783
|
+
}
|
|
784
|
+
const container = new SDKContainer(config);
|
|
785
|
+
this.manager = new NotificationManager(container, this.eventBus);
|
|
786
|
+
await this.manager.initialize();
|
|
787
|
+
}
|
|
788
|
+
on(event, listener) {
|
|
789
|
+
return this.eventBus.on(event, listener);
|
|
790
|
+
}
|
|
791
|
+
off(event, listener) {
|
|
792
|
+
this.eventBus.off(event, listener);
|
|
793
|
+
}
|
|
794
|
+
async requestPermission() {
|
|
795
|
+
return this.getManager().requestPermission();
|
|
796
|
+
}
|
|
797
|
+
async getPermissionStatus() {
|
|
798
|
+
return this.getManager().getPermissionStatus();
|
|
799
|
+
}
|
|
800
|
+
async getToken() {
|
|
801
|
+
return this.getManager().getToken();
|
|
802
|
+
}
|
|
803
|
+
async deleteToken() {
|
|
804
|
+
await this.getManager().deleteToken();
|
|
805
|
+
}
|
|
806
|
+
async displayNotification(notification) {
|
|
807
|
+
await this.getManager().displayNotification(notification);
|
|
808
|
+
}
|
|
809
|
+
async cancelNotification(id) {
|
|
810
|
+
await this.getManager().cancelNotification(id);
|
|
811
|
+
}
|
|
812
|
+
async cancelAllNotifications() {
|
|
813
|
+
await this.getManager().cancelAllNotifications();
|
|
814
|
+
}
|
|
815
|
+
async scheduleNotification(notification) {
|
|
816
|
+
return this.getManager().scheduleNotification(notification);
|
|
817
|
+
}
|
|
818
|
+
async cancelScheduledNotification(id) {
|
|
819
|
+
await this.getManager().cancelScheduledNotification(id);
|
|
820
|
+
}
|
|
821
|
+
async cancelAllScheduledNotifications() {
|
|
822
|
+
await this.getManager().cancelAllScheduledNotifications();
|
|
823
|
+
}
|
|
824
|
+
async getScheduledNotifications() {
|
|
825
|
+
return this.getManager().getScheduledNotifications();
|
|
826
|
+
}
|
|
827
|
+
destroy() {
|
|
828
|
+
this.manager?.destroy();
|
|
829
|
+
this.manager = undefined;
|
|
830
|
+
this.eventBus.removeAll();
|
|
831
|
+
}
|
|
832
|
+
async getStatus() {
|
|
833
|
+
return this.getManager().getStatus();
|
|
834
|
+
}
|
|
835
|
+
getManager() {
|
|
836
|
+
if (!this.manager) {
|
|
837
|
+
throw new SDKNotInitializedError();
|
|
838
|
+
}
|
|
839
|
+
return this.manager;
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
function registerBackgroundHandler(handler) {
|
|
844
|
+
messaging().setBackgroundMessageHandler(async (remoteMessage) => {
|
|
845
|
+
const notification = NotificationMapper.fromRemoteMessage(remoteMessage);
|
|
846
|
+
const logger = new ConsoleLogger(false);
|
|
847
|
+
const notifee = new NotifeeService(logger);
|
|
848
|
+
await notifee.initialize();
|
|
849
|
+
await notifee.displayNotification(NotificationMapper.toDisplayNotification(notification));
|
|
850
|
+
await handler?.(notification);
|
|
851
|
+
});
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
const Notifications = new NotificationSDK();
|
|
855
|
+
|
|
856
|
+
exports.default = Notifications;
|
|
857
|
+
exports.registerBackgroundHandler = registerBackgroundHandler;
|
|
858
|
+
//# sourceMappingURL=index.cjs.map
|