tinycreative / react-native-intercom

React Native wrapper for Intercom.io
MIT License
406 stars 280 forks source link

iOS 13: Black flash while closing or opening the intercom window #361

Closed hemche closed 3 years ago

hemche commented 4 years ago

I am using Intercom.displayMessenger() method and seeing below behaviour (sample app) only on iOS 13+. I have contacted Intercom support and they ruled out it is due to react native dependencies.

Dependencies Used:

"react": "16.11.0", "react-native": "0.62.2", "react-native-intercom": "^15.0.0"

Screen-Recording-2020-04-24-at-6 44 10-PM

graphtobinary commented 4 years ago

+1

AppKidd commented 4 years ago

I also tried to get Intercom to look at this to no avail.

ilyagru commented 4 years ago

+1. Got this issue on react-native: 63.2, react-native-intercom: 17.0.0, ios: 13.6. Any fixes/workarounds?

AppKidd commented 4 years ago

@ilyagru We haven't found any fixes/workarounds. Contacted Intercom and they insisted it has to be solved on the React Native side. It works fine in the standalone iOS SDK, so it's something to do with how React Native is presenting the SDK. My guess is it's related to RCTRootView/RCTBridge but we don't have the resource to look into this at the moment.

AppKidd commented 4 years ago

Hi everyone. We're spending some more time look at this over the next few days.

We've managed to reproduce the problem outside of React Native. If you try and present the Intercom VC outside of an iOS storyboard, you also see the black screen. See this gist for a quick example:

https://gist.github.com/Appkidd/0c75332a6a6eb800a86fb238376a771e https://i.imgur.com/7GOqj3m.mp4

I've sent this over to Intercom for comment. Hopefully by abstracting this to an iOS level (aka not a React Native problem) their engineers will take a look. It's a real eyesore so we'd love to find a fix/workaround for this.

My best guess at this stage is that it's to do with the method the framework uses to present the Intercom which for some reason works nicely with Storyboards, but not but UIWindow/rootViewController.

Will update if we make any progress.

BohdanIvanov commented 4 years ago

Got this issue on "react-native": "0.62.2" as well

rolfb commented 4 years ago

Seeing this as well. Looks like it isn't "jumping in front" of the screen it's opened from anymore?

younes200 commented 4 years ago

@Appkidd is there a ticket opened on Intercom's side to track this issue ?

hemche commented 4 years ago

Intercom support team ruled out suggesting that they cannot confirm the issue is on their side as i am using this react native dependency to install and use intercom. Upon further debugging, this is what has solved the issue for me.

There was this string in the info.plist. i had to remove this and after this, i don't see the flash anymore.

<key>UIMainStoryboardFile</key> <string>LaunchScreen</string>

Screen Shot 2020-09-08 at 1 13 59 PM
rolfb commented 4 years ago

Made the switch from using a Launch Screen.xib to a Launch Screen Storyboard and things seems to work for me now.

BohdanIvanov commented 4 years ago

@rolfb Tried to do the same, but still, get the black flash :(

What kind of react-native version you are using?

rolfb commented 4 years ago

What kind of react-native version you are using?

@BohdanIvanov

    "react": "16.13.1",
    "react-native": "0.63.2",
    "react-native-intercom": "^17.0.0",

Heartily recommend upgrading to 0.63, works much better than 0.62.

BohdanIvanov commented 4 years ago

@rolfb I've tried on react-native: "0.62.2" and react-native-intercom: "^13.1.0" and it didn't worked. Perhaps on newer versions, it's different.

BohdanIvanov commented 4 years ago

@rolfb I've updated react-native to 0.63.2 and react-native-intercom to ^17.0.0. Unfortunately, it didn't help. Used the storyboard format as Launch Screen instead of a xib.

rolfb commented 4 years ago

@BohdanIvanov

Have you set up the storyboard in AppDelegate.m? Code may vary on the name and ViewController identifier.

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Launch Screen" bundle:[NSBundle mainBundle]];
UIViewController *launchScreenViewController = [storyboard instantiateViewControllerWithIdentifier:@"Launch Screen"];

launchScreenViewController.view.frame = self.window.bounds;
rootView.loadingView = launchScreenViewController.view;
BohdanIvanov commented 4 years ago

@rolfb Nope, I've followed the next article, in order to replace xib with the storyboard https://blog.echobind.com/react-native-ios-splash-screen-with-storyboard-f6f9d847994e

rolfb commented 4 years ago

@BohdanIvanov Ok, try adding the above, and check that you've removed all mentions the xib and removed it from your project in Xcode. It's easiest to search across all the files in the project if you used a new name for the Storyboard instead of the same as the xib.

BohdanIvanov commented 4 years ago

@rolfb Ok, I've created the Launch Screen.storyboard file. Attached a storyboard ID and added lines of code that you mentioned above to the AppDelegate.m, but it still does have a flash. Perhaps I'm doing something wrong here?

Screenshot 2020-09-09 at 12 27 58 Screenshot 2020-09-09 at 12 27 04
rolfb commented 4 years ago

@BohdanIvanov did you completely clean and rebuild the project after this?

BohdanIvanov commented 4 years ago

@rolfb Yes. Before every build, I run the Clear Build Folder command. Also tried with deleting the app from the phone.

rolfb commented 4 years ago

@BohdanIvanov can you share the full code in AppDelegate.m?

StaffanKilnes commented 4 years ago

Currently experiencing the same issue as @BohdanIvanov. Following your conversation closely, let me know if I can provide any information! Issue arose for me when I upgraded RN version to 0.63.2 which had me switch from an .xib file to a .storyboard file.

rolfb commented 4 years ago

@StaffanKilnes can you share your AppDelegate.m?

StaffanKilnes commented 4 years ago

Absolutely! Might be worth mentioning that I have a LaunchScreen.storyboard file and that with this code, the app crashes immediately on startup.

#import "AppDelegate.h"

#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>

#import <CodePush/CodePush.h>
#import "AppCenterReactNative.h"
#import "Intercom/intercom.h"
#import <Firebase.h>
#import <react-native-splash-screen/RNSplashScreen.h>
#import <React/RCTLinkingManager.h>

#ifdef FB_SONARKIT_ENABLED
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>
static void InitializeFlipper(UIApplication *application) {
  FlipperClient *client = [FlipperClient sharedClient];
  SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
  [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
  [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
  [client addPlugin:[FlipperKitReactPlugin new]];
  [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
  [client start];
}
#endif

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  #ifdef FB_SONARKIT_ENABLED
    InitializeFlipper(application);
  #endif
  // Init Appcenter
  [AppCenterReactNative register];
  // Init Intercom
  NSString *intercomApiKey = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"IntercomApiKey"];
  NSString *intercomAppId = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"IntercomAppId"];
  [Intercom setApiKey:intercomApiKey forAppId:intercomAppId];
  [Intercom setInAppMessagesVisible:FALSE];
  // Firebase
  [FIRApp configure];
  // Other
  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                   moduleName:@"OMITTED"
                                            initialProperties:nil];

  rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];

  UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"LaunchScreen" bundle:[NSBundle mainBundle]];
  UIViewController *launchScreenViewController = [storyboard instantiateViewControllerWithIdentifier:@"LaunchScreen"];

  launchScreenViewController.view.frame = self.window.bounds;
  rootView.loadingView = launchScreenViewController.view;

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];

  [RNSplashScreen show];
  return YES;
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
  return [CodePush bundleURL];
