Browse Source

Merge options (#3930)

mergeOptions support for commands
Guy Carmeli 6 years ago
parent
commit
2c7dccc677
No account linked to committer's email address
26 changed files with 241 additions and 180 deletions
  1. 1
    0
      lib/android/app/src/main/java/com/reactnativenavigation/parse/Options.java
  2. 22
    16
      lib/android/app/src/main/java/com/reactnativenavigation/react/NavigationModule.java
  3. 1
    0
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ChildController.java
  4. 1
    0
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ComponentViewController.java
  5. 8
    8
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/Navigator.java
  6. 2
    12
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ViewController.java
  7. 3
    1
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/modal/ModalStack.java
  8. 9
    8
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackController.java
  9. 8
    0
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/ComponentViewControllerTest.java
  10. 2
    2
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/FloatingActionButtonTest.java
  11. 13
    13
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/NavigatorTest.java
  12. 1
    1
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/TopTabsViewControllerTest.java
  13. 7
    0
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/child/ChildControllerTest.java
  14. 18
    5
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/modal/ModalStackTest.java
  15. 46
    19
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/StackControllerTest.java
  16. 10
    10
      lib/ios/RNNBridgeModule.m
  17. 14
    14
      lib/ios/RNNCommandsHandler.h
  18. 15
    11
      lib/ios/RNNCommandsHandler.m
  19. 1
    1
      lib/ios/RNNModalManager.h
  20. 2
    2
      lib/ios/RNNModalManager.m
  21. 3
    3
      lib/ios/ReactNativeNavigationTests/RNNCommandsHandlerTest.m
  22. 4
    4
      lib/ios/ReactNativeNavigationTests/RNNModalManagerTest.m
  23. 10
    10
      lib/src/Navigation.ts
  24. 8
    8
      lib/src/adapters/NativeCommandsSender.ts
  25. 17
    17
      lib/src/commands/Commands.test.ts
  26. 15
    15
      lib/src/commands/Commands.ts

+ 1
- 0
lib/android/app/src/main/java/com/reactnativenavigation/parse/Options.java View File

10
 import org.json.JSONObject;
10
 import org.json.JSONObject;
11
 
11
 
12
 public class Options {
12
 public class Options {
13
+    public static final Options EMPTY = new Options();
13
 
14
 
14
     @NonNull
15
     @NonNull
15
     public static Options parse(TypefaceLoader typefaceManager, JSONObject json) {
16
     public static Options parse(TypefaceLoader typefaceManager, JSONObject json) {

+ 22
- 16
lib/android/app/src/main/java/com/reactnativenavigation/react/NavigationModule.java View File

1
 package com.reactnativenavigation.react;
1
 package com.reactnativenavigation.react;
2
 
2
 
3
 import android.support.annotation.NonNull;
3
 import android.support.annotation.NonNull;
4
+import android.support.annotation.Nullable;
4
 
5
 
5
 import com.facebook.react.ReactInstanceManager;
6
 import com.facebook.react.ReactInstanceManager;
6
 import com.facebook.react.bridge.Arguments;
7
 import com.facebook.react.bridge.Arguments;
70
 
71
 
71
 	@ReactMethod
72
 	@ReactMethod
72
 	public void setDefaultOptions(ReadableMap options) {
73
 	public void setDefaultOptions(ReadableMap options) {
73
-        final Options defaultOptions = Options.parse(new TypefaceLoader(activity()), JSONParser.parse(options));
74
-        handle(() -> navigator().setDefaultOptions(defaultOptions));
74
+        handle(() -> navigator().setDefaultOptions(parse(options)));
75
     }
75
     }
76
 
76
 
77
 	@ReactMethod
77
 	@ReactMethod
78
-	public void mergeOptions(String onComponentId, ReadableMap options) {
79
-		final Options navOptions = Options.parse(new TypefaceLoader(activity()), JSONParser.parse(options));
80
-		handle(() -> navigator().mergeOptions(onComponentId, navOptions));
78
+	public void mergeOptions(String onComponentId, @Nullable ReadableMap options) {
79
+		handle(() -> navigator().mergeOptions(onComponentId, parse(options)));
81
 	}
80
 	}
82
 
81
 
83
 	@ReactMethod
82
 	@ReactMethod
99
     }
98
     }
100
 
99
 
101
 	@ReactMethod
100
 	@ReactMethod
102
-	public void pop(String commandId, String componentId, ReadableMap options, Promise promise) {
103
-		handle(() -> navigator().pop(componentId, new NativeCommandListener(commandId, promise, eventEmitter, now)));
101
+	public void pop(String commandId, String componentId, @Nullable ReadableMap mergeOptions, Promise promise) {
102
+		handle(() -> navigator().pop(componentId, parse(mergeOptions), new NativeCommandListener(commandId, promise, eventEmitter, now)));
104
 	}
103
 	}
105
 
104
 
106
 	@ReactMethod
105
 	@ReactMethod
107
-	public void popTo(String commandId, String componentId, Promise promise) {
108
-		handle(() -> navigator().popTo(componentId, new NativeCommandListener(commandId, promise, eventEmitter, now)));
106
+	public void popTo(String commandId, String componentId, @Nullable ReadableMap mergeOptions, Promise promise) {
107
+		handle(() -> navigator().popTo(componentId, parse(mergeOptions), new NativeCommandListener(commandId, promise, eventEmitter, now)));
109
 	}
108
 	}
110
 
109
 
111
 	@ReactMethod
110
 	@ReactMethod
112
-	public void popToRoot(String commandId, String componentId, Promise promise) {
113
-		handle(() -> navigator().popToRoot(componentId, new NativeCommandListener(commandId, promise, eventEmitter, now)));
111
+	public void popToRoot(String commandId, String componentId, @Nullable ReadableMap mergeOptions, Promise promise) {
112
+		handle(() -> navigator().popToRoot(componentId, parse(mergeOptions), new NativeCommandListener(commandId, promise, eventEmitter, now)));
114
 	}
113
 	}
115
 
114
 
116
 	@ReactMethod
115
 	@ReactMethod
123
 	}
122
 	}
124
 
123
 
125
 	@ReactMethod
124
 	@ReactMethod
126
-	public void dismissModal(String commandId, String componentId, Promise promise) {
127
-		handle(() -> navigator().dismissModal(componentId, new NativeCommandListener(commandId, promise, eventEmitter, now)));
125
+	public void dismissModal(String commandId, String componentId, @Nullable ReadableMap mergeOptions, Promise promise) {
126
+		handle(() -> {
127
+            navigator().mergeOptions(componentId, parse(mergeOptions));
128
+            navigator().dismissModal(componentId, new NativeCommandListener(commandId, promise, eventEmitter, now));
129
+        });
128
 	}
130
 	}
129
 
131
 
130
-	@ReactMethod
131
-	public void dismissAllModals(String commandId, Promise promise) {
132
-		handle(() -> navigator().dismissAllModals(new NativeCommandListener(commandId, promise, eventEmitter, now)));
132
+    @ReactMethod
133
+	public void dismissAllModals(String commandId, @Nullable ReadableMap mergeOptions, Promise promise) {
134
+		handle(() -> navigator().dismissAllModals(parse(mergeOptions), new NativeCommandListener(commandId, promise, eventEmitter, now)));
133
 	}
135
 	}
134
 
136
 
135
 	@ReactMethod
137
 	@ReactMethod
161
         );
163
         );
162
 	}
164
 	}
163
 
165
 
166
+    private  Options parse(@Nullable ReadableMap mergeOptions) {
167
+        return mergeOptions == null ? Options.EMPTY : Options.parse(new TypefaceLoader(activity()), JSONParser.parse(mergeOptions));
168
+    }
169
+
164
 	private Map<String, ExternalComponentCreator> externalComponentCreator() {
170
 	private Map<String, ExternalComponentCreator> externalComponentCreator() {
165
         return ((NavigationApplication) activity().getApplication()).getExternalComponents();
171
         return ((NavigationApplication) activity().getApplication()).getExternalComponents();
166
     }
172
     }

+ 1
- 0
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ChildController.java View File

55
 
55
 
56
     @Override
56
     @Override
57
     public void mergeOptions(Options options) {
57
     public void mergeOptions(Options options) {
58
+        if (options == Options.EMPTY) return;
58
         presenter.mergeOptions(getView(), options);
59
         presenter.mergeOptions(getView(), options);
59
         super.mergeOptions(options);
60
         super.mergeOptions(options);
60
     }
61
     }

+ 1
- 0
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ComponentViewController.java View File

63
 
63
 
64
     @Override
64
     @Override
65
     public void mergeOptions(Options options) {
65
     public void mergeOptions(Options options) {
66
+        if (options == Options.EMPTY) return;
66
         performOnParentController(parentController -> parentController.mergeChildOptions(options, this, getView()));
67
         performOnParentController(parentController -> parentController.mergeChildOptions(options, this, getView()));
67
         super.mergeOptions(options);
68
         super.mergeOptions(options);
68
     }
69
     }

+ 8
- 8
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/Navigator.java View File

156
         applyOnStack(id, listener, stack -> stack.setRoot(viewController, listener));
156
         applyOnStack(id, listener, stack -> stack.setRoot(viewController, listener));
157
     }
157
     }
158
 
158
 
159
-    public void pop(String id, CommandListener listener) {
160
-        applyOnStack(id, listener, stack -> stack.pop(listener));
159
+    public void pop(String id, Options mergeOptions, CommandListener listener) {
160
+        applyOnStack(id, listener, stack -> stack.pop(mergeOptions, listener));
161
     }
161
     }
162
 
162
 
163
-    public void popToRoot(final String id, CommandListener listener) {
164
-        applyOnStack(id, listener, stack -> stack.popToRoot(listener));
163
+    public void popToRoot(final String id, Options mergeOptions, CommandListener listener) {
164
+        applyOnStack(id, listener, stack -> stack.popToRoot(mergeOptions, listener));
165
     }
165
     }
166
 
166
 
167
-    public void popTo(final String id, CommandListener listener) {
167
+    public void popTo(final String id, Options mergeOptions, CommandListener listener) {
168
         ViewController target = findControllerById(id);
168
         ViewController target = findControllerById(id);
169
         if (target != null) {
169
         if (target != null) {
170
-            target.performOnParentStack(stack -> ((StackController) stack).popTo(target, listener));
170
+            target.performOnParentStack(stack -> ((StackController) stack).popTo(target, mergeOptions, listener));
171
         } else {
171
         } else {
172
             listener.onError("Failed to execute stack command. Stack by " + id + " not found.");
172
             listener.onError("Failed to execute stack command. Stack by " + id + " not found.");
173
         }
173
         }
185
         modalStack.dismissModal(componentId, root, listener);
185
         modalStack.dismissModal(componentId, root, listener);
186
     }
186
     }
