Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[0.73] Add visionOS support #2039

Merged
merged 2 commits into from
Jan 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,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;
Expand All @@ -138,7 +142,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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,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 "RCTTypeSafety"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@ 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]
+ (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;
#endif // macOS]
+ (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error;
#endif

@end
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@

static NSString *const kErrorUnableToRequestPermissions = @"E_UNABLE_TO_REQUEST_PERMISSIONS";

#if !TARGET_OS_UIKITFORMAC

@interface RCTPushNotificationManager () <NativePushNotificationManagerIOSSpec>
@property (nonatomic, strong) NSMutableDictionary *remoteNotificationCallbacks;
@end
Expand Down Expand Up @@ -97,16 +95,10 @@ @implementation RCTConvert (UIBackgroundFetchResult)

@end
#endif // [macOS]
#else
@interface RCTPushNotificationManager () <NativePushNotificationManagerIOSSpec>
@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)
{
Expand All @@ -126,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];
Expand Down Expand Up @@ -198,16 +191,13 @@ @implementation RCTPushNotificationManager
return [formatter stringFromDate:date];
}

#endif // TARGET_OS_UIKITFORMAC

RCT_EXPORT_MODULE()

- (dispatch_queue_t)methodQueue
{
return dispatch_get_main_queue();
}

#if !TARGET_OS_UIKITFORMAC
- (void)startObserving
{
[[NSNotificationCenter defaultCenter] addObserver:self
Expand Down Expand Up @@ -282,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;
Expand Down Expand Up @@ -568,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<NSString *, id> *initialNotification =
[self.bridge.launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] mutableCopy];

Expand All @@ -583,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));
Expand Down Expand Up @@ -638,100 +630,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<NSString *, id> *)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<NSString *> *)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<NSString *> *)supportedEvents
{
return @[];
}

#endif // TARGET_OS_UIKITFORMAC

- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
(const facebook::react::ObjCTurboModule::InitParams &)params
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
22 changes: 7 additions & 15 deletions packages/react-native/Libraries/Text/Text/RCTTextView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -373,29 +373,21 @@ - (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) {
[_editMenuInteraction presentEditMenuWithConfiguration:config];
}
return;
}
// TODO: Adopt showMenuFromRect (necessary for UIKitForMac)
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 setTargetRect:self.bounds inView:self];
[menuController setMenuVisible:YES animated:YES];
#endif
}
#else // [macOS

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,7 @@ - (void)didMoveToWindow

#pragma mark - Custom Input Accessory View

#if TARGET_OS_IOS // [macOS] [visionOS]
- (void)didSetProps:(NSArray<NSString *> *)changedProps
{
if ([changedProps containsObject:@"inputAccessoryViewID"] && self.inputAccessoryViewID) {
Expand All @@ -862,7 +863,6 @@ - (void)didSetProps:(NSArray<NSString *> *)changedProps

- (void)setCustomInputAccessoryViewWithNativeID:(NSString *)nativeID
{
#if !TARGET_OS_OSX // [macOS]
__weak RCTBaseTextInputView *weakSelf = self;
[_bridge.uiManager rootViewForReactTag:self.reactTag
withCompletion:^(UIView *rootView) {
Expand All @@ -877,12 +877,10 @@ - (void)setCustomInputAccessoryViewWithNativeID:(NSString *)nativeID
}
}
}];
#endif // [macOS]
}

- (void)setDefaultInputAccessoryView
{
#if !TARGET_OS_OSX // [macOS]
UIView<RCTBackedTextInputViewProtocol> *textInputView = self.backedTextInputView;
UIKeyboardType keyboardType = textInputView.keyboardType;

Expand Down Expand Up @@ -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.
Expand All @@ -934,7 +930,7 @@ - (void)handleInputAccessoryDoneButton
[self.backedTextInputView endEditing:YES];
}
}
#endif // [macOS]
#endif // [macOS] [visionOS]

// [macOS

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

// [macOS]

#if TARGET_OS_OSX
#define RCT_SUBCLASS_SECURETEXTFIELD 1
#endif

#include <React/RCTUITextField.h>

Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

// [macOS]

#if TARGET_OS_OSX
#define RCT_SUBCLASS_SECURETEXTFIELD 1
#endif

#include "../RCTUITextField.mm"
2 changes: 2 additions & 0 deletions packages/react-native/React/Base/RCTConvert.m
Original file line number Diff line number Diff line change
Expand Up @@ -555,8 +555,10 @@ + (UIKeyboardType)UIKeyboardType:(id)json RCT_DYNAMIC
(@{
@"default" : @(UIBarStyleDefault),
@"black" : @(UIBarStyleBlack),
#if !TARGET_OS_VISION // [visionOS]
@"blackOpaque" : @(UIBarStyleBlackOpaque),
@"blackTranslucent" : @(UIBarStyleBlackTranslucent),
#endif // [visionOS]
}),
UIBarStyleDefault,
integerValue)
Expand Down
Loading
Loading