Browse Source

V2 overlays (#2510)

* overlay support
yogevbd 6 years ago
parent
commit
1446cd2fe9
No account linked to committer's email address

+ 26
- 0
e2e/ScreenStack.test.js View File

59
     await elementById(testIDs.SWITCH_FIRST_TAB_BUTTON).tap();
59
     await elementById(testIDs.SWITCH_FIRST_TAB_BUTTON).tap();
60
     await expect(elementByLabel('This is tab 1')).toBeVisible();
60
     await expect(elementByLabel('This is tab 1')).toBeVisible();
61
   });
61
   });
62
+
63
+  it('show and dismiss overlay', async () => {
64
+    await elementById(testIDs.PUSH_OPTIONS_BUTTON).tap();
65
+    await elementById(testIDs.SHOW_OVERLAY_BUTTON).tap();
66
+    await expect(elementById(testIDs.DIALOG_HEADER)).toBeVisible();
67
+    await elementById(testIDs.OK_BUTTON).tap();
68
+    await expect(elementById(testIDs.DIALOG_HEADER)).toBeNotVisible();
69
+  });
70
+
71
+  it('overlay pass touches - true', async () => {
72
+    await elementById(testIDs.PUSH_OPTIONS_BUTTON).tap();
73
+    await elementById(testIDs.SHOW_TOUCH_THROUGH_OVERLAY_BUTTON).tap();
74
+    await expect(elementById(testIDs.DIALOG_HEADER)).toBeVisible();
75
+    await expect(elementById(testIDs.TOP_BAR_ELEMENT)).toBeVisible();
76
+    await elementById(testIDs.HIDE_TOP_BAR_BUTTON).tap();
77
+    await expect(elementById(testIDs.TOP_BAR_ELEMENT)).toBeNotVisible();
78
+  });
79
+
80
+  it('overlay pass touches - false', async () => {
81
+    await elementById(testIDs.PUSH_OPTIONS_BUTTON).tap();
82
+    await elementById(testIDs.SHOW_OVERLAY_BUTTON).tap();
83
+    await expect(elementById(testIDs.DIALOG_HEADER)).toBeVisible();
84
+    await expect(elementById(testIDs.TOP_BAR_ELEMENT)).toBeVisible();
85
+    await elementById(testIDs.HIDE_TOP_BAR_BUTTON).tap();
86
+    await expect(elementById(testIDs.TOP_BAR_ELEMENT)).toBeVisible();
87
+  });
62
 });
88
 });

+ 12
- 0
lib/ios/RNNBridgeModule.m View File

78
 	}];
78
 	}];
79
 }
79
 }
80
 
80
 
81
+RCT_EXPORT_METHOD(showOverlay:(NSDictionary*)layout resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
82
+	[_commandsHandler showOverlay:layout completion:^{
83
+		resolve(layout[@"id"]);
84
+	}];
85
+}
86
+
87
+RCT_EXPORT_METHOD(dismissOverlay:(NSString*)componentId resolve:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
88
+	[_commandsHandler dismissOverlay:componentId completion:^{
89
+		resolve(@(1));
90
+	}];
91
+}
92
+
81
 @end
93
 @end
82
 
94
 

+ 4
- 0
lib/ios/RNNCommandsHandler.h View File

28
 
28
 
29
 -(void) dismissAllModalsWithCompletion:(RNNTransitionCompletionBlock)completion;
29
 -(void) dismissAllModalsWithCompletion:(RNNTransitionCompletionBlock)completion;
30
 
30
 
31
+-(void)showOverlay:(NSDictionary *)layout completion:(RNNTransitionCompletionBlock)completion;
32
+
33
+-(void)dismissOverlay:(NSString*)componentId completion:(RNNTransitionCompletionBlock)completion;
34
+
31
 @end
35
 @end

+ 14
- 0
lib/ios/RNNCommandsHandler.m View File

1
 #import "RNNCommandsHandler.h"
1
 #import "RNNCommandsHandler.h"
2
 #import "RNNModalManager.h"
2
 #import "RNNModalManager.h"
3
 #import "RNNNavigationStackManager.h"
3
 #import "RNNNavigationStackManager.h"
4
+#import "RNNOverlayManager.h"
4
 #import "RNNNavigationOptions.h"
5
 #import "RNNNavigationOptions.h"
5
 #import "RNNRootViewController.h"
