OTP/OTP/Views/KeyView.swift

99 lines
3.1 KiB
Swift

//
// KeyView.swift
// OTP
//
// Created by Shadowfacts on 8/21/21.
//
import SwiftUI
import OTPKit
struct KeyView: View {
let key: TOTPKey
let currentCode: TOTPCode
@State private var copying = false
private var formattedCode: String {
let code = currentCode.code
let mid = code.index(code.startIndex, offsetBy: code.count / 2)
return "\(code[code.startIndex..<mid]) \(code[mid...])"
}
init(key: TOTPKey, currentCode: TOTPCode) {
self.key = key
self.currentCode = currentCode
}
var body: some View {
Button(action: self.copy) {
HStack {
VStack(alignment: .leading) {
Text(key.issuer)
.font(.title3)
if let label = key.label, !label.isEmpty {
Text(label)
.font(.footnote)
}
}
Spacer()
if copying {
Text("Copied!")
.font(.title2)
.transition(.move(edge: .trailing).combined(with: .opacity))
} else {
Text(formattedCode)
.font(.system(.title2, design: .monospaced))
.transition(.asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading)).combined(with: .opacity))
}
// Text("\(currentCode.validUntil, style: .relative)")
// .font(.body.monospacedDigit())
// I don't think this TimelineView should be necessary since the CodeHolder timer fires every .5 seconds
TimelineView(.animation) { (ctx) in
ZStack {
CircularProgressView(progress: progress(at: Date()), colorChangeThreshold: 5.0 / Double(key.period))
Text(Int(round(currentCode.validUntil.timeIntervalSinceNow)).description)
.font(.caption.monospacedDigit())
}
.frame(width: 30)
}
}
}
.tint(Color(UIColor.label))
}
private func progress(at date: Date) -> Double {
let seconds = round(date.timeIntervalSince(currentCode.validFrom))
let progress = 1 - seconds / Double(key.period)
return progress
}
private func copy() {
UIPasteboard.general.string = currentCode.code
withAnimation(.easeInOut(duration: 0.5)) {
copying = true
}
withAnimation(.easeInOut(duration: 0.5).delay(0.65)) {
copying = false
}
}
}
struct KeyView_Previews: PreviewProvider {
static var key: TOTPKey {
TOTPKey(urlComponents: URLComponents(string: "otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example")!)!
}
static var code: TOTPCode {
OTPGenerator.generate(key: key)
}
static var previews: some View {
KeyView(key: key, currentCode: code)
}
}