Permalink
Browse files

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...
1 parent b58c8ad commit abf1438f5496d969a5e9e8b805fdcca2c11fdb43 @VojtechBartos VojtechBartos committed with Facebook Github Bot Nov 29, 2016
@@ -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 */
@@ -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 */
@@ -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 */,
@@ -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 */,
);
@@ -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
@@ -47,6 +47,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).
*/
- (void)show;
@@ -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
@@ -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
@@ -119,6 +129,8 @@ - (void)callHandler
@end
+typedef void(^RCTDevMenuAlertActionHandler)(UIAlertAction *action);
+
@interface RCTDevMenu () <RCTBridgeModule, RCTInvalidating, RCTWebSocketProxyDelegate>
@property (nonatomic, strong) Class executorClass;
@@ -133,7 +145,6 @@ @implementation RCTDevMenu
NSURLSessionDataTask *_updateTask;
NSURL *_liveReloadURL;
BOOL _jsLoaded;
- NSArray<RCTDevMenuItem *> *_presentedItems;
NSMutableArray<RCTDevMenuItem *> *_extraMenuItems;
NSString *_webSocketExecutorName;
NSString *_executorOverride;
@@ -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)
{
@@ -675,6 +689,11 @@ - (void)checkForUpdates
[_updateTask resume];
}
+- (BOOL)isActionSheetShown
+{
+ return _actionSheet != nil;
+}
+
@end
#else // Unavailable when not in dev mode
@@ -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

0 comments on commit abf1438

Please sign in to comment.