Skip to content

Commit a1f4af7

Browse files
feat: one tap copy of TOTP secret
1 parent 9f22e55 commit a1f4af7

File tree

1 file changed

+44
-6
lines changed

1 file changed

+44
-6
lines changed

FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/MFAEnrolmentView.swift

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public struct MFAEnrolmentView {
3333
@State private var isLoading = false
3434
@State private var errorMessage = ""
3535
@State private var displayName = ""
36+
@State private var showCopiedFeedback = false
3637

3738
@FocusState private var focus: FocusableField?
3839

@@ -169,6 +170,20 @@ public struct MFAEnrolmentView {
169170
resetForm()
170171
authService.authView = .authPicker
171172
}
173+
174+
private func copyToClipboard(_ text: String) {
175+
UIPasteboard.general.string = text
176+
177+
178+
// Show feedback
179+
showCopiedFeedback = true
180+
181+
// Quickly show it has been copied to the clipboard
182+
Task {
183+
try? await Task.sleep(nanoseconds: 500_000_000)
184+
showCopiedFeedback = false
185+
}
186+
}
172187
}
173188

174189
extension MFAEnrolmentView: View {
@@ -502,14 +517,37 @@ extension MFAEnrolmentView: View {
502517
Text("Manual Entry Key:")
503518
.font(.headline)
504519

505-
Text(totpInfo.sharedSecretKey)
506-
.font(.system(.body, design: .monospaced))
507-
.padding()
508-
.background(Color.gray.opacity(0.1))
509-
.cornerRadius(8)
510-
.textSelection(.enabled)
520+
VStack(spacing: 8) {
521+
Button(action: {
522+
copyToClipboard(totpInfo.sharedSecretKey)
523+
}) {
524+
HStack {
525+
Text(totpInfo.sharedSecretKey)
526+
.font(.system(.body, design: .monospaced))
527+
.lineLimit(1)
528+
.minimumScaleFactor(0.5)
529+
530+
Spacer()
531+
532+
Image(systemName: showCopiedFeedback ? "checkmark" : "doc.on.doc")
533+
.foregroundColor(showCopiedFeedback ? .green : .blue)
534+
}
535+
.padding()
536+
.background(Color.gray.opacity(0.1))
537+
.cornerRadius(8)
538+
}
539+
.buttonStyle(.plain)
511540
.accessibilityIdentifier("totp-secret-key")
512541

542+
if showCopiedFeedback {
543+
Text("Copied to clipboard!")
544+
.font(.caption)
545+
.foregroundColor(.green)
546+
.transition(.opacity)
547+
}
548+
}
549+
.animation(.easeInOut(duration: 0.2), value: showCopiedFeedback)
550+
513551
TextField("Display Name (Optional)", text: $displayName)
514552
.textFieldStyle(.roundedBorder)
515553
.accessibilityIdentifier("display-name-field")

0 commit comments

Comments
 (0)