96 lines
2.9 KiB
Swift
96 lines
2.9 KiB
Swift
//
|
|
// AddQRView.swift
|
|
// OTP
|
|
//
|
|
// Created by Shadowfacts on 8/22/21.
|
|
//
|
|
|
|
import SwiftUI
|
|
import CodeScanner
|
|
import OTPKit
|
|
|
|
struct AddQRView: View {
|
|
let dismiss: (DismissAction) -> Void
|
|
@State private var isPresentingScanFailedAlert = false
|
|
@State private var scanError: ScanError?
|
|
@State private var scannedKey: TOTPKey?
|
|
@State private var isShowingConfirmView = false
|
|
|
|
var body: some View {
|
|
NavigationView {
|
|
CodeScannerView(codeTypes: [.qr], scanMode: .once) { (result) in
|
|
switch result {
|
|
case .success(let code):
|
|
if let components = URLComponents(string: code),
|
|
let key = TOTPKey(urlComponents: components) {
|
|
self.scannedKey = key
|
|
isShowingConfirmView = true
|
|
} else {
|
|
isPresentingScanFailedAlert = true
|
|
scanError = .invalidCode(code)
|
|
}
|
|
case .failure(let error):
|
|
isPresentingScanFailedAlert = true
|
|
scanError = .scanner(error)
|
|
}
|
|
}
|
|
.edgesIgnoringSafeArea(.bottom)
|
|
.navigationBarTitle("Scan QR Code", displayMode: .inline)
|
|
.toolbar {
|
|
ToolbarItem(placement: .navigationBarLeading) {
|
|
Button("Cancel") {
|
|
dismiss(.cancel)
|
|
}
|
|
}
|
|
}
|
|
.overlay {
|
|
NavigationLink(isActive: $isShowingConfirmView) {
|
|
EditKeyForm(editingKey: scannedKey, showCancelButton: false, dismiss: dismiss)
|
|
.navigationTitle("Add Key")
|
|
} label: {
|
|
// EmptyView because this is only used to trigger programatic navigation
|
|
EmptyView()
|
|
}
|
|
|
|
}
|
|
}
|
|
.alert("Unable to get OTP key from QR code", isPresented: $isPresentingScanFailedAlert) {
|
|
Button("Cancel", role: .cancel) {
|
|
dismiss(.cancel)
|
|
}
|
|
Button("Try Again") {
|
|
isPresentingScanFailedAlert = false
|
|
}
|
|
} message: {
|
|
if let error = scanError {
|
|
Text(error.localizedDescription)
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
extension AddQRView {
|
|
enum ScanError: LocalizedError {
|
|
case scanner(CodeScannerView.ScanError)
|
|
case invalidCode(String)
|
|
|
|
var errorDescription: String? {
|
|
switch self {
|
|
case .invalidCode(let code):
|
|
return "Invalid Code: '\(code)'"
|
|
case .scanner(.badInput):
|
|
return "Scanner: Bad Input"
|
|
case .scanner(.badOutput):
|
|
return "Scanner: Bad Output"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
struct AddQRView_Previews: PreviewProvider {
|
|
static var previews: some View {
|
|
AddQRView() { (_) in }
|
|
}
|
|
}
|