diff --git a/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/POLabeledContent.kt b/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/POLabeledContent.kt
index 798320cf9..ed52ada61 100644
--- a/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/POLabeledContent.kt
+++ b/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/POLabeledContent.kt
@@ -2,10 +2,12 @@ package com.processout.sdk.ui.core.component
import androidx.compose.foundation.layout.*
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Immutable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import com.processout.sdk.ui.core.annotation.ProcessOutInternalApi
+import com.processout.sdk.ui.core.style.POLabeledContentStyle
import com.processout.sdk.ui.core.theme.ProcessOutTheme.colors
import com.processout.sdk.ui.core.theme.ProcessOutTheme.spacing
import com.processout.sdk.ui.core.theme.ProcessOutTheme.typography
@@ -50,3 +52,35 @@ fun POLabeledContent(
}
}
}
+
+/** @suppress */
+@ProcessOutInternalApi
+object POLabeledContent {
+
+ @Immutable
+ data class Style(
+ val label: POText.Style,
+ val text: POText.Style,
+ val copyButton: POButton.Style
+ )
+
+ val default: Style
+ @Composable get() = Style(
+ label = POText.Style(
+ color = colors.text.placeholder,
+ textStyle = typography.s12(FontWeight.Medium)
+ ),
+ text = POText.Style(
+ color = colors.text.primary,
+ textStyle = typography.s15(FontWeight.Medium)
+ ),
+ copyButton = POCopyButton.default
+ )
+
+ @Composable
+ fun custom(style: POLabeledContentStyle) = Style(
+ label = POText.custom(style = style.label),
+ text = POText.custom(style = style.text),
+ copyButton = default.copyButton
+ )
+}
diff --git a/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/POTextWithIcon.kt b/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/POTextWithIcon.kt
index aa9f59a42..92b5b5cc6 100644
--- a/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/POTextWithIcon.kt
+++ b/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/POTextWithIcon.kt
@@ -93,7 +93,7 @@ object POTextWithIcon {
)
return Style(
text = text,
- iconResId = R.drawable.po_icon_info,
+ iconResId = R.drawable.po_icon_warning_diamond,
iconColorFilter = ColorFilter.tint(color = text.color)
)
}
diff --git a/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/field/radio/PORadioField.kt b/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/field/radio/PORadioField.kt
index ecac0ddfe..572173274 100644
--- a/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/field/radio/PORadioField.kt
+++ b/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/field/radio/PORadioField.kt
@@ -256,7 +256,7 @@ object PORadioField {
else if (isError) style.error
else style.normal
- internal fun Style.radioButtonStyle() = PORadioButton.Style(
+ fun Style.radioButtonStyle() = PORadioButton.Style(
normalColor = normal.radioButtonColor,
selectedColor = selected.radioButtonColor,
errorColor = error.radioButtonColor,
diff --git a/ui-core/src/main/res/drawable/po_icon_info.xml b/ui-core/src/main/res/drawable/po_icon_info.xml
deleted file mode 100644
index 5cfb1acb5..000000000
--- a/ui-core/src/main/res/drawable/po_icon_info.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
diff --git a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/DynamicCheckoutEvent.kt b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/DynamicCheckoutEvent.kt
index 6b34ce12c..83f0b0abe 100644
--- a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/DynamicCheckoutEvent.kt
+++ b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/DynamicCheckoutEvent.kt
@@ -1,11 +1,11 @@
package com.processout.sdk.ui.checkout
-import androidx.compose.ui.text.input.TextFieldValue
import com.processout.sdk.api.model.response.POAlternativePaymentMethodResponse
import com.processout.sdk.api.model.response.POGooglePayCardTokenizationData
import com.processout.sdk.core.ProcessOutResult
import com.processout.sdk.ui.card.scanner.recognition.POScannedCard
import com.processout.sdk.ui.savedpaymentmethods.POSavedPaymentMethodsConfiguration
+import com.processout.sdk.ui.shared.state.FieldValue
import org.json.JSONObject
internal sealed interface DynamicCheckoutEvent {
@@ -16,7 +16,7 @@ internal sealed interface DynamicCheckoutEvent {
data class FieldValueChanged(
val paymentMethodId: String,
val fieldId: String,
- val value: TextFieldValue
+ val value: FieldValue
) : DynamicCheckoutEvent
data class FieldFocusChanged(
diff --git a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/DynamicCheckoutInteractor.kt b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/DynamicCheckoutInteractor.kt
index fd7c6b5f2..24e8a37f9 100644
--- a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/DynamicCheckoutInteractor.kt
+++ b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/DynamicCheckoutInteractor.kt
@@ -11,8 +11,10 @@ import coil.request.ImageRequest
import coil.request.ImageResult
import com.processout.sdk.R
import com.processout.sdk.api.dispatcher.POEventDispatcher
-import com.processout.sdk.api.model.event.PONativeAlternativePaymentMethodEvent.WillSubmitParameters
-import com.processout.sdk.api.model.request.*
+import com.processout.sdk.api.model.request.POCardTokenizationProcessingRequest
+import com.processout.sdk.api.model.request.POCardTokenizationShouldContinueRequest
+import com.processout.sdk.api.model.request.POInvoiceAuthorizationRequest
+import com.processout.sdk.api.model.request.POInvoiceRequest
import com.processout.sdk.api.model.request.POInvoiceRequest.ExpandedProperty.Companion.paymentMethods
import com.processout.sdk.api.model.request.POInvoiceRequest.ExpandedProperty.Companion.transaction
import com.processout.sdk.api.model.response.*
@@ -59,7 +61,9 @@ import com.processout.sdk.ui.checkout.delegate.PODynamicCheckoutEvent.*
import com.processout.sdk.ui.napm.*
import com.processout.sdk.ui.napm.PONativeAlternativePaymentConfiguration.*
import com.processout.sdk.ui.napm.PONativeAlternativePaymentConfiguration.Flow
-import com.processout.sdk.ui.napm.delegate.PONativeAlternativePaymentEvent
+import com.processout.sdk.ui.napm.delegate.v2.NativeAlternativePaymentDefaultValuesRequest
+import com.processout.sdk.ui.napm.delegate.v2.PONativeAlternativePaymentEvent
+import com.processout.sdk.ui.napm.delegate.v2.PONativeAlternativePaymentEvent.WillSubmitParameters
import com.processout.sdk.ui.savedpaymentmethods.POSavedPaymentMethodsConfiguration
import com.processout.sdk.ui.shared.extension.orElse
import com.processout.sdk.ui.shared.state.FieldValue
@@ -148,8 +152,8 @@ internal class DynamicCheckoutInteractor(
}
private fun cancelWebAuthorization() {
- with(_state.value) {
- if (selectedPaymentMethod != null || pendingSubmitPaymentMethod != null) {
+ _state.value.let {
+ if (it.selectedPaymentMethod != null || it.pendingSubmitPaymentMethod != null) {
interactorScope.launch {
_sideEffects.send(DynamicCheckoutSideEffect.CancelWebAuthorization)
}
@@ -432,8 +436,8 @@ internal class DynamicCheckoutInteractor(
_state.value.paymentMethods.find { it.id == id }
private fun activePaymentMethod(): PaymentMethod? =
- with(_state.value) {
- processingPaymentMethod ?: selectedPaymentMethod
+ _state.value.let {
+ it.processingPaymentMethod ?: it.selectedPaymentMethod
}
private fun onPaymentMethodSelected(event: PaymentMethodSelected) {
@@ -569,20 +573,24 @@ internal class DynamicCheckoutInteractor(
private fun onFieldValueChanged(event: FieldValueChanged) {
when (val paymentMethod = paymentMethod(event.paymentMethodId)) {
- is Card -> cardTokenization.onEvent(
- CardTokenizationEvent.FieldValueChanged(event.fieldId, event.value)
- )
+ is Card -> if (event.value is FieldValue.Text) {
+ cardTokenization.onEvent(
+ CardTokenizationEvent.FieldValueChanged(event.fieldId, event.value.value)
+ )
+ }
is NativeAlternativePayment -> nativeAlternativePayment.onEvent(
- NativeAlternativePaymentEvent.FieldValueChanged(event.fieldId, FieldValue.Text(event.value))
+ NativeAlternativePaymentEvent.FieldValueChanged(event.fieldId, event.value)
)
- else -> _state.update { state ->
- state.copy(
- paymentMethods = state.paymentMethods.map {
- if (it.id == paymentMethod?.id) {
- updatedPaymentMethod(it, event.fieldId, event.value)
- } else it
- }
- )
+ else -> if (event.value is FieldValue.Text) {
+ _state.update { state ->
+ state.copy(
+ paymentMethods = state.paymentMethods.map {
+ if (it.id == paymentMethod?.id) {
+ updatedPaymentMethod(it, event.fieldId, event.value.value)
+ } else it
+ }
+ )
+ }
}
}
}
@@ -593,9 +601,11 @@ internal class DynamicCheckoutInteractor(
value: TextFieldValue
): PaymentMethod = when (paymentMethod) {
is AlternativePayment -> when (fieldId) {
- FieldId.SAVE_PAYMENT_METHOD -> with(paymentMethod) {
+ FieldId.SAVE_PAYMENT_METHOD -> {
POLogger.debug("Field is edited by the user: %s = %s", fieldId, value.text)
- copy(savePaymentMethodField = savePaymentMethodField?.copy(value = value))
+ paymentMethod.copy(
+ savePaymentMethodField = paymentMethod.savePaymentMethodField?.copy(value = value)
+ )
}
else -> paymentMethod
}
@@ -840,16 +850,21 @@ internal class DynamicCheckoutInteractor(
if (paymentMethod.id != paymentMethodId) {
return
}
- result.onSuccess { response ->
- authorizeInvoice(
- paymentMethod = paymentMethod,
- source = response.gatewayToken,
- allowFallbackToSale = true
- )
- }.onFailure { failure ->
- invalidateInvoice(
- reason = PODynamicCheckoutInvoiceInvalidationReason.Failure(failure)
+ when (paymentMethod) {
+ is NativeAlternativePayment -> nativeAlternativePayment.onEvent(
+ NativeAlternativePaymentEvent.RedirectResult(result)
)
+ else -> result.onSuccess { response ->
+ authorizeInvoice(
+ paymentMethod = paymentMethod,
+ source = response.gatewayToken,
+ allowFallbackToSale = true
+ )
+ }.onFailure { failure ->
+ invalidateInvoice(
+ reason = PODynamicCheckoutInvoiceInvalidationReason.Failure(failure)
+ )
+ }
}
}
}
@@ -1081,7 +1096,7 @@ internal class DynamicCheckoutInteractor(
eventDispatcher.send(request.toResponse(shouldContinue))
}
}
- eventDispatcher.subscribeForRequest(
+ eventDispatcher.subscribeForRequest(
coroutineScope = interactorScope
) { request ->
activePaymentMethod()?.let { paymentMethod ->
@@ -1128,9 +1143,17 @@ internal class DynamicCheckoutInteractor(
_sideEffects.send(permissionRequest)
POLogger.info("System permission requested: %s", permissionRequest)
}
- is NativeAlternativePaymentSideEffect.Redirect -> {
- // TODO
- }
+ is NativeAlternativePaymentSideEffect.Redirect ->
+ activePaymentMethod()?.let { paymentMethod ->
+ _state.update { it.copy(processingPaymentMethod = paymentMethod) }
+ _sideEffects.send(
+ DynamicCheckoutSideEffect.AlternativePayment(
+ paymentMethodId = paymentMethod.id,
+ redirectUrl = sideEffect.redirectUrl,
+ returnUrl = sideEffect.returnUrl
+ )
+ )
+ }
}
}
}
diff --git a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/screen/DynamicCheckoutScreen.kt b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/DynamicCheckoutScreen.kt
similarity index 83%
rename from ui/src/main/kotlin/com/processout/sdk/ui/checkout/screen/DynamicCheckoutScreen.kt
rename to ui/src/main/kotlin/com/processout/sdk/ui/checkout/DynamicCheckoutScreen.kt
index 4e1211c22..3b1f6353c 100644
--- a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/screen/DynamicCheckoutScreen.kt
+++ b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/DynamicCheckoutScreen.kt
@@ -1,8 +1,7 @@
@file:Suppress("MayBeConstant", "MemberVisibilityCanBePrivate")
-package com.processout.sdk.ui.checkout.screen
+package com.processout.sdk.ui.checkout
-import android.view.Gravity
import androidx.annotation.DrawableRes
import androidx.compose.animation.*
import androidx.compose.animation.core.LinearEasing
@@ -21,6 +20,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
@@ -35,24 +35,22 @@ import com.processout.sdk.api.model.response.POImageResource
import com.processout.sdk.ui.card.tokenization.CardTokenizationEvent
import com.processout.sdk.ui.card.tokenization.screen.CardTokenizationContent
import com.processout.sdk.ui.card.tokenization.screen.CardTokenizationScreen
-import com.processout.sdk.ui.checkout.DynamicCheckoutEvent
import com.processout.sdk.ui.checkout.DynamicCheckoutEvent.*
-import com.processout.sdk.ui.checkout.DynamicCheckoutViewModelState
+import com.processout.sdk.ui.checkout.DynamicCheckoutScreen.LongAnimationDurationMillis
+import com.processout.sdk.ui.checkout.DynamicCheckoutScreen.PaymentLogoSize
+import com.processout.sdk.ui.checkout.DynamicCheckoutScreen.PaymentSuccessStyle
+import com.processout.sdk.ui.checkout.DynamicCheckoutScreen.RowComponentSpacing
+import com.processout.sdk.ui.checkout.DynamicCheckoutScreen.SectionHeaderStyle
+import com.processout.sdk.ui.checkout.DynamicCheckoutScreen.ShortAnimationDurationMillis
+import com.processout.sdk.ui.checkout.DynamicCheckoutScreen.SuccessImageHeight
+import com.processout.sdk.ui.checkout.DynamicCheckoutScreen.SuccessImageWidth
+import com.processout.sdk.ui.checkout.DynamicCheckoutScreen.animatedBackgroundColor
+import com.processout.sdk.ui.checkout.DynamicCheckoutScreen.cardTokenizationStyle
+import com.processout.sdk.ui.checkout.DynamicCheckoutScreen.nativeAlternativePaymentStyle
+import com.processout.sdk.ui.checkout.DynamicCheckoutScreen.toButtonStyle
import com.processout.sdk.ui.checkout.DynamicCheckoutViewModelState.*
import com.processout.sdk.ui.checkout.DynamicCheckoutViewModelState.Field.CheckboxField
import com.processout.sdk.ui.checkout.DynamicCheckoutViewModelState.RegularPayment.Content.*
-import com.processout.sdk.ui.checkout.PODynamicCheckoutConfiguration
-import com.processout.sdk.ui.checkout.screen.DynamicCheckoutScreen.LongAnimationDurationMillis
-import com.processout.sdk.ui.checkout.screen.DynamicCheckoutScreen.PaymentLogoSize
-import com.processout.sdk.ui.checkout.screen.DynamicCheckoutScreen.PaymentSuccessStyle
-import com.processout.sdk.ui.checkout.screen.DynamicCheckoutScreen.RowComponentSpacing
-import com.processout.sdk.ui.checkout.screen.DynamicCheckoutScreen.SectionHeaderStyle
-import com.processout.sdk.ui.checkout.screen.DynamicCheckoutScreen.ShortAnimationDurationMillis
-import com.processout.sdk.ui.checkout.screen.DynamicCheckoutScreen.SuccessImageHeight
-import com.processout.sdk.ui.checkout.screen.DynamicCheckoutScreen.SuccessImageWidth
-import com.processout.sdk.ui.checkout.screen.DynamicCheckoutScreen.animatedBackgroundColor
-import com.processout.sdk.ui.checkout.screen.DynamicCheckoutScreen.cardTokenizationStyle
-import com.processout.sdk.ui.checkout.screen.DynamicCheckoutScreen.toButtonStyle
import com.processout.sdk.ui.core.R
import com.processout.sdk.ui.core.component.*
import com.processout.sdk.ui.core.component.POButton.HighlightedStyle
@@ -63,8 +61,8 @@ import com.processout.sdk.ui.core.component.field.code.POCodeField
import com.processout.sdk.ui.core.component.field.dropdown.PODropdownField
import com.processout.sdk.ui.core.component.field.radio.PORadioButton
import com.processout.sdk.ui.core.component.field.radio.PORadioField
-import com.processout.sdk.ui.core.component.field.radio.PORadioGroup
-import com.processout.sdk.ui.core.component.field.radio.PORadioGroup.toRadioButtonStyle
+import com.processout.sdk.ui.core.component.field.radio.PORadioField.radioButtonStyle
+import com.processout.sdk.ui.core.component.stepper.POStepper
import com.processout.sdk.ui.core.state.POActionState
import com.processout.sdk.ui.core.state.POImmutableList
import com.processout.sdk.ui.core.style.POBrandButtonStateStyle
@@ -76,10 +74,16 @@ import com.processout.sdk.ui.core.theme.ProcessOutTheme.dimensions
import com.processout.sdk.ui.core.theme.ProcessOutTheme.shapes
import com.processout.sdk.ui.core.theme.ProcessOutTheme.spacing
import com.processout.sdk.ui.core.theme.ProcessOutTheme.typography
+import com.processout.sdk.ui.napm.NativeAlternativePaymentEvent
+import com.processout.sdk.ui.napm.NativeAlternativePaymentViewModelState
+import com.processout.sdk.ui.napm.NativeAlternativePaymentViewModelState.Stage
+import com.processout.sdk.ui.napm.screen.NativeAlternativePaymentContent
+import com.processout.sdk.ui.napm.screen.NativeAlternativePaymentScreen
import com.processout.sdk.ui.shared.component.AndroidTextView
import com.processout.sdk.ui.shared.component.GooglePayButton
import com.processout.sdk.ui.shared.extension.*
import com.processout.sdk.ui.shared.state.FieldState
+import com.processout.sdk.ui.shared.state.FieldValue
@Composable
internal fun DynamicCheckoutScreen(
@@ -166,7 +170,7 @@ private fun Content(
) {
POMessageBox(
text = state.errorMessage,
- style = style.messageBox,
+ style = style.errorMessageBox,
modifier = Modifier.padding(bottom = spacing.large),
horizontalArrangement = Arrangement.spacedBy(RowComponentSpacing),
enterAnimationDelayMillis = ShortAnimationDurationMillis
@@ -383,7 +387,8 @@ private fun RegularPayments(
RegularPaymentContent(
payment = payment,
onEvent = onEvent,
- style = style
+ style = style,
+ isLightTheme = isLightTheme
)
if (index != payments.elements.lastIndex) {
HorizontalDivider(
@@ -438,7 +443,7 @@ private fun RegularPayment(
PORadioButton(
selected = payment.state.selected,
onClick = { onEvent(PaymentMethodSelected(id = payment.id)) },
- style = style.radioGroup.toRadioButtonStyle()
+ style = style.radioField.radioButtonStyle()
)
}
}
@@ -447,7 +452,8 @@ private fun RegularPayment(
private fun RegularPaymentContent(
payment: RegularPayment,
onEvent: (DynamicCheckoutEvent) -> Unit,
- style: DynamicCheckoutScreen.Style
+ style: DynamicCheckoutScreen.Style,
+ isLightTheme: Boolean
) {
AnimatedVisibility(
visible = payment.state.selected && !payment.state.loading,
@@ -476,16 +482,35 @@ private fun RegularPaymentContent(
when (payment.content) {
is Card -> CardTokenizationContent(
state = payment.content.state,
- onEvent = { onEvent(it.map(paymentMethodId = payment.id)) },
+ onEvent = {
+ it.map(paymentMethodId = payment.id)?.let { event ->
+ onEvent(event)
+ }
+ },
style = style.cardTokenizationStyle(),
withActionsContainer = false
)
- is NativeAlternativePayment -> NativeAlternativePayment(
- id = payment.id,
- state = payment.content.state,
- onEvent = onEvent,
- style = style
- )
+ is NativeAlternativePayment -> when (val state = payment.content.state) {
+ is NativeAlternativePaymentViewModelState.Loaded -> {
+ when (state.content.stage) {
+ is Stage.Pending,
+ is Stage.Completed -> LocalFocusManager.current.clearFocus(force = true)
+ else -> {}
+ }
+ NativeAlternativePaymentContent(
+ content = state.content,
+ onEvent = {
+ it.map(paymentMethodId = payment.id)?.let { event ->
+ onEvent(event)
+ }
+ },
+ style = style.nativeAlternativePaymentStyle(),
+ isPrimaryActionEnabled = state.primaryAction?.let { it.enabled && !it.loading } ?: false,
+ isLightTheme = isLightTheme
+ )
+ }
+ else -> {}
+ }
is AlternativePayment -> AlternativePayment(
id = payment.id,
state = payment.content,
@@ -558,7 +583,7 @@ private fun CheckboxField(
FieldValueChanged(
paymentMethodId = id,
fieldId = state.id,
- value = TextFieldValue(text = it.toString())
+ value = FieldValue.Text(value = TextFieldValue(text = it.toString()))
)
)
},
@@ -667,11 +692,11 @@ private fun Success(
private fun CardTokenizationEvent.map(
paymentMethodId: String
-): DynamicCheckoutEvent = when (this) {
+): DynamicCheckoutEvent? = when (this) {
is CardTokenizationEvent.FieldValueChanged -> FieldValueChanged(
paymentMethodId = paymentMethodId,
fieldId = id,
- value = value
+ value = FieldValue.Text(value = value)
)
is CardTokenizationEvent.FieldFocusChanged -> FieldFocusChanged(
paymentMethodId = paymentMethodId,
@@ -682,8 +707,36 @@ private fun CardTokenizationEvent.map(
actionId = id,
paymentMethodId = paymentMethodId
)
- is CardTokenizationEvent.CardScannerResult -> CardScannerResult(card = card)
is CardTokenizationEvent.Dismiss -> Dismiss(failure = failure)
+ is CardTokenizationEvent.CardScannerResult -> null // Ignore, handled by dynamic checkout events.
+}
+
+private fun NativeAlternativePaymentEvent.map(
+ paymentMethodId: String
+): DynamicCheckoutEvent? = when (this) {
+ is NativeAlternativePaymentEvent.FieldValueChanged -> FieldValueChanged(
+ paymentMethodId = paymentMethodId,
+ fieldId = id,
+ value = value
+ )
+ is NativeAlternativePaymentEvent.FieldFocusChanged -> FieldFocusChanged(
+ paymentMethodId = paymentMethodId,
+ fieldId = id,
+ isFocused = isFocused
+ )
+ is NativeAlternativePaymentEvent.Action -> Action(
+ actionId = id,
+ paymentMethodId = paymentMethodId
+ )
+ is NativeAlternativePaymentEvent.DialogAction -> DialogAction(
+ actionId = id,
+ paymentMethodId = paymentMethodId,
+ isConfirmed = isConfirmed
+ )
+ is NativeAlternativePaymentEvent.ActionConfirmationRequested -> ActionConfirmationRequested(id = id)
+ is NativeAlternativePaymentEvent.Dismiss -> Dismiss(failure = failure)
+ is NativeAlternativePaymentEvent.PermissionRequestResult,
+ is NativeAlternativePaymentEvent.RedirectResult -> null // Ignore, handled by dynamic checkout events.
}
internal object DynamicCheckoutScreen {
@@ -691,20 +744,22 @@ internal object DynamicCheckoutScreen {
@Immutable
data class Style(
val sectionHeader: SectionHeaderStyle,
+ val subsectionTitle: POText.Style,
val googlePayButton: GooglePayButton.Style,
val expressPaymentButton: POBrandButtonStyle?,
val regularPayment: RegularPaymentStyle,
- val label: POText.Style,
+ val labeledContent: POLabeledContent.Style,
+ val groupedContent: POGroupedContent.Style,
val field: POField.Style,
val codeField: POField.Style,
val radioField: PORadioField.Style,
- val radioGroup: PORadioGroup.Style, // TODO: remove
val checkbox: POCheckbox.Style,
val dropdownMenu: PODropdownField.MenuStyle,
val bodyText: AndroidTextView.Style,
val errorText: POText.Style,
- val messageBox: POMessageBox.Style,
+ val errorMessageBox: POMessageBox.Style,
val dialog: PODialog.Style,
+ val stepper: POStepper.Style,
val scanCardButton: POButton.Style,
val actionsContainer: POActionsContainer.Style,
val backgroundColor: Color,
@@ -740,29 +795,32 @@ internal object DynamicCheckoutScreen {
isLightTheme: Boolean
) = Style(
sectionHeader = custom?.sectionHeader?.custom() ?: defaultSectionHeader,
- googlePayButton = custom?.googlePayButton?.let {
- GooglePayButton.custom(style = it, isLightTheme)
- } ?: GooglePayButton.default(isLightTheme),
- expressPaymentButton = custom?.expressPaymentButton,
- regularPayment = custom?.regularPayment?.custom() ?: defaultRegularPayment,
- label = custom?.label?.let {
+ subsectionTitle = custom?.subsectionTitle?.let {
POText.custom(style = it)
} ?: POText.Style(
color = colors.text.primary,
textStyle = typography.s14(FontWeight.Medium)
),
+ googlePayButton = custom?.googlePayButton?.let {
+ GooglePayButton.custom(style = it, isLightTheme)
+ } ?: GooglePayButton.default(isLightTheme),
+ expressPaymentButton = custom?.expressPaymentButton,
+ regularPayment = custom?.regularPayment?.custom() ?: defaultRegularPayment,
+ labeledContent = custom?.labeledContent?.let {
+ POLabeledContent.custom(style = it)
+ } ?: POLabeledContent.default,
+ groupedContent = custom?.groupedContent?.let {
+ POGroupedContent.custom(style = it)
+ } ?: POGroupedContent.default,
field = custom?.field?.let {
POField.custom(style = it)
} ?: POField.default2,
codeField = custom?.codeField?.let {
POField.custom(style = it)
- } ?: POCodeField.default,
+ } ?: POCodeField.default2,
radioField = custom?.radioField?.let {
PORadioField.custom(style = it)
} ?: PORadioField.default,
- radioGroup = custom?.radioButton?.let {
- PORadioGroup.custom(style = it)
- } ?: PORadioGroup.default,
checkbox = custom?.checkbox?.let {
POCheckbox.custom(style = it)
} ?: POCheckbox.default2,
@@ -782,12 +840,15 @@ internal object DynamicCheckoutScreen {
color = colors.text.error,
textStyle = typography.s14()
),
- messageBox = custom?.messageBox?.let {
+ errorMessageBox = custom?.errorMessageBox?.let {
POMessageBox.custom(style = it)
- } ?: POMessageBox.error,
+ } ?: POMessageBox.error2,
dialog = custom?.dialog?.let {
PODialog.custom(style = it)
} ?: PODialog.default,
+ stepper = custom?.stepper?.let {
+ POStepper.custom(style = it)
+ } ?: POStepper.default,
scanCardButton = custom?.scanCardButton?.let {
POButton.custom(style = it)
} ?: CardTokenizationScreen.defaultScanButton,
@@ -819,14 +880,14 @@ internal object DynamicCheckoutScreen {
private val defaultRegularPayment: RegularPaymentStyle
@Composable get() {
val description = POText.Style(
- color = colors.text.muted,
- textStyle = typography.body2
+ color = colors.text.secondary,
+ textStyle = typography.s14()
)
return RegularPaymentStyle(
title = POText.body1,
description = POTextWithIcon.Style(
text = description,
- iconResId = R.drawable.po_icon_info,
+ iconResId = R.drawable.po_icon_warning_diamond,
iconColorFilter = ColorFilter.tint(color = description.color)
),
shape = shapes.roundedCornersSmall,
@@ -963,7 +1024,7 @@ internal object DynamicCheckoutScreen {
fun Style.cardTokenizationStyle() = CardTokenizationScreen.Style(
title = regularPayment.title,
- sectionTitle = label,
+ sectionTitle = subsectionTitle,
field = field,
radioField = radioField,
dropdownMenu = dropdownMenu,
@@ -977,6 +1038,29 @@ internal object DynamicCheckoutScreen {
dragHandleColor = Color.Unspecified
)
+ @Composable
+ fun Style.nativeAlternativePaymentStyle() = NativeAlternativePaymentScreen.Style(
+ title = regularPayment.title,
+ bodyText = bodyText,
+ message = regularPayment.description.text,
+ labeledContent = labeledContent,
+ groupedContent = groupedContent,
+ field = field,
+ codeField = codeField,
+ radioField = radioField,
+ dropdownMenu = dropdownMenu,
+ checkbox = checkbox,
+ dialog = dialog,
+ stepper = stepper,
+ success = NativeAlternativePaymentScreen.defaultSuccess,
+ errorMessageBox = errorMessageBox,
+ actionsContainer = actionsContainer,
+ backgroundColor = Color.Unspecified,
+ progressIndicatorColor = Color.Unspecified,
+ dividerColor = Color.Unspecified,
+ dragHandleColor = Color.Unspecified
+ )
+
val ShortAnimationDurationMillis = 300
val LongAnimationDurationMillis = 600
val CrossfadeAnimationDurationMillis = 400
@@ -984,20 +1068,7 @@ internal object DynamicCheckoutScreen {
val RowComponentSpacing = 10.dp
val PaymentLogoSize = 24.dp
- val CaptureLogoHeight = 34.dp
-
- val CaptureImageWidth = 110.dp
- val CaptureImageHeight = 140.dp
val SuccessImageWidth = 220.dp
val SuccessImageHeight = 280.dp
-
- private val ShortMessageMaxLength = 150
-
- fun isMessageShort(text: String) = text.length <= ShortMessageMaxLength
-
- fun messageGravity(text: String): Int =
- if (isMessageShort(text))
- Gravity.CENTER_HORIZONTAL
- else Gravity.START
}
diff --git a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/DynamicCheckoutViewModel.kt b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/DynamicCheckoutViewModel.kt
index 9081e7df4..f4321a73c 100644
--- a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/DynamicCheckoutViewModel.kt
+++ b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/DynamicCheckoutViewModel.kt
@@ -338,10 +338,7 @@ internal class DynamicCheckoutViewModel private constructor(
),
content = if (selected) Content.NativeAlternativePayment(nativeAlternativePaymentState) else null,
submitAction = if (selected && nativeAlternativePaymentState is NativeAlternativePaymentViewModelState.Loaded)
- nativeAlternativePaymentState.primaryAction?.copy(
- text = submitButtonText,
- icon = configuration.submitButton.icon
- ) else null
+ nativeAlternativePaymentState.primaryAction else null
)
else -> null
}
diff --git a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/PODynamicCheckoutActivity.kt b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/PODynamicCheckoutActivity.kt
index fa00ea4cb..315b601fc 100644
--- a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/PODynamicCheckoutActivity.kt
+++ b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/PODynamicCheckoutActivity.kt
@@ -43,7 +43,6 @@ import com.processout.sdk.ui.checkout.DynamicCheckoutSideEffect.*
import com.processout.sdk.ui.checkout.PODynamicCheckoutConfiguration.*
import com.processout.sdk.ui.checkout.PODynamicCheckoutConfiguration.Button
import com.processout.sdk.ui.checkout.PODynamicCheckoutConfiguration.CancelButton
-import com.processout.sdk.ui.checkout.screen.DynamicCheckoutScreen
import com.processout.sdk.ui.core.annotation.ProcessOutInternalApi
import com.processout.sdk.ui.core.theme.ProcessOutTheme
import com.processout.sdk.ui.googlepay.POGooglePayCardTokenizationLauncher
@@ -140,8 +139,17 @@ class PODynamicCheckoutActivity : POBaseTransparentPortraitActivity() {
invoiceId = configuration.invoiceRequest.invoiceId,
gatewayConfigurationId = String()
),
- submitButton = configuration.submitButton.map(),
+ header = null,
+ content = configuration.alternativePayment.content,
+ submitButton = configuration.submitButton.let {
+ PONativeAlternativePaymentConfiguration.Button(
+ text = it.text ?: getString(R.string.po_dynamic_checkout_button_pay),
+ icon = it.icon
+ )
+ },
cancelButton = configuration.cancelButton?.map(),
+ inlineSingleSelectValuesLimit = configuration.alternativePayment.inlineSingleSelectValuesLimit,
+ barcode = configuration.alternativePayment.barcode,
redirect = if (!returnUrl.isNullOrBlank())
RedirectConfiguration(returnUrl = returnUrl) else null,
paymentConfirmation = PaymentConfirmationConfiguration(
@@ -149,8 +157,6 @@ class PODynamicCheckoutActivity : POBaseTransparentPortraitActivity() {
confirmButton = paymentConfirmation.confirmButton?.map(),
cancelButton = paymentConfirmation.cancelButton?.map()
),
- barcode = configuration.alternativePayment.barcode,
- inlineSingleSelectValuesLimit = configuration.alternativePayment.inlineSingleSelectValuesLimit,
success = null
)
}
diff --git a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/PODynamicCheckoutConfiguration.kt b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/PODynamicCheckoutConfiguration.kt
index 14c09df78..4b7beb247 100644
--- a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/PODynamicCheckoutConfiguration.kt
+++ b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/PODynamicCheckoutConfiguration.kt
@@ -13,6 +13,7 @@ import com.processout.sdk.ui.card.scanner.POCardScannerConfiguration
import com.processout.sdk.ui.core.annotation.ProcessOutInternalApi
import com.processout.sdk.ui.core.shared.image.PODrawableImage
import com.processout.sdk.ui.core.style.*
+import com.processout.sdk.ui.napm.PONativeAlternativePaymentConfiguration
import com.processout.sdk.ui.shared.configuration.POActionConfirmationConfiguration
import com.processout.sdk.ui.shared.configuration.POBarcodeConfiguration
import kotlinx.parcelize.Parcelize
@@ -230,6 +231,7 @@ data class PODynamicCheckoutConfiguration(
* Specifies alternative payment configuration.
*
* @param[returnUrl] Deep link return URL. Required for web authorization.
+ * @param[content] Custom content for native alternative payment.
* @param[inlineSingleSelectValuesLimit] Defines maximum number of options that will be
* displayed inline for parameters where user should select single option (e.g. radio buttons).
* Default value is _5_.
@@ -239,6 +241,7 @@ data class PODynamicCheckoutConfiguration(
@Parcelize
data class AlternativePaymentConfiguration(
val returnUrl: String? = null,
+ val content: PONativeAlternativePaymentConfiguration.Content? = null,
val inlineSingleSelectValuesLimit: Int = 5,
val barcode: POBarcodeConfiguration = POBarcodeConfiguration(saveButton = POBarcodeConfiguration.Button()),
val paymentConfirmation: PaymentConfirmationConfiguration = PaymentConfirmationConfiguration()
@@ -249,8 +252,6 @@ data class PODynamicCheckoutConfiguration(
*
* @param[timeoutSeconds] Amount of time (in seconds) to wait for final payment confirmation.
* Default value is 3 minutes, while maximum value is 15 minutes.
- * @param[showProgressIndicatorAfterSeconds] Show progress indicator during payment confirmation after provided delay (in seconds).
- * Use _null_ to hide, this is a default behaviour.
* @param[confirmButton] Confirm button configuration.
* @param[cancelButton] Cancel button configuration.
*/
@@ -258,7 +259,6 @@ data class PODynamicCheckoutConfiguration(
data class PaymentConfirmationConfiguration(
@IntRange(from = 0, to = 15 * 60)
val timeoutSeconds: Int = 3 * 60,
- val showProgressIndicatorAfterSeconds: Int? = null,
val confirmButton: Button? = null,
val cancelButton: CancelButton? = CancelButton()
) : Parcelable
@@ -326,20 +326,22 @@ data class PODynamicCheckoutConfiguration(
* Specifies dynamic checkout style.
*
* @param[sectionHeader] Section header style.
+ * @param[subsectionTitle] Subsection title style.
* @param[googlePayButton] Google Pay button style.
* @param[expressPaymentButton] Branded express payment button style.
* @param[regularPayment] Regular payment style.
- * @param[label] Field label style.
+ * @param[labeledContent] Labeled content style, such as customer instructions.
+ * @param[groupedContent] Grouped content style, such as customer instructions.
* @param[field] Field style.
* @param[codeField] Code field style.
* @param[radioField] Radio field style.
- * @param[radioButton] Radio button style.
* @param[checkbox] Checkbox style.
* @param[dropdownMenu] Dropdown menu style.
* @param[bodyText] Body text style.
* @param[errorText] Error text style.
- * @param[messageBox] Message box style.
+ * @param[errorMessageBox] Error message box style.
* @param[dialog] Dialog style.
+ * @param[stepper] Multi-step progress view style.
* @param[scanCardButton] Scan card button style.
* @param[actionsContainer] Style of action buttons and their container.
* @param[backgroundColorResId] Color resource ID for background.
@@ -350,20 +352,22 @@ data class PODynamicCheckoutConfiguration(
@Parcelize
data class Style(
val sectionHeader: SectionHeaderStyle? = null,
+ val subsectionTitle: POTextStyle? = null,
val googlePayButton: POGooglePayButtonStyle? = null,
val expressPaymentButton: POBrandButtonStyle? = null,
val regularPayment: RegularPaymentStyle? = null,
- val label: POTextStyle? = null,
+ val labeledContent: POLabeledContentStyle? = null,
+ val groupedContent: POGroupedContentStyle? = null,
val field: POFieldStyle? = null,
val codeField: POFieldStyle? = null,
val radioField: PORadioFieldStyle? = null,
- val radioButton: PORadioButtonStyle? = null, // TODO: remove
val checkbox: POCheckboxStyle? = null,
val dropdownMenu: PODropdownMenuStyle? = null,
val bodyText: POTextStyle? = null,
val errorText: POTextStyle? = null,
- val messageBox: POMessageBoxStyle? = null,
+ val errorMessageBox: POMessageBoxStyle? = null,
val dialog: PODialogStyle? = null,
+ val stepper: POStepperStyle? = null,
val scanCardButton: POButtonStyle? = null,
val actionsContainer: POActionsContainerStyle? = null,
@ColorRes
diff --git a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/PODynamicCheckoutLauncher.kt b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/PODynamicCheckoutLauncher.kt
index a39f875a3..42acf5cc1 100644
--- a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/PODynamicCheckoutLauncher.kt
+++ b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/PODynamicCheckoutLauncher.kt
@@ -22,7 +22,7 @@ import com.processout.sdk.ui.card.tokenization.delegate.POCardTokenizationEligib
import com.processout.sdk.ui.card.tokenization.delegate.toResponse
import com.processout.sdk.ui.checkout.delegate.*
import com.processout.sdk.ui.core.annotation.ProcessOutInternalApi
-import com.processout.sdk.ui.napm.delegate.PONativeAlternativePaymentEvent
+import com.processout.sdk.ui.napm.delegate.v2.PONativeAlternativePaymentEvent
import com.processout.sdk.ui.savedpaymentmethods.delegate.POSavedPaymentMethodsEvent
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
diff --git a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/delegate/DynamicCheckoutAlternativePaymentDefaultValues.kt b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/delegate/DynamicCheckoutAlternativePaymentDefaultValues.kt
index efb0eafde..c12c065d0 100644
--- a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/delegate/DynamicCheckoutAlternativePaymentDefaultValues.kt
+++ b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/delegate/DynamicCheckoutAlternativePaymentDefaultValues.kt
@@ -2,16 +2,17 @@ package com.processout.sdk.ui.checkout.delegate
import com.processout.sdk.api.dispatcher.POEventDispatcher
import com.processout.sdk.api.model.response.PODynamicCheckoutPaymentMethod
-import com.processout.sdk.api.model.response.PONativeAlternativePaymentMethodDefaultValuesResponse
-import com.processout.sdk.api.model.response.PONativeAlternativePaymentMethodParameter
+import com.processout.sdk.api.model.response.napm.v2.PONativeAlternativePaymentElement
+import com.processout.sdk.ui.napm.delegate.v2.NativeAlternativePaymentDefaultValuesResponse
+import com.processout.sdk.ui.napm.delegate.v2.PONativeAlternativePaymentParameterValue
import java.util.UUID
internal data class DynamicCheckoutAlternativePaymentDefaultValuesRequest(
override val uuid: UUID,
val paymentMethod: PODynamicCheckoutPaymentMethod.AlternativePayment,
- val parameters: List
+ val parameters: List
) : POEventDispatcher.Request
internal fun DynamicCheckoutAlternativePaymentDefaultValuesRequest.toResponse(
- defaultValues: Map
-) = PONativeAlternativePaymentMethodDefaultValuesResponse(uuid, defaultValues)
+ defaultValues: Map
+) = NativeAlternativePaymentDefaultValuesResponse(uuid, defaultValues)
diff --git a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/delegate/PODynamicCheckoutDelegate.kt b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/delegate/PODynamicCheckoutDelegate.kt
index 339cf3d55..28ebe416a 100644
--- a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/delegate/PODynamicCheckoutDelegate.kt
+++ b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/delegate/PODynamicCheckoutDelegate.kt
@@ -6,10 +6,11 @@ import com.processout.sdk.api.model.request.POInvoiceRequest
import com.processout.sdk.api.model.response.POCardIssuerInformation
import com.processout.sdk.api.model.response.PODynamicCheckoutPaymentMethod
import com.processout.sdk.api.model.response.POInvoice
-import com.processout.sdk.api.model.response.PONativeAlternativePaymentMethodParameter
+import com.processout.sdk.api.model.response.napm.v2.PONativeAlternativePaymentElement
import com.processout.sdk.ui.checkout.PODynamicCheckoutConfiguration
import com.processout.sdk.ui.core.annotation.ProcessOutInternalApi
-import com.processout.sdk.ui.napm.delegate.PONativeAlternativePaymentEvent
+import com.processout.sdk.ui.napm.delegate.v2.PONativeAlternativePaymentEvent
+import com.processout.sdk.ui.napm.delegate.v2.PONativeAlternativePaymentParameterValue
import com.processout.sdk.ui.savedpaymentmethods.POSavedPaymentMethodsConfiguration
import com.processout.sdk.ui.savedpaymentmethods.delegate.POSavedPaymentMethodsEvent
@@ -69,14 +70,14 @@ interface PODynamicCheckoutDelegate {
): String? = issuerInformation.scheme
/**
- * Allows to prefill default values for the given parameters during native alternative payment.
- * Return a map where key is a [PONativeAlternativePaymentMethodParameter.key] and value is a custom default value.
+ * Allows to prefill default values for the given [parameters] during native alternative payment.
+ * Return a map of parameter keys to their custom default values.
* It's not mandatory to provide default values for all parameters.
*/
suspend fun defaultValues(
paymentMethod: PODynamicCheckoutPaymentMethod.AlternativePayment,
- parameters: List
- ): Map = emptyMap()
+ parameters: List
+ ): Map = emptyMap()
/**
* Allows to override default alternative payment configuration.
diff --git a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/screen/NativeAlternativePayment.kt b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/screen/NativeAlternativePayment.kt
deleted file mode 100644
index b7396f71b..000000000
--- a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/screen/NativeAlternativePayment.kt
+++ /dev/null
@@ -1,491 +0,0 @@
-package com.processout.sdk.ui.checkout.screen
-
-import androidx.compose.animation.*
-import androidx.compose.animation.core.MutableTransitionState
-import androidx.compose.animation.core.tween
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.focus.FocusRequester
-import androidx.compose.ui.focus.focusRequester
-import androidx.compose.ui.focus.onFocusChanged
-import androidx.compose.ui.graphics.Color
-import androidx.lifecycle.Lifecycle
-import com.processout.sdk.ui.checkout.DynamicCheckoutEvent
-import com.processout.sdk.ui.checkout.DynamicCheckoutEvent.*
-import com.processout.sdk.ui.checkout.screen.DynamicCheckoutScreen.ShortAnimationDurationMillis
-import com.processout.sdk.ui.core.component.POCircularProgressIndicator
-import com.processout.sdk.ui.core.component.PORequestFocus
-import com.processout.sdk.ui.core.component.field.POField
-import com.processout.sdk.ui.core.component.field.POFieldLabels
-import com.processout.sdk.ui.core.component.field.code.POCodeField
-import com.processout.sdk.ui.core.component.field.code.POLabeledCodeField
-import com.processout.sdk.ui.core.component.field.dropdown.PODropdownField
-import com.processout.sdk.ui.core.component.field.dropdown.POLabeledDropdownField
-import com.processout.sdk.ui.core.component.field.radio.POLabeledRadioField
-import com.processout.sdk.ui.core.component.field.radio.PORadioGroup
-import com.processout.sdk.ui.core.component.field.text.POLabeledTextField
-import com.processout.sdk.ui.core.state.POImmutableList
-import com.processout.sdk.ui.napm.NativeAlternativePaymentViewModelState
-import com.processout.sdk.ui.shared.state.FieldState
-
-@Composable
-internal fun NativeAlternativePayment(
- id: String,
- state: NativeAlternativePaymentViewModelState,
- onEvent: (DynamicCheckoutEvent) -> Unit,
- style: DynamicCheckoutScreen.Style
-) {
-// when (state) {
-// is UserInput -> UserInput(id, state, onEvent, style)
-// is Capture -> if (!state.isCaptured) {
-// Capture(id, state, onEvent, style)
-// }
-// else -> {}
-// }
-}
-
-//@Composable
-//private fun UserInput(
-// id: String,
-// state: UserInput,
-// onEvent: (DynamicCheckoutEvent) -> Unit,
-// style: DynamicCheckoutScreen.Style
-//) {
-// Column(
-// verticalArrangement = Arrangement.spacedBy(spacing.extraLarge)
-// ) {
-// val lifecycleEvent = rememberLifecycleEvent()
-// val labelsStyle = remember {
-// POFieldLabels.Style(
-// title = style.label,
-// description = style.errorText
-// )
-// }
-// val isPrimaryActionEnabled = with(state.primaryAction) { enabled && !loading }
-// state.fields.elements.forEach { field ->
-// when (field) {
-// is TextField -> TextField(
-// id = id,
-// state = field.state,
-// onEvent = onEvent,
-// lifecycleEvent = lifecycleEvent,
-// focusedFieldId = state.focusedFieldId,
-// isPrimaryActionEnabled = isPrimaryActionEnabled,
-// fieldStyle = style.field,
-// labelsStyle = labelsStyle,
-// modifier = Modifier.fillMaxWidth()
-// )
-// is CodeField -> CodeField(
-// id = id,
-// state = field.state,
-// onEvent = onEvent,
-// lifecycleEvent = lifecycleEvent,
-// focusedFieldId = state.focusedFieldId,
-// isPrimaryActionEnabled = isPrimaryActionEnabled,
-// fieldStyle = style.codeField,
-// labelsStyle = labelsStyle,
-// horizontalAlignment = Alignment.Start
-// )
-// is RadioField -> RadioField(
-// id = id,
-// state = field.state,
-// onEvent = onEvent,
-// radioGroupStyle = style.radioGroup,
-// labelsStyle = labelsStyle
-// )
-// is DropdownField -> DropdownField(
-// id = id,
-// state = field.state,
-// onEvent = onEvent,
-// fieldStyle = style.field,
-// labelsStyle = labelsStyle,
-// menuStyle = style.dropdownMenu,
-// modifier = Modifier.fillMaxWidth()
-// )
-// }
-// }
-// }
-//}
-
-@Composable
-private fun TextField(
- id: String,
- state: FieldState,
- onEvent: (DynamicCheckoutEvent) -> Unit,
- lifecycleEvent: Lifecycle.Event,
- focusedFieldId: String?,
- isPrimaryActionEnabled: Boolean,
- fieldStyle: POField.Style,
- labelsStyle: POFieldLabels.Style,
- modifier: Modifier = Modifier
-) {
- val focusRequester = remember { FocusRequester() }
- POLabeledTextField(
- value = state.value,
- onValueChange = {
- onEvent(
- FieldValueChanged(
- paymentMethodId = id,
- fieldId = state.id,
- value = state.inputFilter?.filter(it) ?: it
- )
- )
- },
- title = state.label ?: String(),
- description = state.description,
- modifier = modifier
- .focusRequester(focusRequester)
- .onFocusChanged {
- onEvent(
- FieldFocusChanged(
- paymentMethodId = id,
- fieldId = state.id,
- isFocused = it.isFocused
- )
- )
- },
- fieldStyle = fieldStyle,
- labelsStyle = labelsStyle,
- enabled = state.enabled,
- isError = state.isError,
- forceTextDirectionLtr = state.forceTextDirectionLtr,
- placeholder = state.placeholder,
- visualTransformation = state.visualTransformation,
- keyboardOptions = state.keyboardOptions,
- keyboardActions = POField.keyboardActions(
- imeAction = state.keyboardOptions.imeAction,
- actionId = state.keyboardActionId,
- enabled = isPrimaryActionEnabled,
- onClick = {
- onEvent(
- Action(
- actionId = it,
- paymentMethodId = id
- )
- )
- }
- )
- )
- if (state.id == focusedFieldId && lifecycleEvent == Lifecycle.Event.ON_RESUME) {
- PORequestFocus(focusRequester, lifecycleEvent)
- }
-}
-
-@Composable
-private fun CodeField(
- id: String,
- state: FieldState,
- onEvent: (DynamicCheckoutEvent) -> Unit,
- lifecycleEvent: Lifecycle.Event,
- focusedFieldId: String?,
- isPrimaryActionEnabled: Boolean,
- fieldStyle: POField.Style,
- labelsStyle: POFieldLabels.Style,
- horizontalAlignment: Alignment.Horizontal,
- modifier: Modifier = Modifier
-) {
- POLabeledCodeField(
- value = state.value,
- onValueChange = {
- onEvent(
- FieldValueChanged(
- paymentMethodId = id,
- fieldId = state.id,
- value = it
- )
- )
- },
- title = state.label ?: String(),
- description = state.description,
- modifier = modifier
- .onFocusChanged {
- onEvent(
- FieldFocusChanged(
- paymentMethodId = id,
- fieldId = state.id,
- isFocused = it.isFocused
- )
- )
- },
- fieldStyle = fieldStyle,
- labelsStyle = labelsStyle,
- length = state.length ?: POCodeField.LengthMax,
- horizontalAlignment = horizontalAlignment,
- enabled = state.enabled,
- isError = state.isError,
- isFocused = state.id == focusedFieldId,
- lifecycleEvent = lifecycleEvent,
- keyboardOptions = state.keyboardOptions,
- keyboardActions = POField.keyboardActions(
- imeAction = state.keyboardOptions.imeAction,
- actionId = state.keyboardActionId,
- enabled = isPrimaryActionEnabled,
- onClick = {
- onEvent(
- Action(
- actionId = it,
- paymentMethodId = id
- )
- )
- }
- )
- )
-}
-
-@Composable
-private fun RadioField(
- id: String,
- state: FieldState,
- onEvent: (DynamicCheckoutEvent) -> Unit,
- radioGroupStyle: PORadioGroup.Style,
- labelsStyle: POFieldLabels.Style,
- modifier: Modifier = Modifier
-) {
- POLabeledRadioField(
- value = state.value,
- onValueChange = {
- onEvent(
- FieldValueChanged(
- paymentMethodId = id,
- fieldId = state.id,
- value = it
- )
- )
- },
- availableValues = state.availableValues ?: POImmutableList(emptyList()),
- title = state.label ?: String(),
- description = state.description,
- modifier = modifier,
- radioGroupStyle = radioGroupStyle,
- labelsStyle = labelsStyle,
- isError = state.isError
- )
-}
-
-@Composable
-private fun DropdownField(
- id: String,
- state: FieldState,
- onEvent: (DynamicCheckoutEvent) -> Unit,
- fieldStyle: POField.Style,
- labelsStyle: POFieldLabels.Style,
- menuStyle: PODropdownField.MenuStyle,
- modifier: Modifier = Modifier
-) {
- POLabeledDropdownField(
- value = state.value,
- onValueChange = {
- onEvent(
- FieldValueChanged(
- paymentMethodId = id,
- fieldId = state.id,
- value = it
- )
- )
- },
- availableValues = state.availableValues ?: POImmutableList(emptyList()),
- title = state.label ?: String(),
- description = state.description,
- modifier = modifier
- .onFocusChanged {
- onEvent(
- FieldFocusChanged(
- paymentMethodId = id,
- fieldId = state.id,
- isFocused = it.isFocused
- )
- )
- },
- fieldStyle = fieldStyle,
- labelsStyle = labelsStyle,
- menuStyle = menuStyle,
- isError = state.isError,
- placeholder = state.placeholder
- )
-}
-
-//@Composable
-//private fun Capture(
-// id: String,
-// state: Capture,
-// onEvent: (DynamicCheckoutEvent) -> Unit,
-// style: DynamicCheckoutScreen.Style
-//) {
-// AnimatedVisibility(
-// visibleState = remember {
-// MutableTransitionState(initialState = false)
-// .apply { targetState = true }
-// },
-// enter = fadeIn(animationSpec = tween(durationMillis = LongAnimationDurationMillis)),
-// exit = fadeOut(animationSpec = tween(durationMillis = LongAnimationDurationMillis))
-// ) {
-// val withPaddingTop = isMessageShort(state.message) &&
-// state.logoUrl == null && state.title == null &&
-// !state.withProgressIndicator
-// Column(
-// modifier = Modifier.conditional(
-// condition = withPaddingTop,
-// modifier = { padding(top = spacing.extraLarge) }
-// ),
-// verticalArrangement = Arrangement.spacedBy(spacing.extraLarge),
-// horizontalAlignment = Alignment.CenterHorizontally
-// ) {
-// CaptureHeader(state, style)
-// if (state.withProgressIndicator) {
-// AnimatedProgressIndicator(style.progressIndicatorColor)
-// }
-// AndroidTextView(
-// text = state.message,
-// style = style.bodyText,
-// modifier = Modifier.fillMaxWidth(),
-// gravity = messageGravity(state.message),
-// selectable = true,
-// linksClickable = true
-// )
-// var showImage by remember { mutableStateOf(state.image != null) }
-// if (showImage) {
-// when (state.image) {
-// is Image.Url -> AsyncImage(
-// model = state.image.value,
-// contentDescription = null,
-// modifier = Modifier.requiredSize(
-// width = CaptureImageWidth,
-// height = CaptureImageHeight
-// ),
-// alignment = Alignment.Center,
-// contentScale = ContentScale.Fit,
-// onError = {
-// showImage = false
-// }
-// )
-// is Image.Bitmap -> {
-// val bitmap = state.image.value
-// Image(
-// bitmap = remember(bitmap) { bitmap.asImageBitmap() },
-// contentDescription = null,
-// modifier = Modifier.requiredSize(
-// width = CaptureImageWidth,
-// height = CaptureImageHeight
-// ),
-// alignment = Alignment.Center,
-// contentScale = ContentScale.Fit
-// )
-// }
-// else -> {}
-// }
-// }
-// Column(
-// verticalArrangement = Arrangement.spacedBy(spacing.small)
-// ) {
-// state.primaryAction?.let { action ->
-// POButton(
-// text = action.text,
-// onClick = {
-// onEvent(
-// Action(
-// actionId = action.id,
-// paymentMethodId = id
-// )
-// )
-// },
-// modifier = Modifier
-// .fillMaxWidth()
-// .requiredHeightIn(min = dimensions.interactiveComponentMinSize),
-// style = style.actionsContainer.primary,
-// icon = action.icon
-// )
-// }
-// state.saveBarcodeAction?.let { action ->
-// POButton(
-// text = action.text,
-// onClick = {
-// onEvent(
-// Action(
-// actionId = action.id,
-// paymentMethodId = id
-// )
-// )
-// },
-// modifier = Modifier
-// .fillMaxWidth()
-// .requiredHeightIn(min = dimensions.interactiveComponentMinSize),
-// style = style.actionsContainer.secondary,
-// icon = action.icon
-// )
-// }
-// }
-// state.confirmationDialog?.let { dialog ->
-// PODialog(
-// title = dialog.title,
-// message = dialog.message,
-// confirmActionText = dialog.confirmActionText,
-// dismissActionText = dialog.dismissActionText,
-// onConfirm = {
-// onEvent(
-// DialogAction(
-// actionId = dialog.id,
-// paymentMethodId = id,
-// isConfirmed = true
-// )
-// )
-// },
-// onDismiss = {
-// onEvent(
-// DialogAction(
-// actionId = dialog.id,
-// paymentMethodId = id,
-// isConfirmed = false
-// )
-// )
-// },
-// style = style.dialog
-// )
-// }
-// }
-// }
-//}
-
-//@Composable
-//private fun CaptureHeader(
-// state: Capture,
-// style: DynamicCheckoutScreen.Style
-//) {
-// var showLogo by remember { mutableStateOf(true) }
-// if (showLogo) {
-// AsyncImage(
-// model = state.logoUrl,
-// contentDescription = null,
-// modifier = Modifier.requiredHeight(CaptureLogoHeight),
-// contentScale = ContentScale.FillHeight,
-// onError = {
-// showLogo = false
-// }
-// )
-// } else if (state.title != null) {
-// with(style.regularPayment.title) {
-// POText(
-// text = state.title,
-// color = color,
-// style = textStyle
-// )
-// }
-// }
-//}
-
-@Composable
-private fun AnimatedProgressIndicator(
- progressIndicatorColor: Color
-) {
- AnimatedVisibility(
- visibleState = remember {
- MutableTransitionState(initialState = false)
- .apply { targetState = true }
- },
- enter = expandVertically() + fadeIn(animationSpec = tween(durationMillis = ShortAnimationDurationMillis)),
- exit = shrinkVertically() + fadeOut(animationSpec = tween(durationMillis = ShortAnimationDurationMillis))
- ) {
- POCircularProgressIndicator.Large(color = progressIndicatorColor)
- }
-}
diff --git a/ui/src/main/kotlin/com/processout/sdk/ui/napm/screen/NativeAlternativePaymentContent.kt b/ui/src/main/kotlin/com/processout/sdk/ui/napm/screen/NativeAlternativePaymentContent.kt
index 4f3df958b..9dc62ac22 100644
--- a/ui/src/main/kotlin/com/processout/sdk/ui/napm/screen/NativeAlternativePaymentContent.kt
+++ b/ui/src/main/kotlin/com/processout/sdk/ui/napm/screen/NativeAlternativePaymentContent.kt
@@ -43,7 +43,6 @@ import com.processout.sdk.ui.napm.NativeAlternativePaymentViewModelState.*
import com.processout.sdk.ui.napm.NativeAlternativePaymentViewModelState.Element.*
import com.processout.sdk.ui.napm.PONativeAlternativePaymentConfiguration
import com.processout.sdk.ui.napm.screen.NativeAlternativePaymentScreen.ContentTransitionSpec
-import com.processout.sdk.ui.napm.screen.NativeAlternativePaymentScreen.LabeledContentStyle
import com.processout.sdk.ui.napm.screen.NativeAlternativePaymentScreen.SuccessStyle
import com.processout.sdk.ui.shared.component.AndroidTextView
import com.processout.sdk.ui.shared.component.rememberLifecycleEvent
@@ -536,7 +535,7 @@ private fun PhoneNumberField(
@Composable
private fun CopyableMessage(
message: CopyableMessage,
- style: LabeledContentStyle,
+ style: POLabeledContent.Style,
modifier: Modifier = Modifier
) {
POLabeledContent(
diff --git a/ui/src/main/kotlin/com/processout/sdk/ui/napm/screen/NativeAlternativePaymentScreen.kt b/ui/src/main/kotlin/com/processout/sdk/ui/napm/screen/NativeAlternativePaymentScreen.kt
index 98a5b9ed6..e074d852e 100644
--- a/ui/src/main/kotlin/com/processout/sdk/ui/napm/screen/NativeAlternativePaymentScreen.kt
+++ b/ui/src/main/kotlin/com/processout/sdk/ui/napm/screen/NativeAlternativePaymentScreen.kt
@@ -42,7 +42,6 @@ import com.processout.sdk.ui.core.component.stepper.POStepper
import com.processout.sdk.ui.core.state.POActionState
import com.processout.sdk.ui.core.state.POImmutableList
import com.processout.sdk.ui.core.style.POAxis
-import com.processout.sdk.ui.core.style.POLabeledContentStyle
import com.processout.sdk.ui.core.theme.ProcessOutTheme
import com.processout.sdk.ui.core.theme.ProcessOutTheme.colors
import com.processout.sdk.ui.core.theme.ProcessOutTheme.shapes
@@ -283,7 +282,7 @@ internal object NativeAlternativePaymentScreen {
val title: POText.Style,
val bodyText: AndroidTextView.Style,
val message: POText.Style,
- val labeledContent: LabeledContentStyle,
+ val labeledContent: POLabeledContent.Style,
val groupedContent: POGroupedContent.Style,
val field: POField.Style,
val codeField: POField.Style,
@@ -301,13 +300,6 @@ internal object NativeAlternativePaymentScreen {
val dragHandleColor: Color
)
- @Immutable
- data class LabeledContentStyle(
- val label: POText.Style,
- val text: POText.Style,
- val copyButton: POButton.Style
- )
-
@Immutable
data class SuccessStyle(
val title: POText.Style,
@@ -337,9 +329,11 @@ internal object NativeAlternativePaymentScreen {
POText.custom(style = it)
} ?: POText.Style(
color = colors.text.secondary,
- textStyle = typography.s15()
+ textStyle = typography.s14()
),
- labeledContent = custom?.labeledContent?.custom() ?: defaultLabeledContent,
+ labeledContent = custom?.labeledContent?.let {
+ POLabeledContent.custom(style = it)
+ } ?: POLabeledContent.default,
groupedContent = custom?.groupedContent?.let {
POGroupedContent.custom(style = it)
} ?: POGroupedContent.default,
@@ -386,28 +380,7 @@ internal object NativeAlternativePaymentScreen {
)
}
- private val defaultLabeledContent: LabeledContentStyle
- @Composable get() = LabeledContentStyle(
- label = POText.Style(
- color = colors.text.placeholder,
- textStyle = typography.s12(FontWeight.Medium)
- ),
- text = POText.Style(
- color = colors.text.primary,
- textStyle = typography.s15(FontWeight.Medium)
- ),
- copyButton = POCopyButton.default
- )
-
- @Composable
- private fun POLabeledContentStyle.custom() =
- LabeledContentStyle(
- label = POText.custom(style = label),
- text = POText.custom(style = text),
- copyButton = defaultLabeledContent.copyButton
- )
-
- private val defaultSuccess: SuccessStyle
+ val defaultSuccess: SuccessStyle
@Composable get() = SuccessStyle(
title = POText.Style(
color = colors.text.primary,