@@ -12,8 +12,10 @@ import com.stripe.android.R
12
12
import com.stripe.android.StripeTextUtils
13
13
import com.stripe.android.cards.CardAccountRangeRepository
14
14
import com.stripe.android.cards.CardNumber
15
+ import com.stripe.android.cards.DefaultStaticCardAccountRanges
15
16
import com.stripe.android.cards.LegacyCardAccountRangeRepository
16
17
import com.stripe.android.cards.StaticCardAccountRangeSource
18
+ import com.stripe.android.cards.StaticCardAccountRanges
17
19
import com.stripe.android.model.CardBrand
18
20
import com.stripe.android.model.CardMetadata
19
21
import kotlinx.coroutines.CoroutineDispatcher
@@ -34,7 +36,8 @@ class CardNumberEditText internal constructor(
34
36
// TODO(mshafrir-stripe): make immutable after `CardWidgetViewModel` is integrated in `CardWidget` subclasses
35
37
internal var workDispatcher : CoroutineDispatcher ,
36
38
37
- private val cardAccountRangeRepository : CardAccountRangeRepository
39
+ private val cardAccountRangeRepository : CardAccountRangeRepository ,
40
+ private val staticCardAccountRanges : StaticCardAccountRanges = DefaultStaticCardAccountRanges ()
38
41
) : StripeEditText(context, attrs, defStyleAttr) {
39
42
40
43
@JvmOverloads
@@ -47,7 +50,8 @@ class CardNumberEditText internal constructor(
47
50
attrs,
48
51
defStyleAttr,
49
52
Dispatchers .IO ,
50
- LegacyCardAccountRangeRepository (StaticCardAccountRangeSource ())
53
+ LegacyCardAccountRangeRepository (StaticCardAccountRangeSource ()),
54
+ DefaultStaticCardAccountRanges ()
51
55
)
52
56
53
57
@VisibleForTesting
@@ -81,7 +85,16 @@ class CardNumberEditText internal constructor(
81
85
return cardBrand.getMaxLengthWithSpacesForCardNumber(fieldText)
82
86
}
83
87
84
- private var panLength = CardNumber .DEFAULT_PAN_LENGTH
88
+ private var accountRange: CardMetadata .AccountRange ? = null
89
+ set(value) {
90
+ field = value
91
+ updateLengthFilter()
92
+ }
93
+
94
+ private val panLength: Int
95
+ get() = accountRange?.panLength
96
+ ? : staticCardAccountRanges.match(unvalidatedCardNumber)?.panLength
97
+ ? : CardNumber .DEFAULT_PAN_LENGTH
85
98
86
99
private val formattedPanLength: Int
87
100
get() = panLength + CardNumber .getSpacePositions(panLength).size
@@ -105,6 +118,9 @@ class CardNumberEditText internal constructor(
105
118
null
106
119
}
107
120
121
+ private val unvalidatedCardNumber: CardNumber .Unvalidated
122
+ get() = CardNumber .Unvalidated (fieldText)
123
+
108
124
@VisibleForTesting
109
125
internal var accountRangeRepositoryJob: Job ? = null
110
126
@@ -190,11 +206,11 @@ class CardNumberEditText internal constructor(
190
206
private var newCursorPosition: Int? = null
191
207
private var formattedNumber: String? = null
192
208
193
- private var beforeCardNumber = CardNumber . Unvalidated ( " " )
209
+ private var beforeCardNumber = unvalidatedCardNumber
194
210
195
211
override fun beforeTextChanged (s : CharSequence? , start : Int , count : Int , after : Int ) {
196
212
if (! ignoreChanges) {
197
- beforeCardNumber = CardNumber . Unvalidated (s?.toString().orEmpty())
213
+ beforeCardNumber = unvalidatedCardNumber
198
214
199
215
latestChangeStart = start
200
216
latestInsertionSize = after
@@ -212,7 +228,7 @@ class CardNumberEditText internal constructor(
212
228
).orEmpty()
213
229
214
230
val cardNumber = CardNumber .Unvalidated (spacelessNumber)
215
- updateCardBrand (cardNumber)
231
+ updateAccountRange (cardNumber)
216
232
217
233
val formattedNumber = cardNumber.getFormatted(panLength)
218
234
this .newCursorPosition = updateSelectionIndex(
@@ -242,7 +258,7 @@ class CardNumberEditText internal constructor(
242
258
243
259
ignoreChanges = false
244
260
245
- if (fieldText .length == formattedPanLength ) {
261
+ if (unvalidatedCardNumber .length == panLength ) {
246
262
val wasCardNumberValid = isCardNumberValid
247
263
isCardNumberValid = CardUtils .isValidCardNumber(fieldText)
248
264
shouldShowError = ! isCardNumberValid
@@ -263,15 +279,17 @@ class CardNumberEditText internal constructor(
263
279
* Have digits been added in this text change.
264
280
*/
265
281
private val digitsAdded: Boolean
266
- get() = CardNumber . Unvalidated (fieldText) .length > beforeCardNumber.length
282
+ get() = unvalidatedCardNumber .length > beforeCardNumber.length
267
283
})
268
284
}
269
285
270
286
@JvmSynthetic
271
- internal fun updateCardBrand (cardNumber : CardNumber .Unvalidated ) {
287
+ internal fun updateAccountRange (cardNumber : CardNumber .Unvalidated ) {
272
288
// cancel in-flight job
273
289
cancelAccountRangeRepositoryJob()
274
290
291
+ accountRange = null
292
+
275
293
accountRangeRepositoryJob = CoroutineScope (workDispatcher).launch {
276
294
val bin = cardNumber.bin
277
295
if (bin != null ) {
@@ -292,10 +310,10 @@ class CardNumberEditText internal constructor(
292
310
293
311
@JvmSynthetic
294
312
internal suspend fun onAccountRangeResult (
295
- accountRange : CardMetadata .AccountRange ?
313
+ newAccountRange : CardMetadata .AccountRange ?
296
314
) = withContext(Dispatchers .Main ) {
297
- panLength = accountRange?.panLength ? : CardNumber . DEFAULT_PAN_LENGTH
298
- cardBrand = accountRange ?.brand ? : CardBrand .Unknown
315
+ accountRange = newAccountRange
316
+ cardBrand = newAccountRange ?.brand ? : CardBrand .Unknown
299
317
isProcessingCallback(false )
300
318
}
301
319
}
0 commit comments