129 lines
4.0 KiB
Swift
129 lines
4.0 KiB
Swift
//
|
|
// ScanVC.swift
|
|
// QuickLocation
|
|
//
|
|
|
|
import UIKit
|
|
import AVFoundation
|
|
import RxSwift
|
|
|
|
class ScanVC: BaseViewController {
|
|
|
|
override var isNavigationBarHidden: Bool { true }
|
|
override var preferredStatusBarStyle: UIStatusBarStyle { .lightContent }
|
|
|
|
private var rootView: CameraCaptureView!
|
|
private let scanDoneAction: ((String) -> Void)?
|
|
private var isHandling = false
|
|
|
|
override func loadView() {
|
|
rootView = CameraCaptureView(mode: .scan)
|
|
view = rootView
|
|
}
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
rootView.onClose = { [weak self] in
|
|
self?.closeCapture()
|
|
}
|
|
rootView.onScan = { [weak self] text in
|
|
self?.handleScanResult(text: text)
|
|
}
|
|
rootView.onOpenAlbum = { [weak self] in
|
|
self?.openAlbum()
|
|
}
|
|
}
|
|
|
|
override func viewWillAppear(_ animated: Bool) {
|
|
super.viewWillAppear(animated)
|
|
isHandling = false
|
|
rootView.startSession()
|
|
}
|
|
|
|
override func viewWillDisappear(_ animated: Bool) {
|
|
super.viewWillDisappear(animated)
|
|
rootView.stopSession()
|
|
}
|
|
|
|
init(scanDoneAction: ((String) -> Void)? = nil) {
|
|
self.scanDoneAction = scanDoneAction
|
|
super.init(nibName: nil, bundle: nil)
|
|
}
|
|
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
private func closeCapture() {
|
|
if presentingViewController != nil {
|
|
dismiss(animated: true)
|
|
} else {
|
|
navigationController?.popViewController(animated: true)
|
|
}
|
|
}
|
|
|
|
private func handleScanResult(text: String) {
|
|
guard !isHandling else { return }
|
|
isHandling = true
|
|
rootView.stopSession()
|
|
if let scanDoneAction {
|
|
scanDoneAction(text)
|
|
closeCapture()
|
|
return
|
|
}
|
|
requestJoinGroup(code: text)
|
|
}
|
|
|
|
private func requestJoinGroup(code: String) {
|
|
DLToast.showLoading()
|
|
GroupService.operate(opType: "join", requestData: ["share_code": code]).subscribe(onNext: { response in
|
|
DLToast.showSuccess(text: response.message ?? "申请成功") {
|
|
AppRouter.shared.popOrDismiss()
|
|
}
|
|
}, onError: { [weak self] _ in
|
|
DLToast.showError(text: "无法识别该二维码")
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
|
|
self?.isHandling = false
|
|
self?.rootView.startSession()
|
|
}
|
|
}).disposed(by: disposeBag)
|
|
}
|
|
|
|
private func openAlbum() {
|
|
guard UIImagePickerController.isSourceTypeAvailable(.photoLibrary) else { return }
|
|
let picker = UIImagePickerController()
|
|
picker.sourceType = .photoLibrary
|
|
picker.delegate = self
|
|
present(picker, animated: true)
|
|
}
|
|
|
|
private func decodeQR(from image: UIImage) {
|
|
guard let ciImage = CIImage(image: image) else {
|
|
DLToast.show(text: "无法识别二维码")
|
|
isHandling = false
|
|
return
|
|
}
|
|
let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])
|
|
let features = detector?.features(in: ciImage) ?? []
|
|
if let qr = features.first as? CIQRCodeFeature, let text = qr.messageString, !text.isEmpty {
|
|
handleScanResult(text: text)
|
|
} else {
|
|
DLToast.show(text: "未识别到二维码")
|
|
isHandling = false
|
|
}
|
|
}
|
|
}
|
|
|
|
extension ScanVC: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
|
|
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
|
|
picker.dismiss(animated: true)
|
|
}
|
|
|
|
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
|
|
picker.dismiss(animated: true)
|
|
if let image = info[.originalImage] as? UIImage {
|
|
decodeQR(from: image)
|
|
}
|
|
}
|
|
}
|