diff --git a/ui/src/main/java/ru/tinkoff/acquiring/sdk/redesign/common/carddatainput/CvcComponent.kt b/ui/src/main/java/ru/tinkoff/acquiring/sdk/redesign/common/carddatainput/CvcComponent.kt index 8cc35467..2fd526b9 100644 --- a/ui/src/main/java/ru/tinkoff/acquiring/sdk/redesign/common/carddatainput/CvcComponent.kt +++ b/ui/src/main/java/ru/tinkoff/acquiring/sdk/redesign/common/carddatainput/CvcComponent.kt @@ -24,7 +24,7 @@ class CvcComponent( private val onInitScreen: (Boolean, View.() -> Unit) -> Unit = { _, function -> } ) : UiComponent { - private val cvcInput: AcqTextFieldView = root.findViewById(R.id.cvc_input) + internal val cvcInput: AcqTextFieldView = root.findViewById(R.id.cvc_input) val cvc get() = cvcInput.text.orEmpty() init { diff --git a/ui/src/main/java/ru/tinkoff/acquiring/sdk/redesign/common/carddatainput/FocusDecoratorCvcComponent.kt b/ui/src/main/java/ru/tinkoff/acquiring/sdk/redesign/common/carddatainput/FocusDecoratorCvcComponent.kt new file mode 100644 index 00000000..0b7b9c12 --- /dev/null +++ b/ui/src/main/java/ru/tinkoff/acquiring/sdk/redesign/common/carddatainput/FocusDecoratorCvcComponent.kt @@ -0,0 +1,49 @@ +package ru.tinkoff.acquiring.sdk.redesign.common.carddatainput + +import android.view.View +import android.view.ViewGroup +import kotlinx.android.synthetic.main.acq_fragment_cvc_input.view.cvc_input +import ru.tinkoff.acquiring.sdk.ui.component.UiComponent + +interface CvcUIComponent : UiComponent { + fun clearCvc() + fun enableCvc(isEnabled: Boolean) +} + +class FocusDecoratorCvcComponent( + private val root: ViewGroup, + private val initingFocusAndKeyboard: Boolean, + private val onFocusCvc: View.() -> Unit, + onInputComplete: (String) -> Unit, + onDataChange: (Boolean, String) -> Unit +) : CvcUIComponent { + + private val cvcComponent: CvcComponent = CvcComponent( + root, + initingFocusAndKeyboard, + onInputComplete, + onDataChange, + onInitScreen = { _, function -> + if(initingFocusAndKeyboard){ + onFocusCvc(root.cvc_input.editText.apply(function)) + } + } + ) + + override fun clearCvc() { + cvcComponent.render(null) + } + + override fun enableCvc(isEnabled: Boolean) = cvcComponent.enable(isEnabled) + + fun enable(isEnable: Boolean) = with(cvcComponent.cvcInput) { + isEnabled = isEnable + editable = isEnable + if (isEnable.not()) { + hideKeyboard() + } + } + + override fun render(state: String?) = cvcComponent.render(state) + +} \ No newline at end of file diff --git a/ui/src/main/java/ru/tinkoff/acquiring/sdk/redesign/common/cardpay/CardPayComponent.kt b/ui/src/main/java/ru/tinkoff/acquiring/sdk/redesign/common/cardpay/CardPayComponent.kt index 6f4caa08..d282f390 100644 --- a/ui/src/main/java/ru/tinkoff/acquiring/sdk/redesign/common/cardpay/CardPayComponent.kt +++ b/ui/src/main/java/ru/tinkoff/acquiring/sdk/redesign/common/cardpay/CardPayComponent.kt @@ -1,12 +1,16 @@ package ru.tinkoff.acquiring.sdk.redesign.common.cardpay +import android.view.View +import android.view.ViewGroup import androidx.core.view.isVisible import ru.tinkoff.acquiring.sdk.R import ru.tinkoff.acquiring.sdk.databinding.AcqCardPayComponentBinding import ru.tinkoff.acquiring.sdk.models.options.screen.PaymentOptions +import ru.tinkoff.acquiring.sdk.redesign.common.carddatainput.FocusDecoratorCvcComponent import ru.tinkoff.acquiring.sdk.redesign.common.emailinput.EmailInputComponent import ru.tinkoff.acquiring.sdk.redesign.payment.model.CardChosenModel import ru.tinkoff.acquiring.sdk.redesign.payment.ui.ChosenCardComponent +import ru.tinkoff.acquiring.sdk.ui.component.UiComponent import ru.tinkoff.acquiring.sdk.ui.customview.LoaderButton import ru.tinkoff.acquiring.sdk.utils.KeyboardVisionUtils @@ -14,23 +18,45 @@ import ru.tinkoff.acquiring.sdk.utils.KeyboardVisionUtils * Created by i.golovachev */ class CardPayComponent( + private val root: ViewGroup, + private val initingFocusAndKeyboard: Boolean = false, private val viewBinding: AcqCardPayComponentBinding, private val email: String?, private val onCvcCompleted: (String) -> Unit = {}, private val onEmailInput: (String) -> Unit = {}, private val onEmailVisibleChange: (Boolean) -> Unit = {}, private val onChooseCardClick: () -> Unit = {}, - private val onPayClick: () -> Unit = {} -) { + private val onPayClick: () -> Unit = {}, + private val onChangeCard: (CardChosenModel) -> Unit = {}, + private val onFocusCvc: View.() -> Unit = { + requestFocus() + isEnabled = true + } +): UiComponent { private val loaderButton: LoaderButton = viewBinding.loaderButton.apply { setOnClickListener { onPayClick() } } + + private val cardCvc: FocusDecoratorCvcComponent = FocusDecoratorCvcComponent( + root.findViewById(R.id.cvc_container), + initingFocusAndKeyboard, + onFocusCvc, + onInputComplete = { s -> + onCvcCompleted(s) + }, + onDataChange = { b, s -> + onCvcCompleted(s) + } + ) + + private val emailInputComponent = EmailInputComponent(viewBinding.emailInput.root, onEmailChange = { onEmailInput(it) }, onEmailVisibleChange = { onEmailVisibleChange(it) } ).apply { render(EmailInputComponent.State(email, email != null)) } + private val savedCardComponent = ChosenCardComponent(viewBinding.chosenCard.root, onCvcCompleted = { cvc, _ -> onCvcCompleted(cvc) }, onChangeCard = { onChooseCardClick() } @@ -83,4 +109,12 @@ class CardPayComponent( else KeyboardVisionUtils.hideKeyboard(viewBinding.root) } + + override fun render(state: CardChosenModel) { + root.setOnClickListener { onChangeCard(state) } + } + + fun clearCvc(){ + cardCvc.render(null) + } } \ No newline at end of file diff --git a/ui/src/main/java/ru/tinkoff/acquiring/sdk/redesign/mainform/ui/MainPaymentFormActivity.kt b/ui/src/main/java/ru/tinkoff/acquiring/sdk/redesign/mainform/ui/MainPaymentFormActivity.kt index 0487de65..e6449588 100644 --- a/ui/src/main/java/ru/tinkoff/acquiring/sdk/redesign/mainform/ui/MainPaymentFormActivity.kt +++ b/ui/src/main/java/ru/tinkoff/acquiring/sdk/redesign/mainform/ui/MainPaymentFormActivity.kt @@ -17,6 +17,8 @@ import androidx.core.widget.NestedScrollView import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle +import kotlinx.android.synthetic.main.acq_card_pay_component.view.chosenCard +import kotlinx.android.synthetic.main.acq_fragment_cvc_input.view.cvc_input import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import ru.tinkoff.acquiring.sdk.R @@ -160,6 +162,7 @@ internal class MainPaymentFormActivity : AppCompatActivity() { private val cardPayComponent by lazyUnsafe { CardPayComponent( + this.root, viewBinding = AcqCardPayComponentBinding.bind( findViewById(R.id.acq_main_card_pay) ), @@ -168,7 +171,7 @@ internal class MainPaymentFormActivity : AppCompatActivity() { onEmailInput = cardInputViewModel::email, onEmailVisibleChange = cardInputViewModel::needEmail, onChooseCardClick = viewModel::toChooseCard, - onPayClick = { cardInputViewModel.pay() } + onPayClick = { cardInputViewModel.pay() }, ) } @@ -202,6 +205,9 @@ internal class MainPaymentFormActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.acq_main_from_activity) + + initCvcClickListener(root, cardPayComponent) + createTitleView() WindowCompat.setDecorFitsSystemWindows(window, false) @@ -260,6 +266,10 @@ internal class MainPaymentFormActivity : AppCompatActivity() { viewModel.onBackPressed() } + private fun initCvcClickListener(root: ViewGroup, card: CardPayComponent){ + root.chosenCard.cvc_input.setupCvcInput(root, card) + } + private suspend fun updateContent() { combine( cardInputViewModel.paymentStatus, viewModel.formContent diff --git a/ui/src/main/java/ru/tinkoff/acquiring/sdk/redesign/payment/ui/ChosenCardComponent.kt b/ui/src/main/java/ru/tinkoff/acquiring/sdk/redesign/payment/ui/ChosenCardComponent.kt index d8dd4d98..3c9b3cf5 100644 --- a/ui/src/main/java/ru/tinkoff/acquiring/sdk/redesign/payment/ui/ChosenCardComponent.kt +++ b/ui/src/main/java/ru/tinkoff/acquiring/sdk/redesign/payment/ui/ChosenCardComponent.kt @@ -5,10 +5,8 @@ import android.view.ViewGroup import android.widget.ImageView import android.widget.TextView import androidx.core.view.isVisible -import kotlinx.android.synthetic.main.acq_fragment_cvc_input.view.cvc_input -import kotlinx.android.synthetic.main.acq_layout_choosen_card.view.cvc_container import ru.tinkoff.acquiring.sdk.R -import ru.tinkoff.acquiring.sdk.redesign.common.carddatainput.CvcComponent +import ru.tinkoff.acquiring.sdk.redesign.common.carddatainput.FocusDecoratorCvcComponent import ru.tinkoff.acquiring.sdk.redesign.payment.model.CardChosenModel import ru.tinkoff.acquiring.sdk.ui.component.UiComponent import ru.tinkoff.acquiring.sdk.viewmodel.CardLogoProvider @@ -31,16 +29,15 @@ internal class ChosenCardComponent( private val cardLogo: ImageView = root.findViewById(R.id.acq_card_choosen_item_logo) private val cardName: TextView = root.findViewById(R.id.acq_card_choosen_item) private val cardChange: TextView = root.findViewById(R.id.acq_card_change) - private val cardCvc: CvcComponent = CvcComponent( + private val cardCvc: FocusDecoratorCvcComponent = FocusDecoratorCvcComponent( root.findViewById(R.id.cvc_container), initingFocusAndKeyboard, + onFocusCvc, + onInputComplete = { s -> + onCvcCompleted(s, true) + }, onDataChange = { b, s -> onCvcCompleted(s, b) - }, - onInitScreen = { _, function -> - if(initingFocusAndKeyboard){ - onFocusCvc(root.cvc_container.cvc_input.editText.apply(function)) - } } ) @@ -68,8 +65,4 @@ internal class ChosenCardComponent( fun enableCvc(isEnable: Boolean) { cardCvc.enable(isEnable) } - - fun showKeyboard() { - - } } \ No newline at end of file diff --git a/ui/src/main/java/ru/tinkoff/acquiring/sdk/redesign/recurrent/ui/RecurrentPaymentActivity.kt b/ui/src/main/java/ru/tinkoff/acquiring/sdk/redesign/recurrent/ui/RecurrentPaymentActivity.kt index 486b0310..31d5d804 100644 --- a/ui/src/main/java/ru/tinkoff/acquiring/sdk/redesign/recurrent/ui/RecurrentPaymentActivity.kt +++ b/ui/src/main/java/ru/tinkoff/acquiring/sdk/redesign/recurrent/ui/RecurrentPaymentActivity.kt @@ -60,6 +60,7 @@ internal class RecurrentPaymentActivity : AppCompatActivity() { private val cardPayComponent by lazyUnsafe { CardPayComponent( + binding.root, viewBinding = binding.acqRecurrentFormPay, email = null, onCvcCompleted = rejectedViewModel::inputCvc, diff --git a/ui/src/main/java/ru/tinkoff/acquiring/sdk/utils/ViewExtUtil.kt b/ui/src/main/java/ru/tinkoff/acquiring/sdk/utils/ViewExtUtil.kt index 07200e93..07b2904c 100644 --- a/ui/src/main/java/ru/tinkoff/acquiring/sdk/utils/ViewExtUtil.kt +++ b/ui/src/main/java/ru/tinkoff/acquiring/sdk/utils/ViewExtUtil.kt @@ -10,8 +10,10 @@ import android.view.View import android.view.ViewGroup import android.view.ViewParent import androidx.annotation.IdRes -import androidx.fragment.app.DialogFragment import androidx.fragment.app.Fragment +import kotlinx.android.synthetic.main.acq_card_pay_component.view.chosenCard +import kotlinx.android.synthetic.main.acq_fragment_cvc_input.view.cvc_input +import ru.tinkoff.acquiring.sdk.redesign.common.cardpay.CardPayComponent import kotlin.math.roundToInt import kotlin.math.roundToLong @@ -114,6 +116,21 @@ internal fun ViewGroup.forEachChild(action: (child: View) -> Unit) { } } +internal fun View.setupCvcInput(viewGroup: ViewGroup, cardPayComponent: CardPayComponent) { + val inputField = viewGroup.chosenCard.cvc_input + val inputEditText = viewGroup.chosenCard.cvc_input.editText + + listOf(this, inputField, inputEditText).forEach { view -> + view.apply { + setOnClickListener { + requestFocus() + isEnabled = true + cardPayComponent.clearCvc() + } + } + } +} + internal fun lerp(start: Int, end: Int, fraction: Float): Int { return (start + (end - start) * fraction).roundToInt() } @@ -133,4 +150,7 @@ internal fun Fragment.lazyView(@IdRes id: Int): Lazy = lazyUnsafe { requireView().findViewById(id) } internal fun Activity.lazyView(@IdRes id: Int): Lazy = - lazyUnsafe { findViewById(id) } \ No newline at end of file + lazyUnsafe { findViewById(id) } + +internal fun Activity.lazyView(view: View): Lazy = + lazyUnsafe { this.findViewById(view.id) } \ No newline at end of file diff --git a/ui/src/main/res/layout/acq_fragment_cvc_input.xml b/ui/src/main/res/layout/acq_fragment_cvc_input.xml index bebc8e0b..efc0b18b 100644 --- a/ui/src/main/res/layout/acq_fragment_cvc_input.xml +++ b/ui/src/main/res/layout/acq_fragment_cvc_input.xml @@ -8,4 +8,5 @@ android:minWidth="64dp" android:minHeight="48dp" android:gravity="center" + android:duplicateParentState="true" app:acq_title="@string/acq_label_card_secure" /> \ No newline at end of file