6
 #import "RNNRootViewController.h"
6
 #import "React/RCTUIManager.h"
7
 #import "React/RCTUIManager.h"
10
 	RNNStore *_store;
11
 	RNNStore *_store;
11
 	RNNNavigationStackManager* _navigationStackManager;
12
 	RNNNavigationStackManager* _navigationStackManager;
12
 	RNNModalManager* _modalManager;
13
 	RNNModalManager* _modalManager;
14
+	RNNOverlayManager* _overlayManager;
13
 }
15
 }
14
 
16
 
15
 -(instancetype) initWithStore:(RNNStore*)store controllerFactory:(RNNControllerFactory*)controllerFactory {
17
 -(instancetype) initWithStore:(RNNStore*)store controllerFactory:(RNNControllerFactory*)controllerFactory {
18
 	_controllerFactory = controllerFactory;
20
 	_controllerFactory = controllerFactory;
19
 	_navigationStackManager = [[RNNNavigationStackManager alloc] initWithStore:_store];
21
 	_navigationStackManager = [[RNNNavigationStackManager alloc] initWithStore:_store];
20
 	_modalManager = [[RNNModalManager alloc] initWithStore:_store];
22
 	_modalManager = [[RNNModalManager alloc] initWithStore:_store];
23
+	_overlayManager = [[RNNOverlayManager alloc] init];
21
 	return self;
24
 	return self;
22
 }
25
 }
23
 
26
 
128
 	[CATransaction commit];
131
 	[CATransaction commit];
129
 }
132
 }
130
 
133
 
134
+-(void)showOverlay:(NSDictionary *)layout completion:(RNNTransitionCompletionBlock)completion {
135
+	[self assertReady];
136
+	UIViewController* overlayVC = [_controllerFactory createOverlay:layout];
137
+	[_overlayManager showOverlay:overlayVC completion:completion];
138
+}
139
+
140
+- (void)dismissOverlay:(NSString*)componentId completion:(RNNTransitionCompletionBlock)completion {
141
+	[self assertReady];
142
+	[_overlayManager dismissOverlay:componentId completion:completion];
143
+}
144
+
131
 #pragma mark - private
145
 #pragma mark - private
132
 
146
 
133
 -(void) assertReady {
147
 -(void) assertReady {

+ 3
- 0
lib/ios/RNNControllerFactory.h View File

15
 
15
 
16
 -(UIViewController<RNNRootViewProtocol> *)createLayoutAndSaveToStore:(NSDictionary*)layout;
16
 -(UIViewController<RNNRootViewProtocol> *)createLayoutAndSaveToStore:(NSDictionary*)layout;
17
 
17
 
18
+-(UIViewController *)createOverlay:(NSDictionary*)layout;
19
+
18
 @property (nonatomic, strong) RNNNavigationOptions* defaultOptions;
20
 @property (nonatomic, strong) RNNNavigationOptions* defaultOptions;
19
 
21
 
22
+
20
 @end
23
 @end

+ 12
- 1
lib/ios/RNNControllerFactory.m View File

162
 	return sideMenuChild;
162
 	return sideMenuChild;
163
 }
163
 }
164
 
164
 
165
-
165
+- (UIViewController *)createOverlay:(NSDictionary*)layout {
166
+	UIViewController *vc = [self fromTree:layout];
167
+	NSDictionary* options = layout[@"data"][@"options"];
168
+	RCTRootView* rootView = (RCTRootView*)vc.view;
169
+	rootView.passThroughTouches = ![options[@"interceptTouches"] boolValue];
170
+	rootView.backgroundColor = [UIColor clearColor];
171
+	CGSize availableSize = UIApplication.sharedApplication.delegate.window.bounds.size;
172
+	rootView.frame = CGRectMake(0, 0, availableSize.width, availableSize.height);
173
+	[_bridge.uiManager setAvailableSize:availableSize forRootView:vc.view];
174
+	
175
+	return vc;
176
+}
166
 
177
 
167
 @end
178
 @end

+ 10
- 0
lib/ios/RNNOverlayManager.h View File

1
+#import <Foundation/Foundation.h>
2
+#import <UIKit/UIKit.h>
3
+#import "RNNStore.h"
4
+
5
+@interface RNNOverlayManager : NSObject
6
+
7
+- (void)showOverlay:(UIViewController*)viewController completion:(RNNTransitionCompletionBlock)completion;
8
+- (void)dismissOverlay:(NSString*)componentId completion:(RNNTransitionCompletionBlock)completion;
9
+
10
+@end

