Skip to content
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 @@ -24,4 +24,6 @@
continueUserActivity:(nonnull NSUserActivity *)userActivity
restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> *_Nullable))restorationHandler;

+ (void)onOpenURL:(nonnull NSURL *)url NS_SWIFT_NAME(onOpenURL(url:));

@end
14 changes: 14 additions & 0 deletions packages/react-native/Libraries/LinkingIOS/RCTLinkingManager.mm
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#import "RCTLinkingPlugins.h"

static NSString *const kOpenURLNotification = @"RCTOpenURLNotification";
static NSURL *initialURL = nil;

static void postNotificationWithURL(NSURL *URL, id sender)
{
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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];
Expand All @@ -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));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
*/
Expand Down
3 changes: 3 additions & 0 deletions packages/rn-tester/RNTester-visionOS/App.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
13 changes: 13 additions & 0 deletions packages/rn-tester/RNTester-visionOS/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>com.reactjs.ios</string>
<key>CFBundleURLSchemes</key>
<array>
<string>rntester</string>
</array>
</dict>
</array>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationPreferredDefaultSceneSessionRole</key>
Expand Down