Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
fixing shake to open Dev Menu only work once
Summary:
Fixing issues #10588

This bug has been introduced during refactoring UIActionSheet to UIAlertController d368ebf#diff-f78a84ff95f2bcee5a70d3accb504528

**Test plan**

- shake to open DevMenu, choose random menu item, it should close DevMenu and after another shaking it should open again
Closes #10676

Differential Revision: D4168254

Pulled By: javache

fbshipit-source-id: 6e2935b765053a2b55809af357d2b6ea03e04e8b
  • Loading branch information
VojtechBartos authored and Facebook Github Bot committed Nov 29, 2016
1 parent b58c8ad commit abf1438
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 24 deletions.
4 changes: 4 additions & 0 deletions Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj
Expand Up @@ -117,6 +117,7 @@
83636F8F1B53F22C009F943E /* RCTUIManagerScenarioTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 83636F8E1B53F22C009F943E /* RCTUIManagerScenarioTests.m */; };
8385CEF51B873B5C00C6273E /* RCTImageLoaderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8385CEF41B873B5C00C6273E /* RCTImageLoaderTests.m */; };
8385CF041B87479200C6273E /* RCTImageLoaderHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 8385CF031B87479200C6273E /* RCTImageLoaderHelpers.m */; };
BC9C03401DC9F1D600B1C635 /* RCTDevMenuTests.m in Sources */ = {isa = PBXBuildFile; fileRef = BC9C033F1DC9F1D600B1C635 /* RCTDevMenuTests.m */; };
D85B829E1AB6D5D7003F4FE2 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D85B829C1AB6D5CE003F4FE2 /* libRCTVibration.a */; };
/* End PBXBuildFile section */

Expand Down Expand Up @@ -446,6 +447,7 @@
8385CEF41B873B5C00C6273E /* RCTImageLoaderTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTImageLoaderTests.m; sourceTree = "<group>"; };
8385CF031B87479200C6273E /* RCTImageLoaderHelpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTImageLoaderHelpers.m; sourceTree = "<group>"; };
8385CF051B8747A000C6273E /* RCTImageLoaderHelpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTImageLoaderHelpers.h; sourceTree = "<group>"; };
BC9C033F1DC9F1D600B1C635 /* RCTDevMenuTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTDevMenuTests.m; sourceTree = "<group>"; };
D85B82911AB6D5CE003F4FE2 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = ../../Libraries/Vibration/RCTVibration.xcodeproj; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -679,6 +681,7 @@
001BFCE31D838343008E587E /* RCTMultipartStreamReaderTests.m */,
138D6A161B53CD440074A87E /* RCTShadowViewTests.m */,
1497CFAB1B21F5E400C1F8F2 /* RCTUIManagerTests.m */,
BC9C033F1DC9F1D600B1C635 /* RCTDevMenuTests.m */,
13BCE84E1C9C209600DD7AAD /* RCTComponentPropsTests.m */,
39AA31A31DC1DFDC000F7EBB /* RCTUnicodeDecodeTests.m */,
143BC57E1B21E18100462512 /* Info.plist */,
Expand Down Expand Up @@ -1442,6 +1445,7 @@
39AA31A41DC1DFDC000F7EBB /* RCTUnicodeDecodeTests.m in Sources */,
13B6C1A31C34225900D3FAF5 /* RCTURLUtilsTests.m in Sources */,
8385CF041B87479200C6273E /* RCTImageLoaderHelpers.m in Sources */,
BC9C03401DC9F1D600B1C635 /* RCTDevMenuTests.m in Sources */,
68FF44381CF6111500720EFD /* RCTBundleURLProviderTests.m in Sources */,
8385CEF51B873B5C00C6273E /* RCTImageLoaderTests.m in Sources */,
);
Expand Down
69 changes: 69 additions & 0 deletions Examples/UIExplorer/UIExplorerUnitTests/RCTDevMenuTests.m
@@ -0,0 +1,69 @@
/**
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
* Facebook reserves all rights not expressly granted.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#import <XCTest/XCTest.h>

#import "RCTBridge.h"
#import "RCTDevMenu.h"

typedef void(^RCTDevMenuAlertActionHandler)(UIAlertAction *action);

@interface RCTDevMenu ()

- (RCTDevMenuAlertActionHandler)alertActionHandlerForDevItem:(RCTDevMenuItem *)item;

@end

@interface RCTDevMenuTests : XCTestCase

@end

@implementation RCTDevMenuTests
{
RCTBridge *_bridge;
}

- (void)setUp
{
[super setUp];

NSBundle *bundle = [NSBundle bundleForClass:[self class]];
_bridge = [[RCTBridge alloc] initWithBundleURL:[bundle URLForResource:@"TestBundle" withExtension:@"js"]
moduleProvider:nil
launchOptions:nil];
}

- (void)testShowCreatingActionSheet
{
XCTAssertFalse([_bridge.devMenu isActionSheetShown]);
[_bridge.devMenu show];
XCTAssertTrue([_bridge.devMenu isActionSheetShown]);
}


- (void)testClosingActionSheetAfterAction
{
for (RCTDevMenuItem *item in _bridge.devMenu.presentedItems) {
RCTDevMenuAlertActionHandler handler = [_bridge.devMenu alertActionHandlerForDevItem:item];
XCTAssertTrue([_bridge.devMenu isActionSheetShown]);

handler(nil);
XCTAssertFalse([_bridge.devMenu isActionSheetShown]);

[_bridge.devMenu show];
XCTAssertTrue([_bridge.devMenu isActionSheetShown]);
}
}

@end
12 changes: 12 additions & 0 deletions React/Modules/RCTDevMenu.h
Expand Up @@ -46,6 +46,18 @@
*/
@property (nonatomic, assign) BOOL showFPS;