+ 38
- 0
lib/ios/RNNOverlayManager.m View File

1
+#import "RNNOverlayManager.h"
2
+
3
+@implementation RNNOverlayManager {
4
+	NSMutableDictionary* _overlayDict;
5
+}
6
+
7
+- (instancetype)init {
8
+	self = [super init];
9
+	_overlayDict = [[NSMutableDictionary alloc] init];
10
+	return self;
11
+}
12
+
13
+#pragma mark - public
14
+
15
+- (void)showOverlay:(RNNRootViewController *)viewController completion:(RNNTransitionCompletionBlock)completion {
16
+	[self cacheOverlay:viewController];
17
+	[[[UIApplication sharedApplication] keyWindow] addSubview:viewController.view];
18
+	completion();
19
+}
20
+
21
+- (void)dismissOverlay:(NSString*)componentId completion:(RNNTransitionCompletionBlock)completion {
22
+	RNNRootViewController* viewController = [_overlayDict objectForKey:componentId];
23
+	[self removeCachedOverlay:viewController];
24
+	completion();
25
+}
26
+
27
+#pragma mark - private
28
+
29
+- (void)cacheOverlay:(RNNRootViewController*)viewController {
30
+	[_overlayDict setObject:viewController forKey:viewController.componentId];
31
+}
32
+
33
+- (void)removeCachedOverlay:(RNNRootViewController*)viewController {
34
+	[viewController.view removeFromSuperview];
35
+	[_overlayDict removeObjectForKey:viewController.componentId];
36
+}
37
+
38
+@end

+ 20
- 4
lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj View File

76
 		507F44201FFA8A8800D9425B /* RNNRootViewProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 507F441F1FFA8A8800D9425B /* RNNRootViewProtocol.h */; };
76
 		507F44201FFA8A8800D9425B /* RNNRootViewProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 507F441F1FFA8A8800D9425B /* RNNRootViewProtocol.h */; };
77
 		50CB3B691FDE911400AA153B /* RNNSideMenuOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 50CB3B671FDE911400AA153B /* RNNSideMenuOptions.h */; };
77
 		50CB3B691FDE911400AA153B /* RNNSideMenuOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 50CB3B671FDE911400AA153B /* RNNSideMenuOptions.h */; };
78
 		50CB3B6A1FDE911400AA153B /* RNNSideMenuOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 50CB3B681FDE911400AA153B /* RNNSideMenuOptions.m */; };
78
 		50CB3B6A1FDE911400AA153B /* RNNSideMenuOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 50CB3B681FDE911400AA153B /* RNNSideMenuOptions.m */; };
79
+		50D031342005149000386B3D /* RNNOverlayManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 50D031322005149000386B3D /* RNNOverlayManager.h */; };
80
+		50D031352005149000386B3D /* RNNOverlayManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 50D031332005149000386B3D /* RNNOverlayManager.m */; };
79
 		50EB93421FE14A3E00BD8EEE /* RNNBottomTabOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 50EB93401FE14A3E00BD8EEE /* RNNBottomTabOptions.m */; };
81
 		50EB93421FE14A3E00BD8EEE /* RNNBottomTabOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 50EB93401FE14A3E00BD8EEE /* RNNBottomTabOptions.m */; };
80
 		50F5DFC11F407A8C001A00BC /* RNNTabBarController.h in Headers */ = {isa = PBXBuildFile; fileRef = 50F5DFBF1F407A8C001A00BC /* RNNTabBarController.h */; };
82
 		50F5DFC11F407A8C001A00BC /* RNNTabBarController.h in Headers */ = {isa = PBXBuildFile; fileRef = 50F5DFBF1F407A8C001A00BC /* RNNTabBarController.h */; };
81
 		50F5DFC21F407A8C001A00BC /* RNNTabBarController.m in Sources */ = {isa = PBXBuildFile; fileRef = 50F5DFC01F407A8C001A00BC /* RNNTabBarController.m */; };
83
 		50F5DFC21F407A8C001A00BC /* RNNTabBarController.m in Sources */ = {isa = PBXBuildFile; fileRef = 50F5DFC01F407A8C001A00BC /* RNNTabBarController.m */; };
