Browse Source

Added setStackRoot top level api

yogevbd 6 years ago
parent
commit
be2dd0539a

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

48
 	}];
48
 	}];
49
 }
49
 }
50
 
50
 
51
+RCT_EXPORT_METHOD(setStackRoot:(NSString*)componentId layout:(NSDictionary*)layout resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
52
+	[_commandsHandler setStackRoot:componentId layout:layout completion:^{
53
+		resolve(componentId);
54
+	}];
55
+}
56
+
51
 RCT_EXPORT_METHOD(popTo:(NSString*)componentId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
57
 RCT_EXPORT_METHOD(popTo:(NSString*)componentId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
52
 	[_commandsHandler popTo:componentId completion:^{
58
 	[_commandsHandler popTo:componentId completion:^{
53
 		resolve(componentId);
59
 		resolve(componentId);

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

22
 
22
 
23
 -(void) popToRoot:(NSString*)componentId completion:(RNNTransitionCompletionBlock)completion;
23
 -(void) popToRoot:(NSString*)componentId completion:(RNNTransitionCompletionBlock)completion;
24
 
24
 
25
+-(void)setStackRoot:(NSString*)componentId layout:(NSDictionary*)layout completion:(RNNTransitionCompletionBlock)completion;
26
+
25
 -(void) showModal:(NSDictionary*)layout completion:(RNNTransitionCompletionBlock)completion;
27
 -(void) showModal:(NSDictionary*)layout completion:(RNNTransitionCompletionBlock)completion;
26
 
28
 
27
 -(void) dismissModal:(NSString*)componentId completion:(RNNTransitionCompletionBlock)completion;
29
 -(void) dismissModal:(NSString*)componentId completion:(RNNTransitionCompletionBlock)completion;

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

59
 	[_controllerFactory setDefaultOptionsDict:optionsDict];
59
 	[_controllerFactory setDefaultOptionsDict:optionsDict];
60
 }
60
 }
61
 
61
 
62
--(void) push:(NSString*)componentId layout:(NSDictionary*)layout completion:(RNNTransitionCompletionBlock)completion {
62
+-(void)push:(NSString*)componentId layout:(NSDictionary*)layout completion:(RNNTransitionCompletionBlock)completion {
63
 	[self assertReady];
63
 	[self assertReady];
64
 	
64
 	
65
 	UIViewController<RNNRootViewProtocol> *newVc = [_controllerFactory createLayoutAndSaveToStore:layout];
65
 	UIViewController<RNNRootViewProtocol> *newVc = [_controllerFactory createLayoutAndSaveToStore:layout];
68
 	}];
68
 	}];
69
 }
69
 }
70
 
70
 
71
+-(void)setStackRoot:(NSString*)componentId layout:(NSDictionary*)layout completion:(RNNTransitionCompletionBlock)completion {
72
+	[self assertReady];
73
+	
74
+	UIViewController<RNNRootViewProtocol> *newVc = [_controllerFactory createLayoutAndSaveToStore:layout];
75
+	[_navigationStackManager setRoot:newVc fromComponent:componentId completion:^{
76
+		completion();
77
+	}];
78
+}
79
+
71
 -(void)pop:(NSString*)componentId options:(NSDictionary*)options completion:(RNNTransitionCompletionBlock)completion {
80
 -(void)pop:(NSString*)componentId options:(NSDictionary*)options completion:(RNNTransitionCompletionBlock)completion {
72
 	[self assertReady];
81
 	[self assertReady];
73
 	[CATransaction begin];
82
 	[CATransaction begin];

+ 1
- 0
lib/ios/RNNNavigationStackManager.h View File

14
 -(void)pop:(NSString*)componentId withTransitionOptions:(RNNAnimationOptions*)transitionOptions;
14
 -(void)pop:(NSString*)componentId withTransitionOptions:(RNNAnimationOptions*)transitionOptions;
15
 -(void)popTo:(NSString*)componentId;
15
 -(void)popTo:(NSString*)componentId;
16
 -(void)popToRoot:(NSString*)componentId;
16
 -(void)popToRoot:(NSString*)componentId;
17
+-(void)setRoot:(UIViewController<RNNRootViewProtocol> *)newRoot fromComponent:(NSString *)componentId completion:(RNNTransitionCompletionBlock)completion;
17
 
18
 
18
 @end
19
 @end

+ 16
- 1
lib/ios/RNNNavigationStackManager.m View File

96
 	}
96
 	}
97
 }
97
 }
98
 
98
 
99
--(void) popToRoot:(NSString*)componentId {
99
+-(void)popToRoot:(NSString*)componentId {
100
 	UIViewController* vc = [_store findComponentForId:componentId];
100
 	UIViewController* vc = [_store findComponentForId:componentId];
101
 	UINavigationController* nvc = [vc navigationController];
101
 	UINavigationController* nvc = [vc navigationController];
102
 	NSArray* poppedVCs = [nvc popToRootViewControllerAnimated:YES];
102
 	NSArray* poppedVCs = [nvc popToRootViewControllerAnimated:YES];
103
 	[self removePopedViewControllers:poppedVCs];
103
 	[self removePopedViewControllers:poppedVCs];
104
 }
104
 }
