Sfoglia il codice sorgente

Added setStackRoot top level api

yogevbd 6 anni fa
parent
commit
be2dd0539a

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

@@ -48,6 +48,12 @@ RCT_EXPORT_METHOD(pop:(NSString*)componentId options:(NSDictionary*)options reso
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 57
 RCT_EXPORT_METHOD(popTo:(NSString*)componentId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
52 58
 	[_commandsHandler popTo:componentId completion:^{
53 59
 		resolve(componentId);

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

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

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

@@ -59,7 +59,7 @@
59 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 63
 	[self assertReady];
64 64
 	
65 65
 	UIViewController<RNNRootViewProtocol> *newVc = [_controllerFactory createLayoutAndSaveToStore:layout];
@@ -68,6 +68,15 @@
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 80
 -(void)pop:(NSString*)componentId options:(NSDictionary*)options completion:(RNNTransitionCompletionBlock)completion {
72 81
 	[self assertReady];
73 82
 	[CATransaction begin];

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

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

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

@@ -96,13 +96,28 @@ dispatch_queue_t RCTGetUIManagerQueue(void);
96 96
 	}
97 97
 }
98 98
 
99
--(void) popToRoot:(NSString*)componentId {
99
+-(void)popToRoot:(NSString*)componentId {
100 100
 	UIViewController* vc = [_store findComponentForId:componentId];
101 101
 	UINavigationController* nvc = [vc navigationController];
102 102
 	NSArray* poppedVCs = [nvc popToRootViewControllerAnimated:YES];
103 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 121
 -(void)removePopedViewControllers:(NSArray*)viewControllers {
107 122
 	for (UIViewController *popedVC in viewControllers) {
108 123
 		[_store removeComponentByViewControllerInstance:popedVC];

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

@@ -123,6 +123,13 @@ export class Navigation {
123 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 134
    * Show overlay on top of the entire app
128 135
    */

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

@@ -34,6 +34,10 @@ export class NativeCommandsSender {
34 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 41
   showModal(layout: object) {
38 42
     return this.nativeCommandsModule.showModal(layout);
39 43
   }

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

@@ -245,6 +245,22 @@ describe('Commands', () => {
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 264
   describe('showOverlay', () => {
249 265
     it('sends command to native after parsing into a correct layout tree', () => {
250 266
       uut.showOverlay({
@@ -352,6 +368,7 @@ describe('Commands', () => {
352 368
         pop: ['id', {}],
353 369
         popTo: ['id'],
354 370
         popToRoot: ['id'],
371
+        setStackRoot: ['id', {}],
355 372
         showOverlay: [{}],
356 373
         dismissOverlay: ['id'],
357 374
       };
@@ -366,6 +383,7 @@ describe('Commands', () => {
366 383
         pop: { componentId: 'id', options: {} },
367 384
         popTo: { componentId: 'id' },
368 385
         popToRoot: { componentId: 'id' },
386
+        setStackRoot: { componentId: 'id', layout: 'parsed' },
369 387
         showOverlay: { layout: 'parsed' },
370 388
         dismissOverlay: { componentId: 'id' },
371 389
       };

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

@@ -90,6 +90,17 @@ export class Commands {
90 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 104
   public showOverlay(simpleApi) {
94 105
     const input = _.cloneDeep(simpleApi);
95 106
 

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

@@ -24,6 +24,7 @@ class PushedScreen extends Component {
24 24
     this.onClickPopPrevious = this.onClickPopPrevious.bind(this);
25 25
     this.onClickPopToFirstPosition = this.onClickPopToFirstPosition.bind(this);
26 26
     this.onClickPopToRoot = this.onClickPopToRoot.bind(this);
27
+    this.onClickSetStackRoot = this.onClickSetStackRoot.bind(this);
27 28
   }
28 29
 
29 30
   render() {
@@ -36,6 +37,7 @@ class PushedScreen extends Component {
36 37
         <Button title='Pop' testID={testIDs.POP_BUTTON} onPress={this.onClickPop} />
37 38
         <Button title='Pop Previous' testID={testIDs.POP_PREVIOUS_BUTTON} onPress={this.onClickPopPrevious} />
38 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 41
         {stackPosition > 2 && <Button title='Pop To Stack Position 1' testID={testIDs.POP_STACK_POSITION_ONE_BUTTON} onPress={this.onClickPopToFirstPosition} />}
40 42
         <Text style={styles.footer}>{`this.props.componentId = ${this.props.componentId}`}</Text>
41 43
       </View>
@@ -77,6 +79,25 @@ class PushedScreen extends Component {
77 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 101
   getStackPosition() {
81 102
     return this.props.stackPosition || 1;
82 103
   }

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

@@ -58,6 +58,7 @@ module.exports = {
58 58
   COMPLEX_LAYOUT_BUTTON: `COMPLEX_LAYOUT_BUTTON`,
59 59
   EXTERNAL_COMPONENT_IN_STACK: `EXTERNAL_COMPONENT_IN_STACK`,
60 60
   EXTERNAL_COMPONENT_IN_DEEP_STACK: `EXTERNAL_COMPONENT_IN_DEEP_STACK`,
61
+  SET_STACK_ROOT_BUTTON: `SET_STACK_ROOT_BUTTON`,
61 62
 
62 63
   // Elements
63 64
   SCROLLVIEW_ELEMENT: `SCROLLVIEW_ELEMENT`,