Skip to content

Commit abf1438

Browse files
VojtechBartosFacebook Github Bot
authored andcommitted
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
1 parent b58c8ad commit abf1438

File tree

4 files changed

+129
-24
lines changed

4 files changed

+129
-24
lines changed

Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@
117117
83636F8F1B53F22C009F943E /* RCTUIManagerScenarioTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 83636F8E1B53F22C009F943E /* RCTUIManagerScenarioTests.m */; };
118118
8385CEF51B873B5C00C6273E /* RCTImageLoaderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8385CEF41B873B5C00C6273E /* RCTImageLoaderTests.m */; };
119119
8385CF041B87479200C6273E /* RCTImageLoaderHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 8385CF031B87479200C6273E /* RCTImageLoaderHelpers.m */; };
120+
BC9C03401DC9F1D600B1C635 /* RCTDevMenuTests.m in Sources */ = {isa = PBXBuildFile; fileRef = BC9C033F1DC9F1D600B1C635 /* RCTDevMenuTests.m */; };
120121
D85B829E1AB6D5D7003F4FE2 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D85B829C1AB6D5CE003F4FE2 /* libRCTVibration.a */; };
121122
/* End PBXBuildFile section */
122123

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

@@ -679,6 +681,7 @@
679681
001BFCE31D838343008E587E /* RCTMultipartStreamReaderTests.m */,
680682
138D6A161B53CD440074A87E /* RCTShadowViewTests.m */,
681683
1497CFAB1B21F5E400C1F8F2 /* RCTUIManagerTests.m */,
684+
BC9C033F1DC9F1D600B1C635 /* RCTDevMenuTests.m */,
682685
13BCE84E1C9C209600DD7AAD /* RCTComponentPropsTests.m */,
683686
39AA31A31DC1DFDC000F7EBB /* RCTUnicodeDecodeTests.m */,
684687
143BC57E1B21E18100462512 /* Info.plist */,
@@ -1442,6 +1445,7 @@
14421445
39AA31A41DC1DFDC000F7EBB /* RCTUnicodeDecodeTests.m in Sources */,
14431446
13B6C1A31C34225900D3FAF5 /* RCTURLUtilsTests.m in Sources */,
14441447
8385CF041B87479200C6273E /* RCTImageLoaderHelpers.m in Sources */,
1448+
BC9C03401DC9F1D600B1C635 /* RCTDevMenuTests.m in Sources */,
14451449
68FF44381CF6111500720EFD /* RCTBundleURLProviderTests.m in Sources */,
14461450
8385CEF51B873B5C00C6273E /* RCTImageLoaderTests.m in Sources */,
14471451
);
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/**
2+
* The examples provided by Facebook are for non-commercial testing and
3+
* evaluation purposes only.
4+
*
5+
* Facebook reserves all rights not expressly granted.
6+
*
7+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8+
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9+
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
10+
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
11+
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
12+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13+
*/
14+
15+
#import <XCTest/XCTest.h>
16+
17+
#import "RCTBridge.h"
18+
#import "RCTDevMenu.h"
19+
20+
typedef void(^RCTDevMenuAlertActionHandler)(UIAlertAction *action);
21+
22+
@interface RCTDevMenu ()
23+
24+
- (RCTDevMenuAlertActionHandler)alertActionHandlerForDevItem:(RCTDevMenuItem *)item;
25+
26+
@end
27+
28+
@interface RCTDevMenuTests : XCTestCase
29+
30+
@end
31+
32+
@implementation RCTDevMenuTests
33+
{
34+
RCTBridge *_bridge;
35+
}
36+
37+
- (void)setUp
38+
{
39+
[super setUp];
40+
41+
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
42+
_bridge = [[RCTBridge alloc] initWithBundleURL:[bundle URLForResource:@"TestBundle" withExtension:@"js"]
43+
moduleProvider:nil
44+
launchOptions:nil];
45+
}
46+
47+
- (void)testShowCreatingActionSheet
48+
{
49+
XCTAssertFalse([_bridge.devMenu isActionSheetShown]);
50+
[_bridge.devMenu show];
51+
XCTAssertTrue([_bridge.devMenu isActionSheetShown]);
52+
}
53+
54+
55+
- (void)testClosingActionSheetAfterAction
56+
{
57+
for (RCTDevMenuItem *item in _bridge.devMenu.presentedItems) {
58+
RCTDevMenuAlertActionHandler handler = [_bridge.devMenu alertActionHandlerForDevItem:item];
59+
XCTAssertTrue([_bridge.devMenu isActionSheetShown]);
60+
61+
handler(nil);
62+
XCTAssertFalse([_bridge.devMenu isActionSheetShown]);
63+
64+
[_bridge.devMenu show];
65+
XCTAssertTrue([_bridge.devMenu isActionSheetShown]);
66+
}
67+
}
68+
69+
@end

React/Modules/RCTDevMenu.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,18 @@
4646
*/
4747
@property (nonatomic, assign) BOOL showFPS;
4848