105
 
105
 
106
+-(void)setRoot:(UIViewController<RNNRootViewProtocol> *)newRoot fromComponent:(NSString *)componentId completion:(RNNTransitionCompletionBlock)completion {
107
+	UIViewController* vc = [_store findComponentForId:componentId];
108
+	UINavigationController* nvc = [vc navigationController];
109
+	[CATransaction begin];
110
+	[CATransaction setCompletionBlock:^{
111
+		if (completion) {
112
+			completion();
113
+		}
114
+	}];
115
+	
116
+	[nvc setViewControllers:@[newRoot] animated:newRoot.options.animated];
117
+	
118
+	[CATransaction commit];
119
+}
120
+
106
 -(void)removePopedViewControllers:(NSArray*)viewControllers {
121
 -(void)removePopedViewControllers:(NSArray*)viewControllers {
107
 	for (UIViewController *popedVC in viewControllers) {
122
 	for (UIViewController *popedVC in viewControllers) {
108
 		[_store removeComponentByViewControllerInstance:popedVC];
123
 		[_store removeComponentByViewControllerInstance:popedVC];

+ 7
- 0
lib/src/Navigation.ts View File

123
     return this.commands.popToRoot(componentId);
123
     return this.commands.popToRoot(componentId);
124
   }
124
   }
125
 
125
 
126
+  /**
127
+   * Sets new root component to stack.
128
+   */
129
+  public setStackRoot(componentId: string, layout): Promise<any> {
130
+    return this.commands.setStackRoot(componentId, layout);
131
+  }
132
+
126
   /**
133
   /**
127
    * Show overlay on top of the entire app
134
    * Show overlay on top of the entire app
128
    */
135
    */

+ 4
- 0
lib/src/adapters/NativeCommandsSender.ts View File

34
     return this.nativeCommandsModule.popToRoot(componentId);
34
     return this.nativeCommandsModule.popToRoot(componentId);
35
   }
35
   }
36
 
36
 
37
+  setStackRoot(onComponentId: string, layout: object) {
38
+    return this.nativeCommandsModule.setStackRoot(onComponentId, layout);
39
+  }
40
+
37
   showModal(layout: object) {
41
   showModal(layout: object) {
38
     return this.nativeCommandsModule.showModal(layout);
42
     return this.nativeCommandsModule.showModal(layout);
39
   }
43
   }

+ 18
- 0
lib/src/commands/Commands.test.ts View File

245
     });
245
     });
246
   });
246
   });
247
 
247
 
