[RFC][ReactNative] Integrate dev menu directly into RootView
This commit is contained in:
parent
7ffa7942aa
commit
c5a6b44c76
|
@ -9,7 +9,6 @@
|
||||||
|
|
||||||
#import "AppDelegate.h"
|
#import "AppDelegate.h"
|
||||||
|
|
||||||
#import "RCTDevelopmentViewController.h"
|
|
||||||
#import "RCTRootView.h"
|
#import "RCTRootView.h"
|
||||||
|
|
||||||
@implementation AppDelegate
|
@implementation AppDelegate
|
||||||
|
@ -42,7 +41,7 @@
|
||||||
rootView.moduleName = @"UIExplorerApp";
|
rootView.moduleName = @"UIExplorerApp";
|
||||||
|
|
||||||
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
||||||
UIViewController *rootViewController = [[RCTDevelopmentViewController alloc] init];
|
UIViewController *rootViewController = [[UIViewController alloc] init];
|
||||||
rootViewController.view = rootView;
|
rootViewController.view = rootView;
|
||||||
self.window.rootViewController = rootViewController;
|
self.window.rootViewController = rootViewController;
|
||||||
[self.window makeKeyAndVisible];
|
[self.window makeKeyAndVisible];
|
||||||
|
|
|
@ -9,6 +9,11 @@
|
||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
@interface RCTDevelopmentViewController : UIViewController
|
@class RCTRootView;
|
||||||
|
|
||||||
|
@interface RCTDevMenu : NSObject
|
||||||
|
|
||||||
|
- (instancetype)initWithRootView:(RCTRootView *)rootView;
|
||||||
|
- (void)show;
|
||||||
|
|
||||||
@end
|
@end
|
|
@ -0,0 +1,84 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2015-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "RCTDevMenu.h"
|
||||||
|
|
||||||
|
#import "RCTRedBox.h"
|
||||||
|
#import "RCTRootView.h"
|
||||||
|
|
||||||
|
@interface RCTDevMenu () <UIActionSheetDelegate> {
|
||||||
|
BOOL _liveReload;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property (nonatomic, weak) RCTRootView *view;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation RCTDevMenu
|
||||||
|
|
||||||
|
- (instancetype)initWithRootView:(RCTRootView *)rootView
|
||||||
|
{
|
||||||
|
if (self = [super init]) {
|
||||||
|
self.view = rootView;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)show
|
||||||
|
{
|
||||||
|
NSString *debugTitle = self.view.executorClass == nil ? @"Enable Debugging" : @"Disable Debugging";
|
||||||
|
NSString *liveReloadTitle = _liveReload ? @"Disable Live Reload" : @"Enable Live Reload";
|
||||||
|
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"React Native: Development"
|
||||||
|
delegate:self
|
||||||
|
cancelButtonTitle:@"Cancel"
|
||||||
|
destructiveButtonTitle:nil
|
||||||
|
otherButtonTitles:@"Reload", debugTitle, liveReloadTitle, nil];
|
||||||
|
actionSheet.actionSheetStyle = UIBarStyleBlack;
|
||||||
|
[actionSheet showInView:self.view];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
|
||||||
|
{
|
||||||
|
if (buttonIndex == 0) {
|
||||||
|
[self.view reload];
|
||||||
|
} else if (buttonIndex == 1) {
|
||||||
|
self.view.executorClass = self.view.executorClass == nil ? NSClassFromString(@"RCTWebSocketExecutor") : nil;
|
||||||
|
[self.view reload];
|
||||||
|
} else if (buttonIndex == 2) {
|
||||||
|
_liveReload = !_liveReload;
|
||||||
|
[self _pollAndReload];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)_pollAndReload
|
||||||
|
{
|
||||||
|
if (_liveReload) {
|
||||||
|
NSURL *url = [self.view scriptURL];
|
||||||
|
NSURL *longPollURL = [[NSURL alloc] initWithString:@"/onchange" relativeToURL:url];
|
||||||
|
[self performSelectorInBackground:@selector(_checkForUpdates:) withObject:longPollURL];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)_checkForUpdates:(NSURL *)URL
|
||||||
|
{
|
||||||
|
NSMutableURLRequest *longPollRequest = [NSMutableURLRequest requestWithURL:URL];
|
||||||
|
longPollRequest.timeoutInterval = 30;
|
||||||
|
NSHTTPURLResponse *response;
|
||||||
|
[NSURLConnection sendSynchronousRequest:longPollRequest returningResponse:&response error:nil];
|
||||||
|
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
if (_liveReload && response.statusCode == 205) {
|
||||||
|
[[RCTRedBox sharedInstance] dismiss];
|
||||||
|
[self.view reload];
|
||||||
|
}
|
||||||
|
[self _pollAndReload];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
|
@ -1,89 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (c) 2015-present, Facebook, Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the BSD-style license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree. An additional grant
|
|
||||||
* of patent rights can be found in the PATENTS file in the same directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#import "RCTDevelopmentViewController.h"
|
|
||||||
|
|
||||||
#import "RCTRedBox.h"
|
|
||||||
#import "RCTRootView.h"
|
|
||||||
|
|
||||||
@interface RCTDevelopmentViewController () <UIActionSheetDelegate> {
|
|
||||||
BOOL _liveReload;
|
|
||||||
}
|
|
||||||
|
|
||||||
@property (nonatomic, readonly) RCTRootView *RCTView;
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation RCTDevelopmentViewController
|
|
||||||
|
|
||||||
- (BOOL)canBecomeFirstResponder
|
|
||||||
{
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (RCTRootView *)RCTView
|
|
||||||
{
|
|
||||||
return (RCTRootView *)self.view;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
|
|
||||||
{
|
|
||||||
if (motion == UIEventSubtypeMotionShake)
|
|
||||||
{
|
|
||||||
NSString *debugTitle = self.RCTView.executorClass == nil ? @"Enable Debugging" : @"Disable Debugging";
|
|
||||||
NSString *liveReloadTitle = _liveReload ? @"Disable Live Reload" : @"Enable Live Reload";
|
|
||||||
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"React Native: Development"
|
|
||||||
delegate:self
|
|
||||||
cancelButtonTitle:@"Cancel"
|
|
||||||
destructiveButtonTitle:nil
|
|
||||||
otherButtonTitles:@"Reload", debugTitle, liveReloadTitle, nil];
|
|
||||||
actionSheet.actionSheetStyle = UIBarStyleBlack;
|
|
||||||
[actionSheet showInView:self.view];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
|
|
||||||
{
|
|
||||||
if (buttonIndex == 0) {
|
|
||||||
[self.RCTView reload];
|
|
||||||
} else if (buttonIndex == 1) {
|
|
||||||
self.RCTView.executorClass = self.RCTView.executorClass == nil ? NSClassFromString(@"RCTWebSocketExecutor") : nil;
|
|
||||||
[self.RCTView reload];
|
|
||||||
} else if (buttonIndex == 2) {
|
|
||||||
_liveReload = !_liveReload;
|
|
||||||
[self _pollAndReload];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)_pollAndReload
|
|
||||||
{
|
|
||||||
if (_liveReload) {
|
|
||||||
NSURL *url = [self.RCTView scriptURL];
|
|
||||||
NSURL *longPollURL = [[NSURL alloc] initWithString:@"/onchange" relativeToURL:url];
|
|
||||||
[self performSelectorInBackground:@selector(_checkForUpdates:) withObject:longPollURL];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)_checkForUpdates:(NSURL *)URL
|
|
||||||
{
|
|
||||||
NSMutableURLRequest *longPollRequest = [NSMutableURLRequest requestWithURL:URL];
|
|
||||||
longPollRequest.timeoutInterval = 30;
|
|
||||||
NSHTTPURLResponse *response;
|
|
||||||
[NSURLConnection sendSynchronousRequest:longPollRequest returningResponse:&response error:nil];
|
|
||||||
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
|
||||||
if (_liveReload && response.statusCode == 205) {
|
|
||||||
[[RCTRedBox sharedInstance] dismiss];
|
|
||||||
[self.RCTView reload];
|
|
||||||
}
|
|
||||||
[self _pollAndReload];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
|
@ -48,6 +48,12 @@
|
||||||
*/
|
*/
|
||||||
@property (nonatomic, strong) Class executorClass;
|
@property (nonatomic, strong) Class executorClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If YES will watch for shake gestures and show development menu
|
||||||
|
* with options like "Reload", "Enable Debugging", etc.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) BOOL enableDevMenu;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reload this root view, or all root views, respectively.
|
* Reload this root view, or all root views, respectively.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#import "RCTBridge.h"
|
#import "RCTBridge.h"
|
||||||
#import "RCTContextExecutor.h"
|
#import "RCTContextExecutor.h"
|
||||||
|
#import "RCTDevMenu.h"
|
||||||
#import "RCTEventDispatcher.h"
|
#import "RCTEventDispatcher.h"
|
||||||
#import "RCTKeyCommands.h"
|
#import "RCTKeyCommands.h"
|
||||||
#import "RCTLog.h"
|
#import "RCTLog.h"
|
||||||
|
@ -26,6 +27,7 @@ NSString *const RCTReloadNotification = @"RCTReloadNotification";
|
||||||
|
|
||||||
@implementation RCTRootView
|
@implementation RCTRootView
|
||||||
{
|
{
|
||||||
|
RCTDevMenu *_devMenu;
|
||||||
RCTBridge *_bridge;
|
RCTBridge *_bridge;
|
||||||
RCTTouchHandler *_touchHandler;
|
RCTTouchHandler *_touchHandler;
|
||||||
id<RCTJavaScriptExecutor> _executor;
|
id<RCTJavaScriptExecutor> _executor;
|
||||||
|
@ -84,6 +86,9 @@ static Class _globalExecutorClass;
|
||||||
// Numbering of these tags goes from 1, 11, 21, 31, etc
|
// Numbering of these tags goes from 1, 11, 21, 31, etc
|
||||||
static NSInteger rootViewTag = 1;
|
static NSInteger rootViewTag = 1;
|
||||||
self.reactTag = @(rootViewTag);
|
self.reactTag = @(rootViewTag);
|
||||||
|
#ifdef DEBUG
|
||||||
|
self.enableDevMenu = YES;
|
||||||
|
#endif
|
||||||
rootViewTag += 10;
|
rootViewTag += 10;
|
||||||
|
|
||||||
// Add reload observer
|
// Add reload observer
|
||||||
|
@ -93,6 +98,21 @@ static Class _globalExecutorClass;
|
||||||
object:nil];
|
object:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)canBecomeFirstResponder
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
|
||||||
|
{
|
||||||
|
if (motion == UIEventSubtypeMotionShake && self.enableDevMenu) {
|
||||||
|
if (!_devMenu) {
|
||||||
|
_devMenu = [[RCTDevMenu alloc] initWithRootView:self];
|
||||||
|
}
|
||||||
|
[_devMenu show];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+ (NSArray *)JSMethods
|
+ (NSArray *)JSMethods
|
||||||
{
|
{
|
||||||
return @[
|
return @[
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
000E6CEB1AB0E980000CDF4D /* RCTSourceCode.m in Sources */ = {isa = PBXBuildFile; fileRef = 000E6CEA1AB0E980000CDF4D /* RCTSourceCode.m */; };
|
000E6CEB1AB0E980000CDF4D /* RCTSourceCode.m in Sources */ = {isa = PBXBuildFile; fileRef = 000E6CEA1AB0E980000CDF4D /* RCTSourceCode.m */; };
|
||||||
00C1A2B31AC0B7E000E89A1C /* RCTDevelopmentViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 00C1A2B21AC0B7E000E89A1C /* RCTDevelopmentViewController.m */; };
|
00C1A2B31AC0B7E000E89A1C /* RCTDevMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 00C1A2B21AC0B7E000E89A1C /* RCTDevMenu.m */; };
|
||||||
134FCB361A6D42D900051CC8 /* RCTSparseArray.m in Sources */ = {isa = PBXBuildFile; fileRef = 83BEE46D1A6D19BC00B5863B /* RCTSparseArray.m */; };
|
134FCB361A6D42D900051CC8 /* RCTSparseArray.m in Sources */ = {isa = PBXBuildFile; fileRef = 83BEE46D1A6D19BC00B5863B /* RCTSparseArray.m */; };
|
||||||
134FCB3D1A6E7F0800051CC8 /* RCTContextExecutor.m in Sources */ = {isa = PBXBuildFile; fileRef = 134FCB3A1A6E7F0800051CC8 /* RCTContextExecutor.m */; };
|
134FCB3D1A6E7F0800051CC8 /* RCTContextExecutor.m in Sources */ = {isa = PBXBuildFile; fileRef = 134FCB3A1A6E7F0800051CC8 /* RCTContextExecutor.m */; };
|
||||||
134FCB3E1A6E7F0800051CC8 /* RCTWebViewExecutor.m in Sources */ = {isa = PBXBuildFile; fileRef = 134FCB3C1A6E7F0800051CC8 /* RCTWebViewExecutor.m */; };
|
134FCB3E1A6E7F0800051CC8 /* RCTWebViewExecutor.m in Sources */ = {isa = PBXBuildFile; fileRef = 134FCB3C1A6E7F0800051CC8 /* RCTWebViewExecutor.m */; };
|
||||||
|
@ -77,8 +77,8 @@
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
000E6CE91AB0E97F000CDF4D /* RCTSourceCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSourceCode.h; sourceTree = "<group>"; };
|
000E6CE91AB0E97F000CDF4D /* RCTSourceCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSourceCode.h; sourceTree = "<group>"; };
|
||||||
000E6CEA1AB0E980000CDF4D /* RCTSourceCode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSourceCode.m; sourceTree = "<group>"; };
|
000E6CEA1AB0E980000CDF4D /* RCTSourceCode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSourceCode.m; sourceTree = "<group>"; };
|
||||||
00C1A2B11AC0B7E000E89A1C /* RCTDevelopmentViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTDevelopmentViewController.h; sourceTree = "<group>"; };
|
00C1A2B11AC0B7E000E89A1C /* RCTDevMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTDevMenu.h; sourceTree = "<group>"; };
|
||||||
00C1A2B21AC0B7E000E89A1C /* RCTDevelopmentViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTDevelopmentViewController.m; sourceTree = "<group>"; };
|
00C1A2B21AC0B7E000E89A1C /* RCTDevMenu.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTDevMenu.m; sourceTree = "<group>"; };
|
||||||
13442BF21AA90E0B0037E5B0 /* RCTAnimationType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAnimationType.h; sourceTree = "<group>"; };
|
13442BF21AA90E0B0037E5B0 /* RCTAnimationType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAnimationType.h; sourceTree = "<group>"; };
|
||||||
13442BF31AA90E0B0037E5B0 /* RCTPointerEvents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPointerEvents.h; sourceTree = "<group>"; };
|
13442BF31AA90E0B0037E5B0 /* RCTPointerEvents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPointerEvents.h; sourceTree = "<group>"; };
|
||||||
13442BF41AA90E0B0037E5B0 /* RCTViewControllerProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTViewControllerProtocol.h; sourceTree = "<group>"; };
|
13442BF41AA90E0B0037E5B0 /* RCTViewControllerProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTViewControllerProtocol.h; sourceTree = "<group>"; };
|
||||||
|
@ -368,8 +368,8 @@
|
||||||
83CBBA591A601E9000E9B192 /* RCTRedBox.m */,
|
83CBBA591A601E9000E9B192 /* RCTRedBox.m */,
|
||||||
830A229C1A66C68A008503DA /* RCTRootView.h */,
|
830A229C1A66C68A008503DA /* RCTRootView.h */,
|
||||||
830A229D1A66C68A008503DA /* RCTRootView.m */,
|
830A229D1A66C68A008503DA /* RCTRootView.m */,
|
||||||
00C1A2B11AC0B7E000E89A1C /* RCTDevelopmentViewController.h */,
|
00C1A2B11AC0B7E000E89A1C /* RCTDevMenu.h */,
|
||||||
00C1A2B21AC0B7E000E89A1C /* RCTDevelopmentViewController.m */,
|
00C1A2B21AC0B7E000E89A1C /* RCTDevMenu.m */,
|
||||||
83BEE46C1A6D19BC00B5863B /* RCTSparseArray.h */,
|
83BEE46C1A6D19BC00B5863B /* RCTSparseArray.h */,
|
||||||
83BEE46D1A6D19BC00B5863B /* RCTSparseArray.m */,
|
83BEE46D1A6D19BC00B5863B /* RCTSparseArray.m */,
|
||||||
83CBBA961A6020BB00E9B192 /* RCTTouchHandler.h */,
|
83CBBA961A6020BB00E9B192 /* RCTTouchHandler.h */,
|
||||||
|
@ -499,7 +499,7 @@
|
||||||
13B0801A1A69489C00A75B9A /* RCTNavigator.m in Sources */,
|
13B0801A1A69489C00A75B9A /* RCTNavigator.m in Sources */,
|
||||||
830BA4551A8E3BDA00D53203 /* RCTCache.m in Sources */,
|
830BA4551A8E3BDA00D53203 /* RCTCache.m in Sources */,
|
||||||
137327E71AA5CF210034F82E /* RCTTabBar.m in Sources */,
|
137327E71AA5CF210034F82E /* RCTTabBar.m in Sources */,
|
||||||
00C1A2B31AC0B7E000E89A1C /* RCTDevelopmentViewController.m in Sources */,
|
00C1A2B31AC0B7E000E89A1C /* RCTDevMenu.m in Sources */,
|
||||||
14435CE51AAC4AE100FC20F4 /* RCTMap.m in Sources */,
|
14435CE51AAC4AE100FC20F4 /* RCTMap.m in Sources */,
|
||||||
134FCB3E1A6E7F0800051CC8 /* RCTWebViewExecutor.m in Sources */,
|
134FCB3E1A6E7F0800051CC8 /* RCTWebViewExecutor.m in Sources */,
|
||||||
13B0801C1A69489C00A75B9A /* RCTNavItem.m in Sources */,
|
13B0801C1A69489C00A75B9A /* RCTNavItem.m in Sources */,
|
||||||
|
|
Loading…
Reference in New Issue