240
 		507F441F1FFA8A8800D9425B /* RNNRootViewProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNNRootViewProtocol.h; sourceTree = "<group>"; };
242
 		507F441F1FFA8A8800D9425B /* RNNRootViewProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNNRootViewProtocol.h; sourceTree = "<group>"; };
241
 		50CB3B671FDE911400AA153B /* RNNSideMenuOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNSideMenuOptions.h; sourceTree = "<group>"; };
243
 		50CB3B671FDE911400AA153B /* RNNSideMenuOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNSideMenuOptions.h; sourceTree = "<group>"; };
242
 		50CB3B681FDE911400AA153B /* RNNSideMenuOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNSideMenuOptions.m; sourceTree = "<group>"; };
244
 		50CB3B681FDE911400AA153B /* RNNSideMenuOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNSideMenuOptions.m; sourceTree = "<group>"; };
245
+		50D031322005149000386B3D /* RNNOverlayManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNOverlayManager.h; sourceTree = "<group>"; };
246
+		50D031332005149000386B3D /* RNNOverlayManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNOverlayManager.m; sourceTree = "<group>"; };
243
 		50EB933F1FE14A3E00BD8EEE /* RNNBottomTabOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNBottomTabOptions.h; sourceTree = "<group>"; };
247
 		50EB933F1FE14A3E00BD8EEE /* RNNBottomTabOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNBottomTabOptions.h; sourceTree = "<group>"; };
244
 		50EB93401FE14A3E00BD8EEE /* RNNBottomTabOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNBottomTabOptions.m; sourceTree = "<group>"; };
248
 		50EB93401FE14A3E00BD8EEE /* RNNBottomTabOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNBottomTabOptions.m; sourceTree = "<group>"; };
245
 		50F5DFBF1F407A8C001A00BC /* RNNTabBarController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNTabBarController.h; sourceTree = "<group>"; };
249
 		50F5DFBF1F407A8C001A00BC /* RNNTabBarController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNTabBarController.h; sourceTree = "<group>"; };
459
 			name = HMSegmentControl;
463
 			name = HMSegmentControl;
460
 			sourceTree = "<group>";
464
 			sourceTree = "<group>";
461
 		};
465
 		};
462
-		7B1E4C4B1E2D173700C3A525 /* Controllers */ = {
466
+		50D031312005146C00386B3D /* Managers */ = {
463
 			isa = PBXGroup;
467
 			isa = PBXGroup;
464
 			children = (
468
 			children = (
465
-				E8AEDB471F584175000F5A6A /* Components */,
466
-				E8AEDB461F58414D000F5A6A /* Animations */,
467
-				504AFE611FFE52EF0076E904 /* Options */,
468
 				261F0E621E6EC94900989DE2 /* RNNModalManager.h */,
469
 				261F0E621E6EC94900989DE2 /* RNNModalManager.h */,
469
 				261F0E631E6EC94900989DE2 /* RNNModalManager.m */,
470
 				261F0E631E6EC94900989DE2 /* RNNModalManager.m */,
470
 				261F0E681E6F028A00989DE2 /* RNNNavigationStackManager.h */,
471
 				261F0E681E6F028A00989DE2 /* RNNNavigationStackManager.h */,
471
 				261F0E691E6F028A00989DE2 /* RNNNavigationStackManager.m */,
472
 				261F0E691E6F028A00989DE2 /* RNNNavigationStackManager.m */,
473
+				50D031322005149000386B3D /* RNNOverlayManager.h */,
474
+				50D031332005149000386B3D /* RNNOverlayManager.m */,
475
+			);
476
+			name = Managers;
477
+			sourceTree = "<group>";
478
+		};
479
+		7B1E4C4B1E2D173700C3A525 /* Controllers */ = {
480
+			isa = PBXGroup;
481
+			children = (
482
+				E8AEDB471F584175000F5A6A /* Components */,
483
+				E8AEDB461F58414D000F5A6A /* Animations */,
484
+				504AFE611FFE52EF0076E904 /* Options */,
485
+				50D031312005146C00386B3D /* Managers */,
472
 				26916C941E4B9CCC00D13680 /* RNNRootViewCreator.h */,
486
 				26916C941E4B9CCC00D13680 /* RNNRootViewCreator.h */,
473
 				26916C961E4B9E7700D13680 /* RNNReactRootViewCreator.h */,
487
 				26916C961E4B9E7700D13680 /* RNNReactRootViewCreator.h */,
474
 				26916C971E4B9E7700D13680 /* RNNReactRootViewCreator.m */,
488
 				26916C971E4B9E7700D13680 /* RNNReactRootViewCreator.m */,
668
 				E8DA24401F97459B00CD552B /* RNNElementFinder.h in Headers */,
682
 				E8DA24401F97459B00CD552B /* RNNElementFinder.h in Headers */,
669
 				263905BE1E4C6F440023D7D3 /* RCCTheSideBarManagerViewController.h in Headers */,
683
 				263905BE1E4C6F440023D7D3 /* RCCTheSideBarManagerViewController.h in Headers */,
670
 				263905CE1E4C6F440023D7D3 /* TheSidebarController.h in Headers */,
684
 				263905CE1E4C6F440023D7D3 /* TheSidebarController.h in Headers */,
685
+				50D031342005149000386B3D /* RNNOverlayManager.h in Headers */,
671
 				7B1126A71E2D2B6C00F9B03B /* RNNEventEmitter.h in Headers */,
686
 				7B1126A71E2D2B6C00F9B03B /* RNNEventEmitter.h in Headers */,
672
 				E8A430111F9CB87B00B61A20 /* RNNAnimatedView.h in Headers */,
687
 				E8A430111F9CB87B00B61A20 /* RNNAnimatedView.h in Headers */,
673
 				268692821E5054F800E2C612 /* RNNStore.h in Headers */,
688
 				268692821E5054F800E2C612 /* RNNStore.h in Headers */,
850
 				268692831E5054F800E2C612 /* RNNStore.m in Sources */,
865
 				268692831E5054F800E2C612 /* RNNStore.m in Sources */,
851
 				7BC9346E1E26886E00EFA125 /* RNNControllerFactory.m in Sources */,
866
 				7BC9346E1E26886E00EFA125 /* RNNControllerFactory.m in Sources */,
852
 				507F43F91FF525B500D9425B /* RNNSegmentedControl.m in Sources */,
867
 				507F43F91FF525B500D9425B /* RNNSegmentedControl.m in Sources */,
868
+				50D031352005149000386B3D /* RNNOverlayManager.m in Sources */,
853
 				E8E5182F1F83A48B000467AC /* RNNTransitionStateHolder.m in Sources */,
869
 				E8E5182F1F83A48B000467AC /* RNNTransitionStateHolder.m in Sources */,
854
 				263905B61E4C6F440023D7D3 /* MMExampleDrawerVisualStateManager.m in Sources */,
870
 				263905B61E4C6F440023D7D3 /* MMExampleDrawerVisualStateManager.m in Sources */,
855
 				E8E518331F83B3E0000467AC /* RNNUtils.m in Sources */,
871
 				E8E518331F83B3E0000467AC /* RNNUtils.m in Sources */,

+ 15
- 7
lib/src/Navigation.js View File

119
   }
119
   }
120
 
120
 
121
   /**
121
   /**
122
-   * Obtain the events registery instance
122
+   * Show overlay on top of the window
123
+   * @param {*} params
123
    */
124
    */
124
-  events() {
125
-    return this.publicEventsRegistry;
125
+  showOverlay(params) {
126
+    return this.commands.showOverlay(params);
126
   }
127
   }
127
 
128
 
128
-  showOverlay(type, options) {
129
-    return this.commands.showOverlay(type, options);
129
+  /**
130
+   * dismiss overlay by componentId
131
+   * @param {string} componentId
132
+   */
133
+  dismissOverlay(componentId) {
134
+    return this.commands.dismissOverlay(componentId);
130
   }
135
   }
131
 
136
 
132
-  dismissOverlay() {
133
-    return this.commands.dismissOverlay();
137
+  /**
138
+   * Obtain the events registery instance
139
+   */
140
+  events() {
141
+    return this.publicEventsRegistry;
134
   }
142
   }
135
 }
143
 }