187
 
187
 
188
-    public void dismissAllModals(CommandListener listener) {
189
-        modalStack.dismissAllModals(listener, root);
188
+    public void dismissAllModals(Options mergeOptions, CommandListener listener) {
189
+        modalStack.dismissAllModals(root, mergeOptions, listener);
190
     }
190
     }
191
 
191
 
192
     public void showOverlay(ViewController overlay, CommandListener listener) {
192
     public void showOverlay(ViewController overlay, CommandListener listener) {

+ 2
- 12
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ViewController.java View File

137
         this.parentController = parentController;
137
         this.parentController = parentController;
138
     }
138
     }
139
 
139
 
140
-    boolean performOnParentStack(Task<StackController> task) {
140
+    void performOnParentStack(Task<StackController> task) {
141
         if (parentController instanceof StackController) {
141
         if (parentController instanceof StackController) {
142
             task.run((StackController) parentController);
142
             task.run((StackController) parentController);
143
-            return true;
144
-        }
145
-        if (this instanceof StackController) {
143
+        } else if (this instanceof StackController) {
146
             task.run((StackController) this);
144
             task.run((StackController) this);
147
-            return true;
148
-        }
149
-        return false;
150
-    }
151
-
152
-    void performOnParentStack(Task accept, Runnable reject) {
153
-        if (!performOnParentStack(accept)) {
154
-            reject.run();
155
         }
145
         }
156
     }
146
     }
157
 
147
 

+ 3
- 1
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/modal/ModalStack.java View File

78
         }
78
         }
79
     }
79
     }
80
 
80
 
81
-    public void dismissAllModals(CommandListener listener, ViewController root) {
81
+    public void dismissAllModals(ViewController root, Options mergeOptions, CommandListener listener) {
82
         if (modals.isEmpty()) {
82
         if (modals.isEmpty()) {
83
             listener.onError("Nothing to dismiss");
83
             listener.onError("Nothing to dismiss");
84
             return;
84
             return;
87
         String topModalId = peek().getId();
87
         String topModalId = peek().getId();
88
         int modalsDismissed = size();
88
         int modalsDismissed = size();
89
 
89
 
90
+        peek().mergeOptions(mergeOptions);
91
+
90
         while (!modals.isEmpty()) {
92
         while (!modals.isEmpty()) {
91
             if (modals.size() == 1) {
93
             if (modals.size() == 1) {
92
                 dismissModal(modals.get(0).getId(), root, new CommandListenerAdapter(listener) {
94
                 dismissModal(modals.get(0).getId(), root, new CommandListenerAdapter(listener) {

+ 9
- 8
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackController.java View File

189
         }
189
         }
190
     }
190
     }
191
 
191
 
192
-    public void pop(CommandListener listener) {
192
+    public void pop(Options mergeOptions, CommandListener listener) {
193
         if (!canPop()) {
193
         if (!canPop()) {
194
             listener.onError("Nothing to pop");
194
             listener.onError("Nothing to pop");
195
             return;
195
             return;
197
 
197
 
198
         final ViewController disappearing = stack.pop();
198
         final ViewController disappearing = stack.pop();
199
         final ViewController appearing = stack.peek();
199
         final ViewController appearing = stack.peek();
200
+        disappearing.mergeOptions(mergeOptions);
200
         disappearing.onViewWillDisappear();
201
         disappearing.onViewWillDisappear();
201
         appearing.onViewWillAppear();
202
         appearing.onViewWillAppear();
202
         Options resolvedOptions = resolveCurrentOptions();
203
         Options resolvedOptions = resolveCurrentOptions();
221
         listener.onSuccess(disappearing.getId());
222
         listener.onSuccess(disappearing.getId());
222
     }
223
     }
223
 
224
 
224
-    public void popTo(final ViewController viewController, CommandListener listener) {
225
-        if (!stack.containsId(viewController.getId())) {
225
+    public void popTo(ViewController viewController, Options mergeOptions, CommandListener listener) {
226
+        if (!stack.containsId(viewController.getId()) || peek().equals(viewController)) {
226
             listener.onError("Nothing to pop");
227
             listener.onError("Nothing to pop");
227
             return;
228
             return;
228
         }
229
         }
238
             currentControlId = iterator.next();
239
             currentControlId = iterator.next();
239
         }
240
         }
240
 
241
 
241
-        pop(listener);
242
+        pop(mergeOptions, listener);
242
     }
243
     }
243
 
244
 
244
-    public void popToRoot(CommandListener listener) {
245
+    public void popToRoot(Options mergeOptions, CommandListener listener) {
245
         if (!canPop()) {
246
         if (!canPop()) {
246
             listener.onError("Nothing to pop");
247
             listener.onError("Nothing to pop");
247
             return;
248
             return;
255
             }
256
             }
256
         }
257
         }
257
 
258
 
258
-        pop(listener);
259
+        pop(mergeOptions, listener);
259
     }
260
     }
260
 
261
 
261
     private void removeAndDestroyController(ViewController controller) {
262
     private void removeAndDestroyController(ViewController controller) {
278
     @Override
279
     @Override
279
     public boolean handleBack(CommandListener listener) {
280
     public boolean handleBack(CommandListener listener) {
280
         if (canPop()) {
281
         if (canPop()) {
281
-            pop(listener);
282
+            pop(Options.EMPTY, listener);
282
             return true;
283
             return true;
283
         }
284
         }
284
         return false;
285
         return false;
313
 
314
 
314
     private void onNavigationButtonPressed(String buttonId) {
315
     private void onNavigationButtonPressed(String buttonId) {
315
         if (Constants.BACK_BUTTON_ID.equals(buttonId)) {
316
         if (Constants.BACK_BUTTON_ID.equals(buttonId)) {
316
-            pop(new CommandListenerAdapter());
317
+            pop(Options.EMPTY, new CommandListenerAdapter());
317
         } else {
318
         } else {
318
             sendOnNavigationButtonPressed(buttonId);
319
             sendOnNavigationButtonPressed(buttonId);
319
         }
320
         }

+ 8
- 0
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/ComponentViewControllerTest.java View File

13
 import org.junit.Test;
13
 import org.junit.Test;
14
 
14
 
15
 import static org.assertj.core.api.Java6Assertions.assertThat;
15
 import static org.assertj.core.api.Java6Assertions.assertThat;
16
+import static org.mockito.ArgumentMatchers.any;
16
 import static org.mockito.Mockito.spy;
17
 import static org.mockito.Mockito.spy;
17
 import static org.mockito.Mockito.times;
18
 import static org.mockito.Mockito.times;
18
 import static org.mockito.Mockito.verify;
19
 import static org.mockito.Mockito.verify;
77
         uut.sendOnNavigationButtonPressed("btn1");
78
         uut.sendOnNavigationButtonPressed("btn1");
78
         verify(view, times(1)).sendOnNavigationButtonPressed("btn1");
79
         verify(view, times(1)).sendOnNavigationButtonPressed("btn1");
79
     }
80
     }
81
+
82
+    @Test
83
+    public void mergeOptions_emptyOptionsAreIgnored() {
84
+        ComponentViewController spy = spy(uut);
85
+        spy.mergeOptions(Options.EMPTY);
86
+        verify(spy, times(0)).performOnParentController(any());
87
+    }
80
 }
88
 }

+ 2
- 2
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/FloatingActionButtonTest.java View File

103
         stackController.push(childFab, new CommandListenerAdapter());
103
         stackController.push(childFab, new CommandListenerAdapter());
104
         childFab.onViewAppeared();
104
         childFab.onViewAppeared();
105
         assertThat(hasFab()).isTrue();
105
         assertThat(hasFab()).isTrue();
106
-        stackController.pop(new CommandListenerAdapter());
106
+        stackController.pop(Options.EMPTY, new CommandListenerAdapter());
107
         childNoFab.onViewAppeared();
107
         childNoFab.onViewAppeared();
108
         assertThat(hasFab()).isFalse();
108
         assertThat(hasFab()).isFalse();
109
     }
109
     }
115
         stackController.push(childNoFab, new CommandListenerAdapter());
115
         stackController.push(childNoFab, new CommandListenerAdapter());
116
         childNoFab.onViewAppeared();
116
         childNoFab.onViewAppeared();
117
         assertThat(hasFab()).isFalse();
117
         assertThat(hasFab()).isFalse();
118
-        stackController.pop(new CommandListenerAdapter());
118
+        stackController.pop(Options.EMPTY, new CommandListenerAdapter());
119
         childFab.onViewAppeared();
119
         childFab.onViewAppeared();
120
         assertThat(hasFab()).isTrue();
120
         assertThat(hasFab()).isTrue();
121
     }
121
     }

+ 13
- 13
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/NavigatorTest.java View File

188
 
188
 
189
     @Test
189
     @Test
190
     public void pop_InvalidDoesNothing() {
190
     public void pop_InvalidDoesNothing() {
191
-        uut.pop("123", new CommandListenerAdapter());
191
+        uut.pop("123", Options.EMPTY, new CommandListenerAdapter());
192
         uut.setRoot(child1, new CommandListenerAdapter());
192
         uut.setRoot(child1, new CommandListenerAdapter());
193
-        uut.pop(child1.getId(), new CommandListenerAdapter());
193
+        uut.pop(child1.getId(), Options.EMPTY, new CommandListenerAdapter());
194
         assertThat(uut.getChildControllers()).hasSize(1);
194
         assertThat(uut.getChildControllers()).hasSize(1);
195
     }
195
     }
196
 
196
 
208
                 stack2.push(child4, new CommandListenerAdapter() {
208
                 stack2.push(child4, new CommandListenerAdapter() {
209
                             @Override
209
                             @Override
210
                             public void onSuccess(String childId) {
210
                             public void onSuccess(String childId) {
211
-                                uut.pop("child4", new CommandListenerAdapter());
211
+                                uut.pop("child4", Options.EMPTY, new CommandListenerAdapter());
212
                                 assertThat(stack2.getChildControllers()).containsOnly(child2, child3);
212
                                 assertThat(stack2.getChildControllers()).containsOnly(child2, child3);
213
                             }
213
                             }
214
                         }
214
                         }
226
         stack.push(child1, new CommandListenerAdapter());
226
         stack.push(child1, new CommandListenerAdapter());
227
         stack.push(child2, new CommandListenerAdapter());
227
         stack.push(child2, new CommandListenerAdapter());
228
 
228
 
229
-        uut.pop(stack.getId(), new CommandListenerAdapter());
229
+        uut.pop(stack.getId(), Options.EMPTY, new CommandListenerAdapter());
230
         assertThat(stack.getChildControllers()).containsOnly(child1);
230
         assertThat(stack.getChildControllers()).containsOnly(child1);
231
     }
231
     }
232
 
232
 
244
         stack2.push(child5, new CommandListenerAdapter() {
244
         stack2.push(child5, new CommandListenerAdapter() {
245
             @Override
245
             @Override
246
             public void onSuccess(String childId) {
246
             public void onSuccess(String childId) {
247
-                uut.popTo(child2.getId(), new CommandListenerAdapter());
247
+                uut.popTo(child2.getId(), Options.EMPTY, new CommandListenerAdapter());
248
                 assertThat(stack2.getChildControllers()).containsOnly(child2);
248
                 assertThat(stack2.getChildControllers()).containsOnly(child2);
249
             }
249
             }
250
         });
250
         });
264
         stack2.push(child5, new CommandListenerAdapter() {
264
         stack2.push(child5, new CommandListenerAdapter() {
265
             @Override
265
             @Override
266
             public void onSuccess(String childId) {
266
             public void onSuccess(String childId) {
267
-                uut.popToRoot(child3.getId(), new CommandListenerAdapter());
267
+                uut.popToRoot(child3.getId(), Options.EMPTY, new CommandListenerAdapter());
268
                 assertThat(stack2.getChildControllers()).containsOnly(child2);
268
                 assertThat(stack2.getChildControllers()).containsOnly(child2);
269
             }
269
             }
270
         });
270
         });
370
 
370
 
371
     @Test
371
     @Test
372
     public void pop_InvalidDoesNothing_Promise() {
372
     public void pop_InvalidDoesNothing_Promise() {
373
-        uut.pop("123", new CommandListenerAdapter());
373
+        uut.pop("123", Options.EMPTY, new CommandListenerAdapter());
374
         uut.setRoot(child1, new CommandListenerAdapter());
374
         uut.setRoot(child1, new CommandListenerAdapter());
375
-        uut.pop(child1.getId(), new CommandListenerAdapter() {
375
+        uut.pop(child1.getId(), Options.EMPTY, new CommandListenerAdapter() {
376
             @Override
376
             @Override
377
             public void onError(String reason) {
377
             public void onError(String reason) {
378
                 assertThat(uut.getChildControllers()).hasSize(1);
378
                 assertThat(uut.getChildControllers()).hasSize(1);
393
         stack2.push(child4, new CommandListenerAdapter() {
393
         stack2.push(child4, new CommandListenerAdapter() {
394
             @Override
394
             @Override
395
             public void onSuccess(String childId) {
395
             public void onSuccess(String childId) {
396
-                uut.pop("child4", new CommandListenerAdapter());
396
+                uut.pop("child4", Options.EMPTY, new CommandListenerAdapter());
397
                 assertThat(stack2.getChildControllers()).containsOnly(child2, child3);
397
                 assertThat(stack2.getChildControllers()).containsOnly(child2, child3);
398
             }
398
             }
399
         });
399
         });
431
                 assertThat(spy.getChildControllers().size()).isEqualTo(1);
431
                 assertThat(spy.getChildControllers().size()).isEqualTo(1);
432
             }
432
             }
433
         };
433
         };
434
-        uut.pop("child2", listener);
435
-        verify(spy, times(1)).pop(listener);
434
+        uut.pop("child2", Options.EMPTY, listener);
435
+        verify(spy, times(1)).pop(Options.EMPTY, listener);
436
     }
436
     }
437
 
437
 
438
     @Test
438
     @Test
505
         disablePushAnimation(child2);
505
         disablePushAnimation(child2);
506
         disableShowModalAnimation(child1);
506
         disableShowModalAnimation(child1);
507
 
507
 
508
-        uut.dismissAllModals(new CommandListenerAdapter());
508
+        uut.dismissAllModals(Options.EMPTY, new CommandListenerAdapter());
509
         verify(parentVisibilityListener, times(0)).onViewAppeared(parentController.getView());
509
         verify(parentVisibilityListener, times(0)).onViewAppeared(parentController.getView());
510
 
510
 
511
         uut.setRoot(parentController, new CommandListenerAdapter());
511
         uut.setRoot(parentController, new CommandListenerAdapter());
513
 
513
 
514
         verify(parentVisibilityListener, times(1)).onViewAppeared(parentController.getView());
514
         verify(parentVisibilityListener, times(1)).onViewAppeared(parentController.getView());
515
         uut.showModal(child1, new CommandListenerAdapter());
515
         uut.showModal(child1, new CommandListenerAdapter());
516
-        uut.dismissAllModals(new CommandListenerAdapter());
516
+        uut.dismissAllModals(Options.EMPTY, new CommandListenerAdapter());
517
 
517
 
518
         verify(parentVisibilityListener, times(2)).onViewAppeared(parentController.getView());
518
         verify(parentVisibilityListener, times(2)).onViewAppeared(parentController.getView());
519
     }
519
     }

+ 1
- 1
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/TopTabsViewControllerTest.java View File

232
         uut.onViewAppeared();
232
         uut.onViewAppeared();
233
 
233
 
234
         assertThat(ViewHelper.isVisible(stackController.getTopBar().getTopTabs())).isTrue();
234
         assertThat(ViewHelper.isVisible(stackController.getTopBar().getTopTabs())).isTrue();
235
-        stackController.pop(new CommandListenerAdapter() {
235
+        stackController.pop(Options.EMPTY, new CommandListenerAdapter() {
236
             @Override
236
             @Override
237
             public void onSuccess(String childId) {
237
             public void onSuccess(String childId) {
238
                 assertThat(ViewHelper.isVisible(stackController.getTopBar().getTopTabs())).isFalse();
238
                 assertThat(ViewHelper.isVisible(stackController.getTopBar().getTopTabs())).isFalse();

+ 7
- 0
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/child/ChildControllerTest.java View File

11
 import org.junit.Test;
11
 import org.junit.Test;
12
 import org.mockito.Mockito;
12
 import org.mockito.Mockito;
13
 
13
 
14
+import static org.mockito.ArgumentMatchers.any;
14
 import static org.mockito.Mockito.spy;
15
 import static org.mockito.Mockito.spy;
15
 import static org.mockito.Mockito.times;
16
 import static org.mockito.Mockito.times;
16
 import static org.mockito.Mockito.verify;
17
 import static org.mockito.Mockito.verify;
64
         uut.mergeOptions(options);
65
         uut.mergeOptions(options);
65
         verify(presenter).mergeOptions(uut.getView(), options);
66
         verify(presenter).mergeOptions(uut.getView(), options);
66
     }
67
     }
68
+
69
+    @Test
70
+    public void mergeOptions_emptyOptionsAreIgnored() {
71
+        uut.mergeOptions(Options.EMPTY);
72
+        verify(presenter, times(0)).mergeOptions(any(), any());
73
+    }
67
 }
74
 }

+ 18
- 5
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/modal/ModalStackTest.java View File

141
                 assertThat(uut.isEmpty()).isTrue();
141
                 assertThat(uut.isEmpty()).isTrue();
142
             }
142
             }
143
         });
143
         });
