This repository was archived by the owner on Jul 28, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(plugin): add ios expo plugin (#72)
* feat(plugin): add ios expo plugin * ✏️ (expo) rename iOSApiKey to iosApiKey * ♻️ (expo) import Batch earlier in AppDelegate * 📝 (expo) update android installation doc * 📝 (expo) add ios installation doc * 📝 (expo) update ios warning on AppDelegate * 📝 (expo) delete ios comment about previous version
- Loading branch information
Showing
9 changed files
with
441 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 13 additions & 0 deletions
13
plugin/src/__tests__/withReactNativeBatchAppDelegate.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { modifyAppDelegate } from '../withReactNativeBatchAppDelegate'; | ||
import { | ||
appDelegateExpectedFixture, | ||
appDelegateFixture, | ||
} from '../fixtures/appDelegate'; | ||
|
||
describe(modifyAppDelegate, () => { | ||
it('should modify the AppDelegate', () => { | ||
const result = modifyAppDelegate(appDelegateFixture); | ||
|
||
expect(result).toEqual(appDelegateExpectedFixture); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,319 @@ | ||
export const appDelegateFixture = `#import "AppDelegate.h" | ||
#if defined(EX_DEV_MENU_ENABLED) | ||
@import EXDevMenu; | ||
#endif | ||
#if defined(EX_DEV_LAUNCHER_ENABLED) | ||
#include <EXDevLauncher/EXDevLauncherController.h> | ||
#import <EXUpdates/EXUpdatesDevLauncherController.h> | ||
#endif | ||
#import <React/RCTBridge.h> | ||
#import <React/RCTBundleURLProvider.h> | ||
#import <React/RCTRootView.h> | ||
#import <React/RCTLinkingManager.h> | ||
#import <UMCore/UMModuleRegistry.h> | ||
#import <UMReactNativeAdapter/UMNativeModulesProxy.h> | ||
#import <UMReactNativeAdapter/UMModuleRegistryAdapter.h> | ||
#import <EXSplashScreen/EXSplashScreenService.h> | ||
#import <UMCore/UMModuleRegistryProvider.h> | ||
#if defined(FB_SONARKIT_ENABLED) && __has_include(<FlipperKit/FlipperClient.h>) | ||
#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 | ||
@interface AppDelegate () <RCTBridgeDelegate> | ||
@property (nonatomic, strong) UMModuleRegistryAdapter *moduleRegistryAdapter; | ||
@property (nonatomic, strong) NSDictionary *launchOptions; | ||
@end | ||
@implementation AppDelegate | ||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions | ||
{ | ||
#if defined(FB_SONARKIT_ENABLED) && __has_include(<FlipperKit/FlipperClient.h>) | ||
InitializeFlipper(application); | ||
#endif | ||
self.moduleRegistryAdapter = [[UMModuleRegistryAdapter alloc] initWithModuleRegistryProvider:[[UMModuleRegistryProvider alloc] init]]; | ||
self.launchOptions = launchOptions; | ||
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; | ||
#ifdef DEBUG | ||
#if defined(EX_DEV_LAUNCHER_ENABLED) | ||
EXDevLauncherController *controller = [EXDevLauncherController sharedInstance]; | ||
controller.updatesInterface = [EXUpdatesDevLauncherController sharedInstance]; | ||
[controller startWithWindow:self.window delegate:(id<EXDevLauncherControllerDelegate>)self launchOptions:launchOptions]; | ||
#else | ||
[self initializeReactNativeApp]; | ||
#endif | ||
#else | ||
EXUpdatesAppController *controller = [EXUpdatesAppController sharedInstance]; | ||
controller.delegate = self; | ||
[controller startAndShowLaunchScreen:self.window]; | ||
#endif | ||
[super application:application didFinishLaunchingWithOptions:launchOptions]; | ||
return YES; | ||
} | ||
- (RCTBridge *)initializeReactNativeApp | ||
{ | ||
#if defined(EX_DEV_LAUNCHER_ENABLED) | ||
NSDictionary *launchOptions = [EXDevLauncherController.sharedInstance getLaunchOptions]; | ||
#else | ||
NSDictionary *launchOptions = self.launchOptions; | ||
#endif | ||
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; | ||
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"main" initialProperties:nil]; | ||
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; | ||
UIViewController *rootViewController = [UIViewController new]; | ||
rootViewController.view = rootView; | ||
self.window.rootViewController = rootViewController; | ||
[self.window makeKeyAndVisible]; | ||
return bridge; | ||
} | ||
- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge | ||
{ | ||
NSArray<id<RCTBridgeModule>> *extraModules = [_moduleRegistryAdapter extraModulesForBridge:bridge]; | ||
// If you'd like to export some custom RCTBridgeModules that are not Expo modules, add them here! | ||
return extraModules; | ||
} | ||
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { | ||
#ifdef DEBUG | ||
#if defined(EX_DEV_LAUNCHER_ENABLED) | ||
return [[EXDevLauncherController sharedInstance] sourceUrl]; | ||
#else | ||
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; | ||
#endif | ||
#else | ||
return [[EXUpdatesAppController sharedInstance] launchAssetUrl]; | ||
#endif | ||
} | ||
- (void)appController:(EXUpdatesAppController *)appController didStartWithSuccess:(BOOL)success { | ||
appController.bridge = [self initializeReactNativeApp]; | ||
EXSplashScreenService *splashScreenService = (EXSplashScreenService *)[UMModuleRegistryProvider getSingletonModuleForClass:[EXSplashScreenService class]]; | ||
[splashScreenService showSplashScreenFor:self.window.rootViewController]; | ||
} | ||
// Linking API | ||
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options { | ||
#if defined(EX_DEV_LAUNCHER_ENABLED) | ||
if ([EXDevLauncherController.sharedInstance onDeepLink:url options:options]) { | ||
return true; | ||
} | ||
#endif | ||
return [RCTLinkingManager application:application openURL:url options:options]; | ||
} | ||
// Universal Links | ||
- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler { | ||
return [RCTLinkingManager application:application | ||
continueUserActivity:userActivity | ||
restorationHandler:restorationHandler]; | ||
} | ||
@end | ||
#if defined(EX_DEV_LAUNCHER_ENABLED) | ||
@implementation AppDelegate (EXDevLauncherControllerDelegate) | ||
- (void)devLauncherController:(EXDevLauncherController *)developmentClientController | ||
didStartWithSuccess:(BOOL)success | ||
{ | ||
developmentClientController.appBridge = [self initializeReactNativeApp]; | ||
EXSplashScreenService *splashScreenService = (EXSplashScreenService *)[UMModuleRegistryProvider getSingletonModuleForClass:[EXSplashScreenService class]]; | ||
[splashScreenService showSplashScreenFor:self.window.rootViewController]; | ||
} | ||
@end | ||
#endif | ||
`; | ||
|
||
export const appDelegateExpectedFixture = `#import "AppDelegate.h" | ||
#import <RNBatchPush/RNBatch.h> | ||
#if defined(EX_DEV_MENU_ENABLED) | ||
@import EXDevMenu; | ||
#endif | ||
#if defined(EX_DEV_LAUNCHER_ENABLED) | ||
#include <EXDevLauncher/EXDevLauncherController.h> | ||
#import <EXUpdates/EXUpdatesDevLauncherController.h> | ||
#endif | ||
#import <React/RCTBridge.h> | ||
#import <React/RCTBundleURLProvider.h> | ||
#import <React/RCTRootView.h> | ||
#import <React/RCTLinkingManager.h> | ||
#import <UMCore/UMModuleRegistry.h> | ||
#import <UMReactNativeAdapter/UMNativeModulesProxy.h> | ||
#import <UMReactNativeAdapter/UMModuleRegistryAdapter.h> | ||
#import <EXSplashScreen/EXSplashScreenService.h> | ||
#import <UMCore/UMModuleRegistryProvider.h> | ||
#if defined(FB_SONARKIT_ENABLED) && __has_include(<FlipperKit/FlipperClient.h>) | ||
#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 | ||
@interface AppDelegate () <RCTBridgeDelegate> | ||
@property (nonatomic, strong) UMModuleRegistryAdapter *moduleRegistryAdapter; | ||
@property (nonatomic, strong) NSDictionary *launchOptions; | ||
@end | ||
@implementation AppDelegate | ||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions | ||
{ | ||
[RNBatch start]; | ||
[BatchUNUserNotificationCenterDelegate registerAsDelegate]; | ||
[BatchUNUserNotificationCenterDelegate sharedInstance].showForegroundNotifications = true; | ||
#if defined(FB_SONARKIT_ENABLED) && __has_include(<FlipperKit/FlipperClient.h>) | ||
InitializeFlipper(application); | ||
#endif | ||
self.moduleRegistryAdapter = [[UMModuleRegistryAdapter alloc] initWithModuleRegistryProvider:[[UMModuleRegistryProvider alloc] init]]; | ||
self.launchOptions = launchOptions; | ||
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; | ||
#ifdef DEBUG | ||
#if defined(EX_DEV_LAUNCHER_ENABLED) | ||
EXDevLauncherController *controller = [EXDevLauncherController sharedInstance]; | ||
controller.updatesInterface = [EXUpdatesDevLauncherController sharedInstance]; | ||
[controller startWithWindow:self.window delegate:(id<EXDevLauncherControllerDelegate>)self launchOptions:launchOptions]; | ||
#else | ||
[self initializeReactNativeApp]; | ||
#endif | ||
#else | ||
EXUpdatesAppController *controller = [EXUpdatesAppController sharedInstance]; | ||
controller.delegate = self; | ||
[controller startAndShowLaunchScreen:self.window]; | ||
#endif | ||
[super application:application didFinishLaunchingWithOptions:launchOptions]; | ||
return YES; | ||
} | ||
- (RCTBridge *)initializeReactNativeApp | ||
{ | ||
#if defined(EX_DEV_LAUNCHER_ENABLED) | ||
NSDictionary *launchOptions = [EXDevLauncherController.sharedInstance getLaunchOptions]; | ||
#else | ||
NSDictionary *launchOptions = self.launchOptions; | ||
#endif | ||
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; | ||
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"main" initialProperties:nil]; | ||
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; | ||
UIViewController *rootViewController = [UIViewController new]; | ||
rootViewController.view = rootView; | ||
self.window.rootViewController = rootViewController; | ||
[self.window makeKeyAndVisible]; | ||
return bridge; | ||
} | ||
- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge | ||
{ | ||
NSArray<id<RCTBridgeModule>> *extraModules = [_moduleRegistryAdapter extraModulesForBridge:bridge]; | ||
// If you'd like to export some custom RCTBridgeModules that are not Expo modules, add them here! | ||
return extraModules; | ||
} | ||
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { | ||
#ifdef DEBUG | ||
#if defined(EX_DEV_LAUNCHER_ENABLED) | ||
return [[EXDevLauncherController sharedInstance] sourceUrl]; | ||
#else | ||
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; | ||
#endif | ||
#else | ||
return [[EXUpdatesAppController sharedInstance] launchAssetUrl]; | ||
#endif | ||
} | ||
- (void)appController:(EXUpdatesAppController *)appController didStartWithSuccess:(BOOL)success { | ||
appController.bridge = [self initializeReactNativeApp]; | ||
EXSplashScreenService *splashScreenService = (EXSplashScreenService *)[UMModuleRegistryProvider getSingletonModuleForClass:[EXSplashScreenService class]]; | ||
[splashScreenService showSplashScreenFor:self.window.rootViewController]; | ||
} | ||
// Linking API | ||
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options { | ||
#if defined(EX_DEV_LAUNCHER_ENABLED) | ||
if ([EXDevLauncherController.sharedInstance onDeepLink:url options:options]) { | ||
return true; | ||
} | ||
#endif | ||
return [RCTLinkingManager application:application openURL:url options:options]; | ||
} | ||
// Universal Links | ||
- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler { | ||
return [RCTLinkingManager application:application | ||
continueUserActivity:userActivity | ||
restorationHandler:restorationHandler]; | ||
} | ||
@end | ||
#if defined(EX_DEV_LAUNCHER_ENABLED) | ||
@implementation AppDelegate (EXDevLauncherControllerDelegate) | ||
- (void)devLauncherController:(EXDevLauncherController *)developmentClientController | ||
didStartWithSuccess:(BOOL)success | ||
{ | ||
developmentClientController.appBridge = [self initializeReactNativeApp]; | ||
EXSplashScreenService *splashScreenService = (EXSplashScreenService *)[UMModuleRegistryProvider getSingletonModuleForClass:[EXSplashScreenService class]]; | ||
[splashScreenService showSplashScreenFor:self.window.rootViewController]; | ||
} | ||
@end | ||
#endif | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.