feat: Support rotation (#301)

* feat: Android: Listen to rotation changes

* Only change rotation on configuration change

* feat: iOS: Support Rotation

* Swift lint
This commit is contained in:
Marc Rousavy
2021-07-26 11:32:58 +02:00
committed by GitHub
parent 159ff44de3
commit ef455df865
8 changed files with 119 additions and 36 deletions

View File

@@ -105,10 +105,20 @@ public final class CameraView: UIView {
/// Specifies whether the frameProcessor() function is currently executing. used to drop late frames.
internal var isRunningFrameProcessor = false
/// Returns whether the AVCaptureSession is currently running (reflected by isActive)
var isRunning: Bool {
return captureSession.isRunning
}
/// Returns the current _interface_ orientation of the main window
private var windowInterfaceOrientation: UIInterfaceOrientation {
if #available(iOS 13.0, *) {
return UIApplication.shared.windows.first?.windowScene?.interfaceOrientation ?? .unknown
} else {
return UIApplication.shared.statusBarOrientation
}
}
/// Convenience wrapper to get layer as its statically known type.
var videoPreviewLayer: AVCaptureVideoPreviewLayer {
// swiftlint:disable force_cast
@@ -138,6 +148,10 @@ public final class CameraView: UIView {
selector: #selector(audioSessionInterrupted),
name: AVAudioSession.interruptionNotification,
object: AVAudioSession.sharedInstance)
NotificationCenter.default.addObserver(self,
selector: #selector(onOrientationChanged),
name: UIDevice.orientationDidChangeNotification,
object: nil)
}
@available(*, unavailable)
@@ -155,6 +169,9 @@ public final class CameraView: UIView {
NotificationCenter.default.removeObserver(self,
name: AVAudioSession.interruptionNotification,
object: AVAudioSession.sharedInstance)
NotificationCenter.default.removeObserver(self,
name: UIDevice.orientationDidChangeNotification,
object: nil)
}
// pragma MARK: Props updating
@@ -269,6 +286,31 @@ public final class CameraView: UIView {
}
}
@objc
func onOrientationChanged() {
// Updates the Orientation for all rotable connections (outputs) as well as for the preview layer
DispatchQueue.main.async {
// `windowInterfaceOrientation` and `videoPreviewLayer` should only be accessed from UI thread
let isMirrored = self.videoDeviceInput?.device.position == .front
let orientation = self.windowInterfaceOrientation
self.videoPreviewLayer.connection?.setInterfaceOrientation(orientation)
self.cameraQueue.async {
// Run those updates on cameraQueue since they can be blocking.
self.captureSession.outputs.forEach { output in
output.connections.forEach { connection in
if connection.isVideoMirroringSupported {
connection.automaticallyAdjustsVideoMirroring = false
connection.isVideoMirrored = isMirrored
}
connection.setInterfaceOrientation(orientation)
}
}
}
}
}
// pragma MARK: Event Invokers
internal final func invokeOnError(_ error: CameraError, cause: NSError? = nil) {
ReactLogger.log(level: .error, message: "Invoking onError(): \(error.message)")