2
0
mirror of synced 2025-02-17 08:46:43 +00:00

[notifications] JS tidy up

This commit is contained in:
Chris Bianca 2018-02-23 16:11:59 +00:00
parent 2838bbc0cd
commit c5778c3d0d
12 changed files with 307 additions and 296 deletions

View File

@ -14,10 +14,6 @@
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
@import UserNotifications;
#endif
@interface RNFirebaseMessaging ()
@property (nonatomic, strong) NSMutableDictionary *callbackHandlers;
@end
@implementation RNFirebaseMessaging
@ -47,9 +43,6 @@ RCT_EXPORT_MODULE()
// Set static instance for use from AppDelegate
theRNFirebaseMessaging = self;
// Initialise callback handlers dictionary
_callbackHandlers = [NSMutableDictionary dictionary];
}
// *******************************************************
@ -187,60 +180,6 @@ RCT_EXPORT_METHOD(unsubscribeFromTopic: (NSString*) topic) {
[[FIRMessaging messaging] unsubscribeFromTopic:topic];
}
// Response handler methods
RCT_EXPORT_METHOD(completeNotificationResponse: (NSString*) messageId) {
void(^callbackHandler)() = [_callbackHandlers objectForKey:messageId];
if (!callbackHandler) {
NSLog(@"There is no callback handler for messageId: %@", messageId);
return;
}
callbackHandler();
[_callbackHandlers removeObjectForKey:messageId];
}
RCT_EXPORT_METHOD(completePresentNotification: (NSString*) messageId
result: (NSString*) result) {
void(^callbackHandler)(UNNotificationPresentationOptions) = [_callbackHandlers objectForKey:messageId];
if (!callbackHandler) {
NSLog(@"There is no callback handler for messageId: %@", messageId);
return;
}
UNNotificationPresentationOptions options;
if ([result isEqualToString:@"UNNotificationPresentationOptionAll"]) {
options = UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound;
} else if ([result isEqualToString:@"UNNotificationPresentationOptionNone"]) {
options = UNNotificationPresentationOptionNone;
} else {
NSLog(@"Invalid result for PresentNotification: %@", result);
return;
}
callbackHandler(options);
[_callbackHandlers removeObjectForKey:messageId];
}
RCT_EXPORT_METHOD(completeRemoteNotification: (NSString*) messageId
result: (NSString*) result) {
void(^callbackHandler)(UIBackgroundFetchResult) = [_callbackHandlers objectForKey:messageId];
if (!callbackHandler) {
NSLog(@"There is no callback handler for messageId: %@", messageId);
return;
}
UIBackgroundFetchResult fetchResult;
if ([result isEqualToString:@"UIBackgroundFetchResultNewData"]) {
fetchResult = UIBackgroundFetchResultNewData;
} else if ([result isEqualToString:@"UIBackgroundFetchResultNoData"]) {
fetchResult = UIBackgroundFetchResultNoData;
} else if ([result isEqualToString:@"UIBackgroundFetchResultFailed"]) {
fetchResult = UIBackgroundFetchResultFailed;
} else {
NSLog(@"Invalid result for PresentNotification: %@", result);
return;
}
callbackHandler(fetchResult);
[_callbackHandlers removeObjectForKey:messageId];
}
// ** Start internals **
- (NSDictionary*)parseFIRMessagingRemoteMessage:(FIRMessagingRemoteMessage *)remoteMessage {

View File

@ -378,7 +378,7 @@ RCT_EXPORT_METHOD(setBadge: (NSInteger) number) {
initialNotification = body;
}
// PRE-BRIDGE-EVENTS: Consider enabling this to allow events built up before the bridge is built to be sent to the JS side
[pendingEvents addObject:@{@"name":name, @"body":body}];
// [pendingEvents addObject:@{@"name":name, @"body":body}];
}
}

View File

@ -68,7 +68,6 @@ export type { default as WriteBatch } from './modules/firestore/WriteBatch';
/*
* Export Messaging types
*/
export type { default as Message } from './modules/messaging/Message';
export type {
default as RemoteMessage,
} from './modules/messaging/RemoteMessage';

