Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: onBlur callback on CardField #894

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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