Browse Source

fixed orientation bug in qr - preparing qrRederController to be used from welcomeScreen

nayooti 5 năm trước cách đây
mục cha
commit
8ea9b7fff9

+ 88 - 24
deltachat-ios/Controller/QrCodeReaderController.swift

@@ -2,20 +2,43 @@ import AVFoundation
 import UIKit
 
 class QrCodeReaderController: UIViewController {
-    var captureSession = AVCaptureSession()
-
-    var videoPreviewLayer: AVCaptureVideoPreviewLayer?
 
     weak var delegate: QrCodeReaderDelegate?
 
+    private let captureSession = AVCaptureSession()
+
+    private lazy var videoPreviewLayer: AVCaptureVideoPreviewLayer = {
+        let videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
+        videoPreviewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
+        return videoPreviewLayer
+    }()
+
+    private var infoLabel: UILabel = {
+        let label = UILabel()
+           label.translatesAutoresizingMaskIntoConstraints = false
+           label.text = String.localized("qrscan_hint")
+           label.lineBreakMode = .byWordWrapping
+           label.numberOfLines = 0
+           label.textAlignment = .center
+           label.textColor = .white
+           return label
+    }()
+
+    private lazy var closeButton: UIBarButtonItem = {
+        return UIBarButtonItem(title: String.localized("cancel"), style: .done, target: self, action: #selector(closeButtonPressed(_:)))
+    }()
+
+
     private let supportedCodeTypes = [
         AVMetadataObject.ObjectType.qr
     ]
 
+    // MARK: - lifecycle
     override func viewDidLoad() {
         super.viewDidLoad()
         self.edgesForExtendedLayout = []
         title = String.localized("qrscan_title")
+        navigationItem.leftBarButtonItem = closeButton
 
         guard let captureDevice = AVCaptureDevice.DiscoverySession.init(
             deviceTypes: [AVCaptureDevice.DeviceType.builtInWideAngleCamera],
@@ -40,33 +63,23 @@ class QrCodeReaderController: UIViewController {
             return
         }
 
-        videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
-        videoPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
-        videoPreviewLayer?.frame = view.layer.bounds
-        view.layer.addSublayer(videoPreviewLayer!)
-
-        let infoLabel = createInfoLabel()
-        view.addSubview(infoLabel)
-        view.addConstraint(infoLabel.constraintAlignBottomTo(view, paddingBottom: 8))
-        view.addConstraint(infoLabel.constraintCenterXTo(view))
-        view.bringSubviewToFront(infoLabel)
+        setupSubviews()
     }
 
-    private func createInfoLabel() -> UIView {
-        let label = UILabel()
-        label.translatesAutoresizingMaskIntoConstraints = false
-        label.text = String.localized("qrscan_hint")
-        label.lineBreakMode = .byWordWrapping
-        label.numberOfLines = 0
-        label.textAlignment = .center
-        label.textColor = .white
-        return label
+    override func viewWillAppear(_ animated: Bool) {
+        captureSession.startRunning()
     }
 
+  override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
+        super.viewWillTransition(to: size, with: coordinator)
 
-    override func viewWillAppear(_ animated: Bool) {
-        captureSession.startRunning()
+        coordinator.animate(alongsideTransition: nil, completion: { [weak self] _ in
+            DispatchQueue.main.async(execute: {
+                self?.updateVideoOrientation()
+            })
+        })
     }
+
     override func viewWillDisappear(_ animated: Bool) {
         captureSession.stopRunning()
     }
@@ -75,6 +88,45 @@ class QrCodeReaderController: UIViewController {
         super.didReceiveMemoryWarning()
         // Dispose of any resources that can be recreated.
     }
+
+    // MARK: - setup
+    private func setupSubviews() {
+        view.layer.addSublayer(videoPreviewLayer)
+        videoPreviewLayer.frame = view.layer.bounds
+        view.addSubview(infoLabel)
+        infoLabel.translatesAutoresizingMaskIntoConstraints = false
+        view.addConstraint(infoLabel.constraintAlignBottomTo(view, paddingBottom: 8))
+        view.addConstraint(infoLabel.constraintCenterXTo(view))
+        view.bringSubviewToFront(infoLabel)
+    }
+
+    func updateVideoOrientation() {
+
+        guard let connection = videoPreviewLayer.connection else {
+            return
+        }
+
+        guard connection.isVideoOrientationSupported else {
+            return
+        }
+
+        let statusBarOrientation = UIApplication.shared.statusBarOrientation
+        let videoOrientation: AVCaptureVideoOrientation =  statusBarOrientation.videoOrientation ?? .portrait
+
+        if connection.videoOrientation == videoOrientation {
+            print("no change to videoOrientation")
+            return
+        }
+
+        videoPreviewLayer.frame = view.bounds
+        connection.videoOrientation = videoOrientation
+        videoPreviewLayer.removeAllAnimations()
+    }
+
+    // MARK: - actions
+    @objc private func closeButtonPressed(_ sender: UIBarButtonItem) {
+        self.dismiss(animated: true, completion: nil)
+    }
 }
 
 extension QrCodeReaderController: AVCaptureMetadataOutputObjectsDelegate {
@@ -89,3 +141,15 @@ extension QrCodeReaderController: AVCaptureMetadataOutputObjectsDelegate {
         }
     }
 }
+
+extension UIInterfaceOrientation {
+    var videoOrientation: AVCaptureVideoOrientation? {
+        switch self {
+        case .portraitUpsideDown: return .portraitUpsideDown
+        case .landscapeRight: return .landscapeRight
+        case .landscapeLeft: return .landscapeLeft
+        case .portrait: return .portrait
+        default: return nil
+        }
+    }
+}

+ 3 - 3
deltachat-ios/Controller/QrViewController.swift

@@ -288,9 +288,9 @@ class QrViewController: UITableViewController, QrCodeReaderDelegate {
     }
 
     @objc func openQRCodeScanner() {
-        if let ctrl = navigationController {
-            ctrl.pushViewController(qrCodeReaderController, animated: true)
-        }
+        let nav = UINavigationController(rootViewController: qrCodeReaderController)
+        nav.modalPresentationStyle = .fullScreen
+        present(nav, animated: true)
     }
 
     private func createQRCodeView() -> UIView {

+ 5 - 1
deltachat-ios/Controller/WelcomeViewController.swift

@@ -16,6 +16,10 @@ class WelcomeViewController: UIViewController {
             [unowned self] in
             self.coordinator?.showLogin()
         }
+        view.onScanQRCode = {
+            [unowned self] in
+            self.coordinator?.showQR()
+        }
         view.translatesAutoresizingMaskIntoConstraints = false
         return view
     }()
@@ -154,7 +158,7 @@ class WelcomeContentView: UIView {
     }()
 
     private lazy var buttonStack: UIStackView = {
-        let stack = UIStackView(arrangedSubviews: [loginButton /*, qrCodeButton, importBackupButton */])
+        let stack = UIStackView(arrangedSubviews: [loginButton, qrCodeButton /*, importBackupButton */])
         stack.axis = .vertical
         stack.spacing = 10
         return stack

+ 3 - 1
deltachat-ios/Coordinator/AppCoordinator.swift

@@ -175,7 +175,9 @@ extension AppCoordinator: WelcomeCoordinator {
     }
 
     func showQR() {
-        return
+        let qrController = QrCodeReaderController()
+        let nav = UINavigationController(rootViewController: qrController)
+        welcomeController.present(nav, animated: true)
     }
 
     private func handleLoginSuccess() {