From 7bf78eae5e2d53438bc333d3b9995b218f74c84b Mon Sep 17 00:00:00 2001 From: Paige Sun Date: Sun, 2 May 2021 15:41:22 -0700 Subject: [PATCH] iOS: 5/7 Use visible prop to dismiss Modal for Paper Summary: Changelog: [iOS] Use visible prop to dismiss Modal on old renderer. Visible prop is used on Fabric so that onDismiss can be passed with the the bridgeless per-component event emitter, rather than the bridge global event emitter. The old renderer still uses the global event emitter. I needed to use the visible prop for Paper too because in diff 6/7, Modal.js [no longer uses visible prop to return null](https://github.com/facebook/react-native/blob/dc80b2dcb52fadec6a573a9dd1824393f8c29fdc/Libraries/Modal/Modal.js#L221-L222), and Modal.js can't distinguish on whether it's a Fabric or Paper component. Reviewed By: JoshuaGross Differential Revision: D28137929 fbshipit-source-id: f6ede0019fbe498a10b822ff09fc135a9fff8ec0 --- React/Views/RCTModalHostView.h | 4 ++ React/Views/RCTModalHostView.m | 56 +++++++++++++++++---------- React/Views/RCTModalHostViewManager.m | 2 +- 3 files changed, 41 insertions(+), 21 deletions(-) diff --git a/React/Views/RCTModalHostView.h b/React/Views/RCTModalHostView.h index c54c1c69c94..880b24c9a48 100644 --- a/React/Views/RCTModalHostView.h +++ b/React/Views/RCTModalHostView.h @@ -23,6 +23,7 @@ @property (nonatomic, assign, getter=isTransparent) BOOL transparent; @property (nonatomic, copy) RCTDirectEventBlock onShow; +@property (nonatomic, assign) BOOL visible; @property (nonatomic, copy) NSNumber *identifier; @@ -31,6 +32,9 @@ @property (nonatomic, copy) NSArray *supportedOrientations; @property (nonatomic, copy) RCTDirectEventBlock onOrientationChange; +// Fabric only +@property (nonatomic, copy) RCTBubblingEventBlock onDismiss; + - (instancetype)initWithBridge:(RCTBridge *)bridge NS_DESIGNATED_INITIALIZER; @end diff --git a/React/Views/RCTModalHostView.m b/React/Views/RCTModalHostView.m index 0cfa69a99aa..fa9aae7a2c1 100644 --- a/React/Views/RCTModalHostView.m +++ b/React/Views/RCTModalHostView.m @@ -119,31 +119,13 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : coder) return; } - if (!_isPresented && self.window) { - RCTAssert(self.reactViewController, @"Can't present modal view controller without a presenting view controller"); - - _modalViewController.supportedInterfaceOrientations = [self supportedOrientationsMask]; - - if ([self.animationType isEqualToString:@"fade"]) { - _modalViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; - } else if ([self.animationType isEqualToString:@"slide"]) { - _modalViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical; - } - if (self.presentationStyle != UIModalPresentationNone) { - _modalViewController.modalPresentationStyle = self.presentationStyle; - } - [_delegate presentModalHostView:self withViewController:_modalViewController animated:[self hasAnimationType]]; - _isPresented = YES; - } + [self ensurePresentedOnlyIfNeeded]; } - (void)didMoveToSuperview { [super didMoveToSuperview]; - - if (_isPresented && !self.superview) { - [self dismissModalViewController]; - } + [self ensurePresentedOnlyIfNeeded]; } - (void)invalidate @@ -163,6 +145,40 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : coder) return ![self.animationType isEqualToString:@"none"]; } +- (void)setVisible:(BOOL)visible +{ + if (_visible != visible) { + _visible = visible; + [self ensurePresentedOnlyIfNeeded]; + } +} + +- (void)ensurePresentedOnlyIfNeeded +{ + BOOL shouldBePresented = !_isPresented && _visible && self.window; + if (shouldBePresented) { + RCTAssert(self.reactViewController, @"Can't present modal view controller without a presenting view controller"); + + _modalViewController.supportedInterfaceOrientations = [self supportedOrientationsMask]; + + if ([self.animationType isEqualToString:@"fade"]) { + _modalViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; + } else if ([self.animationType isEqualToString:@"slide"]) { + _modalViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical; + } + if (self.presentationStyle != UIModalPresentationNone) { + _modalViewController.modalPresentationStyle = self.presentationStyle; + } + [_delegate presentModalHostView:self withViewController:_modalViewController animated:[self hasAnimationType]]; + _isPresented = YES; + } + + BOOL shouldBeHidden = _isPresented && (!_visible || !self.superview); + if (shouldBeHidden) { + [self dismissModalViewController]; + } +} + - (void)setTransparent:(BOOL)transparent { if (self.isTransparent != transparent) { diff --git a/React/Views/RCTModalHostViewManager.m b/React/Views/RCTModalHostViewManager.m index 5304d41cf5e..7ca197d5866 100644 --- a/React/Views/RCTModalHostViewManager.m +++ b/React/Views/RCTModalHostViewManager.m @@ -120,9 +120,9 @@ RCT_EXPORT_VIEW_PROPERTY(onShow, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(identifier, NSNumber) RCT_EXPORT_VIEW_PROPERTY(supportedOrientations, NSArray) RCT_EXPORT_VIEW_PROPERTY(onOrientationChange, RCTDirectEventBlock) +RCT_EXPORT_VIEW_PROPERTY(visible, BOOL) // Fabric only -RCT_EXPORT_VIEW_PROPERTY(visible, BOOL) RCT_EXPORT_VIEW_PROPERTY(onDismiss, RCTDirectEventBlock) @end