Skip to content

Instantly share code, notes, and snippets.

@mrousavy
Last active January 29, 2022 04:14
Show Gist options
  • Save mrousavy/b4a4ce2df5ff61d12f46829edb132c7c to your computer and use it in GitHub Desktop.
Save mrousavy/b4a4ce2df5ff61d12f46829edb132c7c to your computer and use it in GitHub Desktop.
react-native 0.63 patch for iOS 13 Modal's onRequestClose (Swipe down gesture)
diff --git a/node_modules/react-native/React/Views/RCTModalHostView.h b/node_modules/react-native/React/Views/RCTModalHostView.h
index 4e61886..2b8b6c0 100644
--- a/node_modules/react-native/React/Views/RCTModalHostView.h
+++ b/node_modules/react-native/React/Views/RCTModalHostView.h
@@ -17,7 +17,7 @@
@protocol RCTModalHostViewInteractor;
-@interface RCTModalHostView : UIView <RCTInvalidating>
+@interface RCTModalHostView : UIView <RCTInvalidating, UIAdaptivePresentationControllerDelegate>
@property (nonatomic, copy) NSString *animationType;
@property (nonatomic, assign) UIModalPresentationStyle presentationStyle;
@@ -31,9 +31,9 @@
@property (nonatomic, copy) NSArray<NSString *> *supportedOrientations;
@property (nonatomic, copy) RCTDirectEventBlock onOrientationChange;
+@property (nonatomic, copy) RCTDirectEventBlock onRequestClose;
#if TARGET_OS_TV
-@property (nonatomic, copy) RCTDirectEventBlock onRequestClose;
@property (nonatomic, strong) RCTTVRemoteHandler *tvRemoteHandler;
#endif
diff --git a/node_modules/react-native/React/Views/RCTModalHostView.m b/node_modules/react-native/React/Views/RCTModalHostView.m
index 6a15330..5269b20 100644
--- a/node_modules/react-native/React/Views/RCTModalHostView.m
+++ b/node_modules/react-native/React/Views/RCTModalHostView.m
@@ -41,6 +41,10 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge
if ((self = [super initWithFrame:CGRectZero])) {
_bridge = bridge;
_modalViewController = [RCTModalHostViewController new];
+ // Transparency breaks for overFullScreen in iOS < 13
+ if (@available(iOS 13.0, *)) {
+ _modalViewController.presentationController.delegate = self;
+ }
UIView *containerView = [UIView new];
containerView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
_modalViewController.view = containerView;
@@ -62,6 +66,26 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge
return self;
}
+// Method must be implemented, otherwise iOS defaults to 'automatic' (pageSheet on >= iOS 13.0)
+- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller traitCollection:(UITraitCollection *)traitCollection
+{
+ if (self.presentationStyle == UIModalPresentationFullScreen && self.isTransparent) {
+ return UIModalPresentationOverFullScreen;
+ }
+ return self.presentationStyle;
+}
+
+// Method must be implemented, otherwise iOS defaults to 'automatic' (pageSheet on >= iOS 13.0)
+- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller
+{
+ if (self.presentationStyle == UIModalPresentationFullScreen && self.isTransparent) {
+ return UIModalPresentationOverFullScreen;
+ }
+ return self.presentationStyle;
+}
+
+
+
#if TARGET_OS_TV
- (void)menuButtonPressed:(__unused UIGestureRecognizer *)gestureRecognizer
{
@@ -69,10 +93,12 @@ - (void)menuButtonPressed:(__unused UIGestureRecognizer *)gestureRecognizer
_onRequestClose(nil);
}
}
+#endif
- (void)setOnRequestClose:(RCTDirectEventBlock)onRequestClose
{
_onRequestClose = onRequestClose;
+ #if TARGET_OS_TV
if (_reactSubview) {
if (_onRequestClose && _menuButtonGestureRecognizer) {
[_reactSubview addGestureRecognizer:_menuButtonGestureRecognizer];
@@ -80,8 +106,8 @@ - (void)setOnRequestClose:(RCTDirectEventBlock)onRequestClose
[_reactSubview removeGestureRecognizer:_menuButtonGestureRecognizer];
}
}
+ #endif
}
-#endif
- (void)notifyForBoundsChange:(CGRect)newBounds
{
@@ -155,6 +181,13 @@ - (void)didUpdateReactSubviews
// Do nothing, as subview (singular) is managed by `insertReactSubview:atIndex:`
}
+- (void)presentationControllerDidDismiss:(UIPresentationController *)presentationController
+{
+ if (_onRequestClose) {
+ _onRequestClose(nil);
+ }
+}
+
- (void)dismissModalViewController
{
if (_isPresented) {
@@ -187,6 +220,9 @@ - (void)didMoveToWindow
if (self.presentationStyle != UIModalPresentationNone) {
_modalViewController.modalPresentationStyle = self.presentationStyle;
}
+ if (@available(iOS 13.0, *)) {
+ _modalViewController.modalInPresentation = self.presentationStyle != UIModalPresentationFormSheet && self.presentationStyle != UIModalPresentationPageSheet;
+ }
[_delegate presentModalHostView:self withViewController:_modalViewController animated:[self hasAnimationType]];
_isPresented = YES;
}
diff --git a/node_modules/react-native/React/Views/RCTModalHostViewManager.m b/node_modules/react-native/React/Views/RCTModalHostViewManager.m
index bafab9d..56944ef 100644
--- a/node_modules/react-native/React/Views/RCTModalHostViewManager.m
+++ b/node_modules/react-native/React/Views/RCTModalHostViewManager.m
@@ -79,9 +79,19 @@ - (void)presentModalHostView:(RCTModalHostView *)modalHostView
if (_presentationBlock) {
_presentationBlock([modalHostView reactViewController], viewController, animated, completionBlock);
} else {
- [[modalHostView reactViewController] presentViewController:viewController
- animated:animated
- completion:completionBlock];
+ UIViewController *topViewController = [modalHostView reactViewController];
+ while (topViewController.presentedViewController != nil) {
+ if ([topViewController.presentedViewController isKindOfClass:UIAlertController.class]) {
+ // Don't present on top of UIAlertController, this will mess it up:
+ // https://stackoverflow.com/questions/27028983/uialertcontroller-is-moved-to-buggy-position-at-top-of-screen-when-it-calls-pre
+ [topViewController dismissViewControllerAnimated:animated completion:^{
+ [topViewController presentViewController:viewController animated:animated completion:completionBlock];
+ }];
+ return;
+ }
+ topViewController = topViewController.presentedViewController;
+ }
+ [topViewController presentViewController:viewController animated:animated completion:completionBlock];
}
}
@@ -116,9 +126,6 @@ - (void)invalidate
RCT_EXPORT_VIEW_PROPERTY(identifier, NSNumber)
RCT_EXPORT_VIEW_PROPERTY(supportedOrientations, NSArray)
RCT_EXPORT_VIEW_PROPERTY(onOrientationChange, RCTDirectEventBlock)
-
-#if TARGET_OS_TV
RCT_EXPORT_VIEW_PROPERTY(onRequestClose, RCTDirectEventBlock)
-#endif
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment