diff --git a/README.md b/README.md index d2238231ffed4d6a6c9efa49291c62e57b8ba389..96786e599dd2f5ce0098110e077a14292a741638 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,6 @@ Handle push notifications for your app, including remote and local notifications **Work in progress, please notice that this library is not production-ready yet!** ## TODO -- Return unified notification object for regular & managed notifications. - Add permissions management. - Add interactive notifications support. - Better support of local notifications. diff --git a/RNNotifications/RNNotifications.m b/RNNotifications/RNNotifications.m index f601dcb7081d0c66c0eac0d98e40ca66672b6218..9344394aac83c816e90d8821e1e2e4871d144d15 100644 --- a/RNNotifications/RNNotifications.m +++ b/RNNotifications/RNNotifications.m @@ -87,10 +87,10 @@ static NSString* username; + (void)didReceiveNotificationOnBackgroundState:(NSDictionary *)notification { - NSDictionary* customData = [notification objectForKey:@"customData"]; - NSDictionary* alert = [customData objectForKey:@"alert"]; - NSString* action = [customData objectForKey:@"action"]; - NSString* notificationId = [customData objectForKey:@"notificationId"]; + NSDictionary* managedAps = [notification objectForKey:@"managedAps"]; + NSDictionary* alert = [managedAps objectForKey:@"alert"]; + NSString* action = [managedAps objectForKey:@"action"]; + NSString* notificationId = [managedAps objectForKey:@"notificationId"]; if (action) { // create or delete notification @@ -122,10 +122,10 @@ static NSString* username; + (void)dispatchLocalNotificationFromNotification:(NSDictionary *)notification { - NSDictionary* customData = [notification objectForKey:@"customData"]; - NSDictionary* alert = [customData objectForKey:@"alert"]; - NSString* action = [customData objectForKey:@"action"]; - NSString* notificationId = [customData objectForKey:@"notificationId"]; + NSDictionary* managedAps = [notification objectForKey:@"managedAps"]; + NSDictionary* alert = [managedAps objectForKey:@"alert"]; + NSString* action = [managedAps objectForKey:@"action"]; + NSString* notificationId = [managedAps objectForKey:@"notificationId"]; if ([action isEqualToString: RNNotificationCreateAction] && notificationId @@ -135,8 +135,8 @@ static NSString* username; UILocalNotification* note = [[UILocalNotification alloc] init]; note.alertTitle = [alert objectForKey:@"title"]; note.alertBody = [alert objectForKey:@"body"]; - note.userInfo = customData; - note.soundName = [customData objectForKey:@"sound"]; + note.userInfo = managedAps; + note.soundName = [managedAps objectForKey:@"sound"]; NSLog(@"Presenting local notification..."); [[UIApplication sharedApplication] presentLocalNotificationNow:note]; diff --git a/example/package.json b/example/package.json index b1e9f9cf046446f0dfdf5192ad6cba9a5aa74ba5..67d6b4d7dcb6d435304cb198d1148bd0ef6f4f07 100644 --- a/example/package.json +++ b/example/package.json @@ -9,5 +9,15 @@ "react": "^0.14.7", "react-native": "^0.22.2", "react-native-notifications": "../" + }, + "devDependencies": { + "babel-preset-react-native": "^1.5.6", + "babel-preset-stage-1": "^6.5.0" + }, + "babel": { + "presets": [ + "react-native", + "stage-1" + ] } } diff --git a/index.ios.js b/index.ios.js index be8adfc8e48d0d64a6f3d26661b10c53c171ab3f..f1968e8377d07885c02ff129b95bdf69a9a90c7f 100644 --- a/index.ios.js +++ b/index.ios.js @@ -6,6 +6,7 @@ import { NativeModules, DeviceEventEmitter } from "react-native"; import Map from "core-js/library/es6/map"; let NativeRNNotifications = NativeModules.RNNotifications; // eslint-disable-line no-unused-vars +import IOSNotification from "./notification.ios"; export const DEVICE_NOTIFICATION_RECEIVED_FOREGROUND_EVENT = "notificationReceivedForeground"; export const DEVICE_NOTIFICATION_RECEIVED_BACKGROUND_EVENT = "notificationReceivedBackground"; @@ -30,7 +31,7 @@ export default class NotificationsIOS { type === DEVICE_NOTIFICATION_OPENED_EVENT) { let listener = DeviceEventEmitter.addListener( type, - notification => handler(notification) + notification => handler(new IOSNotification(notification)) ); _notificationHandlers.set(handler, listener); diff --git a/notification.ios.js b/notification.ios.js new file mode 100644 index 0000000000000000000000000000000000000000..dbc40aedf4ededfdffdb0abd98d977c1418426c4 --- /dev/null +++ b/notification.ios.js @@ -0,0 +1,64 @@ +export default class IOSNotification { + _data: Object; + _alert: string | Object; + _sound: string; + _badge: number; + _category: string; + _type: string; // regular / managed + + constructor(notification: Object) { + this._data = {}; + + if (notification.aps && + notification.aps["content-available"] && + notification.aps["content-available"] === 1 && + !notification.aps.alert && + !notification.aps.sound && + !notification.aps.badge && + notification.managedAps) { + // managed notification + this._alert = notification.managedAps.alert; + this._sound = notification.managedAps.sound; + this._badge = notification.managedAps.badge; + this._category = notification.managedAps.category; + this._type = "managed"; + } else if ( + notification.aps && + notification.aps.alert) { + // regular notification + this._alert = notification.aps.alert; + this._sound = notification.aps.sound; + this._badge = notification.aps.badge; + this._category = notification.aps.category; + this._type = "regular"; + } + + Object.keys(notification).filter(key => key !== "aps").forEach(key => { + this._data[key] = notification[key]; + }); + } + + getMessage(): ?string | ?Object { + return this._alert; + } + + getSound(): ?string { + return this._sound; + } + + getBadgeCount(): ?number { + return this._badge; + } + + getCategory(): ?string { + return this._category; + } + + getData(): ?Object { + return this._data; + } + + getType(): ?string { + return this._type; + } +} diff --git a/package.json b/package.json index 90ec6664aef13173a59982ec22df8a4eeb95c991..86cb15529c1de86d008d1f8cea7c459bd72ecbd2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-notifications", - "version": "0.0.5", + "version": "0.0.6", "description": "Advanced Push Notifications (Silent, interactive notifications) for iOS & Android", "author": "Lidan Hifi ", "license": "MIT", @@ -24,6 +24,7 @@ }, "devDependencies": { "babel-eslint": "^6.0.2", + "babel-plugin-transform-class-properties": "^6.6.0", "babel-preset-es2015": "^6.6.0", "babel-preset-react": "^6.5.0", "babel-register": "^6.7.2", @@ -56,6 +57,9 @@ "presets": [ "es2015", "react" + ], + "plugins": [ + "transform-class-properties" ] } } diff --git a/test/index.ios.spec.js b/test/index.ios.spec.js index 4c83ffb0bf3c3b8739f28ddace3957e26da3904f..39ce2094a2c7b736075f4efb15f61ff6d1ca5b61 100644 --- a/test/index.ios.spec.js +++ b/test/index.ios.spec.js @@ -1,6 +1,6 @@ let expect = require("chai").use(require("sinon-chai")).expect; -let proxyquire = require("proxyquire"); -let sinon = require("sinon"); +import proxyquire from "proxyquire"; +import sinon from "sinon"; describe("NotificationsIOS", () => { let deviceEvents = [ @@ -78,4 +78,6 @@ describe("NotificationsIOS", () => { expect(removeEventListenerSpy).to.not.have.been.called; }); }); + + // TODO: Test handle notification with IOSNotification object }); diff --git a/test/notification.ios.spec.js b/test/notification.ios.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..18d88bf10b3edde4008be239f844442e0e467be5 --- /dev/null +++ b/test/notification.ios.spec.js @@ -0,0 +1,121 @@ +import { expect } from "chai"; +import IOSNotification from "../notification.ios"; + +describe("iOS Notification Object", () => { + let notification; + let someBadgeCount = 123, someSound = "someSound", someCategory = "some_notification_category"; + + describe("for a regular iOS push notification", () => { + let regularNativeNotifications = [ + // basic example, without content-available = 1 (aka silent notification) + { + aps: { + alert: { + title: "some title", + body: "some body" + }, + badge: someBadgeCount, + sound: someSound, + category: someCategory + }, + key1: "value1", + key2: "value2" + }, + + // another example, with content-available but also with alert object (should not be a silent notification) + { + aps: { + "content-available": 1, + alert: { + title: "some title", + body: "some body" + }, + badge: someBadgeCount, + sound: someSound, + category: someCategory + }, + key1: "value1", + key2: "value2" + } + ]; + + regularNativeNotifications.forEach(nativeNotification => { + beforeEach(() => { + notification = new IOSNotification(nativeNotification); + }); + + it("should return 'regular' type", function () { + expect(notification.getType()).to.equal("regular"); + }); + + it("should return the alert object", () => { + expect(notification.getMessage()).to.deep.equal(nativeNotification.aps.alert); + }); + + it("should return the sound", () => { + expect(notification.getSound()).to.equal(someSound); + }); + + it("should return the badge count", () => { + expect(notification.getBadgeCount()).to.equal(someBadgeCount); + }); + + it("should return the category", () => { + expect(notification.getCategory()).to.equal(someCategory); + }); + + it("should return the custom data", () => { + expect(notification.getData()).to.deep.equal({ key1: "value1", key2: "value2" }); + }); + }); + }); + + describe("for a managed iOS push notification (silent notification, with managedAps key and content-available = 1)", () => { + let managedNativeNotification = { + aps: { + "content-available": 1 + }, + managedAps: { + action: "CREATE", + notificationId: "1", + alert: { + title: "some title", + body: "some body" + }, + badge: someBadgeCount, + sound: someSound, + category: someCategory + }, + key1: "value1", + key2: "value2" + }; + + beforeEach(() => { + notification = new IOSNotification(managedNativeNotification); + }); + + it("should return 'managed' type", function () { + expect(notification.getType()).to.equal("managed"); + }); + + it("should return the alert object", () => { + expect(notification.getMessage()).to.equal(managedNativeNotification.managedAps.alert); + }); + + it("should return the sound", () => { + expect(notification.getSound()).to.equal(someSound); + }); + + it("should return the badge count", () => { + expect(notification.getBadgeCount()).to.equal(someBadgeCount); + }); + + it("should return the category", () => { + expect(notification.getCategory()).to.equal(someCategory); + }); + + it("should return the custom data", () => { + expect(notification.getData()).to.deep.equal({ managedAps: managedNativeNotification.managedAps, key1: "value1", key2: "value2" }); + }); + }); +});