Updated on 2026-08-14
This commit is contained in:
parent
7e02e72a40
commit
c2e67ba6bc
41 changed files with 863 additions and 119 deletions
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.feature.wallet.child.wallet.model.intents
|
||||
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
import com.tangem.core.res.R
|
||||
|
|
@ -14,6 +15,7 @@ import com.tangem.domain.pay.repository.OnboardingRepository
|
|||
import com.tangem.domain.pay.usecase.ProduceTangemPayInitialDataUseCase
|
||||
import com.tangem.domain.pay.usecase.TangemPayMainScreenCustomerInfoUseCase
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.TangemPayHideOnboardingStateTransformer
|
||||
import com.tangem.features.tangempay.TangemPayFeatureToggles
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
|
@ -29,6 +31,10 @@ internal interface TangemPayIntents {
|
|||
fun onIssuingFailedClicked()
|
||||
|
||||
fun onPaySupportClick()
|
||||
|
||||
fun onOnboardingBannerClick(userWalletId: UserWalletId)
|
||||
|
||||
fun onOnboardingBannerCloseClick(userWalletId: UserWalletId)
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
|
|
@ -115,4 +121,15 @@ internal class TangemPayClickIntentsImplementor @Inject constructor(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onOnboardingBannerClick(userWalletId: UserWalletId) {
|
||||
router.openTangemPayOnboarding(mode = AppRoute.TangemPayOnboarding.Mode.FromBannerOnMain(userWalletId))
|
||||
}
|
||||
|
||||
override fun onOnboardingBannerCloseClick(userWalletId: UserWalletId) {
|
||||
modelScope.launch {
|
||||
stateHolder.update(transformer = TangemPayHideOnboardingStateTransformer(userWalletId))
|
||||
onboardingRepository.setHideMainOnboardingBanner(userWalletId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -111,14 +111,8 @@ internal class DefaultWalletRouter @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
override fun openTangemPayOnboarding(userWalletId: UserWalletId) {
|
||||
router.push(
|
||||
AppRoute.TangemPayOnboarding(
|
||||
AppRoute.TangemPayOnboarding.Mode.ContinueOnboarding(
|
||||
userWalletId = userWalletId,
|
||||
),
|
||||
),
|
||||
)
|
||||
override fun openTangemPayOnboarding(mode: AppRoute.TangemPayOnboarding.Mode) {
|
||||
router.push(route = AppRoute.TangemPayOnboarding(mode = mode))
|
||||
}
|
||||
|
||||
override fun openTangemPayDetails(userWalletId: UserWalletId, config: TangemPayDetailsConfig) {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.feature.wallet.presentation.router
|
|||
|
||||
import androidx.compose.runtime.Stable
|
||||
import com.arkivanov.decompose.router.slot.SlotNavigation
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.domain.models.TokenReceiveConfig
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
|
|
@ -63,7 +64,7 @@ internal interface InnerWalletRouter {
|
|||
|
||||
fun openTokenReceiveBottomSheet(tokenReceiveConfig: TokenReceiveConfig)
|
||||
|
||||
fun openTangemPayOnboarding(userWalletId: UserWalletId)
|
||||
fun openTangemPayOnboarding(mode: AppRoute.TangemPayOnboarding.Mode)
|
||||
|
||||
fun openTangemPayDetails(userWalletId: UserWalletId, config: TangemPayDetailsConfig)
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,11 @@ internal sealed class TangemPayState {
|
|||
|
||||
data object Loading : TangemPayState()
|
||||
|
||||
data class OnboardingBanner(
|
||||
val onClick: () -> Unit,
|
||||
val closeOnClick: () -> Unit,
|
||||
) : TangemPayState()
|
||||
|
||||
data class Progress(
|
||||
val title: TextReference,
|
||||
val description: TextReference,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.transformers
|
||||
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
|
||||
internal class TangemPayHideOnboardingStateTransformer(
|
||||
userWalletId: UserWalletId,
|
||||
) : WalletStateTransformer(userWalletId) {
|
||||
|
||||
override fun transform(prevState: WalletState): WalletState {
|
||||
return if (prevState is WalletState.MultiCurrency.Content) {
|
||||
prevState.copy(tangemPayState = TangemPayState.Empty)
|
||||
} else {
|
||||
prevState
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.transformers
|
||||
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
|
||||
internal class TangemPayOnboardingBannerStateTransformer(
|
||||
userWalletId: UserWalletId,
|
||||
private val onClick: (UserWalletId) -> Unit,
|
||||
private val closeOnClick: (UserWalletId) -> Unit,
|
||||
) : WalletStateTransformer(userWalletId) {
|
||||
|
||||
override fun transform(prevState: WalletState): WalletState {
|
||||
return if (prevState is WalletState.MultiCurrency.Content) {
|
||||
prevState.copy(
|
||||
tangemPayState = TangemPayState.OnboardingBanner(
|
||||
onClick = { onClick(userWalletId) },
|
||||
closeOnClick = { closeOnClick(userWalletId) },
|
||||
),
|
||||
)
|
||||
} else {
|
||||
prevState
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.subscribers
|
||||
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.pay.model.MainCustomerInfoContentState
|
||||
|
|
@ -79,6 +80,13 @@ internal class TangemPayMainSubscriber @AssistedInject constructor(
|
|||
updateTangemPay(data = state.info, userWalletId = userWalletId)
|
||||
analytics.send(customerInfo = state.info)
|
||||
}
|
||||
is MainCustomerInfoContentState.OnboardingBanner -> stateController.update(
|
||||
transformer = TangemPayOnboardingBannerStateTransformer(
|
||||
userWalletId = userWalletId,
|
||||
onClick = clickIntents::onOnboardingBannerClick,
|
||||
closeOnClick = clickIntents::onOnboardingBannerCloseClick,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -91,7 +99,11 @@ internal class TangemPayMainSubscriber @AssistedInject constructor(
|
|||
userWalletId = userWalletId,
|
||||
value = data,
|
||||
cardFrozenState = cardFrozenState,
|
||||
onClickKyc = { innerWalletRouter.openTangemPayOnboarding(userWalletId) },
|
||||
onClickKyc = {
|
||||
innerWalletRouter.openTangemPayOnboarding(
|
||||
mode = AppRoute.TangemPayOnboarding.Mode.ContinueOnboarding(userWalletId),
|
||||
)
|
||||
},
|
||||
onIssuingCard = clickIntents::onIssuingCardClicked,
|
||||
onIssuingFailed = clickIntents::onIssuingFailedClicked,
|
||||
openDetails = { config ->
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ internal fun TangemPayMainScreenBlock(state: TangemPayState, isBalanceHidden: Bo
|
|||
is TangemPayState.RefreshNeeded -> TangemPayRefreshBlock(state, modifier)
|
||||
is TangemPayState.TemporaryUnavailable -> TangemPayUnavailableBlock(state, modifier)
|
||||
is TangemPayState.FailedIssue -> TangemPayFailedIssueState(state, modifier)
|
||||
is TangemPayState.OnboardingBanner -> TangemPayOnboardingBanner(state, modifier)
|
||||
TangemPayState.Loading -> TangemPayLoadingScreenBlock(modifier)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,129 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.ui.components.visa
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.IntrinsicSize
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.SpacerH
|
||||
import com.tangem.core.ui.components.SpacerH4
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
|
||||
|
||||
private const val GRADIENT_START_COLOR = 0xFF252934
|
||||
private const val GRADIENT_END_COLOR = 0xFF12141E
|
||||
private const val GRADIENT_OFFSET_X = 0f
|
||||
private const val GRADIENT_OFFSET_Y = 80F
|
||||
private const val GRADIENT_RADIUS = 200F
|
||||
|
||||
@Composable
|
||||
internal fun TangemPayOnboardingBanner(state: TangemPayState.OnboardingBanner, modifier: Modifier = Modifier) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.clip(TangemTheme.shapes.roundedCornersXMedium)
|
||||
.background(
|
||||
brush = Brush.radialGradient(
|
||||
colors = listOf(Color(GRADIENT_START_COLOR), Color(GRADIENT_END_COLOR)),
|
||||
center = Offset(GRADIENT_OFFSET_X, GRADIENT_OFFSET_Y),
|
||||
radius = GRADIENT_RADIUS,
|
||||
),
|
||||
)
|
||||
.clickable(onClick = state.onClick),
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(IntrinsicSize.Min)
|
||||
.padding(horizontal = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(R.drawable.img_tangem_pay_onboarding_banner),
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 8.dp)
|
||||
.width(55.dp)
|
||||
.height(95.dp)
|
||||
.offset(y = 10.dp),
|
||||
)
|
||||
|
||||
SpacerH4()
|
||||
|
||||
Column(
|
||||
modifier = Modifier.weight(1f),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
) {
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.tangempay_onboarding_banner_title),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.constantWhite,
|
||||
)
|
||||
|
||||
SpacerH(6.dp)
|
||||
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.tangempay_onboarding_banner_description),
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier.fillMaxHeight(),
|
||||
contentAlignment = Alignment.TopEnd,
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier
|
||||
.clip(TangemTheme.shapes.roundedCornersXMedium)
|
||||
.clickable(onClick = state.closeOnClick)
|
||||
.padding(4.dp)
|
||||
.padding(top = 12.dp)
|
||||
.size(12.dp),
|
||||
painter = painterResource(id = R.drawable.ic_close_24),
|
||||
colorFilter = ColorFilter.tint(TangemTheme.colors.icon.inactive),
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun PreviewTangemOnboardingBanner() {
|
||||
TangemThemePreview {
|
||||
TangemPayOnboardingBanner(
|
||||
TangemPayState.OnboardingBanner(
|
||||
onClick = {},
|
||||
closeOnClick = {},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue