2018-01-30 11:15:59 +00:00
|
|
|
/**
|
|
|
|
* @flow
|
2018-03-05 08:28:13 +00:00
|
|
|
* Notifications representation wrapper
|
2018-01-30 11:15:59 +00:00
|
|
|
*/
|
|
|
|
import { SharedEventEmitter } from '../../utils/events';
|
|
|
|
import { getLogger } from '../../utils/log';
|
|
|
|
import ModuleBase from '../../utils/ModuleBase';
|
|
|
|
import { getNativeModule } from '../../utils/native';
|
|
|
|
import { isFunction, isObject } from '../../utils';
|
2018-03-09 11:09:20 +00:00
|
|
|
import AndroidAction from './AndroidAction';
|
2018-03-05 08:28:13 +00:00
|
|
|
import AndroidChannel from './AndroidChannel';
|
|
|
|
import AndroidChannelGroup from './AndroidChannelGroup';
|
|
|
|
import AndroidNotifications from './AndroidNotifications';
|
2018-03-09 11:09:20 +00:00
|
|
|
import AndroidRemoteInput from './AndroidRemoteInput';
|
2018-02-09 17:00:03 +00:00
|
|
|
import Notification from './Notification';
|
|
|
|
import {
|
|
|
|
BadgeIconType,
|
|
|
|
Category,
|
|
|
|
Defaults,
|
|
|
|
GroupAlert,
|
2018-03-05 08:28:13 +00:00
|
|
|
Importance,
|
2018-02-09 17:00:03 +00:00
|
|
|
Priority,
|
2018-03-09 11:09:20 +00:00
|
|
|
SemanticAction,
|
2018-02-09 17:00:03 +00:00
|
|
|
Visibility,
|
2018-02-22 15:52:24 +00:00
|
|
|
} from './types';
|
2018-01-30 11:15:59 +00:00
|
|
|
|
2018-02-15 14:59:21 +00:00
|
|
|
import type App from '../core/app';
|
2018-03-06 18:20:49 +00:00
|
|
|
import type { NotificationOpen } from './Notification';
|
2018-02-22 17:25:15 +00:00
|
|
|
import type {
|
|
|
|
NativeNotification,
|
2018-03-06 18:20:49 +00:00
|
|
|
NativeNotificationOpen,
|
2018-02-22 17:25:15 +00:00
|
|
|
Schedule,
|
|
|
|
} from './types';
|
2018-01-30 11:15:59 +00:00
|
|
|
|
|
|
|
type OnNotification = Notification => any;
|
|
|
|
|
|
|
|
type OnNotificationObserver = {
|
|
|
|
next: OnNotification,
|
|
|
|
};
|
|
|
|
|
2018-03-06 18:20:49 +00:00
|
|
|
type OnNotificationOpened = NotificationOpen => any;
|
2018-02-22 17:25:15 +00:00
|
|
|
|
2018-02-24 11:32:14 +00:00
|
|
|
type OnNotificationOpenedObserver = {
|
2018-03-07 18:29:53 +00:00
|
|
|
next: NotificationOpen,
|
2018-02-22 17:25:15 +00:00
|
|
|
};
|
|
|
|
|
2018-02-18 16:02:31 +00:00
|
|
|
const NATIVE_EVENTS = [
|
|
|
|
'notifications_notification_displayed',
|
2018-02-24 11:32:14 +00:00
|
|
|
'notifications_notification_opened',
|
2018-02-18 16:02:31 +00:00
|
|
|
'notifications_notification_received',
|
|
|
|
];
|
2018-01-30 11:15:59 +00:00
|
|
|
|
|
|
|
export const MODULE_NAME = 'RNFirebaseNotifications';
|
|
|
|
export const NAMESPACE = 'notifications';
|
|
|
|
|
2018-02-09 17:00:03 +00:00
|
|
|
// iOS 8/9 scheduling
|
|
|
|
// fireDate: Date;
|
|
|
|
// timeZone: TimeZone;
|
|
|
|
// repeatInterval: NSCalendar.Unit;
|
|
|
|
// repeatCalendar: Calendar;
|
|
|
|
// region: CLRegion;
|
|
|
|
// regionTriggersOnce: boolean;
|
|
|
|
|
|
|
|
// iOS 10 scheduling
|
|
|
|
// TODO
|
|
|
|
|
|
|
|
// Android scheduling
|
|
|
|
// TODO
|
|
|
|
|
2018-01-30 11:15:59 +00:00
|
|
|
/**
|
|
|
|
* @class Notifications
|
|
|
|
*/
|
|
|
|
export default class Notifications extends ModuleBase {
|
2018-03-05 08:28:13 +00:00
|
|
|
_android: AndroidNotifications;
|
|
|
|
|
2018-01-30 11:15:59 +00:00
|
|
|
constructor(app: App) {
|
|
|
|
super(app, {
|
|
|
|
events: NATIVE_EVENTS,
|
2018-03-23 13:24:31 +00:00
|
|
|
hasShards: false,
|
2018-01-30 11:15:59 +00:00
|
|
|
moduleName: MODULE_NAME,
|
|
|
|
multiApp: false,
|
|
|
|
namespace: NAMESPACE,
|
|
|
|
});
|
2018-03-05 08:28:13 +00:00
|
|
|
this._android = new AndroidNotifications(this);
|
2018-01-30 11:15:59 +00:00
|
|
|
|
|
|
|
SharedEventEmitter.addListener(
|
|
|
|
// sub to internal native event - this fans out to
|
2018-02-22 17:25:15 +00:00
|
|
|
// public event name: onNotificationDisplayed
|
|
|
|
'notifications_notification_displayed',
|
2018-02-22 15:52:24 +00:00
|
|
|
(notification: NativeNotification) => {
|
|
|
|
SharedEventEmitter.emit(
|
2018-02-22 17:25:15 +00:00
|
|
|
'onNotificationDisplayed',
|
2018-02-22 15:52:24 +00:00
|
|
|
new Notification(notification)
|
|
|
|
);
|
2018-02-18 16:02:31 +00:00
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
SharedEventEmitter.addListener(
|
|
|
|
// sub to internal native event - this fans out to
|
2018-02-24 11:32:14 +00:00
|
|
|
// public event name: onNotificationOpened
|
|
|
|
'notifications_notification_opened',
|
2018-03-06 18:20:49 +00:00
|
|
|
(notificationOpen: NativeNotificationOpen) => {
|
2018-03-05 08:28:13 +00:00
|
|
|
SharedEventEmitter.emit('onNotificationOpened', {
|
2018-03-06 18:20:49 +00:00
|
|
|
action: notificationOpen.action,
|
|
|
|
notification: new Notification(notificationOpen.notification),
|
2018-03-09 11:09:20 +00:00
|
|
|
results: notificationOpen.results,
|
2018-02-22 17:25:15 +00:00
|
|
|
});
|
2018-02-18 16:02:31 +00:00
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
SharedEventEmitter.addListener(
|
|
|
|
// sub to internal native event - this fans out to
|
|
|
|
// public event name: onNotification
|
2018-01-30 11:15:59 +00:00
|
|
|
'notifications_notification_received',
|
2018-02-22 15:52:24 +00:00
|
|
|
(notification: NativeNotification) => {
|
|
|
|
SharedEventEmitter.emit(
|
|
|
|
'onNotification',
|
|
|
|
new Notification(notification)
|
|
|
|
);
|
2018-01-30 11:15:59 +00:00
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-03-05 08:28:13 +00:00
|
|
|
get android(): AndroidNotifications {
|
|
|
|
return this._android;
|
|
|
|
}
|
|
|
|
|
2018-02-18 16:02:31 +00:00
|
|
|
/**
|
|
|
|
* Cancel all notifications
|
|
|
|
*/
|
2018-02-24 11:32:14 +00:00
|
|
|
cancelAllNotifications(): void {
|
|
|
|
getNativeModule(this).cancelAllNotifications();
|
2018-02-09 17:00:03 +00:00
|
|
|
}
|
|
|
|
|
2018-01-30 11:15:59 +00:00
|
|
|
/**
|
2018-02-18 16:02:31 +00:00
|
|
|
* Cancel a notification by id.
|
2018-02-24 11:32:14 +00:00
|
|
|
* @param notificationId
|
2018-01-30 11:15:59 +00:00
|
|
|
*/
|
2018-02-24 11:32:14 +00:00
|
|
|
cancelNotification(notificationId: string): void {
|
2018-02-09 17:00:03 +00:00
|
|
|
if (!notificationId) {
|
2018-02-24 11:32:14 +00:00
|
|
|
throw new Error(
|
|
|
|
'Notifications: cancelNotification expects a `notificationId`'
|
|
|
|
);
|
2018-02-09 17:00:03 +00:00
|
|
|
}
|
2018-02-24 11:32:14 +00:00
|
|
|
getNativeModule(this).cancelNotification(notificationId);
|
2018-01-30 11:15:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-02-18 16:02:31 +00:00
|
|
|
* Display a notification
|
2018-01-30 11:15:59 +00:00
|
|
|
* @param notification
|
|
|
|
* @returns {*}
|
|
|
|
*/
|
2018-02-09 17:00:03 +00:00
|
|
|
displayNotification(notification: Notification): Promise<void> {
|
|
|
|
if (!(notification instanceof Notification)) {
|
2018-03-23 17:03:53 +00:00
|
|
|
return Promise.reject(
|
|
|
|
new Error(
|
|
|
|
`Notifications:displayNotification expects a 'Notification' but got type ${typeof notification}`
|
|
|
|
)
|
2018-02-09 17:00:03 +00:00
|
|
|
);
|
|
|
|
}
|
2018-03-23 17:03:53 +00:00
|
|
|
try {
|
|
|
|
return getNativeModule(this).displayNotification(notification.build());
|
|
|
|
} catch (error) {
|
|
|
|
return Promise.reject(error);
|
|
|
|
}
|
2018-01-30 11:15:59 +00:00
|
|
|
}
|
|
|
|
|
2018-02-23 15:34:00 +00:00
|
|
|
getBadge(): Promise<number> {
|
|
|
|
return getNativeModule(this).getBadge();
|
|
|
|
}
|
|
|
|
|
2018-03-07 18:29:53 +00:00
|
|
|
getInitialNotification(): Promise<NotificationOpen> {
|
2018-03-05 08:28:13 +00:00
|
|
|
return getNativeModule(this)
|
|
|
|
.getInitialNotification()
|
2018-03-07 18:29:53 +00:00
|
|
|
.then((notificationOpen: NativeNotificationOpen) => {
|
|
|
|
if (notificationOpen) {
|
|
|
|
return {
|
|
|
|
action: notificationOpen.action,
|
|
|
|
notification: new Notification(notificationOpen.notification),
|
2018-03-09 11:09:20 +00:00
|
|
|
results: notificationOpen.results,
|
2018-03-07 18:29:53 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
});
|
2018-02-14 09:07:29 +00:00
|
|
|
}
|
|
|
|
|
2018-01-30 11:15:59 +00:00
|
|
|
/**
|
|
|
|
* Returns an array of all scheduled notifications
|
|
|
|
* @returns {Promise.<Array>}
|
|
|
|
*/
|
2018-03-09 11:15:27 +00:00
|
|
|
getScheduledNotifications(): Promise<Notification[]> {
|
2018-02-14 09:07:29 +00:00
|
|
|
return getNativeModule(this).getScheduledNotifications();
|
2018-01-30 11:15:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
onNotification(
|
|
|
|
nextOrObserver: OnNotification | OnNotificationObserver
|
|
|
|
): () => any {
|
|
|
|
let listener;
|
|
|
|
if (isFunction(nextOrObserver)) {
|
|
|
|
listener = nextOrObserver;
|
|
|
|
} else if (isObject(nextOrObserver) && isFunction(nextOrObserver.next)) {
|
|
|
|
listener = nextOrObserver.next;
|
|
|
|
} else {
|
|
|
|
throw new Error(
|
|
|
|
'Notifications.onNotification failed: First argument must be a function or observer object with a `next` function.'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
getLogger(this).info('Creating onNotification listener');
|
|
|
|
SharedEventEmitter.addListener('onNotification', listener);
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
getLogger(this).info('Removing onNotification listener');
|
|
|
|
SharedEventEmitter.removeListener('onNotification', listener);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-02-22 15:52:24 +00:00
|
|
|
onNotificationDisplayed(
|
2018-02-18 16:02:31 +00:00
|
|
|
nextOrObserver: OnNotification | OnNotificationObserver
|
|
|
|
): () => any {
|
|
|
|
let listener;
|
|
|
|
if (isFunction(nextOrObserver)) {
|
|
|
|
listener = nextOrObserver;
|
|
|
|
} else if (isObject(nextOrObserver) && isFunction(nextOrObserver.next)) {
|
|
|
|
listener = nextOrObserver.next;
|
|
|
|
} else {
|
|
|
|
throw new Error(
|
2018-02-22 15:52:24 +00:00
|
|
|
'Notifications.onNotificationDisplayed failed: First argument must be a function or observer object with a `next` function.'
|
2018-02-18 16:02:31 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-02-22 15:52:24 +00:00
|
|
|
getLogger(this).info('Creating onNotificationDisplayed listener');
|
|
|
|
SharedEventEmitter.addListener('onNotificationDisplayed', listener);
|
2018-02-18 16:02:31 +00:00
|
|
|
|
|
|
|
return () => {
|
2018-02-22 15:52:24 +00:00
|
|
|
getLogger(this).info('Removing onNotificationDisplayed listener');
|
|
|
|
SharedEventEmitter.removeListener('onNotificationDisplayed', listener);
|
2018-02-18 16:02:31 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-02-24 11:32:14 +00:00
|
|
|
onNotificationOpened(
|
|
|
|
nextOrObserver: OnNotificationOpened | OnNotificationOpenedObserver
|
2018-02-18 16:02:31 +00:00
|
|
|
): () => any {
|
2018-02-22 17:25:15 +00:00
|
|
|
let listener;
|
2018-02-18 16:02:31 +00:00
|
|
|
if (isFunction(nextOrObserver)) {
|
|
|
|
listener = nextOrObserver;
|
|
|
|
} else if (isObject(nextOrObserver) && isFunction(nextOrObserver.next)) {
|
|
|
|
listener = nextOrObserver.next;
|
|
|
|
} else {
|
|
|
|
throw new Error(
|
2018-02-24 11:32:14 +00:00
|
|
|
'Notifications.onNotificationOpened failed: First argument must be a function or observer object with a `next` function.'
|
2018-02-18 16:02:31 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-02-24 11:32:14 +00:00
|
|
|
getLogger(this).info('Creating onNotificationOpened listener');
|
|
|
|
SharedEventEmitter.addListener('onNotificationOpened', listener);
|
2018-02-18 16:02:31 +00:00
|
|
|
|
|
|
|
return () => {
|
2018-02-24 11:32:14 +00:00
|
|
|
getLogger(this).info('Removing onNotificationOpened listener');
|
|
|
|
SharedEventEmitter.removeListener('onNotificationOpened', listener);
|
2018-02-18 16:02:31 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-01-30 11:15:59 +00:00
|
|
|
/**
|
2018-02-09 17:00:03 +00:00
|
|
|
* Remove all delivered notifications.
|
2018-01-30 11:15:59 +00:00
|
|
|
*/
|
2018-02-24 11:32:14 +00:00
|
|
|
removeAllDeliveredNotifications(): void {
|
|
|
|
getNativeModule(this).removeAllDeliveredNotifications();
|
2018-01-30 11:15:59 +00:00
|
|
|
}
|
|
|
|
|
2018-02-02 08:40:48 +00:00
|
|
|
/**
|
2018-02-09 17:00:03 +00:00
|
|
|
* Remove a delivered notification.
|
|
|
|
* @param notificationId
|
2018-02-02 08:40:48 +00:00
|
|
|
*/
|
2018-02-24 11:32:14 +00:00
|
|
|
removeDeliveredNotification(notificationId: string): void {
|
2018-02-09 17:00:03 +00:00
|
|
|
if (!notificationId) {
|
2018-02-24 11:32:14 +00:00
|
|
|
throw new Error(
|
|
|
|
'Notifications: removeDeliveredNotification expects a `notificationId`'
|
|
|
|
);
|
2018-02-09 17:00:03 +00:00
|
|
|
}
|
2018-02-24 11:32:14 +00:00
|
|
|
getNativeModule(this).removeDeliveredNotification(notificationId);
|
2018-02-02 08:40:48 +00:00
|
|
|
}
|
|
|
|
|
2018-01-30 11:15:59 +00:00
|
|
|
/**
|
2018-02-18 16:02:31 +00:00
|
|
|
* Schedule a notification
|
2018-01-30 11:15:59 +00:00
|
|
|
* @param notification
|
|
|
|
* @returns {*}
|
|
|
|
*/
|
2018-02-09 17:00:03 +00:00
|
|
|
scheduleNotification(
|
|
|
|
notification: Notification,
|
|
|
|
schedule: Schedule
|
|
|
|
): Promise<void> {
|
|
|
|
if (!(notification instanceof Notification)) {
|
2018-03-23 17:03:53 +00:00
|
|
|
return Promise.reject(
|
|
|
|
new Error(
|
|
|
|
`Notifications:scheduleNotification expects a 'Notification' but got type ${typeof notification}`
|
|
|
|
)
|
2018-01-30 11:15:59 +00:00
|
|
|
);
|
2018-02-09 17:00:03 +00:00
|
|
|
}
|
2018-03-23 17:03:53 +00:00
|
|
|
try {
|
|
|
|
const nativeNotification = notification.build();
|
|
|
|
nativeNotification.schedule = schedule;
|
|
|
|
return getNativeModule(this).scheduleNotification(nativeNotification);
|
|
|
|
} catch (error) {
|
|
|
|
return Promise.reject(error);
|
|
|
|
}
|
2018-01-30 11:15:59 +00:00
|
|
|
}
|
2018-02-23 15:34:00 +00:00
|
|
|
|
|
|
|
setBadge(badge: number): void {
|
|
|
|
getNativeModule(this).setBadge(badge);
|
|
|
|
}
|
2018-01-30 11:15:59 +00:00
|
|
|
}
|
2018-02-02 08:40:48 +00:00
|
|
|
|
2018-02-09 17:00:03 +00:00
|
|
|
export const statics = {
|
|
|
|
Android: {
|
2018-03-09 11:09:20 +00:00
|
|
|
Action: AndroidAction,
|
2018-02-09 17:00:03 +00:00
|
|
|
BadgeIconType,
|
|
|
|
Category,
|
2018-03-05 08:28:13 +00:00
|
|
|
Channel: AndroidChannel,
|
|
|
|
ChannelGroup: AndroidChannelGroup,
|
2018-02-09 17:00:03 +00:00
|
|
|
Defaults,
|
|
|
|
GroupAlert,
|
2018-03-05 08:28:13 +00:00
|
|
|
Importance,
|
2018-02-09 17:00:03 +00:00
|
|
|
Priority,
|
2018-03-09 11:09:20 +00:00
|
|
|
RemoteInput: AndroidRemoteInput,
|
|
|
|
SemanticAction,
|
2018-02-09 17:00:03 +00:00
|
|
|
Visibility,
|
|
|
|
},
|
|
|
|
Notification,
|
|
|
|
};
|