Skip to content

Commit 0f9e403

Browse files
committed
fix: verification code input field
1 parent 6cb5b19 commit 0f9e403

File tree

2 files changed

+57
-13
lines changed

2 files changed

+57
-13
lines changed

samples/auth-swiftui/AuthSwiftUIExample/Views/FirebaseAuthViewInternal.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ struct FirebaseAuthViewInternal: View {
218218
phoneNumber: $phoneNumber,
219219
selectedCountry: $selectedCountry,
220220
verificationCode: $verificationCode,
221-
fullPhoneNumber: "\(selectedCountry.dialCode) \(phoneNumber)",
221+
fullPhoneNumber: "\(selectedCountry.dialCode)\(phoneNumber)",
222222
resendTimer: resendTimer,
223223
onSendCodeClick: handleSendCode,
224224
onVerifyCodeClick: handleVerifyCode,

samples/auth-swiftui/AuthSwiftUIExample/Views/Phone/VerificationCodeInputField.swift

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ struct VerificationCodeInputField: View {
3535

3636
@State private var digitFields: [String] = []
3737
@State private var focusedIndex: Int? = nil
38+
@State private var pendingInternalCodeUpdates = 0
3839

3940
var body: some View {
4041
VStack(spacing: 8) {
@@ -45,6 +46,8 @@ struct VerificationCodeInputField: View {
4546
isError: isError,
4647
isFocused: focusedIndex == index,
4748
maxDigits: codeLength - index,
49+
position: index + 1,
50+
totalDigits: codeLength,
4851
onDigitChanged: { newDigit in
4952
handleDigitChanged(at: index, newDigit: newDigit)
5053
},
@@ -75,21 +78,56 @@ struct VerificationCodeInputField: View {
7578
}
7679
.onAppear {
7780
// Initialize digit fields from the code binding
78-
updateDigitFieldsFromCode()
81+
updateDigitFieldsFromCode(shouldUpdateFocus: true, forceFocus: true)
82+
}
83+
.onChange(of: code) { _ in
84+
if pendingInternalCodeUpdates > 0 {
85+
pendingInternalCodeUpdates -= 1
86+
return
87+
}
88+
updateDigitFieldsFromCode(shouldUpdateFocus: true)
7989
}
8090
}
8191

82-
private func updateDigitFieldsFromCode() {
83-
let codeArray = Array(code)
84-
for i in 0..<codeLength {
85-
if i < codeArray.count {
86-
digitFields[i] = String(codeArray[i])
87-
} else {
88-
digitFields[i] = ""
92+
private func updateDigitFieldsFromCode(shouldUpdateFocus: Bool, forceFocus: Bool = false) {
93+
let sanitized = code.filter { $0.isNumber }
94+
let truncated = String(sanitized.prefix(codeLength))
95+
var newFields = Array(repeating: "", count: codeLength)
96+
97+
for (offset, character) in truncated.enumerated() {
98+
newFields[offset] = String(character)
99+
}
100+
101+
let fieldsChanged = newFields != digitFields
102+
if fieldsChanged {
103+
digitFields = newFields
104+
}
105+
106+
if code != truncated {
107+
commitCodeChange(truncated)
108+
}
109+
110+
if shouldUpdateFocus && (fieldsChanged || forceFocus) {
111+
let newFocus = truncated.count < codeLength ? truncated.count : nil
112+
DispatchQueue.main.async {
113+
focusedIndex = newFocus
114+
}
115+
}
116+
117+
if fieldsChanged && truncated.count == codeLength {
118+
DispatchQueue.main.async {
119+
onCodeComplete(truncated)
89120
}
90121
}
91122
}
92-
123+
124+
private func commitCodeChange(_ newCode: String) {
125+
if code != newCode {
126+
pendingInternalCodeUpdates += 1
127+
code = newCode
128+
}
129+
}
130+
93131
private func handleDigitChanged(at index: Int, newDigit: String) {
94132
let sanitized = newDigit.filter { $0.isNumber }
95133

@@ -117,7 +155,7 @@ struct VerificationCodeInputField: View {
117155
}
118156

119157
let newCode = digitFields.joined()
120-
code = newCode
158+
commitCodeChange(newCode)
121159
onCodeChange(newCode)
122160

123161
if !digit.isEmpty,
@@ -154,7 +192,7 @@ struct VerificationCodeInputField: View {
154192

155193
// Update the main code string
156194
let newCode = digitFields.joined()
157-
code = newCode
195+
commitCodeChange(newCode)
158196
onCodeChange(newCode)
159197
}
160198

@@ -174,7 +212,7 @@ struct VerificationCodeInputField: View {
174212
}
175213

176214
let newCode = updatedFields.joined()
177-
code = newCode
215+
commitCodeChange(newCode)
178216
onCodeChange(newCode)
179217

180218
if newCode.count == codeLength {
@@ -215,6 +253,8 @@ private struct SingleDigitField: View {
215253
let isError: Bool
216254
let isFocused: Bool
217255
let maxDigits: Int
256+
let position: Int
257+
let totalDigits: Int
218258
let onDigitChanged: (String) -> Void
219259
let onBackspace: () -> Void
220260
let onFocusChanged: (Bool) -> Void
@@ -268,6 +308,10 @@ private struct SingleDigitField: View {
268308
)
269309
)
270310
.frame(maxWidth: .infinity)
311+
.accessibilityElement(children: .ignore)
312+
.accessibilityLabel("Digit \(position) of \(totalDigits)")
313+
.accessibilityValue(digit.isEmpty ? "Empty" : digit)
314+
.accessibilityHint("Enter verification code digit")
271315
}
272316
}
273317

0 commit comments

Comments
 (0)