react-native-screens 3.28.0 → 3.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -323,6 +323,38 @@ namespace react = facebook::react;
323
323
  }
324
324
  }
325
325
 
326
+ + (UIViewController *)findTopMostPresentedViewControllerFromViewController:(UIViewController *)controller
327
+ {
328
+ auto presentedVc = controller;
329
+ while (presentedVc.presentedViewController != nil) {
330
+ presentedVc = presentedVc.presentedViewController;
331
+ }
332
+ return presentedVc;
333
+ }
334
+
335
+ - (UIViewController *)findReactRootViewController
336
+ {
337
+ UIView *parent = self;
338
+ while (parent) {
339
+ parent = parent.reactSuperview;
340
+ if (parent.isReactRootView) {
341
+ return parent.reactViewController;
342
+ }
343
+ }
344
+ return nil;
345
+ }
346
+
347
+ - (UIViewController *)lastFromPresentedViewControllerChainStartingFrom:(UIViewController *)vc
348
+ {
349
+ UIViewController *lastNonNullVc = vc;
350
+ UIViewController *lastVc = vc.presentedViewController;
351
+ while (lastVc != nil) {
352
+ lastNonNullVc = lastVc;
353
+ lastVc = lastVc.presentedViewController;
354
+ }
355
+ return lastNonNullVc;
356
+ }
357
+
326
358
  - (void)setModalViewControllers:(NSArray<UIViewController *> *)controllers
327
359
  {
328
360
  // prevent re-entry
@@ -349,9 +381,15 @@ namespace react = facebook::react;
349
381
  NSMutableArray<UIViewController *> *newControllers = [NSMutableArray arrayWithArray:controllers];
350
382
  [newControllers removeObjectsInArray:_presentedModals];
351
383
 
352
- // find bottom-most controller that should stay on the stack for the duration of transition
384
+ // We need to find bottom-most view controller that should stay on the stack
385
+ // for the duration of transition. There are couple of scenarios:
386
+ // (1) No modals are presented or all modals were presented by this RNSNavigationController,
387
+ // (2) There are modals presented by other RNSNavigationControllers (nested/outer)
388
+
389
+ // Last controller that is common for both _presentedModals & controllers
390
+ __block UIViewController *changeRootController = _controller;
391
+ // Last common controller index + 1
353
392
  NSUInteger changeRootIndex = 0;
354
- UIViewController *changeRootController = _controller;
355
393
  for (NSUInteger i = 0; i < MIN(_presentedModals.count, controllers.count); i++) {
356
394
  if (_presentedModals[i] == controllers[i]) {
357
395
  changeRootController = controllers[i];
@@ -403,6 +441,7 @@ namespace react = facebook::react;
403
441
  return;
404
442
  } else {
405
443
  UIViewController *previous = changeRootController;
444
+
406
445
  for (NSUInteger i = changeRootIndex; i < controllers.count; i++) {
407
446
  UIViewController *next = controllers[i];
408
447
  BOOL lastModal = (i == controllers.count - 1);
@@ -440,16 +479,38 @@ namespace react = facebook::react;
440
479
  }
441
480
  };
442
481
 
443
- if (changeRootController.presentedViewController != nil &&
444
- [_presentedModals containsObject:changeRootController.presentedViewController]) {
482
+ UIViewController *firstModalToBeDismissed = changeRootController.presentedViewController;
483
+ if (firstModalToBeDismissed != nil) {
445
484
  BOOL shouldAnimate = changeRootIndex == controllers.count &&
446
- [changeRootController.presentedViewController isKindOfClass:[RNSScreen class]] &&
447
- ((RNSScreen *)changeRootController.presentedViewController).screenView.stackAnimation !=
448
- RNSScreenStackAnimationNone;
449
- [changeRootController dismissViewControllerAnimated:shouldAnimate completion:finish];
450
- } else {
451
- finish();
485
+ [firstModalToBeDismissed isKindOfClass:[RNSScreen class]] &&
486
+ ((RNSScreen *)firstModalToBeDismissed).screenView.stackAnimation != RNSScreenStackAnimationNone;
487
+
488
+ if ([_presentedModals containsObject:firstModalToBeDismissed]) {
489
+ // We dismiss every VC that was presented by changeRootController VC or its descendant.
490
+ // After the series of dismissals is completed we run completion block in which
491
+ // we present modals on top of changeRootController (which may be the this stack VC)
492
+ [changeRootController dismissViewControllerAnimated:shouldAnimate completion:finish];
493
+ return;
494
+ }
495
+
496
+ UIViewController *lastModalVc = [self lastFromPresentedViewControllerChainStartingFrom:firstModalToBeDismissed];
497
+
498
+ if (lastModalVc != firstModalToBeDismissed) {
499
+ [lastModalVc dismissViewControllerAnimated:shouldAnimate completion:finish];
500
+ return;
501
+ }
502
+ }
503
+
504
+ // changeRootController does not have presentedViewController but it does not mean that no modals are in presentation,
505
+ // so we need to find top-level controller manually
506
+ UIViewController *reactRootVc = [self findReactRootViewController];
507
+ UIViewController *topMostVc = [RNSScreenStackView findTopMostPresentedViewControllerFromViewController:reactRootVc];
508
+
509
+ if (topMostVc != reactRootVc) {
510
+ changeRootController = topMostVc;
452
511
  }
512
+
513
+ finish();
453
514
  }
454
515
 
455
516
  - (void)setPushViewControllers:(NSArray<UIViewController *> *)controllers
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-screens",
3
- "version": "3.28.0",
3
+ "version": "3.29.0",
4
4
  "description": "Native navigation primitives for your React Native app.",
5
5
  "scripts": {
6
6
  "check-types": "tsc --noEmit",