49+
/**
50+
* Presented items in development menu
51+
*/
52+
@property (nonatomic, copy, readonly) NSArray<RCTDevMenuItem *> *presentedItems;
53+
54+
55+
/**
56+
* Detect if actions sheet (development menu) is shown
57+
*/
58+
- (BOOL)isActionSheetShown;
59+
60+
4961
/**
5062
* Manually show the dev menu (can be called from JS).
5163
*/

React/Modules/RCTDevMenu.m

Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,16 @@ @interface RCTDevMenuItem ()
4747

4848
@property (nonatomic, assign, readonly) RCTDevMenuType type;
4949
@property (nonatomic, copy, readonly) NSString *key;
50-
@property (nonatomic, copy, readonly) NSString *title;
51-
@property (nonatomic, copy, readonly) NSString *selectedTitle;
5250
@property (nonatomic, copy) id value;
5351

5452
@end
5553

5654
@implementation RCTDevMenuItem
5755
{
5856
id _handler; // block
57+
58+
NSString *_title;
59+
NSString *_selectedTitle;
5960
}
6061

6162
- (instancetype)initWithType:(RCTDevMenuType)type
@@ -75,6 +76,15 @@ - (instancetype)initWithType:(RCTDevMenuType)type
7576
return self;
7677
}
7778

79+
- (NSString *)title
80+
{
81+
if (_type == RCTDevMenuTypeToggle && [_value boolValue]) {
82+
return _selectedTitle;
83+
}
84+
85+
return _title;
86+
}
87+
7888
RCT_NOT_IMPLEMENTED(- (instancetype)init)
7989

8090
+ (instancetype)buttonItemWithTitle:(NSString *)title
@@ -119,6 +129,8 @@ - (void)callHandler
119129

120130
@end
121131

132+
typedef void(^RCTDevMenuAlertActionHandler)(UIAlertAction *action);
133+
122134
@interface RCTDevMenu () <RCTBridgeModule, RCTInvalidating, RCTWebSocketProxyDelegate>
123135

124136
@property (nonatomic, strong) Class executorClass;
@@ -133,7 +145,6 @@ @implementation RCTDevMenu
133145
NSURLSessionDataTask *_updateTask;
134146
NSURL *_liveReloadURL;
135147
BOOL _jsLoaded;
136-
NSArray<RCTDevMenuItem *> *_presentedItems;
137148
NSMutableArray<RCTDevMenuItem *> *_extraMenuItems;
138149
NSString *_webSocketExecutorName;
139150
NSString *_executorOverride;
@@ -515,37 +526,40 @@ - (void)addItem:(RCTDevMenuItem *)item
515526

516527
NSArray<RCTDevMenuItem *> *items = [self menuItems];
517528
for (RCTDevMenuItem *item in items) {
518-
switch (item.type) {
519-
case RCTDevMenuTypeButton: {
520-
[_actionSheet addAction:[UIAlertAction actionWithTitle:item.title
521-
style:UIAlertActionStyleDefault
522-
handler:^(__unused UIAlertAction *action) {
523-
[item callHandler];
524-
}]];
525-
break;
526-
}
527-
case RCTDevMenuTypeToggle: {
528-
BOOL selected = [item.value boolValue];
529-
[_actionSheet addAction:[UIAlertAction actionWithTitle:(selected? item.selectedTitle : item.title)
530-
style:UIAlertActionStyleDefault
531-
handler:^(__unused UIAlertAction *action) {
532-
BOOL value = [self->_settings[item.key] boolValue];
533-
[self updateSetting:item.key value:@(!value)]; // will call handler
534-
}]];
535-
break;
536-
}
537-
}
529+
[_actionSheet addAction:[UIAlertAction actionWithTitle:item.title
530+
style:UIAlertActionStyleDefault
531+
handler:[self alertActionHandlerForDevItem:item]]];
538532
}
539533

540534
[_actionSheet addAction:[UIAlertAction actionWithTitle:@"Cancel"
541535
style:UIAlertActionStyleCancel
542-
handler:nil]];
536+
handler:[self alertActionHandlerForDevItem:nil]]];
543537

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

542+
- (RCTDevMenuAlertActionHandler)alertActionHandlerForDevItem:(RCTDevMenuItem *__nullable)item
543+
{
544+
return ^(__unused UIAlertAction *action) {
545+
if (item) {
546+
switch (item.type) {
547+
case RCTDevMenuTypeButton: {
548+
[item callHandler];
549+
break;
550+
}
551+
552+
case RCTDevMenuTypeToggle: {
553+
BOOL value = [self->_settings[item.key] boolValue];
554+
[self updateSetting:item.key value:@(!value)]; // will call handler
555+
break;
556+
}
557+
}
558+
}
548559

560+
self->_actionSheet = nil;
561+
};
562+
}
549563

550564
RCT_EXPORT_METHOD(reload)
551565
{
@@ -675,6 +689,11 @@ - (void)checkForUpdates
675689
[_updateTask resume];
676690
}
677691

692+
- (BOOL)isActionSheetShown
693+
{
694+
return _actionSheet != nil;
695+
}
696+
678697
@end
679698

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

689709
@end
690710

0 commit comments

Comments
 (0)