View File

@ -1,108 +0,0 @@
/**
* @flow
* Message representation wrapper
*/
import { Platform } from 'react-native';
import { getNativeModule } from '../../utils/native';
import {
MessageType,
PresentNotificationResult,
RemoteNotificationResult,
} from './types';
import type Messaging from './';
import type {
NativeMessage,
PresentNotificationResultType,
RemoteNotificationResultType,
} from './types';
/**
* @class Message
*/
export default class Message {
_completed: boolean;
_messaging: Messaging;
_message: NativeMessage;
constructor(messaging: Messaging, message: NativeMessage) {
this._messaging = messaging;
this._message = message;
}
get collapseKey(): ?string {
return this._message.collapseKey;
}
get data(): { [string]: string } {
return this._message.data;
}
get from(): ?string {
return this._message.from;
}
get messageId(): ?string {
return this._message.messageId;
}
get sentTime(): ?number {
return this._message.sentTime;
}
get to(): ?string {
return this._message.to;
}
get ttl(): ?number {
return this._message.ttl;
}
complete(
result?: PresentNotificationResultType | RemoteNotificationResultType
): void {
if (Platform.OS === 'android') {
return;
}
if (!this._completed) {
this._completed = true;
switch (this.messageType) {
case MessageType.NotificationResponse:
getNativeModule(this._messaging).completeNotificationResponse(
this.messageId
);
break;
case MessageType.PresentNotification:
if (
result &&
!Object.values(PresentNotificationResult).includes(result)
) {
throw new Error(`Invalid PresentNotificationResult: ${result}`);
}
getNativeModule(this._messaging).completePresentNotification(
this.messageId,
result || PresentNotificationResult.None
);
break;
case MessageType.RemoteNotificationHandler:
if (
result &&
!Object.values(RemoteNotificationResult).includes(result)
) {
throw new Error(`Invalid RemoteNotificationResult: ${result}`);
}
getNativeModule(this._messaging).completeRemoteNotification(
this.messageId,
result || RemoteNotificationResult.NoData
);
break;
default:
break;
}
}
}
}

View File

