Add RCTDevSettings module
Summary:
This decouples non-UI logic from RCTDevMenu into a new module RCTDevSettings.
**Motivation**: This allows developers to change dev settings without depending on the built-in dev menu, e.g. if they want to introduce their own UI, or have other devtools logic that doesn't depend on an action sheet.
It also introduces the RCTDevSettingsDataSource protocol for storing dev tools preferences. This could allow a developer to implement alternative behaviors, e.g. loading the settings from some other config, changing settings based on the user, deciding not to persist some settings, or something else.
The included data source implementation, RCTDevSettingsUserDefaultsDataSource, uses NSUserDefaults and is backwards compatible with the older implementation, so **no workflows or dependent code will break, and old saved settings will persist.**
The RCTDevMenu interface has not changed and is therefore also backwards-compatible, though
some methods are now deprecated.
In order to ensure that RCTDevSettings
Closes https://github.com/facebook/react-native/pull/11613
Reviewed By: mmmulani
Differential Revision: D4571773
Pulled By: javache
fbshipit-source-id: 25555d0a6eaa81f694343e079ed02439e5845fbc
2017-02-24 14:50:29 +00:00
|
|
|
/**
|
|
|
|
* 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"
|
|
|
|
|
2017-09-05 21:47:06 +00:00
|
|
|
#import "RCTBridge+Private.h"
|
Add RCTDevSettings module
Summary:
This decouples non-UI logic from RCTDevMenu into a new module RCTDevSettings.
**Motivation**: This allows developers to change dev settings without depending on the built-in dev menu, e.g. if they want to introduce their own UI, or have other devtools logic that doesn't depend on an action sheet.
It also introduces the RCTDevSettingsDataSource protocol for storing dev tools preferences. This could allow a developer to implement alternative behaviors, e.g. loading the settings from some other config, changing settings based on the user, deciding not to persist some settings, or something else.
The included data source implementation, RCTDevSettingsUserDefaultsDataSource, uses NSUserDefaults and is backwards compatible with the older implementation, so **no workflows or dependent code will break, and old saved settings will persist.**
The RCTDevMenu interface has not changed and is therefore also backwards-compatible, though
some methods are now deprecated.
In order to ensure that RCTDevSettings
Closes https://github.com/facebook/react-native/pull/11613
Reviewed By: mmmulani
Differential Revision: D4571773
Pulled By: javache
fbshipit-source-id: 25555d0a6eaa81f694343e079ed02439e5845fbc
2017-02-24 14:50:29 +00:00
|
|
|
#import "RCTDevSettings.h"
|
|
|
|
#import "RCTKeyCommands.h"
|
|
|
|
#import "RCTLog.h"
|
|
|
|
#import "RCTUtils.h"
|
|
|
|
|
|
|
|
#if RCT_DEV
|
|
|
|
|
2017-07-31 10:53:09 +00:00
|
|
|
NSString *const RCTShowDevMenuNotification = @"RCTShowDevMenuNotification";
|
Add RCTDevSettings module
Summary:
This decouples non-UI logic from RCTDevMenu into a new module RCTDevSettings.
**Motivation**: This allows developers to change dev settings without depending on the built-in dev menu, e.g. if they want to introduce their own UI, or have other devtools logic that doesn't depend on an action sheet.
It also introduces the RCTDevSettingsDataSource protocol for storing dev tools preferences. This could allow a developer to implement alternative behaviors, e.g. loading the settings from some other config, changing settings based on the user, deciding not to persist some settings, or something else.
The included data source implementation, RCTDevSettingsUserDefaultsDataSource, uses NSUserDefaults and is backwards compatible with the older implementation, so **no workflows or dependent code will break, and old saved settings will persist.**
The RCTDevMenu interface has not changed and is therefore also backwards-compatible, though
some methods are now deprecated.
In order to ensure that RCTDevSettings
Closes https://github.com/facebook/react-native/pull/11613
Reviewed By: mmmulani
Differential Revision: D4571773
Pulled By: javache
fbshipit-source-id: 25555d0a6eaa81f694343e079ed02439e5845fbc
2017-02-24 14:50:29 +00:00
|
|
|
|
|
|
|
@implementation UIWindow (RCTDevMenu)
|
|
|
|
|
|
|
|
- (void)RCT_motionEnded:(__unused UIEventSubtype)motion withEvent:(UIEvent *)event
|
|
|
|
{
|
|
|
|
if (event.subtype == UIEventSubtypeMotionShake) {
|
|
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:RCTShowDevMenuNotification object:nil];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation RCTDevMenuItem
|
|
|
|
{
|
|
|
|
RCTDevMenuItemTitleBlock _titleBlock;
|
|
|
|
dispatch_block_t _handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (instancetype)initWithTitleBlock:(RCTDevMenuItemTitleBlock)titleBlock
|
|
|
|
handler:(dispatch_block_t)handler
|
|
|
|
{
|
|
|
|
if ((self = [super init])) {
|
|
|
|
_titleBlock = [titleBlock copy];
|
|
|
|
_handler = [handler copy];
|
|
|
|
}
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
|
|
|
|
|
|
|
+ (instancetype)buttonItemWithTitleBlock:(NSString *(^)(void))titleBlock handler:(dispatch_block_t)handler
|
|
|
|
{
|
|
|
|
return [[self alloc] initWithTitleBlock:titleBlock handler:handler];
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (instancetype)buttonItemWithTitle:(NSString *)title
|
|
|
|
handler:(dispatch_block_t)handler
|
|
|
|
{
|
|
|
|
return [[self alloc] initWithTitleBlock:^NSString *{ return title; } handler:handler];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)callHandler
|
|
|
|
{
|
|
|
|
if (_handler) {
|
|
|
|
_handler();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *)title
|
|
|
|
{
|
|
|
|
if (_titleBlock) {
|
|
|
|
return _titleBlock();
|
|
|
|
}
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
typedef void(^RCTDevMenuAlertActionHandler)(UIAlertAction *action);
|
|
|
|
|
|
|
|
@interface RCTDevMenu () <RCTBridgeModule, RCTInvalidating>
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation RCTDevMenu
|
|
|
|
{
|
|
|
|
UIAlertController *_actionSheet;
|
|
|
|
NSMutableArray<RCTDevMenuItem *> *_extraMenuItems;
|
|
|
|
}
|
|
|
|
|
|
|
|
@synthesize bridge = _bridge;
|
|
|
|
|
|
|
|
RCT_EXPORT_MODULE()
|
|
|
|
|
|
|
|
+ (void)initialize
|
|
|
|
{
|
|
|
|
// We're swizzling here because it's poor form to override methods in a category,
|
|
|
|
// however UIWindow doesn't actually implement motionEnded:withEvent:, so there's
|
|
|
|
// no need to call the original implementation.
|
|
|
|
RCTSwapInstanceMethods([UIWindow class], @selector(motionEnded:withEvent:), @selector(RCT_motionEnded:withEvent:));
|
|
|
|
}
|
|
|
|
|
2017-08-07 13:45:24 +00:00
|
|
|
+ (BOOL)requiresMainQueueSetup
|
|
|
|
{
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
Add RCTDevSettings module
Summary:
This decouples non-UI logic from RCTDevMenu into a new module RCTDevSettings.
**Motivation**: This allows developers to change dev settings without depending on the built-in dev menu, e.g. if they want to introduce their own UI, or have other devtools logic that doesn't depend on an action sheet.
It also introduces the RCTDevSettingsDataSource protocol for storing dev tools preferences. This could allow a developer to implement alternative behaviors, e.g. loading the settings from some other config, changing settings based on the user, deciding not to persist some settings, or something else.
The included data source implementation, RCTDevSettingsUserDefaultsDataSource, uses NSUserDefaults and is backwards compatible with the older implementation, so **no workflows or dependent code will break, and old saved settings will persist.**
The RCTDevMenu interface has not changed and is therefore also backwards-compatible, though
some methods are now deprecated.
In order to ensure that RCTDevSettings
Closes https://github.com/facebook/react-native/pull/11613
Reviewed By: mmmulani
Differential Revision: D4571773
Pulled By: javache
fbshipit-source-id: 25555d0a6eaa81f694343e079ed02439e5845fbc
2017-02-24 14:50:29 +00:00
|
|
|
- (instancetype)init
|
|
|
|
{
|
|
|
|
if ((self = [super init])) {
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
|
|
selector:@selector(showOnShake)
|
|
|
|
name:RCTShowDevMenuNotification
|
|
|
|
object:nil];
|
|
|
|
_extraMenuItems = [NSMutableArray new];
|
|
|
|
|
2017-04-19 22:15:53 +00:00
|
|
|
#if TARGET_OS_SIMULATOR
|
Add RCTDevSettings module
Summary:
This decouples non-UI logic from RCTDevMenu into a new module RCTDevSettings.
**Motivation**: This allows developers to change dev settings without depending on the built-in dev menu, e.g. if they want to introduce their own UI, or have other devtools logic that doesn't depend on an action sheet.
It also introduces the RCTDevSettingsDataSource protocol for storing dev tools preferences. This could allow a developer to implement alternative behaviors, e.g. loading the settings from some other config, changing settings based on the user, deciding not to persist some settings, or something else.
The included data source implementation, RCTDevSettingsUserDefaultsDataSource, uses NSUserDefaults and is backwards compatible with the older implementation, so **no workflows or dependent code will break, and old saved settings will persist.**
The RCTDevMenu interface has not changed and is therefore also backwards-compatible, though
some methods are now deprecated.
In order to ensure that RCTDevSettings
Closes https://github.com/facebook/react-native/pull/11613
Reviewed By: mmmulani
Differential Revision: D4571773
Pulled By: javache
fbshipit-source-id: 25555d0a6eaa81f694343e079ed02439e5845fbc
2017-02-24 14:50:29 +00:00
|
|
|
RCTKeyCommands *commands = [RCTKeyCommands sharedInstance];
|
|
|
|
__weak __typeof(self) weakSelf = self;
|
|
|
|
|
|
|
|
// Toggle debug menu
|
|
|
|
[commands registerKeyCommandWithInput:@"d"
|
|
|
|
modifierFlags:UIKeyModifierCommand
|
|
|
|
action:^(__unused UIKeyCommand *command) {
|
|
|
|
[weakSelf toggle];
|
|
|
|
}];
|
|
|
|
|
|
|
|
// Toggle element inspector
|
|
|
|
[commands registerKeyCommandWithInput:@"i"
|
|
|
|
modifierFlags:UIKeyModifierCommand
|
|
|
|
action:^(__unused UIKeyCommand *command) {
|
|
|
|
[weakSelf.bridge.devSettings toggleElementInspector];
|
|
|
|
}];
|
|
|
|
|
|
|
|
// Reload in normal mode
|
|
|
|
[commands registerKeyCommandWithInput:@"n"
|
|
|
|
modifierFlags:UIKeyModifierCommand
|
|
|
|
action:^(__unused UIKeyCommand *command) {
|
|
|
|
[weakSelf.bridge.devSettings setIsDebuggingRemotely:NO];
|
|
|
|
}];
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (dispatch_queue_t)methodQueue
|
|
|
|
{
|
|
|
|
return dispatch_get_main_queue();
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)invalidate
|
|
|
|
{
|
|
|
|
_presentedItems = nil;
|
|
|
|
[_actionSheet dismissViewControllerAnimated:YES completion:^(void){}];
|
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)showOnShake
|
|
|
|
{
|
|
|
|
if ([_bridge.devSettings isShakeToShowDevMenuEnabled]) {
|
|
|
|
[self show];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)toggle
|
|
|
|
{
|
|
|
|
if (_actionSheet) {
|
|
|
|
[_actionSheet dismissViewControllerAnimated:YES completion:^(void){}];
|
|
|
|
_actionSheet = nil;
|
|
|
|
} else {
|
|
|
|
[self show];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)isActionSheetShown
|
|
|
|
{
|
|
|
|
return _actionSheet != nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)addItem:(NSString *)title handler:(void(^)(void))handler
|
|
|
|
{
|
|
|
|
[self addItem:[RCTDevMenuItem buttonItemWithTitle:title handler:handler]];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)addItem:(RCTDevMenuItem *)item
|
|
|
|
{
|
|
|
|
[_extraMenuItems addObject:item];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSArray<RCTDevMenuItem *> *)_menuItemsToPresent
|
|
|
|
{
|
|
|
|
NSMutableArray<RCTDevMenuItem *> *items = [NSMutableArray new];
|
|
|
|
|
|
|
|
// Add built-in items
|
|
|
|
__weak RCTBridge *bridge = _bridge;
|
|
|
|
__weak RCTDevSettings *devSettings = _bridge.devSettings;
|
|
|
|
|
|
|
|
[items addObject:[RCTDevMenuItem buttonItemWithTitle:@"Reload" handler:^{
|
|
|
|
[bridge reload];
|
|
|
|
}]];
|
|
|
|
|
|
|
|
if (!devSettings.isRemoteDebuggingAvailable) {
|
2017-03-22 12:27:58 +00:00
|
|
|
[items addObject:[RCTDevMenuItem buttonItemWithTitle:@"Remote JS Debugger Unavailable" handler:^{
|
Add RCTDevSettings module
Summary:
This decouples non-UI logic from RCTDevMenu into a new module RCTDevSettings.
**Motivation**: This allows developers to change dev settings without depending on the built-in dev menu, e.g. if they want to introduce their own UI, or have other devtools logic that doesn't depend on an action sheet.
It also introduces the RCTDevSettingsDataSource protocol for storing dev tools preferences. This could allow a developer to implement alternative behaviors, e.g. loading the settings from some other config, changing settings based on the user, deciding not to persist some settings, or something else.
The included data source implementation, RCTDevSettingsUserDefaultsDataSource, uses NSUserDefaults and is backwards compatible with the older implementation, so **no workflows or dependent code will break, and old saved settings will persist.**
The RCTDevMenu interface has not changed and is therefore also backwards-compatible, though
some methods are now deprecated.
In order to ensure that RCTDevSettings
Closes https://github.com/facebook/react-native/pull/11613
Reviewed By: mmmulani
Differential Revision: D4571773
Pulled By: javache
fbshipit-source-id: 25555d0a6eaa81f694343e079ed02439e5845fbc
2017-02-24 14:50:29 +00:00
|
|
|
UIAlertController *alertController = [UIAlertController
|
2017-03-22 12:27:58 +00:00
|
|
|
alertControllerWithTitle:@"Remote JS Debugger Unavailable"
|
|
|
|
message:@"You need to include the RCTWebSocket library to enable remote JS debugging"
|
Add RCTDevSettings module
Summary:
This decouples non-UI logic from RCTDevMenu into a new module RCTDevSettings.
**Motivation**: This allows developers to change dev settings without depending on the built-in dev menu, e.g. if they want to introduce their own UI, or have other devtools logic that doesn't depend on an action sheet.
It also introduces the RCTDevSettingsDataSource protocol for storing dev tools preferences. This could allow a developer to implement alternative behaviors, e.g. loading the settings from some other config, changing settings based on the user, deciding not to persist some settings, or something else.
The included data source implementation, RCTDevSettingsUserDefaultsDataSource, uses NSUserDefaults and is backwards compatible with the older implementation, so **no workflows or dependent code will break, and old saved settings will persist.**
The RCTDevMenu interface has not changed and is therefore also backwards-compatible, though
some methods are now deprecated.
In order to ensure that RCTDevSettings
Closes https://github.com/facebook/react-native/pull/11613
Reviewed By: mmmulani
Differential Revision: D4571773
Pulled By: javache
fbshipit-source-id: 25555d0a6eaa81f694343e079ed02439e5845fbc
2017-02-24 14:50:29 +00:00
|
|
|
preferredStyle:UIAlertControllerStyleAlert];
|
|
|
|
[RCTPresentedViewController() presentViewController:alertController animated:YES completion:NULL];
|
|
|
|
}]];
|
|
|
|
} else {
|
|
|
|
[items addObject:[RCTDevMenuItem buttonItemWithTitleBlock:^NSString *{
|
2017-03-22 12:27:58 +00:00
|
|
|
return devSettings.isDebuggingRemotely ? @"Stop Remote JS Debugging" : @"Debug JS Remotely";
|
Add RCTDevSettings module
Summary:
This decouples non-UI logic from RCTDevMenu into a new module RCTDevSettings.
**Motivation**: This allows developers to change dev settings without depending on the built-in dev menu, e.g. if they want to introduce their own UI, or have other devtools logic that doesn't depend on an action sheet.
It also introduces the RCTDevSettingsDataSource protocol for storing dev tools preferences. This could allow a developer to implement alternative behaviors, e.g. loading the settings from some other config, changing settings based on the user, deciding not to persist some settings, or something else.
The included data source implementation, RCTDevSettingsUserDefaultsDataSource, uses NSUserDefaults and is backwards compatible with the older implementation, so **no workflows or dependent code will break, and old saved settings will persist.**
The RCTDevMenu interface has not changed and is therefore also backwards-compatible, though
some methods are now deprecated.
In order to ensure that RCTDevSettings
Closes https://github.com/facebook/react-native/pull/11613
Reviewed By: mmmulani
Differential Revision: D4571773
Pulled By: javache
fbshipit-source-id: 25555d0a6eaa81f694343e079ed02439e5845fbc
2017-02-24 14:50:29 +00:00
|
|
|
} handler:^{
|
|
|
|
devSettings.isDebuggingRemotely = !devSettings.isDebuggingRemotely;
|
|
|
|
}]];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (devSettings.isLiveReloadAvailable) {
|
|
|
|
[items addObject:[RCTDevMenuItem buttonItemWithTitleBlock:^NSString *{
|
|
|
|
return devSettings.isLiveReloadEnabled ? @"Disable Live Reload" : @"Enable Live Reload";
|
|
|
|
} handler:^{
|
|
|
|
devSettings.isLiveReloadEnabled = !devSettings.isLiveReloadEnabled;
|
|
|
|
}]];
|
|
|
|
[items addObject:[RCTDevMenuItem buttonItemWithTitleBlock:^NSString *{
|
|
|
|
return devSettings.isProfilingEnabled ? @"Stop Systrace" : @"Start Systrace";
|
|
|
|
} handler:^{
|
|
|
|
devSettings.isProfilingEnabled = !devSettings.isProfilingEnabled;
|
|
|
|
}]];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_bridge.devSettings.isHotLoadingAvailable) {
|
|
|
|
[items addObject:[RCTDevMenuItem buttonItemWithTitleBlock:^NSString *{
|
|
|
|
return devSettings.isHotLoadingEnabled ? @"Disable Hot Reloading" : @"Enable Hot Reloading";
|
|
|
|
} handler:^{
|
|
|
|
devSettings.isHotLoadingEnabled = !devSettings.isHotLoadingEnabled;
|
|
|
|
}]];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (devSettings.isJSCSamplingProfilerAvailable) {
|
|
|
|
// Note: bridge.jsContext is not implemented in the old bridge, so this code is
|
|
|
|
// duplicated in RCTJSCExecutor
|
|
|
|
[items addObject:[RCTDevMenuItem buttonItemWithTitle:@"Start / Stop JS Sampling Profiler" handler:^{
|
|
|
|
[devSettings toggleJSCSamplingProfiler];
|
|
|
|
}]];
|
|
|
|
}
|
|
|
|
|
|
|
|
[items addObject:[RCTDevMenuItem buttonItemWithTitleBlock:^NSString *{
|
2017-07-21 18:43:49 +00:00
|
|
|
return @"Toggle Inspector";
|
Add RCTDevSettings module
Summary:
This decouples non-UI logic from RCTDevMenu into a new module RCTDevSettings.
**Motivation**: This allows developers to change dev settings without depending on the built-in dev menu, e.g. if they want to introduce their own UI, or have other devtools logic that doesn't depend on an action sheet.
It also introduces the RCTDevSettingsDataSource protocol for storing dev tools preferences. This could allow a developer to implement alternative behaviors, e.g. loading the settings from some other config, changing settings based on the user, deciding not to persist some settings, or something else.
The included data source implementation, RCTDevSettingsUserDefaultsDataSource, uses NSUserDefaults and is backwards compatible with the older implementation, so **no workflows or dependent code will break, and old saved settings will persist.**
The RCTDevMenu interface has not changed and is therefore also backwards-compatible, though
some methods are now deprecated.
In order to ensure that RCTDevSettings
Closes https://github.com/facebook/react-native/pull/11613
Reviewed By: mmmulani
Differential Revision: D4571773
Pulled By: javache
fbshipit-source-id: 25555d0a6eaa81f694343e079ed02439e5845fbc
2017-02-24 14:50:29 +00:00
|
|
|
} handler:^{
|
|
|
|
[devSettings toggleElementInspector];
|
|
|
|
}]];
|
|
|
|
|
|
|
|
[items addObjectsFromArray:_extraMenuItems];
|
|
|
|
return items;
|
|
|
|
}
|
|
|
|
|
|
|
|
RCT_EXPORT_METHOD(show)
|
|
|
|
{
|
|
|
|
if (_actionSheet || !_bridge || RCTRunningInAppExtension()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-09-05 21:47:06 +00:00
|
|
|
NSString *desc = _bridge.bridgeDescription;
|
|
|
|
if (desc.length == 0) {
|
|
|
|
desc = NSStringFromClass([_bridge class]);
|
|
|
|
}
|
|
|
|
NSString *title = [NSString stringWithFormat:@"React Native: Development (%@)", desc];
|
Add RCTDevSettings module
Summary:
This decouples non-UI logic from RCTDevMenu into a new module RCTDevSettings.
**Motivation**: This allows developers to change dev settings without depending on the built-in dev menu, e.g. if they want to introduce their own UI, or have other devtools logic that doesn't depend on an action sheet.
It also introduces the RCTDevSettingsDataSource protocol for storing dev tools preferences. This could allow a developer to implement alternative behaviors, e.g. loading the settings from some other config, changing settings based on the user, deciding not to persist some settings, or something else.
The included data source implementation, RCTDevSettingsUserDefaultsDataSource, uses NSUserDefaults and is backwards compatible with the older implementation, so **no workflows or dependent code will break, and old saved settings will persist.**
The RCTDevMenu interface has not changed and is therefore also backwards-compatible, though
some methods are now deprecated.
In order to ensure that RCTDevSettings
Closes https://github.com/facebook/react-native/pull/11613
Reviewed By: mmmulani
Differential Revision: D4571773
Pulled By: javache
fbshipit-source-id: 25555d0a6eaa81f694343e079ed02439e5845fbc
2017-02-24 14:50:29 +00:00
|
|
|
// On larger devices we don't have an anchor point for the action sheet
|
|
|
|
UIAlertControllerStyle style = [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone ? UIAlertControllerStyleActionSheet : UIAlertControllerStyleAlert;
|
|
|
|
_actionSheet = [UIAlertController alertControllerWithTitle:title
|
|
|
|
message:@""
|
|
|
|
preferredStyle:style];
|
|
|
|
|
|
|
|
NSArray<RCTDevMenuItem *> *items = [self _menuItemsToPresent];
|
|
|
|
for (RCTDevMenuItem *item in items) {
|
|
|
|
[_actionSheet addAction:[UIAlertAction actionWithTitle:item.title
|
|
|
|
style:UIAlertActionStyleDefault
|
|
|
|
handler:[self alertActionHandlerForDevItem:item]]];
|
|
|
|
}
|
|
|
|
|
|
|
|
[_actionSheet addAction:[UIAlertAction actionWithTitle:@"Cancel"
|
|
|
|
style:UIAlertActionStyleCancel
|
|
|
|
handler:[self alertActionHandlerForDevItem:nil]]];
|
|
|
|
|
|
|
|
_presentedItems = items;
|
|
|
|
[RCTPresentedViewController() presentViewController:_actionSheet animated:YES completion:nil];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (RCTDevMenuAlertActionHandler)alertActionHandlerForDevItem:(RCTDevMenuItem *__nullable)item
|
|
|
|
{
|
|
|
|
return ^(__unused UIAlertAction *action) {
|
|
|
|
if (item) {
|
|
|
|
[item callHandler];
|
|
|
|
}
|
|
|
|
|
|
|
|
self->_actionSheet = nil;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - deprecated methods and properties
|
|
|
|
|
|
|
|
#define WARN_DEPRECATED_DEV_MENU_EXPORT() RCTLogWarn(@"Using deprecated method %s, use RCTDevSettings instead", __func__)
|
|
|
|
|
|
|
|
- (void)setShakeToShow:(BOOL)shakeToShow
|
|
|
|
{
|
|
|
|
_bridge.devSettings.isShakeToShowDevMenuEnabled = shakeToShow;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)shakeToShow
|
|
|
|
{
|
|
|
|
return _bridge.devSettings.isShakeToShowDevMenuEnabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
RCT_EXPORT_METHOD(reload)
|
|
|
|
{
|
|
|
|
WARN_DEPRECATED_DEV_MENU_EXPORT();
|
|
|
|
[_bridge reload];
|
|
|
|
}
|
|
|
|
|
|
|
|
RCT_EXPORT_METHOD(debugRemotely:(BOOL)enableDebug)
|
|
|
|
{
|
|
|
|
WARN_DEPRECATED_DEV_MENU_EXPORT();
|
|
|
|
_bridge.devSettings.isDebuggingRemotely = enableDebug;
|
|
|
|
}
|
|
|
|
|
|
|
|
RCT_EXPORT_METHOD(setProfilingEnabled:(BOOL)enabled)
|
|
|
|
{
|
|
|
|
WARN_DEPRECATED_DEV_MENU_EXPORT();
|
|
|
|
_bridge.devSettings.isProfilingEnabled = enabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)profilingEnabled
|
|
|
|
{
|
|
|
|
return _bridge.devSettings.isProfilingEnabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
RCT_EXPORT_METHOD(setLiveReloadEnabled:(BOOL)enabled)
|
|
|
|
{
|
|
|
|
WARN_DEPRECATED_DEV_MENU_EXPORT();
|
|
|
|
_bridge.devSettings.isLiveReloadEnabled = enabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)liveReloadEnabled
|
|
|
|
{
|
|
|
|
return _bridge.devSettings.isLiveReloadEnabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
RCT_EXPORT_METHOD(setHotLoadingEnabled:(BOOL)enabled)
|
|
|
|
{
|
|
|
|
WARN_DEPRECATED_DEV_MENU_EXPORT();
|
|
|
|
_bridge.devSettings.isHotLoadingEnabled = enabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)hotLoadingEnabled
|
|
|
|
{
|
|
|
|
return _bridge.devSettings.isHotLoadingEnabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
#else // Unavailable when not in dev mode
|
|
|
|
|
|
|
|
@implementation RCTDevMenu
|
|
|
|
|
|
|
|
- (void)show {}
|
|
|
|
- (void)reload {}
|
|
|
|
- (void)addItem:(NSString *)title handler:(dispatch_block_t)handler {}
|
|
|
|
- (void)addItem:(RCTDevMenu *)item {}
|
|
|
|
- (BOOL)isActionSheetShown { return NO; }
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation RCTDevMenuItem
|
|
|
|
|
|
|
|
+ (instancetype)buttonItemWithTitle:(NSString *)title handler:(void(^)(void))handler {return nil;}
|
|
|
|
+ (instancetype)buttonItemWithTitleBlock:(NSString * (^)(void))titleBlock
|
|
|
|
handler:(void(^)(void))handler {return nil;}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
@implementation RCTBridge (RCTDevMenu)
|
|
|
|
|
|
|
|
- (RCTDevMenu *)devMenu
|
|
|
|
{
|
|
|
|
#if RCT_DEV
|
|
|
|
return [self moduleForClass:[RCTDevMenu class]];
|
|
|
|
#else
|
|
|
|
return nil;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|