144
-        uut.dismissAllModals(listener, rootController);
144
+        uut.dismissAllModals(rootController, Options.EMPTY, listener);
145
         verify(listener, times(1)).onSuccess(anyString());
145
         verify(listener, times(1)).onSuccess(anyString());
146
         verifyZeroInteractions(listener);
146
         verifyZeroInteractions(listener);
147
     }
147
     }
149
     @Test
149
     @Test
150
     public void dismissAllModals_rejectIfEmpty() {
150
     public void dismissAllModals_rejectIfEmpty() {
151
         CommandListener spy = spy(new CommandListenerAdapter());
151
         CommandListener spy = spy(new CommandListenerAdapter());
152
-        uut.dismissAllModals(spy, rootController);
152
+        uut.dismissAllModals(rootController, Options.EMPTY, spy);
153
         verify(spy, times(1)).onError(any());
153
         verify(spy, times(1)).onError(any());
154
     }
154
     }
155
 
155
 
156
+    @Test
157
+    public void dismissAllModals_optionsAreMergedOnTopModal() {
158
+        uut.showModal(modal1, rootController, new CommandListenerAdapter());
159
+        uut.showModal(modal2, rootController, new CommandListenerAdapter());
160
+        uut.showModal(modal3, rootController, new CommandListenerAdapter());
161
+
162
+        Options mergeOptions = new Options();
163
+        uut.dismissAllModals(rootController, mergeOptions, new CommandListenerAdapter());
164
+        verify(modal3).mergeOptions(mergeOptions);
165
+        verify(modal1, times(0)).mergeOptions(mergeOptions);
166
+        verify(modal2, times(0)).mergeOptions(mergeOptions);
167
+    }
168
+
156
     @SuppressWarnings("Convert2Lambda")
169
     @SuppressWarnings("Convert2Lambda")
157
     @Test
170
     @Test
158
     public void dismissAllModals_onlyTopModalIsAnimated() {
171
     public void dismissAllModals_onlyTopModalIsAnimated() {
162
         ViewGroup view1 = modal1.getView();
175
         ViewGroup view1 = modal1.getView();
163
         ViewGroup view2 = modal2.getView();
176
         ViewGroup view2 = modal2.getView();
164
         CommandListener listener = spy(new CommandListenerAdapter());
177
         CommandListener listener = spy(new CommandListenerAdapter());
165
-        uut.dismissAllModals(listener, rootController);
178
+        uut.dismissAllModals(rootController, Options.EMPTY, listener);
166
         verify(presenter, times(1)).dismissTopModal(eq(modal2), eq(rootController), any());
179
         verify(presenter, times(1)).dismissTopModal(eq(modal2), eq(rootController), any());
167
         verify(listener).onSuccess(modal2.getId());
180
         verify(listener).onSuccess(modal2.getId());
168
         verify(animator, times(0)).dismiss(eq(view1), eq(modal1.options.animations.dismissModal), any());
181
         verify(animator, times(0)).dismiss(eq(view1), eq(modal1.options.animations.dismissModal), any());
175
         uut.showModal(modal1, rootController, new CommandListenerAdapter());
188
         uut.showModal(modal1, rootController, new CommandListenerAdapter());
176
         uut.showModal(modal2, rootController, new CommandListenerAdapter());
189
         uut.showModal(modal2, rootController, new CommandListenerAdapter());
177
 
190
 
178
-        uut.dismissAllModals(new CommandListenerAdapter(), rootController);
191
+        uut.dismissAllModals(rootController, Options.EMPTY, new CommandListenerAdapter());
179
 
192
 
180
         verify(modal1, times(1)).destroy();
193
         verify(modal1, times(1)).destroy();
181
         verify(modal1, times(1)).onViewDisappear();
194
         verify(modal1, times(1)).onViewDisappear();
187
         assertThat(uut.isEmpty()).isTrue();
200
         assertThat(uut.isEmpty()).isTrue();
188
         uut.showModal(modal1, rootController, new CommandListenerAdapter());
201
         uut.showModal(modal1, rootController, new CommandListenerAdapter());
189
         assertThat(uut.isEmpty()).isFalse();
202
         assertThat(uut.isEmpty()).isFalse();
190
-        uut.dismissAllModals(new CommandListenerAdapter(), rootController);
203
+        uut.dismissAllModals(rootController, Options.EMPTY, new CommandListenerAdapter());
191
         assertThat(uut.isEmpty()).isTrue();
204
         assertThat(uut.isEmpty()).isTrue();
192
     }
205
     }
