Skip to content

Commit 3c4f608

Browse files
committed
React Native Sync Android #1
1 parent 0751190 commit 3c4f608

15 files changed

+121
-73
lines changed

packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/CardFieldView.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,9 @@ import com.stripe.android.view.CardInputListener
2828
import com.stripe.android.view.CardInputWidget
2929
import com.stripe.android.view.CardValidCallback
3030
import com.stripe.android.view.StripeEditText
31-
import java.lang.Exception
3231

3332
class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
34-
internal var mCardWidget: CardInputWidget = CardInputWidget(context)
33+
private var mCardWidget: CardInputWidget = CardInputWidget(context)
3534
private val cardInputWidgetBinding = CardInputWidgetBinding.bind(mCardWidget)
3635
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")
3736
var cardParams: PaymentMethodCreateParams.Card? = null

packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/CardFieldViewManager.kt

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import com.facebook.react.common.MapBuilder
66
import com.facebook.react.uimanager.SimpleViewManager
77
import com.facebook.react.uimanager.ThemedReactContext
88
import com.facebook.react.uimanager.annotations.ReactProp
9-
import com.stripe.android.model.PaymentMethodCreateParams
109

1110
class CardFieldViewManager : SimpleViewManager<CardFieldView>() {
1211
override fun getName() = "CardField"
@@ -74,24 +73,4 @@ class CardFieldViewManager : SimpleViewManager<CardFieldView>() {
7473
stripeSdkModule?.cardFieldView = null
7574
reactContextRef = null
7675
}
77-
78-
fun getCardViewInstance(): CardFieldView? {
79-
val stripeSdkModule: StripeSdkModule? = reactContextRef?.getNativeModule(StripeSdkModule::class.java)
80-
return stripeSdkModule?.cardFieldView
81-
}
82-
83-
fun setCardDetails(value: ReadableMap, reactContext: ThemedReactContext) {
84-
val number = getValOr(value, "number", null)
85-
val expirationYear = getIntOrNull(value, "expirationYear")
86-
val expirationMonth = getIntOrNull(value, "expirationMonth")
87-
val cvc = getValOr(value, "cvc", null)
88-
89-
val cardViewInstance = getCardViewInstance() ?: createViewInstance(reactContext)
90-
cardViewInstance.cardParams = PaymentMethodCreateParams.Card.Builder()
91-
.setNumber(number)
92-
.setCvc(cvc)
93-
.setExpiryMonth(expirationMonth)
94-
.setExpiryYear(expirationYear)
95-
.build()
96-
}
9776
}

packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/CardFormView.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,9 @@ import com.stripe.android.model.Address
2424
import com.stripe.android.model.PaymentMethodCreateParams
2525
import com.stripe.android.view.CardFormView
2626
import com.stripe.android.view.CardInputListener
27-
import com.flutter.stripe.R
28-
2927

3028
class CardFormView(context: ThemedReactContext) : FrameLayout(context) {
31-
internal var cardForm: CardFormView = CardFormView(context, null, R.style.StripeCardFormView_Borderless)
29+
private var cardForm: CardFormView = CardFormView(context, null, R.style.StripeCardFormView_Borderless)
3230
private var mEventDispatcher: EventDispatcher? = context.getNativeModule(UIManagerModule::class.java)?.eventDispatcher
3331
private var dangerouslyGetFullCardDetails: Boolean = false
3432
private var currentFocusedField: String? = null

packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/CardFormViewManager.kt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,4 @@ class CardFormViewManager : SimpleViewManager<CardFormView>() {
7373
stripeSdkModule?.cardFormView = null
7474
reactContextRef = null
7575
}
76-
77-
fun getCardViewInstance(): CardFormView? {
78-
val stripeSdkModule: StripeSdkModule? = reactContextRef?.getNativeModule(StripeSdkModule::class.java)
79-
return stripeSdkModule?.cardFormView
80-
}
8176
}

packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/FinancialConnectionsSheetFragment.kt

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import android.view.ViewGroup
77
import android.widget.FrameLayout
88
import androidx.appcompat.app.AppCompatActivity
99
import androidx.fragment.app.Fragment
10-
import androidx.fragment.app.FragmentActivity
1110
import com.facebook.react.bridge.*
1211
import com.reactnativestripesdk.utils.*
1312
import com.reactnativestripesdk.utils.createError
@@ -70,7 +69,7 @@ class FinancialConnectionsSheetFragment : Fragment() {
7069
}
7170
is FinancialConnectionsSheetForTokenResult.Completed -> {
7271
promise.resolve(createTokenResult(result))
73-
context.currentActivity?.supportFragmentManager?.beginTransaction()?.remove(this)?.commitAllowingStateLoss()
72+
(context.currentActivity as? AppCompatActivity)?.supportFragmentManager?.beginTransaction()?.remove(this)?.commitAllowingStateLoss()
7473
}
7574
}
7675
}
@@ -93,7 +92,7 @@ class FinancialConnectionsSheetFragment : Fragment() {
9392
it.putMap("session", mapFromSession(result.financialConnectionsSession))
9493
}
9594
)
96-
context.currentActivity.supportFragmentManager?.beginTransaction()?.remove(this)?.commitAllowingStateLoss()
95+
(context.currentActivity as? AppCompatActivity)?.supportFragmentManager?.beginTransaction()?.remove(this)?.commitAllowingStateLoss()
9796
}
9897
}
9998
}
@@ -108,7 +107,7 @@ class FinancialConnectionsSheetFragment : Fragment() {
108107
stripeAccountId = stripeAccountId,
109108
)
110109

