Merge pull request #702 from BlueWallet/catal

add mac catalyst support
This commit is contained in:
Seph Soliman 2025-02-27 10:21:16 -08:00 committed by GitHub
commit cb7619bbbd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 73 additions and 4 deletions

View File

@ -28,15 +28,35 @@ import Foundation
@objc public static func checkDeviceCameraAuthorizationStatus(_ resolve: @escaping RCTPromiseResolveBlock,
reject: @escaping RCTPromiseRejectBlock) {
switch AVCaptureDevice.authorizationStatus(for: .video) {
case .authorized: resolve(true)
case .notDetermined: resolve(-1)
default: resolve(false)
#if targetEnvironment(macCatalyst)
if #available(macCatalyst 14.0, *) {
switch AVCaptureDevice.authorizationStatus(for: .video) {
case .authorized: resolve(true)
case .notDetermined: resolve(-1)
default: resolve(false)
}
} else {
resolve(false)
}
#else
switch AVCaptureDevice.authorizationStatus(for: .video) {
case .authorized: resolve(true)
case .notDetermined: resolve(-1)
default: resolve(false)
}
#endif
}
@objc public static func requestDeviceCameraAuthorization(_ resolve: @escaping RCTPromiseResolveBlock,
reject: @escaping RCTPromiseRejectBlock) {
#if targetEnvironment(macCatalyst)
if #available(macCatalyst 14.0, *) {
AVCaptureDevice.requestAccess(for: .video, completionHandler: { resolve($0) })
} else {
resolve(false)
}
#else
AVCaptureDevice.requestAccess(for: .video, completionHandler: { resolve($0) })
#endif
}
}

View File

@ -80,7 +80,12 @@ public class CameraView: UIView {
private func setupCamera() {
if hasPropBeenSetup && hasPermissionBeenGranted && !hasCameraBeenSetup {
hasCameraBeenSetup = true
#if targetEnvironment(macCatalyst)
// Force front camera on Mac Catalyst during initial setup
camera.setup(cameraType: .front, supportedBarcodeType: scanBarcode && onReadCode != nil ? supportedBarcodeType : [])
#else
camera.setup(cameraType: cameraType, supportedBarcodeType: scanBarcode && onReadCode != nil ? supportedBarcodeType : [])
#endif
}
}
@ -124,6 +129,7 @@ public class CameraView: UIView {
}
private func configureHardwareInteraction() {
#if !targetEnvironment(macCatalyst)
// Create a new capture event interaction with a handler that captures a photo.
if #available(iOS 17.2, *) {
let interaction = AVCaptureEventInteraction { event in
@ -138,6 +144,7 @@ public class CameraView: UIView {
self.addInteraction(interaction)
eventInteraction = interaction
}
#endif
}
override public func removeFromSuperview() {
@ -177,7 +184,12 @@ public class CameraView: UIView {
// Camera settings
if changedProps.contains("cameraType") {
#if targetEnvironment(macCatalyst)
// Force front camera on Mac Catalyst regardless of what's passed
camera.update(cameraType: .front)
#else
camera.update(cameraType: cameraType)
#endif
}
if changedProps.contains("flashMode") {
camera.update(flashMode: flashMode)
@ -314,6 +326,26 @@ public class CameraView: UIView {
}
private func handleCameraPermission() {
#if targetEnvironment(macCatalyst)
// On macOS, camera permissions are handled differently
if #available(macCatalyst 14.0, *) {
switch AVCaptureDevice.authorizationStatus(for: .video) {
case .authorized:
hasPermissionBeenGranted = true
case .notDetermined:
AVCaptureDevice.requestAccess(for: .video) { [weak self] granted in
if granted {
DispatchQueue.main.async {
self?.hasPermissionBeenGranted = true
}
}
}
default:
break
}
}
#else
// iOS permission handling
switch AVCaptureDevice.authorizationStatus(for: .video) {
case .authorized:
// The user has previously granted access to the camera.
@ -329,6 +361,7 @@ public class CameraView: UIView {
// The user has previously denied access.
break
}
#endif
}
private func writeCaptured(imageData: Data,

View File

@ -55,6 +55,7 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
// MARK: - Lifecycle
#if !targetEnvironment(macCatalyst)
override init() {
super.init()
@ -68,6 +69,12 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
queue: nil,
using: { _ in self.setVideoOrientationToInterfaceOrientation() })
}
#else
override init() {
super.init()
// Mac Catalyst doesn't support device orientation notifications
}
#endif
@available(*, unavailable)
required init?(coder aDecoder: NSCoder) {
@ -82,11 +89,13 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
}
}
#if !targetEnvironment(macCatalyst)
motionManager?.stopAccelerometerUpdates()
NotificationCenter.default.removeObserver(self, name: UIDevice.orientationDidChangeNotification, object: UIDevice.current)
UIDevice.current.endGeneratingDeviceOrientationNotifications()
#endif
}
deinit {
@ -591,6 +600,7 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
// MARK: - Private device orientation from accelerometer
private func initializeMotionManager() {
#if !targetEnvironment(macCatalyst)
motionManager = CMMotionManager()
motionManager?.accelerometerUpdateInterval = 0.2
motionManager?.gyroUpdateInterval = 0.2
@ -612,6 +622,7 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
self.deviceOrientation = newOrientation
self.onOrientationChange?(["orientation": Orientation.init(from: newOrientation)!.rawValue])
})
#endif
}
private func deviceOrientation(from acceleration: CMAcceleration) -> UIDeviceOrientation? {
@ -678,6 +689,7 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
}
private func setVideoOrientationToInterfaceOrientation() {
#if !targetEnvironment(macCatalyst)
var interfaceOrientation: UIInterfaceOrientation
if #available(iOS 13.0, *) {
interfaceOrientation = self.previewView.window?.windowScene?.interfaceOrientation ?? .portrait
@ -685,6 +697,10 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
interfaceOrientation = UIApplication.shared.statusBarOrientation
}
self.cameraPreview.previewLayer.connection?.videoOrientation = self.videoOrientation(from: interfaceOrientation)
#else
// Mac Catalyst always uses landscape orientation
self.cameraPreview.previewLayer.connection?.videoOrientation = .landscapeRight
#endif
}
private func sessionRuntimeError(notification: Notification) {