136
 
144
 

+ 4
- 5
lib/src/adapters/NativeCommandsSender.js View File

47
     return this.nativeCommandsModule.dismissAllModals();
47
     return this.nativeCommandsModule.dismissAllModals();
48
   }
48
   }
49
 
49
 
50
-  showOverlay(type, options) {
51
-    return this.nativeCommandsModule.showOverlay(type, options);
50
+  showOverlay(layout) {
51
+    return this.nativeCommandsModule.showOverlay(layout);
52
   }
52
   }
53
 
53
 
54
-  dismissOverlay() {
55
-    this.nativeCommandsModule.dismissOverlay();
56
-    return Promise.resolve(true);
54
+  dismissOverlay(componentId) {
55
+    return this.nativeCommandsModule.dismissOverlay(componentId);
57
   }
56
   }
58
 }
57
 }
59
 
58
 

+ 12
- 16
lib/src/commands/Commands.js View File

62
     return this.nativeCommandsSender.popToRoot(componentId);
62
     return this.nativeCommandsSender.popToRoot(componentId);
63
   }
63
   }
64
 
64
 
65
-  // showOverlay(type, options) {
66
-    // let promise;
67
-    // if (type === 'custom') {
68
-    //   const layout = this.layoutTreeParser.createDialogComponent({ name: options });
69
-    //   this.layoutTreeCrawler.crawl(layout);
70
-    //   promise = this.nativeCommandsSender.showOverlay(type, layout);
71
-    // } else {
72
-    //   const input = _.cloneDeep(options);
73
-    //   OptionsProcessor.processOptions(input);
74
-    //   promise = this.nativeCommandsSender.showOverlay(type, input);
75
-    // }
76
-    // return promise;
77
-  // }
78
-
79
-  dismissOverlay() {
80
-    return this.nativeCommandsSender.dismissOverlay();
65
+  showOverlay(componentData) {
66
+    const input = _.cloneDeep(componentData);
67
+    OptionsProcessor.processOptions(input);
68
+
69
+    const layout = this.layoutTreeParser.parse(input);
70
+    this.layoutTreeCrawler.crawl(layout);
71
+
72
+    return this.nativeCommandsSender.showOverlay(layout);
73
+  }
74
+
75
+  dismissOverlay(componentId) {
76
+    return this.nativeCommandsSender.dismissOverlay(componentId);
81
   }
77
   }
