Skip to content

Commit

Permalink
fix: onBlur callback on CardField (#894)
Browse files Browse the repository at this point in the history
  • Loading branch information
charliecruzan-stripe authored Apr 18, 2022
1 parent e27d3f0 commit f11f8dc
Show file tree
Hide file tree
Showing 9 changed files with 53 additions and 70 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# CHANGELOG

- [#894](https://github.com/stripe/stripe-react-native/pull/894) Fix: `<CardField />` `onBlur` callback will now be called appropriately on Android
- [#846](https://github.com/stripe/stripe-react-native/pull/846) Fix: Avoid crashes when `currentActivity` is null
- [#879](https://github.com/stripe/stripe-react-native/pull/879) Feat: Add support for ACHv2 payments on Android (already existed on iOS).
- [#879](https://github.com/stripe/stripe-react-native/pull/879) Chore: Upgraded `stripe-android` from v19.3.+ to v20.0.+
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,11 @@ class AuBECSDebitFormViewManager : SimpleViewManager<AuBECSDebitFormView>() {
}

@ReactProp(name = "companyName")
@SuppressWarnings("unused")
fun setCompanyName(view: AuBECSDebitFormView, name: String?) {
view.setCompanyName(name)
}

@ReactProp(name = "formStyle")
@SuppressWarnings("unused")
fun setFormStyle(view: AuBECSDebitFormView, style: ReadableMap) {
view.setFormStyle(style)
}
Expand Down
82 changes: 48 additions & 34 deletions android/src/main/java/com/reactnativestripesdk/CardFieldView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,18 @@ import com.stripe.android.view.CardValidCallback

class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
private var mCardWidget: CardInputWidget = CardInputWidget(context)
private val cardInputWidgetBinding = CardInputWidgetBinding.bind(mCardWidget)
val cardDetails: MutableMap<String, Any?> = mutableMapOf("brand" to "", "last4" to "", "expiryMonth" to null, "expiryYear" to null, "postalCode" to "", "validNumber" to "Unknown", "validCVC" to "Unknown", "validExpiryDate" to "Unknown")
var cardParams: PaymentMethodCreateParams.Card? = null
var cardAddress: Address? = null
private var mEventDispatcher: EventDispatcher? = context.getNativeModule(UIManagerModule::class.java)?.eventDispatcher
private var dangerouslyGetFullCardDetails: Boolean = false
private var currentFocusedField: String? = null

init {

val binding = CardInputWidgetBinding.bind(mCardWidget)
binding.container.isFocusable = true
binding.container.isFocusableInTouchMode = true
binding.container.requestFocus()
cardInputWidgetBinding.container.isFocusable = true
cardInputWidgetBinding.container.isFocusableInTouchMode = true
cardInputWidgetBinding.container.requestFocus()

addView(mCardWidget)
setListeners()
Expand All @@ -44,37 +44,37 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {

fun setAutofocus(value: Boolean) {
if (value) {
val binding = CardInputWidgetBinding.bind(mCardWidget)
binding.cardNumberEditText.requestFocus()
binding.cardNumberEditText.showSoftKeyboard()
cardInputWidgetBinding.cardNumberEditText.requestFocus()
cardInputWidgetBinding.cardNumberEditText.showSoftKeyboard()
}
}

fun requestFocusFromJS() {
val binding = CardInputWidgetBinding.bind(mCardWidget)
binding.cardNumberEditText.requestFocus()
binding.cardNumberEditText.showSoftKeyboard()
cardInputWidgetBinding.cardNumberEditText.requestFocus()
cardInputWidgetBinding.cardNumberEditText.showSoftKeyboard()
}

fun requestBlurFromJS() {
val binding = CardInputWidgetBinding.bind(mCardWidget)
binding.cardNumberEditText.hideSoftKeyboard()
binding.cardNumberEditText.clearFocus()
binding.container.requestFocus()
cardInputWidgetBinding.cardNumberEditText.hideSoftKeyboard()
cardInputWidgetBinding.cardNumberEditText.clearFocus()
cardInputWidgetBinding.container.requestFocus()
}

fun requestClearFromJS() {
val binding = CardInputWidgetBinding.bind(mCardWidget)
binding.cardNumberEditText.setText("")
binding.cvcEditText.setText("")
binding.expiryDateEditText.setText("")
cardInputWidgetBinding.cardNumberEditText.setText("")
cardInputWidgetBinding.cvcEditText.setText("")
cardInputWidgetBinding.expiryDateEditText.setText("")
if (mCardWidget.postalCodeEnabled) {
binding.postalCodeEditText.setText("")
cardInputWidgetBinding.postalCodeEditText.setText("")
}
}

private fun onChangeFocus() {
mEventDispatcher?.dispatchEvent(
CardFocusEvent(id, currentFocusedField))
}

fun setCardStyle(value: ReadableMap) {
val binding = CardInputWidgetBinding.bind(mCardWidget)
val borderWidth = getIntOrNull(value, "borderWidth")
val backgroundColor = getValOr(value, "backgroundColor", null)
val borderColor = getValOr(value, "borderColor", null)
Expand All @@ -85,7 +85,11 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
val placeholderColor = getValOr(value, "placeholderColor", null)
val textErrorColor = getValOr(value, "textErrorColor", null)
val cursorColor = getValOr(value, "cursorColor", null)
val bindings = setOf(binding.cardNumberEditText, binding.cvcEditText, binding.expiryDateEditText, binding.postalCodeEditText)
val bindings = setOf(
cardInputWidgetBinding.cardNumberEditText,
cardInputWidgetBinding.cvcEditText,
cardInputWidgetBinding.expiryDateEditText,
cardInputWidgetBinding.postalCodeEditText)

textColor?.let {
for (editTextBinding in bindings) {
Expand Down Expand Up @@ -148,23 +152,22 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
}

fun setPlaceHolders(value: ReadableMap) {
val binding = CardInputWidgetBinding.bind(mCardWidget)
val numberPlaceholder = getValOr(value, "number", null)
val expirationPlaceholder = getValOr(value, "expiration", null)
val cvcPlaceholder = getValOr(value, "cvc", null)
val postalCodePlaceholder = getValOr(value, "postalCode", null)

numberPlaceholder?.let {
binding.cardNumberEditText.hint = it
cardInputWidgetBinding.cardNumberEditText.hint = it
}
expirationPlaceholder?.let {
binding.expiryDateEditText.hint = it
cardInputWidgetBinding.expiryDateEditText.hint = it
}
cvcPlaceholder?.let {
mCardWidget.setCvcLabel(it)
}
postalCodePlaceholder?.let {
binding.postalCodeEditText.hint = it
cardInputWidgetBinding.postalCodeEditText.hint = it
}
}

Expand All @@ -180,7 +183,7 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
return cardDetails
}

fun onValidCardChange() {
private fun onValidCardChange() {
mCardWidget.paymentMethodCard?.let {
cardParams = it
cardAddress = Address.Builder()
Expand All @@ -207,6 +210,23 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
}

private fun setListeners() {
cardInputWidgetBinding.cardNumberEditText.setOnFocusChangeListener { _, hasFocus ->
currentFocusedField = if (hasFocus) CardInputListener.FocusField.CardNumber.name else null
onChangeFocus()
}
cardInputWidgetBinding.expiryDateEditText.setOnFocusChangeListener { _, hasFocus ->
currentFocusedField = if (hasFocus) CardInputListener.FocusField.ExpiryDate.name else null
onChangeFocus()
}
cardInputWidgetBinding.cvcEditText.setOnFocusChangeListener { _, hasFocus ->
currentFocusedField = if (hasFocus) CardInputListener.FocusField.Cvc.name else null
onChangeFocus()
}
cardInputWidgetBinding.postalCodeEditText.setOnFocusChangeListener { _, hasFocus ->
currentFocusedField = if (hasFocus) CardInputListener.FocusField.PostalCode.name else null
onChangeFocus()
}

mCardWidget.setCardValidCallback { isValid, invalidFields ->
cardDetails["validNumber"] = if (invalidFields.contains(CardValidCallback.Fields.Number)) "Invalid" else "Valid"
cardDetails["validCVC"] = if (invalidFields.contains(CardValidCallback.Fields.Cvc)) "Invalid" else "Valid"
Expand All @@ -224,13 +244,7 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
override fun onExpirationComplete() {}
override fun onCvcComplete() {}
override fun onPostalCodeComplete() {}

override fun onFocusChange(focusField: CardInputListener.FocusField) {
if (mEventDispatcher != null) {
mEventDispatcher?.dispatchEvent(
CardFocusEvent(id, focusField.name))
}
}
override fun onFocusChange(focusField: CardInputListener.FocusField) {}
})

mCardWidget.setExpiryDateTextWatcher(object : TextWatcher {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,31 +27,26 @@ class CardFieldViewManager : SimpleViewManager<CardFieldView>() {
}

@ReactProp(name = "dangerouslyGetFullCardDetails")
@SuppressWarnings("unused")
fun setDangerouslyGetFullCardDetails(view: CardFieldView, dangerouslyGetFullCardDetails: Boolean = false) {
view.setDangerouslyGetFullCardDetails(dangerouslyGetFullCardDetails)
}

@ReactProp(name = "postalCodeEnabled")
@SuppressWarnings("unused")
fun setPostalCodeEnabled(view: CardFieldView, postalCodeEnabled: Boolean = true) {
view.setPostalCodeEnabled(postalCodeEnabled)
}

@ReactProp(name = "autofocus")
@SuppressWarnings("unused")
fun setAutofocus(view: CardFieldView, autofocus: Boolean = false) {
view.setAutofocus(autofocus)
}

@ReactProp(name = "cardStyle")
@SuppressWarnings("unused")
fun setCardStyle(view: CardFieldView, cardStyle: ReadableMap) {
view.setCardStyle(cardStyle)
}

@ReactProp(name = "placeholder")
@SuppressWarnings("unused")
fun setPlaceHolders(view: CardFieldView, placeholder: ReadableMap) {
view.setPlaceHolders(placeholder)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,11 @@ class CardFormViewManager : SimpleViewManager<CardFormView>() {
}

@ReactProp(name = "dangerouslyGetFullCardDetails")
@SuppressWarnings("unused")
fun setDangerouslyGetFullCardDetails(view: CardFormView, dangerouslyGetFullCardDetails: Boolean = false) {
view.setDangerouslyGetFullCardDetails(dangerouslyGetFullCardDetails)
}

@ReactProp(name = "postalCodeEnabled")
@SuppressWarnings("unused")
fun setPostalCodeEnabled(view: CardFormView, postalCodeEnabled: Boolean = false) {
view.setPostalCodeEnabled(postalCodeEnabled)
}
Expand All @@ -44,13 +42,11 @@ class CardFormViewManager : SimpleViewManager<CardFormView>() {
// }

@ReactProp(name = "autofocus")
@SuppressWarnings("unused")
fun setAutofocus(view: CardFormView, autofocus: Boolean = false) {
view.setAutofocus(autofocus)
}

@ReactProp(name = "cardStyle")
@SuppressWarnings("unused")
fun setCardStyle(view: CardFormView, cardStyle: ReadableMap) {
view.setCardStyle(cardStyle)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ class GooglePayButtonManager : SimpleViewManager<GooglePayButtonView?>() {
}

@ReactProp(name = "buttonType")
@SuppressWarnings("unused")
fun buttonType(view: GooglePayButtonView, buttonType: String) {
view.setType(buttonType)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ class PaymentLauncherFragment(
private val publishableKey: String,
private val stripeAccountId: String?,
) : Fragment() {
lateinit var paymentLauncher: PaymentLauncher

var clientSecret: String? = null
var promise: Promise? = null
var isPaymentIntent: Boolean = true
private lateinit var paymentLauncher: PaymentLauncher
private var clientSecret: String? = null
private var promise: Promise? = null
private var isPaymentIntent: Boolean = true

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ class StripeContainerManager : ViewGroupManager<StripeContainerView>() {
override fun getName() = "StripeContainer"

@ReactProp(name = "keyboardShouldPersistTaps")
@SuppressWarnings("unused")
fun setKeyboardShouldPersistTaps(view: StripeContainerView, keyboardShouldPersistTaps: Boolean) {
view.setKeyboardShouldPersistTaps(keyboardShouldPersistTaps)
}
Expand Down
Loading

0 comments on commit f11f8dc

Please sign in to comment.