Procházet zdrojové kódy

show a warning if qr code scanner setup fails

cyberta před 4 roky
rodič
revize
40935e6faa
1 změnil soubory, kde provedl 58 přidání a 28 odebrání
  1. 58 28
      deltachat-ios/Controller/QrCodeReaderController.swift

+ 58 - 28
deltachat-ios/Controller/QrCodeReaderController.swift

@@ -1,11 +1,15 @@
 import AVFoundation
 import UIKit
+import DcCore
 
 class QrCodeReaderController: UIViewController {
 
     weak var delegate: QrCodeReaderDelegate?
 
     private let captureSession = AVCaptureSession()
+    
+    private var infoLabelBottomConstraint: NSLayoutConstraint?
+    private var infoLabelCenterConstraint: NSLayoutConstraint?
 
     private lazy var videoPreviewLayer: AVCaptureVideoPreviewLayer = {
         let videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
@@ -36,34 +40,23 @@ class QrCodeReaderController: UIViewController {
         super.viewDidLoad()
         self.edgesForExtendedLayout = []
         title = String.localized("qrscan_title")
-
-        guard let captureDevice = AVCaptureDevice.DiscoverySession.init(
-            deviceTypes: [AVCaptureDevice.DeviceType.builtInWideAngleCamera],
-            mediaType: .video,
-            position: .back).devices.first else {
-            print("Failed to get the camera device")
-            return
-        }
-
-        do {
-            let input = try AVCaptureDeviceInput(device: captureDevice)
-            captureSession.addInput(input)
-
-            let captureMetadataOutput = AVCaptureMetadataOutput()
-            captureSession.addOutput(captureMetadataOutput)
-
-            captureMetadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
-            captureMetadataOutput.metadataObjectTypes = supportedCodeTypes
-        } catch {
-            // If any error occurs, simply print it out and don't continue any more.
-            logger.error("failed to setup QR Code Scanner: \(error)")
-            return
+        self.setupInfoLabel()
+        if AVCaptureDevice.authorizationStatus(for: .video) == .authorized {
+            self.setupQRCodeScanner()
+        } else {
+            AVCaptureDevice.requestAccess(for: .video, completionHandler: {  [weak self] (granted: Bool) in
+                guard let self = self else { return }
+                if granted {
+                    self.setupQRCodeScanner()
+                } else {
+                    self.setInfoWarning(text: "You need to give Delta Chat the camera permission in order to use the QR-Code scanner")
+                }
+            })
         }
-
-        setupSubviews()
     }
 
     override func viewWillAppear(_ animated: Bool) {
+        super.viewWillAppear(animated)
         startSession()
     }
 
@@ -82,18 +75,55 @@ class QrCodeReaderController: UIViewController {
     }
 
     // MARK: - setup
-    private func setupSubviews() {
+    
+    private func setupQRCodeScanner() {
+        guard let captureDevice = AVCaptureDevice.DiscoverySession.init(
+            deviceTypes: [AVCaptureDevice.DeviceType.builtInWideAngleCamera],
+            mediaType: .video,
+            position: .back).devices.first else {
+            self.setInfoWarning(text: "Failed to get the camera device. It might be occupied by another app.")
+            return
+        }
+        do {
+            let input = try AVCaptureDeviceInput(device: captureDevice)
+            self.captureSession.addInput(input)
+
+            let captureMetadataOutput = AVCaptureMetadataOutput()
+            self.captureSession.addOutput(captureMetadataOutput)
+
+            captureMetadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
+            captureMetadataOutput.metadataObjectTypes = self.supportedCodeTypes
+        } catch {
+            // If any error occurs, simply print it out and don't continue any more.
+            self.setInfoWarning(text: "failed to setup QR Code Scanner: \(error)")
+            return
+        }
         view.layer.addSublayer(videoPreviewLayer)
         videoPreviewLayer.frame = view.layer.bounds
+    }
+    
+    private func setupInfoLabel() {
         view.addSubview(infoLabel)
         infoLabel.translatesAutoresizingMaskIntoConstraints = false
-
-        infoLabel.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -10).isActive = true
+        infoLabelBottomConstraint = infoLabel.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -10)
+        infoLabelCenterConstraint = infoLabel.constraintCenterYTo(view)
+        infoLabelBottomConstraint?.isActive = true
         infoLabel.constraintAlignLeadingTo(view, paddingLeading: 5).isActive = true
         infoLabel.constraintAlignTrailingTo(view, paddingTrailing: 5).isActive = true
         view.bringSubviewToFront(infoLabel)
     }
-
+    
+    private func setInfoWarning(text: String) {
+        DispatchQueue.main.async { [weak self] in
+            guard let self = self else { return }
+            logger.error(text)
+            self.infoLabel.textColor = DcColors.defaultTextColor
+            self.infoLabel.text = text
+            self.infoLabelBottomConstraint?.isActive = false
+            self.infoLabelCenterConstraint?.isActive = true
+        }
+    }
+    
     private func updateVideoOrientation() {
 
         guard let connection = videoPreviewLayer.connection else {