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.
- package/ios/RNSScreenStack.mm +71 -10
- package/package.json +1 -1
package/ios/RNSScreenStack.mm
CHANGED
|
@@ -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
|
|
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
|
-
|
|
444
|
-
|
|
482
|
+
UIViewController *firstModalToBeDismissed = changeRootController.presentedViewController;
|
|
483
|
+
if (firstModalToBeDismissed != nil) {
|
|
445
484
|
BOOL shouldAnimate = changeRootIndex == controllers.count &&
|
|
446
|
-
[
|
|
447
|
-
((RNSScreen *)
|
|
448
|
-
|
|
449
|
-
[
|
|
450
|
-
|
|
451
|
-
|
|
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
|