diff --git a/playground/ios/playground.xcodeproj/project.pbxproj b/playground/ios/playground.xcodeproj/project.pbxproj index 3164dd12133..3348ebb64f5 100644 --- a/playground/ios/playground.xcodeproj/project.pbxproj +++ b/playground/ios/playground.xcodeproj/project.pbxproj @@ -10,6 +10,9 @@ 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; + 4AB1738927EBB9DC00B94349 /* MyRootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AB1738827EBB9DC00B94349 /* MyRootViewController.m */; }; + 4AB1738D27EBE57800B94349 /* ReactNativeNavigationWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AB1738C27EBE57800B94349 /* ReactNativeNavigationWindow.m */; }; + 4AB1739027EBEB5D00B94349 /* ReactNativeNavigation+BootstrapWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AB1738F27EBEB5D00B94349 /* ReactNativeNavigation+BootstrapWindow.m */; }; 5006E16627974DEA00D106A6 /* RNNModalHostViewManagerHandlerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5006E16527974DEA00D106A6 /* RNNModalHostViewManagerHandlerTest.m */; }; 5007B4312472CA390002AA4E /* RNNNativeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5007B4302472CA390002AA4E /* RNNNativeViewController.m */; }; 5007B4342472CBD40002AA4E /* RNNCustomViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5007B4322472CBD30002AA4E /* RNNCustomViewController.m */; }; @@ -116,6 +119,12 @@ 18EFC85255DC04E4B557855F /* libPods-NavigationTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-NavigationTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 33BE713009EFB937EA4BF877 /* libPods-playground.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-playground.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 4259AF43A23D928FE78B4A3A /* Pods-NavigationTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NavigationTests.debug.xcconfig"; path = "Target Support Files/Pods-NavigationTests/Pods-NavigationTests.debug.xcconfig"; sourceTree = ""; }; + 4AB1738727EBB9DC00B94349 /* MyRootViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyRootViewController.h; sourceTree = ""; }; + 4AB1738827EBB9DC00B94349 /* MyRootViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MyRootViewController.m; sourceTree = ""; }; + 4AB1738B27EBE57800B94349 /* ReactNativeNavigationWindow.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReactNativeNavigationWindow.h; sourceTree = ""; }; + 4AB1738C27EBE57800B94349 /* ReactNativeNavigationWindow.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ReactNativeNavigationWindow.m; sourceTree = ""; }; + 4AB1738E27EBEB5D00B94349 /* ReactNativeNavigation+BootstrapWindow.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ReactNativeNavigation+BootstrapWindow.h"; sourceTree = ""; }; + 4AB1738F27EBEB5D00B94349 /* ReactNativeNavigation+BootstrapWindow.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "ReactNativeNavigation+BootstrapWindow.m"; sourceTree = ""; }; 4AE37ACF6BFBAB211EE8E7E9 /* Pods-NavigationIOS12Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NavigationIOS12Tests.release.xcconfig"; path = "Target Support Files/Pods-NavigationIOS12Tests/Pods-NavigationIOS12Tests.release.xcconfig"; sourceTree = ""; }; 4C14E49C47AA48BEDE90A218 /* Pods-SnapshotTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SnapshotTests.debug.xcconfig"; path = "Target Support Files/Pods-SnapshotTests/Pods-SnapshotTests.debug.xcconfig"; sourceTree = ""; }; 5006E16527974DEA00D106A6 /* RNNModalHostViewManagerHandlerTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNModalHostViewManagerHandlerTest.m; sourceTree = ""; }; @@ -250,6 +259,12 @@ children = ( 13B07FAF1A68108700A75B9A /* AppDelegate.h */, 13B07FB01A68108700A75B9A /* AppDelegate.m */, + 4AB1738727EBB9DC00B94349 /* MyRootViewController.h */, + 4AB1738827EBB9DC00B94349 /* MyRootViewController.m */, + 4AB1738E27EBEB5D00B94349 /* ReactNativeNavigation+BootstrapWindow.h */, + 4AB1738F27EBEB5D00B94349 /* ReactNativeNavigation+BootstrapWindow.m */, + 4AB1738B27EBE57800B94349 /* ReactNativeNavigationWindow.h */, + 4AB1738C27EBE57800B94349 /* ReactNativeNavigationWindow.m */, 5007B42F2472CA390002AA4E /* RNNNativeViewController.h */, 5007B4302472CA390002AA4E /* RNNNativeViewController.m */, 5007B4332472CBD40002AA4E /* RNNCustomViewController.h */, @@ -361,7 +376,7 @@ indentWidth = 4; sourceTree = ""; tabWidth = 4; - usesTabs = 1; + usesTabs = 0; }; 83CBBA001A601CBA00E9B192 /* Products */ = { isa = PBXGroup; @@ -812,8 +827,11 @@ files = ( 5007B4312472CA390002AA4E /* RNNNativeViewController.m in Sources */, 5078DF39242BE8AA007B0B4F /* TestingAppDelegate.m in Sources */, + 4AB1738927EBB9DC00B94349 /* MyRootViewController.m in Sources */, + 4AB1739027EBEB5D00B94349 /* ReactNativeNavigation+BootstrapWindow.m in Sources */, 5007B4342472CBD40002AA4E /* RNNCustomViewController.m in Sources */, 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, + 4AB1738D27EBE57800B94349 /* ReactNativeNavigationWindow.m in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/playground/ios/playground/AppDelegate.m b/playground/ios/playground/AppDelegate.m index e105dad6efd..3a7565d82a5 100644 --- a/playground/ios/playground/AppDelegate.m +++ b/playground/ios/playground/AppDelegate.m @@ -6,6 +6,10 @@ #import "RNNCustomViewController.h" #import +#import "MyRootViewController.h" +#import "ReactNativeNavigation+BootstrapWindow.h" +#import "ReactNativeNavigationWindow.h" + @interface AppDelegate () @end @@ -20,10 +24,11 @@ - (BOOL)application:(UIApplication *)application } else { self.window.backgroundColor = [UIColor whiteColor]; } - [self.window makeKeyWindow]; + self.window.rootViewController = [[MyRootViewController alloc] init]; + [self.window makeKeyAndVisible]; RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; - [ReactNativeNavigation bootstrapWithBridge:bridge]; + // [ReactNativeNavigation bootstrapWithBridge:bridge]; [ReactNativeNavigation registerExternalComponent:@"RNNCustomComponent" callback:^UIViewController *(NSDictionary *props, RCTBridge *bridge) { @@ -45,6 +50,7 @@ - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { } - (NSArray> *)extraModulesForBridge:(RCTBridge *)bridge { + [ReactNativeNavigation bootstrapWithBridge:bridge window:[ReactNativeNavigationWindow shared]]; return [ReactNativeNavigation extraModulesForBridge:bridge]; } diff --git a/playground/ios/playground/MyRootViewController.h b/playground/ios/playground/MyRootViewController.h new file mode 100644 index 00000000000..7d5791824eb --- /dev/null +++ b/playground/ios/playground/MyRootViewController.h @@ -0,0 +1,4 @@ +#import + +@interface MyRootViewController : UIViewController +@end diff --git a/playground/ios/playground/MyRootViewController.m b/playground/ios/playground/MyRootViewController.m new file mode 100644 index 00000000000..a95e804efc2 --- /dev/null +++ b/playground/ios/playground/MyRootViewController.m @@ -0,0 +1,41 @@ +#import "MyRootViewController.h" +#import "ReactNativeNavigationWindow.h" + +@implementation MyRootViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + [self setup]; +} + +- (void)setup +{ + self.view.backgroundColor = UIColor.whiteColor; + + UIButton *windowButton = [[UIButton alloc] initWithFrame:CGRectMake(self.view.center.x - 100, 370, 200, 50)]; + windowButton.backgroundColor = UIColor.systemBlueColor; + [windowButton setTitle:@"Present Window" forState:UIControlStateNormal]; + [windowButton addTarget:self action:@selector(presentWindow) forControlEvents:UIControlEventTouchUpInside]; + [self.view addSubview:windowButton]; + + UIButton *vcButton = [[UIButton alloc] initWithFrame:CGRectMake(self.view.center.x - 130, 370 + 50 + 22, 260, 50)]; + vcButton.backgroundColor = UIColor.systemBlueColor; + [vcButton setTitle:@"Present View Controller" forState:UIControlStateNormal]; + [vcButton addTarget:self action:@selector(presentViewController) forControlEvents:UIControlEventTouchUpInside]; + [self.view addSubview:vcButton]; +} + +- (void)presentWindow +{ + [[ReactNativeNavigationWindow shared] presentAnimated:YES]; +} + +- (void)presentViewController +{ + UIViewController *viewController = [ReactNativeNavigationWindow shared].rootViewController; + viewController.modalPresentationStyle = UIModalPresentationFullScreen; + [self presentViewController:viewController animated:YES completion:nil]; +} + +@end diff --git a/playground/ios/playground/ReactNativeNavigation+BootstrapWindow.h b/playground/ios/playground/ReactNativeNavigation+BootstrapWindow.h new file mode 100644 index 00000000000..f15b37782c9 --- /dev/null +++ b/playground/ios/playground/ReactNativeNavigation+BootstrapWindow.h @@ -0,0 +1,12 @@ +// +// ReactNativeNavigation+BootstrapWindow.h +// +// Created by Jim Speth on 3/23/22. +// + +#import +#import + +@interface ReactNativeNavigation (BootstrapWindow) ++ (void)bootstrapWithBridge:(RCTBridge *)bridge window:(UIWindow *)window; +@end diff --git a/playground/ios/playground/ReactNativeNavigation+BootstrapWindow.m b/playground/ios/playground/ReactNativeNavigation+BootstrapWindow.m new file mode 100644 index 00000000000..7b942a790ae --- /dev/null +++ b/playground/ios/playground/ReactNativeNavigation+BootstrapWindow.m @@ -0,0 +1,23 @@ +// +// ReactNativeNavigation+BootstrapWindow.m +// +// Created by Jim Speth on 3/23/22. +// + +#import "ReactNativeNavigation+BootstrapWindow.h" +#import + +@interface ReactNativeNavigation (ReactNativeNavigationSecrets) ++ (instancetype)sharedInstance; +@property(nonatomic, strong) RNNBridgeManager *bridgeManager; +@end + +@implementation ReactNativeNavigation (BootstrapWindow) + ++ (void)bootstrapWithBridge:(RCTBridge *)bridge window:(UIWindow *)window +{ + ReactNativeNavigation *navigation = [ReactNativeNavigation sharedInstance]; + navigation.bridgeManager = [[RNNBridgeManager alloc] initWithBridge:bridge mainWindow:window]; +} + +@end diff --git a/playground/ios/playground/ReactNativeNavigationWindow.h b/playground/ios/playground/ReactNativeNavigationWindow.h new file mode 100644 index 00000000000..b12282b2465 --- /dev/null +++ b/playground/ios/playground/ReactNativeNavigationWindow.h @@ -0,0 +1,16 @@ +// +// ReactNativeNavigationWindow.h +// +// Created by Jim Speth on 3/23/22. +// + +#import + +@interface ReactNativeNavigationWindow : UIWindow + ++ (instancetype)shared; + +- (void)presentAnimated:(BOOL)animated; +- (void)dismissAnimated:(BOOL)animated; + +@end diff --git a/playground/ios/playground/ReactNativeNavigationWindow.m b/playground/ios/playground/ReactNativeNavigationWindow.m new file mode 100644 index 00000000000..124e249e85c --- /dev/null +++ b/playground/ios/playground/ReactNativeNavigationWindow.m @@ -0,0 +1,59 @@ +// +// ReactNativeNavigationWindow.m +// +// Created by Jim Speth on 3/23/22. +// + +#import "ReactNativeNavigationWindow.h" + +@interface ReactNativeNavigationWindow () +@property (nonatomic, strong) UIWindow *lastWindow; +@end + +@implementation ReactNativeNavigationWindow + +static NSTimeInterval animationDuration = 0.3; + ++ (instancetype)shared +{ + static ReactNativeNavigationWindow *instance = nil; + static dispatch_once_t onceToken = 0; + dispatch_once(&onceToken, ^{ + if (!instance) { + instance = [[ReactNativeNavigationWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; + } + }); + return instance; +} + +- (void)setRootViewController:(UIViewController *)rootViewController +{ + NSLog(@"ReactNativeNavigationWindow: setRootViewController: %@", rootViewController); + [super setRootViewController:rootViewController]; +} + +- (void)presentAnimated:(BOOL)animated +{ + self.lastWindow = [UIApplication sharedApplication].keyWindow; + + self.alpha = 0.0; + [self makeKeyAndVisible]; + [UIApplication sharedApplication].delegate.window = self; + + [UIView animateWithDuration:animated ? animationDuration : 0.0 animations:^{ + self.alpha = 1.0; + } completion:nil]; +} + +- (void)dismissAnimated:(BOOL)animated +{ + [UIView animateWithDuration:animated ? animationDuration : 0.0 animations:^{ + self.alpha = 0.0; + } completion:^(BOOL finished) { + [self.lastWindow makeKeyAndVisible]; + [UIApplication sharedApplication].delegate.window = self.lastWindow; + self.lastWindow = nil; + }]; +} + +@end