// // CameraPreviewView.swift // Focale // // Author: Simon-Pierre Boucher // Contact: contact@spboucher.ai // @preconcurrency import AVFoundation import SwiftUI /// AVCaptureVideoPreviewLayer host. The session runs on its own queue; /// attaching it to the layer here is safe and cheap. struct CameraPreviewView: UIViewRepresentable { let session: AVCaptureSession /// Changing this re-runs updateUIView once the session has its inputs, /// so the rotation lands on a connection that actually exists. var isSessionConfigured: Bool = false func makeUIView(context: Context) -> PreviewLayerView { let view = PreviewLayerView() view.previewLayer.session = session view.previewLayer.videoGravity = .resizeAspectFill applyPortraitRotation(to: view) return view } func updateUIView(_ uiView: PreviewLayerView, context: Context) { applyPortraitRotation(to: uiView) } private func applyPortraitRotation(to view: PreviewLayerView) { if let connection = view.previewLayer.connection, connection.isVideoRotationAngleSupported(90) { connection.videoRotationAngle = 90 } } final class PreviewLayerView: UIView { override static var layerClass: AnyClass { AVCaptureVideoPreviewLayer.self } var previewLayer: AVCaptureVideoPreviewLayer { layer as! AVCaptureVideoPreviewLayer } } }