diff --git a/RNNotifications/RCTConvert+RNNotifications.m b/RNNotifications/RCTConvert+RNNotifications.m
index 92609ec98b9cf4eb08371fa89fa349d7dbe9d1bb..ce065cfb2951b5819290a9f61a3f2af3a7bb02c4 100644
--- a/RNNotifications/RCTConvert+RNNotifications.m
+++ b/RNNotifications/RCTConvert+RNNotifications.m
@@ -109,7 +109,7 @@
formattedNotification[@"body"] = RCTNullIfNil(content.body);
formattedNotification[@"category"] = RCTNullIfNil(content.categoryIdentifier);
formattedNotification[@"thread"] = RCTNullIfNil(content.threadIdentifier);
- [formattedNotification addEntriesFromDictionary:RCTNullIfNil(RCTJSONClean(content.userInfo))];
+ formattedNotification[@"data"] = [NSDictionary dictionaryWithDictionary:RCTNullIfNil(RCTJSONClean(content.userInfo))];
return formattedNotification;
}
diff --git a/RNNotifications/RNNotificationParser.m b/RNNotifications/RNNotificationParser.m
index 9a2815a2a948b682eec4c824bc6ae863bd920db2..6800f05c77c2d374aa1a8e41868aeb1ddc2d70bc 100644
--- a/RNNotifications/RNNotificationParser.m
+++ b/RNNotifications/RNNotificationParser.m
@@ -4,15 +4,11 @@
@implementation RNNotificationParser
+ (NSDictionary *)parseNotification:(UNNotification *)notification {
- NSDictionary* notificationDict = @{@"identifier": notification.request.identifier,
- @"payload": [RCTConvert UNNotificationPayload:notification]
- };
-
- return notificationDict;
+ return [RCTConvert UNNotificationPayload:notification];
}
+ (NSDictionary *)parseNotificationResponse:(UNNotificationResponse *)response {
- NSDictionary* responseDict = @{@"payload": [RCTConvert UNNotificationPayload:response.notification], @"identifier": response.notification.request.identifier, @"action": [self parseNotificationResponseAction:response]};
+ NSDictionary* responseDict = @{@"notification": [RCTConvert UNNotificationPayload:response.notification], @"identifier": response.notification.request.identifier, @"action": [self parseNotificationResponseAction:response]};
return responseDict;
}
diff --git a/example/index.ios.js b/example/index.ios.js
index a80704c7a6c6458776f621c53153250f40c9fff7..0e2dc641acffa2bcd9ebf73da2ac07d0f2b8c3ed 100644
--- a/example/index.ios.js
+++ b/example/index.ios.js
@@ -6,90 +6,92 @@ import {
Button
} from 'react-native';
import React, {Component} from 'react';
-
import { Notifications } from '../lib/dist/index';
-// let upvoteAction = new NotificationAction({
-// activationMode: 'background',
-// title: String.fromCodePoint(0x1F44D),
-// identifier: 'UPVOTE_ACTION'
-// });
-
-// let replyAction = new NotificationAction({
-// activationMode: 'background',
-// title: 'Reply',
-// authenticationRequired: true,
-// textInput: {
-// buttonTitle: 'Reply now',
-// placeholder: 'Insert message'
-// },
-// identifier: 'REPLY_ACTION'
-// });
-
class NotificationsExampleApp extends Component {
-
constructor() {
super();
this.state = {
notifications: []
};
- Notifications.events().registerNotificationsReceived((notification) => {
- alert(JSON.stringify(notification));
- })
- // NotificationsIOS.addEventListener('remoteNotificationsRegistered', this.onPushRegistered.bind(this));
- // NotificationsIOS.addEventListener('remoteNotificationsRegistrationFailed', this.onPushRegisteredFailed.bind(this));
+ this.registerNotificationEvents();
+ }
- // NotificationsIOS.addEventListener('pushKitRegistered', this.onPushKitRegistered.bind(this));
- // NotificationsIOS.registerPushKit();
+ registerNotificationEvents() {
+ Notifications.events().registerNotificationReceived((notification, completion) => {
+ this.setState({
+ notifications: [...this.state.notifications, notification.data.link]
+ });
- // NotificationsIOS.addEventListener('notificationReceivedForeground', this.onNotificationReceivedForeground.bind(this));
- // NotificationsIOS.addEventListener('notificationOpened', this.onNotificationOpened.bind(this));
- // NotificationsIOS.addEventListener('pushKitNotificationReceived', this.onPushKitNotificationReceived.bind(this));
- }
+ completion({alert: true, sound: false, badge: false});
+ });
- async componentDidMount() {
- const initialNotification = await Notifications.getInitialNotification();
- if (initialNotification) {
- this.setState({notifications: [initialNotification.getData().link, ...this.state.notifications]});
- }
+ Notifications.events().registerRemoteNotificationOpened((response, completion) => {
+ this.setState({
+ notifications: [...this.state.notifications, `Notification Clicked: ${response.notification.data.link}`]
+ });
+
+ completion();
+ });
}
- onPushRegistered(deviceToken) {
- console.log('Device Token Received: ' + deviceToken);
+ renderNotification(notification) {
+ return {`${notification}`};
}
- onPushRegisteredFailed(error) {
- console.log('Remote notifiction registration failed: ' + error);
+ requestPermissions() {
+ Notifications.requestPermissions();
}
- onPushKitRegistered(deviceToken) {
- console.log('PushKit Token Received: ' + deviceToken);
- }
+ setCategories() {
+ const upvoteAction = {
+ activationMode: 'background',
+ title: String.fromCodePoint(0x1F44D),
+ identifier: 'UPVOTE_ACTION'
+ };
+
+ const replyAction = {
+ activationMode: 'background',
+ title: 'Reply',
+ authenticationRequired: true,
+ textInput: {
+ buttonTitle: 'Reply now',
+ placeholder: 'Insert message'
+ },
+ identifier: 'REPLY_ACTION'
+ };
+
+ const category = {
+ identifier: 'SOME_CATEGORY',
+ actions: [upvoteAction, replyAction]
+ };
- onPushKitNotificationReceived(notification) {
- console.log('PushKit notification Received: ' + JSON.stringify(notification));
+ Notifications.setCategories([category]);
}
- onNotificationReceivedForeground(notification, completion) {
- console.log('Notification Received Foreground with title: ' + JSON.stringify(notification));
- this.setState({
- notifications: [...this.state.notifications, notification.getData().link]
+ sendLocalNotification() {
+ Notifications.localNotification({
+ body: 'Local notificiation!',
+ title: 'Local Notification Title',
+ sound: 'chime.aiff',
+ category: 'SOME_CATEGORY',
+ userInfo: { link: 'localNotificationLink' },
});
+ }
- completion({alert: notification.getData().showAlert, sound: false, badge: false});
+ removeAllDeliveredNotifications() {
+ Notifications.removeAllDeliveredNotifications();
}
- onNotificationOpened(notification, completion, action) {
- console.log('Notification Opened: ' + JSON.stringify(notification) + JSON.stringify(action));
- this.setState({
- notifications: [...this.state.notifications, `Notification Clicked: ${notification.getData().link}`]
- });
- completion();
+ async componentDidMount() {
+ const initialNotification = await Notifications.getInitialNotification();
+ if (initialNotification) {
+ this.setState({notifications: [initialNotification.data.link, ...this.state.notifications]});
+ }
}
- renderNotification(notification) {
- return {`${notification}`};
+ componentWillUnmount() {
}
render() {
@@ -109,35 +111,6 @@ class NotificationsExampleApp extends Component {
);
}
-
- requestPermissions() {
- // let cat = new NotificationCategory({
- // identifier: 'SOME_CATEGORY',
- // actions: [upvoteAction, replyAction]
- // });
- Notifications.requestPermissions(/*[cat]*/);
- }
-
- sendLocalNotification() {
- Notifications.localNotification({
- body: 'Local notificiation!',
- title: 'Local Notification Title',
- sound: 'chime.aiff',
- category: 'SOME_CATEGORY',
- userInfo: { link: 'localNotificationLink' },
- });
- }
-
- removeAllDeliveredNotifications() {
- // NotificationsIOS.removeAllDeliveredNotifications();
- }
-
- componentWillUnmount() {
- // NotificationsIOS.removeEventListener('notificationReceivedForeground', this.onNotificationReceivedForeground.bind(this));
- // NotificationsIOS.removeEventListener('notificationOpened', this.onNotificationOpened.bind(this));
- // NotificationsIOS.removeEventListener('remoteNotificationsRegistered', this.onPushRegistered.bind(this));
- // NotificationsIOS.removeEventListener('pushKitRegistered', this.onPushKitRegistered.bind(this));
- }
}
const styles = StyleSheet.create({
diff --git a/example/ios/NotificationsExampleApp.xcodeproj/project.pbxproj b/example/ios/NotificationsExampleApp.xcodeproj/project.pbxproj
index cbd0289118e2db35923a98ae156c3ac80e085e21..8925461ff1a79ce7fc8b79e5e78300183aaad788 100644
--- a/example/ios/NotificationsExampleApp.xcodeproj/project.pbxproj
+++ b/example/ios/NotificationsExampleApp.xcodeproj/project.pbxproj
@@ -11,6 +11,7 @@
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
+ 50CBD3CD22F2558C00142352 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 50CBD3A922F2556900142352 /* libRCTAnimation.a */; };
50F1F0CC22CE3B4700FD5829 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 50F1F06022CE3A6100FD5829 /* libReact.a */; };
50F1F0CD22CE3B6300FD5829 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 50F1F08A22CE3AA000FD5829 /* libRCTActionSheet.a */; };
50F1F0CF22CE3B6300FD5829 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 50F1F09522CE3ABE00FD5829 /* libRCTImage.a */; };
@@ -27,6 +28,20 @@
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
+ 50CBD3A822F2556900142352 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 50CBD3A222F2556900142352 /* RCTAnimation.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 134814201AA4EA6300B7C361;
+ remoteInfo = RCTAnimation;
+ };
+ 50CBD3AA22F2556900142352 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 50CBD3A222F2556900142352 /* RCTAnimation.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 2D2A28201D9B03D100D4039D;
+ remoteInfo = "RCTAnimation-tvOS";
+ };
50E49F4022D1F06C007160C1 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
@@ -283,6 +298,7 @@
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = NotificationsExampleApp/Info.plist; sourceTree = ""; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = NotificationsExampleApp/main.m; sourceTree = ""; };
146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../../node_modules/react-native/React/React.xcodeproj"; sourceTree = ""; };
+ 50CBD3A222F2556900142352 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = ""; };
50F1F08522CE3A9F00FD5829 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = "../../node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj"; sourceTree = ""; };
50F1F0A022CE3B0600FD5829 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = "../../node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj"; sourceTree = ""; };
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = ""; };
@@ -296,6 +312,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 50CBD3CD22F2558C00142352 /* libRCTAnimation.a in Frameworks */,
50F1F0D722CE3C1E00FD5829 /* libcxxreact.a in Frameworks */,
50F1F0D622CE3C0F00FD5829 /* libyoga.a in Frameworks */,
50F1F0CD22CE3B6300FD5829 /* libRCTActionSheet.a in Frameworks */,
@@ -346,6 +363,15 @@
name = NotificationsExampleApp;
sourceTree = "";
};
+ 50CBD3A322F2556900142352 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 50CBD3A922F2556900142352 /* libRCTAnimation.a */,
+ 50CBD3AB22F2556900142352 /* libRCTAnimation.a */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
50F1F04D22CE3A6100FD5829 /* Products */ = {
isa = PBXGroup;
children = (
@@ -444,6 +470,7 @@
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
isa = PBXGroup;
children = (
+ 50CBD3A222F2556900142352 /* RCTAnimation.xcodeproj */,
50F1F0A022CE3B0600FD5829 /* RCTNetwork.xcodeproj */,
D85498C21D97B31100DEEE06 /* RNNotifications.xcodeproj */,
146833FF1AC3E56700842450 /* React.xcodeproj */,
@@ -542,6 +569,10 @@
ProductGroup = 50F1F08622CE3A9F00FD5829 /* Products */;
ProjectRef = 50F1F08522CE3A9F00FD5829 /* RCTActionSheet.xcodeproj */;
},
+ {
+ ProductGroup = 50CBD3A322F2556900142352 /* Products */;
+ ProjectRef = 50CBD3A222F2556900142352 /* RCTAnimation.xcodeproj */;
+ },
{
ProductGroup = 50F1F09022CE3ABE00FD5829 /* Products */;
ProjectRef = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */;
@@ -587,6 +618,20 @@
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
+ 50CBD3A922F2556900142352 /* libRCTAnimation.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libRCTAnimation.a;
+ remoteRef = 50CBD3A822F2556900142352 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 50CBD3AB22F2556900142352 /* libRCTAnimation.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libRCTAnimation.a;
+ remoteRef = 50CBD3AA22F2556900142352 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
50E49F4122D1F06C007160C1 /* libjsi.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
diff --git a/lib/src/Notifications.ts b/lib/src/Notifications.ts
index 3d28969f9d7f760346ac199c1f39c7b4cf1d6094..a5b1fbef188f3f16e74a58d7ad150f114e3a6e6f 100644
--- a/lib/src/Notifications.ts
+++ b/lib/src/Notifications.ts
@@ -4,6 +4,7 @@ import { Commands } from './commands/Commands';
import { EventsRegistry } from './events/EventsRegistry';
import { Notification, NotificationCategory } from './interfaces/Notification';
import { UniqueIdProvider } from './adapters/UniqueIdProvider';
+import { CompletionCallbackWrapper } from './adapters/CompletionCallbackWrapper';
export class NotificationsRoot {
private readonly nativeEventsReceiver: NativeEventsReceiver;
@@ -11,16 +12,18 @@ export class NotificationsRoot {
private readonly commands: Commands;
private readonly eventsRegistry: EventsRegistry;
private readonly uniqueIdProvider: UniqueIdProvider;
+ private readonly completionCallbackWrapper: CompletionCallbackWrapper;
constructor() {
this.nativeEventsReceiver = new NativeEventsReceiver();
this.nativeCommandsSender = new NativeCommandsSender();
+ this.completionCallbackWrapper = new CompletionCallbackWrapper(this.nativeCommandsSender);
this.uniqueIdProvider = new UniqueIdProvider();
this.commands = new Commands(
this.nativeCommandsSender,
this.uniqueIdProvider
);
- this.eventsRegistry = new EventsRegistry(this.nativeEventsReceiver);
+ this.eventsRegistry = new EventsRegistry(this.nativeEventsReceiver, this.completionCallbackWrapper);
}
/**
@@ -45,7 +48,7 @@ export class NotificationsRoot {
}
/**
- *
+ * getInitialNotification
*/
public getInitialNotification(): Promise {
return this.commands.getInitialNotification();
diff --git a/lib/src/adapters/CompletionCallbackWrapper.ts b/lib/src/adapters/CompletionCallbackWrapper.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2458e7927ac9aaf70f5cc951dcad4a590ef5d5ec
--- /dev/null
+++ b/lib/src/adapters/CompletionCallbackWrapper.ts
@@ -0,0 +1,29 @@
+import { NativeCommandsSender } from './NativeCommandsSender';
+import { NotificationCompletion, Notification } from '../interfaces/Notification';
+import { NotificationResponse } from '../interfaces/NotificationEvents';
+
+export class CompletionCallbackWrapper {
+ constructor(
+ private readonly nativeCommandsSender: NativeCommandsSender
+ ) {}
+
+ public wrapReceivedCallback(callback: Function): (notification: Notification) => void {
+ return (notification) => {
+ const completion = (response: NotificationCompletion) => {
+ this.nativeCommandsSender.finishPresentingNotification(notification.identifier, response);
+ };
+
+ callback(notification, completion);
+ }
+ }
+
+ public wrapOpenedCallback(callback: Function): (response: NotificationResponse) => void {
+ return (response) => {
+ const completion = () => {
+ this.nativeCommandsSender.finishHandlingAction(response.notification.identifier);
+ };
+
+ callback(response, completion);
+ }
+ }
+}
diff --git a/lib/src/adapters/NativeCommandsSender.mock.ts b/lib/src/adapters/NativeCommandsSender.mock.ts
new file mode 100644
index 0000000000000000000000000000000000000000..138de4ca57a7bfcbff6d49b963df3c4b309129aa
--- /dev/null
+++ b/lib/src/adapters/NativeCommandsSender.mock.ts
@@ -0,0 +1 @@
+export const { NativeCommandsSender } = jest.genMockFromModule('./NativeCommandsSender');
diff --git a/lib/src/adapters/NativeCommandsSender.ts b/lib/src/adapters/NativeCommandsSender.ts
index 1b9b9169336245c961f965311e92300aadf40654..1e4e7f3d7adbb9b9e689c424b4103cebfccc737d 100644
--- a/lib/src/adapters/NativeCommandsSender.ts
+++ b/lib/src/adapters/NativeCommandsSender.ts
@@ -1,5 +1,5 @@
import { NativeModules } from 'react-native';
-import { Notification, NotificationCategory, NotificationPermissions } from '../interfaces/Notification';
+import { Notification, NotificationCategory, NotificationPermissions, NotificationCompletion } from '../interfaces/Notification';
interface NativeCommandsModule {
getInitialNotification(): Promise;
@@ -16,6 +16,8 @@ interface NativeCommandsModule {
removeDeliveredNotifications(identifiers: Array): void;
removeAllDeliveredNotifications(): void;
setCategories(categories: [NotificationCategory?]): void;
+ finishPresentingNotification(notificationId: string, callback: NotificationCompletion): void;
+ finishHandlingAction(notificationId: string): void;
}
export class NativeCommandsSender {
@@ -28,7 +30,7 @@ export class NativeCommandsSender {
return this.nativeCommandsModule.localNotification(notification, id);
}
- getInitialNotification() {
+ getInitialNotification(): Promise {
return this.nativeCommandsModule.getInitialNotification();
}
@@ -79,4 +81,12 @@ export class NativeCommandsSender {
removeDeliveredNotifications(identifiers: Array) {
return this.nativeCommandsModule.removeDeliveredNotifications(identifiers);
}
+
+ finishPresentingNotification(notificationId: string, notificationCompletion: NotificationCompletion): void {
+ this.nativeCommandsModule.finishPresentingNotification(notificationId, notificationCompletion);
+ }
+
+ finishHandlingAction(notificationId: string): void {
+ this.nativeCommandsModule.finishHandlingAction(notificationId);
+ }
}
diff --git a/lib/src/adapters/NativeEventsReceiver.ts b/lib/src/adapters/NativeEventsReceiver.ts
index a8b3f535aa6f00f591352dc970780adde056c1a1..99bc6f9ba55f7441ceef80d9d916290ac576ec48 100644
--- a/lib/src/adapters/NativeEventsReceiver.ts
+++ b/lib/src/adapters/NativeEventsReceiver.ts
@@ -1,7 +1,8 @@
import { NativeModules, NativeEventEmitter, EventEmitter, EmitterSubscription } from 'react-native';
import {
- NotificationRegisteredEvent, NotificationReceived
+ Registered, RegistrationError, RegisteredPushKit, NotificationResponse
} from '../interfaces/NotificationEvents';
+import { Notification } from '../interfaces/Notification';
export class NativeEventsReceiver {
private emitter: EventEmitter;
@@ -9,11 +10,27 @@ export class NativeEventsReceiver {
this.emitter = new NativeEventEmitter(NativeModules.RNEventEmitter);
}
- public registerRemoteNotificationsRegistered(callback: (event: NotificationRegisteredEvent) => void): EmitterSubscription {
+ public registerRemoteNotificationsRegistered(callback: (event: Registered) => void): EmitterSubscription {
return this.emitter.addListener('remoteNotificationsRegistered', callback);
}
- public registerRemoteNotificationReceived(callback: (event: NotificationReceived) => void): EmitterSubscription {
+ public registerPushKitRegistered(callback: (event: RegisteredPushKit) => void): EmitterSubscription {
+ return this.emitter.addListener('pushKitRegistered', callback);
+ }
+
+ public registerRemoteNotificationReceived(callback: (notification: Notification) => void): EmitterSubscription {
+ return this.emitter.addListener('notificationReceivedForeground', callback);
+ }
+
+ public registerPushKitNotificationReceived(callback: (event: object) => void): EmitterSubscription {
return this.emitter.addListener('notificationReceivedForeground', callback);
}
+
+ public registerRemoteNotificationOpened(callback: (response: NotificationResponse, completion: () => void) => void): EmitterSubscription {
+ return this.emitter.addListener('notificationOpened', callback);
+ }
+
+ public registerRemoteNotificationsRegistrationFailed(callback: (event: RegistrationError) => void): EmitterSubscription {
+ return this.emitter.addListener('remoteNotificationsRegistrationFailed', callback);
+ }
}
diff --git a/lib/src/commands/Commands.test.ts b/lib/src/commands/Commands.test.ts
index aba9afc2d05f4dd8c6ffabef71499c0be624d2ef..ddac792d5155290946c034221d152157aa071893 100644
--- a/lib/src/commands/Commands.test.ts
+++ b/lib/src/commands/Commands.test.ts
@@ -1,5 +1,5 @@
import * as _ from 'lodash';
-import { mock, verify, instance, deepEqual, when, anything, anyString } from 'ts-mockito';
+import { mock, verify, instance, when, anything, anyString } from 'ts-mockito';
import { Commands } from './Commands';
import { NativeCommandsSender } from '../adapters/NativeCommandsSender';
@@ -28,7 +28,7 @@ describe('Commands', () => {
});
it('returns a promise with the initial notification', async () => {
- const expectedNotification: Notification = {data: {}, alert: 'alert'};
+ const expectedNotification: Notification = {identifier: 'id', data: {}, alert: 'alert'};
when(mockedNativeCommandsSender.getInitialNotification()).thenResolve(
expectedNotification
);
@@ -75,19 +75,19 @@ describe('Commands', () => {
describe('sendLocalNotification', () => {
it('sends to native', () => {
- const notification: Notification = {data: {}, alert: 'alert'};
+ const notification: Notification = {identifier: 'id', alert: 'alert', data: {}};
uut.sendLocalNotification(notification);
verify(mockedNativeCommandsSender.sendLocalNotification(notification, anyString())).called();
});
it('generates unique identifier', () => {
- const notification: Notification = {data: {}, alert: 'alert'};
+ const notification: Notification = {identifier: 'id', data: {}, alert: 'alert'};
uut.sendLocalNotification(notification);
verify(mockedNativeCommandsSender.sendLocalNotification(notification, `Notification_+UNIQUE_ID`)).called();
});
it('use passed notification id', () => {
- const notification: Notification = {data: {}, alert: 'alert'};
+ const notification: Notification = {identifier: 'id', data: {}, alert: 'alert'};
const passedId: string = "passedId";
uut.sendLocalNotification(notification, passedId);
verify(mockedNativeCommandsSender.sendLocalNotification(notification, passedId)).called();
diff --git a/lib/src/commands/Commands.ts b/lib/src/commands/Commands.ts
index 07986a675d87581f5641eb47b8e27c49510764f6..7d8049100ad0512662622b2c58cb4913934689e5 100644
--- a/lib/src/commands/Commands.ts
+++ b/lib/src/commands/Commands.ts
@@ -15,7 +15,7 @@ export class Commands {
return result;
}
- public getInitialNotification() {
+ public getInitialNotification(): Promise {
const result = this.nativeCommandsSender.getInitialNotification();
return result;
}
diff --git a/lib/src/events/EventsRegistry.test.ts b/lib/src/events/EventsRegistry.test.ts
new file mode 100644
index 0000000000000000000000000000000000000000..367ecd0e9eb798a68e07a71c3153109ddc25fe1b
--- /dev/null
+++ b/lib/src/events/EventsRegistry.test.ts
@@ -0,0 +1,140 @@
+import { EventsRegistry } from './EventsRegistry';
+import { NativeEventsReceiver } from '../adapters/NativeEventsReceiver.mock';
+import { NotificationCompletion, Notification } from '../interfaces/Notification';
+import { CompletionCallbackWrapper } from '../adapters/CompletionCallbackWrapper';
+import { NativeCommandsSender } from '../adapters/NativeCommandsSender.mock';
+import { NotificationResponse } from '../interfaces/NotificationEvents';
+
+describe('EventsRegistry', () => {
+ let uut: EventsRegistry;
+ const mockNativeEventsReceiver = new NativeEventsReceiver();
+ const mockNativeCommandsSender = new NativeCommandsSender();
+ const completionCallbackWrapper = new CompletionCallbackWrapper(mockNativeCommandsSender);
+
+ beforeEach(() => {
+ uut = new EventsRegistry(mockNativeEventsReceiver, completionCallbackWrapper);
+ });
+
+ describe('registerRemoteNotificationsReceived', () => {
+ it('delegates to nativeEventsReceiver', () => {
+ const cb = jest.fn();
+
+ uut.registerNotificationReceived(cb);
+
+ expect(mockNativeEventsReceiver.registerRemoteNotificationReceived).toHaveBeenCalledTimes(1);
+ expect(mockNativeEventsReceiver.registerRemoteNotificationReceived).toHaveBeenCalledWith(expect.any(Function));
+ });
+
+ it('should wrap callback with completion block', () => {
+ const wrappedCallback = jest.fn();
+ const notification: Notification = {identifier: 'identifier', data: {}, alert: 'alert'}
+
+ uut.registerNotificationReceived(wrappedCallback);
+ const call = mockNativeEventsReceiver.registerRemoteNotificationReceived.mock.calls[0][0];
+ call(notification);
+
+ expect(wrappedCallback).toBeCalledWith(notification, expect.any(Function));
+ expect(wrappedCallback).toBeCalledTimes(1);
+ });
+
+ it('should wrap callback with completion block', () => {
+ const expectedNotification: Notification = {identifier: 'identifier', data: {}, alert: 'alert'}
+
+ uut.registerNotificationReceived((notification) => {
+ expect(notification).toEqual(expectedNotification);
+ });
+ const call = mockNativeEventsReceiver.registerRemoteNotificationReceived.mock.calls[0][0];
+ call(expectedNotification);
+ });
+
+ it('calling completion should invoke finishPresentingNotification', () => {
+ const notification: Notification = {identifier: 'notificationId', data: {}, alert: 'alert'}
+ const response: NotificationCompletion = {alert: true}
+
+ uut.registerNotificationReceived((notification, completion) => {
+ completion(response);
+
+ expect(mockNativeCommandsSender.finishPresentingNotification).toBeCalledWith(notification.identifier, response);
+ });
+ const call = mockNativeEventsReceiver.registerRemoteNotificationReceived.mock.calls[0][0];
+ call(notification);
+ });
+ });
+
+ describe('', () => {
+ it('delegates to nativeEventsReceiver', () => {
+ const cb = jest.fn();
+
+ uut.registerRemoteNotificationOpened(cb);
+
+ expect(mockNativeEventsReceiver.registerRemoteNotificationOpened).toHaveBeenCalledTimes(1);
+ expect(mockNativeEventsReceiver.registerRemoteNotificationOpened).toHaveBeenCalledWith(expect.any(Function));
+ });
+
+ it('should wrap callback with completion block', () => {
+ const wrappedCallback = jest.fn();
+ const notification: Notification = {identifier: 'identifier', data: {}, alert: 'alert'};
+ const response: NotificationResponse = {notification, identifier: 'responseId'};
+
+ uut.registerRemoteNotificationOpened(wrappedCallback);
+ const call = mockNativeEventsReceiver.registerRemoteNotificationOpened.mock.calls[0][0];
+ call(response);
+
+ expect(wrappedCallback).toBeCalledWith(response, expect.any(Function));
+ expect(wrappedCallback).toBeCalledTimes(1);
+ });
+
+ it('should wrap callback with completion block', () => {
+ const notification: Notification = {identifier: 'identifier', data: {}, alert: 'alert'}
+ const expectedResponse: NotificationResponse = {notification, identifier: 'responseId'}
+
+ uut.registerRemoteNotificationOpened((response) => {
+ expect(response).toEqual(expectedResponse);
+ });
+ const call = mockNativeEventsReceiver.registerRemoteNotificationOpened.mock.calls[0][0];
+ call(expectedResponse);
+ });
+
+ it('calling completion should invoke finishHandlingAction', () => {
+ const notification: Notification = {identifier: 'notificationId', data: {}, alert: 'alert'}
+ const expectedResponse: NotificationResponse = {identifier: 'responseId', notification};
+
+ uut.registerRemoteNotificationOpened((response, completion) => {
+ completion();
+
+ expect(response).toEqual(expectedResponse);
+ expect(mockNativeCommandsSender.finishHandlingAction).toBeCalledWith(notification.identifier);
+ });
+ const call = mockNativeEventsReceiver.registerRemoteNotificationOpened.mock.calls[0][0];
+ call(expectedResponse);
+ });
+ });
+
+ it('delegates registerRemoteNotificationsRegistered to nativeEventsReceiver', () => {
+ const cb = jest.fn();
+ uut.registerRemoteNotificationsRegistered(cb);
+ expect(mockNativeEventsReceiver.registerRemoteNotificationsRegistered).toHaveBeenCalledTimes(1);
+ expect(mockNativeEventsReceiver.registerRemoteNotificationsRegistered).toHaveBeenCalledWith(cb);
+ });
+
+ it('delegates registerPushKitRegistered to nativeEventsReceiver', () => {
+ const cb = jest.fn();
+ uut.registerPushKitRegistered(cb);
+ expect(mockNativeEventsReceiver.registerPushKitRegistered).toHaveBeenCalledTimes(1);
+ expect(mockNativeEventsReceiver.registerPushKitRegistered).toHaveBeenCalledWith(cb);
+ });
+
+ it('delegates registerPushKitNotificationReceived to nativeEventsReceiver', () => {
+ const cb = jest.fn();
+ uut.registerPushKitNotificationReceived(cb);
+ expect(mockNativeEventsReceiver.registerPushKitNotificationReceived).toHaveBeenCalledTimes(1);
+ expect(mockNativeEventsReceiver.registerPushKitNotificationReceived).toHaveBeenCalledWith(cb);
+ });
+
+ it('delegates registerRemoteNotificationsRegistrationFailed to nativeEventsReceiver', () => {
+ const cb = jest.fn();
+ uut.registerRemoteNotificationsRegistrationFailed(cb);
+ expect(mockNativeEventsReceiver.registerRemoteNotificationsRegistrationFailed).toHaveBeenCalledTimes(1);
+ expect(mockNativeEventsReceiver.registerRemoteNotificationsRegistrationFailed).toHaveBeenCalledWith(cb);
+ });
+});
diff --git a/lib/src/events/EventsRegistry.test.tsx b/lib/src/events/EventsRegistry.test.tsx
deleted file mode 100644
index 2d323b8bf83341af4662d687199b1d1f495f9724..0000000000000000000000000000000000000000
--- a/lib/src/events/EventsRegistry.test.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import { EventsRegistry } from './EventsRegistry';
-import { NativeEventsReceiver } from '../adapters/NativeEventsReceiver.mock';
-
-describe('EventsRegistry', () => {
- let uut: EventsRegistry;
- const mockNativeEventsReceiver = new NativeEventsReceiver();
-
- beforeEach(() => {
- uut = new EventsRegistry(mockNativeEventsReceiver);
- });
-
- it('delegates registerRemoteNotificationsRegistered to nativeEventsReceiver', () => {
- const cb = jest.fn();
- uut.registerRemoteNotificationsRegistered(cb);
- expect(mockNativeEventsReceiver.registerRemoteNotificationsRegistered).toHaveBeenCalledTimes(1);
- expect(mockNativeEventsReceiver.registerRemoteNotificationsRegistered).toHaveBeenCalledWith(cb);
- });
-
- it('delegates registerRemoteNotificationsReceived to nativeEventsReceiver', () => {
- const cb = jest.fn();
- uut.registerNotificationReceived(cb);
- expect(mockNativeEventsReceiver.registerRemoteNotificationReceived).toHaveBeenCalledTimes(1);
- expect(mockNativeEventsReceiver.registerRemoteNotificationReceived).toHaveBeenCalledWith(cb);
- });
-});
diff --git a/lib/src/events/EventsRegistry.ts b/lib/src/events/EventsRegistry.ts
index cd7054031cf099711714a5a345dfc37a15c3f8b4..d143de4d11592a73fe2b34e9d6df742c2b25afa3 100644
--- a/lib/src/events/EventsRegistry.ts
+++ b/lib/src/events/EventsRegistry.ts
@@ -1,18 +1,42 @@
import { EmitterSubscription } from 'react-native';
import { NativeEventsReceiver } from '../adapters/NativeEventsReceiver';
import {
- NotificationRegisteredEvent,
- NotificationReceived
+ Registered,
+ RegistrationError,
+ RegisteredPushKit,
+ NotificationResponse
} from '../interfaces/NotificationEvents';
+import { CompletionCallbackWrapper } from '../adapters/CompletionCallbackWrapper';
+import { NotificationCompletion, Notification } from '../interfaces/Notification';
export class EventsRegistry {
- constructor(private nativeEventsReceiver: NativeEventsReceiver) { }
+ constructor(
+ private nativeEventsReceiver: NativeEventsReceiver,
+ private completionCallbackWrapper: CompletionCallbackWrapper)
+ {}
- public registerRemoteNotificationsRegistered(callback: (event: NotificationRegisteredEvent) => void): EmitterSubscription {
+ public registerRemoteNotificationsRegistered(callback: (event: Registered) => void): EmitterSubscription {
return this.nativeEventsReceiver.registerRemoteNotificationsRegistered(callback);
}
- public registerNotificationReceived(callback: (event: NotificationReceived) => void): EmitterSubscription {
- return this.nativeEventsReceiver.registerRemoteNotificationReceived(callback);
+ public registerPushKitRegistered(callback: (event: RegisteredPushKit) => void): EmitterSubscription {
+ return this.nativeEventsReceiver.registerPushKitRegistered(callback);
}
+
+ public registerNotificationReceived(callback: (notification: Notification, completion: (response: NotificationCompletion) => void) => void): EmitterSubscription {
+ return this.nativeEventsReceiver.registerRemoteNotificationReceived(this.completionCallbackWrapper.wrapReceivedCallback(callback));
+ }
+
+ public registerPushKitNotificationReceived(callback: (event: object) => void): EmitterSubscription {
+ return this.nativeEventsReceiver.registerPushKitNotificationReceived(callback);
+ }
+
+ public registerRemoteNotificationOpened(callback: (response: NotificationResponse, completion: () => void) => void): EmitterSubscription {
+ return this.nativeEventsReceiver.registerRemoteNotificationOpened(this.completionCallbackWrapper.wrapOpenedCallback(callback));
+ }
+
+ public registerRemoteNotificationsRegistrationFailed(callback: (event: RegistrationError) => void): EmitterSubscription {
+ return this.nativeEventsReceiver.registerRemoteNotificationsRegistrationFailed(callback);
+ }
+
}
diff --git a/lib/src/interfaces/Notification.ts b/lib/src/interfaces/Notification.ts
index a564909092d14483061a167b2593a7be2f9febe9..106393adadc6cb763e21249ff79f5604bc657beb 100644
--- a/lib/src/interfaces/Notification.ts
+++ b/lib/src/interfaces/Notification.ts
@@ -1,4 +1,5 @@
export interface Notification {
+ identifier: string;
data: object;
alert: string
sound?: string;
@@ -31,3 +32,14 @@ export interface NotificationAction {
authenticationRequired: boolean;
textInput: NotificationTextInput
}
+
+export interface NotificationActionResponse {
+ identifier: string;
+ text: string;
+}
+
+export interface NotificationCompletion {
+ badge?: boolean;
+ alert?: boolean;
+ sound?: boolean;
+}
diff --git a/lib/src/interfaces/NotificationEvents.ts b/lib/src/interfaces/NotificationEvents.ts
index 53ce2ea55a3ac238097f5e717a7656495a8a555a..7284220044de981400338b0850090f6790bc6cb0 100644
--- a/lib/src/interfaces/NotificationEvents.ts
+++ b/lib/src/interfaces/NotificationEvents.ts
@@ -1,9 +1,21 @@
-import { Notification } from './Notification';
+import { Notification, NotificationActionResponse } from './Notification';
-export interface NotificationRegisteredEvent {
+export interface Registered {
deviceToken: string;
}
-export interface NotificationReceived {
+export interface RegistrationError {
+ code: string;
+ domain: string;
+ localizedDescription: string;
+}
+
+export interface RegisteredPushKit {
+ pushKitToken: string;
+}
+
+export interface NotificationResponse {
+ identifier: string;
notification: Notification;
+ action?: NotificationActionResponse
}