248
+  describe('setStackRoot', () => {
249
+    it('parses into correct layout node and sends to native', () => {
250
+      uut.setStackRoot('theComponentId', { component: { name: 'com.example.MyScreen' } });
251
+      expect(mockCommandsSender.setStackRoot).toHaveBeenCalledTimes(1);
252
+      expect(mockCommandsSender.setStackRoot).toHaveBeenCalledWith('theComponentId', {
253
+        type: 'Component',
254
+        id: 'Component+UNIQUE_ID',
255
+        data: {
256
+          name: 'com.example.MyScreen',
257
+          options: {}
258
+        },
259
+        children: []
260
+      });
261
+    });
262
+  });
263
+
248
   describe('showOverlay', () => {
264
   describe('showOverlay', () => {
249
     it('sends command to native after parsing into a correct layout tree', () => {
265
     it('sends command to native after parsing into a correct layout tree', () => {
250
       uut.showOverlay({
266
       uut.showOverlay({
352
         pop: ['id', {}],
368
         pop: ['id', {}],
353
         popTo: ['id'],
369
         popTo: ['id'],
354
         popToRoot: ['id'],
370
         popToRoot: ['id'],
371
+        setStackRoot: ['id', {}],
355
         showOverlay: [{}],
372
         showOverlay: [{}],
356
         dismissOverlay: ['id'],
373
         dismissOverlay: ['id'],
357
       };
374
       };
366
         pop: { componentId: 'id', options: {} },
383
         pop: { componentId: 'id', options: {} },
367
         popTo: { componentId: 'id' },
384
         popTo: { componentId: 'id' },
368
         popToRoot: { componentId: 'id' },
385
         popToRoot: { componentId: 'id' },
386
+        setStackRoot: { componentId: 'id', layout: 'parsed' },
369
         showOverlay: { layout: 'parsed' },
387
         showOverlay: { layout: 'parsed' },
370
         dismissOverlay: { componentId: 'id' },
388
         dismissOverlay: { componentId: 'id' },
371
       };
389
       };

+ 11
- 0
lib/src/commands/Commands.ts View File

90
     return result;
90
     return result;
91
   }
91
   }
92
 
92
 
93
+  public setStackRoot(componentId, simpleApi) {
94
+    const input = _.cloneDeep(simpleApi);
95
+
96
+    const layout = this.layoutTreeParser.parse(input);
97
+    this.layoutTreeCrawler.crawl(layout);
98
+
99
+    const result = this.nativeCommandsSender.setStackRoot(componentId, layout);
100
+    this.commandsObserver.notify('setStackRoot', { componentId, layout });
101
+    return result;
102
+  }
103
+
93
   public showOverlay(simpleApi) {
104
   public showOverlay(simpleApi) {
94
     const input = _.cloneDeep(simpleApi);
105
     const input = _.cloneDeep(simpleApi);
95
 
106
 

+ 21
- 0
playground/src/screens/PushedScreen.js View File

24
     this.onClickPopPrevious = this.onClickPopPrevious.bind(this);
24
     this.onClickPopPrevious = this.onClickPopPrevious.bind(this);
25
     this.onClickPopToFirstPosition = this.onClickPopToFirstPosition.bind(this);
25
     this.onClickPopToFirstPosition = this.onClickPopToFirstPosition.bind(this);
26
     this.onClickPopToRoot = this.onClickPopToRoot.bind(this);
26
     this.onClickPopToRoot = this.onClickPopToRoot.bind(this);
27
+    this.onClickSetStackRoot = this.onClickSetStackRoot.bind(this);
27
   }
28
   }
28
 
29
 
29
   render() {
30
   render() {
36
         <Button title='Pop' testID={testIDs.POP_BUTTON} onPress={this.onClickPop} />
37
         <Button title='Pop' testID={testIDs.POP_BUTTON} onPress={this.onClickPop} />
37
         <Button title='Pop Previous' testID={testIDs.POP_PREVIOUS_BUTTON} onPress={this.onClickPopPrevious} />
38
         <Button title='Pop Previous' testID={testIDs.POP_PREVIOUS_BUTTON} onPress={this.onClickPopPrevious} />
38
         <Button title='Pop To Root' testID={testIDs.POP_TO_ROOT} onPress={this.onClickPopToRoot} />
39
         <Button title='Pop To Root' testID={testIDs.POP_TO_ROOT} onPress={this.onClickPopToRoot} />
40
+        <Button title='Set Stack Root' testID={testIDs.SET_STACK_ROOT_BUTTON} onPress={this.onClickSetStackRoot} />
39
         {stackPosition > 2 && <Button title='Pop To Stack Position 1' testID={testIDs.POP_STACK_POSITION_ONE_BUTTON} onPress={this.onClickPopToFirstPosition} />}
41
         {stackPosition > 2 && <Button title='Pop To Stack Position 1' testID={testIDs.POP_STACK_POSITION_ONE_BUTTON} onPress={this.onClickPopToFirstPosition} />}
40
         <Text style={styles.footer}>{`this.props.componentId = ${this.props.componentId}`}</Text>
42
         <Text style={styles.footer}>{`this.props.componentId = ${this.props.componentId}`}</Text>
41
       </View>
43
       </View>
77
     await Navigation.popToRoot(this.props.componentId);
79
     await Navigation.popToRoot(this.props.componentId);
78
   }
80
   }
79
 
81
 
82
+  async onClickSetStackRoot() {
83
+    await Navigation.setStackRoot(this.props.componentId, {
84
+      component: {
85
+        name: 'navigation.playground.PushedScreen',
86
+        passProps: {
87
+          stackPosition: this.getStackPosition() + 1,
88
+          previousScreenIds: _.concat([], this.props.previousScreenIds || [], this.props.componentId)
89
+        },
90
+        options: {
91
+          topBar: {
92
+            title: {
93
+              text: `Pushed ${this.getStackPosition() + 1}`
94
+            }
95
+          }
96
+        }
97
+      }
98
+    });
99
+  }
100
+
80
   getStackPosition() {
101
   getStackPosition() {
81
     return this.props.stackPosition || 1;
102
     return this.props.stackPosition || 1;
82
   }
103
   }

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

58
   COMPLEX_LAYOUT_BUTTON: `COMPLEX_LAYOUT_BUTTON`,
58
   COMPLEX_LAYOUT_BUTTON: `COMPLEX_LAYOUT_BUTTON`,
59
   EXTERNAL_COMPONENT_IN_STACK: `EXTERNAL_COMPONENT_IN_STACK`,
59
   EXTERNAL_COMPONENT_IN_STACK: `EXTERNAL_COMPONENT_IN_STACK`,
60
   EXTERNAL_COMPONENT_IN_DEEP_STACK: `EXTERNAL_COMPONENT_IN_DEEP_STACK`,
60
   EXTERNAL_COMPONENT_IN_DEEP_STACK: `EXTERNAL_COMPONENT_IN_DEEP_STACK`,
61
+  SET_STACK_ROOT_BUTTON: `SET_STACK_ROOT_BUTTON`,
61
 
62
 
62
   // Elements
63
   // Elements
63
   SCROLLVIEW_ELEMENT: `SCROLLVIEW_ELEMENT`,
64
   SCROLLVIEW_ELEMENT: `SCROLLVIEW_ELEMENT`,