Commit 903834a4 authored by Lidan Hifi's avatar Lidan Hifi

fix interactive notification action coldstart

parent 4392135f
...@@ -6,5 +6,4 @@ Handle push notifications for your app, including remote and local notifications ...@@ -6,5 +6,4 @@ Handle push notifications for your app, including remote and local notifications
## TODO ## TODO
- Add permissions management. - Add permissions management.
- Add interactive notifications support.
- Better support of local notifications. - Better support of local notifications.
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#import "RNNotifications.h" #import "RNNotifications.h"
#import "RCTConvert.h" #import "RCTConvert.h"
#import "RCTUtils.h" #import "RCTUtils.h"
#import "RNNotificationsBridgeQueue.h"
NSString* const RNNotificationCreateAction = @"CREATE"; NSString* const RNNotificationCreateAction = @"CREATE";
NSString* const RNNotificationClearAction = @"CLEAR"; NSString* const RNNotificationClearAction = @"CLEAR";
...@@ -110,6 +111,15 @@ RCT_EXPORT_MODULE() ...@@ -110,6 +111,15 @@ RCT_EXPORT_MODULE()
selector:@selector(handleNotificationActionTriggered:) selector:@selector(handleNotificationActionTriggered:)
name:RNNotificationActionTriggered name:RNNotificationActionTriggered
object:nil]; object:nil];
NSDictionary* lastActionInfo = [RNNotificationsBridgeQueue sharedInstance].lastAction;
if (lastActionInfo) {
[[NSNotificationCenter defaultCenter] postNotificationName:RNNotificationActionTriggered
object:self
userInfo:lastActionInfo];
[RNNotificationsBridgeQueue sharedInstance].lastAction = nil;
}
} }
/* /*
...@@ -146,14 +156,12 @@ RCT_EXPORT_MODULE() ...@@ -146,14 +156,12 @@ RCT_EXPORT_MODULE()
+ (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler + (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler
{ {
[self emitNotificationActionForIdentifier:identifier responseInfo:responseInfo userInfo:notification.userInfo]; [self emitNotificationActionForIdentifier:identifier responseInfo:responseInfo userInfo:notification.userInfo completionHandler:completionHandler];
completionHandler();
} }
+ (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler + (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler
{ {
[self emitNotificationActionForIdentifier:identifier responseInfo:responseInfo userInfo:userInfo]; [self emitNotificationActionForIdentifier:identifier responseInfo:responseInfo userInfo:userInfo completionHandler:completionHandler];
completionHandler();
} }
/* /*
...@@ -270,7 +278,7 @@ RCT_EXPORT_MODULE() ...@@ -270,7 +278,7 @@ RCT_EXPORT_MODULE()
[[UIApplication sharedApplication] registerUserNotificationSettings:settings]; [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
} }
+ (void)emitNotificationActionForIdentifier:(NSString *)identifier responseInfo:(NSDictionary *)responseInfo userInfo:(NSDictionary *)userInfo + (void)emitNotificationActionForIdentifier:(NSString *)identifier responseInfo:(NSDictionary *)responseInfo userInfo:(NSDictionary *)userInfo completionHandler:(void (^)())completionHandler
{ {
NSMutableDictionary* info = [[NSMutableDictionary alloc] initWithDictionary:@{ @"identifier": identifier }]; NSMutableDictionary* info = [[NSMutableDictionary alloc] initWithDictionary:@{ @"identifier": identifier }];
...@@ -289,6 +297,9 @@ RCT_EXPORT_MODULE() ...@@ -289,6 +297,9 @@ RCT_EXPORT_MODULE()
[[NSNotificationCenter defaultCenter] postNotificationName:RNNotificationActionTriggered [[NSNotificationCenter defaultCenter] postNotificationName:RNNotificationActionTriggered
object:self object:self
userInfo:info]; userInfo:info];
[RNNotificationsBridgeQueue sharedInstance].lastAction = info;
[RNNotificationsBridgeQueue sharedInstance].lastCompletionHandler = completionHandler;
} }
/* /*
...@@ -322,4 +333,18 @@ RCT_EXPORT_METHOD(updateNotificationCategories:(NSArray *)json) ...@@ -322,4 +333,18 @@ RCT_EXPORT_METHOD(updateNotificationCategories:(NSArray *)json)
[RNNotifications updateNotificationCategories:json]; [RNNotifications updateNotificationCategories:json];
} }
RCT_EXPORT_METHOD(log:(NSString *)message)
{
NSLog(message);
}
RCT_EXPORT_METHOD(completionHandler)
{
void (^completionHandler)() = [RNNotificationsBridgeQueue sharedInstance].lastCompletionHandler;
if (completionHandler) {
completionHandler();
[RNNotificationsBridgeQueue sharedInstance].lastCompletionHandler = nil;
}
}
@end @end
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
D85B37451CC05A0900DE9EB6 /* RNNotificationsBridgeQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = D85B37441CC05A0900DE9EB6 /* RNNotificationsBridgeQueue.m */; };
D8A2F7551CB57F1A002CC8F5 /* RNNotifications.m in Sources */ = {isa = PBXBuildFile; fileRef = D8A2F7541CB57F1A002CC8F5 /* RNNotifications.m */; }; D8A2F7551CB57F1A002CC8F5 /* RNNotifications.m in Sources */ = {isa = PBXBuildFile; fileRef = D8A2F7541CB57F1A002CC8F5 /* RNNotifications.m */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
...@@ -24,6 +25,8 @@ ...@@ -24,6 +25,8 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
134814201AA4EA6300B7C361 /* libRNNotifications.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNNotifications.a; sourceTree = BUILT_PRODUCTS_DIR; }; 134814201AA4EA6300B7C361 /* libRNNotifications.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNNotifications.a; sourceTree = BUILT_PRODUCTS_DIR; };
D85B37441CC05A0900DE9EB6 /* RNNotificationsBridgeQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNotificationsBridgeQueue.m; sourceTree = "<group>"; };
D85B37461CC05A1200DE9EB6 /* RNNotificationsBridgeQueue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNotificationsBridgeQueue.h; sourceTree = "<group>"; };
D8A2F7541CB57F1A002CC8F5 /* RNNotifications.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNotifications.m; sourceTree = "<group>"; }; D8A2F7541CB57F1A002CC8F5 /* RNNotifications.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNotifications.m; sourceTree = "<group>"; };
D8A2F7561CB57F28002CC8F5 /* RNNotifications.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNNotifications.h; sourceTree = "<group>"; }; D8A2F7561CB57F28002CC8F5 /* RNNotifications.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNNotifications.h; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
...@@ -50,6 +53,8 @@ ...@@ -50,6 +53,8 @@
58B511D21A9E6C8500147676 = { 58B511D21A9E6C8500147676 = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D85B37461CC05A1200DE9EB6 /* RNNotificationsBridgeQueue.h */,
D85B37441CC05A0900DE9EB6 /* RNNotificationsBridgeQueue.m */,
D8A2F7561CB57F28002CC8F5 /* RNNotifications.h */, D8A2F7561CB57F28002CC8F5 /* RNNotifications.h */,
D8A2F7541CB57F1A002CC8F5 /* RNNotifications.m */, D8A2F7541CB57F1A002CC8F5 /* RNNotifications.m */,
134814211AA4EA7D00B7C361 /* Products */, 134814211AA4EA7D00B7C361 /* Products */,
...@@ -113,6 +118,7 @@ ...@@ -113,6 +118,7 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
D8A2F7551CB57F1A002CC8F5 /* RNNotifications.m in Sources */, D8A2F7551CB57F1A002CC8F5 /* RNNotifications.m in Sources */,
D85B37451CC05A0900DE9EB6 /* RNNotificationsBridgeQueue.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
......
#import <Foundation/Foundation.h>
@interface RNNotificationsBridgeQueue : NSObject
@property (nonatomic, retain) NSDictionary* lastAction;
@property (nonatomic, copy) void (^lastCompletionHandler)();
+ (nonnull instancetype)sharedInstance;
@end
\ No newline at end of file
#import "RNNotificationsBridgeQueue.h"
@implementation RNNotificationsBridgeQueue
+ (nonnull instancetype)sharedInstance {
static RNNotificationsBridgeQueue* sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [self new];
});
return sharedInstance;
}
@end
\ No newline at end of file
...@@ -14,47 +14,51 @@ import React, { ...@@ -14,47 +14,51 @@ import React, {
import NotificationsIOS, { NotificationAction, NotificationCategory } from 'react-native-notifications'; import NotificationsIOS, { NotificationAction, NotificationCategory } from 'react-native-notifications';
class NotificationsExampleApp extends Component { let upvoteAction = new NotificationAction({
constructor() {
super();
PushNotificationIOS.addEventListener('register', this.onPushRegistered.bind(this));
NotificationsIOS.addEventListener('notificationReceivedForeground', this.onNotificationReceivedForeground.bind(this));
NotificationsIOS.addEventListener('notificationReceivedBackground', this.onNotificationReceivedBackground.bind(this));
NotificationsIOS.addEventListener('notificationOpened', this.onNotificationOpened.bind(this));
}
componentDidMount() {
PushNotificationIOS.requestPermissions();
let upvoteAction = new NotificationAction({
activationMode: "background", activationMode: "background",
title: String.fromCodePoint(0x1F44D), title: String.fromCodePoint(0x1F44D),
identifier: "UPVOTE_ACTION" identifier: "UPVOTE_ACTION"
}, (action) => { }, (action, completed) => {
console.log("ACTION RECEIVED"); NotificationsIOS.log("ACTION RECEIVED");
console.log(action); NotificationsIOS.log(JSON.stringify(action));
});
completed();
});
let replyAction = new NotificationAction({ let replyAction = new NotificationAction({
activationMode: "background", activationMode: "background",
title: "Reply", title: "Reply",
behavior: "textInput", behavior: "textInput",
authenticationRequired: true, authenticationRequired: true,
identifier: "REPLY_ACTION" identifier: "REPLY_ACTION"
}, (action) => { }, (action, completed) => {
console.log("ACTION RECEIVED"); console.log("ACTION RECEIVED");
console.log(action); console.log(action);
});
let cat = new NotificationCategory({ completed();
});
let cat = new NotificationCategory({
identifier: "SOME_CATEGORY", identifier: "SOME_CATEGORY",
actions: [upvoteAction, replyAction], actions: [upvoteAction, replyAction],
context: "default" context: "default"
}); });
NotificationsIOS.setCategories([cat]);
class NotificationsExampleApp extends Component {
constructor() {
super();
PushNotificationIOS.addEventListener('register', this.onPushRegistered.bind(this));
NotificationsIOS.addEventListener('notificationReceivedForeground', this.onNotificationReceivedForeground.bind(this));
NotificationsIOS.addEventListener('notificationReceivedBackground', this.onNotificationReceivedBackground.bind(this));
NotificationsIOS.addEventListener('notificationOpened', this.onNotificationOpened.bind(this));
}
NotificationsIOS.setCategories([cat]); componentDidMount() {
// PushNotificationIOS.requestPermissions();
} }
onPushRegistered(deviceToken) { onPushRegistered(deviceToken) {
...@@ -94,7 +98,7 @@ class NotificationsExampleApp extends Component { ...@@ -94,7 +98,7 @@ class NotificationsExampleApp extends Component {
NotificationsIOS.removeEventListener('notificationReceivedForeground', this.onNotificationReceivedForeground.bind(this)); NotificationsIOS.removeEventListener('notificationReceivedForeground', this.onNotificationReceivedForeground.bind(this));
NotificationsIOS.removeEventListener('notificationReceivedBackground', this.onNotificationReceivedBackground.bind(this)); NotificationsIOS.removeEventListener('notificationReceivedBackground', this.onNotificationReceivedBackground.bind(this));
NotificationsIOS.removeEventListener('notificationOpened', this.onNotificationOpened.bind(this)); NotificationsIOS.removeEventListener('notificationOpened', this.onNotificationOpened.bind(this));
NotificationsIOS.resetCategories(); // NotificationsIOS.resetCategories();
} }
_onNotification(notification) { _onNotification(notification) {
......
...@@ -76,7 +76,9 @@ export default class NotificationsIOS { ...@@ -76,7 +76,9 @@ export default class NotificationsIOS {
let actionHandler = _actionHandlers.get(action.identifier); let actionHandler = _actionHandlers.get(action.identifier);
if (actionHandler) { if (actionHandler) {
actionHandler(action); action.notification = new IOSNotification(action.notification);
actionHandler(action, () => { NativeRNNotifications.completionHandler(); });
} }
} }
...@@ -89,7 +91,7 @@ export default class NotificationsIOS { ...@@ -89,7 +91,7 @@ export default class NotificationsIOS {
if (categories) { if (categories) {
// subscribe once for all actions // subscribe once for all actions
_actionListener = NativeAppEventEmitter.addListener(DEVICE_NOTIFICATION_ACTION_RECEIVED, this._actionHandlerDispatcher); _actionListener = NativeAppEventEmitter.addListener(DEVICE_NOTIFICATION_ACTION_RECEIVED, this._actionHandlerDispatcher.bind(this));
notificationCategories = categories.map(category => { notificationCategories = categories.map(category => {
return Object.assign({}, category.options, { return Object.assign({}, category.options, {
...@@ -117,4 +119,8 @@ export default class NotificationsIOS { ...@@ -117,4 +119,8 @@ export default class NotificationsIOS {
_actionHandlers.clear(); _actionHandlers.clear();
} }
static log(message) {
NativeRNNotifications.log(message);
}
} }
...@@ -149,7 +149,7 @@ describe("NotificationsIOS", () => { ...@@ -149,7 +149,7 @@ describe("NotificationsIOS", () => {
NotificationsIOS.setCategories([someCategory]); NotificationsIOS.setCategories([someCategory]);
expect(nativeAppAddEventListener).to.have.been.calledOnce; expect(nativeAppAddEventListener).to.have.been.calledOnce;
expect(nativeAppAddEventListener).to.have.been.calledWith("notificationActionReceived", NotificationsIOS._actionHandlerDispatcher); expect(nativeAppAddEventListener).to.have.been.calledWith("notificationActionReceived", sinon.match.func);
}); });
}); });
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment