Skip to content

Commit

Permalink
fix(messaging): initialize app props method to fix isHeadless property (
Browse files Browse the repository at this point in the history
#4082)

Co-authored-by: Mike Diarmid <mike.diarmid@gmail.com>
  • Loading branch information
russellwheatley and Salakar authored Aug 15, 2020
1 parent fe83d28 commit 2bdebb1
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 13 deletions.
23 changes: 21 additions & 2 deletions docs/messaging/usage/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ Although the library supports handling messages in background/quit states, the u
On Android, a [Headless JS](https://reactnative.dev/docs/headless-js-android) task (an Android only feature) is created that runs separately to your main React component; allowing your background handler code to run without mounting your root component.

On iOS however, when a message is received the device silently starts your application in a background state. At this point, your background handler (via `setBackgroundMessageHandler`) is triggered, but your root React component also gets mounted. This can be problematic for some users since any side-effects will be called inside of your app (e.g. `useEffects`, analytics events/triggers etc). To get around this problem,
the messaging module injects a `isHeadless` prop to your root component which you can conditionally use to render/do "nothing" if your app is launched in the background:
you can configure your `AppDelegate.m` file (see instructions below) to inject a `isHeadless` prop into your root component. Use this property to conditionally render `null` ("nothing") if your app is launched in the background:

```jsx
// index.js
Expand All @@ -273,7 +273,26 @@ function App{) {
AppRegistry.registerComponent('app', () => HeadlessCheck);
```

On Android, this prop will not exist.
To inject a `isHeadless` prop into your app, please update your `AppDelegate.m` file as instructed below:

```obj-c
// add this import statement at the top of your `AppDelegate.m` file
#import "RNFBMessagingModule.h"

// in "(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions" method
// Use `addCustomPropsToUserProps` to pass in props for initialization of your app
// Or pass in `nil` if you have none as per below example
// For `withLaunchOptions` please pass in `launchOptions` object
NSDictionary *appProperties = [RNFBMessagingModule addCustomPropsToUserProps:nil withLaunchOptions:launchOptions];

// Find the `RCTRootView` instance and update the `initialProperties` with your `appProperties` instance
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
moduleName:@"nameOfYourApp"
initialProperties:appProperties];
```
On Android, the `isHeadless` prop will not exist.
### Topics
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,12 @@ - (void)application_onDidFinishLaunchingNotification:(nonnull NSNotification *)n
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
if (rctRootView != nil) {
NSMutableDictionary *appPropertiesDict = rctRootView.appProperties != nil ? [rctRootView.appProperties mutableCopy] : [NSMutableDictionary dictionary];
appPropertiesDict[@"isHeadless"] = @([RCTConvert BOOL:@(YES)]);
rctRootView.appProperties = appPropertiesDict;
if([appPropertiesDict objectForKey:@"isHeadless"] != nil && [appPropertiesDict[@"isHeadless"] isEqual:@([RCTConvert BOOL:@(NO)])]) {
appPropertiesDict[@"isHeadless"] = @([RCTConvert BOOL:@(YES)]);
rctRootView.appProperties = appPropertiesDict;
}
}

#if !(TARGET_IPHONE_SIMULATOR)
// When an app launches in the background (BG mode) and is launched with the notification launch option the app delegate method
// application:didReceiveRemoteNotification:fetchCompletionHandler: will not get called unless registerForRemoteNotifications
Expand All @@ -151,15 +154,21 @@ - (void)application_onDidFinishLaunchingNotification:(nonnull NSNotification *)n
} else {
if (rctRootView != nil) {
NSMutableDictionary *appPropertiesDict = rctRootView.appProperties != nil ? [rctRootView.appProperties mutableCopy] : [NSMutableDictionary dictionary];
appPropertiesDict[@"isHeadless"] = @([RCTConvert BOOL:@(NO)]);
rctRootView.appProperties = appPropertiesDict;
if([appPropertiesDict objectForKey:@"isHeadless"] != nil && [appPropertiesDict[@"isHeadless"] isEqual:@([RCTConvert BOOL:@(YES)])]) {
appPropertiesDict[@"isHeadless"] = @([RCTConvert BOOL:@(NO)]);
rctRootView.appProperties = appPropertiesDict;
}

}
}
} else {
if (rctRootView != nil) {
NSMutableDictionary *appPropertiesDict = rctRootView.appProperties != nil ? [rctRootView.appProperties mutableCopy] : [NSMutableDictionary dictionary];
appPropertiesDict[@"isHeadless"] = @([RCTConvert BOOL:@(NO)]);
rctRootView.appProperties = appPropertiesDict;
if([appPropertiesDict objectForKey:@"isHeadless"] != nil && [appPropertiesDict[@"isHeadless"] isEqual:@([RCTConvert BOOL:@(YES)])]) {
appPropertiesDict[@"isHeadless"] = @([RCTConvert BOOL:@(NO)]);
rctRootView.appProperties = appPropertiesDict;
}

}
}
}
Expand All @@ -175,8 +184,10 @@ - (void)application_onDidEnterForeground {
RCTRootView *rctRootView = (RCTRootView *) [UIApplication sharedApplication].delegate.window.rootViewController.view;
if (rctRootView.appProperties != nil && rctRootView.appProperties[@"isHeadless"] == @(YES)) {
NSMutableDictionary *appPropertiesDict = [rctRootView.appProperties mutableCopy];
appPropertiesDict[@"isHeadless"] = @([RCTConvert BOOL:@(NO)]);
rctRootView.appProperties = appPropertiesDict;
if([appPropertiesDict objectForKey:@"isHeadless"] != nil && [appPropertiesDict[@"isHeadless"] isEqual:@([RCTConvert BOOL:@(YES)])]) {
appPropertiesDict[@"isHeadless"] = @([RCTConvert BOOL:@(NO)]);
rctRootView.appProperties = appPropertiesDict;
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/messaging/ios/RNFBMessaging/RNFBMessagingModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@


@interface RNFBMessagingModule : NSObject <RCTBridgeModule>

+ (NSDictionary *)addCustomPropsToUserProps:(NSDictionary *_Nullable)userProps withLaunchOptions:(NSDictionary *_Nullable)launchOptions;
@end
13 changes: 13 additions & 0 deletions packages/messaging/ios/RNFBMessaging/RNFBMessagingModule.m
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,19 @@ + (BOOL)requiresMainQueueSetup {
return YES;
}

+ (NSDictionary *)addCustomPropsToUserProps:(NSDictionary *_Nullable)userProps withLaunchOptions:(NSDictionary *_Nullable)launchOptions {
NSMutableDictionary *appProperties = userProps != nil ? [userProps mutableCopy] : [NSMutableDictionary dictionary];
appProperties[@"isHeadless"] = @([RCTConvert BOOL:@(NO)]);

if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) {
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
appProperties[@"isHeadless"] = @([RCTConvert BOOL:@(YES)]);
}
}

return [NSDictionary dictionaryWithDictionary:appProperties];
}

- (NSDictionary *)constantsToExport {
NSMutableDictionary *constants = [NSMutableDictionary new];
constants[@"isAutoInitEnabled"] = @([RCTConvert BOOL:@([FIRMessaging messaging].autoInitEnabled)]);
Expand Down
6 changes: 4 additions & 2 deletions tests/ios/testing/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*/

#import "AppDelegate.h"

#import "RNFBMessagingModule.h"
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <Firebase/Firebase.h>
Expand All @@ -32,9 +32,11 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
NSURL *jsCodeLocation;
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];

NSDictionary *appProperties = [RNFBMessagingModule addCustomPropsToUserProps:nil withLaunchOptions:launchOptions];

RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"testing"
initialProperties:nil
initialProperties:appProperties
launchOptions:launchOptions];


Expand Down

0 comments on commit 2bdebb1

Please sign in to comment.