diff --git a/RNScreens.podspec b/RNScreens.podspec index 612f7c33c0..d82234d567 100644 --- a/RNScreens.podspec +++ b/RNScreens.podspec @@ -60,7 +60,7 @@ Pod::Spec.new do |s| s.homepage = "https://github.com/software-mansion/react-native-screens" s.license = "MIT" s.author = { "author" => "author@domain.cn" } - s.platforms = { :ios => platform, :tvos => "11.0" } + s.platforms = { :ios => platform, :tvos => "11.0", :visionos => "1.0" } s.source = { :git => "https://github.com/software-mansion/react-native-screens.git", :tag => "#{s.version}" } s.source_files = source_files s.requires_arc = true diff --git a/ios/RNSConvert.h b/ios/RNSConvert.h index 17b0485dc8..dcf0232636 100644 --- a/ios/RNSConvert.h +++ b/ios/RNSConvert.h @@ -26,8 +26,10 @@ namespace react = facebook::react; + (NSDictionary *)gestureResponseDistanceDictFromCppStruct: (const react::RNSScreenGestureResponseDistanceStruct &)gestureResponseDistance; +#if !TARGET_OS_VISION + (UITextAutocapitalizationType)UITextAutocapitalizationTypeFromCppEquivalent: (react::RNSSearchBarAutoCapitalize)autoCapitalize; +#endif + (RNSSearchBarPlacement)RNSScreenSearchBarPlacementFromCppEquivalent:(react::RNSSearchBarPlacement)placement; diff --git a/ios/RNSConvert.mm b/ios/RNSConvert.mm index 70a1f39e2f..64c9301a88 100644 --- a/ios/RNSConvert.mm +++ b/ios/RNSConvert.mm @@ -123,6 +123,7 @@ + (NSDictionary *)gestureResponseDistanceDictFromCppStruct: }; } +#if !TARGET_OS_VISION + (UITextAutocapitalizationType)UITextAutocapitalizationTypeFromCppEquivalent: (react::RNSSearchBarAutoCapitalize)autoCapitalize { @@ -137,6 +138,7 @@ + (UITextAutocapitalizationType)UITextAutocapitalizationTypeFromCppEquivalent: return UITextAutocapitalizationTypeNone; } } +#endif + (RNSSearchBarPlacement)RNSScreenSearchBarPlacementFromCppEquivalent:(react::RNSSearchBarPlacement)placement { diff --git a/ios/RNSScreen.mm b/ios/RNSScreen.mm index a4cbfe27ae..f07d591f40 100644 --- a/ios/RNSScreen.mm +++ b/ios/RNSScreen.mm @@ -229,7 +229,7 @@ - (void)setActivityStateOrNil:(NSNumber *)activityStateOrNil } } -#if !TARGET_OS_TV +#if !TARGET_OS_TV && !TARGET_OS_VISION - (void)setStatusBarStyle:(RNSStatusBarStyle)statusBarStyle { _hasStatusBarStyleSet = YES; @@ -604,7 +604,7 @@ - (BOOL)isTransparentModal self.controller.modalPresentationStyle == UIModalPresentationOverCurrentContext; } -#if !TARGET_OS_TV +#if !TARGET_OS_TV && !TARGET_OS_VISION /** * Updates settings for sheet presentation controller. * Note that this method should not be called inside `stackPresentation` setter, because on Paper we don't have @@ -821,7 +821,7 @@ - (void)updateLayoutMetrics:(const react::LayoutMetrics &)layoutMetrics - (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask { [super finalizeUpdates:updateMask]; -#if !TARGET_OS_TV +#if !TARGET_OS_TV && !TARGET_OS_VISION [self updatePresentationStyle]; #endif // !TARGET_OS_TV } @@ -832,7 +832,7 @@ - (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask - (void)didSetProps:(NSArray *)changedProps { [super didSetProps:changedProps]; -#if !TARGET_OS_TV +#if !TARGET_OS_TV && !TARGET_OS_VISION [self updatePresentationStyle]; #endif // !TARGET_OS_TV } @@ -1065,7 +1065,7 @@ - (BOOL)hasNestedStack - (CGSize)getStatusBarHeightIsModal:(BOOL)isModal { -#if !TARGET_OS_TV +#if !TARGET_OS_TV && !TARGET_OS_VISION CGSize fallbackStatusBarSize = [[UIApplication sharedApplication] statusBarFrame].size; #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \ @@ -1505,7 +1505,7 @@ @implementation RNSScreenManager RCT_EXPORT_VIEW_PROPERTY(sheetExpandsWhenScrolledToEdge, BOOL); #endif -#if !TARGET_OS_TV +#if !TARGET_OS_TV && !TARGET_OS_VISION // See: // 1. https://github.com/software-mansion/react-native-screens/pull/1543 // 2. https://github.com/software-mansion/react-native-screens/pull/1596 diff --git a/ios/RNSScreenStack.mm b/ios/RNSScreenStack.mm index 643643c02f..caf3d2e2da 100644 --- a/ios/RNSScreenStack.mm +++ b/ios/RNSScreenStack.mm @@ -92,7 +92,7 @@ - (UIViewController *)childViewControllerForHomeIndicatorAutoHidden @end -#if !TARGET_OS_TV +#if !TARGET_OS_TV && !TARGET_OS_VISION @interface RNSScreenEdgeGestureRecognizer : UIScreenEdgePanGestureRecognizer @end @@ -150,7 +150,7 @@ - (void)initCommonProps _presentedModals = [NSMutableArray new]; _controller = [RNSNavigationController new]; _controller.delegate = self; -#if !TARGET_OS_TV +#if !TARGET_OS_TV && !TARGET_OS_VISION [self setupGestureHandlers]; #endif // we have to initialize viewControllers with a non empty array for @@ -731,7 +731,7 @@ - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer } RNSScreenView *topScreen = _reactSubviews.lastObject; -#if TARGET_OS_TV +#if TARGET_OS_TV || TARGET_OS_VISION [self cancelTouchesInParent]; return YES; #else @@ -774,7 +774,7 @@ - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer #endif // TARGET_OS_TV } -#if !TARGET_OS_TV +#if !TARGET_OS_TV && !TARGET_OS_VISION - (void)setupGestureHandlers { // gesture recognizers for custom stack animations @@ -951,7 +951,7 @@ - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event return [super hitTest:point withEvent:event]; } -#if !TARGET_OS_TV +#if !TARGET_OS_TV && !TARGET_OS_VISION - (BOOL)isScrollViewPanGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer { diff --git a/ios/RNSScreenStackHeaderConfig.mm b/ios/RNSScreenStackHeaderConfig.mm index 4fa7506285..92e03553df 100644 --- a/ios/RNSScreenStackHeaderConfig.mm +++ b/ios/RNSScreenStackHeaderConfig.mm @@ -227,7 +227,7 @@ + (void)setAnimatedConfig:(UIViewController *)vc withConfig:(RNSScreenStackHeade [navbar setTitleTextAttributes:attrs]; } -#if !TARGET_OS_TV +#if !TARGET_OS_TV && !TARGET_OS_VISION if (@available(iOS 11.0, *)) { if (config.largeTitle && (config.largeTitleFontFamily || config.largeTitleFontSize || config.largeTitleFontWeight || @@ -397,9 +397,12 @@ + (UINavigationBarAppearance *)buildAppearance:(UIViewController *)vc if (config.titleFontFamily || config.titleFontSize || config.titleFontWeight || config.titleColor) { NSMutableDictionary *attrs = [NSMutableDictionary new]; + // Ignore changing header title color on visionOS +#if !TARGET_OS_VISION if (config.titleColor) { attrs[NSForegroundColorAttributeName] = config.titleColor; } +#endif NSString *family = config.titleFontFamily ?: nil; NSNumber *size = config.titleFontSize ?: @17; @@ -422,9 +425,12 @@ + (UINavigationBarAppearance *)buildAppearance:(UIViewController *)vc config.largeTitleColor || config.titleColor) { NSMutableDictionary *largeAttrs = [NSMutableDictionary new]; + // Ignore changing header title color on visionOS +#if !TARGET_OS_VISION if (config.largeTitleColor || config.titleColor) { largeAttrs[NSForegroundColorAttributeName] = config.largeTitleColor ? config.largeTitleColor : config.titleColor; } +#endif NSString *largeFamily = config.largeTitleFontFamily ?: nil; NSNumber *largeSize = config.largeTitleFontSize ?: @34; diff --git a/ios/RNSScreenWindowTraits.h b/ios/RNSScreenWindowTraits.h index 1970b9d0b8..0665bdce6e 100644 --- a/ios/RNSScreenWindowTraits.h +++ b/ios/RNSScreenWindowTraits.h @@ -4,7 +4,7 @@ + (void)updateWindowTraits; -#if !TARGET_OS_TV +#if !TARGET_OS_TV && !TARGET_OS_VISION + (void)assertViewControllerBasedStatusBarAppearenceSet; #endif + (void)updateStatusBarAppearance; diff --git a/ios/RNSScreenWindowTraits.mm b/ios/RNSScreenWindowTraits.mm index e8a717ef37..e407fdb4ae 100644 --- a/ios/RNSScreenWindowTraits.mm +++ b/ios/RNSScreenWindowTraits.mm @@ -4,7 +4,7 @@ @implementation RNSScreenWindowTraits -#if !TARGET_OS_TV +#if !TARGET_OS_TV && !TARGET_OS_VISION + (void)assertViewControllerBasedStatusBarAppearenceSet { static dispatch_once_t once; @@ -22,21 +22,10 @@ + (void)assertViewControllerBasedStatusBarAppearenceSet + (void)updateStatusBarAppearance { -#if !TARGET_OS_TV +#if !TARGET_OS_TV && !TARGET_OS_VISION [UIView animateWithDuration:0.4 animations:^{ // duration based on "Programming iOS 13" p. 311 implementation -#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \ - __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0 - if (@available(iOS 13, *)) { - UIWindow *firstWindow = [[[UIApplication sharedApplication] windows] firstObject]; - if (firstWindow != nil) { - [[firstWindow rootViewController] setNeedsStatusBarAppearanceUpdate]; - } - } else -#endif - { - [UIApplication.sharedApplication.keyWindow.rootViewController setNeedsStatusBarAppearanceUpdate]; - } + [RCTKeyWindow().rootViewController setNeedsStatusBarAppearanceUpdate]; }]; #endif } @@ -44,21 +33,7 @@ + (void)updateStatusBarAppearance + (void)updateHomeIndicatorAutoHidden { #if !TARGET_OS_TV - -#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \ - __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0 - if (@available(iOS 13, *)) { - UIWindow *firstWindow = [[[UIApplication sharedApplication] windows] firstObject]; - if (firstWindow != nil) { - [[firstWindow rootViewController] setNeedsUpdateOfHomeIndicatorAutoHidden]; - } - } else -#endif - { - if (@available(iOS 11.0, *)) { - [UIApplication.sharedApplication.keyWindow.rootViewController setNeedsUpdateOfHomeIndicatorAutoHidden]; - } - } + [RCTKeyWindow().rootViewController setNeedsUpdateOfHomeIndicatorAutoHidden]; #endif } @@ -134,21 +109,10 @@ + (UIInterfaceOrientationMask)maskFromOrientation:(UIInterfaceOrientation)orient + (void)enforceDesiredDeviceOrientation { -#if !TARGET_OS_TV +#if !TARGET_OS_TV && !TARGET_OS_VISION dispatch_async(dispatch_get_main_queue(), ^{ - UIInterfaceOrientationMask orientationMask = UIInterfaceOrientationMaskAllButUpsideDown; -#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \ - __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0 - if (@available(iOS 13, *)) { - UIWindow *firstWindow = [[[UIApplication sharedApplication] windows] firstObject]; - if (firstWindow != nil) { - orientationMask = [firstWindow rootViewController].supportedInterfaceOrientations; - } - } else -#endif - { - orientationMask = UIApplication.sharedApplication.keyWindow.rootViewController.supportedInterfaceOrientations; - } + UIInterfaceOrientationMask orientationMask = [RCTKeyWindow().rootViewController supportedInterfaceOrientations]; + UIInterfaceOrientation currentDeviceOrientation = [RNSScreenWindowTraits interfaceOrientationFromDeviceOrientation:[[UIDevice currentDevice] orientation]]; UIInterfaceOrientation currentInterfaceOrientation = [RNSScreenWindowTraits interfaceOrientation]; @@ -211,7 +175,7 @@ + (void)updateWindowTraits [RNSScreenWindowTraits updateHomeIndicatorAutoHidden]; } -#if !TARGET_OS_TV +#if !TARGET_OS_TV && !TARGET_OS_VISION // based on // https://stackoverflow.com/questions/57965701/statusbarorientation-was-deprecated-in-ios-13-0-when-attempting-to-get-app-ori/61249908#61249908 + (UIInterfaceOrientation)interfaceOrientation @@ -219,11 +183,7 @@ + (UIInterfaceOrientation)interfaceOrientation #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \ __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0 if (@available(iOS 13.0, *)) { - UIWindow *firstWindow = [[[UIApplication sharedApplication] windows] firstObject]; - if (firstWindow == nil) { - return UIInterfaceOrientationUnknown; - } - UIWindowScene *windowScene = firstWindow.windowScene; + UIWindowScene *windowScene = RCTKeyWindow().windowScene; if (windowScene == nil) { return UIInterfaceOrientationUnknown; } diff --git a/ios/RNSSearchBar.mm b/ios/RNSSearchBar.mm index 20a4603802..26aa97e8c2 100644 --- a/ios/RNSSearchBar.mm +++ b/ios/RNSSearchBar.mm @@ -338,9 +338,11 @@ - (void)updateProps:(react::Props::Shared const &)props oldProps:(react::Props:: [self setPlaceholder:RCTNSStringFromStringNilIfEmpty(newScreenProps.placeholder)]; } +#if !TARGET_OS_VISION if (oldScreenProps.autoCapitalize != newScreenProps.autoCapitalize) { [self setAutoCapitalize:[RNSConvert UITextAutocapitalizationTypeFromCppEquivalent:newScreenProps.autoCapitalize]]; } +#endif if (oldScreenProps.tintColor != newScreenProps.tintColor) { [self setTintColor:RCTUIColorFromSharedColor(newScreenProps.tintColor)]; diff --git a/ios/utils/RNSUIBarButtonItem.h b/ios/utils/RNSUIBarButtonItem.h index e35f29047f..d7c6c10fe2 100644 --- a/ios/utils/RNSUIBarButtonItem.h +++ b/ios/utils/RNSUIBarButtonItem.h @@ -1,3 +1,5 @@ +#import + @interface RNSUIBarButtonItem : UIBarButtonItem @property (nonatomic) BOOL menuHidden; diff --git a/src/native-stack/views/HeaderConfig.tsx b/src/native-stack/views/HeaderConfig.tsx index 3264197790..f1ed55d820 100644 --- a/src/native-stack/views/HeaderConfig.tsx +++ b/src/native-stack/views/HeaderConfig.tsx @@ -16,6 +16,7 @@ import { import { NativeStackNavigationOptions } from '../types'; import { useBackPressSubscription } from '../utils/useBackPressSubscription'; import { processFonts } from './FontProcessor'; +import warnOnce from 'warn-once'; type Props = NativeStackNavigationOptions & { route: Route; @@ -96,6 +97,15 @@ export default function HeaderConfig({ return searchBar; }, [searchBar, createSubscription, clearSubscription]); + // @ts-ignore isVision is not yet in the type definitions (RN 0.74+) + const isVisionOS = Platform?.isVision; + + warnOnce( + isVisionOS && + (headerTitleStyle.color !== undefined || headerTintColor !== undefined), + 'headerTitleStyle.color and headerTintColor are not supported on visionOS.' + ); + return (