82
 }
78
 }
83
 
79
 

+ 36
- 10
lib/src/commands/Commands.test.js View File

238
     });
238
     });
239
   });
239
   });
240
 
240
 
241
-  xdescribe('showOverlay', () => {
241
+  describe('showOverlay', () => {
242
+    it('sends command to native after parsing into a correct layout tree', () => {
243
+      uut.showOverlay({
244
+        component: {
245
+          name: 'com.example.MyScreen'
246
+        }
247
+      });
248
+      expect(mockCommandsSender.showOverlay).toHaveBeenCalledTimes(1);
249
+      expect(mockCommandsSender.showOverlay).toHaveBeenCalledWith({
250
+        type: 'Component',
251
+        id: 'Component+UNIQUE_ID',
252
+        data: {
253
+          name: 'com.example.MyScreen',
254
+          options: {}
255
+        },
256
+        children: []
257
+      });
258
+    });
259
+
242
     it('deep clones input to avoid mutation errors', () => {
260
     it('deep clones input to avoid mutation errors', () => {
243
-      const obj = { title: 'test' };
244
-      uut.showOverlay('alert', obj);
245
-      expect(mockCommandsSender.showOverlay.mock.calls[0][1]).not.toBe(obj);
261
+      const obj = {};
262
+      uut.showOverlay({ component: { name: 'name', inner: obj } });
263
+      expect(mockCommandsSender.showOverlay.mock.calls[0][0].data.inner).not.toBe(obj);
246
     });
264
     });
247
 
265
 
248
-    it('resolves with the parsed layout', async () => {
249
-      mockCommandsSender.showOverlay.mockReturnValue(Promise.resolve('result'));
250
-      const result = await uut.showOverlay('custom', 'com.example.MyScreen');
251
-      expect(result).toEqual('result');
266
+    it('resolves with the component id', async () => {
267
+      mockCommandsSender.showOverlay.mockReturnValue(Promise.resolve('Component1'));
268
+      const result = await uut.showOverlay({ component: { name: 'com.example.MyScreen' } });
269
+      expect(result).toEqual('Component1');
252
     });
270
     });
253
   });
271
   });
254
 
272
 
