forked from facebook/react-native
-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: implement Spatial API * feat: make RCTSpatial decoupled from RCTMainWindow() * feat: implement XR module docs: add image to README, annotate nightly APIs fix: export XR library from typescript
- Loading branch information
1 parent
99dbcd7
commit 30bd592
Showing
23 changed files
with
380 additions
and
71 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import Foundation | ||
import SwiftUI | ||
|
||
@objc public enum ImmersiveSpaceResult: Int { | ||
case opened | ||
case userCancelled | ||
case error | ||
} | ||
|
||
public typealias CompletionHandlerType = (_ result: ImmersiveSpaceResult) -> Void | ||
|
||
/** | ||
* Utility view used to bridge the gap between SwiftUI environment and UIKit. | ||
* | ||
* Calls `openImmersiveSpace` when view appears in the UIKit hierarchy and `dismissImmersiveSpace` when removed. | ||
*/ | ||
struct ImmersiveBridgeView: View { | ||
@Environment(\.openImmersiveSpace) private var openImmersiveSpace | ||
@Environment(\.dismissImmersiveSpace) private var dismissImmersiveSpace | ||
|
||
var spaceId: String | ||
var completionHandler: CompletionHandlerType | ||
|
||
var body: some View { | ||
EmptyView() | ||
.onAppear { | ||
Task { | ||
let result = await openImmersiveSpace(id: spaceId) | ||
|
||
switch result { | ||
case .opened: | ||
completionHandler(.opened) | ||
case .error: | ||
completionHandler(.error) | ||
case .userCancelled: | ||
completionHandler(.userCancelled) | ||
default: | ||
break | ||
} | ||
} | ||
} | ||
.onDisappear { | ||
Task { await dismissImmersiveSpace() } | ||
} | ||
} | ||
} | ||
|
||
@objc public class ImmersiveBridgeFactory: NSObject { | ||
@objc public static func makeImmersiveBridgeView( | ||
spaceId: String, | ||
completionHandler: @escaping CompletionHandlerType | ||
) -> UIViewController { | ||
return UIHostingController(rootView: ImmersiveBridgeView(spaceId: spaceId, completionHandler: completionHandler)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/** | ||
* @flow strict | ||
* @format | ||
*/ | ||
|
||
export * from '../../src/private/specs/visionos_modules/NativeXRModule'; | ||
import NativeXRModule from '../../src/private/specs/visionos_modules/NativeXRModule'; | ||
export default NativeXRModule; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#import <Foundation/Foundation.h> | ||
#import <React/RCTBridgeModule.h> | ||
|
||
@interface RCTXRModule : NSObject <RCTBridgeModule> | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
#import <React/RCTXRModule.h> | ||
|
||
#import <FBReactNativeSpec_visionOS/FBReactNativeSpec_visionOS.h> | ||
|
||
#import <React/RCTBridge.h> | ||
#import <React/RCTConvert.h> | ||
#import <React/RCTUtils.h> | ||
#import "RCTXR-Swift.h" | ||
|
||
@interface RCTXRModule () <NativeXRModuleSpec> | ||
@end | ||
|
||
@implementation RCTXRModule { | ||
UIViewController *_immersiveBridgeView; | ||
} | ||
|
||
RCT_EXPORT_MODULE() | ||
|
||
RCT_EXPORT_METHOD(endSession | ||
: (RCTPromiseResolveBlock)resolve reject | ||
: (RCTPromiseRejectBlock)reject) | ||
{ | ||
[self removeImmersiveBridge]; | ||
resolve(nil); | ||
} | ||
|
||
|
||
RCT_EXPORT_METHOD(requestSession | ||
: (NSString *)sessionId resolve | ||
: (RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) | ||
{ | ||
RCTExecuteOnMainQueue(^{ | ||
UIWindow *keyWindow = RCTKeyWindow(); | ||
UIViewController *rootViewController = keyWindow.rootViewController; | ||
|
||
if (self->_immersiveBridgeView == nil) { | ||
self->_immersiveBridgeView = [ImmersiveBridgeFactory makeImmersiveBridgeViewWithSpaceId:sessionId | ||
completionHandler:^(enum ImmersiveSpaceResult result){ | ||
if (result == ImmersiveSpaceResultError) { | ||
reject(@"ERROR", @"Immersive Space failed to open, the system cannot fulfill the request.", nil); | ||
[self removeImmersiveBridge]; | ||
} else if (result == ImmersiveSpaceResultUserCancelled) { | ||
reject(@"ERROR", @"Immersive Space canceled by user", nil); | ||
[self removeImmersiveBridge]; | ||
} else if (result == ImmersiveSpaceResultOpened) { | ||
resolve(nil); | ||
} | ||
}]; | ||
|
||
[rootViewController.view addSubview:self->_immersiveBridgeView.view]; | ||
[rootViewController addChildViewController:self->_immersiveBridgeView]; | ||
[self->_immersiveBridgeView didMoveToParentViewController:rootViewController]; | ||
} else { | ||
reject(@"ERROR", @"Immersive Space already opened", nil); | ||
} | ||
}); | ||
} | ||
|
||
- (facebook::react::ModuleConstants<JS::NativeXRModule::Constants::Builder>)constantsToExport { | ||
return [self getConstants]; | ||
} | ||
|
||
- (facebook::react::ModuleConstants<JS::NativeXRModule::Constants>)getConstants { | ||
__block facebook::react::ModuleConstants<JS::NativeXRModule::Constants> constants; | ||
RCTUnsafeExecuteOnMainQueueSync(^{ | ||
constants = facebook::react::typedConstants<JS::NativeXRModule::Constants>({ | ||
.supportsMultipleScenes = RCTSharedApplication().supportsMultipleScenes | ||
}); | ||
}); | ||
|
||
return constants; | ||
} | ||
|
||
- (void) removeImmersiveBridge | ||
{ | ||
RCTExecuteOnMainQueue(^{ | ||
[self->_immersiveBridgeView willMoveToParentViewController:nil]; | ||
[self->_immersiveBridgeView.view removeFromSuperview]; | ||
[self->_immersiveBridgeView removeFromParentViewController]; | ||
self->_immersiveBridgeView = nil; | ||
}); | ||
} | ||
|
||
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const facebook::react::ObjCTurboModule::InitParams &)params { | ||
return std::make_shared<facebook::react::NativeXRModuleSpecJSI>(params); | ||
} | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
|
||
export interface XRStatic { | ||
requestSession(sessionId: string): Promise<void>; | ||
endSession(): Promise<void>; | ||
supportsMultipleScenes: boolean; | ||
} | ||
|
||
export const XR: XRStatic; | ||
export type XR = XRStatic; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/** | ||
* @format | ||
* @flow strict | ||
* @jsdoc | ||
*/ | ||
|
||
import NativeXRModule from './NativeXRModule'; | ||
|
||
const XR = { | ||
requestSession: (sessionId?: string): Promise<void> => { | ||
if (NativeXRModule != null && NativeXRModule.requestSession != null) { | ||
return NativeXRModule.requestSession(sessionId); | ||
} | ||
return Promise.reject(new Error('NativeXRModule is not available')); | ||
}, | ||
endSession: (): Promise<void> => { | ||
if (NativeXRModule != null && NativeXRModule.endSession != null) { | ||
return NativeXRModule.endSession(); | ||
} | ||
return Promise.reject(new Error('NativeXRModule is not available')); | ||
}, | ||
// $FlowIgnore[unsafe-getters-setters] | ||
get supportsMultipleScenes(): boolean { | ||
if (NativeXRModule == null) { | ||
return false; | ||
} | ||
|
||
const nativeConstants = NativeXRModule.getConstants(); | ||
return nativeConstants.supportsMultipleScenes || false; | ||
}, | ||
}; | ||
|
||
module.exports = XR; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
packages/react-native/src/private/specs/visionos_modules/NativeXRModule.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/** | ||
* @flow strict | ||
* @format | ||
*/ | ||
|
||
import type {TurboModule} from '../../../../Libraries/TurboModule/RCTExport'; | ||
|
||
import * as TurboModuleRegistry from '../../../../Libraries/TurboModule/TurboModuleRegistry'; | ||
|
||
export type XRModuleConstants = {| | ||
+supportsMultipleScenes?: boolean, | ||
|}; | ||
|
||
export interface Spec extends TurboModule { | ||
+getConstants: () => XRModuleConstants; | ||
|
||
+requestSession: (sessionId?: string) => Promise<void>; | ||
+endSession: () => Promise<void>; | ||
} | ||
|
||
export default (TurboModuleRegistry.get<Spec>('XRModule'): ?Spec); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.