Browse Source

Refactored modals and added tests (#3955)

Yogev Ben David 6 years ago
parent
commit
0984d047f6
No account linked to committer's email address

+ 10
- 3
lib/ios/RNNCommandsHandler.m View File

@@ -204,9 +204,16 @@ static NSString* const setDefaultOptions	= @"setDefaultOptions";
204 204
 	[self assertReady];
205 205
 	
206 206
 	UIViewController<RNNRootViewProtocol> *newVc = [_controllerFactory createLayoutAndSaveToStore:layout];
207
-	[_modalManager showModal:newVc animated:newVc.getLeafViewController.options.animations.showModal.enable completion:^(NSString *componentId) {
208
-		[_eventEmitter sendOnNavigationCommandCompletion:showModal params:@{@"layout": layout}];
209
-		completion(componentId);
207
+	
208
+	if ([newVc respondsToSelector:@selector(applyModalOptions)]) {
209
+		[newVc.getLeafViewController applyModalOptions];
210
+	}
211
+	
212
+	[newVc.getLeafViewController waitForReactViewRender:newVc.getLeafViewController.options.animations.showModal.waitForRender perform:^{
213
+		[_modalManager showModal:newVc animated:newVc.getLeafViewController.options.animations.showModal.enable hasCustomAnimation:newVc.getLeafViewController.options.animations.showModal.hasCustomAnimation completion:^(NSString *componentId) {
214
+			[_eventEmitter sendOnNavigationCommandCompletion:showModal params:@{@"layout": layout}];
215
+			completion(componentId);
216
+		}];
210 217
 	}];
211 218
 }
212 219
 

+ 2
- 2
lib/ios/RNNModalManager.h View File

@@ -11,10 +11,10 @@
11 11
 
12 12
 @interface RNNModalManager : NSObject
13 13
 
14
-@property (nonatomic, strong) UIViewController<RNNRootViewProtocol>* toVC;
15 14
 @property (nonatomic, weak) id<RNNModalManagerDelegate> delegate;
16 15
 
17
-- (void)showModal:(UIViewController*)viewController animated:(BOOL)animated completion:(RNNTransitionWithComponentIdCompletionBlock)completion;
16
+- (void)showModal:(UIViewController *)viewController animated:(BOOL)animated completion:(RNNTransitionWithComponentIdCompletionBlock)completion;
17
+- (void)showModal:(UIViewController *)viewController animated:(BOOL)animated hasCustomAnimation:(BOOL)hasCustomAnimation completion:(RNNTransitionWithComponentIdCompletionBlock)completion;
18 18
 - (void)dismissModal:(UIViewController *)viewController completion:(RNNTransitionCompletionBlock)completion;
19 19
 - (void)dismissAllModalsAnimated:(BOOL)animated;
20 20
 

+ 15
- 36
lib/ios/RNNModalManager.m View File

@@ -2,7 +2,6 @@
2 2
 #import "RNNRootViewController.h"
3 3
 
4 4
 @implementation RNNModalManager {
5
-	RNNTransitionWithComponentIdCompletionBlock _completionBlock;
6 5
 	NSMutableArray* _pendingModalIdsToDismiss;
7 6
 	NSMutableArray* _presentedModals;
8 7
 }
@@ -16,51 +15,31 @@
16 15
 	return self;
17 16
 }
18 17
 
19
--(void)showModal:(BOOL)animated {
18
+-(void)showModal:(UIViewController *)viewController animated:(BOOL)animated completion:(RNNTransitionWithComponentIdCompletionBlock)completion {
19
+	[self showModal:viewController animated:animated hasCustomAnimation:NO completion:completion];
20
+}
21
+
22
+-(void)showModal:(UIViewController *)viewController animated:(BOOL)animated hasCustomAnimation:(BOOL)hasCustomAnimation completion:(RNNTransitionWithComponentIdCompletionBlock)completion {
23
+	if (!viewController) {
24
+		@throw [NSException exceptionWithName:@"ShowUnknownModal" reason:@"showModal called with nil viewController" userInfo:nil];
25
+	}
26
+	
20 27
 	UIViewController* topVC = [self topPresentedVC];
21 28
 	topVC.definesPresentationContext = YES;
22 29
 	
23
-	if ([topVC conformsToProtocol:@protocol(RNNRootViewProtocol)]) {
24
-		UIViewController<RNNRootViewProtocol> *navigationTopVC = (UIViewController<RNNRootViewProtocol>*)topVC;
25
-		RNNNavigationOptions* options = navigationTopVC.getLeafViewController.options;
26
-		if (options.animations.showModal.hasCustomAnimation) {
27
-			self.toVC.transitioningDelegate = navigationTopVC;
28
-		}
30
+	if (hasCustomAnimation) {
31
+		viewController.transitioningDelegate = (UIViewController<UIViewControllerTransitioningDelegate>*)topVC;
29 32
 	}
30 33
 	
31
-	[topVC presentViewController:self.toVC animated:animated completion:^{
32
-		if (_completionBlock) {
33
-			_completionBlock(self.toVC.getLeafViewController.componentId);
34
-			_completionBlock = nil;
34
+	[topVC presentViewController:viewController animated:animated completion:^{
35
+		if (completion) {
36
+			completion(nil);
35 37
 		}
36 38
 		
37
-		[_presentedModals addObject:self.toVC.navigationController ? self.toVC.navigationController : self.toVC];
38
-		
39
-		self.toVC = nil;
39
+		[_presentedModals addObject:viewController.navigationController ? viewController.navigationController : viewController];
40 40
 	}];
41 41
 }
42 42
 
43
--(void)showModal:(UIViewController *)viewController animated:(BOOL)animated completion:(RNNTransitionWithComponentIdCompletionBlock)completion {
44
-	self.toVC = (UIViewController<RNNRootViewProtocol>*)viewController;
45
-	RNNNavigationOptions* options = self.toVC.getLeafViewController.options;
46
-
47
-	_completionBlock = completion;
48
-	
49
-    if ([self.toVC respondsToSelector:@selector(applyModalOptions)]) {
50
-        [self.toVC.getLeafViewController applyModalOptions];
51
-    }
52
-    
53
-    if ([self.toVC respondsToSelector:@selector(isCustomViewController)] &&
54
-        [self.toVC.getLeafViewController isCustomViewController]
55
-    ) {
56
-		[self showModal:animated];
57
-	} else {
58
-		[self.toVC.getLeafViewController waitForReactViewRender:options.animations.showModal.waitForRender perform:^{
59
-			[self showModal:animated];
60
-		}];
61
-	}
62
-}
63
-
64 43
 - (void)dismissModal:(UIViewController *)viewController completion:(RNNTransitionCompletionBlock)completion {
65 44
 	if (viewController) {
66 45
 		[_pendingModalIdsToDismiss addObject:viewController];

+ 1
- 1
lib/ios/RNNRootViewController.m View File

@@ -89,7 +89,7 @@
89 89
 }
90 90
 
91 91
 - (void)waitForReactViewRender:(BOOL)wait perform:(RNNReactViewReadyCompletionBlock)readyBlock {
92
-	if (wait) {
92
+	if (wait && !_isExternalComponent) {
93 93
 		[self onReactViewReady:readyBlock];
94 94
 	} else {
95 95
 		readyBlock();

+ 16
- 6
lib/ios/ReactNativeNavigationTests/RNNModalManagerTest.m View File

@@ -2,24 +2,24 @@
2 2
 #import "RNNModalManager.h"
3 3
 
4 4
 @interface MockViewController : UIViewController
5
+
6
+@property CGFloat presentViewControllerCalls;
7
+
5 8
 @end
6 9
 @implementation MockViewController
7 10
 
8 11
 - (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {
12
+	_presentViewControllerCalls++;
9 13
 	completion();
10 14
 }
11 15
 
12 16
 @end
13 17
 
14 18
 @interface MockModalManager : RNNModalManager
19
+@property (nonatomic, strong) MockViewController* topPresentedVC;
15 20
 @end
16
-@implementation MockModalManager
17
-
18
--(UIViewController*)topPresentedVC {
19
-	MockViewController* vc = [MockViewController new];
20
-	return vc;
21
-}
22 21
 
22
+@implementation MockModalManager
23 23
 @end
24 24
 
25 25
 @interface RNNModalManagerTest : XCTestCase <RNNModalManagerDelegate> {
@@ -41,7 +41,9 @@
41 41
 	_vc2 = [RNNRootViewController new];
42 42
 	_vc3 = [RNNRootViewController new];
43 43
 	_modalManager = [[MockModalManager alloc] init];
44
+	_modalManager.topPresentedVC = [MockViewController new];
44 45
 }
46
+
45 47
 - (void)testDismissMultipleModalsInvokeDelegateWithCorrectParameters {
46 48
 	[_modalManager showModal:_vc1 animated:NO completion:nil];
47 49
 	[_modalManager showModal:_vc2 animated:NO completion:nil];
@@ -95,6 +97,14 @@
95 97
 	XCTAssertTrue(_modalDismissedCount == 0);
96 98
 }
97 99
 
100
+- (void)testShowModal_NilModalThrows {
101
+	XCTAssertThrows([_modalManager showModal:nil animated:NO completion:nil]);
102
+}
103
+
104
+- (void)testShowModal_CallPresentViewController {
105
+	[_modalManager showModal:_vc1 animated:NO completion:nil];
106
+	XCTAssertTrue(_modalManager.topPresentedVC.presentViewControllerCalls == 1);
107
+}
98 108
 
99 109
 #pragma mark RNNModalManagerDelegate
100 110