255
   describe('dismissOverlay', () => {
273
   describe('dismissOverlay', () => {
256
-    it('check promis returns true', () => {
257
-      uut.dismissOverlay();
274
+    it('check promise returns true', async () => {
275
+      mockCommandsSender.dismissOverlay.mockReturnValue(Promise.resolve(true));
276
+      const result = await uut.dismissOverlay('Component1');
277
+      expect(mockCommandsSender.dismissOverlay).toHaveBeenCalledTimes(1);
278
+      expect(result).toEqual(true);
279
+    });
280
+
281
+    it('send command to native with componentId', () => {
282
+      uut.dismissOverlay('Component1');
258
       expect(mockCommandsSender.dismissOverlay).toHaveBeenCalledTimes(1);
283
       expect(mockCommandsSender.dismissOverlay).toHaveBeenCalledTimes(1);
284
+      expect(mockCommandsSender.dismissOverlay).toHaveBeenCalledWith('Component1');
259
     });
285
     });
260
   });
286
   });
261
 });
287
 });

+ 11
- 5
playground/src/screens/CustomDialog.js View File

4
 const { View, Text, Button } = require('react-native');
4
 const { View, Text, Button } = require('react-native');
5
 const Navigation = require('react-native-navigation');
5
 const Navigation = require('react-native-navigation');
6
 
6
 
7
+const testIDs = require('../testIDs');
8
+
7
 class CustomDialog extends PureComponent {
9
 class CustomDialog extends PureComponent {
8
 
10
 
9
   render() {
11
   render() {
10
     return (
12
     return (
11
       <View style={styles.root}>
13
       <View style={styles.root}>
12
-        <Text style={styles.h1}>Test view</Text>
13
-        <Button title="OK" onPress={this.onCLickOk} />
14
+        <Text style={styles.h1} testID={testIDs.DIALOG_HEADER}>Test view</Text>
15
+        <Button title="OK" testID={testIDs.OK_BUTTON} onPress={() => this.onCLickOk()} />
14
       </View>
16
       </View>
15
     );
17
     );
16
   }
18
   }
17
 
19
 
18
   onCLickOk() {
20
   onCLickOk() {
19
-    Navigation.dismissOverlay();
21
+    Navigation.dismissOverlay(this.props.componentId);
20
   }
22
   }
21
 }
23
 }
22
 
24
 
23
 const styles = {
25
 const styles = {
24
   root: {
26
   root: {
25
-    flex: 1,
26
     backgroundColor: 'green',
27
     backgroundColor: 'green',
27
     justifyContent: 'center',
28
     justifyContent: 'center',
28
-    alignItems: 'center'
29
+    alignItems: 'center',
30
+    height: 100,
31
+    bottom: 0,
32
+    position: 'absolute',
33
+    left: 0,
34
+    right: 0
29
   },
35
   },
30
   h1: {
36
   h1: {
31
     fontSize: 24,
37
     fontSize: 24,

+ 13
- 0
playground/src/screens/OptionsScreen.js View File

16
       topBar: {
16
       topBar: {
17
         title: 'Static Title',
17
         title: 'Static Title',
18
         textColor: 'black',
18
         textColor: 'black',
19
+        drawUnder: false,
19
         largeTitle: false,
20
         largeTitle: false,
20
         hidden: false,
21
         hidden: false,
21
         textFontSize: 16,
22
         textFontSize: 16,
48
     this.onClickTopBarTransparent = this.onClickTopBarTransparent.bind(this);
49
     this.onClickTopBarTransparent = this.onClickTopBarTransparent.bind(this);
49
     this.onClickTopBarOpaque = this.onClickTopBarOpaque.bind(this);
50
     this.onClickTopBarOpaque = this.onClickTopBarOpaque.bind(this);
50
     this.onClickCustomTranstition = this.onClickCustomTranstition.bind(this);
51
     this.onClickCustomTranstition = this.onClickCustomTranstition.bind(this);
52
+    this.onClickShowOverlay = this.onClickShowOverlay.bind(this);
51
     this.onClickPushDefaultOptionsScreen = this.onClickPushDefaultOptionsScreen.bind(this);
53
     this.onClickPushDefaultOptionsScreen = this.onClickPushDefaultOptionsScreen.bind(this);
52
   }
54
   }
53
 
55
 
64
         <Button title="Custom Transition" onPress={this.onClickCustomTranstition} />
66
         <Button title="Custom Transition" onPress={this.onClickCustomTranstition} />
65
         <Button title="Show custom alert" testID={testIDs.SHOW_CUSTOM_ALERT_BUTTON} onPress={this.onClickAlert} />
67
         <Button title="Show custom alert" testID={testIDs.SHOW_CUSTOM_ALERT_BUTTON} onPress={this.onClickAlert} />
66
         <Button title="Show snackbar" testID={testIDs.SHOW_SNACKBAR_BUTTON} onPress={this.onClickSnackbar} />
68
         <Button title="Show snackbar" testID={testIDs.SHOW_SNACKBAR_BUTTON} onPress={this.onClickSnackbar} />
69
+        <Button title="Show overlay" testID={testIDs.SHOW_OVERLAY_BUTTON} onPress={() => this.onClickShowOverlay(true)} />
70
+        <Button title="Show touch through overlay" testID={testIDs.SHOW_TOUCH_THROUGH_OVERLAY_BUTTON} onPress={() => this.onClickShowOverlay(false)} />
67
         <Button title="Push Default Options Screen" testID={testIDs.PUSH_DEFAULT_OPTIONS_BUTTON} onPress={this.onClickPushDefaultOptionsScreen} />
71
         <Button title="Push Default Options Screen" testID={testIDs.PUSH_DEFAULT_OPTIONS_BUTTON} onPress={this.onClickPushDefaultOptionsScreen} />
68
         <Text style={styles.footer}>{`this.props.containerId = ${this.props.containerId}`}</Text>
72
         <Text style={styles.footer}>{`this.props.containerId = ${this.props.containerId}`}</Text>
69
       </View>
73
       </View>
190
     });
194
     });
