diff --git a/.gitignore b/.gitignore index 82b4d3ace..b46bdf13c 100644 --- a/.gitignore +++ b/.gitignore @@ -193,4 +193,4 @@ package-lock.json .history # Typescript build -lib/dist/ +# lib/dist/ diff --git a/lib/android/app/src/main/java/com/wix/reactnativenotifications/RNNotificationsModule.java b/lib/android/app/src/main/java/com/wix/reactnativenotifications/RNNotificationsModule.java index 90969b273..8239044c2 100644 --- a/lib/android/app/src/main/java/com/wix/reactnativenotifications/RNNotificationsModule.java +++ b/lib/android/app/src/main/java/com/wix/reactnativenotifications/RNNotificationsModule.java @@ -97,6 +97,11 @@ public void getInitialNotification(final Promise promise) { } } + @ReactMethod + public void getInitialAction(final Promise promise) { + promise.resolve(null); + } + @ReactMethod public void postLocalNotification(ReadableMap notificationPropsMap, int notificationId) { if(BuildConfig.DEBUG) Log.d(LOGTAG, "Native method invocation: postLocalNotification"); diff --git a/lib/dist/DTO/Notification.d.ts b/lib/dist/DTO/Notification.d.ts new file mode 100644 index 000000000..7b2b3b191 --- /dev/null +++ b/lib/dist/DTO/Notification.d.ts @@ -0,0 +1,11 @@ +export declare class Notification { + identifier: string; + payload: any; + constructor(payload: object); + get title(): string; + get body(): string; + get sound(): string; + get badge(): number; + get type(): string; + get thread(): string; +} diff --git a/lib/dist/DTO/Notification.js b/lib/dist/DTO/Notification.js new file mode 100644 index 000000000..54874f4f8 --- /dev/null +++ b/lib/dist/DTO/Notification.js @@ -0,0 +1,30 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Notification = void 0; +class Notification { + identifier; + payload; + constructor(payload) { + this.payload = payload; + this.identifier = this.payload.identifier; + } + get title() { + return this.payload.title; + } + get body() { + return this.payload.body; + } + get sound() { + return this.payload.sound; + } + get badge() { + return this.payload.badge; + } + get type() { + return this.payload.type; + } + get thread() { + return this.payload.thread; + } +} +exports.Notification = Notification; diff --git a/lib/dist/DTO/Notification.test.d.ts b/lib/dist/DTO/Notification.test.d.ts new file mode 100644 index 000000000..cb0ff5c3b --- /dev/null +++ b/lib/dist/DTO/Notification.test.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/lib/dist/DTO/Notification.test.js b/lib/dist/DTO/Notification.test.js new file mode 100644 index 000000000..376aa25b3 --- /dev/null +++ b/lib/dist/DTO/Notification.test.js @@ -0,0 +1,52 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Notification_1 = require("./Notification"); +const NotificationIOS_1 = require("./NotificationIOS"); +const NotificationAndroid_1 = require("./NotificationAndroid"); +describe('Notification', () => { + it('Should create notification with payload', () => { + const payload = { p: 'p' }; + const notification = new Notification_1.Notification(payload); + expect(notification.payload).toEqual(payload); + }); + it('Should create iOS notification with identifier', () => { + const payload = { identifier: 'identifier' }; + const notification = new NotificationIOS_1.NotificationIOS(payload); + expect(notification.identifier).toEqual(payload.identifier); + }); + it('Should create Android notification with identifier', () => { + const payload = { 'google.message_id': 'identifier' }; + const notification = new NotificationAndroid_1.NotificationAndroid(payload); + expect(notification.identifier).toEqual('identifier'); + }); + it('Should return title from payload', () => { + const payload = { title: 'title' }; + const notification = new Notification_1.Notification(payload); + expect(notification.title).toEqual(payload.title); + }); + it('Should return body from payload', () => { + const payload = { body: 'body' }; + const notification = new Notification_1.Notification(payload); + expect(notification.body).toEqual(payload.body); + }); + it('Should return sound from payload', () => { + const payload = { sound: 'sound.mp4' }; + const notification = new Notification_1.Notification(payload); + expect(notification.sound).toEqual(payload.sound); + }); + it('Should return badge from payload', () => { + const payload = { badge: 1 }; + const notification = new Notification_1.Notification(payload); + expect(notification.badge).toEqual(payload.badge); + }); + it('Should return type from payload', () => { + const payload = { type: 'type' }; + const notification = new Notification_1.Notification(payload); + expect(notification.type).toEqual(payload.type); + }); + it('Should return thread from payload', () => { + const payload = { thread: 'thread' }; + const notification = new Notification_1.Notification(payload); + expect(notification.thread).toEqual(payload.thread); + }); +}); diff --git a/lib/dist/DTO/NotificationAndroid.d.ts b/lib/dist/DTO/NotificationAndroid.d.ts new file mode 100644 index 000000000..8bdcb9b28 --- /dev/null +++ b/lib/dist/DTO/NotificationAndroid.d.ts @@ -0,0 +1,7 @@ +import { Notification } from './Notification'; +export declare class NotificationAndroid extends Notification { + constructor(payload: object); + get title(): string; + get body(): string; + get sound(): string; +} diff --git a/lib/dist/DTO/NotificationAndroid.js b/lib/dist/DTO/NotificationAndroid.js new file mode 100644 index 000000000..9dec9f71f --- /dev/null +++ b/lib/dist/DTO/NotificationAndroid.js @@ -0,0 +1,20 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.NotificationAndroid = void 0; +const Notification_1 = require("./Notification"); +class NotificationAndroid extends Notification_1.Notification { + constructor(payload) { + super(payload); + this.identifier = this.payload["google.message_id"]; + } + get title() { + return this.payload.title; + } + get body() { + return this.payload.body; + } + get sound() { + return this.payload.sound; + } +} +exports.NotificationAndroid = NotificationAndroid; diff --git a/lib/dist/DTO/NotificationAndroid.test.d.ts b/lib/dist/DTO/NotificationAndroid.test.d.ts new file mode 100644 index 000000000..cb0ff5c3b --- /dev/null +++ b/lib/dist/DTO/NotificationAndroid.test.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/lib/dist/DTO/NotificationAndroid.test.js b/lib/dist/DTO/NotificationAndroid.test.js new file mode 100644 index 000000000..706541c2f --- /dev/null +++ b/lib/dist/DTO/NotificationAndroid.test.js @@ -0,0 +1,25 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const NotificationAndroid_1 = require("./NotificationAndroid"); +describe('Notification', () => { + it('Should create notification with payload', () => { + const payload = { p: 'p' }; + const notification = new NotificationAndroid_1.NotificationAndroid(payload); + expect(notification.payload).toEqual(payload); + }); + it('Should return title from payload', () => { + const payload = { title: 'title', body: 'body' }; + const notification = new NotificationAndroid_1.NotificationAndroid(payload); + expect(notification.title).toEqual('title'); + }); + it('Should return body from payload', () => { + const payload = { title: 'title', body: 'body' }; + const notification = new NotificationAndroid_1.NotificationAndroid(payload); + expect(notification.body).toEqual('body'); + }); + it('Should return sound from payload', () => { + const payload = { title: 'title', sound: 'sound.wav' }; + const notification = new NotificationAndroid_1.NotificationAndroid(payload); + expect(notification.sound).toEqual('sound.wav'); + }); +}); diff --git a/lib/dist/DTO/NotificationFactory.d.ts b/lib/dist/DTO/NotificationFactory.d.ts new file mode 100644 index 000000000..49c7b17c6 --- /dev/null +++ b/lib/dist/DTO/NotificationFactory.d.ts @@ -0,0 +1,4 @@ +import { Notification } from './Notification'; +export declare class NotificationFactory { + fromPayload(payload: any): Notification; +} diff --git a/lib/dist/DTO/NotificationFactory.js b/lib/dist/DTO/NotificationFactory.js new file mode 100644 index 000000000..1c40cbaef --- /dev/null +++ b/lib/dist/DTO/NotificationFactory.js @@ -0,0 +1,18 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.NotificationFactory = void 0; +const Notification_1 = require("./Notification"); +const NotificationIOS_1 = require("./NotificationIOS"); +const NotificationAndroid_1 = require("./NotificationAndroid"); +const react_native_1 = require("react-native"); +class NotificationFactory { + fromPayload(payload) { + if (react_native_1.Platform.OS === 'ios') { + return payload.aps ? new NotificationIOS_1.NotificationIOS(payload) : new Notification_1.Notification(payload); + } + else { + return new NotificationAndroid_1.NotificationAndroid(payload); + } + } +} +exports.NotificationFactory = NotificationFactory; diff --git a/lib/dist/DTO/NotificationIOS.d.ts b/lib/dist/DTO/NotificationIOS.d.ts new file mode 100644 index 000000000..ed2616e2b --- /dev/null +++ b/lib/dist/DTO/NotificationIOS.d.ts @@ -0,0 +1,12 @@ +import { Notification } from './Notification'; +export declare class NotificationIOS extends Notification { + identifier: string; + constructor(payload: object); + get aps(): any; + get alert(): any; + get title(): string; + get body(): string; + get sound(): string; + get badge(): number; + get thread(): string; +} diff --git a/lib/dist/DTO/NotificationIOS.js b/lib/dist/DTO/NotificationIOS.js new file mode 100644 index 000000000..ef541240d --- /dev/null +++ b/lib/dist/DTO/NotificationIOS.js @@ -0,0 +1,41 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.NotificationIOS = void 0; +const Notification_1 = require("./Notification"); +const _ = require("lodash"); +class NotificationIOS extends Notification_1.Notification { + identifier; + constructor(payload) { + super(payload); + this.identifier = this.payload.identifier; + } + get aps() { + return this.payload.aps || {}; + } + get alert() { + if (_.isObject(this.aps.alert)) { + return this.aps.alert; + } + else if (_.isString(this.aps.alert)) { + return { + body: this.aps.alert + }; + } + } + get title() { + return this.alert.title; + } + get body() { + return this.alert.body; + } + get sound() { + return this.aps.sound; + } + get badge() { + return this.aps.badge; + } + get thread() { + return this.aps.thread; + } +} +exports.NotificationIOS = NotificationIOS; diff --git a/lib/dist/DTO/NotificationIOS.test.d.ts b/lib/dist/DTO/NotificationIOS.test.d.ts new file mode 100644 index 000000000..cb0ff5c3b --- /dev/null +++ b/lib/dist/DTO/NotificationIOS.test.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/lib/dist/DTO/NotificationIOS.test.js b/lib/dist/DTO/NotificationIOS.test.js new file mode 100644 index 000000000..bd5d6f196 --- /dev/null +++ b/lib/dist/DTO/NotificationIOS.test.js @@ -0,0 +1,58 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const NotificationIOS_1 = require("./NotificationIOS"); +describe('Notification', () => { + it('Should create notification with payload', () => { + const payload = { p: 'p' }; + const notification = new NotificationIOS_1.NotificationIOS(payload); + expect(notification.payload).toEqual(payload); + }); + it('Should create notification with valid aps', () => { + const aps = { alert: {} }; + const payload = { aps }; + const notification = new NotificationIOS_1.NotificationIOS(payload); + expect(notification.aps).toEqual(aps); + }); + it('Should create notification with empy aps', () => { + const payload = { aps: undefined }; + const notification = new NotificationIOS_1.NotificationIOS(payload); + expect(notification.aps).toEqual({}); + }); + it('Should return alert object', () => { + const payload = { aps: { alert: { title: 'title' } } }; + const notification = new NotificationIOS_1.NotificationIOS(payload); + expect(notification.alert).toEqual(payload.aps.alert); + }); + it('Should return alert object when alert is string', () => { + const payload = { aps: { alert: 'title' } }; + const notification = new NotificationIOS_1.NotificationIOS(payload); + expect(notification.alert).toEqual({ + body: 'title' + }); + }); + it('Should return title from alert', () => { + const payload = { aps: { alert: { title: 'title' } } }; + const notification = new NotificationIOS_1.NotificationIOS(payload); + expect(notification.title).toEqual('title'); + }); + it('Should return body from alert', () => { + const payload = { aps: { alert: { title: 'title', body: 'body' } } }; + const notification = new NotificationIOS_1.NotificationIOS(payload); + expect(notification.body).toEqual('body'); + }); + it('Should return badge from aps', () => { + const payload = { aps: { badge: 0 } }; + const notification = new NotificationIOS_1.NotificationIOS(payload); + expect(notification.badge).toEqual(0); + }); + it('Should return sound from aps', () => { + const payload = { aps: { sound: 'sound.wav' } }; + const notification = new NotificationIOS_1.NotificationIOS(payload); + expect(notification.sound).toEqual('sound.wav'); + }); + it('Should return thread from aps', () => { + const payload = { aps: { thread: 'thread' } }; + const notification = new NotificationIOS_1.NotificationIOS(payload); + expect(notification.thread).toEqual('thread'); + }); +}); diff --git a/lib/dist/Notifications.d.ts b/lib/dist/Notifications.d.ts new file mode 100644 index 000000000..1884271e3 --- /dev/null +++ b/lib/dist/Notifications.d.ts @@ -0,0 +1,65 @@ +import { EventsRegistry } from './events/EventsRegistry'; +import { Notification } from './DTO/Notification'; +import { NotificationCategory } from './interfaces/NotificationCategory'; +import { NotificationChannel } from './interfaces/NotificationChannel'; +import { NotificationsIOS } from './NotificationsIOS'; +import { NotificationsAndroid } from './NotificationsAndroid'; +import { NotificationPermissionOptions } from './interfaces/NotificationPermissions'; +export declare class NotificationsRoot { + readonly _ios: NotificationsIOS; + readonly _android: NotificationsAndroid; + private readonly notificationFactory; + private readonly nativeEventsReceiver; + private readonly nativeCommandsSender; + private readonly commands; + private readonly eventsRegistry; + private readonly eventsRegistryIOS; + private readonly uniqueIdProvider; + private readonly completionCallbackWrapper; + constructor(); + /** + * registerRemoteNotifications + */ + registerRemoteNotifications(options?: NotificationPermissionOptions): void; + /** + * postLocalNotification + */ + postLocalNotification(notification: Notification, id?: number): number; + /** + * getInitialNotification + */ + getInitialNotification(): Promise; + /** + * getInitialAction + */ + getInitialAction(): Promise; + /** + * setCategories + */ + setCategories(categories: [NotificationCategory?]): void; + /** + * cancelLocalNotification + */ + cancelLocalNotification(notificationId: number): void; + /** + * removeAllDeliveredNotifications + */ + removeAllDeliveredNotifications(): void; + /** + * isRegisteredForRemoteNotifications + */ + isRegisteredForRemoteNotifications(): Promise; + /** + * setNotificationChannel + */ + setNotificationChannel(notificationChannel: NotificationChannel): void; + /** + * Obtain the events registry instance + */ + events(): EventsRegistry; + /** + * ios/android getters + */ + get ios(): NotificationsIOS; + get android(): NotificationsAndroid; +} diff --git a/lib/dist/Notifications.js b/lib/dist/Notifications.js new file mode 100644 index 000000000..8d8a8d23c --- /dev/null +++ b/lib/dist/Notifications.js @@ -0,0 +1,108 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.NotificationsRoot = void 0; +const NativeCommandsSender_1 = require("./adapters/NativeCommandsSender"); +const NativeEventsReceiver_1 = require("./adapters/NativeEventsReceiver"); +const Commands_1 = require("./commands/Commands"); +const EventsRegistry_1 = require("./events/EventsRegistry"); +const EventsRegistryIOS_1 = require("./events/EventsRegistryIOS"); +const UniqueIdProvider_1 = require("./adapters/UniqueIdProvider"); +const CompletionCallbackWrapper_1 = require("./adapters/CompletionCallbackWrapper"); +const NotificationsIOS_1 = require("./NotificationsIOS"); +const NotificationsAndroid_1 = require("./NotificationsAndroid"); +const NotificationFactory_1 = require("./DTO/NotificationFactory"); +class NotificationsRoot { + _ios; + _android; + notificationFactory; + nativeEventsReceiver; + nativeCommandsSender; + commands; + eventsRegistry; + eventsRegistryIOS; + uniqueIdProvider; + completionCallbackWrapper; + constructor() { + this.notificationFactory = new NotificationFactory_1.NotificationFactory(); + this.nativeEventsReceiver = new NativeEventsReceiver_1.NativeEventsReceiver(this.notificationFactory); + this.nativeCommandsSender = new NativeCommandsSender_1.NativeCommandsSender(); + this.completionCallbackWrapper = new CompletionCallbackWrapper_1.CompletionCallbackWrapper(this.nativeCommandsSender); + this.uniqueIdProvider = new UniqueIdProvider_1.UniqueIdProvider(); + this.commands = new Commands_1.Commands(this.nativeCommandsSender, this.uniqueIdProvider, this.notificationFactory); + this.eventsRegistry = new EventsRegistry_1.EventsRegistry(this.nativeEventsReceiver, this.completionCallbackWrapper); + this.eventsRegistryIOS = new EventsRegistryIOS_1.EventsRegistryIOS(this.nativeEventsReceiver, this.completionCallbackWrapper); + this._ios = new NotificationsIOS_1.NotificationsIOS(this.commands, this.eventsRegistryIOS); + this._android = new NotificationsAndroid_1.NotificationsAndroid(this.commands); + } + /** + * registerRemoteNotifications + */ + registerRemoteNotifications(options) { + this.ios.registerRemoteNotifications(options); + this.android.registerRemoteNotifications(); + } + /** + * postLocalNotification + */ + postLocalNotification(notification, id) { + return this.commands.postLocalNotification(notification, id); + } + /** + * getInitialNotification + */ + getInitialNotification() { + return this.commands.getInitialNotification(); + } + /** + * getInitialAction + */ + getInitialAction() { + return this.commands.getInitialAction(); + } + /** + * setCategories + */ + setCategories(categories) { + this.commands.setCategories(categories); + } + /** + * cancelLocalNotification + */ + cancelLocalNotification(notificationId) { + return this.commands.cancelLocalNotification(notificationId); + } + /** + * removeAllDeliveredNotifications + */ + removeAllDeliveredNotifications() { + return this.commands.removeAllDeliveredNotifications(); + } + /** + * isRegisteredForRemoteNotifications + */ + isRegisteredForRemoteNotifications() { + return this.commands.isRegisteredForRemoteNotifications(); + } + /** + * setNotificationChannel + */ + setNotificationChannel(notificationChannel) { + return this.android.setNotificationChannel(notificationChannel); + } + /** + * Obtain the events registry instance + */ + events() { + return this.eventsRegistry; + } + /** + * ios/android getters + */ + get ios() { + return this._ios; + } + get android() { + return this._android; + } +} +exports.NotificationsRoot = NotificationsRoot; diff --git a/lib/dist/NotificationsAndroid.d.ts b/lib/dist/NotificationsAndroid.d.ts new file mode 100644 index 000000000..83a020234 --- /dev/null +++ b/lib/dist/NotificationsAndroid.d.ts @@ -0,0 +1,14 @@ +import { Commands } from './commands/Commands'; +import { NotificationChannel } from './interfaces/NotificationChannel'; +export declare class NotificationsAndroid { + private readonly commands; + constructor(commands: Commands); + /** + * Refresh FCM token + */ + registerRemoteNotifications(): void; + /** + * setNotificationChannel + */ + setNotificationChannel(notificationChannel: NotificationChannel): void; +} diff --git a/lib/dist/NotificationsAndroid.js b/lib/dist/NotificationsAndroid.js new file mode 100644 index 000000000..9d2218c11 --- /dev/null +++ b/lib/dist/NotificationsAndroid.js @@ -0,0 +1,33 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.NotificationsAndroid = void 0; +const react_native_1 = require("react-native"); +class NotificationsAndroid { + commands; + constructor(commands) { + this.commands = commands; + return new Proxy(this, { + get(target, name) { + if (react_native_1.Platform.OS === 'android') { + return target[name]; + } + else { + return () => { }; + } + } + }); + } + /** + * Refresh FCM token + */ + registerRemoteNotifications() { + this.commands.refreshToken(); + } + /** + * setNotificationChannel + */ + setNotificationChannel(notificationChannel) { + return this.commands.setNotificationChannel(notificationChannel); + } +} +exports.NotificationsAndroid = NotificationsAndroid; diff --git a/lib/dist/NotificationsIOS.d.ts b/lib/dist/NotificationsIOS.d.ts new file mode 100644 index 000000000..b035581fb --- /dev/null +++ b/lib/dist/NotificationsIOS.d.ts @@ -0,0 +1,51 @@ +import { Notification } from './DTO/Notification'; +import { Commands } from './commands/Commands'; +import { EventsRegistryIOS } from './events/EventsRegistryIOS'; +import { NotificationPermissionOptions } from './interfaces/NotificationPermissions'; +export declare class NotificationsIOS { + private readonly commands; + private readonly eventsRegistry; + constructor(commands: Commands, eventsRegistry: EventsRegistryIOS); + /** + * Request permissions to send remote notifications + */ + registerRemoteNotifications(options?: NotificationPermissionOptions): void; + /** + * Unregister for all remote notifications received via Apple Push Notification service + */ + abandonPermissions(): void; + /** + * registerPushKit + */ + registerPushKit(): void; + /** + * getBadgeCount + */ + getBadgeCount(): Promise; + /** + * setBadgeCount + * @param count number of the new badge count + */ + setBadgeCount(count: number): void; + /** + * cancelAllLocalNotifications + */ + cancelAllLocalNotifications(): void; + /** + * checkPermissions + */ + checkPermissions(): Promise; + /** + * removeDeliveredNotifications + * @param identifiers Array of notification identifiers + */ + removeDeliveredNotifications(identifiers: Array): void; + /** + * getDeliveredNotifications + */ + getDeliveredNotifications(): Promise; + /** + * Obtain the events registry instance + */ + events(): EventsRegistryIOS; +} diff --git a/lib/dist/NotificationsIOS.js b/lib/dist/NotificationsIOS.js new file mode 100644 index 000000000..3e47a7a88 --- /dev/null +++ b/lib/dist/NotificationsIOS.js @@ -0,0 +1,85 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.NotificationsIOS = void 0; +const react_native_1 = require("react-native"); +class NotificationsIOS { + commands; + eventsRegistry; + constructor(commands, eventsRegistry) { + this.commands = commands; + this.eventsRegistry = eventsRegistry; + return new Proxy(this, { + get(target, name) { + if (react_native_1.Platform.OS === 'ios') { + return target[name]; + } + else { + return () => { }; + } + } + }); + } + /** + * Request permissions to send remote notifications + */ + registerRemoteNotifications(options) { + return this.commands.requestPermissions(options); + } + /** + * Unregister for all remote notifications received via Apple Push Notification service + */ + abandonPermissions() { + return this.commands.abandonPermissions(); + } + /** + * registerPushKit + */ + registerPushKit() { + return this.commands.registerPushKit(); + } + /** + * getBadgeCount + */ + getBadgeCount() { + return this.commands.getBadgeCount(); + } + /** + * setBadgeCount + * @param count number of the new badge count + */ + setBadgeCount(count) { + return this.commands.setBadgeCount(count); + } + /** + * cancelAllLocalNotifications + */ + cancelAllLocalNotifications() { + this.commands.cancelAllLocalNotifications(); + } + /** + * checkPermissions + */ + checkPermissions() { + return this.commands.checkPermissions(); + } + /** + * removeDeliveredNotifications + * @param identifiers Array of notification identifiers + */ + removeDeliveredNotifications(identifiers) { + return this.commands.removeDeliveredNotifications(identifiers); + } + /** + * getDeliveredNotifications + */ + getDeliveredNotifications() { + return this.commands.getDeliveredNotifications(); + } + /** + * Obtain the events registry instance + */ + events() { + return this.eventsRegistry; + } +} +exports.NotificationsIOS = NotificationsIOS; diff --git a/lib/dist/adapters/CompletionCallbackWrapper.d.ts b/lib/dist/adapters/CompletionCallbackWrapper.d.ts new file mode 100644 index 000000000..01e6f8321 --- /dev/null +++ b/lib/dist/adapters/CompletionCallbackWrapper.d.ts @@ -0,0 +1,11 @@ +import { NativeCommandsSender } from './NativeCommandsSender'; +import { Notification } from ".."; +import { NotificationActionResponse } from '../interfaces/NotificationActionResponse'; +export declare class CompletionCallbackWrapper { + private readonly nativeCommandsSender; + constructor(nativeCommandsSender: NativeCommandsSender); + wrapReceivedBackgroundCallback(callback: Function): (notification: Notification) => void; + wrapReceivedForegroundCallback(callback: Function): (notification: Notification) => void; + private wrapReceivedAndInvoke; + wrapOpenedCallback(callback: Function): (notification: object, actionResponse?: NotificationActionResponse) => void; +} diff --git a/lib/dist/adapters/CompletionCallbackWrapper.js b/lib/dist/adapters/CompletionCallbackWrapper.js new file mode 100644 index 000000000..d581e9f57 --- /dev/null +++ b/lib/dist/adapters/CompletionCallbackWrapper.js @@ -0,0 +1,45 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CompletionCallbackWrapper = void 0; +const react_native_1 = require("react-native"); +class CompletionCallbackWrapper { + nativeCommandsSender; + constructor(nativeCommandsSender) { + this.nativeCommandsSender = nativeCommandsSender; + } + wrapReceivedBackgroundCallback(callback) { + return (notification) => { + this.wrapReceivedAndInvoke(callback, notification, true); + }; + } + wrapReceivedForegroundCallback(callback) { + return (notification) => { + this.wrapReceivedAndInvoke(callback, notification, false); + }; + } + wrapReceivedAndInvoke(callback, notification, background) { + const completion = (response) => { + if (react_native_1.Platform.OS === 'ios') { + const identifier = notification.identifier; + if (background) { + this.nativeCommandsSender.finishHandlingBackgroundAction(identifier, response); + } + else { + this.nativeCommandsSender.finishPresentingNotification(identifier, response); + } + } + }; + callback(notification, completion); + } + wrapOpenedCallback(callback) { + return (notification, actionResponse) => { + const completion = () => { + if (react_native_1.Platform.OS === 'ios') { + this.nativeCommandsSender.finishHandlingAction(notification.identifier); + } + }; + callback(notification, completion, actionResponse); + }; + } +} +exports.CompletionCallbackWrapper = CompletionCallbackWrapper; diff --git a/lib/dist/adapters/NativeCommandsSender.d.ts b/lib/dist/adapters/NativeCommandsSender.d.ts new file mode 100644 index 000000000..9f8b4cffe --- /dev/null +++ b/lib/dist/adapters/NativeCommandsSender.d.ts @@ -0,0 +1,32 @@ +import { Notification } from '../DTO/Notification'; +import { NotificationCompletion } from '../interfaces/NotificationCompletion'; +import { NotificationPermissions } from '../interfaces/NotificationPermissions'; +import { NotificationCategory } from '../interfaces/NotificationCategory'; +import { NotificationChannel } from '../interfaces/NotificationChannel'; +import { NotificationPermissionOptions } from '../interfaces/NotificationPermissions'; +import { NotificationResponse } from '../interfaces/NotificationEvents'; +export declare class NativeCommandsSender { + private readonly nativeCommandsModule; + constructor(); + postLocalNotification(notification: Notification, id: number): void; + getInitialNotification(): Promise; + getInitialAction(): Promise; + requestPermissions(options?: NotificationPermissionOptions): void; + abandonPermissions(): void; + refreshToken(): void; + registerPushKit(): void; + setCategories(categories: [NotificationCategory?]): void; + getBadgeCount(): Promise; + setBadgeCount(count: number): void; + cancelLocalNotification(notificationId: number): void; + cancelAllLocalNotifications(): void; + isRegisteredForRemoteNotifications(): Promise; + checkPermissions(): Promise; + removeAllDeliveredNotifications(): void; + removeDeliveredNotifications(identifiers: Array): void; + getDeliveredNotifications(): Promise; + finishPresentingNotification(notificationId: string, notificationCompletion: NotificationCompletion): void; + finishHandlingAction(notificationId: string): void; + setNotificationChannel(notificationChannel: NotificationChannel): void; + finishHandlingBackgroundAction(notificationId: string, backgroundFetchResult: string): void; +} diff --git a/lib/dist/adapters/NativeCommandsSender.js b/lib/dist/adapters/NativeCommandsSender.js new file mode 100644 index 000000000..5febfbd8d --- /dev/null +++ b/lib/dist/adapters/NativeCommandsSender.js @@ -0,0 +1,74 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.NativeCommandsSender = void 0; +const react_native_1 = require("react-native"); +class NativeCommandsSender { + nativeCommandsModule; + constructor() { + this.nativeCommandsModule = react_native_1.NativeModules.RNBridgeModule; + } + postLocalNotification(notification, id) { + return this.nativeCommandsModule.postLocalNotification(notification, id); + } + getInitialNotification() { + return this.nativeCommandsModule.getInitialNotification(); + } + getInitialAction() { + return this.nativeCommandsModule.getInitialAction(); + } + requestPermissions(options) { + return this.nativeCommandsModule.requestPermissions(options || {}); + } + abandonPermissions() { + return this.nativeCommandsModule.abandonPermissions(); + } + refreshToken() { + this.nativeCommandsModule.refreshToken(); + } + registerPushKit() { + return this.nativeCommandsModule.registerPushKit(); + } + setCategories(categories) { + this.nativeCommandsModule.setCategories(categories); + } + getBadgeCount() { + return this.nativeCommandsModule.getBadgeCount(); + } + setBadgeCount(count) { + this.nativeCommandsModule.setBadgeCount(count); + } + cancelLocalNotification(notificationId) { + this.nativeCommandsModule.cancelLocalNotification(notificationId); + } + cancelAllLocalNotifications() { + this.nativeCommandsModule.cancelAllLocalNotifications(); + } + isRegisteredForRemoteNotifications() { + return this.nativeCommandsModule.isRegisteredForRemoteNotifications(); + } + checkPermissions() { + return this.nativeCommandsModule.checkPermissions(); + } + removeAllDeliveredNotifications() { + return this.nativeCommandsModule.removeAllDeliveredNotifications(); + } + removeDeliveredNotifications(identifiers) { + return this.nativeCommandsModule.removeDeliveredNotifications(identifiers); + } + getDeliveredNotifications() { + return this.nativeCommandsModule.getDeliveredNotifications(); + } + finishPresentingNotification(notificationId, notificationCompletion) { + this.nativeCommandsModule.finishPresentingNotification(notificationId, notificationCompletion); + } + finishHandlingAction(notificationId) { + this.nativeCommandsModule.finishHandlingAction(notificationId); + } + setNotificationChannel(notificationChannel) { + this.nativeCommandsModule.setNotificationChannel(notificationChannel); + } + finishHandlingBackgroundAction(notificationId, backgroundFetchResult) { + this.nativeCommandsModule.finishHandlingBackgroundAction(notificationId, backgroundFetchResult); + } +} +exports.NativeCommandsSender = NativeCommandsSender; diff --git a/lib/dist/adapters/NativeEventsReceiver.d.ts b/lib/dist/adapters/NativeEventsReceiver.d.ts new file mode 100644 index 000000000..890230340 --- /dev/null +++ b/lib/dist/adapters/NativeEventsReceiver.d.ts @@ -0,0 +1,19 @@ +import { EmitterSubscription } from 'react-native'; +import { Registered, RegistrationError, RegisteredPushKit } from '../interfaces/NotificationEvents'; +import { Notification } from '../DTO/Notification'; +import { NotificationActionResponse } from '../interfaces/NotificationActionResponse'; +import { NotificationFactory } from '../DTO/NotificationFactory'; +export declare class NativeEventsReceiver { + private readonly notificationFactory; + private emitter; + constructor(notificationFactory?: NotificationFactory); + registerRemoteNotificationsRegistered(callback: (event: Registered) => void): EmitterSubscription; + appNotificationSettingsLinked(callback: () => void): EmitterSubscription; + registerPushKitRegistered(callback: (event: RegisteredPushKit) => void): EmitterSubscription; + registerNotificationReceived(callback: (notification: Notification) => void): EmitterSubscription; + registerNotificationReceivedBackground(callback: (notification: Notification) => void): EmitterSubscription; + registerPushKitNotificationReceived(callback: (event: object) => void): EmitterSubscription; + registerNotificationOpened(callback: (notification: Notification, actionResponse?: NotificationActionResponse) => void): EmitterSubscription; + registerRemoteNotificationsRegistrationFailed(callback: (event: RegistrationError) => void): EmitterSubscription; + registerRemoteNotificationsRegistrationDenied(callback: () => void): EmitterSubscription; +} diff --git a/lib/dist/adapters/NativeEventsReceiver.js b/lib/dist/adapters/NativeEventsReceiver.js new file mode 100644 index 000000000..db48a0d64 --- /dev/null +++ b/lib/dist/adapters/NativeEventsReceiver.js @@ -0,0 +1,49 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.NativeEventsReceiver = void 0; +const react_native_1 = require("react-native"); +const NotificationActionResponse_1 = require("../interfaces/NotificationActionResponse"); +const NotificationFactory_1 = require("../DTO/NotificationFactory"); +class NativeEventsReceiver { + notificationFactory; + emitter; + constructor(notificationFactory = new NotificationFactory_1.NotificationFactory()) { + this.notificationFactory = notificationFactory; + this.emitter = new react_native_1.NativeEventEmitter(react_native_1.NativeModules.RNEventEmitter); + } + registerRemoteNotificationsRegistered(callback) { + return this.emitter.addListener('remoteNotificationsRegistered', callback); + } + appNotificationSettingsLinked(callback) { + return this.emitter.addListener('appNotificationSettingsLinked', callback); + } + registerPushKitRegistered(callback) { + return this.emitter.addListener('pushKitRegistered', callback); + } + registerNotificationReceived(callback) { + return this.emitter.addListener('notificationReceived', (payload) => { + callback(this.notificationFactory.fromPayload(payload)); + }); + } + registerNotificationReceivedBackground(callback) { + return this.emitter.addListener('notificationReceivedBackground', (payload) => { + callback(this.notificationFactory.fromPayload(payload)); + }); + } + registerPushKitNotificationReceived(callback) { + return this.emitter.addListener('pushKitNotificationReceived', callback); + } + registerNotificationOpened(callback) { + return this.emitter.addListener('notificationOpened', (response) => { + const action = response.action ? new NotificationActionResponse_1.NotificationActionResponse(response.action) : undefined; + callback(this.notificationFactory.fromPayload(response.notification), action); + }); + } + registerRemoteNotificationsRegistrationFailed(callback) { + return this.emitter.addListener('remoteNotificationsRegistrationFailed', callback); + } + registerRemoteNotificationsRegistrationDenied(callback) { + return this.emitter.addListener('remoteNotificationsRegistrationDenied', callback); + } +} +exports.NativeEventsReceiver = NativeEventsReceiver; diff --git a/lib/dist/adapters/UniqueIdProvider.d.ts b/lib/dist/adapters/UniqueIdProvider.d.ts new file mode 100644 index 000000000..8d5ee38ba --- /dev/null +++ b/lib/dist/adapters/UniqueIdProvider.d.ts @@ -0,0 +1,3 @@ +export declare class UniqueIdProvider { + generate(): number; +} diff --git a/lib/dist/adapters/UniqueIdProvider.js b/lib/dist/adapters/UniqueIdProvider.js new file mode 100644 index 000000000..6a4dd18b5 --- /dev/null +++ b/lib/dist/adapters/UniqueIdProvider.js @@ -0,0 +1,10 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.UniqueIdProvider = void 0; +const _ = require("lodash"); +class UniqueIdProvider { + generate() { + return parseInt(_.uniqueId()); + } +} +exports.UniqueIdProvider = UniqueIdProvider; diff --git a/lib/dist/commands/Commands.d.ts b/lib/dist/commands/Commands.d.ts new file mode 100644 index 000000000..af8d20bec --- /dev/null +++ b/lib/dist/commands/Commands.d.ts @@ -0,0 +1,32 @@ +import { NativeCommandsSender } from '../adapters/NativeCommandsSender'; +import { Notification } from '../DTO/Notification'; +import { NotificationCategory } from '../interfaces/NotificationCategory'; +import { NotificationChannel } from '../interfaces/NotificationChannel'; +import { NotificationPermissions } from '../interfaces/NotificationPermissions'; +import { UniqueIdProvider } from '../adapters/UniqueIdProvider'; +import { NotificationFactory } from '../DTO/NotificationFactory'; +import { NotificationPermissionOptions } from '../interfaces/NotificationPermissions'; +export declare class Commands { + private readonly nativeCommandsSender; + private readonly uniqueIdProvider; + private readonly notificationFactory; + constructor(nativeCommandsSender: NativeCommandsSender, uniqueIdProvider: UniqueIdProvider, notificationFactory: NotificationFactory); + postLocalNotification(notification: Notification, id?: number): number; + getInitialNotification(): Promise; + getInitialAction(): Promise; + requestPermissions(options?: NotificationPermissionOptions): void; + abandonPermissions(): void; + registerPushKit(): void; + setCategories(categories: [NotificationCategory?]): void; + getBadgeCount(): Promise; + setBadgeCount(count: number): void; + cancelLocalNotification(notificationId: number): void; + cancelAllLocalNotifications(): void; + isRegisteredForRemoteNotifications(): Promise; + checkPermissions(): Promise; + removeAllDeliveredNotifications(): void; + removeDeliveredNotifications(identifiers: Array): void; + getDeliveredNotifications(): Promise; + refreshToken(): void; + setNotificationChannel(notificationChannel: NotificationChannel): void; +} diff --git a/lib/dist/commands/Commands.js b/lib/dist/commands/Commands.js new file mode 100644 index 000000000..198e3104e --- /dev/null +++ b/lib/dist/commands/Commands.js @@ -0,0 +1,82 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Commands = void 0; +class Commands { + nativeCommandsSender; + uniqueIdProvider; + notificationFactory; + constructor(nativeCommandsSender, uniqueIdProvider, notificationFactory) { + this.nativeCommandsSender = nativeCommandsSender; + this.uniqueIdProvider = uniqueIdProvider; + this.notificationFactory = notificationFactory; + } + postLocalNotification(notification, id) { + const notificationId = id ? id : this.uniqueIdProvider.generate(); + this.nativeCommandsSender.postLocalNotification(notification, notificationId); + return notificationId; + } + async getInitialNotification() { + return this.nativeCommandsSender.getInitialNotification().then((payload) => { + if (payload) { + return this.notificationFactory.fromPayload(payload); + } + return undefined; + }); + } + async getInitialAction() { + return this.nativeCommandsSender.getInitialAction().then((payload) => { + if (payload) { + return this.notificationFactory.fromPayload(payload); + } + return undefined; + }); + } + requestPermissions(options) { + const result = this.nativeCommandsSender.requestPermissions(options); + return result; + } + abandonPermissions() { + const result = this.nativeCommandsSender.abandonPermissions(); + return result; + } + registerPushKit() { + this.nativeCommandsSender.registerPushKit(); + } + setCategories(categories) { + this.nativeCommandsSender.setCategories(categories); + } + getBadgeCount() { + return this.nativeCommandsSender.getBadgeCount(); + } + setBadgeCount(count) { + this.nativeCommandsSender.setBadgeCount(count); + } + cancelLocalNotification(notificationId) { + this.nativeCommandsSender.cancelLocalNotification(notificationId); + } + cancelAllLocalNotifications() { + this.nativeCommandsSender.cancelAllLocalNotifications(); + } + isRegisteredForRemoteNotifications() { + return this.nativeCommandsSender.isRegisteredForRemoteNotifications(); + } + checkPermissions() { + return this.nativeCommandsSender.checkPermissions(); + } + removeAllDeliveredNotifications() { + this.nativeCommandsSender.removeAllDeliveredNotifications(); + } + removeDeliveredNotifications(identifiers) { + return this.nativeCommandsSender.removeDeliveredNotifications(identifiers); + } + getDeliveredNotifications() { + return this.nativeCommandsSender.getDeliveredNotifications(); + } + refreshToken() { + this.nativeCommandsSender.refreshToken(); + } + setNotificationChannel(notificationChannel) { + this.nativeCommandsSender.setNotificationChannel(notificationChannel); + } +} +exports.Commands = Commands; diff --git a/lib/dist/commands/Commands.test.d.ts b/lib/dist/commands/Commands.test.d.ts new file mode 100644 index 000000000..cb0ff5c3b --- /dev/null +++ b/lib/dist/commands/Commands.test.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/lib/dist/commands/Commands.test.js b/lib/dist/commands/Commands.test.js new file mode 100644 index 000000000..c896ee392 --- /dev/null +++ b/lib/dist/commands/Commands.test.js @@ -0,0 +1,236 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const ts_mockito_1 = require("ts-mockito"); +const Commands_1 = require("./Commands"); +const NativeCommandsSender_1 = require("../adapters/NativeCommandsSender"); +const Notification_1 = require("../DTO/Notification"); +const UniqueIdProvider_1 = require("../adapters/UniqueIdProvider"); +const NotificationFactory_1 = require("../DTO/NotificationFactory"); +const NotificationAndroid_1 = require("../DTO/NotificationAndroid"); +const react_native_1 = require("react-native"); +const NotificationIOS_1 = require("../DTO/NotificationIOS"); +describe('Commands', () => { + let uut; + let mockedNativeCommandsSender; + let mockedUniqueIdProvider; + let notificationFactory; + beforeEach(() => { + notificationFactory = new NotificationFactory_1.NotificationFactory(); + mockedNativeCommandsSender = (0, ts_mockito_1.mock)(NativeCommandsSender_1.NativeCommandsSender); + mockedUniqueIdProvider = (0, ts_mockito_1.mock)(UniqueIdProvider_1.UniqueIdProvider); + (0, ts_mockito_1.when)(mockedUniqueIdProvider.generate()).thenCall(() => 12); + uut = new Commands_1.Commands((0, ts_mockito_1.instance)(mockedNativeCommandsSender), (0, ts_mockito_1.instance)(mockedUniqueIdProvider), notificationFactory); + }); + describe('getInitialNotification', () => { + it('sends to native', () => { + uut.getInitialNotification(); + (0, ts_mockito_1.verify)(mockedNativeCommandsSender.getInitialNotification()).called(); + }); + it('Android - returns a promise with the initial notification', async () => { + react_native_1.Platform.OS = 'android'; + const expectedNotification = new NotificationAndroid_1.NotificationAndroid({ 'google.message_id': 'id' }); + (0, ts_mockito_1.when)(mockedNativeCommandsSender.getInitialNotification()).thenResolve({ 'google.message_id': 'id' }); + const result = await uut.getInitialNotification(); + expect(result).toEqual(expectedNotification); + }); + it('Should return undefined initial notification', async () => { + react_native_1.Platform.OS = 'android'; + (0, ts_mockito_1.when)(mockedNativeCommandsSender.getInitialNotification()).thenResolve(); + const result = await uut.getInitialNotification(); + expect(result).toEqual(undefined); + }); + it('iOS - returns a promise with the initial notification', async () => { + react_native_1.Platform.OS = 'ios'; + const expectedNotification = new NotificationIOS_1.NotificationIOS({ identifier: 'id' }); + (0, ts_mockito_1.when)(mockedNativeCommandsSender.getInitialNotification()).thenResolve({ identifier: 'id' }); + const result = await uut.getInitialNotification(); + expect(result).toEqual(expectedNotification); + }); + }); + describe('getInitialAction', () => { + it('sends to native', () => { + uut.getInitialAction(); + (0, ts_mockito_1.verify)(mockedNativeCommandsSender.getInitialAction()).called(); + }); + it('Android - should return undefined initial action', async () => { + react_native_1.Platform.OS = 'android'; + (0, ts_mockito_1.when)(mockedNativeCommandsSender.getInitialAction()).thenResolve(); + const actual = await uut.getInitialAction(); + expect(actual).toEqual(undefined); + }); + it('iOS - should return undefined initial action', async () => { + react_native_1.Platform.OS = 'ios'; + (0, ts_mockito_1.when)(mockedNativeCommandsSender.getInitialAction()).thenResolve(); + const actual = await uut.getInitialAction(); + expect(actual).toEqual(undefined); + }); + it('iOS - returns a promise with the initial action', async () => { + react_native_1.Platform.OS = 'ios'; + const expectedNotification = new Notification_1.Notification({ + identifier: 'id', + payload: { + action: { + identifier: 'id', + text: 'text' + }, + body: 'body', + title: 'title' + } + }); + (0, ts_mockito_1.when)(mockedNativeCommandsSender.getInitialAction()).thenResolve({ identifier: 'id', notification: expectedNotification, action: { identifier: 'id', text: 'text' } }); + const actual = await uut.getInitialAction(); + expect(actual).toEqual(expectedNotification); + }); + }); + describe('requestPermissions', () => { + it('sends to native', () => { + const opts = {}; + uut.requestPermissions(opts); + (0, ts_mockito_1.verify)(mockedNativeCommandsSender.requestPermissions(opts)).called(); + }); + it('sends to native with options', () => { + const opts = { criticalAlert: true }; + uut.requestPermissions(opts); + (0, ts_mockito_1.verify)(mockedNativeCommandsSender.requestPermissions(opts)).called(); + }); + }); + describe('registerPushKit', () => { + it('sends to native', () => { + uut.registerPushKit(); + (0, ts_mockito_1.verify)(mockedNativeCommandsSender.registerPushKit()).called(); + }); + }); + describe('setCategories', () => { + it('sends to native', () => { + const emptyCategoriesArray = []; + uut.setCategories(emptyCategoriesArray); + (0, ts_mockito_1.verify)(mockedNativeCommandsSender.setCategories(emptyCategoriesArray)).called(); + }); + it('sends to native with categories', () => { + const category = { identifier: 'id', actions: [] }; + const categoriesArray = [category]; + uut.setCategories(categoriesArray); + (0, ts_mockito_1.verify)(mockedNativeCommandsSender.setCategories(categoriesArray)).called(); + }); + }); + describe('abandonPermissions', () => { + it('sends to native', () => { + uut.abandonPermissions(); + (0, ts_mockito_1.verify)(mockedNativeCommandsSender.abandonPermissions()).called(); + }); + }); + describe('postLocalNotification', () => { + it('sends to native', () => { + const notification = new Notification_1.Notification({ identifier: 'id' }); + uut.postLocalNotification(notification); + (0, ts_mockito_1.verify)(mockedNativeCommandsSender.postLocalNotification(notification, (0, ts_mockito_1.anyNumber)())).called(); + }); + it('generates unique identifier', () => { + const notification = new Notification_1.Notification({ identifier: 'id' }); + uut.postLocalNotification(notification); + (0, ts_mockito_1.verify)(mockedNativeCommandsSender.postLocalNotification(notification, (0, ts_mockito_1.anyNumber)())).called(); + }); + it('use passed notification id', () => { + const notification = new Notification_1.Notification({ identifier: 'id' }); + const passedId = 2; + uut.postLocalNotification(notification, passedId); + (0, ts_mockito_1.verify)(mockedNativeCommandsSender.postLocalNotification(notification, passedId)).called(); + }); + it('return notification id', () => { + const notification = new Notification_1.Notification({ identifier: 'id' }); + const notificationId = 2; + const response = uut.postLocalNotification(notification, notificationId); + expect(response).toEqual(notificationId); + }); + }); + describe('getBadgeCount', () => { + it('sends to native', () => { + uut.getBadgeCount(); + (0, ts_mockito_1.verify)(mockedNativeCommandsSender.getBadgeCount()).called(); + }); + }); + describe('setBadgeCount', () => { + it('sends to native', () => { + uut.setBadgeCount(10); + (0, ts_mockito_1.verify)(mockedNativeCommandsSender.setBadgeCount(10)).called(); + }); + }); + describe('cancelLocalNotification', () => { + it('sends to native', () => { + const notificationId = 1; + uut.cancelLocalNotification(notificationId); + (0, ts_mockito_1.verify)(mockedNativeCommandsSender.cancelLocalNotification(notificationId)).called(); + }); + }); + describe('cancelAllLocalNotifications', () => { + it('sends to native', () => { + uut.cancelAllLocalNotifications(); + (0, ts_mockito_1.verify)(mockedNativeCommandsSender.cancelAllLocalNotifications()).called(); + }); + }); + describe('isRegisteredForRemoteNotifications', () => { + it('sends to native', () => { + uut.isRegisteredForRemoteNotifications(); + (0, ts_mockito_1.verify)(mockedNativeCommandsSender.isRegisteredForRemoteNotifications()).called(); + }); + it('return positive response from native', async () => { + (0, ts_mockito_1.when)(mockedNativeCommandsSender.isRegisteredForRemoteNotifications()).thenResolve(true); + const isRegistered = await uut.isRegisteredForRemoteNotifications(); + (0, ts_mockito_1.verify)(mockedNativeCommandsSender.isRegisteredForRemoteNotifications()).called(); + expect(isRegistered).toEqual(true); + }); + it('return negative response from native', async () => { + (0, ts_mockito_1.when)(mockedNativeCommandsSender.isRegisteredForRemoteNotifications()).thenResolve(false); + const isRegistered = await uut.isRegisteredForRemoteNotifications(); + expect(isRegistered).toEqual(false); + }); + }); + describe('checkPermissions', () => { + it('sends to native', () => { + uut.checkPermissions(); + (0, ts_mockito_1.verify)(mockedNativeCommandsSender.checkPermissions()).called(); + }); + it('return negative response from native', async () => { + const expectedPermissions = { + badge: false, + alert: true, + sound: false, + carPlay: false, + criticalAlert: false, + providesAppNotificationSettings: false, + provisional: false, + announcement: false, + notificationCenter: true, + lockScreen: false, + }; + (0, ts_mockito_1.when)(mockedNativeCommandsSender.checkPermissions()).thenResolve(expectedPermissions); + const permissions = await uut.checkPermissions(); + expect(permissions).toEqual(expectedPermissions); + }); + }); + describe('removeAllDeliveredNotifications', () => { + it('sends to native', () => { + uut.removeAllDeliveredNotifications(); + (0, ts_mockito_1.verify)(mockedNativeCommandsSender.removeAllDeliveredNotifications()).called(); + }); + }); + describe('removeDeliveredNotifications', () => { + it('sends to native', () => { + const identifiers = ["id1", "id2"]; + uut.removeDeliveredNotifications(identifiers); + (0, ts_mockito_1.verify)(mockedNativeCommandsSender.removeDeliveredNotifications(identifiers)).called(); + }); + }); + describe('getDeliveredNotifications', () => { + it('sends to native', () => { + uut.getDeliveredNotifications(); + (0, ts_mockito_1.verify)(mockedNativeCommandsSender.getDeliveredNotifications()).called(); + }); + }); + describe('refreshToken', () => { + it('sends to native', () => { + uut.refreshToken(); + (0, ts_mockito_1.verify)(mockedNativeCommandsSender.refreshToken()).called(); + }); + }); +}); diff --git a/lib/dist/events/EventsRegistry.d.ts b/lib/dist/events/EventsRegistry.d.ts new file mode 100644 index 000000000..17b37393c --- /dev/null +++ b/lib/dist/events/EventsRegistry.d.ts @@ -0,0 +1,18 @@ +import { EmitterSubscription } from 'react-native'; +import { NativeEventsReceiver } from '../adapters/NativeEventsReceiver'; +import { Registered, RegistrationError } from '../interfaces/NotificationEvents'; +import { NotificationActionResponse } from '../interfaces/NotificationActionResponse'; +import { CompletionCallbackWrapper } from '../adapters/CompletionCallbackWrapper'; +import { Notification } from '../DTO/Notification'; +import { NotificationCompletion, NotificationBackgroundFetchResult } from '../interfaces/NotificationCompletion'; +export declare class EventsRegistry { + private nativeEventsReceiver; + private completionCallbackWrapper; + constructor(nativeEventsReceiver: NativeEventsReceiver, completionCallbackWrapper: CompletionCallbackWrapper); + registerRemoteNotificationsRegistered(callback: (event: Registered) => void): EmitterSubscription; + registerNotificationReceivedForeground(callback: (notification: Notification, completion: (response: NotificationCompletion) => void) => void): EmitterSubscription; + registerNotificationReceivedBackground(callback: (notification: Notification, completion: (response: NotificationBackgroundFetchResult) => void) => void): EmitterSubscription; + registerNotificationOpened(callback: (notification: Notification, completion: () => void, actionResponse?: NotificationActionResponse) => void): EmitterSubscription; + registerRemoteNotificationsRegistrationFailed(callback: (event: RegistrationError) => void): EmitterSubscription; + registerRemoteNotificationsRegistrationDenied(callback: () => void): EmitterSubscription; +} diff --git a/lib/dist/events/EventsRegistry.js b/lib/dist/events/EventsRegistry.js new file mode 100644 index 000000000..37f8a2441 --- /dev/null +++ b/lib/dist/events/EventsRegistry.js @@ -0,0 +1,30 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.EventsRegistry = void 0; +class EventsRegistry { + nativeEventsReceiver; + completionCallbackWrapper; + constructor(nativeEventsReceiver, completionCallbackWrapper) { + this.nativeEventsReceiver = nativeEventsReceiver; + this.completionCallbackWrapper = completionCallbackWrapper; + } + registerRemoteNotificationsRegistered(callback) { + return this.nativeEventsReceiver.registerRemoteNotificationsRegistered(callback); + } + registerNotificationReceivedForeground(callback) { + return this.nativeEventsReceiver.registerNotificationReceived(this.completionCallbackWrapper.wrapReceivedForegroundCallback(callback)); + } + registerNotificationReceivedBackground(callback) { + return this.nativeEventsReceiver.registerNotificationReceivedBackground(this.completionCallbackWrapper.wrapReceivedBackgroundCallback(callback)); + } + registerNotificationOpened(callback) { + return this.nativeEventsReceiver.registerNotificationOpened(this.completionCallbackWrapper.wrapOpenedCallback(callback)); + } + registerRemoteNotificationsRegistrationFailed(callback) { + return this.nativeEventsReceiver.registerRemoteNotificationsRegistrationFailed(callback); + } + registerRemoteNotificationsRegistrationDenied(callback) { + return this.nativeEventsReceiver.registerRemoteNotificationsRegistrationDenied(callback); + } +} +exports.EventsRegistry = EventsRegistry; diff --git a/lib/dist/events/EventsRegistry.test.d.ts b/lib/dist/events/EventsRegistry.test.d.ts new file mode 100644 index 000000000..cb0ff5c3b --- /dev/null +++ b/lib/dist/events/EventsRegistry.test.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/lib/dist/events/EventsRegistry.test.js b/lib/dist/events/EventsRegistry.test.js new file mode 100644 index 000000000..fb6c6f3bb --- /dev/null +++ b/lib/dist/events/EventsRegistry.test.js @@ -0,0 +1,183 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const react_native_1 = require("react-native"); +const Notification_1 = require("../DTO/Notification"); +const CompletionCallbackWrapper_1 = require("../adapters/CompletionCallbackWrapper"); +const NativeCommandsSender_1 = require("../adapters/NativeCommandsSender"); +const NativeEventsReceiver_1 = require("../adapters/NativeEventsReceiver"); +const NotificationCompletion_1 = require("../interfaces/NotificationCompletion"); +const EventsRegistry_1 = require("./EventsRegistry"); +jest.mock('../adapters/NativeCommandsSender'); +jest.mock('../adapters/NativeEventsReceiver'); +describe('EventsRegistry', () => { + let uut; + const mockNativeEventsReceiver = new NativeEventsReceiver_1.NativeEventsReceiver(); + const mockNativeCommandsSender = new NativeCommandsSender_1.NativeCommandsSender(); + const completionCallbackWrapper = new CompletionCallbackWrapper_1.CompletionCallbackWrapper(mockNativeCommandsSender); + beforeEach(() => { + uut = new EventsRegistry_1.EventsRegistry(mockNativeEventsReceiver, completionCallbackWrapper); + }); + describe('registerRemoteNotificationsReceivedForeground', () => { + beforeEach(() => { + react_native_1.AppState.currentState = 'active'; + }); + it('delegates to nativeEventsReceiver', () => { + const cb = jest.fn(); + uut.registerNotificationReceivedForeground(cb); + expect(mockNativeEventsReceiver.registerNotificationReceived).toHaveBeenCalledTimes(1); + expect(mockNativeEventsReceiver.registerNotificationReceived).toHaveBeenCalledWith(expect.any(Function)); + }); + it('should wrap callback with completion block', () => { + const wrappedCallback = jest.fn(); + const notification = new Notification_1.Notification({ identifier: 'identifier' }); + uut.registerNotificationReceivedForeground(wrappedCallback); + const call = mockNativeEventsReceiver.registerNotificationReceived.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 = new Notification_1.Notification({ identifier: 'identifier' }); + uut.registerNotificationReceivedForeground((notification) => { + expect(notification).toEqual(expectedNotification); + }); + const call = mockNativeEventsReceiver.registerNotificationReceived.mock.calls[0][0]; + call(expectedNotification); + }); + it('should invoke finishPresentingNotification', () => { + const notification = new Notification_1.Notification({ identifier: 'notificationId' }); + const response = { alert: true }; + uut.registerNotificationReceivedForeground((notification, completion) => { + completion(response); + expect(mockNativeCommandsSender.finishPresentingNotification).toBeCalledWith(notification.identifier, response); + }); + const call = mockNativeEventsReceiver.registerNotificationReceived.mock.calls[0][0]; + call(notification); + }); + it('should not invoke finishPresentingNotification on Android', () => { + react_native_1.Platform.OS = 'android'; + const expectedNotification = new Notification_1.Notification({ identifier: 'notificationId' }); + const response = { alert: true }; + uut.registerNotificationReceivedForeground((notification, completion) => { + completion(response); + expect(expectedNotification).toEqual(notification); + expect(mockNativeCommandsSender.finishPresentingNotification).toBeCalledTimes(0); + }); + const call = mockNativeEventsReceiver.registerNotificationReceived.mock.calls[0][0]; + call(expectedNotification); + }); + }); + describe('registerRemoteNotificationsReceivedBackground', () => { + beforeEach(() => { + react_native_1.AppState.currentState = 'background'; + }); + it('delegates to nativeEventsReceiver', () => { + const cb = jest.fn(); + uut.registerNotificationReceivedBackground(cb); + expect(mockNativeEventsReceiver.registerNotificationReceivedBackground).toHaveBeenCalledTimes(1); + expect(mockNativeEventsReceiver.registerNotificationReceivedBackground).toHaveBeenCalledWith(expect.any(Function)); + }); + it('should wrap callback with completion block', () => { + const wrappedCallback = jest.fn(); + const notification = new Notification_1.Notification({ identifier: 'identifier' }); + uut.registerNotificationReceivedBackground(wrappedCallback); + const call = mockNativeEventsReceiver.registerNotificationReceivedBackground.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 = new Notification_1.Notification({ identifier: 'identifier' }); + uut.registerNotificationReceivedBackground((notification) => { + expect(notification).toEqual(expectedNotification); + }); + const call = mockNativeEventsReceiver.registerNotificationReceivedBackground.mock.calls[0][0]; + call(expectedNotification); + }); + it('should invoke finishHandlingBackgroundAction', () => { + const notification = new Notification_1.Notification({ identifier: 'notificationId' }); + const response = NotificationCompletion_1.NotificationBackgroundFetchResult.NO_DATA; + uut.registerNotificationReceivedBackground((notification, completion) => { + completion(response); + expect(mockNativeCommandsSender.finishHandlingBackgroundAction).toBeCalledWith(notification.identifier, response); + }); + const call = mockNativeEventsReceiver.registerNotificationReceivedBackground.mock.calls[0][0]; + call(notification); + }); + it('should not invoke finishHandlingBackgroundAction on Android', () => { + react_native_1.Platform.OS = 'android'; + const expectedNotification = new Notification_1.Notification({ identifier: 'notificationId' }); + const response = NotificationCompletion_1.NotificationBackgroundFetchResult.NO_DATA; + uut.registerNotificationReceivedBackground((notification, completion) => { + completion(response); + expect(expectedNotification).toEqual(notification); + expect(mockNativeCommandsSender.finishHandlingBackgroundAction).toBeCalledTimes(0); + }); + const call = mockNativeEventsReceiver.registerNotificationReceivedBackground.mock.calls[0][0]; + call(expectedNotification); + }); + }); + describe('', () => { + it('delegates to nativeEventsReceiver', () => { + const cb = jest.fn(); + uut.registerNotificationOpened(cb); + expect(mockNativeEventsReceiver.registerNotificationOpened).toHaveBeenCalledTimes(1); + expect(mockNativeEventsReceiver.registerNotificationOpened).toHaveBeenCalledWith(expect.any(Function)); + }); + it('should wrap callback with completion block', () => { + const wrappedCallback = jest.fn(); + const notification = new Notification_1.Notification({ identifier: 'identifier' }); + const response = { + notification, + identifier: 'responseId', + action: { identifier: 'actionIdentifier', text: 'userText' }, + }; + uut.registerNotificationOpened(wrappedCallback); + const call = mockNativeEventsReceiver.registerNotificationOpened.mock.calls[0][0]; + call(response.notification, response.action); + expect(wrappedCallback).toBeCalledWith(response.notification, expect.any(Function), response.action); + expect(wrappedCallback).toBeCalledTimes(1); + }); + it('should wrap callback with completion block', () => { + const notification = new Notification_1.Notification({ identifier: 'identifier' }); + uut.registerNotificationOpened((response) => { + expect(response).toEqual(notification); + }); + const call = mockNativeEventsReceiver.registerNotificationOpened.mock.calls[0][0]; + call(notification); + }); + it('calling completion should invoke finishHandlingAction', () => { + const expectedNotification = new Notification_1.Notification({ identifier: 'notificationId' }); + uut.registerNotificationOpened((notification, completion) => { + completion(); + expect(expectedNotification).toEqual(notification); + expect(mockNativeCommandsSender.finishHandlingAction).toBeCalledWith(notification.identifier); + }); + const call = mockNativeEventsReceiver.registerNotificationOpened.mock.calls[0][0]; + call(expectedNotification); + }); + it('should not invoke finishHandlingAction on Android', () => { + react_native_1.Platform.OS = 'android'; + const expectedNotification = new Notification_1.Notification({ identifier: 'notificationId' }); + uut.registerNotificationOpened((notification, completion) => { + completion(); + expect(expectedNotification).toEqual(notification); + expect(mockNativeCommandsSender.finishHandlingAction).toBeCalledTimes(0); + }); + const call = mockNativeEventsReceiver.registerNotificationOpened.mock.calls[0][0]; + call(expectedNotification); + }); + }); + it('delegates registerRemoteNotificationsRegistered to nativeEventsReceiver', () => { + const cb = jest.fn(); + uut.registerRemoteNotificationsRegistered(cb); + expect(mockNativeEventsReceiver.registerRemoteNotificationsRegistered).toHaveBeenCalledTimes(1); + expect(mockNativeEventsReceiver.registerRemoteNotificationsRegistered).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/dist/events/EventsRegistryIOS.d.ts b/lib/dist/events/EventsRegistryIOS.d.ts new file mode 100644 index 000000000..0daa355ca --- /dev/null +++ b/lib/dist/events/EventsRegistryIOS.d.ts @@ -0,0 +1,12 @@ +import { EmitterSubscription } from 'react-native'; +import { NativeEventsReceiver } from '../adapters/NativeEventsReceiver'; +import { RegisteredPushKit } from '../interfaces/NotificationEvents'; +import { CompletionCallbackWrapper } from '../adapters/CompletionCallbackWrapper'; +export declare class EventsRegistryIOS { + private nativeEventsReceiver; + private completionCallbackWrapper; + constructor(nativeEventsReceiver: NativeEventsReceiver, completionCallbackWrapper: CompletionCallbackWrapper); + registerPushKitRegistered(callback: (event: RegisteredPushKit) => void): EmitterSubscription; + registerPushKitNotificationReceived(callback: (event: object, completion: () => void) => void): EmitterSubscription; + appNotificationSettingsLinked(callback: () => void): EmitterSubscription; +} diff --git a/lib/dist/events/EventsRegistryIOS.js b/lib/dist/events/EventsRegistryIOS.js new file mode 100644 index 000000000..5daa0b255 --- /dev/null +++ b/lib/dist/events/EventsRegistryIOS.js @@ -0,0 +1,21 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.EventsRegistryIOS = void 0; +class EventsRegistryIOS { + nativeEventsReceiver; + completionCallbackWrapper; + constructor(nativeEventsReceiver, completionCallbackWrapper) { + this.nativeEventsReceiver = nativeEventsReceiver; + this.completionCallbackWrapper = completionCallbackWrapper; + } + registerPushKitRegistered(callback) { + return this.nativeEventsReceiver.registerPushKitRegistered(callback); + } + registerPushKitNotificationReceived(callback) { + return this.nativeEventsReceiver.registerPushKitNotificationReceived(this.completionCallbackWrapper.wrapOpenedCallback(callback)); + } + appNotificationSettingsLinked(callback) { + return this.nativeEventsReceiver.appNotificationSettingsLinked(callback); + } +} +exports.EventsRegistryIOS = EventsRegistryIOS; diff --git a/lib/dist/events/EventsRegistryIOS.test.d.ts b/lib/dist/events/EventsRegistryIOS.test.d.ts new file mode 100644 index 000000000..cb0ff5c3b --- /dev/null +++ b/lib/dist/events/EventsRegistryIOS.test.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/lib/dist/events/EventsRegistryIOS.test.js b/lib/dist/events/EventsRegistryIOS.test.js new file mode 100644 index 000000000..75062b324 --- /dev/null +++ b/lib/dist/events/EventsRegistryIOS.test.js @@ -0,0 +1,53 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const EventsRegistryIOS_1 = require("./EventsRegistryIOS"); +const CompletionCallbackWrapper_1 = require("../adapters/CompletionCallbackWrapper"); +const NativeCommandsSender_1 = require("../adapters/NativeCommandsSender"); +const NativeEventsReceiver_1 = require("../adapters/NativeEventsReceiver"); +jest.mock('../adapters/NativeCommandsSender'); +jest.mock('../adapters/NativeEventsReceiver'); +describe('EventsRegistryIOS', () => { + let uut; + const mockNativeEventsReceiver = new NativeEventsReceiver_1.NativeEventsReceiver(); + const mockNativeCommandsSender = new NativeCommandsSender_1.NativeCommandsSender(); + const completionCallbackWrapper = new CompletionCallbackWrapper_1.CompletionCallbackWrapper(mockNativeCommandsSender); + beforeEach(() => { + uut = new EventsRegistryIOS_1.EventsRegistryIOS(mockNativeEventsReceiver, completionCallbackWrapper); + }); + 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(expect.any(Function)); + }); + it('should wrap callback with completion block', () => { + const expectedNotification = { identifier: 'notificationId' }; + uut.registerPushKitNotificationReceived((notification) => { + expect(notification).toEqual(expectedNotification); + }); + const call = mockNativeEventsReceiver.registerPushKitNotificationReceived.mock.calls[0][0]; + call(expectedNotification); + }); + it('should invoke finishPresentingNotification', () => { + const expectedNotification = { identifier: 'notificationId' }; + uut.registerPushKitNotificationReceived((notification, completion) => { + completion(); + expect(notification).toEqual(expectedNotification); + expect(mockNativeCommandsSender.finishHandlingAction).toBeCalledWith('notificationId'); + }); + const call = mockNativeEventsReceiver.registerPushKitNotificationReceived.mock.calls[0][0]; + call(expectedNotification); + }); + it('delegates appNotificationSettingsLinked to nativeEventsReceiver', () => { + const cb = jest.fn(); + uut.appNotificationSettingsLinked(cb); + expect(mockNativeEventsReceiver.appNotificationSettingsLinked).toHaveBeenCalledTimes(1); + expect(mockNativeEventsReceiver.appNotificationSettingsLinked).toHaveBeenCalledWith(cb); + }); +}); diff --git a/lib/dist/index.d.ts b/lib/dist/index.d.ts new file mode 100644 index 000000000..0c3e5639b --- /dev/null +++ b/lib/dist/index.d.ts @@ -0,0 +1,7 @@ +import { NotificationsRoot } from './Notifications'; +export declare const Notifications: NotificationsRoot; +export * from './interfaces/EventSubscription'; +export * from './DTO/Notification'; +export * from './interfaces/NotificationEvents'; +export * from './interfaces/NotificationCategory'; +export * from './interfaces/NotificationCompletion'; diff --git a/lib/dist/index.js b/lib/dist/index.js new file mode 100644 index 000000000..279c5d6a2 --- /dev/null +++ b/lib/dist/index.js @@ -0,0 +1,12 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Notifications = void 0; +const tslib_1 = require("tslib"); +const Notifications_1 = require("./Notifications"); +const notificationsSingleton = new Notifications_1.NotificationsRoot(); +exports.Notifications = notificationsSingleton; +tslib_1.__exportStar(require("./interfaces/EventSubscription"), exports); +tslib_1.__exportStar(require("./DTO/Notification"), exports); +tslib_1.__exportStar(require("./interfaces/NotificationEvents"), exports); +tslib_1.__exportStar(require("./interfaces/NotificationCategory"), exports); +tslib_1.__exportStar(require("./interfaces/NotificationCompletion"), exports); diff --git a/lib/dist/interfaces/EventSubscription.d.ts b/lib/dist/interfaces/EventSubscription.d.ts new file mode 100644 index 000000000..3cd09f598 --- /dev/null +++ b/lib/dist/interfaces/EventSubscription.d.ts @@ -0,0 +1,3 @@ +export interface EventSubscription { + remove(): void; +} diff --git a/lib/dist/interfaces/EventSubscription.js b/lib/dist/interfaces/EventSubscription.js new file mode 100644 index 000000000..c8ad2e549 --- /dev/null +++ b/lib/dist/interfaces/EventSubscription.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/dist/interfaces/NotificationActionResponse.d.ts b/lib/dist/interfaces/NotificationActionResponse.d.ts new file mode 100644 index 000000000..ee174df2f --- /dev/null +++ b/lib/dist/interfaces/NotificationActionResponse.d.ts @@ -0,0 +1,5 @@ +export declare class NotificationActionResponse { + identifier: string; + text?: string; + constructor(response: any); +} diff --git a/lib/dist/interfaces/NotificationActionResponse.js b/lib/dist/interfaces/NotificationActionResponse.js new file mode 100644 index 000000000..c7921617b --- /dev/null +++ b/lib/dist/interfaces/NotificationActionResponse.js @@ -0,0 +1,12 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.NotificationActionResponse = void 0; +class NotificationActionResponse { + identifier; + text; + constructor(response) { + this.identifier = response.identifier; + this.text = response.text; + } +} +exports.NotificationActionResponse = NotificationActionResponse; diff --git a/lib/dist/interfaces/NotificationCategory.d.ts b/lib/dist/interfaces/NotificationCategory.d.ts new file mode 100644 index 000000000..4993f54ff --- /dev/null +++ b/lib/dist/interfaces/NotificationCategory.d.ts @@ -0,0 +1,18 @@ +export declare class NotificationCategory { + identifier: string; + actions?: NotificationAction[]; + constructor(identifier: string, actions?: NotificationAction[]); +} +export interface NotificationTextInput { + buttonTitle: string; + placeholder: string; +} +export type ActivationMode = 'background' | 'foreground' | 'authenticationRequired' | 'destructive'; +export declare class NotificationAction { + identifier: string; + activationMode: ActivationMode; + title: string; + authenticationRequired: boolean; + textInput?: NotificationTextInput; + constructor(identifier: string, activationMode: ActivationMode, title: string, authenticationRequired: boolean, textInput?: NotificationTextInput); +} diff --git a/lib/dist/interfaces/NotificationCategory.js b/lib/dist/interfaces/NotificationCategory.js new file mode 100644 index 000000000..9aabb3ff2 --- /dev/null +++ b/lib/dist/interfaces/NotificationCategory.js @@ -0,0 +1,27 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.NotificationAction = exports.NotificationCategory = void 0; +class NotificationCategory { + identifier; + actions; + constructor(identifier, actions) { + this.identifier = identifier; + this.actions = actions; + } +} +exports.NotificationCategory = NotificationCategory; +class NotificationAction { + identifier; + activationMode; + title; + authenticationRequired; + textInput; + constructor(identifier, activationMode, title, authenticationRequired, textInput) { + this.identifier = identifier; + this.activationMode = activationMode; + this.title = title; + this.authenticationRequired = authenticationRequired; + this.textInput = textInput; + } +} +exports.NotificationAction = NotificationAction; diff --git a/lib/dist/interfaces/NotificationChannel.d.ts b/lib/dist/interfaces/NotificationChannel.d.ts new file mode 100644 index 000000000..28d629759 --- /dev/null +++ b/lib/dist/interfaces/NotificationChannel.d.ts @@ -0,0 +1,14 @@ +export interface NotificationChannel { + channelId: string; + name: string; + importance: -1000 | 0 | 1 | 2 | 3 | 4 | 5; + description?: string; + enableLights?: boolean; + enableVibration?: boolean; + groupId?: string; + groupName?: string; + lightColor?: string; + showBadge?: boolean; + soundFile?: string; + vibrationPattern?: number[]; +} diff --git a/lib/dist/interfaces/NotificationChannel.js b/lib/dist/interfaces/NotificationChannel.js new file mode 100644 index 000000000..c8ad2e549 --- /dev/null +++ b/lib/dist/interfaces/NotificationChannel.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/dist/interfaces/NotificationCompletion.d.ts b/lib/dist/interfaces/NotificationCompletion.d.ts new file mode 100644 index 000000000..dab29537b --- /dev/null +++ b/lib/dist/interfaces/NotificationCompletion.d.ts @@ -0,0 +1,10 @@ +export interface NotificationCompletion { + badge?: boolean; + alert?: boolean; + sound?: boolean; +} +export declare enum NotificationBackgroundFetchResult { + NEW_DATA = "newData", + NO_DATA = "noData", + FAILED = "failed" +} diff --git a/lib/dist/interfaces/NotificationCompletion.js b/lib/dist/interfaces/NotificationCompletion.js new file mode 100644 index 000000000..270de6578 --- /dev/null +++ b/lib/dist/interfaces/NotificationCompletion.js @@ -0,0 +1,9 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.NotificationBackgroundFetchResult = void 0; +var NotificationBackgroundFetchResult; +(function (NotificationBackgroundFetchResult) { + NotificationBackgroundFetchResult["NEW_DATA"] = "newData"; + NotificationBackgroundFetchResult["NO_DATA"] = "noData"; + NotificationBackgroundFetchResult["FAILED"] = "failed"; +})(NotificationBackgroundFetchResult = exports.NotificationBackgroundFetchResult || (exports.NotificationBackgroundFetchResult = {})); diff --git a/lib/dist/interfaces/NotificationEvents.d.ts b/lib/dist/interfaces/NotificationEvents.d.ts new file mode 100644 index 000000000..d21e2326d --- /dev/null +++ b/lib/dist/interfaces/NotificationEvents.d.ts @@ -0,0 +1,18 @@ +import { Notification } from '../DTO/Notification'; +import { NotificationActionResponse } from './NotificationActionResponse'; +export interface Registered { + deviceToken: string; +} +export interface RegistrationError { + code: string; + domain: string; + localizedDescription: string; +} +export interface RegisteredPushKit { + pushKitToken: string; +} +export interface NotificationResponse { + identifier: string; + notification: Notification; + action?: NotificationActionResponse; +} diff --git a/lib/dist/interfaces/NotificationEvents.js b/lib/dist/interfaces/NotificationEvents.js new file mode 100644 index 000000000..c8ad2e549 --- /dev/null +++ b/lib/dist/interfaces/NotificationEvents.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/dist/interfaces/NotificationPermissions.d.ts b/lib/dist/interfaces/NotificationPermissions.d.ts new file mode 100644 index 000000000..e2cf6df56 --- /dev/null +++ b/lib/dist/interfaces/NotificationPermissions.d.ts @@ -0,0 +1,14 @@ +export interface NotificationPermissionOptions { + carPlay?: boolean; + criticalAlert?: boolean; + providesAppNotificationSettings?: boolean; + provisional?: boolean; + announcement?: boolean; +} +export interface NotificationPermissions extends NotificationPermissionOptions { + badge: boolean; + alert: boolean; + sound: boolean; + notificationCenter: boolean; + lockScreen: boolean; +} diff --git a/lib/dist/interfaces/NotificationPermissions.js b/lib/dist/interfaces/NotificationPermissions.js new file mode 100644 index 000000000..c8ad2e549 --- /dev/null +++ b/lib/dist/interfaces/NotificationPermissions.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/ios/RNBridgeModule.m b/lib/ios/RNBridgeModule.m index 2526f5836..7e83dca8f 100644 --- a/lib/ios/RNBridgeModule.m +++ b/lib/ios/RNBridgeModule.m @@ -48,6 +48,10 @@ - (dispatch_queue_t)methodQueue { [_commandsHandler getInitialNotification:resolve reject:reject]; } +RCT_EXPORT_METHOD(getInitialAction: (RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject){ + [_commandsHandler getInitialAction:resolve reject:reject]; +} + RCT_EXPORT_METHOD(finishHandlingAction:(NSString *)completionKey) { [_commandsHandler finishHandlingAction:completionKey]; } diff --git a/lib/ios/RNCommandsHandler.h b/lib/ios/RNCommandsHandler.h index b7e10e4f4..790aca5da 100644 --- a/lib/ios/RNCommandsHandler.h +++ b/lib/ios/RNCommandsHandler.h @@ -11,6 +11,8 @@ - (void)getInitialNotification:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject; +- (void)getInitialAction:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject; + - (void)finishHandlingAction:(NSString *)completionKey; - (void)finishPresentingNotification:(NSString *)completionKey presentingOptions:(NSDictionary *)presentingOptions; diff --git a/lib/ios/RNCommandsHandler.m b/lib/ios/RNCommandsHandler.m index 55049299e..10abb78b8 100644 --- a/lib/ios/RNCommandsHandler.m +++ b/lib/ios/RNCommandsHandler.m @@ -27,6 +27,14 @@ - (void)getInitialNotification:(RCTPromiseResolveBlock)resolve reject:(RCTPromis resolve(initialNotification); } + +- (void)getInitialAction:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { + NSDictionary* initialAction = [[RNNotificationsStore sharedInstance] initialAction]; + [[RNNotificationsStore sharedInstance] setInitialAction:nil]; + resolve(initialAction); +} + + - (void)finishHandlingAction:(NSString *)completionKey { [[RNNotificationsStore sharedInstance] completeAction:completionKey]; } diff --git a/lib/ios/RNNotificationEventHandler.m b/lib/ios/RNNotificationEventHandler.m index 5c8dd0b35..ea67b52ef 100644 --- a/lib/ios/RNNotificationEventHandler.m +++ b/lib/ios/RNNotificationEventHandler.m @@ -30,6 +30,7 @@ - (void)didReceiveForegroundNotification:(UNNotification *)notification withComp - (void)didReceiveNotificationResponse:(UNNotificationResponse *)response completionHandler:(void (^)(void))completionHandler { [_store setActionCompletionHandler:completionHandler withCompletionKey:response.notification.request.identifier]; + [_store setInitialAction:[RNNotificationParser parseNotificationResponse:response]]; [RNEventEmitter sendEvent:RNNotificationOpened body:[RNNotificationParser parseNotificationResponse:response]]; } diff --git a/lib/ios/RNNotificationsStore.h b/lib/ios/RNNotificationsStore.h index 4f8a17199..4b06dbf49 100644 --- a/lib/ios/RNNotificationsStore.h +++ b/lib/ios/RNNotificationsStore.h @@ -5,6 +5,7 @@ @interface RNNotificationsStore : NSObject @property (nonatomic, retain) NSDictionary* initialNotification; +@property (nonatomic, retain) NSDictionary* initialAction; + (instancetype)sharedInstance; diff --git a/lib/src/Notifications.ts b/lib/src/Notifications.ts index 0848f6d4a..18018e849 100644 --- a/lib/src/Notifications.ts +++ b/lib/src/Notifications.ts @@ -66,13 +66,20 @@ export class NotificationsRoot { return this.commands.getInitialNotification(); } + /** + * getInitialAction + */ + public getInitialAction(): Promise { + return this.commands.getInitialAction(); + } + /** * setCategories */ public setCategories(categories: [NotificationCategory?]) { this.commands.setCategories(categories); } - + /** * cancelLocalNotification */ diff --git a/lib/src/adapters/NativeCommandsSender.ts b/lib/src/adapters/NativeCommandsSender.ts index 33a9508fb..c9463ed72 100644 --- a/lib/src/adapters/NativeCommandsSender.ts +++ b/lib/src/adapters/NativeCommandsSender.ts @@ -5,9 +5,11 @@ import { NotificationPermissions } from '../interfaces/NotificationPermissions'; import { NotificationCategory } from '../interfaces/NotificationCategory'; import { NotificationChannel } from '../interfaces/NotificationChannel'; import { NotificationPermissionOptions } from '../interfaces/NotificationPermissions'; +import { NotificationResponse } from '../interfaces/NotificationEvents'; interface NativeCommandsModule { getInitialNotification(): Promise; + getInitialAction(): Promise; postLocalNotification(notification: Notification, id: number): void; requestPermissions(options: NotificationPermissionOptions): void; abandonPermissions(): void; @@ -43,6 +45,10 @@ export class NativeCommandsSender { return this.nativeCommandsModule.getInitialNotification(); } + getInitialAction(): Promise { + return this.nativeCommandsModule.getInitialAction(); + } + requestPermissions(options?: NotificationPermissionOptions) { return this.nativeCommandsModule.requestPermissions(options || {}); } diff --git a/lib/src/commands/Commands.test.ts b/lib/src/commands/Commands.test.ts index 9aeddfa5e..0fb6cbaa1 100644 --- a/lib/src/commands/Commands.test.ts +++ b/lib/src/commands/Commands.test.ts @@ -7,9 +7,9 @@ import { UniqueIdProvider } from '../adapters/UniqueIdProvider'; import { NotificationCategory } from '../interfaces/NotificationCategory'; import { NotificationPermissions } from '../interfaces/NotificationPermissions'; import { NotificationFactory } from '../DTO/NotificationFactory'; -import {NotificationAndroid} from "../DTO/NotificationAndroid"; -import {Platform} from "react-native"; -import {NotificationIOS} from "../DTO/NotificationIOS"; +import { NotificationAndroid } from "../DTO/NotificationAndroid"; +import { Platform } from "react-native"; +import { NotificationIOS } from "../DTO/NotificationIOS"; describe('Commands', () => { let uut: Commands; @@ -37,9 +37,9 @@ describe('Commands', () => { it('Android - returns a promise with the initial notification', async () => { Platform.OS = 'android'; - const expectedNotification: Notification = new NotificationAndroid({'google.message_id': 'id'}); + const expectedNotification: Notification = new NotificationAndroid({ 'google.message_id': 'id' }); when(mockedNativeCommandsSender.getInitialNotification()).thenResolve( - {'google.message_id': 'id'} + { 'google.message_id': 'id' } ); const result = await uut.getInitialNotification(); expect(result).toEqual(expectedNotification); @@ -54,15 +54,56 @@ describe('Commands', () => { it('iOS - returns a promise with the initial notification', async () => { Platform.OS = 'ios'; - const expectedNotification: Notification = new NotificationIOS({identifier: 'id'}); + const expectedNotification: Notification = new NotificationIOS({ identifier: 'id' }); when(mockedNativeCommandsSender.getInitialNotification()).thenResolve( - {identifier: 'id'} + { identifier: 'id' } ); const result = await uut.getInitialNotification(); expect(result).toEqual(expectedNotification); }); }); + describe('getInitialAction', () => { + it('sends to native', () => { + uut.getInitialAction(); + verify(mockedNativeCommandsSender.getInitialAction()).called(); + }); + + it('Android - should return undefined initial action', async () => { + Platform.OS = 'android'; + when(mockedNativeCommandsSender.getInitialAction()).thenResolve(); + const actual = await uut.getInitialAction(); + expect(actual).toEqual(undefined); + }); + + it('iOS - should return undefined initial action', async () => { + Platform.OS = 'ios'; + when(mockedNativeCommandsSender.getInitialAction()).thenResolve(); + const actual = await uut.getInitialAction(); + expect(actual).toEqual(undefined); + }); + + it('iOS - returns a promise with the initial action', async () => { + Platform.OS = 'ios'; + const expectedNotification: Notification = new Notification({ + identifier: 'id', + payload: { + action: { + identifier: 'id', + text: 'text' + }, + body: 'body', + title: 'title' + } + }); + when(mockedNativeCommandsSender.getInitialAction()).thenResolve( + { identifier: 'id', notification: expectedNotification, action: { identifier: 'id', text: 'text'} } + ); + const actual = await uut.getInitialAction(); + expect(actual).toEqual(expectedNotification); + }); + }); + describe('requestPermissions', () => { it('sends to native', () => { const opts = {}; @@ -92,7 +133,7 @@ describe('Commands', () => { }); it('sends to native with categories', () => { - const category: NotificationCategory = {identifier: 'id', actions: []}; + const category: NotificationCategory = { identifier: 'id', actions: [] }; const categoriesArray: [NotificationCategory] = [category]; uut.setCategories(categoriesArray); verify(mockedNativeCommandsSender.setCategories(categoriesArray)).called(); @@ -108,26 +149,26 @@ describe('Commands', () => { describe('postLocalNotification', () => { it('sends to native', () => { - const notification: Notification = new Notification({identifier: 'id'}); + const notification: Notification = new Notification({ identifier: 'id' }); uut.postLocalNotification(notification); verify(mockedNativeCommandsSender.postLocalNotification(notification, anyNumber())).called(); }); it('generates unique identifier', () => { - const notification: Notification = new Notification({identifier: 'id'}); + const notification: Notification = new Notification({ identifier: 'id' }); uut.postLocalNotification(notification); verify(mockedNativeCommandsSender.postLocalNotification(notification, anyNumber())).called(); }); it('use passed notification id', () => { - const notification: Notification = new Notification({identifier: 'id'}); + const notification: Notification = new Notification({ identifier: 'id' }); const passedId: number = 2; uut.postLocalNotification(notification, passedId); verify(mockedNativeCommandsSender.postLocalNotification(notification, passedId)).called(); }); it('return notification id', () => { - const notification: Notification = new Notification({identifier: 'id'}); + const notification: Notification = new Notification({ identifier: 'id' }); const notificationId: number = 2; const response = uut.postLocalNotification(notification, notificationId); expect(response).toEqual(notificationId); diff --git a/lib/src/commands/Commands.ts b/lib/src/commands/Commands.ts index 1f344457c..80bd0f544 100644 --- a/lib/src/commands/Commands.ts +++ b/lib/src/commands/Commands.ts @@ -30,6 +30,16 @@ export class Commands { }); } + public async getInitialAction(): Promise { + return this.nativeCommandsSender.getInitialAction().then((payload) => { + if (payload) { + return this.notificationFactory.fromPayload(payload); + } + + return undefined; + }); + } + public requestPermissions(options?: NotificationPermissionOptions) { const result = this.nativeCommandsSender.requestPermissions(options); return result; diff --git a/package.json b/package.json index 22e709834..6e5d507f6 100644 --- a/package.json +++ b/package.json @@ -114,4 +114,4 @@ "html" ] } -} \ No newline at end of file +}