@ -4,30 +4,64 @@
*/
import { isObject, generatePushID } from './../../utils';
type NativeRemoteMessage = {
collapseKey?: string,
data: { [string]: string },
messageId: string,
messageType?: string,
to: string,
ttl: number,
};
import type {
NativeInboundRemoteMessage,
NativeOutboundRemoteMessage,
} from './types';
export default class RemoteMessage {
_collapseKey: string | void;
_data: { [string]: string };
_from: string | void;
_messageId: string;
_messageType: string | void;
_sentTime: number | void;
_to: string;
_ttl: number;
constructor() {
this._data = {};
constructor(inboundMessage?: NativeInboundRemoteMessage) {
if (inboundMessage) {
this._collapseKey = inboundMessage.collapseKey;
this._data = inboundMessage.data;
this._from = inboundMessage.from;
this._messageId = inboundMessage.messageId;
this._sentTime = inboundMessage.sentTime;
}
// defaults
this._data = this._data || {};
// TODO: Is this the best way to generate an ID?
this._messageId = generatePushID();
this._messageId = this._messageId || generatePushID();
this._ttl = 3600;
}
get collapseKey(): ?string {
return this._collapseKey;
}
get data(): { [string]: string } {
return this._data;
}
get from(): ?string {
return this._from;
}
get messageId(): ?string {
return this._messageId;
}
get sentTime(): ?number {
return this._sentTime;
}
get to(): ?string {
return this._to;
}
get ttl(): ?number {
return this._ttl;
}
/**
*
* @param collapseKey
@ -83,7 +117,7 @@ export default class RemoteMessage {
return this;
}
build(): NativeRemoteMessage {
build(): NativeOutboundRemoteMessage {
if (!this.data) {
throw new Error('RemoteMessage: Missing required `data` property');
} else if (!this.messageId) {

View File

@ -8,18 +8,12 @@ import { getLogger } from '../../utils/log';
import ModuleBase from '../../utils/ModuleBase';
import { getNativeModule } from '../../utils/native';
import { isFunction, isObject } from '../../utils';
import Message from './Message';
import RemoteMessage from './RemoteMessage';
import {
MessageType,
PresentNotificationResult,
RemoteNotificationResult,
} from './types';
import type App from '../core/app';
import type { NativeMessage } from './types';
import type { NativeInboundRemoteMessage } from './types';
type OnMessage = Message => any;
type OnMessage = RemoteMessage => any;
type OnMessageObserver = {
next: OnMessage,
@ -55,8 +49,8 @@ export default class Messaging extends ModuleBase {
// sub to internal native event - this fans out to
// public event name: onMessage
'messaging_message_received',
(message: NativeMessage) => {
SharedEventEmitter.emit('onMessage', new Message(this, message));
(message: NativeInboundRemoteMessage) => {
SharedEventEmitter.emit('onMessage', new RemoteMessage(message));
}
);
@ -75,7 +69,7 @@ export default class Messaging extends ModuleBase {
}
onMessage(nextOrObserver: OnMessage | OnMessageObserver): () => any {
let listener: Message => any;
let listener: RemoteMessage => any;
if (isFunction(nextOrObserver)) {
// $FlowBug: Not coping with the overloaded method signature
listener = nextOrObserver;
@ -89,24 +83,20 @@ export default class Messaging extends ModuleBase {
getLogger(this).info('Creating onMessage listener');
const wrappedListener = async (message: Message) => {
await listener(message);
message.complete();
};
SharedEventEmitter.addListener('onMessage', wrappedListener);
SharedEventEmitter.addListener('onMessage', listener);
return () => {
getLogger(this).info('Removing onMessage listener');
SharedEventEmitter.removeListener('onMessage', wrappedListener);
SharedEventEmitter.removeListener('onMessage', listener);
};
}
onTokenRefresh(
nextOrObserver: OnTokenRefresh | OnTokenRefreshObserver
): () => any {
let listener;
let listener: String => any;
if (isFunction(nextOrObserver)) {
// $FlowBug: Not coping with the overloaded method signature
listener = nextOrObserver;
} else if (isObject(nextOrObserver) && isFunction(nextOrObserver.next)) {
listener = nextOrObserver.next;
@ -186,8 +176,5 @@ export default class Messaging extends ModuleBase {
}
export const statics = {
MessageType,
PresentNotificationResult,
RemoteMessage,
RemoteNotificationResult,
};

View File

@ -1,35 +1,6 @@
/**
* @flow
*/
export const MessageType = {
InitialMessage: 'InitialMessage',
NotificationResponse: 'NotificationResponse',
PresentNotification: 'PresentNotification',
RemoteMessage: 'RemoteMessage',
RemoteNotification: 'RemoteNotification',
RemoteNotificationHandler: 'RemoteNotificationHandler',
};
export const PresentNotificationResult = {
All: 'UNNotificationPresentationOptionAll',
None: 'UNNotificationPresentationOptionNone',
};
export const RemoteNotificationResult = {
NewData: 'UIBackgroundFetchResultNewData',
NoData: 'UIBackgroundFetchResultNoData',
ResultFailed: 'UIBackgroundFetchResultFailed',
};
export type MessageTypeType = $Values<typeof MessageType>;
export type PresentNotificationResultType = $Values<
typeof PresentNotificationResult
>;
export type RemoteNotificationResultType = $Values<
typeof RemoteNotificationResult
>;
export type Notification = {
body: string,
bodyLocalizationArgs?: string[],
@ -46,7 +17,7 @@ export type Notification = {
titleLocalizationKey?: string,
};
export type NativeMessage = {
export type NativeInboundRemoteMessage = {
collapseKey?: string,
data: { [string]: string },
from?: string,
@ -55,3 +26,12 @@ export type NativeMessage = {
to?: string,
ttl?: number,
};
export type NativeOutboundRemoteMessage = {
collapseKey?: string,
data: { [string]: string },
messageId: string,
messageType?: string,
to: string,
ttl: number,
};

View File

@ -20,41 +20,41 @@ import type {
export default class AndroidNotification {
// TODO optional fields
// TODO actions: Action[]; // icon, title, ??pendingIntent??, allowGeneratedReplies, extender, extras, remoteinput (ugh)
_autoCancel: boolean;
_badgeIconType: BadgeIconTypeType;
_category: CategoryType;
_autoCancel: boolean | void;
_badgeIconType: BadgeIconTypeType | void;
_category: CategoryType | void;
_channelId: string;
_clickAction: string | void;
_color: string;
_colorized: boolean;
_contentInfo: string;
_defaults: DefaultsType[];
_group: string;
_groupAlertBehaviour: GroupAlertType;
_groupSummary: boolean;
_largeIcon: string;
_lights: Lights;
_localOnly: boolean;
_color: string | void;
_colorized: boolean | void;
_contentInfo: string | void;
_defaults: DefaultsType[] | void;
_group: string | void;
_groupAlertBehaviour: GroupAlertType | void;
_groupSummary: boolean | void;
_largeIcon: string | void;
_lights: Lights | void;
_localOnly: boolean | void;
_notification: Notification;
_number: number;
_ongoing: boolean;
_onlyAlertOnce: boolean;
_number: number | void;
_ongoing: boolean | void;
_onlyAlertOnce: boolean | void;
_people: string[];
_priority: PriorityType;
_progress: Progress;
_priority: PriorityType | void;
_progress: Progress | void;
// _publicVersion: Notification;
_remoteInputHistory: string[];
_shortcutId: string;
_showWhen: boolean;
_remoteInputHistory: string[] | void;
_shortcutId: string | void;
_showWhen: boolean | void;
_smallIcon: SmallIcon;
_sortKey: string;
_sortKey: string | void;
// TODO: style: Style; // Need to figure out if this can work
_ticker: string;
_timeoutAfter: number;
_usesChronometer: boolean;
_vibrate: number[];
_visibility: VisibilityType;
_when: number;
_ticker: string | void;
_timeoutAfter: number | void;
_usesChronometer: boolean | void;
_vibrate: number[] | void;
_visibility: VisibilityType | void;
_when: number | void;
// android unsupported
// content: RemoteViews
@ -112,6 +112,134 @@ export default class AndroidNotification {
};
}
get autoCancel(): ?boolean {
return this._autoCancel;
}
get badgeIconType(): ?BadgeIconTypeType {
return this._badgeIconType;
}
get category(): ?CategoryType {
return this._category;
}
get channelId(): string {
return this._channelId;
}
get clickAction(): ?string {
return this._clickAction;
}
get color(): ?string {
return this._color;
}
get colorized(): ?boolean {
return this._colorized;
}
get contentInfo(): ?string {
return this._contentInfo;
}
get defaults(): ?(DefaultsType[]) {
return this._defaults;
}
get group(): ?string {
return this._group;
}
get groupAlertBehaviour(): ?GroupAlertType {
return this._groupAlertBehaviour;
}
get groupSummary(): ?boolean {
return this._groupSummary;
}
get largeIcon(): ?string {
return this._largeIcon;
}
get lights(): ?Lights {
return this._lights;
}
get localOnly(): ?boolean {
return this._localOnly;
}
get number(): ?number {
return this._number;
}
get ongoing(): ?boolean {
return this._ongoing;
}
get onlyAlertOnce(): ?boolean {
return this._onlyAlertOnce;
}
get people(): string[] {
return this._people;
}
get priority(): ?PriorityType {
return this._priority;
}
get progress(): ?Progress {
return this._progress;
}
get remoteInputHistory(): ?(string[]) {
return this._remoteInputHistory;
}
get shortcutId(): ?string {
return this._shortcutId;
}
get showWhen(): ?boolean {
return this._showWhen;
}
get smallIcon(): SmallIcon {
return this._smallIcon;
}
get sortKey(): ?string {
return this._sortKey;
}
get ticker(): ?string {
return this._ticker;
}
get timeoutAfter(): ?number {
return this._timeoutAfter;
}
get usesChronometer(): ?boolean {
return this._usesChronometer;
}
get vibrate(): ?(number[]) {
return this._vibrate;
}
get visibility(): ?VisibilityType {
return this._visibility;
}
get when(): ?number {
return this._when;
}
/**
*
* @param person
@ -451,6 +579,10 @@ export default class AndroidNotification {
throw new Error(
'AndroidNotification: Missing required `channelId` property'
);
} else if (!this._smallIcon) {
throw new Error(
'AndroidNotification: Missing required `smallIcon` property'
);
}
return {

View File

@ -36,6 +36,34 @@ export default class IOSNotification {
this._attachments = this._attachments || [];
}
get alertAction(): ?string {
return this._alertAction;
}
get attachments(): Attachment[] {
return this._attachments;
}
get badge(): ?number {
return this._badge;
}
get category(): ?string {
return this._category;
}
get hasAction(): ?boolean {
return this._hasAction;
}
get launchImage(): ?string {
return this._launchImage;
}
get threadIdentifier(): ?string {
return this._threadIdentifier;
}
/**
*
* @param identifier

View File

@ -32,7 +32,6 @@ export default class Notification {
if (data) {
this._body = data.body;
this._data = data.data;
// TODO: Is this the best way to generate an ID?
this._notificationId = data.notificationId;
this._sound = data.sound;
this._subtitle = data.subtitle;
@ -41,6 +40,7 @@ export default class Notification {
// Defaults
this._data = this._data || {};
// TODO: Is this the best way to generate an ID?
this._notificationId = this._notificationId || generatePushID();
}
@ -48,10 +48,34 @@ export default class Notification {
return this._android;
}
get body(): string {
return this._body;
}
get data(): { [string]: string } {
return this._data;
}
get ios(): IOSNotification {
return this._ios;
}
get notificationId(): string {
return this._notificationId;
}
get sound(): ?string {
return this._sound;
}
get subtitle(): ?string {
return this._subtitle;
}
get title(): string {
return this._title;
}
/**
*
* @param body

View File

@ -79,40 +79,40 @@ export type SmallIcon = {
export type NativeAndroidNotification = {|
// TODO actions: Action[],
autoCancel: boolean,
badgeIconType: BadgeIconTypeType,
category: CategoryType,
autoCancel?: boolean,
badgeIconType?: BadgeIconTypeType,
category?: CategoryType,
channelId: string,
clickAction?: string,
color: string,
colorized: boolean,
contentInfo: string,
defaults: DefaultsType[],
group: string,
groupAlertBehaviour: GroupAlertType,
groupSummary: boolean,
largeIcon: string,
lights: Lights,
localOnly: boolean,
number: number,
ongoing: boolean,
onlyAlertOnce: boolean,
color?: string,
colorized?: boolean,
contentInfo?: string,
defaults?: DefaultsType[],
group?: string,
groupAlertBehaviour?: GroupAlertType,
groupSummary?: boolean,
largeIcon?: string,
lights?: Lights,
localOnly?: boolean,
number?: number,
ongoing?: boolean,
onlyAlertOnce?: boolean,
people: string[],
priority: PriorityType,
progress: Progress,
priority?: PriorityType,
progress?: Progress,
// publicVersion: Notification,
remoteInputHistory: string[],
shortcutId: string,
showWhen: boolean,
remoteInputHistory?: string[],
shortcutId?: string,
showWhen?: boolean,
smallIcon: SmallIcon,
sortKey: string,
sortKey?: string,
// TODO: style: Style,
ticker: string,
timeoutAfter: number,
usesChronometer: boolean,
vibrate: number[],
visibility: VisibilityType,
when: number,
ticker?: string,
timeoutAfter?: number,
usesChronometer?: boolean,
vibrate?: number[],
visibility?: VisibilityType,
when?: number,
|};
export type AttachmentOptions = {|

View File

@ -38,10 +38,6 @@
return YES;
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
[[RNFirebaseNotifications instance] didReceiveRemoteNotification:userInfo];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
[[RNFirebaseNotifications instance] didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];