191
   }
195
   }
192
 
196
 
197
+  onClickShowOverlay(interceptTouches) {
198
+    Navigation.showOverlay({
199
+      component: {
200
+        name: 'navigation.playground.CustomDialog',
201
+        options: { interceptTouches }
202
+      }
203
+    });
204
+  }
205
+
193
   onClickPushDefaultOptionsScreen() {
206
   onClickPushDefaultOptionsScreen() {
194
     Navigation.setDefaultOptions({
207
     Navigation.setDefaultOptions({
195
       topBar: {
208
       topBar: {

+ 5
- 1
playground/src/testIDs.js View File

46
   SHOW_BOTTOM_TABS_BUTTON: `SHOW_BOTTOM_TABS_BUTTON`,
46
   SHOW_BOTTOM_TABS_BUTTON: `SHOW_BOTTOM_TABS_BUTTON`,
47
   FIRST_TAB_BAR_BUTTON: `FIRST_TAB_BAR_BUTTON`,
47
   FIRST_TAB_BAR_BUTTON: `FIRST_TAB_BAR_BUTTON`,
48
   SECOND_TAB_BAR_BUTTON: `SECOND_TAB_BAR_BUTTON`,
48
   SECOND_TAB_BAR_BUTTON: `SECOND_TAB_BAR_BUTTON`,
49
+  SHOW_OVERLAY_BUTTON: `SHOW_OVERLAY_BUTTON`,
50
+  SHOW_TOUCH_THROUGH_OVERLAY_BUTTON: `SHOW_TOUCH_THROUGH_OVERLAY_BUTTON`,
51
+  OK_BUTTON: `OK_BUTTON`,
49
 
52
 
50
   // Elements
53
   // Elements
51
   SCROLLVIEW_ELEMENT: `SCROLLVIEW_ELEMENT`,
54
   SCROLLVIEW_ELEMENT: `SCROLLVIEW_ELEMENT`,
57
   PUSHED_SCREEN_HEADER: `PUSHED_SCREEN_HEADER`,
60
   PUSHED_SCREEN_HEADER: `PUSHED_SCREEN_HEADER`,
58
   OPTIONS_SCREEN_HEADER: `OPTIONS_SCREEN_HEADER`,
61
   OPTIONS_SCREEN_HEADER: `OPTIONS_SCREEN_HEADER`,
59
   MODAL_SCREEN: `MODAL_SCREEN`,
62
   MODAL_SCREEN: `MODAL_SCREEN`,
60
-  CENTERED_TEXT_HEADER: `CENTERED_TEXT_HEADER`
63
+  CENTERED_TEXT_HEADER: `CENTERED_TEXT_HEADER`,
64
+  DIALOG_HEADER: `DIALOG_HEADER`
61
 };
65
 };