Updated on 2026-08-14
This commit is contained in:
parent
c40326c1c9
commit
894b3fdc71
6 changed files with 112 additions and 30 deletions
|
|
@ -1,6 +1,8 @@
|
|||
package com.tangem.features.onboarding.v2.common.analytics
|
||||
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
|
||||
sealed class OnboardingEvent(
|
||||
category: String,
|
||||
|
|
@ -46,6 +48,11 @@ sealed class OnboardingEvent(
|
|||
object ScreenOpened : Topup("Activation Screen Opened")
|
||||
|
||||
object ButtonShowWalletAddress : Topup("Button - Show the Wallet Address")
|
||||
|
||||
class ButtonBuyCrypto(currency: CryptoCurrency) : Topup(
|
||||
event = "Button - Buy Crypto",
|
||||
params = mapOf(AnalyticsParam.CURRENCY to currency.symbol),
|
||||
)
|
||||
}
|
||||
|
||||
sealed class Backup(
|
||||
|
|
|
|||
|
|
@ -4,20 +4,30 @@ import com.tangem.core.analytics.Analytics
|
|||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.navigation.share.ShareManager
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.core.ui.clipboard.ClipboardManager
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.tokenreceive.TokenReceiveBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.tokenreceive.mapToAddressModels
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.domain.exchange.RampStateManager
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.onramp.GetLegacyTopUpUrlUseCase
|
||||
import com.tangem.domain.tokens.FetchCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.tokens.model.NetworkAddress
|
||||
import com.tangem.domain.tokens.model.analytics.TokenReceiveAnalyticsEvent
|
||||
import com.tangem.domain.wallets.builder.UserWalletBuilder
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.features.onboarding.v2.common.analytics.OnboardingEvent
|
||||
import com.tangem.features.onboarding.v2.note.impl.child.topup.OnboardingNoteTopUpComponent
|
||||
import com.tangem.features.onboarding.v2.note.impl.child.topup.ui.state.OnboardingNoteTopUpUM
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
|
@ -32,6 +42,9 @@ internal class OnboardingNoteTopUpModel @Inject constructor(
|
|||
private val userWalletBuilderFactory: UserWalletBuilder.Factory,
|
||||
private val getLegacyTopUpUrlUseCase: GetLegacyTopUpUrlUseCase,
|
||||
private val urlOpener: UrlOpener,
|
||||
private val clipboardManager: ClipboardManager,
|
||||
private val shareManager: ShareManager,
|
||||
private val rampStateManager: RampStateManager,
|
||||
) : Model() {
|
||||
|
||||
private val params = paramsContainer.require<OnboardingNoteTopUpComponent.Params>()
|
||||
|
|
@ -44,6 +57,7 @@ internal class OnboardingNoteTopUpModel @Inject constructor(
|
|||
onRefreshBalanceClick = ::refreshBalance,
|
||||
onBuyCryptoClick = ::onBuyCryptoClick,
|
||||
onShowWalletAddressClick = ::onShowWalletAddressClick,
|
||||
onDismissBottomSheet = ::onDismissBottomSheet,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -79,10 +93,23 @@ internal class OnboardingNoteTopUpModel @Inject constructor(
|
|||
urlOpener.openUrl(it)
|
||||
}
|
||||
}
|
||||
Analytics.send(OnboardingEvent.Topup.ButtonBuyCrypto(cryptoCurrencyStatus.currency))
|
||||
}
|
||||
|
||||
private fun onShowWalletAddressClick() {
|
||||
// TODO [REDACTED_TASK_KEY]
|
||||
val currencyStatus = params.childParams.commonState.value.cryptoCurrencyStatus ?: return
|
||||
val networkAddress = currencyStatus.value.networkAddress ?: return
|
||||
|
||||
_uiState.update {
|
||||
it.copy(addressBottomSheetConfig = createReceiveBS(currencyStatus, networkAddress))
|
||||
}
|
||||
Analytics.send(OnboardingEvent.Topup.ButtonShowWalletAddress)
|
||||
}
|
||||
|
||||
private fun onDismissBottomSheet() {
|
||||
_uiState.update {
|
||||
it.copy(addressBottomSheetConfig = null)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun createUserWalletIfNull() {
|
||||
|
|
@ -110,9 +137,13 @@ internal class OnboardingNoteTopUpModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun applyCryptoCurrencyStatusToState(status: CryptoCurrencyStatus) {
|
||||
if (commonState.value.cryptoCurrencyStatus == null) {
|
||||
loadAvailableForBuy(status)
|
||||
}
|
||||
commonState.update {
|
||||
it.copy(cryptoCurrencyStatus = status)
|
||||
}
|
||||
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
amountToCreateAccount = (status.value as? CryptoCurrencyStatus.NoAccount)
|
||||
|
|
@ -132,7 +163,7 @@ internal class OnboardingNoteTopUpModel @Inject constructor(
|
|||
decimals = status.currency.decimals,
|
||||
)
|
||||
},
|
||||
),
|
||||
).orEmpty(),
|
||||
isTopUpDataLoading = status.value.networkAddress == null,
|
||||
)
|
||||
}
|
||||
|
|
@ -144,6 +175,48 @@ internal class OnboardingNoteTopUpModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun loadAvailableForBuy(cryptoCurrencyStatus: CryptoCurrencyStatus) {
|
||||
val userWalletId = userWallet?.walletId ?: return
|
||||
|
||||
modelScope.launch {
|
||||
val availableForBuy = rampStateManager.availableForBuy(
|
||||
scanResponse = scanResponse,
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrency = cryptoCurrencyStatus.currency,
|
||||
)
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
availableForBuy = availableForBuy,
|
||||
availableForBuyLoading = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createReceiveBS(currencyStatus: CryptoCurrencyStatus, networkAddress: NetworkAddress) =
|
||||
TangemBottomSheetConfig(
|
||||
isShown = true,
|
||||
onDismissRequest = uiState.value.onDismissBottomSheet,
|
||||
content = TokenReceiveBottomSheetConfig(
|
||||
name = currencyStatus.currency.name,
|
||||
symbol = currencyStatus.currency.symbol,
|
||||
network = currencyStatus.currency.network.name,
|
||||
addresses = networkAddress.availableAddresses
|
||||
.mapToAddressModels(currencyStatus.currency)
|
||||
.toImmutableList(),
|
||||
showMemoDisclaimer =
|
||||
currencyStatus.currency.network.transactionExtrasType != Network.TransactionExtrasType.NONE,
|
||||
onCopyClick = {
|
||||
Analytics.send(TokenReceiveAnalyticsEvent.ButtonCopyAddress(currencyStatus.currency.symbol))
|
||||
clipboardManager.setText(text = it, isSensitive = true)
|
||||
},
|
||||
onShareClick = {
|
||||
Analytics.send(TokenReceiveAnalyticsEvent.ButtonShareAddress(currencyStatus.currency.symbol))
|
||||
shareManager.shareText(text = it)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
private suspend fun createUserWallet(scanResponse: ScanResponse): UserWallet {
|
||||
return requireNotNull(
|
||||
value = userWalletBuilderFactory.create(scanResponse = scanResponse).build(),
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import com.tangem.features.onboarding.v2.impl.R
|
|||
|
||||
@Composable
|
||||
fun OnboardingNoteTopUpHeader(
|
||||
balance: String?,
|
||||
balance: String,
|
||||
cardArtworkUrl: String?,
|
||||
isRefreshing: Boolean,
|
||||
onRefreshBalanceClick: () -> Unit,
|
||||
|
|
@ -58,7 +58,7 @@ fun OnboardingNoteTopUpHeader(
|
|||
)
|
||||
SpacerH8()
|
||||
Text(
|
||||
text = balance.orEmpty(),
|
||||
text = balance,
|
||||
style = TangemTheme.typography.h2,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
textAlign = TextAlign.Center,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
package com.tangem.features.onboarding.v2.note.impl.child.topup.ui
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
|
|
@ -11,9 +11,9 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.PrimaryButtonIconEnd
|
||||
import com.tangem.core.ui.components.PrimaryButton
|
||||
import com.tangem.core.ui.components.SecondaryButton
|
||||
import com.tangem.core.ui.components.SpacerH8
|
||||
import com.tangem.core.ui.components.bottomsheets.tokenreceive.TokenReceiveBottomSheet
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
|
|
@ -66,14 +66,10 @@ fun OnboardingNoteTopUp(state: OnboardingNoteTopUpUM, modifier: Modifier = Modif
|
|||
)
|
||||
}
|
||||
|
||||
if (state.isTopUpDataLoading) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier
|
||||
.padding(all = 32.dp)
|
||||
.size(36.dp),
|
||||
)
|
||||
} else {
|
||||
BottomButtons(state)
|
||||
BottomButtons(state)
|
||||
|
||||
state.addressBottomSheetConfig?.let { config ->
|
||||
TokenReceiveBottomSheet(config = config)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -81,32 +77,33 @@ fun OnboardingNoteTopUp(state: OnboardingNoteTopUpUM, modifier: Modifier = Modif
|
|||
@Composable
|
||||
private fun BottomButtons(state: OnboardingNoteTopUpUM) {
|
||||
if (state.availableForBuy) {
|
||||
PrimaryButtonIconEnd(
|
||||
PrimaryButton(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.padding(start = 16.dp, end = 16.dp, bottom = 8.dp)
|
||||
.fillMaxWidth(),
|
||||
iconResId = R.drawable.ic_tangem_24,
|
||||
text = stringResourceSafe(R.string.onboarding_top_up_button_but_crypto),
|
||||
onClick = state.onBuyCryptoClick,
|
||||
)
|
||||
SpacerH8()
|
||||
SecondaryButton(
|
||||
modifier = Modifier
|
||||
.padding(start = 16.dp, end = 16.dp, bottom = 16.dp)
|
||||
.fillMaxWidth(),
|
||||
text = stringResourceSafe(R.string.onboarding_top_up_button_show_wallet_address),
|
||||
onClick = state.onShowWalletAddressClick,
|
||||
)
|
||||
} else {
|
||||
PrimaryButtonIconEnd(
|
||||
PrimaryButton(
|
||||
modifier = Modifier
|
||||
.padding(start = 16.dp, end = 16.dp, bottom = 16.dp)
|
||||
.fillMaxWidth(),
|
||||
iconResId = R.drawable.ic_tangem_24,
|
||||
text = stringResourceSafe(R.string.onboarding_button_receive_crypto),
|
||||
onClick = state.onShowWalletAddressClick,
|
||||
)
|
||||
}
|
||||
AnimatedVisibility(visible = !state.availableForBuyLoading) {
|
||||
if (state.availableForBuy) {
|
||||
SecondaryButton(
|
||||
modifier = Modifier
|
||||
.padding(start = 16.dp, end = 16.dp, bottom = 16.dp)
|
||||
.fillMaxWidth(),
|
||||
text = stringResourceSafe(R.string.onboarding_top_up_button_show_wallet_address),
|
||||
onClick = state.onShowWalletAddressClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
|
|
@ -1,13 +1,18 @@
|
|||
package com.tangem.features.onboarding.v2.note.impl.child.topup.ui.state
|
||||
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
|
||||
data class OnboardingNoteTopUpUM(
|
||||
val cardArtworkUrl: String? = null,
|
||||
val availableForBuy: Boolean = true,
|
||||
val balance: String? = null,
|
||||
val availableForBuy: Boolean = false,
|
||||
val availableForBuyLoading: Boolean = true,
|
||||
val balance: String = "–",
|
||||
val isRefreshing: Boolean = false,
|
||||
val isTopUpDataLoading: Boolean = true,
|
||||
val amountToCreateAccount: String? = null,
|
||||
val addressBottomSheetConfig: TangemBottomSheetConfig? = null,
|
||||
val onBuyCryptoClick: () -> Unit = {},
|
||||
val onShowWalletAddressClick: () -> Unit = {},
|
||||
val onRefreshBalanceClick: () -> Unit = {},
|
||||
val onDismissBottomSheet: () -> Unit = {},
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue