From c3299035fa2e7950923004cfb85c48dd644cf5be Mon Sep 17 00:00:00 2001 From: Oscar Spruit Date: Fri, 30 Jun 2023 16:49:15 +0200 Subject: [PATCH 1/2] Provide pay button view per delegate This makes it possible to have a different pay button based on the payment method. COAND-634 --- .../checkout/ui/core/AdyenComponentView.kt | 47 ++++++++++++------- .../ui/core/internal/ui/ButtonViewProvider.kt | 31 ++++++++++++ .../ui/core/internal/ui/ComponentViewType.kt | 3 ++ .../core/internal/ui/view/DefaultPayButton.kt | 31 ++++++++++++ .../ui/core/internal/ui/view/PayButton.kt | 24 ++++++++++ .../main/res/layout/adyen_component_view.xml | 11 +++-- .../res/layout/default_pay_button_view.xml | 18 +++++++ 7 files changed, 142 insertions(+), 23 deletions(-) create mode 100644 ui-core/src/main/java/com/adyen/checkout/ui/core/internal/ui/ButtonViewProvider.kt create mode 100644 ui-core/src/main/java/com/adyen/checkout/ui/core/internal/ui/view/DefaultPayButton.kt create mode 100644 ui-core/src/main/java/com/adyen/checkout/ui/core/internal/ui/view/PayButton.kt create mode 100644 ui-core/src/main/res/layout/default_pay_button_view.xml diff --git a/ui-core/src/main/java/com/adyen/checkout/ui/core/AdyenComponentView.kt b/ui-core/src/main/java/com/adyen/checkout/ui/core/AdyenComponentView.kt index fbf0a93fc4..f3e86d9530 100644 --- a/ui-core/src/main/java/com/adyen/checkout/ui/core/AdyenComponentView.kt +++ b/ui-core/src/main/java/com/adyen/checkout/ui/core/AdyenComponentView.kt @@ -11,8 +11,8 @@ import android.content.Context import android.util.AttributeSet import android.view.LayoutInflater import android.view.MotionEvent -import android.widget.Button import android.widget.LinearLayout +import androidx.core.view.children import androidx.core.view.isVisible import androidx.core.view.updateLayoutParams import androidx.lifecycle.LifecycleOwner @@ -32,6 +32,7 @@ import com.adyen.checkout.ui.core.internal.ui.PaymentComponentUIEvent import com.adyen.checkout.ui.core.internal.ui.UIStateDelegate import com.adyen.checkout.ui.core.internal.ui.ViewProvidingDelegate import com.adyen.checkout.ui.core.internal.ui.ViewableComponent +import com.adyen.checkout.ui.core.internal.ui.view.PayButton import com.adyen.checkout.ui.core.internal.util.PayButtonFormatter import com.adyen.checkout.ui.core.internal.util.createLocalizedContext import com.adyen.checkout.ui.core.internal.util.hideKeyboard @@ -123,8 +124,6 @@ class AdyenComponentView @JvmOverloads constructor( val localizedContext = context.createLocalizedContext(componentParams.shopperLocale) - binding.payButton.setText(viewType, componentParams, localizedContext) - val view = componentView.getView() binding.frameLayoutComponentContainer.addView(view) view.updateLayoutParams { width = LayoutParams.MATCH_PARENT } @@ -144,20 +143,23 @@ class AdyenComponentView @JvmOverloads constructor( } }?.launchIn(coroutineScope) - binding.payButton.isVisible = buttonDelegate.shouldShowSubmitButton() - binding.payButton.setOnClickListener { + binding.frameLayoutButtonContainer.isVisible = buttonDelegate.shouldShowSubmitButton() + val buttonView = (viewType as ButtonComponentViewType) + .buttonViewProvider.getButton(context, attrs, defStyleAttr) + buttonView.setText(viewType, componentParams, localizedContext) + buttonView.setOnClickListener { buttonDelegate.onSubmit() } + binding.frameLayoutButtonContainer.addView(buttonView) } else { - binding.payButton.isVisible = false - binding.payButton.setOnClickListener(null) + binding.frameLayoutButtonContainer.isVisible = false } } private fun setInteractionBlocked(isInteractionBlocked: Boolean) { this.isInteractionBlocked = isInteractionBlocked - binding.payButton.isEnabled = !isInteractionBlocked + binding.frameLayoutButtonContainer.children.forEach { it.isEnabled = !isInteractionBlocked } if (isInteractionBlocked) { resetFocus() @@ -165,21 +167,30 @@ class AdyenComponentView @JvmOverloads constructor( } } - private fun Button.setText( + private fun PayButton.setText( viewType: ComponentViewType, componentParams: ComponentParams, localizedContext: Context ) { - if (viewType is AmountButtonComponentViewType) { - text = PayButtonFormatter.getPayButtonText( - amount = componentParams.amount, - locale = componentParams.shopperLocale, - localizedContext = localizedContext, - emptyAmountStringResId = viewType.buttonTextResId - ) - } else if (viewType is ButtonComponentViewType) { - text = localizedContext.getString(viewType.buttonTextResId) + val text = when (viewType) { + is AmountButtonComponentViewType -> { + PayButtonFormatter.getPayButtonText( + amount = componentParams.amount, + locale = componentParams.shopperLocale, + localizedContext = localizedContext, + emptyAmountStringResId = viewType.buttonTextResId + ) + } + + is ButtonComponentViewType -> { + localizedContext.getString(viewType.buttonTextResId) + } + + else -> { + null + } } + setText(text) } /** diff --git a/ui-core/src/main/java/com/adyen/checkout/ui/core/internal/ui/ButtonViewProvider.kt b/ui-core/src/main/java/com/adyen/checkout/ui/core/internal/ui/ButtonViewProvider.kt new file mode 100644 index 0000000000..ffb0a4b5e3 --- /dev/null +++ b/ui-core/src/main/java/com/adyen/checkout/ui/core/internal/ui/ButtonViewProvider.kt @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 Adyen N.V. + * + * This file is open source and available under the MIT license. See the LICENSE file for more info. + * + * Created by oscars on 30/6/2023. + */ + +package com.adyen.checkout.ui.core.internal.ui + +import android.content.Context +import android.util.AttributeSet +import androidx.annotation.RestrictTo +import com.adyen.checkout.ui.core.internal.ui.view.DefaultPayButton +import com.adyen.checkout.ui.core.internal.ui.view.PayButton + +@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) +interface ButtonViewProvider { + fun getButton( + context: Context, + attrs: AttributeSet?, + defStyleAttr: Int, + ): PayButton +} + +@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) +internal class DefaultButtonViewProvider : ButtonViewProvider { + + override fun getButton(context: Context, attrs: AttributeSet?, defStyleAttr: Int): PayButton = + DefaultPayButton(context, attrs, defStyleAttr) +} diff --git a/ui-core/src/main/java/com/adyen/checkout/ui/core/internal/ui/ComponentViewType.kt b/ui-core/src/main/java/com/adyen/checkout/ui/core/internal/ui/ComponentViewType.kt index 258a75f8e2..fc71b37a40 100644 --- a/ui-core/src/main/java/com/adyen/checkout/ui/core/internal/ui/ComponentViewType.kt +++ b/ui-core/src/main/java/com/adyen/checkout/ui/core/internal/ui/ComponentViewType.kt @@ -19,6 +19,9 @@ interface ComponentViewType { @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) interface ButtonComponentViewType : ComponentViewType { + + val buttonViewProvider: ButtonViewProvider get() = DefaultButtonViewProvider() + val buttonTextResId: Int @StringRes get diff --git a/ui-core/src/main/java/com/adyen/checkout/ui/core/internal/ui/view/DefaultPayButton.kt b/ui-core/src/main/java/com/adyen/checkout/ui/core/internal/ui/view/DefaultPayButton.kt new file mode 100644 index 0000000000..46e89df7b9 --- /dev/null +++ b/ui-core/src/main/java/com/adyen/checkout/ui/core/internal/ui/view/DefaultPayButton.kt @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 Adyen N.V. + * + * This file is open source and available under the MIT license. See the LICENSE file for more info. + * + * Created by oscars on 30/6/2023. + */ + +package com.adyen.checkout.ui.core.internal.ui.view + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import com.adyen.checkout.ui.core.databinding.DefaultPayButtonViewBinding + +internal class DefaultPayButton @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : PayButton(context, attrs, defStyleAttr) { + + private val binding = DefaultPayButtonViewBinding.inflate(LayoutInflater.from(context), this) + + override fun setOnClickListener(listener: OnClickListener?) { + binding.payButton.setOnClickListener(listener) + } + + override fun setText(text: String?) { + binding.payButton.text = text + } +} diff --git a/ui-core/src/main/java/com/adyen/checkout/ui/core/internal/ui/view/PayButton.kt b/ui-core/src/main/java/com/adyen/checkout/ui/core/internal/ui/view/PayButton.kt new file mode 100644 index 0000000000..15013026bc --- /dev/null +++ b/ui-core/src/main/java/com/adyen/checkout/ui/core/internal/ui/view/PayButton.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 Adyen N.V. + * + * This file is open source and available under the MIT license. See the LICENSE file for more info. + * + * Created by oscars on 30/6/2023. + */ + +package com.adyen.checkout.ui.core.internal.ui.view + +import android.content.Context +import android.util.AttributeSet +import android.widget.FrameLayout + +abstract class PayButton( + context: Context, + attrs: AttributeSet?, + defStyleAttr: Int, +) : FrameLayout(context, attrs, defStyleAttr) { + + abstract override fun setOnClickListener(listener: OnClickListener?) + + abstract fun setText(text: String?) +} diff --git a/ui-core/src/main/res/layout/adyen_component_view.xml b/ui-core/src/main/res/layout/adyen_component_view.xml index ada6f324da..5e616eda3a 100644 --- a/ui-core/src/main/res/layout/adyen_component_view.xml +++ b/ui-core/src/main/res/layout/adyen_component_view.xml @@ -19,10 +19,11 @@ android:layout_height="0dp" android:layout_weight="1" /> - + diff --git a/ui-core/src/main/res/layout/default_pay_button_view.xml b/ui-core/src/main/res/layout/default_pay_button_view.xml new file mode 100644 index 0000000000..6c0c8a142e --- /dev/null +++ b/ui-core/src/main/res/layout/default_pay_button_view.xml @@ -0,0 +1,18 @@ + + + + + From 013635530ef4e84e15f63cb47bca7dbdbbe9d7b0 Mon Sep 17 00:00:00 2001 From: Oscar Spruit Date: Mon, 3 Jul 2023 13:58:56 +0200 Subject: [PATCH 2/2] Provide custom button for Cash App Pay COAND-634 --- .../internal/ui/CashAppPayViewProvider.kt | 11 +++++++ .../internal/ui/view/CashAppPayButtonView.kt | 30 +++++++++++++++++++ .../layout-night/cash_app_pay_button_view.xml | 18 +++++++++++ .../res/layout/cash_app_pay_button_view.xml | 20 +++++++++++++ .../ui/core/internal/ui/ButtonViewProvider.kt | 1 - .../ui/core/internal/ui/view/PayButton.kt | 2 ++ 6 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 cashapppay/src/main/java/com/adyen/checkout/cashapppay/internal/ui/view/CashAppPayButtonView.kt create mode 100644 cashapppay/src/main/res/layout-night/cash_app_pay_button_view.xml create mode 100644 cashapppay/src/main/res/layout/cash_app_pay_button_view.xml diff --git a/cashapppay/src/main/java/com/adyen/checkout/cashapppay/internal/ui/CashAppPayViewProvider.kt b/cashapppay/src/main/java/com/adyen/checkout/cashapppay/internal/ui/CashAppPayViewProvider.kt index 276e753083..ff42afd501 100644 --- a/cashapppay/src/main/java/com/adyen/checkout/cashapppay/internal/ui/CashAppPayViewProvider.kt +++ b/cashapppay/src/main/java/com/adyen/checkout/cashapppay/internal/ui/CashAppPayViewProvider.kt @@ -10,12 +10,15 @@ package com.adyen.checkout.cashapppay.internal.ui import android.content.Context import android.util.AttributeSet +import com.adyen.checkout.cashapppay.internal.ui.view.CashAppPayButtonView import com.adyen.checkout.cashapppay.internal.ui.view.CashAppPayView import com.adyen.checkout.cashapppay.internal.ui.view.CashAppPayWaitingView import com.adyen.checkout.ui.core.internal.ui.ButtonComponentViewType +import com.adyen.checkout.ui.core.internal.ui.ButtonViewProvider import com.adyen.checkout.ui.core.internal.ui.ComponentView import com.adyen.checkout.ui.core.internal.ui.ComponentViewType import com.adyen.checkout.ui.core.internal.ui.ViewProvider +import com.adyen.checkout.ui.core.internal.ui.view.PayButton internal object CashAppPayViewProvider : ViewProvider { @@ -31,7 +34,15 @@ internal object CashAppPayViewProvider : ViewProvider { } } +internal class CashAppPayButtonViewProvider : ButtonViewProvider { + override fun getButton(context: Context, attrs: AttributeSet?, defStyleAttr: Int): PayButton = + CashAppPayButtonView(context, attrs, defStyleAttr) +} + internal object CashAppPayComponentViewType : ButtonComponentViewType { + + override val buttonViewProvider: ButtonViewProvider get() = CashAppPayButtonViewProvider() + override val viewProvider: ViewProvider = CashAppPayViewProvider override val buttonTextResId: Int = ButtonComponentViewType.DEFAULT_BUTTON_TEXT_RES_ID diff --git a/cashapppay/src/main/java/com/adyen/checkout/cashapppay/internal/ui/view/CashAppPayButtonView.kt b/cashapppay/src/main/java/com/adyen/checkout/cashapppay/internal/ui/view/CashAppPayButtonView.kt new file mode 100644 index 0000000000..77ae87dc89 --- /dev/null +++ b/cashapppay/src/main/java/com/adyen/checkout/cashapppay/internal/ui/view/CashAppPayButtonView.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Adyen N.V. + * + * This file is open source and available under the MIT license. See the LICENSE file for more info. + * + * Created by oscars on 30/6/2023. + */ + +package com.adyen.checkout.cashapppay.internal.ui.view + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import com.adyen.checkout.cashapppay.databinding.CashAppPayButtonViewBinding +import com.adyen.checkout.ui.core.internal.ui.view.PayButton + +internal class CashAppPayButtonView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : PayButton(context, attrs, defStyleAttr) { + + private val binding = CashAppPayButtonViewBinding.inflate(LayoutInflater.from(context), this) + + override fun setOnClickListener(listener: OnClickListener?) { + binding.payButton.setOnClickListener(listener) + } + + override fun setText(text: String?) = Unit +} diff --git a/cashapppay/src/main/res/layout-night/cash_app_pay_button_view.xml b/cashapppay/src/main/res/layout-night/cash_app_pay_button_view.xml new file mode 100644 index 0000000000..08061bf235 --- /dev/null +++ b/cashapppay/src/main/res/layout-night/cash_app_pay_button_view.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/cashapppay/src/main/res/layout/cash_app_pay_button_view.xml b/cashapppay/src/main/res/layout/cash_app_pay_button_view.xml new file mode 100644 index 0000000000..d1a8f65f82 --- /dev/null +++ b/cashapppay/src/main/res/layout/cash_app_pay_button_view.xml @@ -0,0 +1,20 @@ + + + + + + + diff --git a/ui-core/src/main/java/com/adyen/checkout/ui/core/internal/ui/ButtonViewProvider.kt b/ui-core/src/main/java/com/adyen/checkout/ui/core/internal/ui/ButtonViewProvider.kt index ffb0a4b5e3..a9ab1f17c7 100644 --- a/ui-core/src/main/java/com/adyen/checkout/ui/core/internal/ui/ButtonViewProvider.kt +++ b/ui-core/src/main/java/com/adyen/checkout/ui/core/internal/ui/ButtonViewProvider.kt @@ -23,7 +23,6 @@ interface ButtonViewProvider { ): PayButton } -@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) internal class DefaultButtonViewProvider : ButtonViewProvider { override fun getButton(context: Context, attrs: AttributeSet?, defStyleAttr: Int): PayButton = diff --git a/ui-core/src/main/java/com/adyen/checkout/ui/core/internal/ui/view/PayButton.kt b/ui-core/src/main/java/com/adyen/checkout/ui/core/internal/ui/view/PayButton.kt index 15013026bc..4ed202cd71 100644 --- a/ui-core/src/main/java/com/adyen/checkout/ui/core/internal/ui/view/PayButton.kt +++ b/ui-core/src/main/java/com/adyen/checkout/ui/core/internal/ui/view/PayButton.kt @@ -11,7 +11,9 @@ package com.adyen.checkout.ui.core.internal.ui.view import android.content.Context import android.util.AttributeSet import android.widget.FrameLayout +import androidx.annotation.RestrictTo +@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) abstract class PayButton( context: Context, attrs: AttributeSet?,