/**
* Presented items in development menu
*/
@property (nonatomic, copy, readonly) NSArray<RCTDevMenuItem *> *presentedItems;


/**
* Detect if actions sheet (development menu) is shown
*/
- (BOOL)isActionSheetShown;


/**
* Manually show the dev menu (can be called from JS).
*/
Expand Down
68 changes: 44 additions & 24 deletions React/Modules/RCTDevMenu.m
Expand Up @@ -47,15 +47,16 @@ @interface RCTDevMenuItem ()

@property (nonatomic, assign, readonly) RCTDevMenuType type;
@property (nonatomic, copy, readonly) NSString *key;
@property (nonatomic, copy, readonly) NSString *title;
@property (nonatomic, copy, readonly) NSString *selectedTitle;
@property (nonatomic, copy) id value;

@end

@implementation RCTDevMenuItem
{
id _handler; // block

NSString *_title;
NSString *_selectedTitle;
}

- (instancetype)initWithType:(RCTDevMenuType)type
Expand All @@ -75,6 +76,15 @@ - (instancetype)initWithType:(RCTDevMenuType)type
return self;
}

- (NSString *)title
{
if (_type == RCTDevMenuTypeToggle && [_value boolValue]) {
return _selectedTitle;
}

return _title;
}

RCT_NOT_IMPLEMENTED(- (instancetype)init)

+ (instancetype)buttonItemWithTitle:(NSString *)title
Expand Down Expand Up @@ -119,6 +129,8 @@ - (void)callHandler

@end

typedef void(^RCTDevMenuAlertActionHandler)(UIAlertAction *action);

@interface RCTDevMenu () <RCTBridgeModule, RCTInvalidating, RCTWebSocketProxyDelegate>

@property (nonatomic, strong) Class executorClass;
Expand All @@ -133,7 +145,6 @@ @implementation RCTDevMenu
NSURLSessionDataTask *_updateTask;
NSURL *_liveReloadURL;
BOOL _jsLoaded;
NSArray<RCTDevMenuItem *> *_presentedItems;
NSMutableArray<RCTDevMenuItem *> *_extraMenuItems;
NSString *_webSocketExecutorName;
NSString *_executorOverride;
Expand Down Expand Up @@ -515,37 +526,40 @@ - (void)addItem:(RCTDevMenuItem *)item

NSArray<RCTDevMenuItem *> *items = [self menuItems];
for (RCTDevMenuItem *item in items) {
switch (item.type) {
case RCTDevMenuTypeButton: {
[_actionSheet addAction:[UIAlertAction actionWithTitle:item.title
style:UIAlertActionStyleDefault
handler:^(__unused UIAlertAction *action) {
[item callHandler];
}]];
break;
}
case RCTDevMenuTypeToggle: {
BOOL selected = [item.value boolValue];
[_actionSheet addAction:[UIAlertAction actionWithTitle:(selected? item.selectedTitle : item.title)
style:UIAlertActionStyleDefault
handler:^(__unused UIAlertAction *action) {
BOOL value = [self->_settings[item.key] boolValue];
[self updateSetting:item.key value:@(!value)]; // will call handler
}]];
break;
}
}
[_actionSheet addAction:[UIAlertAction actionWithTitle:item.title
style:UIAlertActionStyleDefault
handler:[self alertActionHandlerForDevItem:item]]];
}

[_actionSheet addAction:[UIAlertAction actionWithTitle:@"Cancel"
style:UIAlertActionStyleCancel
handler:nil]];
handler:[self alertActionHandlerForDevItem:nil]]];

_presentedItems = items;
[RCTPresentedViewController() presentViewController:_actionSheet animated:YES completion:nil];
}

- (RCTDevMenuAlertActionHandler)alertActionHandlerForDevItem:(RCTDevMenuItem *__nullable)item
{
return ^(__unused UIAlertAction *action) {
if (item) {
switch (item.type) {
case RCTDevMenuTypeButton: {
[item callHandler];
break;
}

case RCTDevMenuTypeToggle: {
BOOL value = [self->_settings[item.key] boolValue];
[self updateSetting:item.key value:@(!value)]; // will call handler
break;
}
}
}

self->_actionSheet = nil;
};
}

RCT_EXPORT_METHOD(reload)
{
Expand Down Expand Up @@ -675,6 +689,11 @@ - (void)checkForUpdates
[_updateTask resume];
}

- (BOOL)isActionSheetShown
{
return _actionSheet != nil;
}

@end

#else // Unavailable when not in dev mode
Expand All @@ -685,6 +704,7 @@ - (void)show {}
- (void)reload {}
- (void)addItem:(NSString *)title handler:(dispatch_block_t)handler {}
- (void)addItem:(RCTDevMenu *)item {}
- (BOOL)isActionSheetShown { return NO; }

@end

Expand Down

0 comments on commit abf1438

Please sign in to comment.