Skip to content

Commit

Permalink
Merge pull request #300 from tinkoff-mobile-tech/EACQAPW-5611-bugfix-…
Browse files Browse the repository at this point in the history
…main-screen-cvc-input-focus

EACQAPW-5611 Изменена логика поведения CVC поля на главной форме оплаты, при клике фокусируется
  • Loading branch information
harcoPro authored Aug 4, 2023
2 parents ed03849 + 12b4b5e commit 8bd0be1
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class CvcComponent(
private val onInitScreen: (Boolean, View.() -> Unit) -> Unit = { _, function -> }
) : UiComponent<String?> {

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 {
Expand Down
Original file line number Diff line number Diff line change
@@ -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<String?> {
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)

}
Original file line number Diff line number Diff line change
@@ -1,36 +1,62 @@
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

/**
* 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<CardChosenModel> {
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() }
Expand Down Expand Up @@ -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)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
),
Expand All @@ -168,7 +171,7 @@ internal class MainPaymentFormActivity : AppCompatActivity() {
onEmailInput = cardInputViewModel::email,
onEmailVisibleChange = cardInputViewModel::needEmail,
onChooseCardClick = viewModel::toChooseCard,
onPayClick = { cardInputViewModel.pay() }
onPayClick = { cardInputViewModel.pay() },
)
}

Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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))
}
}
)

Expand Down Expand Up @@ -68,8 +65,4 @@ internal class ChosenCardComponent(
fun enableCvc(isEnable: Boolean) {
cardCvc.enable(isEnable)
}

fun showKeyboard() {

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ internal class RecurrentPaymentActivity : AppCompatActivity() {

private val cardPayComponent by lazyUnsafe {
CardPayComponent(
binding.root,
viewBinding = binding.acqRecurrentFormPay,
email = null,
onCvcCompleted = rejectedViewModel::inputCvc,
Expand Down
24 changes: 22 additions & 2 deletions ui/src/main/java/ru/tinkoff/acquiring/sdk/utils/ViewExtUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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()
}
Expand All @@ -133,4 +150,7 @@ internal fun <T> Fragment.lazyView(@IdRes id: Int): Lazy<T> =
lazyUnsafe { requireView().findViewById(id) }

internal fun <T> Activity.lazyView(@IdRes id: Int): Lazy<T> =
lazyUnsafe { findViewById(id) }
lazyUnsafe { findViewById(id) }

internal fun <T : View> Activity.lazyView(view: View): Lazy<T> =
lazyUnsafe { this.findViewById(view.id) }
1 change: 1 addition & 0 deletions ui/src/main/res/layout/acq_fragment_cvc_input.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@
android:minWidth="64dp"
android:minHeight="48dp"
android:gravity="center"
android:duplicateParentState="true"
app:acq_title="@string/acq_label_card_secure" />

0 comments on commit 8bd0be1

Please sign in to comment.