Updated on 2026-08-14
This commit is contained in:
parent
990b06c3ed
commit
0ce75f1445
13 changed files with 154 additions and 2 deletions
|
|
@ -140,6 +140,7 @@ internal class ChildFactory @Inject constructor(
|
|||
AppRoute.ManageTokens.Source.SETTINGS -> ManageTokensSource.SETTINGS
|
||||
AppRoute.ManageTokens.Source.STORIES -> ManageTokensSource.STORIES
|
||||
AppRoute.ManageTokens.Source.ACCOUNT -> ManageTokensSource.ACCOUNT
|
||||
AppRoute.ManageTokens.Source.TOKEN_SYNC_BANNER -> ManageTokensSource.TOKEN_SYNC_BANNER
|
||||
}
|
||||
|
||||
val mode = route.accountId?.let { ManageTokensMode.Account(it) } ?: ManageTokensMode.None
|
||||
|
|
|
|||
|
|
@ -139,6 +139,7 @@ sealed class AppRoute(val path: String) : Route {
|
|||
STORIES,
|
||||
SETTINGS,
|
||||
ACCOUNT,
|
||||
TOKEN_SYNC_BANNER,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -140,6 +140,8 @@ object PreferencesKeys {
|
|||
|
||||
val HAS_HAD_FIRST_TOP_UP_KEY by lazy { stringPreferencesKey(name = "hasHadFirstTopUp") }
|
||||
|
||||
val PENDING_DISCOVERY_SYNC_KEY by lazy { stringPreferencesKey(name = "pendingDiscoverySync") }
|
||||
|
||||
// region Notifications
|
||||
val NOTIFICATIONS_APPLICATION_ID_KEY by lazy { stringPreferencesKey(name = "notificationsApplicationId") }
|
||||
|
||||
|
|
|
|||
|
|
@ -692,6 +692,9 @@
|
|||
<string name="initial_message_scan_header">Tap to scan</string>
|
||||
<string name="initial_message_sign_header">Tap to sign</string>
|
||||
<string name="initial_message_tap_header">Tap the card or ring</string>
|
||||
<string name="initial_wallet_sync_banner_description">Your wallet is synced and ready.\nSome tokens missing?</string>
|
||||
<string name="initial_wallet_sync_banner_title">Wallet successfully imported</string>
|
||||
<string name="initial_wallet_sync_restore_progress">Restoring %d%</string>
|
||||
<string name="key_invalidated_warning_description">You have updated biometrics, scan your card or ring to enter</string>
|
||||
<string name="koinos_insufficient_balance_to_send_koin_description">Your balance should be higher than the fee value to make a transfer</string>
|
||||
<string name="koinos_insufficient_balance_to_send_koin_title">Not enough balance</string>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
package com.tangem.domain.tokens.model.tokensync
|
||||
|
||||
import java.math.BigDecimal
|
||||
|
||||
data class DiscoveredToken(
|
||||
val contractAddress: String?,
|
||||
val symbol: String,
|
||||
val name: String,
|
||||
val decimals: Int,
|
||||
val amount: BigDecimal,
|
||||
val isNativeToken: Boolean,
|
||||
val currencyId: String?,
|
||||
val networkId: String,
|
||||
)
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package com.tangem.domain.tokens.model.tokensync
|
||||
|
||||
sealed class TokenSyncProgress {
|
||||
|
||||
data object Idle : TokenSyncProgress()
|
||||
|
||||
data class InProgress(
|
||||
val completedNetworks: Int,
|
||||
val totalNetworks: Int,
|
||||
) : TokenSyncProgress() {
|
||||
val progressPercent: Int
|
||||
get() = if (totalNetworks > 0) {
|
||||
completedNetworks * 100 / totalNetworks
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
data object Completed : TokenSyncProgress()
|
||||
|
||||
data class Error(val cause: Throwable) : TokenSyncProgress()
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package com.tangem.domain.tokens.repository
|
||||
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.tokens.model.tokensync.TokenSyncProgress
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface TokenSyncRepository {
|
||||
|
||||
suspend fun runSync(userWalletId: UserWalletId)
|
||||
|
||||
suspend fun getPendingSyncWalletIds(): List<UserWalletId>
|
||||
|
||||
fun observeSyncProgress(userWalletId: UserWalletId): Flow<TokenSyncProgress>
|
||||
|
||||
fun acknowledgeCompletion(userWalletId: UserWalletId)
|
||||
|
||||
suspend fun clearPendingFlag(userWalletId: UserWalletId)
|
||||
|
||||
suspend fun getDiscoveredCurrencies(userWalletId: UserWalletId): List<CryptoCurrency>
|
||||
|
||||
suspend fun clearDiscoveredTokens(userWalletId: UserWalletId)
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ enum class ManageTokensSource(val analyticsName: String) {
|
|||
ONBOARDING(analyticsName = "Onboarding"),
|
||||
SETTINGS(analyticsName = "Wallet Settings"),
|
||||
ACCOUNT(analyticsName = "Account"),
|
||||
TOKEN_SYNC_BANNER(analyticsName = "Token Sync Banner"),
|
||||
SEND_VIA_SWAP(analyticsName = "SendViaSwap"),
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ internal class WalletWarningsAnalyticsSender @Inject constructor(
|
|||
is WalletNotification.Warning.TangemPayRefreshNeeded -> null
|
||||
is WalletNotification.Warning.TangemPayUnreachable -> null
|
||||
is WalletNotification.UpgradeHotWalletPromo -> null
|
||||
is WalletNotification.TokenSyncCompleted -> null
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,4 +8,5 @@ data class WalletAdditionalInfo(
|
|||
val hideable: Boolean,
|
||||
val content: TextReference,
|
||||
val isHotBackedUp: Boolean = false,
|
||||
val shouldShowProgress: Boolean = false,
|
||||
)
|
||||
|
|
@ -463,4 +463,21 @@ sealed class WalletNotification(val config: NotificationConfig) {
|
|||
iconSize = 72.dp,
|
||||
),
|
||||
)
|
||||
|
||||
data class TokenSyncCompleted(
|
||||
val onCloseClick: () -> Unit,
|
||||
val onManageTokensClick: () -> Unit,
|
||||
) : WalletNotification(
|
||||
config = NotificationConfig(
|
||||
title = resourceReference(R.string.initial_wallet_sync_banner_title),
|
||||
subtitle = resourceReference(R.string.initial_wallet_sync_banner_description),
|
||||
iconResId = R.drawable.ic_check_circle_24,
|
||||
iconTint = IconTint.Accent,
|
||||
onCloseClick = onCloseClick,
|
||||
buttonsState = ButtonsState.SecondaryButtonConfig(
|
||||
text = resourceReference(R.string.main_manage_tokens),
|
||||
onClick = onManageTokensClick,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.transformers
|
||||
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletAdditionalInfo
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
|
||||
internal class SetTokenSyncProgressTransformer(
|
||||
userWalletId: UserWalletId,
|
||||
private val progressPercent: Int,
|
||||
) : WalletStateTransformer(userWalletId) {
|
||||
|
||||
override fun transform(prevState: WalletState): WalletState {
|
||||
return when (prevState) {
|
||||
is WalletState.MultiCurrency.Content -> {
|
||||
val updatedCardState = updateCardState(prevState.walletCardState)
|
||||
prevState.copy(walletCardState = updatedCardState)
|
||||
}
|
||||
else -> {
|
||||
prevState
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return walletUM
|
||||
}
|
||||
|
||||
private fun updateCardState(cardState: WalletCardState): WalletCardState {
|
||||
val additionalInfo = WalletAdditionalInfo(
|
||||
hideable = false,
|
||||
content = resourceReference(
|
||||
id = R.string.initial_wallet_sync_restore_progress,
|
||||
formatArgs = wrappedList(progressPercent),
|
||||
),
|
||||
shouldShowProgress = true,
|
||||
)
|
||||
return when (cardState) {
|
||||
is WalletCardState.Loading -> {
|
||||
cardState.copy(additionalInfo = additionalInfo)
|
||||
}
|
||||
is WalletCardState.Content -> {
|
||||
cardState.copy(additionalInfo = additionalInfo)
|
||||
}
|
||||
else -> cardState
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ import androidx.compose.foundation.indication
|
|||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.interaction.PressInteraction
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.TextAutoSize
|
||||
import androidx.compose.material3.*
|
||||
|
|
@ -164,6 +165,7 @@ private fun CardContainer(state: WalletCardState, isBalanceHidden: Boolean, item
|
|||
}
|
||||
AdditionalInfo(
|
||||
text = additionalText,
|
||||
showProgress = state.additionalInfo?.shouldShowProgress == true,
|
||||
modifier = Modifier.conditional(
|
||||
state.imageResId == null,
|
||||
) { fillMaxWidth() },
|
||||
|
|
@ -298,7 +300,7 @@ private fun Modifier.nonContentBalanceSize(dimens: TangemDimens): Modifier {
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun AdditionalInfo(text: TextReference?, modifier: Modifier = Modifier) {
|
||||
private fun AdditionalInfo(text: TextReference?, showProgress: Boolean, modifier: Modifier = Modifier) {
|
||||
AnimatedContent(
|
||||
targetState = text,
|
||||
label = "Update the additional text",
|
||||
|
|
@ -309,7 +311,19 @@ private fun AdditionalInfo(text: TextReference?, modifier: Modifier = Modifier)
|
|||
},
|
||||
) { animatedText ->
|
||||
if (animatedText != null) {
|
||||
AdditionalInfoText(text = animatedText)
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(6.dp),
|
||||
) {
|
||||
AdditionalInfoText(text = animatedText)
|
||||
if (showProgress) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier
|
||||
.size(TangemTheme.dimens.size16),
|
||||
color = TangemTheme.colors.icon.accent,
|
||||
strokeWidth = TangemTheme.dimens.size2,
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
RectangleShimmer(modifier = Modifier.nonContentAdditionalInfoSize(dimens = TangemTheme.dimens))
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue