feat: add visionOS support (#3425)

* feat: add visionOS to target platforms

* disable unsupported API

* add temporary `promises` patches

* fix(visionOS): update promises patches

* apply code review suggestions

* format code
This commit is contained in:
Krzysztof Moch
2024-01-15 08:04:29 +01:00
committed by GitHub
parent 8f1bdb7c36
commit cf3ebb7f15
7 changed files with 108 additions and 42 deletions

View File

@@ -118,7 +118,9 @@ class RCTPlayerObserver: NSObject, AVPlayerItemMetadataOutputPushDelegate {
_playerRateChangeObserver = player.observe(\.rate, options: [.old], changeHandler: _handlers.handlePlaybackRateChange)
_playerVolumeChangeObserver = player.observe(\.volume, options: [.old], changeHandler: _handlers.handleVolumeChange)
_playerExternalPlaybackActiveObserver = player.observe(\.isExternalPlaybackActive, changeHandler: _handlers.handleExternalPlaybackActiveChange)
#if !os(visionOS)
_playerExternalPlaybackActiveObserver = player.observe(\.isExternalPlaybackActive, changeHandler: _handlers.handleExternalPlaybackActiveChange)
#endif
}
func removePlayerObservers() {
@@ -151,11 +153,13 @@ class RCTPlayerObserver: NSObject, AVPlayerItemMetadataOutputPushDelegate {
func addPlayerViewControllerObservers() {
guard let playerViewController, let _handlers else { return }
_playerViewControllerReadyForDisplayObserver = playerViewController.observe(
\.isReadyForDisplay,
options: [.new],
changeHandler: _handlers.handleReadyForDisplay
)
#if !os(visionOS)
_playerViewControllerReadyForDisplayObserver = playerViewController.observe(
\.isReadyForDisplay,
options: [.new],
changeHandler: _handlers.handleReadyForDisplay
)
#endif
_playerViewControllerOverlayFrameObserver = playerViewController.contentOverlayView?.observe(
\.frame,

View File

@@ -78,24 +78,21 @@ enum RCTVideoDRM {
contentIdData: Data
) -> Promise<Data> {
return Promise<Data>(on: .global()) { fulfill, reject in
var spcError: NSError!
var spcData: Data?
do {
spcData = try loadingRequest.streamingContentKeyRequestData(forApp: certificateData, contentIdentifier: contentIdData as Data, options: nil)
} catch _ {
print("SPC error")
}
#if os(visionOS)
// TODO: DRM is not supported yet on visionOS. See #3467
reject(NSError(domain: "DRM is not supported yet on visionOS", code: 0, userInfo: nil))
#else
guard let spcData = try? loadingRequest.streamingContentKeyRequestData(
forApp: certificateData,
contentIdentifier: contentIdData as Data,
options: nil
) else {
reject(RCTVideoErrorHandler.noSPC)
return
}
if spcError != nil {
reject(spcError)
}
guard let spcData else {
reject(RCTVideoErrorHandler.noSPC)
return
}
fulfill(spcData)
fulfill(spcData)
#endif
}
}

View File

@@ -28,9 +28,11 @@ enum RCTVideoAssetsUtils {
asset.loadTracks(withMediaType: withMediaType, completionHandler: handler)
}
} else {
return Promise { fulfill, _ in
fulfill(asset.tracks(withMediaType: withMediaType))
}
#if !os(visionOS)
return Promise { fulfill, _ in
fulfill(asset.tracks(withMediaType: withMediaType))
}
#endif
}
}
}

View File

@@ -508,7 +508,9 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
@objc
func setAllowsExternalPlayback(_ allowsExternalPlayback: Bool) {
_allowsExternalPlayback = allowsExternalPlayback
_player?.allowsExternalPlayback = _allowsExternalPlayback
#if !os(visionOS)
_player?.allowsExternalPlayback = _allowsExternalPlayback
#endif
}
@objc
@@ -642,7 +644,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
RCTPlayerOperations.configureAudio(ignoreSilentSwitch: _ignoreSilentSwitch, mixWithOthers: _mixWithOthers, audioOutput: _audioOutput)
do {
if audioOutput == "speaker" {
#if os(iOS)
#if os(iOS) || os(visionOS)
try AVAudioSession.sharedInstance().overrideOutputAudioPort(AVAudioSession.PortOverride.speaker)
#endif
} else if audioOutput == "earpiece" {
@@ -713,7 +715,9 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
}
if #available(iOS 12.0, tvOS 12.0, *) {
_player?.preventsDisplaySleepDuringVideoPlayback = _preventsDisplaySleepDuringVideoPlayback
#if !os(visionOS)
_player?.preventsDisplaySleepDuringVideoPlayback = _preventsDisplaySleepDuringVideoPlayback
#endif
} else {
// Fallback on earlier versions
}
@@ -972,12 +976,8 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
}
let filter: CIFilter! = CIFilter(name: filterName)
if #available(iOS 9.0, *), let _playerItem {
RCTVideoUtils.generateVideoComposition(asset: _playerItem.asset, filter: filter).then { [weak self] composition in
self?._playerItem?.videoComposition = composition
}
} else {
// Fallback on earlier versions
RCTVideoUtils.generateVideoComposition(asset: _playerItem!.asset, filter: filter).then { [weak self] composition in
self?._playerItem?.videoComposition = composition
}
}
@@ -1280,9 +1280,11 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
}
func handleExternalPlaybackActiveChange(player _: AVPlayer, change _: NSKeyValueObservedChange<Bool>) {
guard let _player else { return }
onVideoExternalPlaybackChange?(["isExternalPlaybackActive": NSNumber(value: _player.isExternalPlaybackActive),
"target": reactTag as Any])
#if !os(visionOS)
guard let _player else { return }
onVideoExternalPlaybackChange?(["isExternalPlaybackActive": NSNumber(value: _player.isExternalPlaybackActive),
"target": reactTag as Any])
#endif
}
func handleViewControllerOverlayViewFrameChange(overlayView _: UIView, change: NSKeyValueObservedChange<CGRect>) {