193
 
206
 

+ 46
- 19
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/StackControllerTest.java View File

227
             @Override
227
             @Override
228
             public void onSuccess(String childId) {
228
             public void onSuccess(String childId) {
229
                 assertContainsOnlyId(child2.getId(), child1.getId());
229
                 assertContainsOnlyId(child2.getId(), child1.getId());
230
-                uut.pop(new CommandListenerAdapter());
230
+                uut.pop(Options.EMPTY, new CommandListenerAdapter());
231
                 assertContainsOnlyId(child1.getId());
231
                 assertContainsOnlyId(child1.getId());
232
             }
232
             }
233
         });
233
         });
239
         uut.push(child2, new CommandListenerAdapter() {
239
         uut.push(child2, new CommandListenerAdapter() {
240
             @Override
240
             @Override
241
             public void onSuccess(String childId) {
241
             public void onSuccess(String childId) {
242
-                uut.pop(new CommandListenerAdapter());
242
+                uut.pop(Options.EMPTY, new CommandListenerAdapter());
243
                 verify(uut, times(1)).applyChildOptions(uut.options, eq((ReactComponent) child1.getView()));
243
                 verify(uut, times(1)).applyChildOptions(uut.options, eq((ReactComponent) child1.getView()));
244
             }
244
             }
245
         });
245
         });
