Implement bank transfer app flows
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
import SwiftUI
|
||||
|
||||
struct OtpPreviewView: View {
|
||||
let seed: String
|
||||
|
||||
@State private var code = ""
|
||||
@State private var progress = 0.0 // 0.0 – 1.0 within the current 30s window
|
||||
@State private var timer: Timer?
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: 12) {
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text("Current OTP")
|
||||
.font(.caption2)
|
||||
.foregroundStyle(.secondary)
|
||||
Text(formatted(code))
|
||||
.font(.system(size: 22, weight: .semibold, design: .monospaced))
|
||||
.foregroundStyle(.primary)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
ZStack {
|
||||
Circle()
|
||||
.stroke(Color(.systemFill), lineWidth: 3)
|
||||
Circle()
|
||||
.trim(from: 0, to: progress)
|
||||
.stroke(progressColor, style: StrokeStyle(lineWidth: 3, lineCap: .round))
|
||||
.rotationEffect(.degrees(-90))
|
||||
.animation(.linear(duration: 0.8), value: progress)
|
||||
Text("\(Int(progress * 30))")
|
||||
.font(.caption2.monospacedDigit())
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
.frame(width: 36, height: 36)
|
||||
}
|
||||
.padding(.horizontal, 16)
|
||||
.padding(.vertical, 10)
|
||||
.background(.regularMaterial, in: RoundedRectangle(cornerRadius: 12))
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture { UIPasteboard.general.string = code }
|
||||
.onAppear { refresh(); startTimer() }
|
||||
.onDisappear { timer?.invalidate(); timer = nil }
|
||||
}
|
||||
|
||||
private var progressColor: Color {
|
||||
progress < 0.33 ? .red : progress < 0.6 ? .orange : .green
|
||||
}
|
||||
|
||||
private func formatted(_ otp: String) -> String {
|
||||
guard otp.count == 6 else { return otp }
|
||||
return "\(otp.prefix(3)) \(otp.suffix(3))"
|
||||
}
|
||||
|
||||
private func refresh() {
|
||||
code = (try? Totp.generate(seed)) ?? Totp.generate(seed)
|
||||
let seconds = Int(Date().timeIntervalSince1970) % 30
|
||||
progress = Double(30 - seconds) / 30.0
|
||||
}
|
||||
|
||||
private func startTimer() {
|
||||
timer?.invalidate()
|
||||
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in refresh() }
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
OtpPreviewView(seed: "JBSWY3DPEHPK3PXP")
|
||||
.padding()
|
||||
}
|
||||
Reference in New Issue
Block a user