111-
context.currentActivity?.let {
110+
(context.currentActivity as? AppCompatActivity)?.let {
112111
attemptToCleanupPreviousFragment(it)
113112
commitFragmentAndStartFlow(it)
114113
} ?: run {
@@ -117,13 +116,13 @@ class FinancialConnectionsSheetFragment : Fragment() {
117116
}
118117
}
119118

120-
private fun attemptToCleanupPreviousFragment(currentActivity: FragmentActivity) {
119+
private fun attemptToCleanupPreviousFragment(currentActivity: AppCompatActivity) {
121120
currentActivity.supportFragmentManager.beginTransaction()
122121
.remove(this)
123122
.commitAllowingStateLoss()
124123
}
125124

126-
private fun commitFragmentAndStartFlow(currentActivity: FragmentActivity) {
125+
private fun commitFragmentAndStartFlow(currentActivity: AppCompatActivity) {
127126
try {
128127
currentActivity.supportFragmentManager.beginTransaction()
129128
.add(this, "financial_connections_sheet_launch_fragment")
Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,18 @@
11
package com.reactnativestripesdk
22

3-
import android.content.res.Configuration
43
import android.view.LayoutInflater
54
import android.widget.FrameLayout
65
import com.facebook.react.uimanager.ThemedReactContext
7-
import com.flutter.stripe.R
86

97
class GooglePayButtonView(private val context: ThemedReactContext) : FrameLayout(context) {
108
private var buttonType: String? = null
119

1210
fun initialize() {
1311
val type =
1412
when (buttonType) {
15-
"pay" -> R.layout.pay_with_googlepay_button_no_shadow
16-
"pay_dark" -> R.layout.pay_with_googlepay_button_dark
17-
"pay_shadow" -> R.layout.pay_with_googlepay_button
18-
"standard" -> R.layout.googlepay_button_no_shadow
19-
"standard_dark" -> R.layout.googlepay_button_dark
20-
"standard_shadow" -> R.layout.googlepay_button
21-
else -> if (isNightMode()) R.layout.googlepay_button_dark else R.layout.googlepay_button
13+
"pay" -> R.layout.pay_with_googlepay_button
14+
"standard" -> R.layout.googlepay_button
15+
else -> R.layout.googlepay_button
2216
}
2317

2418
val button = LayoutInflater.from(context).inflate(
@@ -31,9 +25,4 @@ class GooglePayButtonView(private val context: ThemedReactContext) : FrameLayout
3125
fun setType(type: String) {
3226
buttonType = type
3327
}
34-
35-
private fun isNightMode(): Boolean {
36-
val nightModeFlags: Int = context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
37-
return nightModeFlags == Configuration.UI_MODE_NIGHT_YES
38-
}
3928
}

packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/PaymentLauncherFragment.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ class PaymentLauncherFragment(
107107
}
108108

109109
private fun addFragment(fragment: PaymentLauncherFragment, context: ReactApplicationContext, promise: Promise) {
110-
context.currentActivity?.let {
110+
(context.currentActivity as? AppCompatActivity)?.let {
111111
try {
112112
it.supportFragmentManager.beginTransaction()
113113
.add(fragment, TAG)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.reactnativestripesdk
2+
3+
import com.facebook.react.uimanager.ThemedReactContext
4+
import com.facebook.react.uimanager.ViewGroupManager
5+
import com.facebook.react.uimanager.annotations.ReactProp
6+
7+
class StripeContainerManager : ViewGroupManager<StripeContainerView>() {
8+
override fun getName() = "StripeContainer"
9+
10+
@ReactProp(name = "keyboardShouldPersistTaps")
11+
fun setKeyboardShouldPersistTaps(view: StripeContainerView, keyboardShouldPersistTaps: Boolean) {
12+
view.setKeyboardShouldPersistTaps(keyboardShouldPersistTaps)
13+
}
14+
15+
override fun createViewInstance(reactContext: ThemedReactContext): StripeContainerView {
16+
return StripeContainerView(reactContext)
17+
}
18+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.reactnativestripesdk
2+
3+
import android.content.Context
4+
import android.graphics.Rect
5+
import android.view.MotionEvent
6+
import android.view.inputmethod.InputMethodManager
7+
import android.widget.EditText
8+
import android.widget.FrameLayout
9+
import com.facebook.react.uimanager.ThemedReactContext
10+
11+
class StripeContainerView(private val context: ThemedReactContext) : FrameLayout(context) {
12+
private var keyboardShouldPersistTapsValue: Boolean = true
13+
14+
init {
15+
rootView.isFocusable = true
16+
rootView.isFocusableInTouchMode = true
17+
rootView.isClickable = true
18+
}
19+
20+
fun setKeyboardShouldPersistTaps(value: Boolean) {
21+
keyboardShouldPersistTapsValue = value
22+
}
23+
24+
override fun dispatchTouchEvent(event: MotionEvent?): Boolean {
25+
if (event!!.action == MotionEvent.ACTION_DOWN && !keyboardShouldPersistTapsValue) {
26+
val v = context.currentActivity!!.currentFocus
27+
if (v is EditText) {
28+
val outRect = Rect()
29+
v.getGlobalVisibleRect(outRect)
30+
if (!outRect.contains(event.rawX.toInt(), event.rawY.toInt())) {
31+
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
32+
imm.hideSoftInputFromWindow(v.windowToken, 0)
33+
rootView.requestFocus()
34+
}
35+
}
36+
}
37+
return super.dispatchTouchEvent(event)
38+
}
39+
}

packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/StripeSdkModule.kt

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import androidx.appcompat.app.AppCompatActivity
88
import androidx.fragment.app.Fragment
99
import com.facebook.react.bridge.*
1010
import com.facebook.react.module.annotations.ReactModule
11-
import com.flutter.stripe.getCurrentActivityOrResolveWithError
12-
import com.flutter.stripe.invoke
1311
import com.reactnativestripesdk.pushprovisioning.PushProvisioningProxy
1412
import com.reactnativestripesdk.utils.*
1513
import com.reactnativestripesdk.utils.createError
@@ -26,7 +24,7 @@ import kotlinx.coroutines.launch
2624

2725

2826
@ReactModule(name = StripeSdkModule.NAME)
29-
class StripeSdkModule(internal val reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
27+
class StripeSdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
3028
override fun getName(): String {
3129
return "StripeSdk"
3230
}
@@ -39,21 +37,22 @@ class StripeSdkModule(internal val reactContext: ReactApplicationContext) : Reac
3937
private var stripeAccountId: String? = null
4038
private var urlScheme: String? = null
4139

40+
private var confirmPromise: Promise? = null
41+
private var confirmPaymentClientSecret: String? = null
42+
4243
private var paymentSheetFragment: PaymentSheetFragment? = null
4344
private var googlePayFragment: GooglePayFragment? = null
4445
private var paymentLauncherFragment: PaymentLauncherFragment? = null
4546
private var collectBankAccountLauncherFragment: CollectBankAccountLauncherFragment? = null
4647
private var financialConnectionsSheetFragment: FinancialConnectionsSheetFragment? = null
47-
private var allFragments : Array<Fragment?> = arrayOf(
48-
paymentSheetFragment,
49-
googlePayFragment,
50-
paymentLauncherFragment,
51-
collectBankAccountLauncherFragment,
52-
financialConnectionsSheetFragment
53-
)
54-
55-
private var confirmPromise: Promise? = null
56-
private var confirmPaymentClientSecret: String? = null
48+
private val allFragments: List<Fragment?>
49+
get() = listOf(
50+
paymentSheetFragment,
51+
googlePayFragment,
52+
paymentLauncherFragment,
53+
collectBankAccountLauncherFragment,
54+
financialConnectionsSheetFragment
55+
)
5756

5857
private val mActivityEventListener = object : BaseActivityEventListener() {
5958
override fun onActivityResult(activity: Activity, requestCode: Int, resultCode: Int, data: Intent?) {
@@ -78,7 +77,7 @@ class StripeSdkModule(internal val reactContext: ReactApplicationContext) : Reac
7877
// Necessary on older versions of React Native (~0.65 and below)
7978
private fun dispatchActivityResultsToFragments(requestCode: Int, resultCode: Int, data: Intent?) {
8079
for (fragment in allFragments) {
81-
//fragment?.activity?.activityResultRegistry?.dispatchResult(requestCode, resultCode, data)
80+
fragment?.activity?.activityResultRegistry?.dispatchResult(requestCode, resultCode, data)
8281
}
8382
}
8483

@@ -728,6 +727,18 @@ class StripeSdkModule(internal val reactContext: ReactApplicationContext) : Reac
728727
}
729728
}
730729

730+
/**
731+
* Safely get and cast the current activity as an AppCompatActivity. If that fails, the promise
732+
* provided will be resolved with an error message instructing the user to retry the method.
733+
*/
734+
private fun getCurrentActivityOrResolveWithError(promise: Promise?): AppCompatActivity? {
735+
(currentActivity as? AppCompatActivity)?.let {
736+
return it
737+
}
738+
promise?.resolve(createMissingActivityError())
739+
return null
740+
}
741+
731742
companion object {
732743
const val NAME = "StripeSdk"
733744
}

0 commit comments

Comments
 (0)