diff --git a/packages/react-native/Libraries/LinkingIOS/RCTLinkingManager.h b/packages/react-native/Libraries/LinkingIOS/RCTLinkingManager.h index eff3b0c5461422..8bfee5fa745420 100644 --- a/packages/react-native/Libraries/LinkingIOS/RCTLinkingManager.h +++ b/packages/react-native/Libraries/LinkingIOS/RCTLinkingManager.h @@ -24,4 +24,6 @@ continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray> *_Nullable))restorationHandler; ++ (void)onOpenURL:(nonnull NSURL *)url NS_SWIFT_NAME(onOpenURL(url:)); + @end diff --git a/packages/react-native/Libraries/LinkingIOS/RCTLinkingManager.mm b/packages/react-native/Libraries/LinkingIOS/RCTLinkingManager.mm index 3fa06c43979bfd..b63c6340640452 100644 --- a/packages/react-native/Libraries/LinkingIOS/RCTLinkingManager.mm +++ b/packages/react-native/Libraries/LinkingIOS/RCTLinkingManager.mm @@ -15,6 +15,7 @@ #import "RCTLinkingPlugins.h" static NSString *const kOpenURLNotification = @"RCTOpenURLNotification"; +static NSURL *initialURL = nil; static void postNotificationWithURL(NSURL *URL, id sender) { @@ -81,6 +82,16 @@ + (BOOL)application:(UIApplication *)application return YES; } + ++ (void)onOpenURL:(NSURL *)url +{ + if (initialURL == nil) { + initialURL = url; + } else { + postNotificationWithURL(url, self); + } +} + - (void)handleOpenURLNotification:(NSNotification *)notification { [self sendEventWithName:@"url" body:notification.userInfo]; @@ -153,6 +164,7 @@ - (void)handleOpenURLNotification:(NSNotification *)notification RCT_EXPORT_METHOD(getInitialURL : (RCTPromiseResolveBlock)resolve reject : (__unused RCTPromiseRejectBlock)reject) { +#if !TARGET_OS_VISION NSURL *initialURL = nil; if (self.bridge.launchOptions[UIApplicationLaunchOptionsURLKey]) { initialURL = self.bridge.launchOptions[UIApplicationLaunchOptionsURLKey]; @@ -163,6 +175,8 @@ - (void)handleOpenURLNotification:(NSNotification *)notification initialURL = ((NSUserActivity *)userActivityDictionary[@"UIApplicationLaunchOptionsUserActivityKey"]).webpageURL; } } +#endif + // React Native visionOS uses static property to retrieve initialURL. resolve(RCTNullIfNil(initialURL.absoluteString)); } diff --git a/packages/react-native/Libraries/SwiftExtensions/RCTMainWindow.swift b/packages/react-native/Libraries/SwiftExtensions/RCTMainWindow.swift index d34c31221d87b0..3dff68146cb66e 100644 --- a/packages/react-native/Libraries/SwiftExtensions/RCTMainWindow.swift +++ b/packages/react-native/Libraries/SwiftExtensions/RCTMainWindow.swift @@ -20,6 +20,7 @@ import SwiftUI public struct RCTMainWindow: Scene { var moduleName: String var initialProps: RCTRootViewRepresentable.InitialPropsType + var onOpenURLCallback: ((URL) -> ())? public init(moduleName: String, initialProps: RCTRootViewRepresentable.InitialPropsType = nil) { self.moduleName = moduleName @@ -30,10 +31,21 @@ public struct RCTMainWindow: Scene { WindowGroup { RCTRootViewRepresentable(moduleName: moduleName, initialProps: initialProps) .modifier(WindowHandlingModifier()) + .onOpenURL(perform: { url in + onOpenURLCallback?(url) + }) } } } +extension RCTMainWindow { + public func onOpenURL(perform action: @escaping (URL) -> ()) -> some Scene { + var scene = self + scene.onOpenURLCallback = action + return scene + } +} + /** Handles data sharing between React Native and SwiftUI views. */ diff --git a/packages/rn-tester/RNTester-visionOS/App.swift b/packages/rn-tester/RNTester-visionOS/App.swift index 939cef2664d031..4b18e6303461f9 100644 --- a/packages/rn-tester/RNTester-visionOS/App.swift +++ b/packages/rn-tester/RNTester-visionOS/App.swift @@ -11,6 +11,9 @@ struct RNTesterApp: App { var body: some Scene { RCTMainWindow(moduleName: "RNTesterApp") + .onOpenURL(perform: { url in + RCTLinkingManager.onOpenURL(url: url) + }) RCTWindow(id: "SecondWindow", sceneData: reactContext.getSceneData(id: "SecondWindow")) .defaultSize(CGSize(width: 400, height: 700)) diff --git a/packages/rn-tester/RNTester-visionOS/Info.plist b/packages/rn-tester/RNTester-visionOS/Info.plist index 20f75e2afa73d1..a05d67cebe956c 100644 --- a/packages/rn-tester/RNTester-visionOS/Info.plist +++ b/packages/rn-tester/RNTester-visionOS/Info.plist @@ -2,6 +2,19 @@ + CFBundleURLTypes + + + CFBundleTypeRole + Editor + CFBundleURLName + com.reactjs.ios + CFBundleURLSchemes + + rntester + + + UIApplicationSceneManifest UIApplicationPreferredDefaultSceneSessionRole