Skip to content

Commit

Permalink
added 11.6.0
Browse files Browse the repository at this point in the history
  • Loading branch information
sMaltsevAcuant committed May 25, 2023
1 parent 8a89d86 commit b51c4ad
Show file tree
Hide file tree
Showing 295 changed files with 127,784 additions and 64,535 deletions.
188 changes: 131 additions & 57 deletions AcuantCamera/AcuantCamera.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//
// BarcodeCameraOptions.swift
// AcuantCamera
//
// Created by Federico Nicoli on 7/12/22.
// Copyright © 2022 Acuant. All rights reserved.
//

@objc public enum BarcodeCameraState: Int {
case align
case capturing
}

@objcMembers public class BarcodeCameraOptions: CameraOptions {
public let waitTimeAfterCapturingInSeconds: Int
public let timeoutInSeconds: Int
public let textForState: (BarcodeCameraState) -> String
public let colorForState: (BarcodeCameraState) -> CGColor

public init(hideNavigationBar: Bool = true,
showBackButton: Bool = true,
waitTimeAfterCapturingInSeconds: Int = 1,
timeoutInSeconds: Int = 20,
placeholderImageName: String? = "barcode_placement_overlay",
textForState: @escaping (BarcodeCameraState) -> String = { state in
switch state {
case .align: return "CAPTURE BARCODE"
case .capturing: return "CAPTURING"
@unknown default: return ""
}
},
colorForState: @escaping (BarcodeCameraState) -> CGColor = { state in
switch state {
case .align: return UIColor.white.cgColor
case .capturing: return UIColor.green.cgColor
@unknown default: return UIColor.white.cgColor
}
},
textForCameraPaused: String = "CAMERA PAUSED",
backButtonText: String = "BACK") {
self.waitTimeAfterCapturingInSeconds = waitTimeAfterCapturingInSeconds
self.timeoutInSeconds = timeoutInSeconds
self.textForState = textForState
self.colorForState = colorForState
super.init(hideNavigationBar: hideNavigationBar,
showBackButton: showBackButton,
placeholderImageName: placeholderImageName,
bracketLengthInHorizontal: 0,
bracketLengthInVertical: 0,
textForCameraPaused: textForCameraPaused,
backButtonText: backButtonText)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,101 +9,60 @@
import UIKit
import AVFoundation

@objcMembers public class BarcodeCameraViewController: UIViewController {

private var cameraPreviewView: CameraPreviewView!
private var messageLayer: CameraTextView!
private var barcodeLayer: DocumentPlaceholderLayer?
private var alertView: CameraAlertView?
private var captureSession: BarcodeCaptureSession!

private var options: CameraOptions!
@objcMembers public class BarcodeCameraViewController: CameraViewController {
private let barcodeOptions: BarcodeCameraOptions
private var timeoutTimer: Timer?
private var afterCaptureTimer: Timer?
private var isNavigationBarHidden = false

private weak var delegate: BarcodeCameraDelegate?

override public var prefersStatusBarHidden: Bool {
true
}
public weak var delegate: BarcodeCameraViewControllerDelegate?

public init(options: CameraOptions, delegate: BarcodeCameraDelegate) {
self.options = options
self.delegate = delegate
super.init(nibName: nil, bundle: nil)
messageLayer = createMessageLayer(holdColor: options.colorHold, capturingColor: options.colorCapturing)
barcodeLayer = createBarcodeLayer()
timeoutTimer = scheduleTimeoutTimer(options.digitsToShow)
public init(options: BarcodeCameraOptions) {
barcodeOptions = options
let captureDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: AVMediaType.video, position: .back)!
let captureSession = BarcodeCaptureSession(captureDevice: captureDevice)
super.init(options: options, captureSession: captureSession)
timeoutTimer = scheduleTimeoutTimer(options.timeoutInSeconds)
captureSession.delegate = self
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override public func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
handleNavigationBarVisibility()
addDeviceOrientationObserver()
addCaptureSessionObservers()
override public func viewDidLoad() {
super.viewDidLoad()
customizeImageLayer()
customizeMessageLayer()
}

override public func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
attachSession()
override func onCameraInterrupted() {
messageLayer.string = options.textForCameraPaused
imageLayer?.isHidden = true
}

override public func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
detachSession()
NotificationCenter.default.removeObserver(self)
navigationController?.setNavigationBarHidden(isNavigationBarHidden, animated: false)
override func onCameraInterruptionEnded() {
imageLayer?.isHidden = false
messageLayer.string = barcodeOptions.textForState(.align)
}

override public func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)

coordinator.animate(alongsideTransition: { [weak self] context in
guard let self = self else { return }
override func onBackTapped() {
delegate?.onCaptured(barcode: nil)
}

let newFrame = CGRect(origin: self.view.frame.origin, size: size)
self.rotateCameraPreview(to: self.view.window?.interfaceOrientation, frame: newFrame)
})
override func onPreviewCreated() {
cameraPreviewView.videoPreviewLayer.videoGravity = .resizeAspectFill
}

private func createMessageLayer(holdColor: CGColor, capturingColor: CGColor) -> CameraTextView {
let messageLayer = CameraTextView()
messageLayer.string = NSLocalizedString("acuant_camera_capture_barcode", comment: "")
messageLayer.foregroundColorDefault = holdColor
messageLayer.foregroundColorCapture = capturingColor
private func customizeMessageLayer() {
messageLayer.string = barcodeOptions.textForState(.align)
messageLayer.foregroundColorDefault = barcodeOptions.colorForState(.align)
messageLayer.foregroundColorCapture = barcodeOptions.colorForState(.capturing)
messageLayer.backgroundColorCapture = UIColor.black.cgColor
messageLayer.textSizeCapture = 30
return messageLayer
}

private func createBarcodeLayer() -> DocumentPlaceholderLayer? {
guard let barcodeImage = getPlaceholderImage() else {
return nil
}

let barcodeLayer = DocumentPlaceholderLayer(image: barcodeImage, bounds: view.frame)
barcodeLayer.opacity = 0.4
return barcodeLayer
}

private func getPlaceholderImage() -> UIImage? {
if let image = UIImage(named: "barcode_placement_overlay",
in: Bundle(for: BarcodeCameraViewController.self),
compatibleWith: nil) {
return image
} else if let bundlePath = Bundle(for: BarcodeCameraViewController.self).path(forResource: "AcuantCameraAssets",
ofType: "bundle"),
let bundle = Bundle(path: bundlePath), let image = UIImage(named: "barcode_placement_overlay",
in: bundle,
compatibleWith: nil) {
return image
}
return nil
private func customizeImageLayer() {
imageLayer?.opacity = 0.4
}

private func scheduleTimeoutTimer(_ timeout: Int) -> Timer {
Expand All @@ -112,168 +71,32 @@ import AVFoundation

self.afterCaptureTimer?.invalidate()
self.navigationController?.popViewController(animated: true)
self.delegate?.captured(barcode: nil)
}
}

private func handleNavigationBarVisibility() {
isNavigationBarHidden = navigationController?.isNavigationBarHidden ?? false
navigationController?.setNavigationBarHidden(options.hideNavigationBar, animated: false)
}

private func addNavigationBackButton() {
let backButton = UIButton(frame: CGRect(x: 0, y: UIScreen.main.heightOfSafeArea() * 0.065, width: 90, height: 40))

var attribs: [NSAttributedString.Key: Any?] = [:]
attribs[NSAttributedString.Key.font] = UIFont.systemFont(ofSize: 18)
attribs[NSAttributedString.Key.foregroundColor] = UIColor.white
attribs[NSAttributedString.Key.baselineOffset] = 4

let str = NSMutableAttributedString(string: "BACK", attributes: attribs as [NSAttributedString.Key: Any])
backButton.setAttributedTitle(str, for: .normal)
backButton.addTarget(self, action: #selector(backTapped), for: .touchUpInside)
backButton.isOpaque = true
backButton.imageView?.contentMode = .scaleAspectFit

view.addSubview(backButton)
}

@objc private func backTapped(_ sender: Any) {
delegate?.captured(barcode: nil)
navigationController?.popViewController(animated: true)
}

private func attachSession() {
let captureDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: AVMediaType.video, position: .back)!
captureSession = BarcodeCaptureSession(captureDevice: captureDevice, delegate: self)
cameraPreviewView = CameraPreviewView(frame: view.frame, captureSession: captureSession)
cameraPreviewView.videoPreviewLayer.videoGravity = .resizeAspectFill

if let barcodeLayer = barcodeLayer {
cameraPreviewView.layer.addSublayer(barcodeLayer)
}
messageLayer.setFrame(frame: view.frame)
cameraPreviewView.layer.addSublayer(messageLayer)
view.addSubview(cameraPreviewView)

if options.showBackButton {
addNavigationBackButton()
}

captureSession.start {
self.rotateCameraPreview(to: self.view.window?.interfaceOrientation, frame: self.view.frame)
}
}

private func detachSession() {
captureSession.stop()
cameraPreviewView.removeFromSuperview()
}

private func rotateCameraPreview(to interfaceOrientation: UIInterfaceOrientation?, frame: CGRect) {
guard let connection = cameraPreviewView.videoPreviewLayer.connection,
connection.isVideoOrientationSupported,
let orientation = interfaceOrientation else {
return
}

cameraPreviewView.frame = frame
connection.videoOrientation = orientation.videoOrientation ?? .portrait
cameraPreviewView.clearAccessibilityElements()

if orientation.isLandscape {
messageLayer.transform = CATransform3DIdentity
messageLayer.setFrame(frame: frame)
barcodeLayer?.transform = CATransform3DIdentity
barcodeLayer?.setFrame(frame: frame)
} else {
if CATransform3DIsIdentity(messageLayer.transform) {
messageLayer.rotate(angle: 90)
}
if let barcodeLayer = barcodeLayer, CATransform3DIsIdentity(barcodeLayer.transform) {
barcodeLayer.setFrame(frame: frame)
barcodeLayer.rotate(angle: 90)
}
messageLayer.setVerticalDefaultSettings(frame: frame)
}
cameraPreviewView.videoPreviewLayer.removeAllAnimations()
}

private func addDeviceOrientationObserver() {
guard let orientations = Bundle.main.infoDictionary?[.kUISupportedInterfaceOrientations] as? [String],
orientations.count == 1,
orientations[0] == .kUIInterfaceOrientationPortrait else {
return
}

UIDevice.current.beginGeneratingDeviceOrientationNotifications()
NotificationCenter.default.addObserver(self,
selector: #selector(self.deviceDidRotate),
name: UIDevice.orientationDidChangeNotification,
object: nil)
}

private func addCaptureSessionObservers() {
NotificationCenter.default.addObserver(forName: .AVCaptureSessionWasInterrupted,
object: captureSession,
queue: .main) { [weak self] _ in
guard let self = self, self.alertView == nil else { return }

self.messageLayer.string = NSLocalizedString("acuant_camera_paused", comment: "")
self.barcodeLayer?.isHidden = true
let alertView = CameraAlertView(frame: self.view.bounds)
self.view.addSubview(alertView)
self.view.bringSubviewToFront(alertView)
self.alertView = alertView
}

NotificationCenter.default.addObserver(forName: .AVCaptureSessionInterruptionEnded,
object: captureSession,
queue: .main) { [weak self] _ in
guard let self = self else { return }

self.alertView?.removeFromSuperview()
self.barcodeLayer?.isHidden = false
self.alertView = nil
self.messageLayer.string = NSLocalizedString("acuant_camera_capture_barcode", comment: "")
}
}

@objc private func deviceDidRotate(notification: NSNotification) {
let currentOrientation = UIDevice.current.orientation
if currentOrientation.isLandscape {
if currentOrientation == UIDeviceOrientation.landscapeLeft {
messageLayer.rotate(angle: -270)
barcodeLayer?.rotate(angle: -270)
} else if currentOrientation == UIDeviceOrientation.landscapeRight {
messageLayer.rotate(angle: 270)
barcodeLayer?.rotate(angle: 270)
}
self.delegate?.onCaptured(barcode: nil)
}
}

}

//MARK: - BarcodeCaptureDelegate

extension BarcodeCameraViewController: BarcodeCaptureDelegate {
extension BarcodeCameraViewController: BarcodeCaptureSessionDelegate {

public func captured(barcode: String?) {
guard let barcode = barcode, afterCaptureTimer == nil else { return }

messageLayer.string = NSLocalizedString("acuant_camera_capturing", comment: "")
messageLayer.string = barcodeOptions.textForState(.capturing)
if let orientation = view.window?.interfaceOrientation, orientation.isPortrait {
messageLayer.setVerticalCaptureSettings(frame: view.bounds)
} else {
messageLayer.setCaptureSettings(frame: view.bounds)
}
afterCaptureTimer = Timer.scheduledTimer(withTimeInterval: TimeInterval(options.timeInMsPerDigit/1000),
repeats: false) { [weak self] _ in
afterCaptureTimer = Timer.scheduledTimer(withTimeInterval: TimeInterval(barcodeOptions.waitTimeAfterCapturingInSeconds),
repeats: false) { [weak self] _ in
guard let self = self else { return }

self.timeoutTimer?.invalidate()
self.navigationController?.popViewController(animated: true)
self.delegate?.captured(barcode: barcode)
self.delegate?.onCaptured(barcode: barcode)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//
// BarcodeCameraDelegate.swift
// AcuantCamera
//
// Created by Federico Nicoli on 9/8/21.
// Copyright © 2021 Acuant. All rights reserved.
//

@objc public protocol BarcodeCameraViewControllerDelegate: AnyObject {
func onCaptured(barcode: String?)
}

This file was deleted.

Loading

0 comments on commit b51c4ad

Please sign in to comment.