260
         uut.push(child2, new CommandListenerAdapter() {
260
         uut.push(child2, new CommandListenerAdapter() {
261
             @Override
261
             @Override
262
             public void onSuccess(String childId) {
262
             public void onSuccess(String childId) {
263
-                uut.pop(new CommandListenerAdapter() {
263
+                uut.pop(Options.EMPTY, new CommandListenerAdapter() {
264
                     @Override
264
                     @Override
265
                     public void onSuccess(String childId) {
265
                     public void onSuccess(String childId) {
266
                         verify(presenter, times(1)).onChildWillAppear(child1.options, child2.options);
266
                         verify(presenter, times(1)).onChildWillAppear(child1.options, child2.options);
312
     @Test
312
     @Test
313
     public void popDoesNothingWhenZeroOrOneChild() {
313
     public void popDoesNothingWhenZeroOrOneChild() {
314
         assertThat(uut.isEmpty()).isTrue();
314
         assertThat(uut.isEmpty()).isTrue();
315
-        uut.pop(new CommandListenerAdapter());
315
+        uut.pop(Options.EMPTY, new CommandListenerAdapter());
316
         assertThat(uut.isEmpty()).isTrue();
316
         assertThat(uut.isEmpty()).isTrue();
317
 
317
 
318
         uut.push(child1, new CommandListenerAdapter());
318
         uut.push(child1, new CommandListenerAdapter());
319
-        uut.pop(new CommandListenerAdapter());
319
+        uut.pop(Options.EMPTY, new CommandListenerAdapter());
320
         assertContainsOnlyId(child1.getId());
320
         assertContainsOnlyId(child1.getId());
321
     }
321
     }
322
 
322
 
417
             public void onSuccess(String childId) {
417
             public void onSuccess(String childId) {
418
                 assertIsChild(uut.getView(), child2View);
418
                 assertIsChild(uut.getView(), child2View);
419
                 assertNotChildOf(uut.getView(), child1View);
419
                 assertNotChildOf(uut.getView(), child1View);
420
-                uut.pop(new CommandListenerAdapter());
420
+                uut.pop(Options.EMPTY, new CommandListenerAdapter());
421
                 assertNotChildOf(uut.getView(), child2View);
421
                 assertNotChildOf(uut.getView(), child2View);
422
                 assertIsChild(uut.getView(), child1View);
422
                 assertIsChild(uut.getView(), child1View);
423
             }
423
             }
433
         uut.ensureViewIsCreated();
433
         uut.ensureViewIsCreated();
434
 
434
 
435
         assertThat(child2.getView().getParent()).isEqualTo(uut.getView());
435
         assertThat(child2.getView().getParent()).isEqualTo(uut.getView());
436
-        uut.pop(new CommandListenerAdapter());
436
+        uut.pop(Options.EMPTY, new CommandListenerAdapter());
437
         assertThat(child1.getView().getParent()).isEqualTo(uut.getView());
437
         assertThat(child1.getView().getParent()).isEqualTo(uut.getView());
438
 
438
 
439
         assertThat(child1.getView().getLayoutParams().width).isEqualTo(ViewGroup.LayoutParams.MATCH_PARENT);
439
         assertThat(child1.getView().getLayoutParams().width).isEqualTo(ViewGroup.LayoutParams.MATCH_PARENT);
453
                 assertThat(uut.size()).isEqualTo(3);
453
                 assertThat(uut.size()).isEqualTo(3);
454
                 assertThat(uut.peek()).isEqualTo(child3);
454
                 assertThat(uut.peek()).isEqualTo(child3);
455
 
455
 
456
-                uut.popTo(child1, new CommandListenerAdapter());
456
+                uut.popTo(child1, Options.EMPTY, new CommandListenerAdapter());
457
 
457
 
458
                 assertThat(uut.size()).isEqualTo(1);
458
                 assertThat(uut.size()).isEqualTo(1);
459
                 assertThat(uut.peek()).isEqualTo(child1);
459
                 assertThat(uut.peek()).isEqualTo(child1);
461
         });
461
         });
462
     }
462
     }
463
 
463
 
464
+    @Test
465
+    public void popTo_optionsAreMergedOnTopChild() {
466
+        disablePushAnimation(child1, child2);
467
+        uut.push(child1, new CommandListenerAdapter());
468
+
469
+        Options mergeOptions = new Options();
470
+        uut.popTo(child2, mergeOptions, new CommandListenerAdapter());
471
+        uut.popTo(child1, mergeOptions, new CommandListenerAdapter());
472
+        verify(child1, times(0)).mergeOptions(mergeOptions);
473
+
474
+        uut.push(child2, new CommandListenerAdapter());
475
+        uut.popTo(child1, mergeOptions, new CommandListenerAdapter());
476
+        verify(child2).mergeOptions(mergeOptions);
477
+    }
478
+
464
     @Test
479
     @Test
465
     public void popTo_NotAChildOfThisStack_DoesNothing() {
480
     public void popTo_NotAChildOfThisStack_DoesNothing() {
466
         uut.push(child1, new CommandListenerAdapter());
481
         uut.push(child1, new CommandListenerAdapter());
467
         uut.push(child3, new CommandListenerAdapter());
482
         uut.push(child3, new CommandListenerAdapter());
468
         assertThat(uut.size()).isEqualTo(2);
483
         assertThat(uut.size()).isEqualTo(2);
469
-        uut.popTo(child2, new CommandListenerAdapter());
484
+        uut.popTo(child2, Options.EMPTY, new CommandListenerAdapter());
470
         assertThat(uut.size()).isEqualTo(2);
485
         assertThat(uut.size()).isEqualTo(2);
471
     }
486
     }
472
 
487
 
478
         uut.push(child4, new CommandListenerAdapter() {
493
         uut.push(child4, new CommandListenerAdapter() {
479
             @Override
494
             @Override
480
             public void onSuccess(String childId) {
495
             public void onSuccess(String childId) {
481
-                uut.popTo(child2, new CommandListenerAdapter() {
496
+                uut.popTo(child2, Options.EMPTY, new CommandListenerAdapter() {
482
                     @Override
497
                     @Override
483
                     public void onSuccess(String childId) {
498
                     public void onSuccess(String childId) {
484
                         verify(animator, times(0)).pop(eq(child1.getView()), any(), any());
499
                         verify(animator, times(0)).pop(eq(child1.getView()), any(), any());
503
                 assertThat(uut.size()).isEqualTo(3);
518
                 assertThat(uut.size()).isEqualTo(3);
504
                 assertThat(uut.peek()).isEqualTo(child3);
519
                 assertThat(uut.peek()).isEqualTo(child3);
505
 
520
 
506
-                uut.popToRoot(new CommandListenerAdapter() {
521
+                uut.popToRoot(Options.EMPTY, new CommandListenerAdapter() {
507
                     @Override
522
                     @Override
508
                     public void onSuccess(String childId) {
523
                     public void onSuccess(String childId) {
509
                         assertThat(uut.size()).isEqualTo(1);
524
                         assertThat(uut.size()).isEqualTo(1);
524
         uut.push(child3, new CommandListenerAdapter() {
539
         uut.push(child3, new CommandListenerAdapter() {
525
             @Override
540
             @Override
526
             public void onSuccess(String childId) {
541
             public void onSuccess(String childId) {
527
-                uut.popToRoot(new CommandListenerAdapter() {
542
+                uut.popToRoot(Options.EMPTY, new CommandListenerAdapter() {
528
                     @Override
543
                     @Override
529
                     public void onSuccess(String childId) {
544
                     public void onSuccess(String childId) {
530
                         verify(animator, times(1)).pop(eq(child3.getView()), eq(child3.options.animations.pop), any());
545
                         verify(animator, times(1)).pop(eq(child3.getView()), eq(child3.options.animations.pop), any());
544
         uut.push(child2, new CommandListenerAdapter());
559
         uut.push(child2, new CommandListenerAdapter());
545
         uut.push(child3, new CommandListenerAdapter());
560
         uut.push(child3, new CommandListenerAdapter());
546
 
561
 
547
-        uut.popToRoot(new CommandListenerAdapter() {
562
+        uut.popToRoot(Options.EMPTY, new CommandListenerAdapter() {
548
             @Override
563
             @Override
549
             public void onSuccess(String childId) {
564
             public void onSuccess(String childId) {
550
                 verify(child1, times(0)).destroy();
565
                 verify(child1, times(0)).destroy();
558
     public void popToRoot_EmptyStackDoesNothing() {
573
     public void popToRoot_EmptyStackDoesNothing() {
559
         assertThat(uut.isEmpty()).isTrue();
574
         assertThat(uut.isEmpty()).isTrue();
560
         CommandListenerAdapter listener = spy(new CommandListenerAdapter());
575
         CommandListenerAdapter listener = spy(new CommandListenerAdapter());
561
-        uut.popToRoot(listener);
576
+        uut.popToRoot(Options.EMPTY, listener);
562
         assertThat(uut.isEmpty()).isTrue();
577
         assertThat(uut.isEmpty()).isTrue();
563
         verify(listener, times(1)).onError(any());
578
         verify(listener, times(1)).onError(any());
564
     }
579
     }
565
 
580
 
581
+    @Test
582
+    public void popToRoot_optionsAreMergedOnTopChild() {
583
+        disablePushAnimation(child1, child2);
584
+        uut.push(child1, new CommandListenerAdapter());
585
+        uut.push(child2, new CommandListenerAdapter());
586
+
587
+        Options mergeOptions = new Options();
588
+        uut.popToRoot(mergeOptions, new CommandListenerAdapter());
589
+        verify(child2).mergeOptions(mergeOptions);
590
+        verify(child1, times(0)).mergeOptions(mergeOptions);
591
+    }
592
+
566
     @Test
593
     @Test
567
     public void findControllerById_ReturnsSelfOrChildrenById() {
594
     public void findControllerById_ReturnsSelfOrChildrenById() {
568
         assertThat(uut.findControllerById("123")).isNull();
595
         assertThat(uut.findControllerById("123")).isNull();
591
             @Override
618
             @Override
592
             public void onSuccess(String childId) {
619
             public void onSuccess(String childId) {
593
                 verify(child3, times(0)).destroy();
620
                 verify(child3, times(0)).destroy();
594
-                uut.pop(new CommandListenerAdapter());
621
+                uut.pop(Options.EMPTY, new CommandListenerAdapter());
595
                 verify(child3, times(1)).destroy();
622
                 verify(child3, times(1)).destroy();
596
             }
623
             }
597
         });
624
         });
605
         child2 = spy(child2);
632
         child2 = spy(child2);
606
         uut.push(child1, new CommandListenerAdapter());
633
         uut.push(child1, new CommandListenerAdapter());
607
         uut.push(child2, new CommandListenerAdapter());
634
         uut.push(child2, new CommandListenerAdapter());
608
-        uut.pop(new CommandListenerAdapter());
635
+        uut.pop(Options.EMPTY, new CommandListenerAdapter());
609
         verify(child1, times(1)).onViewWillAppear();
636
         verify(child1, times(1)).onViewWillAppear();
610
         verify(child2, times(1)).onViewWillDisappear();
637
         verify(child2, times(1)).onViewWillDisappear();
611
     }
638
     }
625
                 uut.push(child2, new CommandListenerAdapter() {
652
                 uut.push(child2, new CommandListenerAdapter() {
626
                     @Override
653
                     @Override
627
                     public void onSuccess(String childId) {
654
                     public void onSuccess(String childId) {
628
-                        uut.pop(new CommandListenerAdapter() {
655
+                        uut.pop(Options.EMPTY, new CommandListenerAdapter() {
629
                             @Override
656
                             @Override
630
                             public void onSuccess(String childId) {
657
                             public void onSuccess(String childId) {
631
                                 verify(uut.getTopBar(), times(1)).hideAnimate(child2.options.animations.pop.topBar);
658
                                 verify(uut.getTopBar(), times(1)).hideAnimate(child2.options.animations.pop.topBar);
653
                 uut.push(child2, new CommandListenerAdapter());
680
                 uut.push(child2, new CommandListenerAdapter());
654
                 assertThat(uut.getTopBar().getVisibility()).isEqualTo(View.VISIBLE);
681
                 assertThat(uut.getTopBar().getVisibility()).isEqualTo(View.VISIBLE);
655
 
682
 
656
-                uut.pop(new CommandListenerAdapter());
683
+                uut.pop(Options.EMPTY, new CommandListenerAdapter());
657
                 verify(uut.getTopBar(), times(0)).hideAnimate(child2.options.animations.pop.topBar);
684
                 verify(uut.getTopBar(), times(0)).hideAnimate(child2.options.animations.pop.topBar);
658
                 assertThat(uut.getTopBar().getVisibility()).isEqualTo(View.GONE);
685
                 assertThat(uut.getTopBar().getVisibility()).isEqualTo(View.GONE);
659
             }
686
             }
673
                 verify(child2, times(0)).destroy();
700
                 verify(child2, times(0)).destroy();
674
                 verify(child3, times(0)).destroy();
701
                 verify(child3, times(0)).destroy();
675
 
702
 
676
-                uut.popTo(child1, new CommandListenerAdapter() {
703
+                uut.popTo(child1, Options.EMPTY, new CommandListenerAdapter() {
677
                     @Override
704
                     @Override
678
                     public void onSuccess(String childId) {
705
                     public void onSuccess(String childId) {
679
                         verify(child2, times(1)).destroy();
706
                         verify(child2, times(1)).destroy();

+ 10
- 10
lib/ios/RNNBridgeModule.m View File

43
 	} rejection:reject];
43
 	} rejection:reject];
44
 }
44
 }
45
 
45
 
46
-RCT_EXPORT_METHOD(pop:(NSString*)commandId componentId:(NSString*)componentId options:(NSDictionary*)options resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
47
-	[_commandsHandler pop:componentId options:(NSDictionary*)options completion:^{
46
+RCT_EXPORT_METHOD(pop:(NSString*)commandId componentId:(NSString*)componentId mergeOptions:(NSDictionary*)options resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
47
+	[_commandsHandler pop:componentId mergeOptions:(NSDictionary*)options completion:^{
48
 		resolve(componentId);
48
 		resolve(componentId);
49
 	} rejection:reject];
49
 	} rejection:reject];
50
 }
50
 }
55
 	} rejection:reject];
55
 	} rejection:reject];
56
 }
56
 }
57
 
57
 
58
-RCT_EXPORT_METHOD(popTo:(NSString*)commandId componentId:(NSString*)componentId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
59
-	[_commandsHandler popTo:componentId completion:^{
58
+RCT_EXPORT_METHOD(popTo:(NSString*)commandId componentId:(NSString*)componentId mergeOptions:(NSDictionary*)options resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
59
+	[_commandsHandler popTo:componentId mergeOptions:options completion:^{
60
 		resolve(componentId);
60
 		resolve(componentId);
61
 	} rejection:reject];
61
 	} rejection:reject];
62
 }
62
 }
63
 
63
 
64
-RCT_EXPORT_METHOD(popToRoot:(NSString*)commandId componentId:(NSString*)componentId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
65
-	[_commandsHandler popToRoot:componentId completion:^{
64
+RCT_EXPORT_METHOD(popToRoot:(NSString*)commandId componentId:(NSString*)componentId mergeOptions:(NSDictionary*)options resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
65
+	[_commandsHandler popToRoot:componentId mergeOptions:options completion:^{
66
 		resolve(componentId);
66
 		resolve(componentId);
67
 	} rejection:reject];
67
 	} rejection:reject];
68
 }
68
 }
73
 	}];
73
 	}];
74
 }
74
 }
75
 
75
 
76
-RCT_EXPORT_METHOD(dismissModal:(NSString*)commandId componentId:(NSString*)componentId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
77
-	[_commandsHandler dismissModal:componentId completion:^{
76
+RCT_EXPORT_METHOD(dismissModal:(NSString*)commandId componentId:(NSString*)componentId mergeOptions:(NSDictionary*)options resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
77
+	[_commandsHandler dismissModal:componentId mergeOptions:options completion:^{
78
 		resolve(componentId);
78
 		resolve(componentId);
79
 	}];
79
 	}];
80
 }
80
 }
81
 
81
 
82
-RCT_EXPORT_METHOD(dismissAllModals:(NSString*)commandId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
83
-	[_commandsHandler dismissAllModalsWithCompletion:^{
82
+RCT_EXPORT_METHOD(dismissAllModals:(NSString*)commandId mergeOptions:(NSDictionary*)options resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
83
+	[_commandsHandler dismissAllModals:options completion:^{
84
 		resolve(nil);
84
 		resolve(nil);
85
 	}];
85
 	}];
86
 }
86
 }

+ 14
- 14
lib/ios/RNNCommandsHandler.h View File

6
 
6
 
7
 @interface RNNCommandsHandler : NSObject
7
 @interface RNNCommandsHandler : NSObject
8
 
8
 
9
--(instancetype)initWithStore:(RNNStore*)store controllerFactory:(RNNControllerFactory*)controllerFactory eventEmitter:(RNNEventEmitter*)eventEmitter;
9
+- (instancetype)initWithStore:(RNNStore*)store controllerFactory:(RNNControllerFactory*)controllerFactory eventEmitter:(RNNEventEmitter*)eventEmitter;
10
 
10
 
11
--(void)setRoot:(NSDictionary*)layout completion:(RNNTransitionCompletionBlock)completion;
11
+- (void)setRoot:(NSDictionary*)layout completion:(RNNTransitionCompletionBlock)completion;
12
 
12
 
13
--(void)mergeOptions:(NSString*)componentId options:(NSDictionary*)options completion:(RNNTransitionCompletionBlock)completion;
13
+- (void)mergeOptions:(NSString*)componentId options:(NSDictionary*)options completion:(RNNTransitionCompletionBlock)completion;
14
 
14
 
15
--(void)setDefaultOptions:(NSDictionary*)options completion:(RNNTransitionCompletionBlock)completion;
15
+- (void)setDefaultOptions:(NSDictionary*)options completion:(RNNTransitionCompletionBlock)completion;
16
 
16
 
17
--(void)push:(NSString*)componentId layout:(NSDictionary*)layout completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection;
17
+- (void)push:(NSString*)componentId layout:(NSDictionary*)layout completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection;
18
 
18
 
19
--(void)pop:(NSString*)componentId options:(NSDictionary*)options completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection;
19
+- (void)pop:(NSString*)componentId mergeOptions:(NSDictionary*)options completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection;
20
 
20
 
21
--(void)popTo:(NSString*)componentId completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection;
21
+- (void)popTo:(NSString*)componentId mergeOptions:(NSDictionary*)options completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection;
22
 
22
 
23
--(void)popToRoot:(NSString*)componentId completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection;
23
+- (void)popToRoot:(NSString*)componentId mergeOptions:(NSDictionary*)options completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection;
24
 
24
 
25
--(void)setStackRoot:(NSString*)componentId layout:(NSDictionary*)layout completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection;
25
+- (void)setStackRoot:(NSString*)componentId layout:(NSDictionary*)layout completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection;
26
 
26
 
27
--(void)showModal:(NSDictionary*)layout completion:(RNNTransitionWithComponentIdCompletionBlock)completion;
27
+- (void)showModal:(NSDictionary*)layout completion:(RNNTransitionWithComponentIdCompletionBlock)completion;
28
 
28
 
29
--(void)dismissModal:(NSString*)componentId completion:(RNNTransitionCompletionBlock)completion;
29
+- (void)dismissModal:(NSString*)componentId mergeOptions:(NSDictionary*)options completion:(RNNTransitionCompletionBlock)completion;
30
 
30
 
31
--(void)dismissAllModalsWithCompletion:(RNNTransitionCompletionBlock)completion;
31
+- (void)dismissAllModals:(NSDictionary *)options completion:(RNNTransitionCompletionBlock)completion;
32
 
32
 
33
--(void)showOverlay:(NSDictionary *)layout completion:(RNNTransitionCompletionBlock)completion;
33
+- (void)showOverlay:(NSDictionary *)layout completion:(RNNTransitionCompletionBlock)completion;
34
 
34
 
35
--(void)dismissOverlay:(NSString*)componentId completion:(RNNTransitionCompletionBlock)completion rejection:(RNNTransitionRejectionBlock)reject;
35
+- (void)dismissOverlay:(NSString*)componentId completion:(RNNTransitionCompletionBlock)completion rejection:(RNNTransitionRejectionBlock)reject;
36
 
36
 
37
 @end
37
 @end

+ 15
- 11
lib/ios/RNNCommandsHandler.m View File

54
 - (void)setRoot:(NSDictionary*)layout completion:(RNNTransitionCompletionBlock)completion {
54
 - (void)setRoot:(NSDictionary*)layout completion:(RNNTransitionCompletionBlock)completion {
55
 	[self assertReady];
55
 	[self assertReady];
56
 	
56
 	
57
-	[_modalManager dismissAllModals];
57
+	[_modalManager dismissAllModalsAnimated:NO];
58
 	
58
 	
59
 	UIViewController *vc = [_controllerFactory createLayoutAndSaveToStore:layout[@"root"]];
59
 	UIViewController *vc = [_controllerFactory createLayoutAndSaveToStore:layout[@"root"]];
60
 	
60
 	
153
 	} rejection:rejection];
153
 	} rejection:rejection];
154
 }
154
 }
155
 
155
 
156
-- (void)pop:(NSString*)componentId options:(NSDictionary*)optionsDict completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection {
156
+- (void)pop:(NSString*)componentId mergeOptions:(NSDictionary*)options completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection {
157
 	[self assertReady];
157
 	[self assertReady];
158
 	
158
 	
159
 	RNNRootViewController *vc = (RNNRootViewController*)[_store findComponentForId:componentId];
159
 	RNNRootViewController *vc = (RNNRootViewController*)[_store findComponentForId:componentId];
160
-	[vc.options mergeWith:optionsDict];
160
+	[vc.options mergeWith:options];
161
 	
161
 	
162
 	UINavigationController *nvc = vc.navigationController;
162
 	UINavigationController *nvc = vc.navigationController;
163
 	
163
 	
182
 	}];
182
 	}];
183
 }
183
 }
184
 
184
 
185
-- (void)popTo:(NSString*)componentId completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection {
185
+- (void)popTo:(NSString*)componentId mergeOptions:(NSDictionary *)options completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection {
186
 	[self assertReady];
186
 	[self assertReady];
187
 	RNNRootViewController *vc = (RNNRootViewController*)[_store findComponentForId:componentId];
187
 	RNNRootViewController *vc = (RNNRootViewController*)[_store findComponentForId:componentId];
188
+	[vc.options mergeWith:options];
188
 	
189
 	
189
 	[_stackManager popTo:vc animated:vc.options.animations.pop.enable completion:^(NSArray *poppedViewControllers) {
190
 	[_stackManager popTo:vc animated:vc.options.animations.pop.enable completion:^(NSArray *poppedViewControllers) {
190
 		[_eventEmitter sendOnNavigationCommandCompletion:popTo params:@{@"componentId": componentId}];
191
 		[_eventEmitter sendOnNavigationCommandCompletion:popTo params:@{@"componentId": componentId}];
193
 	} rejection:rejection];
194
 	} rejection:rejection];
194
 }
195
 }
195
 
196
 
196
--(void) popToRoot:(NSString*)componentId completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection {
197
+- (void)popToRoot:(NSString*)componentId mergeOptions:(NSDictionary *)options completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection {
197
 	[self assertReady];
198
 	[self assertReady];
198
-	RNNRootViewController *newVc = (RNNRootViewController*)[_store findComponentForId:componentId];
199
+	RNNRootViewController *vc = (RNNRootViewController*)[_store findComponentForId:componentId];
200
+	[vc.options mergeWith:options];
199
 	
201
 	
200
 	[CATransaction begin];
202
 	[CATransaction begin];
201
 	[CATransaction setCompletionBlock:^{
203
 	[CATransaction setCompletionBlock:^{
203
 		completion();
205
 		completion();
204
 	}];
206
 	}];
205
 	
207
 	
206
-	[_stackManager popToRoot:newVc animated:newVc.options.animations.pop.enable completion:^(NSArray *poppedViewControllers) {
208
+	[_stackManager popToRoot:vc animated:vc.options.animations.pop.enable completion:^(NSArray *poppedViewControllers) {
207
 		[self removePopedViewControllers:poppedViewControllers];
209
 		[self removePopedViewControllers:poppedViewControllers];
208
 	} rejection:^(NSString *code, NSString *message, NSError *error) {
210
 	} rejection:^(NSString *code, NSString *message, NSError *error) {
209
 		
211
 		
222
 	}];
224
 	}];
223
 }
225
 }
224
 
226
 
225
-- (void)dismissModal:(NSString*)componentId completion:(RNNTransitionCompletionBlock)completion {
227
+- (void)dismissModal:(NSString*)componentId mergeOptions:(NSDictionary *)options completion:(RNNTransitionCompletionBlock)completion {
226
 	[self assertReady];
228
 	[self assertReady];
227
 	
229
 	
228
 	[CATransaction begin];
230
 	[CATransaction begin];
230
 		[_eventEmitter sendOnNavigationCommandCompletion:dismissModal params:@{@"componentId": componentId}];
232
 		[_eventEmitter sendOnNavigationCommandCompletion:dismissModal params:@{@"componentId": componentId}];
231
 	}];
233
 	}];
232
 	UIViewController<RNNRootViewProtocol> *modalToDismiss = (UIViewController<RNNRootViewProtocol>*)[_store findComponentForId:componentId];
234
 	UIViewController<RNNRootViewProtocol> *modalToDismiss = (UIViewController<RNNRootViewProtocol>*)[_store findComponentForId:componentId];
235
+	[modalToDismiss.getLeafViewController.options mergeWith:options];
236
+	
233
 	[self removePopedViewControllers:modalToDismiss.navigationController.viewControllers];
237
 	[self removePopedViewControllers:modalToDismiss.navigationController.viewControllers];
234
 	
238
 	
235
 	[_modalManager dismissModal:modalToDismiss completion:completion];
239
 	[_modalManager dismissModal:modalToDismiss completion:completion];
237
 	[CATransaction commit];
241
 	[CATransaction commit];
238
 }
242
 }
239
 
243
 
240
-- (void)dismissAllModalsWithCompletion:(RNNTransitionCompletionBlock)completion {
244
+- (void)dismissAllModals:(NSDictionary *)mergeOptions completion:(RNNTransitionCompletionBlock)completion {
241
 	[self assertReady];
245
 	[self assertReady];
242
 	
246
 	
243
 	[CATransaction begin];
247
 	[CATransaction begin];
245
 		[_eventEmitter sendOnNavigationCommandCompletion:dismissAllModals params:@{}];
249
 		[_eventEmitter sendOnNavigationCommandCompletion:dismissAllModals params:@{}];
246
 		completion();
250
 		completion();
247
 	}];
251
 	}];
248
-	
249
-	[_modalManager dismissAllModals];
252
+	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:mergeOptions];
253
+	[_modalManager dismissAllModalsAnimated:options.animations.dismissModal.enable];
250
 	
254
 	
251
 	[CATransaction commit];
255
 	[CATransaction commit];
252
 }
256
 }

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

16
 
16
 
17
 - (void)showModal:(UIViewController*)viewController animated:(BOOL)animated completion:(RNNTransitionWithComponentIdCompletionBlock)completion;
17
 - (void)showModal:(UIViewController*)viewController animated:(BOOL)animated completion:(RNNTransitionWithComponentIdCompletionBlock)completion;
18
 - (void)dismissModal:(UIViewController *)viewController completion:(RNNTransitionCompletionBlock)completion;
18
 - (void)dismissModal:(UIViewController *)viewController completion:(RNNTransitionCompletionBlock)completion;
19
-- (void)dismissAllModals;
19
+- (void)dismissAllModalsAnimated:(BOOL)animated;
20
 
20
 
21
 @end
21
 @end

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

68
 	}
68
 	}
69
 }
69
 }
70
 
70
 
71
--(void)dismissAllModals {
71
+-(void)dismissAllModalsAnimated:(BOOL)animated {
72
 	UIViewController *root = UIApplication.sharedApplication.delegate.window.rootViewController;
72
 	UIViewController *root = UIApplication.sharedApplication.delegate.window.rootViewController;
73
-	[root dismissViewControllerAnimated:YES completion:nil];
73
+	[root dismissViewControllerAnimated:animated completion:nil];
74
 	[_delegate dismissedMultipleModals:_presentedModals];
74
 	[_delegate dismissedMultipleModals:_presentedModals];
75
 	[_pendingModalIdsToDismiss removeAllObjects];
75
 	[_pendingModalIdsToDismiss removeAllObjects];
76
 	[_presentedModals removeAllObjects];
76
 	[_presentedModals removeAllObjects];

+ 3
- 3
lib/ios/ReactNativeNavigationTests/RNNCommandsHandlerTest.m View File

121
 	[self.store setReadyToReceiveCommands:true];
121
 	[self.store setReadyToReceiveCommands:true];
122
 	XCTestExpectation *expectation = [self expectationWithDescription:@"Testing Async Method"];
122
 	XCTestExpectation *expectation = [self expectationWithDescription:@"Testing Async Method"];
123
 
123
 
124
-	[self.uut pop:@"vc3" options:nil completion:^{
124
+	[self.uut pop:@"vc3" mergeOptions:nil completion:^{
125
 		XCTAssertNil([self.store findComponentForId:@"vc3"]);
125
 		XCTAssertNil([self.store findComponentForId:@"vc3"]);
126
 		XCTAssertNotNil([self.store findComponentForId:@"vc2"]);
126
 		XCTAssertNotNil([self.store findComponentForId:@"vc2"]);
127
 		XCTAssertNotNil([self.store findComponentForId:@"vc1"]);
127
 		XCTAssertNotNil([self.store findComponentForId:@"vc1"]);
137
 	[self.store setReadyToReceiveCommands:true];
137
 	[self.store setReadyToReceiveCommands:true];
138
 	XCTestExpectation *expectation = [self expectationWithDescription:@"Testing Async Method"];
138
 	XCTestExpectation *expectation = [self expectationWithDescription:@"Testing Async Method"];
139
 	_nvc.willReturnVCs = @[self.vc2, self.vc3];
139
 	_nvc.willReturnVCs = @[self.vc2, self.vc3];
140
-	[self.uut popTo:@"vc1" completion:^{
140
+	[self.uut popTo:@"vc1" mergeOptions:nil completion:^{
141
 		XCTAssertNil([self.store findComponentForId:@"vc2"]);
141
 		XCTAssertNil([self.store findComponentForId:@"vc2"]);
142
 		XCTAssertNil([self.store findComponentForId:@"vc3"]);
142
 		XCTAssertNil([self.store findComponentForId:@"vc3"]);
143
 		XCTAssertNotNil([self.store findComponentForId:@"vc1"]);
143
 		XCTAssertNotNil([self.store findComponentForId:@"vc1"]);
151
 	[self.store setReadyToReceiveCommands:true];
151
 	[self.store setReadyToReceiveCommands:true];
152
 	_nvc.willReturnVCs = @[self.vc2, self.vc3];
152
 	_nvc.willReturnVCs = @[self.vc2, self.vc3];
153
 	XCTestExpectation *expectation = [self expectationWithDescription:@"Testing Async Method"];
153
 	XCTestExpectation *expectation = [self expectationWithDescription:@"Testing Async Method"];
154
-	[self.uut popToRoot:@"vc3" completion:^{
154
+	[self.uut popToRoot:@"vc3" mergeOptions:nil completion:^{
155
 		XCTAssertNil([self.store findComponentForId:@"vc2"]);
155
 		XCTAssertNil([self.store findComponentForId:@"vc2"]);
156
 		XCTAssertNil([self.store findComponentForId:@"vc3"]);
156
 		XCTAssertNil([self.store findComponentForId:@"vc3"]);
157
 		XCTAssertNotNil([self.store findComponentForId:@"vc1"]);
157
 		XCTAssertNotNil([self.store findComponentForId:@"vc1"]);

+ 4
- 4
lib/ios/ReactNativeNavigationTests/RNNModalManagerTest.m View File

48
 	[_modalManager showModal:_vc3 animated:NO completion:nil];
48
 	[_modalManager showModal:_vc3 animated:NO completion:nil];
49
 	
49
 	
50
 	_modalManager.delegate = self;
50
 	_modalManager.delegate = self;
51
-	[_modalManager dismissAllModals];
51
+	[_modalManager dismissAllModalsAnimated:NO];
52
 	
52
 	
53
 	XCTAssertTrue(_modalDismissedCount == 3);
53
 	XCTAssertTrue(_modalDismissedCount == 3);
54
 }
54
 }
75
 	XCTAssertTrue(_modalDismissedCount == 1);
75
 	XCTAssertTrue(_modalDismissedCount == 1);
76
 }
76
 }
77
 
77
 
78
-- (void)testDismissAllModalsAfterDismissingPreviousModal_InvokeDelegateWithCorrectParameters {
78
+- (void)testDismissAllModals_AfterDismissingPreviousModal_InvokeDelegateWithCorrectParameters {
79
 	[_modalManager showModal:_vc1 animated:NO completion:nil];
79
 	[_modalManager showModal:_vc1 animated:NO completion:nil];
80
 	[_modalManager showModal:_vc2 animated:NO completion:nil];
80
 	[_modalManager showModal:_vc2 animated:NO completion:nil];
81
 	[_modalManager showModal:_vc3 animated:NO completion:nil];
81
 	[_modalManager showModal:_vc3 animated:NO completion:nil];
84
 	[_modalManager dismissModal:_vc2 completion:nil];
84
 	[_modalManager dismissModal:_vc2 completion:nil];
85
 	
85
 	
86
 	XCTAssertTrue(_modalDismissedCount == 1);
86
 	XCTAssertTrue(_modalDismissedCount == 1);
87
-	[_modalManager dismissAllModals];
87
+	[_modalManager dismissAllModalsAnimated:NO];
88
 	XCTAssertTrue(_modalDismissedCount == 2);
88
 	XCTAssertTrue(_modalDismissedCount == 2);
89
 }
89
 }
90
 
90
 
91
-- (void)testDismissNilModal_doesntCrash {
91
+- (void)testDismissModal_DismissNilModalDoesntCrash {
92
 	_modalManager.delegate = self;
92
 	_modalManager.delegate = self;
93
 	[_modalManager dismissModal:nil completion:nil];
93
 	[_modalManager dismissModal:nil completion:nil];
94
 	
94
 	

+ 10
- 10
lib/src/Navigation.ts View File

92
   /**
92
   /**
93
    * Dismiss a modal by componentId. The dismissed modal can be anywhere in the stack.
93
    * Dismiss a modal by componentId. The dismissed modal can be anywhere in the stack.
94
    */
94
    */
95
-  public dismissModal(componentId: string): Promise<any> {
96
-    return this.commands.dismissModal(componentId);
95
+  public dismissModal(componentId: string, mergeOptions?): Promise<any> {
96
+    return this.commands.dismissModal(componentId, mergeOptions);
97
   }
97
   }
98
 
98
 
99
   /**
99
   /**
100
    * Dismiss all Modals
100
    * Dismiss all Modals
101
    */
101
    */
102
-  public dismissAllModals(): Promise<any> {
103
-    return this.commands.dismissAllModals();
102
+  public dismissAllModals(mergeOptions?): Promise<any> {
103
+    return this.commands.dismissAllModals(mergeOptions);
104
   }
104
   }
105
 
105
 
106
   /**
106
   /**
113
   /**
113
   /**
114
    * Pop a component from the stack, regardless of it's position.
114
    * Pop a component from the stack, regardless of it's position.
115
    */
115
    */
116
-  public pop(componentId: string, params?): Promise<any> {
117
-    return this.commands.pop(componentId, params);
116
+  public pop(componentId: string, mergeOptions?): Promise<any> {
117
+    return this.commands.pop(componentId, mergeOptions);
118
   }
118
   }
119
 
119
 
120
   /**
120
   /**
121
    * Pop the stack to a given component
121
    * Pop the stack to a given component
122
    */
122
    */
123
-  public popTo(componentId: string): Promise<any> {
124
-    return this.commands.popTo(componentId);
123
+  public popTo(componentId: string, mergeOptions?): Promise<any> {
124
+    return this.commands.popTo(componentId, mergeOptions);
125
   }
125
   }
126
 
126
 
127
   /**
127
   /**
128
    * Pop the component's stack to root.
128
    * Pop the component's stack to root.
129
    */
129
    */
130
-  public popToRoot(componentId: string): Promise<any> {
131
-    return this.commands.popToRoot(componentId);
130
+  public popToRoot(componentId: string, mergeOptions?): Promise<any> {
131
+    return this.commands.popToRoot(componentId, mergeOptions);
132
   }
132
   }
133
 
133
 
134
   /**
134
   /**

+ 8
- 8
lib/src/adapters/NativeCommandsSender.ts View File

26
     return this.nativeCommandsModule.pop(commandId, componentId, options);
26
     return this.nativeCommandsModule.pop(commandId, componentId, options);
27
   }
27
   }
28
 
28
 
29
-  popTo(commandId: string, componentId: string) {
30
-    return this.nativeCommandsModule.popTo(commandId, componentId);
29
+  popTo(commandId: string, componentId: string, options: object) {
30
+    return this.nativeCommandsModule.popTo(commandId, componentId, options);
31
   }
31
   }
32
 
32
 
33
-  popToRoot(commandId: string, componentId: string) {
34
-    return this.nativeCommandsModule.popToRoot(commandId, componentId);
33
+  popToRoot(commandId: string, componentId: string, options: object) {
34
+    return this.nativeCommandsModule.popToRoot(commandId, componentId, options);
35
   }
35
   }
36
 
36
 
37
   setStackRoot(commandId: string, onComponentId: string, layout: object) {
37
   setStackRoot(commandId: string, onComponentId: string, layout: object) {
42
     return this.nativeCommandsModule.showModal(commandId, layout);
42
     return this.nativeCommandsModule.showModal(commandId, layout);
43
   }
43
   }
44
 
44
 
45
-  dismissModal(commandId: string, componentId: string) {
46
-    return this.nativeCommandsModule.dismissModal(commandId, componentId);
45
+  dismissModal(commandId: string, componentId: string, options: object) {
46
+    return this.nativeCommandsModule.dismissModal(commandId, componentId, options);
47
   }
47
   }
48
 
48
 
49
-  dismissAllModals(commandId: string) {
50
-    return this.nativeCommandsModule.dismissAllModals(commandId);
49
+  dismissAllModals(commandId: string, options: object) {
50
+    return this.nativeCommandsModule.dismissAllModals(commandId, options);
51
   }
51
   }
52
 
52
 
53
   showOverlay(commandId: string, layout: object) {
53
   showOverlay(commandId: string, layout: object) {

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

202
 
202
 
203
   describe('dismissModal', () => {
203
   describe('dismissModal', () => {
204
     it('sends command to native', () => {
204
     it('sends command to native', () => {
205
-      uut.dismissModal('myUniqueId');
205
+      uut.dismissModal('myUniqueId', {});
206
       expect(mockCommandsSender.dismissModal).toHaveBeenCalledTimes(1);
206
       expect(mockCommandsSender.dismissModal).toHaveBeenCalledTimes(1);
207
-      expect(mockCommandsSender.dismissModal).toHaveBeenCalledWith('dismissModal+UNIQUE_ID', 'myUniqueId');
207
+      expect(mockCommandsSender.dismissModal).toHaveBeenCalledWith('dismissModal+UNIQUE_ID', 'myUniqueId', {});
208
     });
208
     });
209
 
209
 
210
     it('returns a promise with the id', async () => {
210
     it('returns a promise with the id', async () => {
216
 
216
 
217
   describe('dismissAllModals', () => {
217
   describe('dismissAllModals', () => {
218
     it('sends command to native', () => {
218
     it('sends command to native', () => {
219
-      uut.dismissAllModals();
219
+      uut.dismissAllModals({});
220
       expect(mockCommandsSender.dismissAllModals).toHaveBeenCalledTimes(1);
220
       expect(mockCommandsSender.dismissAllModals).toHaveBeenCalledTimes(1);
221
-      expect(mockCommandsSender.dismissAllModals).toHaveBeenCalledWith('dismissAllModals+UNIQUE_ID');
221
+      expect(mockCommandsSender.dismissAllModals).toHaveBeenCalledWith('dismissAllModals+UNIQUE_ID', {});
222
     });
222
     });
223
 
223
 
224
     it('returns a promise with the id', async () => {
224
     it('returns a promise with the id', async () => {
285
 
285
 
286
   describe('popTo', () => {
286
   describe('popTo', () => {
287
     it('pops all components until the passed Id is top', () => {
287
     it('pops all components until the passed Id is top', () => {
288
-      uut.popTo('theComponentId');
288
+      uut.popTo('theComponentId', {});
289
       expect(mockCommandsSender.popTo).toHaveBeenCalledTimes(1);
289
       expect(mockCommandsSender.popTo).toHaveBeenCalledTimes(1);
290
-      expect(mockCommandsSender.popTo).toHaveBeenCalledWith('popTo+UNIQUE_ID', 'theComponentId');
290
+      expect(mockCommandsSender.popTo).toHaveBeenCalledWith('popTo+UNIQUE_ID', 'theComponentId', {});
291
     });
291
     });
292
 
292
 
293
     it('returns a promise that resolves to targetId', async () => {
293
     it('returns a promise that resolves to targetId', async () => {
299
 
299
 
300
   describe('popToRoot', () => {
300
   describe('popToRoot', () => {
301
     it('pops all components to root', () => {
301
     it('pops all components to root', () => {
302
-      uut.popToRoot('theComponentId');
302
+      uut.popToRoot('theComponentId', {});
303
       expect(mockCommandsSender.popToRoot).toHaveBeenCalledTimes(1);
303
       expect(mockCommandsSender.popToRoot).toHaveBeenCalledTimes(1);
304
-      expect(mockCommandsSender.popToRoot).toHaveBeenCalledWith('popToRoot+UNIQUE_ID', 'theComponentId');
304
+      expect(mockCommandsSender.popToRoot).toHaveBeenCalledWith('popToRoot+UNIQUE_ID', 'theComponentId', {});
305
     });
305
     });
306
 
306
 
307
     it('returns a promise that resolves to targetId', async () => {
307
     it('returns a promise that resolves to targetId', async () => {
428
         setDefaultOptions: [{}],
428
         setDefaultOptions: [{}],
429
         mergeOptions: ['id', {}],
429
         mergeOptions: ['id', {}],
430
         showModal: [{}],
430
         showModal: [{}],
431
-        dismissModal: ['id'],
432
-        dismissAllModals: [],
431
+        dismissModal: ['id', {}],
432
+        dismissAllModals: [{}],
433
         push: ['id', {}],
433
         push: ['id', {}],
434
         pop: ['id', {}],
434
         pop: ['id', {}],
435
-        popTo: ['id'],
436
-        popToRoot: ['id'],
435
+        popTo: ['id', {}],
436
+        popToRoot: ['id', {}],
437
         setStackRoot: ['id', {}],
437
         setStackRoot: ['id', {}],
438
         showOverlay: [{}],
438
         showOverlay: [{}],
439
         dismissOverlay: ['id'],
439
         dismissOverlay: ['id'],
444
         setDefaultOptions: { options: {} },
444
         setDefaultOptions: { options: {} },
445
         mergeOptions: { componentId: 'id', options: {} },
445
         mergeOptions: { componentId: 'id', options: {} },
446
         showModal: { commandId: 'showModal+UNIQUE_ID', layout: 'parsed' },
446
         showModal: { commandId: 'showModal+UNIQUE_ID', layout: 'parsed' },
447
-        dismissModal: { commandId: 'dismissModal+UNIQUE_ID', componentId: 'id' },
448
-        dismissAllModals: { commandId: 'dismissAllModals+UNIQUE_ID' },
447
+        dismissModal: { commandId: 'dismissModal+UNIQUE_ID', componentId: 'id', mergeOptions: {} },
448
+        dismissAllModals: { commandId: 'dismissAllModals+UNIQUE_ID', mergeOptions: {} },
449
         push: { commandId: 'push+UNIQUE_ID', componentId: 'id', layout: 'parsed' },
449
         push: { commandId: 'push+UNIQUE_ID', componentId: 'id', layout: 'parsed' },
450
-        pop: { commandId: 'pop+UNIQUE_ID', componentId: 'id', options: {} },
451
-        popTo: { commandId: 'popTo+UNIQUE_ID', componentId: 'id' },
452
-        popToRoot: { commandId: 'popToRoot+UNIQUE_ID', componentId: 'id' },
450
+        pop: { commandId: 'pop+UNIQUE_ID', componentId: 'id', mergeOptions: {} },
451
+        popTo: { commandId: 'popTo+UNIQUE_ID', componentId: 'id', mergeOptions: {} },
452
+        popToRoot: { commandId: 'popToRoot+UNIQUE_ID', componentId: 'id', mergeOptions: {} },
453
         setStackRoot: { commandId: 'setStackRoot+UNIQUE_ID', componentId: 'id', layout: 'parsed' },
453
         setStackRoot: { commandId: 'setStackRoot+UNIQUE_ID', componentId: 'id', layout: 'parsed' },
454
         showOverlay: { commandId: 'showOverlay+UNIQUE_ID', layout: 'parsed' },
454
         showOverlay: { commandId: 'showOverlay+UNIQUE_ID', layout: 'parsed' },
455
         dismissOverlay: { commandId: 'dismissOverlay+UNIQUE_ID', componentId: 'id' },
455
         dismissOverlay: { commandId: 'dismissOverlay+UNIQUE_ID', componentId: 'id' },

+ 15
- 15
lib/src/commands/Commands.ts View File

62
     return result;
62
     return result;
63
   }
63
   }
64
 
64
 
65
-  public dismissModal(componentId) {
65
+  public dismissModal(componentId, mergeOptions?) {
66
     const commandId = this.uniqueIdProvider.generate('dismissModal');
66
     const commandId = this.uniqueIdProvider.generate('dismissModal');
67
-    const result = this.nativeCommandsSender.dismissModal(commandId, componentId);
68
-    this.commandsObserver.notify('dismissModal', { commandId, componentId });
67
+    const result = this.nativeCommandsSender.dismissModal(commandId, componentId, mergeOptions);
68
+    this.commandsObserver.notify('dismissModal', { commandId, componentId, mergeOptions});
69
     return result;
69
     return result;
70
   }
70
   }
71
 
71
 
72
-  public dismissAllModals() {
72
+  public dismissAllModals(mergeOptions?) {
73
     const commandId = this.uniqueIdProvider.generate('dismissAllModals');
73
     const commandId = this.uniqueIdProvider.generate('dismissAllModals');
74
-    const result = this.nativeCommandsSender.dismissAllModals(commandId);
75
-    this.commandsObserver.notify('dismissAllModals', { commandId });
74
+    const result = this.nativeCommandsSender.dismissAllModals(commandId, mergeOptions);
75
+    this.commandsObserver.notify('dismissAllModals', { commandId, mergeOptions });
76
     return result;
76
     return result;
77
   }
77
   }
78
 
78
 
88
     return result;
88
     return result;
89
   }
89
   }
90
 
90
 
91
-  public pop(componentId, options) {
91
+  public pop(componentId, mergeOptions?) {
92
     const commandId = this.uniqueIdProvider.generate('pop');
92
     const commandId = this.uniqueIdProvider.generate('pop');
93
-    const result = this.nativeCommandsSender.pop(commandId, componentId, options);
94
-    this.commandsObserver.notify('pop', { commandId, componentId, options });
93
+    const result = this.nativeCommandsSender.pop(commandId, componentId, mergeOptions);
94
+    this.commandsObserver.notify('pop', { commandId, componentId, mergeOptions });
95
     return result;
95
     return result;
96
   }
96
   }
97
 
97
 
98
-  public popTo(componentId) {
98
+  public popTo(componentId, mergeOptions?) {
99
     const commandId = this.uniqueIdProvider.generate('popTo');
99
     const commandId = this.uniqueIdProvider.generate('popTo');
100
-    const result = this.nativeCommandsSender.popTo(commandId, componentId);
101
-    this.commandsObserver.notify('popTo', { commandId, componentId });
100
+    const result = this.nativeCommandsSender.popTo(commandId, componentId, mergeOptions);
101
+    this.commandsObserver.notify('popTo', { commandId, componentId, mergeOptions });
102
     return result;
102
     return result;
103
   }
103
   }
104
 
104
 
105
-  public popToRoot(componentId) {
105
+  public popToRoot(componentId, mergeOptions?) {
106
     const commandId = this.uniqueIdProvider.generate('popToRoot');
106
     const commandId = this.uniqueIdProvider.generate('popToRoot');
107
-    const result = this.nativeCommandsSender.popToRoot(commandId, componentId);
108
-    this.commandsObserver.notify('popToRoot', { commandId, componentId });
107
+    const result = this.nativeCommandsSender.popToRoot(commandId, componentId, mergeOptions);
108
+    this.commandsObserver.notify('popToRoot', { commandId, componentId, mergeOptions });
109
     return result;
109
     return result;
110
   }
110
   }
111
 
111