From b9c008b05df2f172818d76335271a11f7951f5e9 Mon Sep 17 00:00:00 2001 From: Saad Najmi Date: Tue, 16 Jan 2024 07:50:27 -0800 Subject: [PATCH 1/3] Remove TARGET_OS_UIKITFORMAC macros (#42278) Summary: There seems to be a lot of `TARGET_OS_UIKITFORMAC` macro in React Native that don't need to be there. Let's remove them. First off, what is `TARGET_OS_UIKITFORMAC` targeting? You might think it's [Mac Catalyst](https://developer.apple.com/mac-catalyst/), if you look at the [commit](https://github.com/facebook/react-native/commit/3724810d2168eb182db24acf9e741775df27ae13) introducing the ifdefs. However.. that doesn't seem right because `TARGET_OS_MACCATALYST` exists, and is used elsewhere in the codebase. In fact, if you look at this handy comment inside `TargetConditionals.h` (the file that defines all these conditionals), `TARGET_OS_UIKITFORMAC` is not even on there! ``` /* * TARGET_OS_* * * These conditionals specify in which Operating System the generated code will * run. Indention is used to show which conditionals are evolutionary subclasses. * * The MAC/WIN32/UNIX conditionals are mutually exclusive. * The IOS/TV/WATCH/VISION conditionals are mutually exclusive. * * TARGET_OS_WIN32 - Generated code will run on WIN32 API * TARGET_OS_WINDOWS - Generated code will run on Windows * TARGET_OS_UNIX - Generated code will run on some Unix (not macOS) * TARGET_OS_LINUX - Generated code will run on Linux * TARGET_OS_MAC - Generated code will run on a variant of macOS * TARGET_OS_OSX - Generated code will run on macOS * TARGET_OS_IPHONE - Generated code will run on a variant of iOS (firmware, devices, simulator) * TARGET_OS_IOS - Generated code will run on iOS * TARGET_OS_MACCATALYST - Generated code will run on macOS * TARGET_OS_TV - Generated code will run on tvOS * TARGET_OS_WATCH - Generated code will run on watchOS * TARGET_OS_VISION - Generated code will run on visionOS * TARGET_OS_BRIDGE - Generated code will run on bridge devices * TARGET_OS_SIMULATOR - Generated code will run on an iOS, tvOS, watchOS, or visionOS simulator * TARGET_OS_DRIVERKIT - Generated code will run on macOS, iOS, tvOS, watchOS, or visionOS * * TARGET_OS_EMBEDDED - DEPRECATED: Use TARGET_OS_IPHONE and/or TARGET_OS_SIMULATOR instead * TARGET_IPHONE_SIMULATOR - DEPRECATED: Same as TARGET_OS_SIMULATOR * TARGET_OS_NANO - DEPRECATED: Same as TARGET_OS_WATCH * * +--------------------------------------------------------------------------------------+ * | TARGET_OS_MAC | * | +-----+ +------------------------------------------------------------+ +-----------+ | * | | | | TARGET_OS_IPHONE | | | | * | | | | +-----------------+ +----+ +-------+ +--------+ +--------+ | | | | * | | | | | IOS | | | | | | | | | | | | | * | | OSX | | | +-------------+ | | TV | | WATCH | | BRIDGE | | VISION | | | DRIVERKIT | | * | | | | | | MACCATALYST | | | | | | | | | | | | | | * | | | | | +-------------+ | | | | | | | | | | | | | * | | | | +-----------------+ +----+ +-------+ +--------+ +--------+ | | | | * | +-----+ +------------------------------------------------------------+ +-----------+ | * +--------------------------------------------------------------------------------------+ */ ``` Going even deeper into `TargetConditionals.h`, you will see `TARGET_OS_UIKITFORMAC` defined... and it's always 1 when `TARGET_OS_MACCATALYST` is 1, making it feel even more redundant. My current conclusion is it's either another variant of Mac Catalyst (the one where they just run unmodified UIKit maybe..), or it's an older macro back from when Catalyst was still experimental. Either way, it's pretty obvious nobody is running or testing this codepath, and it adds bloat, especially to React Native macOS where we have extra ifdef blocks for macOS support (and eventually visionOS support). Let's remove it. Another change I made while we're here: I've seen this lingering TODO to replace setTargetRect:InView: / setMenuVisible:animated: (deprecated as of iOS 13, below our minimum OS requirement) with showMenuFromView (deprecated as of iOS 16, in line with the availability check). Let's just.... do that? [IOS] [REMOVED] - Remove TARGET_OS_UIKITFORMAC macros Pull Request resolved: https://github.com/facebook/react-native/pull/42278 Test Plan: RNTester with Mac Catalyst still compiles: ![Screenshot 2024-01-15 at 12 26 03 AM](https://github.com/facebook/react-native/assets/6722175/015bd37d-f536-43c7-9586-96187cdbd013) Reviewed By: cipolleschi Differential Revision: D52780690 Pulled By: sammy-SC fbshipit-source-id: df6a333e8e15f79de0ce6f538ebd73b92698dcb6 --- .../Libraries/Image/RCTUIImageViewAnimated.mm | 5 - .../RCTPushNotificationManager.h | 2 - .../RCTPushNotificationManager.mm | 107 +----------------- .../Libraries/Text/Text/RCTTextView.mm | 20 ++-- .../Text/RCTParagraphComponentView.mm | 10 +- packages/rn-tester/RNTester/AppDelegate.mm | 5 - 6 files changed, 12 insertions(+), 137 deletions(-) diff --git a/packages/react-native/Libraries/Image/RCTUIImageViewAnimated.mm b/packages/react-native/Libraries/Image/RCTUIImageViewAnimated.mm index ce209e06a4487e..da7751226363f3 100644 --- a/packages/react-native/Libraries/Image/RCTUIImageViewAnimated.mm +++ b/packages/react-native/Libraries/Image/RCTUIImageViewAnimated.mm @@ -193,15 +193,10 @@ - (BOOL)paused - (void)displayDidRefresh:(CADisplayLink *)displayLink { -#if TARGET_OS_UIKITFORMAC - // TODO: `displayLink.frameInterval` is not available on UIKitForMac - NSTimeInterval durationToNextRefresh = displayLink.duration; -#else // displaylink.duration -- time interval between frames, assuming maximumFramesPerSecond // displayLink.preferredFramesPerSecond (>= iOS 10) -- Set to 30 for displayDidRefresh to be called at 30 fps // durationToNextRefresh -- Time interval to the next time displayDidRefresh is called NSTimeInterval durationToNextRefresh = displayLink.targetTimestamp - displayLink.timestamp; -#endif NSUInteger totalFrameCount = self.totalFrameCount; NSUInteger currentFrameIndex = self.currentFrameIndex; NSUInteger nextFrameIndex = (currentFrameIndex + 1) % totalFrameCount; diff --git a/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationManager.h b/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationManager.h index f6fdb8c4e7e660..a4820ff7e57b3f 100644 --- a/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationManager.h +++ b/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationManager.h @@ -15,7 +15,6 @@ extern NSString *const RCTRemoteNotificationReceived; typedef void (^RCTRemoteNotificationCallback)(UIBackgroundFetchResult result); #endif // [macOS] -#if !TARGET_OS_UIKITFORMAC + (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken; + (void)didReceiveRemoteNotification:(NSDictionary *)notification; #if !TARGET_OS_OSX // [macOS] @@ -27,6 +26,5 @@ typedef void (^RCTRemoteNotificationCallback)(UIBackgroundFetchResult result); + (void)didReceiveUserNotification:(NSUserNotification *)notification; #endif // macOS] + (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error; -#endif @end diff --git a/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationManager.mm b/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationManager.mm index c0c08ab746c853..597aa2a1cb4596 100644 --- a/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationManager.mm +++ b/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationManager.mm @@ -24,8 +24,6 @@ static NSString *const kErrorUnableToRequestPermissions = @"E_UNABLE_TO_REQUEST_PERMISSIONS"; -#if !TARGET_OS_UIKITFORMAC - @interface RCTPushNotificationManager () @property (nonatomic, strong) NSMutableDictionary *remoteNotificationCallbacks; @end @@ -97,16 +95,10 @@ @implementation RCTConvert (UIBackgroundFetchResult) @end #endif // [macOS] -#else -@interface RCTPushNotificationManager () -@end -#endif // TARGET_OS_UIKITFORMAC @implementation RCTPushNotificationManager -#if !TARGET_OS_UIKITFORMAC - -#if !TARGET_OS_OSX // [macOS] +#if TARGET_OS_IOS // [macOS] [visionOS] /** DEPRECATED. UILocalNotification was deprecated in iOS 10. Please don't add new callsites. */ static NSDictionary *RCTFormatLocalNotification(UILocalNotification *notification) { @@ -198,8 +190,6 @@ @implementation RCTPushNotificationManager return [formatter stringFromDate:date]; } -#endif // TARGET_OS_UIKITFORMAC - RCT_EXPORT_MODULE() - (dispatch_queue_t)methodQueue @@ -207,7 +197,6 @@ - (dispatch_queue_t)methodQueue return dispatch_get_main_queue(); } -#if !TARGET_OS_UIKITFORMAC - (void)startObserving { [[NSNotificationCenter defaultCenter] addObserver:self @@ -638,100 +627,6 @@ - (void)handleRemoteNotificationRegistrationError:(NSNotification *)notification }]; } -#else // TARGET_OS_UIKITFORMAC - -RCT_EXPORT_METHOD(onFinishRemoteNotification : (NSString *)notificationId fetchResult : (NSString *)fetchResult) -{ - RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd)); -} - -RCT_EXPORT_METHOD(setApplicationIconBadgeNumber : (double)number) -{ - RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd)); -} - -RCT_EXPORT_METHOD(getApplicationIconBadgeNumber : (RCTResponseSenderBlock)callback) -{ - RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd)); -} - -RCT_EXPORT_METHOD(requestPermissions - : (JS::NativePushNotificationManagerIOS::SpecRequestPermissionsPermission &)permissions resolve - : (RCTPromiseResolveBlock)resolve reject - : (RCTPromiseRejectBlock)reject) -{ - RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd)); -} - -RCT_EXPORT_METHOD(abandonPermissions) -{ - RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd)); -} - -RCT_EXPORT_METHOD(checkPermissions : (RCTResponseSenderBlock)callback) -{ - RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd)); -} - -RCT_EXPORT_METHOD(presentLocalNotification : (JS::NativePushNotificationManagerIOS::Notification &)notification) -{ - RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd)); -} - -RCT_EXPORT_METHOD(scheduleLocalNotification : (JS::NativePushNotificationManagerIOS::Notification &)notification) -{ - RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd)); -} - -RCT_EXPORT_METHOD(cancelAllLocalNotifications) -{ - RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd)); -} - -RCT_EXPORT_METHOD(cancelLocalNotifications : (NSDictionary *)userInfo) -{ - RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd)); -} - -RCT_EXPORT_METHOD(getInitialNotification - : (RCTPromiseResolveBlock)resolve reject - : (__unused RCTPromiseRejectBlock)reject) -{ - RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd)); -} - -RCT_EXPORT_METHOD(getScheduledLocalNotifications : (RCTResponseSenderBlock)callback) -{ - RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd)); -} - -RCT_EXPORT_METHOD(removeAllDeliveredNotifications) -{ - RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd)); -} - -RCT_EXPORT_METHOD(removeDeliveredNotifications : (NSArray *)identifiers) -{ - RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd)); -} - -RCT_EXPORT_METHOD(getDeliveredNotifications : (RCTResponseSenderBlock)callback) -{ - RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd)); -} - -RCT_EXPORT_METHOD(getAuthorizationStatus : (RCTResponseSenderBlock)callback) -{ - RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd)); -} - -- (NSArray *)supportedEvents -{ - return @[]; -} - -#endif // TARGET_OS_UIKITFORMAC - - (std::shared_ptr)getTurboModule: (const facebook::react::ObjCTurboModule::InitParams &)params { diff --git a/packages/react-native/Libraries/Text/Text/RCTTextView.mm b/packages/react-native/Libraries/Text/Text/RCTTextView.mm index 3f47a3a23b8787..b56fb29329afef 100644 --- a/packages/react-native/Libraries/Text/Text/RCTTextView.mm +++ b/packages/react-native/Libraries/Text/Text/RCTTextView.mm @@ -373,8 +373,7 @@ - (void)disableContextMenu - (void)handleLongPress:(UILongPressGestureRecognizer *)gesture { -#if !TARGET_OS_UIKITFORMAC - if (@available(iOS 16.0, *)) { + if (@available(iOS 16.0, macCatalyst 16.0, *)) { CGPoint location = [gesture locationInView:self]; UIEditMenuConfiguration *config = [UIEditMenuConfiguration configurationWithIdentifier:nil sourcePoint:location]; if (_editMenuInteraction) { @@ -382,20 +381,17 @@ - (void)handleLongPress:(UILongPressGestureRecognizer *)gesture } return; } - // TODO: Adopt showMenuFromRect (necessary for UIKitForMac) UIMenuController *menuController = [UIMenuController sharedMenuController]; - if (menuController.isMenuVisible) { - return; - } + if (menuController.isMenuVisible) { + return; + } - if (!self.isFirstResponder) { - [self becomeFirstResponder]; - } + if (!self.isFirstResponder) { + [self becomeFirstResponder]; + } - [menuController setTargetRect:self.bounds inView:self]; - [menuController setMenuVisible:YES animated:YES]; -#endif + [menuController showMenuFromView:self rect:self.bounds]; } #else // [macOS diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm index 8a20e5326707b0..1a2765cadb9df3 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm @@ -251,7 +251,6 @@ - (void)disableContextMenu - (void)handleLongPress:(UILongPressGestureRecognizer *)gesture { -#if !TARGET_OS_UIKITFORMAC if (@available(iOS 16.0, *)) { CGPoint location = [gesture locationInView:self]; UIEditMenuConfiguration *config = [UIEditMenuConfiguration configurationWithIdentifier:nil sourcePoint:location]; @@ -260,20 +259,17 @@ - (void)handleLongPress:(UILongPressGestureRecognizer *)gesture } return; } - // TODO: Adopt showMenuFromRect (necessary for UIKitForMac) UIMenuController *menuController = [UIMenuController sharedMenuController]; if (menuController.isMenuVisible) { - return; + return; } if (!self.isFirstResponder) { - [self becomeFirstResponder]; + [self becomeFirstResponder]; } - [menuController setTargetRect:self.bounds inView:self]; - [menuController setMenuVisible:YES animated:YES]; -#endif + [menuController showMenuFromView:self rect:self.bounds]; } #endif // [macOS] diff --git a/packages/rn-tester/RNTester/AppDelegate.mm b/packages/rn-tester/RNTester/AppDelegate.mm index 4ab8f7a5a0a80d..6e903f360200f0 100644 --- a/packages/rn-tester/RNTester/AppDelegate.mm +++ b/packages/rn-tester/RNTester/AppDelegate.mm @@ -12,9 +12,7 @@ #import #import -#if !TARGET_OS_TV && !TARGET_OS_UIKITFORMAC #import -#endif #if RCT_NEW_ARCH_ENABLED #import @@ -100,8 +98,6 @@ - (void)loadSourceForBridge:(RCTBridge *)bridge return nullptr; } -#if !TARGET_OS_TV && !TARGET_OS_UIKITFORMAC - // Required for the remoteNotificationsRegistered event. - (void)application:(__unused RCTUIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken @@ -148,7 +144,6 @@ - (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center return YES; } #endif // macOS] -#endif #pragma mark - RCTComponentViewFactoryComponentProvider From 332c6e459cc1af8edcb67bfa3c59a8850a4d66b9 Mon Sep 17 00:00:00 2001 From: Saad Najmi Date: Wed, 17 Jan 2024 08:50:25 -0800 Subject: [PATCH 2/3] Remove an early return to suppress a deprecated API warning for `UIMenuController` (#42277) Summary: `UIMenuController` is deprecated as of iOS 16. https://github.com/facebook/react-native/commit/e08a1973f67d85acc157111c749c43572469e4c2 migrated a usage into an `available` check. However, it does not properly fall back to the deprecated API in the "else" block of the availability check, instead it uses an early return. It seems this means Xcode still sees the API as used, and spits out a deprecated warning. Let's just refactor the code so we don't have that anymore. [IOS] [FIXED] - Remove an early return to suppress a deprecated API warning for `UIMenuController` Pull Request resolved: https://github.com/facebook/react-native/pull/42277 Test Plan: CI should pass. Reviewed By: cipolleschi Differential Revision: D52785488 Pulled By: sammy-SC fbshipit-source-id: 0b47e8aa8d7c94728e3d68332fbb8f97f8ded34e --- .../Libraries/Text/Text/RCTTextView.mm | 18 +++++++----------- .../Text/RCTParagraphComponentView.mm | 18 +++++++----------- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/packages/react-native/Libraries/Text/Text/RCTTextView.mm b/packages/react-native/Libraries/Text/Text/RCTTextView.mm index b56fb29329afef..d2a7d3a646729f 100644 --- a/packages/react-native/Libraries/Text/Text/RCTTextView.mm +++ b/packages/react-native/Libraries/Text/Text/RCTTextView.mm @@ -379,19 +379,15 @@ - (void)handleLongPress:(UILongPressGestureRecognizer *)gesture if (_editMenuInteraction) { [_editMenuInteraction presentEditMenuWithConfiguration:config]; } - return; - } - UIMenuController *menuController = [UIMenuController sharedMenuController]; - - if (menuController.isMenuVisible) { - return; - } + } else { + UIMenuController *menuController = [UIMenuController sharedMenuController]; - if (!self.isFirstResponder) { - [self becomeFirstResponder]; - } + if (menuController.isMenuVisible) { + return; + } - [menuController showMenuFromView:self rect:self.bounds]; + [menuController showMenuFromView:self rect:self.bounds]; + } } #else // [macOS diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm index 1a2765cadb9df3..74026ca2292976 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm @@ -251,25 +251,21 @@ - (void)disableContextMenu - (void)handleLongPress:(UILongPressGestureRecognizer *)gesture { - if (@available(iOS 16.0, *)) { + if (@available(iOS 16.0, macCatalyst 16.0, *)) { CGPoint location = [gesture locationInView:self]; UIEditMenuConfiguration *config = [UIEditMenuConfiguration configurationWithIdentifier:nil sourcePoint:location]; if (_editMenuInteraction) { [_editMenuInteraction presentEditMenuWithConfiguration:config]; } - return; - } - UIMenuController *menuController = [UIMenuController sharedMenuController]; + } else { + UIMenuController *menuController = [UIMenuController sharedMenuController]; - if (menuController.isMenuVisible) { - return; - } + if (menuController.isMenuVisible) { + return; + } - if (!self.isFirstResponder) { - [self becomeFirstResponder]; + [menuController showMenuFromView:self rect:self.bounds]; } - - [menuController showMenuFromView:self rect:self.bounds]; } #endif // [macOS] From 1419ac2c3cff51c4796c6479630a19456ac17134 Mon Sep 17 00:00:00 2001 From: Saad Najmi Date: Wed, 17 Jan 2024 01:47:04 -0800 Subject: [PATCH 3/3] Native changes for visionOS --- .../Libraries/AppDelegate/RCTAppDelegate.mm | 6 ++- .../Network/React-RCTNetwork.podspec | 5 ++- .../RCTPushNotificationManager.h | 2 + .../RCTPushNotificationManager.mm | 13 +++--- .../Libraries/Text/React-RCTText.podspec | 5 ++- .../Text/TextInput/RCTBaseTextInputView.mm | 8 +--- .../Singleline/macOS/RCTUISecureTextField.h | 3 ++ .../Singleline/macOS/RCTUISecureTextField.m | 2 + packages/react-native/React/Base/RCTConvert.m | 2 + .../react-native/React/Base/RCTKeyCommands.m | 6 ++- packages/react-native/React/Base/RCTUtils.h | 5 +++ packages/react-native/React/Base/RCTUtils.m | 12 ++++++ .../React/CoreModules/RCTDeviceInfo.mm | 13 +++--- .../React/CoreModules/RCTPerfMonitor.mm | 6 ++- .../React/CoreModules/RCTRedBox.mm | 6 +++ .../React/CoreModules/RCTStatusBarManager.mm | 43 ++++++++++++++++--- .../RCTInputAccessoryComponentView.mm | 4 ++ .../Modal/RCTFabricModalHostViewController.mm | 8 ++++ .../ScrollView/RCTScrollViewComponentView.mm | 10 +++-- .../TextInput/RCTTextInputComponentView.mm | 4 +- .../TextInput/RCTTextInputUtils.mm | 4 +- .../React/Fabric/RCTSurfacePointerHandler.mm | 9 +++- .../React/Fabric/RCTSurfaceTouchHandler.mm | 4 ++ .../react-native/React/Modules/RCTUIManager.m | 6 ++- .../React/React-RCTFabric.podspec | 7 ++- .../react-native/React/UIUtils/RCTUIUtils.m | 25 +++++++++-- .../React/Views/RCTModalHostView.m | 2 + .../React/Views/RCTModalHostViewController.m | 8 ++++ .../React/Views/ScrollView/RCTScrollView.m | 4 ++ .../Views/ScrollView/RCTScrollViewManager.h | 2 + .../Views/ScrollView/RCTScrollViewManager.m | 6 ++- .../ios/ReactCommon/RCTSampleTurboModule.mm | 4 ++ packages/rn-tester/RNTester/AppDelegate.mm | 6 +-- 33 files changed, 199 insertions(+), 51 deletions(-) diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm index 2ff3f336a61739..8bb67e580f28f3 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm @@ -133,7 +133,11 @@ - (void)applicationDidFinishLaunching:(NSNotification *)notification rootView = [self createRootViewWithBridge:self.bridge moduleName:self.moduleName initProps:initProps]; } #if !TARGET_OS_OSX // [macOS] +#if !TARGET_OS_VISION // [visionOS] self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; +#else + self.window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, 1280, 720)]; +#endif // [visionOS] UIViewController *rootViewController = [self createRootViewController]; [self setRootView:rootView toRootViewController:rootViewController]; self.window.rootViewController = rootViewController; @@ -142,7 +146,7 @@ - (void)applicationDidFinishLaunching:(NSNotification *)notification return YES; #else // [macOS - NSRect frame = NSMakeRect(0,0,1024,768); + NSRect frame = NSMakeRect(0,0,1280,720); self.window = [[NSWindow alloc] initWithContentRect:NSZeroRect styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskResizable | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable backing:NSBackingStoreBuffered diff --git a/packages/react-native/Libraries/Network/React-RCTNetwork.podspec b/packages/react-native/Libraries/Network/React-RCTNetwork.podspec index cbe0998f0b2b3f..d36e1a5a975c75 100644 --- a/packages/react-native/Libraries/Network/React-RCTNetwork.podspec +++ b/packages/react-native/Libraries/Network/React-RCTNetwork.podspec @@ -54,7 +54,10 @@ Pod::Spec.new do |s| "CLANG_CXX_LANGUAGE_STANDARD" => "c++20", "HEADER_SEARCH_PATHS" => header_search_paths.join(' ') } - s.ios.frameworks = "MobileCoreServices" # [macOS] Restrict to iOS + # [macOS MobileCoreServices Not available on macOS + s.ios.frameworks = "MobileCoreServices" + s.visionos.frameworks = "MobileCoreServices" + # macOS] s.dependency "RCT-Folly", folly_version s.dependency "React-Codegen", version diff --git a/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationManager.h b/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationManager.h index a4820ff7e57b3f..b7944837bf9147 100644 --- a/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationManager.h +++ b/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationManager.h @@ -20,7 +20,9 @@ typedef void (^RCTRemoteNotificationCallback)(UIBackgroundFetchResult result); #if !TARGET_OS_OSX // [macOS] + (void)didReceiveRemoteNotification:(NSDictionary *)notification fetchCompletionHandler:(RCTRemoteNotificationCallback)completionHandler; +#if TARGET_OS_IOS // [visionOS] + (void)didReceiveLocalNotification:(UILocalNotification *)notification; +#endif // [visionOS] #endif // [macOS] #if TARGET_OS_OSX // [macOS + (void)didReceiveUserNotification:(NSUserNotification *)notification; diff --git a/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationManager.mm b/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationManager.mm index 597aa2a1cb4596..3e7a6e6826d5f1 100644 --- a/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationManager.mm +++ b/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationManager.mm @@ -118,7 +118,8 @@ @implementation RCTPushNotificationManager formattedLocalNotification[@"remote"] = @NO; return formattedLocalNotification; } -#else // [macOS +#endif // [macOS] [visionOS] +#if TARGET_OS_OSX // [macOS static NSDictionary *RCTFormatUserNotification(NSUserNotification *notification) { NSMutableDictionary *formattedUserNotification = [NSMutableDictionary dictionary]; @@ -271,14 +272,15 @@ + (void)didReceiveRemoteNotification:(NSDictionary *)notification } #endif // [macOS] -#if !TARGET_OS_OSX // [macOS] +#if TARGET_OS_IOS // [macOS] [visionOS] + (void)didReceiveLocalNotification:(UILocalNotification *)notification { [[NSNotificationCenter defaultCenter] postNotificationName:kLocalNotificationReceived object:self userInfo:RCTFormatLocalNotification(notification)]; } -#else // [macOS +#endif // [macOS] [visionOS] +#if TARGET_OS_OSX // [macOS + (void)didReceiveUserNotification:(NSUserNotification *)notification { NSString *notificationName = notification.isRemote ? RCTRemoteNotificationReceived : kLocalNotificationReceived; @@ -557,7 +559,7 @@ - (void)handleRemoteNotificationRegistrationError:(NSNotification *)notification : (RCTPromiseResolveBlock)resolve reject : (__unused RCTPromiseRejectBlock)reject) { -#if !TARGET_OS_OSX // [macOS] +#if TARGET_OS_IOS // [macOS] [visionOS] NSMutableDictionary *initialNotification = [self.bridge.launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] mutableCopy]; @@ -572,7 +574,8 @@ - (void)handleRemoteNotificationRegistrationError:(NSNotification *)notification } else { resolve((id)kCFNull); } -#else // [macOS +#endif // [macOS] [visionOS] +#if TARGET_OS_OSX // [macOS NSUserNotification *initialNotification = self.bridge.launchOptions[NSApplicationLaunchUserNotificationKey]; if (initialNotification) { resolve(RCTFormatUserNotification(initialNotification)); diff --git a/packages/react-native/Libraries/Text/React-RCTText.podspec b/packages/react-native/Libraries/Text/React-RCTText.podspec index 800b5f726654ac..103e930b373440 100644 --- a/packages/react-native/Libraries/Text/React-RCTText.podspec +++ b/packages/react-native/Libraries/Text/React-RCTText.podspec @@ -30,7 +30,10 @@ Pod::Spec.new do |s| s.ios.exclude_files = "**/macOS/*" # [macOS] s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs" s.header_dir = "RCTText" - s.ios.framework = ["MobileCoreServices"] # [macOS] Restrict to iOS + # [macOS MobileCoreServices Not available on macOS + s.ios.frameworks = "MobileCoreServices" + s.visionos.frameworks = "MobileCoreServices" + # macOS] s.pod_target_xcconfig = { "CLANG_CXX_LANGUAGE_STANDARD" => "c++20" } s.dependency "Yoga" diff --git a/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.mm b/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.mm index c7b66f0cfb892d..36015db3ce7735 100644 --- a/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.mm +++ b/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.mm @@ -851,6 +851,7 @@ - (void)didMoveToWindow #pragma mark - Custom Input Accessory View +#if TARGET_OS_IOS // [macOS] [visionOS] - (void)didSetProps:(NSArray *)changedProps { if ([changedProps containsObject:@"inputAccessoryViewID"] && self.inputAccessoryViewID) { @@ -862,7 +863,6 @@ - (void)didSetProps:(NSArray *)changedProps - (void)setCustomInputAccessoryViewWithNativeID:(NSString *)nativeID { -#if !TARGET_OS_OSX // [macOS] __weak RCTBaseTextInputView *weakSelf = self; [_bridge.uiManager rootViewForReactTag:self.reactTag withCompletion:^(UIView *rootView) { @@ -877,12 +877,10 @@ - (void)setCustomInputAccessoryViewWithNativeID:(NSString *)nativeID } } }]; -#endif // [macOS] } - (void)setDefaultInputAccessoryView { -#if !TARGET_OS_OSX // [macOS] UIView *textInputView = self.backedTextInputView; UIKeyboardType keyboardType = textInputView.keyboardType; @@ -914,10 +912,8 @@ - (void)setDefaultInputAccessoryView textInputView.inputAccessoryView = nil; } [self reloadInputViewsIfNecessary]; -#endif // [macOS] } -#if !TARGET_OS_OSX // [macOS] - (void)reloadInputViewsIfNecessary { // We have to call `reloadInputViews` for focused text inputs to update an accessory view. @@ -934,7 +930,7 @@ - (void)handleInputAccessoryDoneButton [self.backedTextInputView endEditing:YES]; } } -#endif // [macOS] +#endif // [macOS] [visionOS] // [macOS diff --git a/packages/react-native/Libraries/Text/TextInput/Singleline/macOS/RCTUISecureTextField.h b/packages/react-native/Libraries/Text/TextInput/Singleline/macOS/RCTUISecureTextField.h index 792c6703c41d58..c0586c7be5dbfd 100644 --- a/packages/react-native/Libraries/Text/TextInput/Singleline/macOS/RCTUISecureTextField.h +++ b/packages/react-native/Libraries/Text/TextInput/Singleline/macOS/RCTUISecureTextField.h @@ -7,6 +7,9 @@ // [macOS] +#if TARGET_OS_OSX #define RCT_SUBCLASS_SECURETEXTFIELD 1 +#endif #include + diff --git a/packages/react-native/Libraries/Text/TextInput/Singleline/macOS/RCTUISecureTextField.m b/packages/react-native/Libraries/Text/TextInput/Singleline/macOS/RCTUISecureTextField.m index 610a8e39a32367..41d4f4c9b7b3b3 100644 --- a/packages/react-native/Libraries/Text/TextInput/Singleline/macOS/RCTUISecureTextField.m +++ b/packages/react-native/Libraries/Text/TextInput/Singleline/macOS/RCTUISecureTextField.m @@ -7,6 +7,8 @@ // [macOS] +#if TARGET_OS_OSX #define RCT_SUBCLASS_SECURETEXTFIELD 1 +#endif #include "../RCTUITextField.mm" diff --git a/packages/react-native/React/Base/RCTConvert.m b/packages/react-native/React/Base/RCTConvert.m index 48978105ba1fc3..a2b652b1daa02a 100644 --- a/packages/react-native/React/Base/RCTConvert.m +++ b/packages/react-native/React/Base/RCTConvert.m @@ -542,8 +542,10 @@ + (UIKeyboardType)UIKeyboardType:(id)json RCT_DYNAMIC (@{ @"default" : @(UIBarStyleDefault), @"black" : @(UIBarStyleBlack), +#if !TARGET_OS_VISION // [visionOS] @"blackOpaque" : @(UIBarStyleBlackOpaque), @"blackTranslucent" : @(UIBarStyleBlackTranslucent), +#endif // [visionOS] }), UIBarStyleDefault, integerValue) diff --git a/packages/react-native/React/Base/RCTKeyCommands.m b/packages/react-native/React/Base/RCTKeyCommands.m index 978e3841839544..9121cde3c88cf1 100644 --- a/packages/react-native/React/Base/RCTKeyCommands.m +++ b/packages/react-native/React/Base/RCTKeyCommands.m @@ -129,7 +129,11 @@ - (void)handleKeyUIEventSwizzle:(UIEvent *)event isKeyDown = [event _isKeyDown]; } - BOOL interactionEnabled = !RCTSharedApplication().isIgnoringInteractionEvents; +#if !TARGET_OS_VISION // [visionOS] + BOOL interactionEnabled = !RCTSharedApplication().isIgnoringInteractionEvents; + #else // [visionOS + BOOL interactionEnabled = true; + #endif // visionOS] BOOL hasFirstResponder = NO; if (isKeyDown && modifiedInput.length > 0 && interactionEnabled) { UIResponder *firstResponder = nil; diff --git a/packages/react-native/React/Base/RCTUtils.h b/packages/react-native/React/Base/RCTUtils.h index d391b64327178e..25cea7b240742c 100644 --- a/packages/react-native/React/Base/RCTUtils.h +++ b/packages/react-native/React/Base/RCTUtils.h @@ -99,6 +99,11 @@ RCT_EXTERN RCTUIApplication *__nullable RCTSharedApplication(void); // [macOS] // or view controller RCT_EXTERN RCTUIWindow *__nullable RCTKeyWindow(void); // [macOS] +#if TARGET_OS_VISION // [visionOS +// Returns UIStatusBarManager to get it's configuration info. +RCT_EXTERN UIStatusBarManager *__nullable RCTUIStatusBarManager(void); +#endif // visionOS] + #if !TARGET_OS_OSX // [macOS] // Returns the presented view controller, useful if you need // e.g. to present a modal view controller or alert over it diff --git a/packages/react-native/React/Base/RCTUtils.m b/packages/react-native/React/Base/RCTUtils.m index 648bceacfd841b..36916fc85429f4 100644 --- a/packages/react-native/React/Base/RCTUtils.m +++ b/packages/react-native/React/Base/RCTUtils.m @@ -352,7 +352,11 @@ CGSize RCTScreenSize(void) static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ RCTUnsafeExecuteOnMainQueueSync(^{ +#if TARGET_OS_IOS // [visionOS] size = [UIScreen mainScreen].bounds.size; +#else // [visionOS + size = RCTKeyWindow().bounds.size; +#endif // visionOS] }); }); @@ -620,6 +624,14 @@ BOOL RCTRunningInAppExtension(void) #endif // macOS] } +#if TARGET_OS_VISION // [visionOS +UIStatusBarManager *__nullable RCTUIStatusBarManager(void) { + NSSet *connectedScenes = RCTSharedApplication().connectedScenes; + UIWindowScene *windowScene = [connectedScenes anyObject]; + return windowScene.statusBarManager; +} +#endif // visionOS] + #if !TARGET_OS_OSX // [macOS] UIViewController *__nullable RCTPresentedViewController(void) { diff --git a/packages/react-native/React/CoreModules/RCTDeviceInfo.mm b/packages/react-native/React/CoreModules/RCTDeviceInfo.mm index b39e14e5639f81..3a784faf3716aa 100644 --- a/packages/react-native/React/CoreModules/RCTDeviceInfo.mm +++ b/packages/react-native/React/CoreModules/RCTDeviceInfo.mm @@ -56,12 +56,14 @@ - (void)initialize name:RCTAccessibilityManagerDidUpdateMultiplierNotification object:[_moduleRegistry moduleForName:"AccessibilityManager"]]; +#if TARGET_OS_IOS // [visionOS] _currentInterfaceOrientation = [RCTSharedApplication() statusBarOrientation]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(interfaceOrientationDidChange) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; +#endif // [visionOS] #endif // [macOS] _currentInterfaceDimensions = [self _exportedDimensions]; @@ -90,8 +92,8 @@ - (void)invalidate static BOOL RCTIsIPhoneNotched() { -#if !TARGET_OS_OSX // [macOS] static BOOL isIPhoneNotched = NO; +#if TARGET_OS_IOS // [macOS] [visionOS] static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ @@ -100,11 +102,9 @@ static BOOL RCTIsIPhoneNotched() // 20pt is the top safeArea value in non-notched devices isIPhoneNotched = RCTSharedApplication().keyWindow.safeAreaInsets.top > 20; }); +#endif // [macOS] [visionOS] return isIPhoneNotched; -#else // [macOS - return NO; -#endif // macOS] } @@ -182,8 +182,7 @@ - (void)didReceiveNewContentSizeMultiplier }); } -#if !TARGET_OS_OSX // [macOS] - +#if TARGET_OS_IOS // [macOS] [visionOS] - (void)interfaceOrientationDidChange { __weak __typeof(self) weakSelf = self; @@ -224,7 +223,7 @@ - (void)_interfaceOrientationDidChange #pragma clang diagnostic pop } } -#endif // [macOS] +#endif // [macOS] [visionOS] - (void)interfaceFrameDidChange { diff --git a/packages/react-native/React/CoreModules/RCTPerfMonitor.mm b/packages/react-native/React/CoreModules/RCTPerfMonitor.mm index f728963f1a905a..816671c591136e 100644 --- a/packages/react-native/React/CoreModules/RCTPerfMonitor.mm +++ b/packages/react-native/React/CoreModules/RCTPerfMonitor.mm @@ -183,7 +183,11 @@ - (UIPanGestureRecognizer *)gestureRecognizer - (UIView *)container { if (!_container) { - CGSize statusBarSize = RCTSharedApplication().statusBarFrame.size; +#if !TARGET_OS_VISION // [visionOS] + CGSize statusBarSize = RCTSharedApplication().statusBarFrame.size; +#else // [visionOS + CGSize statusBarSize = RCTUIStatusBarManager().statusBarFrame.size; +#endif // visionOS] CGFloat statusBarHeight = statusBarSize.height; _container = [[UIView alloc] initWithFrame:CGRectMake(10, statusBarHeight, 180, RCTPerfMonitorBarHeight)]; _container.layer.borderWidth = 2; diff --git a/packages/react-native/React/CoreModules/RCTRedBox.mm b/packages/react-native/React/CoreModules/RCTRedBox.mm index 33113b5b8a09ca..736494693ebc21 100644 --- a/packages/react-native/React/CoreModules/RCTRedBox.mm +++ b/packages/react-native/React/CoreModules/RCTRedBox.mm @@ -953,9 +953,15 @@ - (void)showErrorMessage:(NSString *)message if (!self->_window) { #if !TARGET_OS_OSX // [macOS] +#if !TARGET_OS_VISION // [macOS] self->_window = [[RCTRedBoxWindow alloc] initWithFrame:[UIScreen mainScreen].bounds customButtonTitles:self->_customButtonTitles customButtonHandlers:self->_customButtonHandlers]; +#else // [visionOS + self->_window = [[RCTRedBoxWindow alloc] initWithFrame:CGRectMake(0, 0, 1280, 720) + customButtonTitles:self->_customButtonTitles + customButtonHandlers:self->_customButtonHandlers]; +#endif // visionOS] #else // [macOS self->_window = [RCTRedBoxWindow new]; #endif // macOS] diff --git a/packages/react-native/React/CoreModules/RCTStatusBarManager.mm b/packages/react-native/React/CoreModules/RCTStatusBarManager.mm index 8abd78b5d2be1d..4bacdde8553cac 100644 --- a/packages/react-native/React/CoreModules/RCTStatusBarManager.mm +++ b/packages/react-native/React/CoreModules/RCTStatusBarManager.mm @@ -12,9 +12,9 @@ #import #import -#if !TARGET_OS_OSX // [macOS] #import +#if !TARGET_OS_OSX // [macOS] @implementation RCTConvert (UIStatusBar) + (UIStatusBarStyle)UIStatusBarStyle:(id)json RCT_DYNAMIC @@ -44,14 +44,14 @@ + (UIStatusBarStyle)UIStatusBarStyle:(id)json RCT_DYNAMIC integerValue); @end +#endif // [macOS] @interface RCTStatusBarManager () @end -#endif // [macOS] - @implementation RCTStatusBarManager +#if !TARGET_OS_OSX // [macOS] static BOOL RCTViewControllerBasedStatusBarAppearance() { static BOOL value; @@ -64,6 +64,7 @@ static BOOL RCTViewControllerBasedStatusBarAppearance() return value; } +#endif // [macOS] RCT_EXPORT_MODULE() @@ -72,15 +73,15 @@ + (BOOL)requiresMainQueueSetup return YES; } +#if TARGET_OS_OSX // [macOS] - (NSArray *)supportedEvents { return @[ @"statusBarFrameDidChange", @"statusBarFrameWillChange" ]; } -#if !TARGET_OS_OSX // [macOS] - - (void)startObserving { +#if TARGET_OS_IOS // [visionOS] NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; [nc addObserver:self selector:@selector(applicationDidChangeStatusBarFrame:) @@ -90,6 +91,7 @@ - (void)startObserving selector:@selector(applicationWillChangeStatusBarFrame:) name:UIApplicationWillChangeStatusBarFrameNotification object:nil]; +#endif // [visionOS] } - (void)stopObserving @@ -99,6 +101,7 @@ - (void)stopObserving - (void)emitEvent:(NSString *)eventName forNotification:(NSNotification *)notification { +#if TARGET_OS_IOS // [visionOS] CGRect frame = [notification.userInfo[UIApplicationStatusBarFrameUserInfoKey] CGRectValue]; NSDictionary *event = @{ @"frame" : @{ @@ -109,6 +112,7 @@ - (void)emitEvent:(NSString *)eventName forNotification:(NSNotification *)notifi }, }; [self sendEventWithName:eventName body:event]; +#endif // [visionOS] } - (void)applicationDidChangeStatusBarFrame:(NSNotification *)notification @@ -120,16 +124,30 @@ - (void)applicationWillChangeStatusBarFrame:(NSNotification *)notification { [self emitEvent:@"statusBarFrameWillChange" forNotification:notification]; } +#endif RCT_EXPORT_METHOD(getHeight : (RCTResponseSenderBlock)callback) { +#if !TARGET_OS_OSX // [macOS] +#if !TARGET_OS_VISION // [visionOS] callback(@[ @{ @"height" : @(RCTSharedApplication().statusBarFrame.size.height), } ]); +#else // [visionOS + callback(@[ @{ + @"height" : @(RCTUIStatusBarManager().statusBarFrame.size), + } ]); +#endif // visionOS] +#else // [macOS + callback(@[ @{ + @"height" : @(0), + } ]); +#endif // macOS] } RCT_EXPORT_METHOD(setStyle : (NSString *)style animated : (BOOL)animated) { +#if TARGET_OS_IOS // [macOS] [visionOS] dispatch_async(dispatch_get_main_queue(), ^{ UIStatusBarStyle statusBarStyle = [RCTConvert UIStatusBarStyle:style]; if (RCTViewControllerBasedStatusBarAppearance()) { @@ -142,10 +160,12 @@ - (void)applicationWillChangeStatusBarFrame:(NSNotification *)notification } #pragma clang diagnostic pop }); +#endif // [macOS] [visionOS] } RCT_EXPORT_METHOD(setHidden : (BOOL)hidden withAnimation : (NSString *)withAnimation) { +#if TARGET_OS_IOS // [macOS] [visionOS] dispatch_async(dispatch_get_main_queue(), ^{ UIStatusBarAnimation animation = [RCTConvert UIStatusBarAnimation:withAnimation]; if (RCTViewControllerBasedStatusBarAppearance()) { @@ -158,13 +178,16 @@ - (void)applicationWillChangeStatusBarFrame:(NSNotification *)notification #pragma clang diagnostic pop } }); +#endif // [macOS] [visionOS] } RCT_EXPORT_METHOD(setNetworkActivityIndicatorVisible : (BOOL)visible) { +#if TARGET_OS_IOS // [visionOS] dispatch_async(dispatch_get_main_queue(), ^{ RCTSharedApplication().networkActivityIndicatorVisible = visible; }); +#endif // [visionOS] } - (facebook::react::ModuleConstants)getConstants @@ -172,7 +195,15 @@ - (void)applicationWillChangeStatusBarFrame:(NSNotification *)notification __block facebook::react::ModuleConstants constants; RCTUnsafeExecuteOnMainQueueSync(^{ constants = facebook::react::typedConstants({ +#if !TARGET_OS_OSX // [macOS] +#if !TARGET_OS_VISION // [visionOS] .HEIGHT = RCTSharedApplication().statusBarFrame.size.height, +#else // [visionOS + .HEIGHT = RCTUIStatusBarManager().statusBarFrame.size.height, +#endif // visionOS] +#else // [macOS + .HEIGHT = 0, +#endif // macOS] .DEFAULT_BACKGROUND_COLOR = std::nullopt, }); }); @@ -191,8 +222,6 @@ - (void)applicationWillChangeStatusBarFrame:(NSNotification *)notification return std::make_shared(params); } -#endif // [macOS] - @end Class RCTStatusBarManagerCls(void) diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/InputAccessory/RCTInputAccessoryComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/InputAccessory/RCTInputAccessoryComponentView.mm index e9dabd8f5bc4fa..04e336d8667889 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/InputAccessory/RCTInputAccessoryComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/InputAccessory/RCTInputAccessoryComponentView.mm @@ -68,7 +68,9 @@ - (void)didMoveToWindow if (self.nativeId) { #if !TARGET_OS_OSX // [macOS] _textInput = RCTFindTextInputWithNativeId(self.window, self.nativeId); +#if !TARGET_OS_VISION // [visionOS] _textInput.inputAccessoryView = _contentView; +#endif // [visionOS] #else // [macOS _textInput = RCTFindTextInputWithNativeId(self.window.contentView, self.nativeId); #endif // macOS] @@ -87,10 +89,12 @@ - (BOOL)canBecomeFirstResponder return true; } +#if !TARGET_OS_VISION // [visionOS] - (RCTUIView *)inputAccessoryView // [macOS] { return _contentView; } +#endif // [visionOS] #pragma mark - RCTComponentViewProtocol diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.mm index b7d2b3c5a53614..29e45d4d6f0f80 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.mm @@ -43,10 +43,12 @@ - (void)loadView [_touchHandler attachToView:self.view]; } +#if TARGET_OS_IOS // [visionOS] - (UIStatusBarStyle)preferredStatusBarStyle { return [RCTSharedApplication() statusBarStyle]; } +#endif // [visionOS] - (void)viewDidDisappear:(BOOL)animated { @@ -54,16 +56,22 @@ - (void)viewDidDisappear:(BOOL)animated _lastViewBounds = CGRectZero; } +#if TARGET_OS_IOS // [visionOS] - (BOOL)prefersStatusBarHidden { return [RCTSharedApplication() isStatusBarHidden]; } +#endif // [visionOS] #if RCT_DEV - (UIInterfaceOrientationMask)supportedInterfaceOrientations { +#if !TARGET_OS_VISION // [visionOS] UIInterfaceOrientationMask appSupportedOrientationsMask = [RCTSharedApplication() supportedInterfaceOrientationsForWindow:[RCTSharedApplication() keyWindow]]; +#else // [visionOS + UIInterfaceOrientationMask appSupportedOrientationsMask = UIInterfaceOrientationMaskLandscape; +#endif // visonOS] if (!(_supportedInterfaceOrientations & appSupportedOrientationsMask)) { RCTLogError( @"Modal was presented with 0x%x orientations mask but the application only supports 0x%x." diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm index a5c85a84c48d6b..81a0b79d6fd98e 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm @@ -28,7 +28,7 @@ static const CGFloat kClippingLeeway = 44.0; -#if !TARGET_OS_OSX // [macOS] +#if TARGET_OS_IOS // [macOS] [visionOS] static UIScrollViewKeyboardDismissMode RCTUIKeyboardDismissModeFromProps(const ScrollViewProps &props) { switch (props.keyboardDismissMode) { @@ -40,7 +40,9 @@ static UIScrollViewKeyboardDismissMode RCTUIKeyboardDismissModeFromProps(const S return UIScrollViewKeyboardDismissModeInteractive; } } +#endif // [macOS] [visionOS] +#if !TARGET_OS_OSX // [macOS static UIScrollViewIndicatorStyle RCTUIScrollViewIndicatorStyleFromProps(const ScrollViewProps &props) { switch (props.indicatorStyle) { @@ -52,6 +54,7 @@ static UIScrollViewIndicatorStyle RCTUIScrollViewIndicatorStyleFromProps(const S return UIScrollViewIndicatorStyleWhite; } } +#endif // [macOS] // Once Fabric implements proper NativeAnimationDriver, this should be removed. // This is just a workaround to allow animations based on onScroll event. @@ -79,7 +82,6 @@ static void RCTSendScrollEventForNativeAnimations_DEPRECATED(RCTUIScrollView *sc userInfo:userInfo]; } } -#endif // [macOS] @interface RCTScrollViewComponentView () < #if !TARGET_OS_OSX // [macOS] @@ -329,9 +331,9 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared & MAP_SCROLL_VIEW_PROP(snapToInterval); if (oldScrollViewProps.keyboardDismissMode != newScrollViewProps.keyboardDismissMode) { -#if !TARGET_OS_OSX // [macOS] +#if TARGET_OS_IOS // [macOS] [visionOS] scrollView.keyboardDismissMode = RCTUIKeyboardDismissModeFromProps(newScrollViewProps); -#endif // [macOS] +#endif // [macOS] [visionOS] } [super updateProps:props oldProps:oldProps]; diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm index fda7f88c6ebd5d..2c12cfa47909ab 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm @@ -563,6 +563,7 @@ - (void)setDefaultInputAccessoryView keyboardType == UIKeyboardTypeDecimalPad || keyboardType == UIKeyboardTypeASCIICapableNumberPad) && _backedTextInputView.returnKeyType == UIReturnKeyDone; +#if !TARGET_OS_VISION // [visionOS] if ((_backedTextInputView.inputAccessoryView != nil) == shouldHaveInputAccessoryView) { return; } @@ -581,7 +582,8 @@ - (void)setDefaultInputAccessoryView } else { _backedTextInputView.inputAccessoryView = nil; } - +#endif // [visionOS] + if (_backedTextInputView.isFirstResponder) { [_backedTextInputView reloadInputViews]; } diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputUtils.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputUtils.mm index bac8eeb7685704..319ec09fedcfa5 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputUtils.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputUtils.mm @@ -32,9 +32,9 @@ void RCTCopyBackedTextInput( toTextInput.placeholder = fromTextInput.placeholder; toTextInput.placeholderColor = fromTextInput.placeholderColor; toTextInput.textContainerInset = fromTextInput.textContainerInset; -#if !TARGET_OS_OSX // [macOS] +#if TARGET_OS_IOS // [macOS] [visionOS] toTextInput.inputAccessoryView = fromTextInput.inputAccessoryView; -#endif // [macOS] +#endif // [macOS] [visionOS] toTextInput.textInputDelegate = fromTextInput.textInputDelegate; toTextInput.placeholderColor = fromTextInput.placeholderColor; toTextInput.defaultTextAttributes = fromTextInput.defaultTextAttributes; diff --git a/packages/react-native/React/Fabric/RCTSurfacePointerHandler.mm b/packages/react-native/React/Fabric/RCTSurfacePointerHandler.mm index c54c46e3a88573..559d528d43311c 100644 --- a/packages/react-native/React/Fabric/RCTSurfacePointerHandler.mm +++ b/packages/react-native/React/Fabric/RCTSurfacePointerHandler.mm @@ -291,9 +291,11 @@ static PointerEvent CreatePointerEventFromActivePointer( if (eventType == RCTPointerEventTypeCancel) { event.clientPoint = RCTPointFromCGPoint(CGPointZero); +#if !TARGET_OS_VISION // [visionOS] event.screenPoint = RCTPointFromCGPoint([rootComponentView convertPoint:CGPointZero toCoordinateSpace:rootComponentView.window.screen.coordinateSpace]); +#endif // [visionOS] event.offsetPoint = RCTPointFromCGPoint([rootComponentView convertPoint:CGPointZero toView:activePointer.componentView]); } else { @@ -386,8 +388,10 @@ static void UpdateActivePointerWithUITouch( #if !TARGET_OS_OSX // [macOS] activePointer.clientPoint = [uiTouch locationInView:rootComponentView]; +#if !TARGET_OS_VISION // [visionOS] activePointer.screenPoint = [rootComponentView convertPoint:activePointer.clientPoint toCoordinateSpace:rootComponentView.window.screen.coordinateSpace]; +#endif // [visionOS] activePointer.offsetPoint = [uiTouch locationInView:activePointer.componentView]; #else // [macOS activePointer.offsetPoint = [activePointer.componentView convertPoint:uiTouch.locationInWindow fromView:nil]; @@ -910,9 +914,12 @@ - (void)hovering:(UIHoverGestureRecognizer *)recognizer { UIView *listenerView = recognizer.view; CGPoint clientLocation = [recognizer locationInView:listenerView]; +#if !TARGET_OS_VISION // [visionOS] CGPoint screenLocation = [listenerView convertPoint:clientLocation toCoordinateSpace:listenerView.window.screen.coordinateSpace]; - +#else // [visionOS + CGPoint screenLocation = CGPointZero; +#endif // visionOS] UIView *targetView = [listenerView hitTest:clientLocation withEvent:nil]; targetView = FindClosestFabricManagedTouchableView(targetView); diff --git a/packages/react-native/React/Fabric/RCTSurfaceTouchHandler.mm b/packages/react-native/React/Fabric/RCTSurfaceTouchHandler.mm index c58cd5f237646b..fc83e173dc51ae 100644 --- a/packages/react-native/React/Fabric/RCTSurfaceTouchHandler.mm +++ b/packages/react-native/React/Fabric/RCTSurfaceTouchHandler.mm @@ -58,8 +58,12 @@ static void UpdateActiveTouchWithUITouch( #if !TARGET_OS_OSX // [macOS] CGPoint offsetPoint = [uiTouch locationInView:activeTouch.componentView]; CGPoint pagePoint = [uiTouch locationInView:rootComponentView]; +#if !TARGET_OS_VISION // [visionOS] CGPoint screenPoint = [rootComponentView convertPoint:pagePoint toCoordinateSpace:rootComponentView.window.screen.coordinateSpace]; +#else // [visionOS + CGPoint screenPoint = CGPointZero; +#endif // visionOS] pagePoint = CGPointMake(pagePoint.x + rootViewOriginOffset.x, pagePoint.y + rootViewOriginOffset.y); #else // [macOS CGPoint offsetPoint = [activeTouch.componentView convertPoint:uiTouch.locationInWindow fromView:nil]; diff --git a/packages/react-native/React/Modules/RCTUIManager.m b/packages/react-native/React/Modules/RCTUIManager.m index b36041d3a8d201..89b0dccd4e7bf3 100644 --- a/packages/react-native/React/Modules/RCTUIManager.m +++ b/packages/react-native/React/Modules/RCTUIManager.m @@ -195,10 +195,12 @@ - (void)setBridge:(RCTBridge *)bridge object:[self->_bridge moduleForName:@"AccessibilityManager" lazilyLoadIfNecessary:YES]]; }); +#if TARGET_OS_IOS // [visionOS] [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(namedOrientationDidChange) name:UIDeviceOrientationDidChangeNotification object:nil]; +#endif // [visionOS] [RCTLayoutAnimation initializeStatics]; #endif // [macOS] } @@ -228,7 +230,7 @@ - (void)didReceiveNewContentSizeMultiplier } #endif // [macOS] -#if !TARGET_OS_OSX // [macOS] +#if TARGET_OS_IOS // [macOS] [visionOS] // Names and coordinate system from html5 spec: // https://developer.mozilla.org/en-US/docs/Web/API/Screen.orientation // https://developer.mozilla.org/en-US/docs/Web/API/Screen.lockOrientation @@ -281,7 +283,7 @@ - (void)namedOrientationDidChange body:orientationEvent]; #pragma clang diagnostic pop } -#endif // macOS] +#endif // [macOS] [visionOS] - (dispatch_queue_t)methodQueue { diff --git a/packages/react-native/React/React-RCTFabric.podspec b/packages/react-native/React/React-RCTFabric.podspec index f5b994930003c9..04430ee6605331 100644 --- a/packages/react-native/React/React-RCTFabric.podspec +++ b/packages/react-native/React/React-RCTFabric.podspec @@ -66,8 +66,11 @@ Pod::Spec.new do |s| s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags s.header_dir = "React" s.module_name = "RCTFabric" - s.ios.framework = ["JavaScriptCore", "MobileCoreServices"] # [macOS] Restrict MobileCoreServices to iOS - s.osx.framework = ["JavaScriptCore"] # [macOS] Restrict MobileCoreServices to iOS + # [macOS MobileCoreServices not available on macOS + s.ios.framework = ["JavaScriptCore", "MobileCoreServices"] + s.visionos.framework = ["JavaScriptCore", "MobileCoreServices"] + s.osx.framework = ["JavaScriptCore"] + # macOS] s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => header_search_paths, "OTHER_CFLAGS" => "$(inherited) -DRN_FABRIC_ENABLED" + " " + folly_flags, diff --git a/packages/react-native/React/UIUtils/RCTUIUtils.m b/packages/react-native/React/UIUtils/RCTUIUtils.m index c5fe036be9f593..90ce88b3d5c6da 100644 --- a/packages/react-native/React/UIUtils/RCTUIUtils.m +++ b/packages/react-native/React/UIUtils/RCTUIUtils.m @@ -12,24 +12,41 @@ RCTDimensions RCTGetDimensions(CGFloat fontScale) { #if !TARGET_OS_OSX // [macOS] +#if !TARGET_OS_VISION // [visionOS] UIScreen *mainScreen = UIScreen.mainScreen; CGSize screenSize = mainScreen.bounds.size; +#else + CGSize screenSize = CGSizeZero; +#endif +#else // [macOS + NSScreen *mainScreen = NSScreen.mainScreen; + CGSize screenSize = mainScreen.frame.size; +#endif // macOS] +#if !TARGET_OS_OSX // [macOS] UIView *mainWindow = RCTKeyWindow(); // We fallback to screen size if a key window is not found. CGSize windowSize = mainWindow ? mainWindow.bounds.size : screenSize; #else // [macOS - RCTUIWindow *window = RCTKeyWindow(); - NSSize windowSize = window ? [window frame].size : CGSizeMake(0, 0); - NSSize screenSize = window ? [[window screen] frame].size : CGSizeMake(0, 0); + NSWindow *window = RCTKeyWindow(); + NSSize windowSize = window ? [window frame].size : CGSizeZero; + screenSize = window ? [[window screen] frame].size : screenSize; CGFloat scale = window ? [[window screen] backingScaleFactor] : 1.0; // Default scale to 1.0 if window is nil -#endif // macOS +#endif // macOS] + RCTDimensions result; #if !TARGET_OS_OSX // [macOS] +#if !TARGET_OS_VISION // [visionOS] typeof(result.screen) dimsScreen = { .width = screenSize.width, .height = screenSize.height, .scale = mainScreen.scale, .fontScale = fontScale}; typeof(result.window) dimsWindow = { .width = windowSize.width, .height = windowSize.height, .scale = mainScreen.scale, .fontScale = fontScale}; +#else // [visionOS hardcode the scale to a dummy value of 2 + typeof(result.screen) dimsScreen = { + .width = screenSize.width, .height = screenSize.height, .scale = 2, .fontScale = fontScale}; + typeof(result.window) dimsWindow = { + .width = windowSize.width, .height = windowSize.height, .scale = 2, .fontScale = fontScale}; +#endif // visionOS] #else // [macOS typeof(result.screen) dimsScreen = { .width = screenSize.width, diff --git a/packages/react-native/React/Views/RCTModalHostView.m b/packages/react-native/React/Views/RCTModalHostView.m index 639889f6638536..9d6e331734c446 100644 --- a/packages/react-native/React/Views/RCTModalHostView.m +++ b/packages/react-native/React/Views/RCTModalHostView.m @@ -73,6 +73,7 @@ - (void)presentationControllerDidAttemptToDismiss:(UIPresentationController *)co - (void)notifyForOrientationChange { +#if TARGET_OS_IOS // [visionOS] if (!_onOrientationChange) { return; } @@ -89,6 +90,7 @@ - (void)notifyForOrientationChange @"orientation" : isPortrait ? @"portrait" : @"landscape", }; _onOrientationChange(eventPayload); +#endif // [visionOS] } - (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex diff --git a/packages/react-native/React/Views/RCTModalHostViewController.m b/packages/react-native/React/Views/RCTModalHostViewController.m index e030d8f0ae235e..36ce42fa6ad9e3 100644 --- a/packages/react-native/React/Views/RCTModalHostViewController.m +++ b/packages/react-native/React/Views/RCTModalHostViewController.m @@ -25,8 +25,10 @@ - (instancetype)init self.modalInPresentation = YES; +#if TARGET_OS_IOS // [visionOS] _preferredStatusBarStyle = [RCTSharedApplication() statusBarStyle]; _preferredStatusBarHidden = [RCTSharedApplication() isStatusBarHidden]; +#endif // [visionOS] return self; } @@ -41,6 +43,7 @@ - (void)viewDidLayoutSubviews } } +#if TARGET_OS_IOS // [visionOS] - (UIStatusBarStyle)preferredStatusBarStyle { return _preferredStatusBarStyle; @@ -50,12 +53,17 @@ - (BOOL)prefersStatusBarHidden { return _preferredStatusBarHidden; } +#endif // [visionOS] #if RCT_DEV - (UIInterfaceOrientationMask)supportedInterfaceOrientations { +#if !TARGET_OS_VISION // [visionOS] UIInterfaceOrientationMask appSupportedOrientationsMask = [RCTSharedApplication() supportedInterfaceOrientationsForWindow:[RCTSharedApplication() keyWindow]]; +#else // [visionOS + UIInterfaceOrientationMask appSupportedOrientationsMask = UIInterfaceOrientationMaskAll; +#endif // visionOS] if (!(_supportedInterfaceOrientations & appSupportedOrientationsMask)) { RCTLogError( @"Modal was presented with 0x%x orientations mask but the application only supports 0x%x." diff --git a/packages/react-native/React/Views/ScrollView/RCTScrollView.m b/packages/react-native/React/Views/ScrollView/RCTScrollView.m index ffe7919c141626..a4f13e906b2e09 100644 --- a/packages/react-native/React/Views/ScrollView/RCTScrollView.m +++ b/packages/react-native/React/Views/ScrollView/RCTScrollView.m @@ -1403,7 +1403,9 @@ -(type)getter \ RCT_SET_AND_PRESERVE_OFFSET(setDecelerationRate, decelerationRate, CGFloat) RCT_SET_AND_PRESERVE_OFFSET(setDirectionalLockEnabled, isDirectionalLockEnabled, BOOL) RCT_SET_AND_PRESERVE_OFFSET(setIndicatorStyle, indicatorStyle, UIScrollViewIndicatorStyle) +#if TARGET_OS_IOS // [visionOS] RCT_SET_AND_PRESERVE_OFFSET(setKeyboardDismissMode, keyboardDismissMode, UIScrollViewKeyboardDismissMode) +#endif // visionOS] RCT_SET_AND_PRESERVE_OFFSET(setMaximumZoomScale, maximumZoomScale, CGFloat) RCT_SET_AND_PRESERVE_OFFSET(setMinimumZoomScale, minimumZoomScale, CGFloat) #endif // [macOS] @@ -1415,7 +1417,9 @@ -(type)getter \ RCT_SET_AND_PRESERVE_OFFSET(setShowsHorizontalScrollIndicator, showsHorizontalScrollIndicator, BOOL) RCT_SET_AND_PRESERVE_OFFSET(setShowsVerticalScrollIndicator, showsVerticalScrollIndicator, BOOL) RCT_SET_AND_PRESERVE_OFFSET(setZoomScale, zoomScale, CGFloat); +#if !TARGET_OS_VISION // [visionOS] RCT_SET_AND_PRESERVE_OFFSET(setScrollIndicatorInsets, scrollIndicatorInsets, UIEdgeInsets); +#endif // [visionOS] #if !TARGET_OS_OSX // [macOS] - (void)setAutomaticallyAdjustsScrollIndicatorInsets:(BOOL)automaticallyAdjusts API_AVAILABLE(ios(13.0)) diff --git a/packages/react-native/React/Views/ScrollView/RCTScrollViewManager.h b/packages/react-native/React/Views/ScrollView/RCTScrollViewManager.h index f5a0060df8123a..90fdd7caea5283 100644 --- a/packages/react-native/React/Views/ScrollView/RCTScrollViewManager.h +++ b/packages/react-native/React/Views/ScrollView/RCTScrollViewManager.h @@ -11,7 +11,9 @@ #if !TARGET_OS_OSX // [macOS] @interface RCTConvert (UIScrollView) +#if TARGET_OS_IOS // [visionOS] + (UIScrollViewKeyboardDismissMode)UIScrollViewKeyboardDismissMode:(id)json; +#endif // [visionOS] @end #endif // [macOS] diff --git a/packages/react-native/React/Views/ScrollView/RCTScrollViewManager.m b/packages/react-native/React/Views/ScrollView/RCTScrollViewManager.m index 75e2365f5d1149..65fe5c498c57b7 100644 --- a/packages/react-native/React/Views/ScrollView/RCTScrollViewManager.m +++ b/packages/react-native/React/Views/ScrollView/RCTScrollViewManager.m @@ -12,7 +12,7 @@ #import "RCTShadowView.h" #import "RCTUIManager.h" -#if !TARGET_OS_OSX // [macOS] +#if TARGET_OS_IOS // [macOS] [visionOS] @implementation RCTConvert (UIScrollView) RCT_ENUM_CONVERTER( @@ -49,7 +49,7 @@ @implementation RCTConvert (UIScrollView) integerValue) @end -#endif // [macOS] +#endif // [macOS] [visionOS] @implementation RCTScrollViewManager @@ -72,7 +72,9 @@ - (RCTPlatformView *)view // [macOS] RCT_EXPORT_NOT_OSX_VIEW_PROPERTY(decelerationRate, CGFloat) // [macOS] RCT_EXPORT_NOT_OSX_VIEW_PROPERTY(directionalLockEnabled, BOOL) // [macOS] RCT_EXPORT_NOT_OSX_VIEW_PROPERTY(indicatorStyle, UIScrollViewIndicatorStyle) // [macOS] +#if TARGET_OS_IOS // [visionOS] RCT_EXPORT_NOT_OSX_VIEW_PROPERTY(keyboardDismissMode, UIScrollViewKeyboardDismissMode) // [macOS] +#endif // [visionOS] RCT_EXPORT_NOT_OSX_VIEW_PROPERTY(maximumZoomScale, CGFloat) // [macOS] RCT_EXPORT_NOT_OSX_VIEW_PROPERTY(minimumZoomScale, CGFloat) // [macOS] RCT_EXPORT_VIEW_PROPERTY(scrollEnabled, BOOL) diff --git a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.mm b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.mm index 1c3df6c577d215..c7f403747ae98d 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.mm +++ b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.mm @@ -46,8 +46,12 @@ - (NSDictionary *)getConstants __block NSDictionary *constants; RCTUnsafeExecuteOnMainQueueSync(^{ #if !TARGET_OS_OSX // [macOS] +#if !TARGET_OS_VISION // [visionOS] UIScreen *mainScreen = UIScreen.mainScreen; CGSize screenSize = mainScreen.bounds.size; +#else // [visionOS + CGSize screenSize = CGSizeZero; +#endif // visionOS] #else // [macOS NSScreen *mainScreen = NSScreen.mainScreen; CGSize screenSize = mainScreen.frame.size; diff --git a/packages/rn-tester/RNTester/AppDelegate.mm b/packages/rn-tester/RNTester/AppDelegate.mm index 6e903f360200f0..40705b5fb7070b 100644 --- a/packages/rn-tester/RNTester/AppDelegate.mm +++ b/packages/rn-tester/RNTester/AppDelegate.mm @@ -24,7 +24,7 @@ #if BUNDLE_PATH NSString *kBundlePath = @"xplat/js/RKJSModules/EntryPoints/RNTesterTestBundle.js"; #else -#if TARGET_OS_OSX // [macOS] +#if !TARGET_OS_OSX // [macOS] NSString *kBundlePath = @"js/RNTesterApp.ios"; #else // [macOS NSString *kBundlePath = @"js/RNTesterApp.macos"; @@ -118,14 +118,14 @@ - (void)application:(__unused RCTUIApplication *)application didReceiveRemoteNot [RCTPushNotificationManager didReceiveRemoteNotification:notification]; } -#if !TARGET_OS_OSX // [macOS] +#if TARGET_OS_IOS // [macOS] [visionOS] // Required for the localNotificationReceived event. - (void)application:(__unused UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification { [RCTPushNotificationManager didReceiveLocalNotification:notification]; } -#endif // [macOS] +#endif // [macOS] [visionOS] #if TARGET_OS_OSX // [macOS - (void)userNotificationCenter:(NSUserNotificationCenter *)center didDeliverNotification:(NSUserNotification *)notification