#endif
}

//for deeplinking per https://reactnavigation.org/docs/en/deep-linking.html#set-up-with-react-native-init-projects
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
  return [RCTLinkingManager application:app openURL:url options:options];
}

@end
rolfb commented 4 years ago

@StaffanKilnes if it's crashing it's not very helpful, but please share the error message. Would try removing [RNSplashScreen show]; when you are using rootView.loadingView.

StaffanKilnes commented 4 years ago

Alright, so the crash was my bad, forgot to give the storyboard a matching ID. Also removed [RNSplashScreen show];. The app is starting now but opening Intercom still "hides" the entire app instead of "pushing it" backwards and displaying on top of it. Also flashes black when closing.

rolfb commented 4 years ago

@StaffanKilnes try moving

  UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"LaunchScreen" bundle:[NSBundle mainBundle]];
  UIViewController *launchScreenViewController = [storyboard instantiateViewControllerWithIdentifier:@"LaunchScreen"];

  launchScreenViewController.view.frame = self.window.bounds;
  rootView.loadingView = launchScreenViewController.view;

below [self.window makeKeyAndVisible];

StaffanKilnes commented 4 years ago

Still no luck I'm afraid.. Performed a full react-native-clean-project and cleaned build folders etc.. Any other suggestions?

Br1an-Boyle commented 4 years ago

👋 Thanks @Appkidd for your sample code from this comment. I've managed to re-create the issue. The fix will be available in the next release of the Intercom iOS SDK

AppKidd commented 4 years ago

Excellent! Thanks so much @bboyle18

rolfb commented 4 years ago

@bboyle18 great, thanks for joining the conversation ⭐

Br1an-Boyle commented 4 years ago

No problem 😄 It's likely that this release will be next week when we release support for iOS 14.

rolfb commented 4 years ago

@bboyle18 Sounds good. Is there a way around it in the meantime? I had the issue yesterday but apparently did something to fix the issue, ... and apparently I have no clue what exactly. 😀

Br1an-Boyle commented 4 years ago

Not really I'm afraid. The root cause is your app having two UIWindow objects and one being hidden. When Intercom is opened, we grab the first non-intercom window we can find, take a snapshot of it and so that its presented behind the Intercom window. The background is black because we end up grabbing a snapshot of the hidden UIWindow. If you can figure out how to not have a hidden UIWindow in your app, then it will work.

BohdanIvanov commented 4 years ago

@rolfb Thank you for your help. @bboyle18 Thank you for joining 👍

hemche commented 4 years ago

Thanks all and @bboyle18 for bringing this to closure. On the other side, these were the two changes that fixed the issue for me. I had to move from LaunchScreen.xib to Launchscreen.storyboardas well. and yes, i had to uninstall the existing app and clean build&run to see the changes.

Screen Shot 2020-09-09 at 10 24 54 AM Screen Shot 2020-09-08 at 1 13 59 PM
hemche commented 3 years ago

@bboyle18 Now that Intercom iOS 8.0.0 is released, Can we assume that this issue had been taken care of ?

Br1an-Boyle commented 3 years ago

Yep, the fix is included in the 8.0.0 release.

younes200 commented 3 years ago

A new release of react-native-intercom is required, with updated pod dependencies to use 8.0.0.

Br1an-Boyle commented 3 years ago

@younes200 FYI....we've not updated the Intercom Pod with 8.0.0 just yet. It's coming later this afternoon. Just in case you were trying to update it now 😄

Br1an-Boyle commented 3 years ago

@younes200 8.0.0 pod is there now 😄

BohdanIvanov commented 3 years ago

Does anyone know when react-native-intercom plans to release an update with the latest pod version?

younes200 commented 3 years ago

A MR is still pending, until then my fork. @bboyle18 this package is used by high number of projets, will Intercom be interested to maintain this package too ?

Br1an-Boyle commented 3 years ago

Hi @younes200 👋 Unfortunately we're not able to maintain this project at this time. Brian