Updated on 2026-08-14
This commit is contained in:
commit
af09ce9ca4
877 changed files with 16091 additions and 6613 deletions
|
|
@ -45,7 +45,6 @@ dependencies {
|
|||
implementation(tangemDeps.hot.core)
|
||||
implementation(tangemDeps.card.core)
|
||||
implementation(tangemDeps.blockchain)
|
||||
implementation(deps.timber)
|
||||
implementation(deps.firebase.perf) {
|
||||
exclude(group = "com.google.firebase", module = "protolite-well-known-types")
|
||||
exclude(group = "com.google.protobuf", module = "protobuf-javalite")
|
||||
|
|
@ -126,6 +125,7 @@ dependencies {
|
|||
implementation(projects.domain.yieldSupply.models)
|
||||
implementation(projects.domain.appTheme)
|
||||
implementation(projects.domain.appTheme.models)
|
||||
implementation(projects.domain.tokensync)
|
||||
|
||||
/** Feature Apis */
|
||||
implementation(projects.features.details.api)
|
||||
|
|
@ -149,6 +149,7 @@ dependencies {
|
|||
implementation(projects.features.tangempay.details.api)
|
||||
implementation(projects.features.feed.api)
|
||||
implementation(projects.features.promoBanners.api)
|
||||
implementation(projects.features.tangempay.main.api)
|
||||
|
||||
/** Common modules */
|
||||
implementation(projects.common)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,110 @@
|
|||
package com.tangem.feature.wallet.child.tokenActions
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.unit.DpOffset
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.ui.components.SimpleSettingsRow
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet
|
||||
import com.tangem.core.ui.components.getDefaultRowColors
|
||||
import com.tangem.core.ui.components.getWarningRowColors
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.LocalRedesignEnabled
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||
import com.tangem.feature.wallet.child.tokenActions.TokenActionsComponent.Params
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.fastForEach
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
||||
internal class DefaultTokenActionsComponent @AssistedInject constructor(
|
||||
@Assisted appComponentContext: AppComponentContext,
|
||||
@Assisted private val params: Params,
|
||||
val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
|
||||
) : TokenActionsComponent, AppComponentContext by appComponentContext {
|
||||
|
||||
val isBalanceHiddenFlow: StateFlow<Boolean>
|
||||
field = MutableStateFlow(false)
|
||||
|
||||
init {
|
||||
getBalanceHidingSettingsUseCase()
|
||||
.conflate()
|
||||
.distinctUntilChanged()
|
||||
.onEach {
|
||||
isBalanceHiddenFlow.value = it.isBalanceHidden
|
||||
}
|
||||
.launchIn(componentScope)
|
||||
}
|
||||
|
||||
override fun dismiss() {
|
||||
params.onDismiss()
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun BottomSheet() {
|
||||
if (!LocalRedesignEnabled.current) {
|
||||
TangemBottomSheet<TangemBottomSheetConfigContent.Empty>(
|
||||
containerColor = TangemTheme.colors.background.primary,
|
||||
config = TangemBottomSheetConfig(
|
||||
isShown = true,
|
||||
onDismissRequest = ::dismiss,
|
||||
content = TangemBottomSheetConfigContent.Empty,
|
||||
),
|
||||
) {
|
||||
Column {
|
||||
params.actions.fastForEach { action ->
|
||||
if (action.isEnabled) {
|
||||
val rowColors = if (action.isWarning) {
|
||||
getWarningRowColors()
|
||||
} else {
|
||||
getDefaultRowColors()
|
||||
}
|
||||
SimpleSettingsRow(
|
||||
title = action.text.resolveReference(),
|
||||
icon = action.iconResId,
|
||||
enabled = action.isEnabled,
|
||||
rowColors = rowColors,
|
||||
onItemsClick = action.onClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
if (params.tokenRowUM == null) {
|
||||
dismiss()
|
||||
} else {
|
||||
val isBalanceHidden by isBalanceHiddenFlow.collectAsStateWithLifecycle()
|
||||
if (LocalRedesignEnabled.current) {
|
||||
val offset = with(LocalDensity.current) {
|
||||
DpOffset(params.offsetX.toDp(), params.offsetY.toDp())
|
||||
}
|
||||
TokenActionContent(
|
||||
tokenRowUM = params.tokenRowUM,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
offset = offset,
|
||||
actions = params.actions,
|
||||
onDismiss = params.onDismiss,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : TokenActionsComponent.Factory {
|
||||
override fun create(context: AppComponentContext, params: Params): DefaultTokenActionsComponent
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,210 @@
|
|||
package com.tangem.feature.wallet.child.tokenActions
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.core.animateDpAsState
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.DpOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
import com.tangem.core.ui.ds.contextmenu.CenteredContextMenuPositionProvider
|
||||
import com.tangem.core.ui.ds.contextmenu.TangemContextMenu
|
||||
import com.tangem.core.ui.ds.row.token.TangemTokenRow
|
||||
import com.tangem.core.ui.ds.row.token.TangemTokenRowUM
|
||||
import com.tangem.core.ui.ds.row.token.internal.TangemTokenRowPreviewData
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TokenActionButtonUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
@Composable
|
||||
internal fun TokenActionContent(
|
||||
tokenRowUM: TangemTokenRowUM,
|
||||
isBalanceHidden: Boolean,
|
||||
offset: DpOffset,
|
||||
actions: ImmutableList<TokenActionButtonUM>,
|
||||
modifier: Modifier = Modifier,
|
||||
onDismiss: () -> Unit,
|
||||
) {
|
||||
val density = LocalDensity.current
|
||||
var anchorShiftPx by remember { mutableIntStateOf(0) }
|
||||
val anchorShiftDp = with(density) { anchorShiftPx.toDp() }
|
||||
val animatedShift by animateDpAsState(
|
||||
targetValue = anchorShiftDp,
|
||||
animationSpec = tween(),
|
||||
label = "AnchorShift",
|
||||
)
|
||||
|
||||
Box(modifier.fillMaxSize()) {
|
||||
Box(modifier = Modifier.offset(y = offset.y - animatedShift)) {
|
||||
TangemTokenRow(
|
||||
tokenRowUM = tokenRowUM,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
reorderableState = null,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = TangemTheme.dimens2.x3)
|
||||
.clip(RoundedCornerShape(18.dp))
|
||||
.background(TangemTheme.colors2.surface.level3),
|
||||
)
|
||||
TangemContextMenu(
|
||||
expanded = true,
|
||||
onDismissRequest = onDismiss,
|
||||
positionProvider = remember(density) {
|
||||
CenteredContextMenuPositionProvider(
|
||||
contentOffset = DpOffset(x = 0.dp, y = 12.dp),
|
||||
density = density,
|
||||
onAnchorShiftRequired = { shift ->
|
||||
if (anchorShiftPx == 0 && shift > 0) {
|
||||
anchorShiftPx = shift
|
||||
}
|
||||
},
|
||||
)
|
||||
},
|
||||
) {
|
||||
TokenActionContextMenuContent(
|
||||
actions = actions,
|
||||
onDismiss = onDismiss,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TokenActionContextMenuContent(actions: ImmutableList<TokenActionButtonUM>, onDismiss: () -> Unit) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.widthIn(min = 206.dp)
|
||||
.padding(
|
||||
vertical = TangemTheme.dimens2.x2_5,
|
||||
horizontal = TangemTheme.dimens2.x4,
|
||||
),
|
||||
) {
|
||||
actions.fastForEach { item ->
|
||||
Column {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x2),
|
||||
modifier = Modifier
|
||||
.clickable(
|
||||
enabled = item.isEnabled,
|
||||
onClick = {
|
||||
item.onClick()
|
||||
onDismiss()
|
||||
},
|
||||
)
|
||||
.padding(
|
||||
start = TangemTheme.dimens2.x1_5,
|
||||
end = TangemTheme.dimens2.x2,
|
||||
top = TangemTheme.dimens2.x2_5,
|
||||
bottom = TangemTheme.dimens2.x2_5,
|
||||
),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(item.iconResId),
|
||||
contentDescription = null,
|
||||
tint = if (item.isWarning) {
|
||||
TangemTheme.colors2.graphic.status.warning
|
||||
} else {
|
||||
TangemTheme.colors2.graphic.neutral.primary
|
||||
},
|
||||
modifier = Modifier.size(TangemTheme.dimens2.x5),
|
||||
)
|
||||
Text(
|
||||
text = item.text.resolveReference(),
|
||||
style = TangemTheme.typography2.headingRegular17,
|
||||
color = if (item.isWarning) {
|
||||
TangemTheme.colors2.text.status.warning
|
||||
} else {
|
||||
TangemTheme.colors2.text.neutral.primary
|
||||
},
|
||||
)
|
||||
}
|
||||
if (item.hasDivider) {
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
vertical = TangemTheme.dimens2.x2_5,
|
||||
horizontal = TangemTheme.dimens2.x2,
|
||||
)
|
||||
.fillMaxWidth()
|
||||
.height(1.dp)
|
||||
.background(TangemTheme.colors2.border.neutral.primary),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// region Preview
|
||||
@Composable
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
private fun TokenActionContent_Preview() {
|
||||
TangemThemePreviewRedesign {
|
||||
TokenActionContent(
|
||||
tokenRowUM = TangemTokenRowPreviewData.tokenState,
|
||||
offset = DpOffset(
|
||||
x = 100.dp,
|
||||
y = 100.dp,
|
||||
),
|
||||
actions = persistentListOf(
|
||||
TokenActionButtonUM(
|
||||
id = "Send",
|
||||
text = stringReference("Send"),
|
||||
iconResId = R.drawable.ic_arrow_up_24,
|
||||
isEnabled = true,
|
||||
isWarning = false,
|
||||
hasDivider = false,
|
||||
onClick = {},
|
||||
),
|
||||
TokenActionButtonUM(
|
||||
id = "Receive",
|
||||
text = stringReference("Receive"),
|
||||
iconResId = R.drawable.ic_arrow_down_24,
|
||||
isEnabled = true,
|
||||
isWarning = false,
|
||||
hasDivider = false,
|
||||
onClick = {},
|
||||
),
|
||||
TokenActionButtonUM(
|
||||
id = "Swap",
|
||||
text = stringReference("Swap"),
|
||||
iconResId = R.drawable.ic_exchange_vertical_24,
|
||||
isEnabled = true,
|
||||
isWarning = false,
|
||||
hasDivider = true,
|
||||
onClick = {},
|
||||
),
|
||||
TokenActionButtonUM(
|
||||
id = "Remove",
|
||||
text = stringReference("Remove"),
|
||||
iconResId = R.drawable.ic_trash_24,
|
||||
isEnabled = true,
|
||||
isWarning = true,
|
||||
hasDivider = false,
|
||||
onClick = {},
|
||||
),
|
||||
),
|
||||
isBalanceHidden = false,
|
||||
onDismiss = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
// endregion
|
||||
|
|
@ -1,64 +1,20 @@
|
|||
package com.tangem.feature.wallet.child.tokenActions
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.ui.components.SimpleSettingsRow
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet
|
||||
import com.tangem.core.ui.components.getDefaultRowColors
|
||||
import com.tangem.core.ui.components.getWarningRowColors
|
||||
import com.tangem.core.decompose.factory.ComponentFactory
|
||||
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.ds.row.token.TangemTokenRowUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TokenActionButtonUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.fastForEach
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedInject
|
||||
|
||||
internal class TokenActionsComponent @AssistedInject constructor(
|
||||
@Assisted appComponentContext: AppComponentContext,
|
||||
@Assisted private val params: Params,
|
||||
) : ComposableBottomSheetComponent, AppComponentContext by appComponentContext {
|
||||
|
||||
override fun dismiss() {
|
||||
params.onDismiss()
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun BottomSheet() {
|
||||
TangemBottomSheet<TangemBottomSheetConfigContent.Empty>(
|
||||
containerColor = TangemTheme.colors.background.primary,
|
||||
config = TangemBottomSheetConfig(
|
||||
isShown = true,
|
||||
onDismissRequest = ::dismiss,
|
||||
content = TangemBottomSheetConfigContent.Empty,
|
||||
),
|
||||
) {
|
||||
Column {
|
||||
params.actions.fastForEach { action ->
|
||||
if (action.isEnabled) {
|
||||
val rowColors = if (action.isWarning) {
|
||||
getWarningRowColors()
|
||||
} else {
|
||||
getDefaultRowColors()
|
||||
}
|
||||
SimpleSettingsRow(
|
||||
title = action.text.resolveReference(),
|
||||
icon = action.iconResId,
|
||||
enabled = action.isEnabled,
|
||||
rowColors = rowColors,
|
||||
onItemsClick = action.onClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
internal interface TokenActionsComponent : ComposableBottomSheetComponent, ComposableContentComponent {
|
||||
data class Params(
|
||||
val actions: List<TokenActionButtonUM>,
|
||||
val actions: ImmutableList<TokenActionButtonUM>,
|
||||
val tokenRowUM: TangemTokenRowUM?,
|
||||
val offsetX: Float,
|
||||
val offsetY: Float,
|
||||
val onDismiss: () -> Unit,
|
||||
)
|
||||
|
||||
interface Factory : ComponentFactory<Params, TokenActionsComponent>
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.tangem.feature.wallet.child.tokenActions.di
|
||||
|
||||
import com.tangem.feature.wallet.child.tokenActions.DefaultTokenActionsComponent
|
||||
import com.tangem.feature.wallet.child.tokenActions.TokenActionsComponent
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal interface TokenActionsModule {
|
||||
|
||||
@Binds
|
||||
fun bindTokenActionsComponentFactory(impl: DefaultTokenActionsComponent.Factory): TokenActionsComponent.Factory
|
||||
}
|
||||
|
|
@ -16,14 +16,15 @@ import com.tangem.core.decompose.context.child
|
|||
import com.tangem.core.decompose.context.childByContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.DesignFeatureToggles
|
||||
import com.tangem.features.promobanners.api.NewPromoBannersFeatureToggles
|
||||
import com.tangem.features.promobanners.api.PromoBannersBlockComponent
|
||||
import com.tangem.core.ui.components.bottomsheets.state.BottomSheetState
|
||||
import com.tangem.core.ui.components.haze.hazeEffectTangem
|
||||
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.decompose.ComposableDialogComponent
|
||||
import com.tangem.core.ui.utils.parseBigDecimal
|
||||
import com.tangem.domain.tokens.model.details.TokenAction
|
||||
import com.tangem.feature.wallet.child.organizetokens.OrganizeTokensComponent
|
||||
import com.tangem.feature.wallet.child.tokenActions.DefaultTokenActionsComponent
|
||||
import com.tangem.feature.wallet.child.tokenActions.TokenActionsComponent
|
||||
import com.tangem.feature.wallet.child.wallet.model.WalletModel
|
||||
import com.tangem.feature.wallet.navigation.WalletRoute
|
||||
|
|
@ -32,12 +33,14 @@ import com.tangem.feature.wallet.presentation.wallet.ui.WalletScreen
|
|||
import com.tangem.feature.wallet.presentation.wallet.ui.WalletScreen2
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.visa.KycRejectedComponent
|
||||
import com.tangem.feature.walletsettings.component.RenameWalletComponent
|
||||
import com.tangem.core.ui.utils.parseBigDecimal
|
||||
import com.tangem.features.biometry.AskBiometryComponent
|
||||
import com.tangem.features.feed.entry.components.FeedEntryComponent
|
||||
import com.tangem.features.promobanners.api.NewPromoBannersFeatureToggles
|
||||
import com.tangem.features.promobanners.api.PromoBannersBlockComponent
|
||||
import com.tangem.features.pushnotifications.api.PushNotificationsBottomSheetComponent
|
||||
import com.tangem.features.pushnotifications.api.PushNotificationsParams
|
||||
import com.tangem.features.send.v2.api.NetworkSelectionComponent
|
||||
import com.tangem.features.tangempay.component.TangemPayMainBlockComponent
|
||||
import com.tangem.features.tokenreceive.TokenReceiveComponent
|
||||
import com.tangem.features.yield.supply.api.YieldSupplyDepositedWarningComponent
|
||||
import dagger.assisted.Assisted
|
||||
|
|
@ -51,6 +54,7 @@ internal class WalletComponent @AssistedInject constructor(
|
|||
@Assisted appComponentContext: AppComponentContext,
|
||||
@Assisted navigate: (WalletRoute) -> Unit,
|
||||
feedEntryComponentFactory: FeedEntryComponent.Factory,
|
||||
tangemPayMainBlockComponentFactory: TangemPayMainBlockComponent.Factory,
|
||||
private val renameWalletComponentFactory: RenameWalletComponent.Factory,
|
||||
private val askBiometryComponentFactory: AskBiometryComponent.Factory,
|
||||
private val pushNotificationsBottomSheetComponent: PushNotificationsBottomSheetComponent.Factory,
|
||||
|
|
@ -59,6 +63,7 @@ internal class WalletComponent @AssistedInject constructor(
|
|||
private val promoBannersBlockComponentFactory: PromoBannersBlockComponent.Factory,
|
||||
private val newPromoBannersFeatureToggles: NewPromoBannersFeatureToggles,
|
||||
private val networkSelectionComponentFactory: NetworkSelectionComponent.Factory,
|
||||
private val tokenActionsComponentFactory: TokenActionsComponent.Factory,
|
||||
private val designFeatureToggles: DesignFeatureToggles,
|
||||
) : ComposableContentComponent, AppComponentContext by appComponentContext {
|
||||
|
||||
|
|
@ -70,6 +75,12 @@ internal class WalletComponent @AssistedInject constructor(
|
|||
entryRoute = null,
|
||||
)
|
||||
}
|
||||
private val tangemPayMainBlockComponent by lazy {
|
||||
tangemPayMainBlockComponentFactory.create(
|
||||
context = child("tangemPayMainBlockComponent"),
|
||||
params = Unit,
|
||||
)
|
||||
}
|
||||
|
||||
private val promoBannersBlockComponent: PromoBannersBlockComponent? by lazy {
|
||||
if (!newPromoBannersFeatureToggles.isNewPromoBannersEnabled) return@lazy null
|
||||
|
|
@ -156,11 +167,14 @@ internal class WalletComponent @AssistedInject constructor(
|
|||
)
|
||||
}
|
||||
is WalletDialogConfig.TokenActionList -> {
|
||||
TokenActionsComponent(
|
||||
appComponentContext = childByContext(componentContext),
|
||||
tokenActionsComponentFactory.create(
|
||||
context = childByContext(componentContext),
|
||||
params = TokenActionsComponent.Params(
|
||||
actions = dialogConfig.actionList,
|
||||
onDismiss = model.innerWalletRouter.dialogNavigation::dismiss,
|
||||
tokenRowUM = dialogConfig.tokenRowUM,
|
||||
offsetX = dialogConfig.offsetX,
|
||||
offsetY = dialogConfig.offsetY,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -218,10 +232,12 @@ internal class WalletComponent @AssistedInject constructor(
|
|||
val bottomSheetState = remember { mutableStateOf(BottomSheetState.COLLAPSED) }
|
||||
var headerSize by remember { mutableStateOf(0.dp) }
|
||||
val dialog by dialog.subscribeAsState()
|
||||
val uiState by model.uiState.collectAsStateWithLifecycle()
|
||||
|
||||
if (designFeatureToggles.isRedesignEnabled) {
|
||||
WalletScreen2(
|
||||
state = model.uiState.collectAsStateWithLifecycle().value,
|
||||
state = uiState,
|
||||
tangemPayComponent = tangemPayMainBlockComponent,
|
||||
bottomSheetContent = {
|
||||
BottomSheetContent(
|
||||
bottomSheetState = bottomSheetState,
|
||||
|
|
@ -234,8 +250,9 @@ internal class WalletComponent @AssistedInject constructor(
|
|||
)
|
||||
} else {
|
||||
WalletScreen(
|
||||
state = model.uiState.collectAsStateWithLifecycle().value,
|
||||
state = uiState,
|
||||
promoBannersBlockComponent = promoBannersBlockComponent,
|
||||
tangemPayComponent = tangemPayMainBlockComponent,
|
||||
bottomSheetContent = {
|
||||
BottomSheetContent(
|
||||
bottomSheetState = bottomSheetState,
|
||||
|
|
@ -250,6 +267,13 @@ internal class WalletComponent @AssistedInject constructor(
|
|||
|
||||
when (val dialog = dialog.child?.instance) {
|
||||
is ComposableDialogComponent -> dialog.Dialog()
|
||||
is DefaultTokenActionsComponent -> {
|
||||
if (designFeatureToggles.isRedesignEnabled) {
|
||||
dialog.Content(Modifier.hazeEffectTangem())
|
||||
} else {
|
||||
dialog.BottomSheet()
|
||||
}
|
||||
}
|
||||
is ComposableBottomSheetComponent -> dialog.BottomSheet()
|
||||
else -> {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@ import com.arkivanov.decompose.router.slot.activate
|
|||
import com.arkivanov.decompose.router.slot.dismiss
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.ui.utils.parseBigDecimal
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.analytics.models.event.MainScreenAnalyticsEvent
|
||||
import com.tangem.core.analytics.utils.TrackingContextProxy
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
import com.tangem.core.ui.utils.parseBigDecimal
|
||||
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
|
||||
import com.tangem.domain.account.supplier.SingleAccountListSupplier
|
||||
import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase
|
||||
|
|
@ -25,20 +25,22 @@ import com.tangem.domain.common.wallets.UserWalletsListRepository
|
|||
import com.tangem.domain.models.wallet.*
|
||||
import com.tangem.domain.notifications.GetIsHuaweiDeviceWithoutGoogleServicesUseCase
|
||||
import com.tangem.domain.notifications.repository.NotificationsRepository
|
||||
import com.tangem.domain.qrscanning.models.QrResultSource
|
||||
import com.tangem.domain.qrscanning.models.SourceType
|
||||
import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase
|
||||
import com.tangem.domain.qrscanning.models.ClassifiedQrContent
|
||||
import com.tangem.domain.qrscanning.models.QrSendTarget
|
||||
import com.tangem.domain.walletconnect.WcPairService
|
||||
import com.tangem.domain.walletconnect.model.WcPairRequest
|
||||
import com.tangem.domain.pay.flow.PaymentAccountStatusFetcher
|
||||
import com.tangem.domain.pay.repository.OnboardingRepository
|
||||
import com.tangem.domain.pay.usecase.TangemPayMainScreenCustomerInfoUseCase
|
||||
import com.tangem.domain.qrscanning.models.ClassifiedQrContent
|
||||
import com.tangem.domain.qrscanning.models.QrResultSource
|
||||
import com.tangem.domain.qrscanning.models.QrSendTarget
|
||||
import com.tangem.domain.qrscanning.models.SourceType
|
||||
import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase
|
||||
import com.tangem.domain.qrscanning.usecases.ResolveQrSendTargetsUseCase
|
||||
import com.tangem.domain.settings.*
|
||||
import com.tangem.domain.tokens.RefreshMultiCurrencyWalletQuotesUseCase
|
||||
import com.tangem.domain.walletconnect.WcPairService
|
||||
import com.tangem.domain.walletconnect.model.WcPairRequest
|
||||
import com.tangem.domain.tokensync.usecase.StartTokenSyncUseCase
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
import com.tangem.domain.wallets.usecase.*
|
||||
import com.tangem.domain.wallets.usecase.GetWalletIconUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyApyUpdateUseCase
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
|
||||
|
|
@ -61,6 +63,7 @@ import com.tangem.feature.wallet.presentation.wallet.ui.components.visa.KycRejec
|
|||
import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvider
|
||||
import com.tangem.features.biometry.AskBiometryComponent
|
||||
import com.tangem.features.pushnotifications.api.PushNotificationsModelCallbacks
|
||||
import com.tangem.features.tangempay.TangemPayFeatureToggles
|
||||
import com.tangem.features.wallet.deeplink.WalletDeepLinkActionListener
|
||||
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
|
||||
import com.tangem.utils.Provider
|
||||
|
|
@ -68,7 +71,7 @@ import com.tangem.utils.coroutines.*
|
|||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.*
|
||||
import timber.log.Timber
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import javax.inject.Inject
|
||||
|
||||
private const val TANGEM_PAY_UPDATE_INTERVAL = 60_000L
|
||||
|
|
@ -119,7 +122,11 @@ internal class WalletModel @Inject constructor(
|
|||
private val listenToQrScanningUseCase: ListenToQrScanningUseCase,
|
||||
private val wcPairService: WcPairService,
|
||||
private val resolveQrSendTargetsUseCase: ResolveQrSendTargetsUseCase,
|
||||
private val paymentAccountStatusFetcher: PaymentAccountStatusFetcher,
|
||||
private val tangemPayFeatureToggles: TangemPayFeatureToggles,
|
||||
private val uiMessageSender: UiMessageSender,
|
||||
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
private val startTokenSyncUseCase: StartTokenSyncUseCase,
|
||||
val screenLifecycleProvider: ScreenLifecycleProvider,
|
||||
val innerWalletRouter: InnerWalletRouter,
|
||||
) : Model() {
|
||||
|
|
@ -152,12 +159,13 @@ internal class WalletModel @Inject constructor(
|
|||
subscribeTangemPayOnWalletState()
|
||||
subscribeToMainScreenQrScanning()
|
||||
enableNotificationsIfNeeded()
|
||||
applyPendingTokenSyncs()
|
||||
|
||||
clickIntents.initialize(innerWalletRouter, modelScope)
|
||||
|
||||
modelScope.launch {
|
||||
bindRefcodeWithWalletUseCase.retry()
|
||||
.onLeft { Timber.e("Failed to bind refcode with wallets: $it") }
|
||||
.onLeft { TangemLogger.e("Failed to bind refcode with wallets: $it") }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -308,7 +316,7 @@ internal class WalletModel @Inject constructor(
|
|||
val shouldAskNotificationPermissionsViaBs = notificationsRepository.shouldAskNotificationPermissionsViaBs()
|
||||
val shouldShow = notificationsRepository.shouldShowSubscribeOnNotificationsAfterUpdate()
|
||||
val isHuaweiDevice = getIsHuaweiDeviceWithoutGoogleServicesUseCase()
|
||||
Timber.d(
|
||||
TangemLogger.d(
|
||||
"push BS afterUpdate: $shouldShow," +
|
||||
"isHuaweiDevice $isHuaweiDevice",
|
||||
)
|
||||
|
|
@ -427,14 +435,17 @@ internal class WalletModel @Inject constructor(
|
|||
updateTangemPayJobHolder.cancel()
|
||||
modelScope.launch {
|
||||
tangemPayMainScreenCustomerInfoUseCase.fetch(userWalletId)
|
||||
paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWalletId))
|
||||
while (isActive) {
|
||||
delay(TANGEM_PAY_UPDATE_INTERVAL)
|
||||
tangemPayMainScreenCustomerInfoUseCase.fetch(userWalletId)
|
||||
paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWalletId))
|
||||
}
|
||||
}.saveIn(updateTangemPayJobHolder)
|
||||
} else {
|
||||
// Don't refresh customer info periodically if the card was already issued, only update on swipe to refresh
|
||||
tangemPayMainScreenCustomerInfoUseCase.fetch(userWalletId)
|
||||
paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWalletId))
|
||||
}
|
||||
}.launchIn(modelScope)
|
||||
}
|
||||
|
|
@ -454,7 +465,7 @@ internal class WalletModel @Inject constructor(
|
|||
awaitAll(
|
||||
async {
|
||||
refreshMultiCurrencyWalletQuotesUseCase(wallet.walletCardState.id).getOrElse {
|
||||
Timber.e("Failed to refreshMultiCurrencyWalletQuotesUseCase $it")
|
||||
TangemLogger.e("Failed to refreshMultiCurrencyWalletQuotesUseCase $it")
|
||||
}
|
||||
},
|
||||
async {
|
||||
|
|
@ -497,10 +508,10 @@ internal class WalletModel @Inject constructor(
|
|||
}
|
||||
is WalletsUpdateActionResolver.Action.ReorderWallets -> reorderWallets(action)
|
||||
WalletsUpdateActionResolver.Action.EmptyWallets -> {
|
||||
Timber.w("Wallets list is empty!")
|
||||
TangemLogger.w("Wallets list is empty!")
|
||||
}
|
||||
is WalletsUpdateActionResolver.Action.Unknown -> {
|
||||
Timber.w("Unable to perform action: $action")
|
||||
TangemLogger.w("Unable to perform action: $action")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -543,6 +554,7 @@ internal class WalletModel @Inject constructor(
|
|||
walletImageResolver = walletImageResolver,
|
||||
isMainScreenQrScanningEnabled = walletFeatureToggles.isMainScreenQrScanningEnabled,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isTangemPayRefactorEnabled = tangemPayFeatureToggles.isTangemPayAccountsRefactorEnabled,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -589,6 +601,7 @@ internal class WalletModel @Inject constructor(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isTangemPayRefactorEnabled = tangemPayFeatureToggles.isTangemPayAccountsRefactorEnabled,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -610,6 +623,7 @@ internal class WalletModel @Inject constructor(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isTangemPayRefactorEnabled = tangemPayFeatureToggles.isTangemPayAccountsRefactorEnabled,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -624,6 +638,7 @@ internal class WalletModel @Inject constructor(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isTangemPayRefactorEnabled = tangemPayFeatureToggles.isTangemPayAccountsRefactorEnabled,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -685,6 +700,7 @@ internal class WalletModel @Inject constructor(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isTangemPayRefactorEnabled = tangemPayFeatureToggles.isTangemPayAccountsRefactorEnabled,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -824,6 +840,12 @@ internal class WalletModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun applyPendingTokenSyncs() {
|
||||
if (hotWalletFeatureToggles.isTokenSyncEnabled) {
|
||||
startTokenSyncUseCase.applyPendingSyncs()
|
||||
}
|
||||
}
|
||||
|
||||
private fun enableNotificationsIfNeeded() {
|
||||
modelScope.launch {
|
||||
val isUserAllowToEnableNotifications = notificationsRepository.isUserAllowToSubscribeOnPushNotifications()
|
||||
|
|
@ -836,7 +858,7 @@ internal class WalletModel @Inject constructor(
|
|||
setNotificationsEnabledUseCase(userWalletId, true).onRight {
|
||||
notificationsRepository.setNotificationsWasEnabledAutomatically(userWalletId.stringValue)
|
||||
}.onLeft {
|
||||
Timber.e(it)
|
||||
TangemLogger.e("Error", it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotificat
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletScreenState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletType
|
||||
import timber.log.Timber
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
|
|
@ -42,7 +42,7 @@ internal class WalletsUpdateActionResolver @Inject constructor(
|
|||
getUpdateContentAction(currentState, wallets, selectedWallet)
|
||||
}
|
||||
|
||||
Timber.i("Resolved action: $action")
|
||||
TangemLogger.i("Resolved action: $action")
|
||||
|
||||
return action
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import com.tangem.domain.models.wallet.UserWalletId
|
|||
import com.tangem.domain.pay.TangemPayDetailsConfig
|
||||
import com.tangem.domain.pay.TangemPayEligibilityManager
|
||||
import com.tangem.domain.pay.model.TangemPayEntryPoint
|
||||
import com.tangem.domain.pay.flow.PaymentAccountStatusFetcher
|
||||
import com.tangem.domain.pay.repository.OnboardingRepository
|
||||
import com.tangem.domain.pay.usecase.ProduceTangemPayInitialDataUseCase
|
||||
import com.tangem.domain.pay.usecase.TangemPayMainScreenCustomerInfoUseCase
|
||||
|
|
@ -30,7 +31,6 @@ import com.tangem.domain.tangempay.TangemPayAnalyticsEvents
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletDialogConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.TangemPayHideOnboardingStateTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.TangemPayRefreshNeededStateTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.TangemPayRefreshShowProgressTransformer
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
|
@ -77,6 +77,7 @@ internal class TangemPayClickIntentsImplementor @Inject constructor(
|
|||
private val tangemPayEligibilityManager: TangemPayEligibilityManager,
|
||||
private val uiMessageSender: UiMessageSender,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val paymentAccountStatusFetcher: PaymentAccountStatusFetcher,
|
||||
) : BaseWalletClickIntents(), TangemPayIntents {
|
||||
|
||||
override suspend fun onPullToRefresh() {
|
||||
|
|
@ -85,20 +86,28 @@ internal class TangemPayClickIntentsImplementor @Inject constructor(
|
|||
return
|
||||
}
|
||||
tangemPayMainScreenCustomerInfoUseCase.fetch(userWalletId)
|
||||
paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWalletId))
|
||||
}
|
||||
|
||||
override fun onRefreshPayToken(userWallet: UserWallet) {
|
||||
stateHolder.update(TangemPayRefreshShowProgressTransformer(userWallet.walletId))
|
||||
stateHolder.update(
|
||||
TangemPayRefreshShowProgressTransformer(
|
||||
userWalletId = userWallet.walletId,
|
||||
shouldShowProgress = true,
|
||||
),
|
||||
)
|
||||
|
||||
modelScope.launch {
|
||||
produceInitialDataTangemPay.invoke(userWallet.walletId)
|
||||
.onRight { tangemPayMainScreenCustomerInfoUseCase.fetch(userWallet.walletId) }
|
||||
.onRight {
|
||||
tangemPayMainScreenCustomerInfoUseCase.fetch(userWallet.walletId)
|
||||
paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWallet.walletId))
|
||||
}
|
||||
.onLeft {
|
||||
stateHolder.update(
|
||||
transformer = TangemPayRefreshNeededStateTransformer(
|
||||
userWallet = userWallet,
|
||||
TangemPayRefreshShowProgressTransformer(
|
||||
userWalletId = userWallet.walletId,
|
||||
onRefreshClick = { onRefreshPayToken(userWallet) },
|
||||
shouldShowProgress = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -267,7 +276,10 @@ internal class TangemPayClickIntentsImplementor @Inject constructor(
|
|||
analyticsEventHandler.send(TangemPayAnalyticsEvents.KycCancelled())
|
||||
modelScope.launch {
|
||||
tangemPayOnboardingRepository.disableTangemPay(userWalletId)
|
||||
.onRight { tangemPayMainScreenCustomerInfoUseCase.fetch(userWalletId) }
|
||||
.onRight {
|
||||
tangemPayMainScreenCustomerInfoUseCase.fetch(userWalletId)
|
||||
paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWalletId))
|
||||
}
|
||||
.onLeft { uiMessageSender.send(ToastMessage(resourceReference(R.string.common_something_went_wrong))) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package com.tangem.feature.wallet.child.wallet.model.intents
|
||||
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import com.tangem.common.ui.expressStatus.ExpressStatusBottomSheetConfig
|
||||
import com.tangem.common.ui.tokens.TokenItemStateConverter.ApySource
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
|
|
@ -8,6 +10,7 @@ import com.tangem.core.analytics.models.AnalyticsParam
|
|||
import com.tangem.core.analytics.models.event.MainScreenAnalyticsEvent
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
import com.tangem.core.ui.ds.row.token.TangemTokenRowUM
|
||||
import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
|
|
@ -37,10 +40,10 @@ import com.tangem.feature.wallet.presentation.wallet.state.transformers.OpenBott
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.MultiWalletCurrencyActionsConverter
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletEventSender
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.take
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("TooManyFunctions")
|
||||
|
|
@ -56,6 +59,13 @@ internal interface WalletContentClickIntents {
|
|||
|
||||
fun onTokenItemLongClick(accountId: AccountId, cryptoCurrencyStatus: CryptoCurrencyStatus)
|
||||
|
||||
fun onTokenItemLongClickV2(
|
||||
accountId: AccountId,
|
||||
cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
offset: Offset,
|
||||
tokenRowUM: TangemTokenRowUM,
|
||||
)
|
||||
|
||||
fun onApyLabelClick(accountId: AccountId, currencyStatus: CryptoCurrencyStatus, apySource: ApySource, apy: String)
|
||||
|
||||
fun onYieldPromoCloseClick()
|
||||
|
|
@ -131,12 +141,12 @@ internal class WalletContentClickIntentsImplementor @Inject constructor(
|
|||
override fun onTokenItemLongClick(accountId: AccountId, cryptoCurrencyStatus: CryptoCurrencyStatus) {
|
||||
modelScope.launch(dispatchers.main) {
|
||||
val userWalletId = accountId.userWalletId
|
||||
val userWallet = getUserWalletUseCase(userWalletId).getOrElse {
|
||||
Timber.e(
|
||||
val userWallet = getUserWalletUseCase(userWalletId).getOrElse { error ->
|
||||
TangemLogger.e(
|
||||
"""
|
||||
Unable to get user wallet
|
||||
|- ID: $userWalletId
|
||||
|- Exception: $it
|
||||
|- Exception: $error
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
||||
|
|
@ -153,6 +163,47 @@ internal class WalletContentClickIntentsImplementor @Inject constructor(
|
|||
accountId = accountId,
|
||||
clickIntents = currencyActionsClickIntents,
|
||||
).convert(actionsState),
|
||||
offset = Offset.Zero,
|
||||
tokenRowUM = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTokenItemLongClickV2(
|
||||
accountId: AccountId,
|
||||
cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
offset: Offset,
|
||||
tokenRowUM: TangemTokenRowUM,
|
||||
) {
|
||||
modelScope.launch {
|
||||
val userWalletId = accountId.userWalletId
|
||||
val userWallet = getUserWalletUseCase(userWalletId).getOrElse { exception ->
|
||||
TangemLogger.e(
|
||||
"""
|
||||
Unable to get user wallet
|
||||
|- ID: $userWalletId
|
||||
|- Exception: $exception
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
||||
return@launch
|
||||
}
|
||||
|
||||
getCryptoCurrencyActionsUseCase(userWallet = userWallet, cryptoCurrencyStatus = cryptoCurrencyStatus)
|
||||
.take(count = 1)
|
||||
.collectLatest { actionsState ->
|
||||
router.openTokenActionSheet(
|
||||
userWallet = userWallet,
|
||||
tokenActionList = MultiWalletCurrencyActionsConverter(
|
||||
userWallet = userWallet,
|
||||
accountId = accountId,
|
||||
clickIntents = currencyActionsClickIntents,
|
||||
).convert(actionsState)
|
||||
.filter { it.isEnabled }
|
||||
.toPersistentList(),
|
||||
offset = offset,
|
||||
tokenRowUM = tokenRowUM,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -287,7 +338,7 @@ internal class WalletContentClickIntentsImplementor @Inject constructor(
|
|||
txHash = txHash,
|
||||
currency = currency,
|
||||
).fold(
|
||||
ifLeft = { Timber.e(it.toString()) },
|
||||
ifLeft = { TangemLogger.e(it.toString()) },
|
||||
ifRight = { router.openUrl(url = it) },
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.tangem.feature.wallet.child.wallet.model.intents
|
||||
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.common.TangemBlogUrlBuilder
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import com.tangem.common.routing.AppRoute.*
|
||||
import com.tangem.common.routing.AppRouter
|
||||
import com.tangem.common.ui.notifications.NotificationId
|
||||
|
|
@ -11,14 +11,15 @@ import com.tangem.core.analytics.models.AnalyticsParam
|
|||
import com.tangem.core.analytics.models.Basic.ButtonSupport
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.core.navigation.review.ReviewManager
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.domain.card.SetCardWasScannedUseCase
|
||||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.feedback.GetWalletMetaInfoUseCase
|
||||
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||
import com.tangem.domain.feedback.models.FeedbackEmailType
|
||||
import com.tangem.domain.hotwallet.CloseHotWalletUpgradeBannerUseCase
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
|
|
@ -39,12 +40,12 @@ import com.tangem.domain.tokens.model.analytics.PromoAnalyticsEvent
|
|||
import com.tangem.domain.tokens.model.analytics.PromoAnalyticsEvent.Program
|
||||
import com.tangem.domain.tokens.model.analytics.PromoAnalyticsEvent.PromotionBannerClicked
|
||||
import com.tangem.domain.tokens.model.details.NavigationAction
|
||||
import com.tangem.domain.tokensync.usecase.AcknowledgeTokenSyncCompletionUseCase
|
||||
import com.tangem.domain.wallets.usecase.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.Basic
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.MainScreen
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletAlertUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletEvent
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletEventSender
|
||||
import com.tangem.features.pushnotifications.api.analytics.PushNotificationAnalyticEvents
|
||||
|
|
@ -53,7 +54,6 @@ import kotlinx.coroutines.async
|
|||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("TooManyFunctions")
|
||||
|
|
@ -85,14 +85,6 @@ internal interface WalletWarningsClickIntents {
|
|||
|
||||
fun onNoteMigrationButtonClick(url: String)
|
||||
|
||||
fun onSeedPhraseNotificationConfirm()
|
||||
|
||||
fun onSeedPhraseNotificationDecline()
|
||||
|
||||
fun onSeedPhraseSecondNotificationAccept()
|
||||
|
||||
fun onSeedPhraseSecondNotificationReject()
|
||||
|
||||
fun onAllowPermissions()
|
||||
|
||||
fun onDenyPermissions()
|
||||
|
|
@ -104,6 +96,10 @@ internal interface WalletWarningsClickIntents {
|
|||
fun onUpgradeHotWalletClick(userWalletId: UserWalletId)
|
||||
|
||||
fun onCloseUpgradeBannerClick(userWalletId: UserWalletId)
|
||||
|
||||
fun onDismissTokenSyncNotification(userWalletId: UserWalletId)
|
||||
|
||||
fun onTokenSyncManageClick(userWalletId: UserWalletId)
|
||||
}
|
||||
|
||||
@Suppress("LargeClass", "LongParameterList", "TooManyFunctions")
|
||||
|
|
@ -122,7 +118,6 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
|
|||
private val shouldShowPromoWalletUseCase: ShouldShowPromoWalletUseCase,
|
||||
private val getWalletMetaInfoUseCase: GetWalletMetaInfoUseCase,
|
||||
private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase,
|
||||
private val seedPhraseNotificationUseCase: SeedPhraseNotificationUseCase,
|
||||
private val urlOpener: UrlOpener,
|
||||
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
|
||||
|
|
@ -137,6 +132,7 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
|
|||
private val uiMessageSender: UiMessageSender,
|
||||
private val reviewManager: ReviewManager,
|
||||
private val closeHotWalletUpgradeBannerUseCase: CloseHotWalletUpgradeBannerUseCase,
|
||||
private val acknowledgeTokenSyncCompletionUseCase: AcknowledgeTokenSyncCompletionUseCase,
|
||||
) : BaseWalletClickIntents(), WalletWarningsClickIntents {
|
||||
|
||||
override fun onAddBackupCardClick() {
|
||||
|
|
@ -187,7 +183,7 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
|
|||
userWalletId = userWallet.walletId,
|
||||
currencies = missedAddressCurrencies,
|
||||
).fold(
|
||||
ifLeft = { Timber.e(it, "Failed to derive public keys") },
|
||||
ifLeft = { TangemLogger.e("Failed to derive public keys", it) },
|
||||
ifRight = {
|
||||
fetchCryptoCurrencies(userWalletId = userWallet.walletId, currencies = missedAddressCurrencies)
|
||||
},
|
||||
|
|
@ -360,66 +356,6 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override fun onSeedPhraseNotificationConfirm() {
|
||||
val userWallet = getSelectedUserWallet() ?: return
|
||||
|
||||
analyticsEventHandler.send(MainScreen.NoticeSeedPhraseSupportButtonYes())
|
||||
|
||||
uiMessageSender.send(
|
||||
WalletAlertUM.seedPhraseConfirm {
|
||||
modelScope.launch {
|
||||
seedPhraseNotificationUseCase.confirm(userWalletId = userWallet.walletId)
|
||||
|
||||
urlOpener.openUrl(
|
||||
url = TangemBlogUrlBuilder.build(post = TangemBlogUrlBuilder.Post.SeedNotify),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
override fun onSeedPhraseNotificationDecline() {
|
||||
val userWallet = getSelectedUserWallet() ?: return
|
||||
|
||||
analyticsEventHandler.send(MainScreen.NoticeSeedPhraseSupportButtonNo())
|
||||
|
||||
uiMessageSender.send(
|
||||
WalletAlertUM.seedPhraseDismiss {
|
||||
modelScope.launch {
|
||||
seedPhraseNotificationUseCase.decline(userWalletId = userWallet.walletId)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
override fun onSeedPhraseSecondNotificationAccept() {
|
||||
val userWallet = getSelectedUserWallet() ?: return
|
||||
|
||||
analyticsEventHandler.send(MainScreen.NoticeSeedPhraseSupportButtonUsed())
|
||||
|
||||
uiMessageSender.send(
|
||||
WalletAlertUM.seedPhraseConfirm {
|
||||
modelScope.launch {
|
||||
seedPhraseNotificationUseCase.acceptSecond(userWalletId = userWallet.walletId)
|
||||
|
||||
urlOpener.openUrl(
|
||||
url = TangemBlogUrlBuilder.build(post = TangemBlogUrlBuilder.Post.SeedNotifySecond),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
override fun onSeedPhraseSecondNotificationReject() {
|
||||
val userWallet = getSelectedUserWallet() ?: return
|
||||
|
||||
analyticsEventHandler.send(MainScreen.NoticeSeedPhraseSupportButtonDeclined())
|
||||
|
||||
modelScope.launch {
|
||||
seedPhraseNotificationUseCase.rejectSecond(userWalletId = userWallet.walletId)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFinishWalletActivationClick(isBackupExists: Boolean) {
|
||||
analyticsEventHandler.send(MainScreen.ButtonFinalizeActivation())
|
||||
val userWalletId = stateHolder.getSelectedWalletId()
|
||||
|
|
@ -485,7 +421,7 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
|
|||
networks = currencies.map(CryptoCurrency::network).toSet(),
|
||||
),
|
||||
)
|
||||
.onLeft { Timber.e("Unable to fetch networks: $it") }
|
||||
.onLeft { TangemLogger.e("Unable to fetch networks: $it") }
|
||||
},
|
||||
async {
|
||||
multiQuoteStatusFetcher(
|
||||
|
|
@ -494,7 +430,7 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
|
|||
appCurrencyId = null,
|
||||
),
|
||||
)
|
||||
.onLeft { Timber.e("Unable to fetch quotes: $it") }
|
||||
.onLeft { TangemLogger.e("Unable to fetch quotes: $it") }
|
||||
},
|
||||
async {
|
||||
val stakingIds = currencies.mapNotNullTo(hashSetOf()) {
|
||||
|
|
@ -507,7 +443,7 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
|
|||
stakingIds = stakingIds,
|
||||
),
|
||||
)
|
||||
.onLeft { Timber.e("Unable to fetch yield balances: $it") }
|
||||
.onLeft { TangemLogger.e("Unable to fetch yield balances: $it") }
|
||||
},
|
||||
)
|
||||
.awaitAll()
|
||||
|
|
@ -516,12 +452,12 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
|
|||
|
||||
private fun getSelectedUserWallet(): UserWallet? {
|
||||
val userWalletId = stateHolder.getSelectedWalletId()
|
||||
return getUserWalletUseCase(userWalletId).getOrElse {
|
||||
Timber.e(
|
||||
return getUserWalletUseCase(userWalletId).getOrElse { error ->
|
||||
TangemLogger.e(
|
||||
"""
|
||||
Unable to get user wallet
|
||||
|- ID: $userWalletId
|
||||
|- Exception: $it
|
||||
|- Exception: $error
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
||||
|
|
@ -538,7 +474,7 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
|
|||
setNotificationsEnabledUseCase(userWalletId, true).onRight {
|
||||
notificationsRepository.setNotificationsWasEnabledAutomatically(userWalletId.stringValue)
|
||||
}.onLeft {
|
||||
Timber.e(it)
|
||||
TangemLogger.e("Error", it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -572,6 +508,17 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override fun onDismissTokenSyncNotification(userWalletId: UserWalletId) {
|
||||
acknowledgeTokenSyncCompletionUseCase(userWalletId)
|
||||
}
|
||||
|
||||
override fun onTokenSyncManageClick(userWalletId: UserWalletId) {
|
||||
acknowledgeTokenSyncCompletionUseCase(userWalletId)
|
||||
router.openManageTokensScreen(
|
||||
AccountId.forMainCryptoPortfolio(userWalletId),
|
||||
)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val VISA_PROMO_LINK = "https://tangem.com/en/cardwaitlist/?utm_source=tangem-app-banner" +
|
||||
"&utm_medium=banner" +
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ import kotlinx.coroutines.delay
|
|||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withTimeoutOrNull
|
||||
import timber.log.Timber
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
|
|
@ -72,12 +72,12 @@ internal class DefaultPromoDeeplinkHandler @AssistedInject constructor(
|
|||
|
||||
private fun findSelectedWallet(promoCode: String) {
|
||||
getSelectedWalletSyncUseCase().fold(
|
||||
ifLeft = {
|
||||
Timber.tag(LOG_TAG).e("Error on getting user wallet: $it")
|
||||
ifLeft = { error ->
|
||||
TangemLogger.withTag(LOG_TAG).e("Error on getting user wallet: $error")
|
||||
showAlert(Failed)
|
||||
},
|
||||
ifRight = { userWallet ->
|
||||
Timber.tag(LOG_TAG).d("SelectedUserWallet ${userWallet.walletId.stringValue.mask()}")
|
||||
TangemLogger.withTag(LOG_TAG).d("SelectedUserWallet ${userWallet.walletId.stringValue.mask()}")
|
||||
findBitcoinAddress(userWallet = userWallet, promoCode = promoCode)
|
||||
},
|
||||
)
|
||||
|
|
@ -96,24 +96,24 @@ internal class DefaultPromoDeeplinkHandler @AssistedInject constructor(
|
|||
},
|
||||
)
|
||||
|
||||
Timber.tag(LOG_TAG).d("All user network statuses ${networkStatuses?.size}")
|
||||
TangemLogger.withTag(LOG_TAG).d("All user network statuses ${networkStatuses?.size}")
|
||||
|
||||
val cryptoCurrencies = multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
|
||||
MultiWalletCryptoCurrenciesProducer.Params(userWallet.walletId),
|
||||
)
|
||||
|
||||
Timber.tag(LOG_TAG).d("All user cryptoCurrencies on main ${cryptoCurrencies?.size}")
|
||||
TangemLogger.withTag(LOG_TAG).d("All user cryptoCurrencies on main ${cryptoCurrencies?.size}")
|
||||
|
||||
val bitcoinCurrency = cryptoCurrencies?.firstOrNull { it.id.rawNetworkId == Blockchain.Bitcoin.id }
|
||||
Timber.tag(LOG_TAG).d("BitcoinCurrency $bitcoinCurrency")
|
||||
TangemLogger.withTag(LOG_TAG).d("BitcoinCurrency $bitcoinCurrency")
|
||||
|
||||
val bitcoinStatus = networkStatuses?.firstOrNull { status ->
|
||||
status.network.id == bitcoinCurrency?.network?.id
|
||||
}
|
||||
Timber.tag(LOG_TAG).d("BitcoinStatus $bitcoinStatus")
|
||||
TangemLogger.withTag(LOG_TAG).d("BitcoinStatus $bitcoinStatus")
|
||||
|
||||
if (bitcoinStatus == null) {
|
||||
Timber.tag(LOG_TAG).d("No bitcoin, bitcoin network status == null")
|
||||
TangemLogger.withTag(LOG_TAG).d("No bitcoin, bitcoin network status == null")
|
||||
showAlert(NoBitcoinAddress)
|
||||
} else {
|
||||
val networkAddress = when (bitcoinStatus.value) {
|
||||
|
|
@ -126,7 +126,7 @@ internal class DefaultPromoDeeplinkHandler @AssistedInject constructor(
|
|||
?.defaultAddress?.value
|
||||
|
||||
if (bitcoinAddress != null) {
|
||||
Timber.tag(LOG_TAG).d(
|
||||
TangemLogger.withTag(LOG_TAG).d(
|
||||
"Start activation promoCode ${promoCode.mask()} address ${bitcoinAddress.mask()}",
|
||||
)
|
||||
|
||||
|
|
@ -138,7 +138,7 @@ internal class DefaultPromoDeeplinkHandler @AssistedInject constructor(
|
|||
} else {
|
||||
uiMessageSender.send(GlobalLoadingMessage(false))
|
||||
delay(DEFAULT_MESSAGE_SENDER_DELAY)
|
||||
Timber.tag(LOG_TAG).d("No Bitcoin address $bitcoinStatus.value")
|
||||
TangemLogger.withTag(LOG_TAG).d("No Bitcoin address $bitcoinStatus.value")
|
||||
showAlert(NoBitcoinAddress)
|
||||
}
|
||||
}
|
||||
|
|
@ -155,13 +155,15 @@ internal class DefaultPromoDeeplinkHandler @AssistedInject constructor(
|
|||
delay(DEFAULT_MESSAGE_SENDER_DELAY)
|
||||
uiMessageSender.send(GlobalLoadingMessage(false))
|
||||
delay(DEFAULT_MESSAGE_SENDER_DELAY)
|
||||
Timber.tag(LOG_TAG).d("${promoCode.mask()} activation success on address ${bitcoinAddress.mask()}")
|
||||
TangemLogger.withTag(
|
||||
LOG_TAG,
|
||||
).d("${promoCode.mask()} activation success on address ${bitcoinAddress.mask()}")
|
||||
showAlert(Activated)
|
||||
}.onLeft { error ->
|
||||
delay(DEFAULT_MESSAGE_SENDER_DELAY)
|
||||
uiMessageSender.send(GlobalLoadingMessage(false))
|
||||
delay(DEFAULT_MESSAGE_SENDER_DELAY)
|
||||
Timber.tag(LOG_TAG).d("${promoCode.mask()} activation failed $error")
|
||||
TangemLogger.withTag(LOG_TAG).d("${promoCode.mask()} activation failed $error")
|
||||
val alertType = when (error) {
|
||||
ActivatePromoCodeError.ActivationFailed -> Failed
|
||||
ActivatePromoCodeError.InvalidPromoCode -> InvalidPromoCode
|
||||
|
|
@ -203,7 +205,7 @@ internal class DefaultPromoDeeplinkHandler @AssistedInject constructor(
|
|||
@Suppress("NullableToStringCall")
|
||||
private fun saveAndBindRefcode() {
|
||||
scope.launch(dispatchers.default) {
|
||||
Timber.i("saveAndBindRefcode: refcode = $refcode, campaign = $campaign")
|
||||
TangemLogger.i("saveAndBindRefcode: refcode = $refcode, campaign = $campaign")
|
||||
|
||||
if (!refcode.isNullOrBlank()) {
|
||||
val conversionData = AppsFlyerConversionData(refcode = refcode, campaign = campaign)
|
||||
|
|
@ -211,7 +213,7 @@ internal class DefaultPromoDeeplinkHandler @AssistedInject constructor(
|
|||
appsFlyerStore.storeIfAbsent(value = conversionData)
|
||||
|
||||
bindRefcodeWithWalletUseCase(conversionData)
|
||||
.onLeft { Timber.e("Failed to bind refcode with wallets: $it") }
|
||||
.onLeft { TangemLogger.e("Failed to bind refcode with wallets: $it") }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@ internal object WalletPreviewDataLegacy {
|
|||
balance = "8923,05312312312312312312331231231233432423423424234 $",
|
||||
additionalInfo = WalletAdditionalInfo(
|
||||
hideable = false,
|
||||
content = TextReference.Str("3 cards • Seed phrase3 cards • Seed phrasephrasephrasephrase"),
|
||||
content = WalletAdditionalInfo.Content.Text(
|
||||
TextReference.Str("3 cards • Seed phrase3 cards • Seed phrasephrasephrasephrase"),
|
||||
),
|
||||
),
|
||||
imageResId = R.drawable.ill_wallet2_cards3_120_106,
|
||||
dropDownItems = persistentListOf(),
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import com.tangem.feature.wallet.presentation.common.WalletPreviewDataLegacy.top
|
|||
import com.tangem.feature.wallet.presentation.preview.WalletBalancePreview
|
||||
import com.tangem.feature.wallet.presentation.preview.WalletPreviewData
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.*
|
||||
import com.tangem.features.tangempay.entity.TangemPayMainUM
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
internal object WalletScreenPreviewData {
|
||||
|
|
@ -39,7 +40,7 @@ internal object WalletScreenPreviewData {
|
|||
promoBannerUM = TangemTokenRowUM.PromoBannerUM.Empty,
|
||||
tailUM = TangemRowTailUM.Empty,
|
||||
onItemClick = {},
|
||||
onItemLongClick = {},
|
||||
onItemLongClick = { _, _ -> },
|
||||
)
|
||||
|
||||
private val accountRowDefault = TangemTokenRowUM.Content(
|
||||
|
|
@ -60,7 +61,7 @@ internal object WalletScreenPreviewData {
|
|||
promoBannerUM = TangemTokenRowUM.PromoBannerUM.Empty,
|
||||
tailUM = TangemRowTailUM.Empty,
|
||||
onItemClick = {},
|
||||
onItemLongClick = {},
|
||||
onItemLongClick = { _, _ -> },
|
||||
)
|
||||
|
||||
private val tokenListDefault = WalletTokensListUM.Content(
|
||||
|
|
@ -167,7 +168,7 @@ internal object WalletScreenPreviewData {
|
|||
isFlickering = false,
|
||||
onItemClick = {},
|
||||
),
|
||||
tangemPayState = TangemPayState.Loading,
|
||||
tangemPayMainUM = TangemPayMainUM.Loading,
|
||||
)
|
||||
|
||||
private val walletEmpty = WalletUM.Content(
|
||||
|
|
@ -182,7 +183,7 @@ internal object WalletScreenPreviewData {
|
|||
notificationsCarousel = persistentListOf(),
|
||||
tokensListUM = WalletTokensListUM.Empty(onEmptyClick = {}),
|
||||
nftState = WalletNFTItemUM.Hidden,
|
||||
tangemPayState = TangemPayState.Empty,
|
||||
tangemPayMainUM = TangemPayMainUM.Empty,
|
||||
)
|
||||
|
||||
private val walletAccountDefault = walletDefault.copy(
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import com.tangem.feature.wallet.child.wallet.model.WalletActivationBannerType
|
|||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.common.WalletPreviewDataLegacy.topBarConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.*
|
||||
import com.tangem.features.tangempay.entity.TangemPayMainUM
|
||||
import com.tangem.utils.StringsSigns.DASH_SIGN
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
|
@ -159,7 +160,7 @@ internal object WalletScreenPreviewDataLegacy {
|
|||
title = "Note",
|
||||
additionalInfo = WalletAdditionalInfo(
|
||||
hideable = false,
|
||||
content = TextReference.Str("Locked"),
|
||||
content = WalletAdditionalInfo.Content.Text(TextReference.Str("Locked")),
|
||||
),
|
||||
imageResId = R.drawable.ill_note_btc_120_106,
|
||||
dropDownItems = persistentListOf(),
|
||||
|
|
@ -171,7 +172,7 @@ internal object WalletScreenPreviewDataLegacy {
|
|||
title = "Wallet 1",
|
||||
additionalInfo = WalletAdditionalInfo(
|
||||
hideable = false,
|
||||
content = TextReference.Str("Seed phrase"),
|
||||
content = WalletAdditionalInfo.Content.Text(TextReference.Str("Seed phrase")),
|
||||
),
|
||||
imageResId = R.drawable.ill_wallet2_cards3_120_106,
|
||||
cardCount = 3,
|
||||
|
|
@ -217,6 +218,8 @@ internal object WalletScreenPreviewDataLegacy {
|
|||
onClick = {},
|
||||
),
|
||||
type = WalletType.Cold,
|
||||
tangemPayMainUM = TangemPayMainUM.Empty,
|
||||
isTangemPayRefactorEnabled = false,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.feature.wallet.presentation.router
|
||||
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import com.arkivanov.decompose.router.slot.SlotNavigation
|
||||
import com.arkivanov.decompose.router.slot.activate
|
||||
import com.arkivanov.decompose.router.slot.dismiss
|
||||
|
|
@ -8,6 +9,7 @@ import com.tangem.common.routing.AppRouter
|
|||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.core.ui.DesignFeatureToggles
|
||||
import com.tangem.core.ui.ds.row.token.TangemTokenRowUM
|
||||
import com.tangem.domain.models.TokenReceiveConfig
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
|
|
@ -17,8 +19,6 @@ import com.tangem.domain.qrscanning.models.QrSendTarget
|
|||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.pay.TangemPayDetailsConfig
|
||||
import com.tangem.domain.redux.ReduxStateHolder
|
||||
import com.tangem.domain.redux.StateDialog
|
||||
import com.tangem.domain.tokens.model.details.NavigationAction
|
||||
import com.tangem.domain.tokens.model.details.TokenAction
|
||||
import com.tangem.feature.wallet.child.organizetokens.OrganizeTokensComponent
|
||||
|
|
@ -35,7 +35,6 @@ import javax.inject.Inject
|
|||
internal class DefaultWalletRouter @Inject constructor(
|
||||
private val router: AppRouter,
|
||||
private val urlOpener: UrlOpener,
|
||||
private val reduxStateHolder: ReduxStateHolder,
|
||||
private val designFeatureToggles: DesignFeatureToggles,
|
||||
) : InnerWalletRouter {
|
||||
|
||||
|
|
@ -117,10 +116,6 @@ internal class DefaultWalletRouter @Inject constructor(
|
|||
return router.stack.lastOrNull() is AppRoute.Wallet
|
||||
}
|
||||
|
||||
override fun openScanFailedDialog(onTryAgain: () -> Unit) {
|
||||
reduxStateHolder.dispatchDialogShow(StateDialog.ScanFailsDialog(StateDialog.ScanFailsSource.MAIN, onTryAgain))
|
||||
}
|
||||
|
||||
override fun openNFT(userWallet: UserWallet) {
|
||||
router.push(
|
||||
AppRoute.NFT(
|
||||
|
|
@ -168,10 +163,18 @@ internal class DefaultWalletRouter @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
override fun openTokenActionSheet(userWallet: UserWallet, tokenActionList: ImmutableList<TokenActionButtonUM>) {
|
||||
override fun openTokenActionSheet(
|
||||
userWallet: UserWallet,
|
||||
tokenActionList: ImmutableList<TokenActionButtonUM>,
|
||||
offset: Offset,
|
||||
tokenRowUM: TangemTokenRowUM?,
|
||||
) {
|
||||
dialogNavigation.activate(
|
||||
configuration = WalletDialogConfig.TokenActionList(
|
||||
actionList = tokenActionList,
|
||||
offsetX = offset.x,
|
||||
offsetY = offset.y,
|
||||
tokenRowUM = tokenRowUM,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
package com.tangem.feature.wallet.presentation.router
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import com.arkivanov.decompose.router.slot.SlotNavigation
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.core.ui.ds.row.token.TangemTokenRowUM
|
||||
import com.tangem.domain.models.TokenReceiveConfig
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
|
|
@ -66,9 +68,6 @@ internal interface InnerWalletRouter {
|
|||
/** Is wallet last screen */
|
||||
fun isWalletLastScreen(): Boolean
|
||||
|
||||
/** Open scan failed dialog */
|
||||
fun openScanFailedDialog(onTryAgain: () -> Unit)
|
||||
|
||||
/** Open NFT collections screen */
|
||||
fun openNFT(userWallet: UserWallet)
|
||||
|
||||
|
|
@ -89,7 +88,12 @@ internal interface InnerWalletRouter {
|
|||
fun openYieldSupplyEntryScreen(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency, apy: String)
|
||||
|
||||
/** Open token action sheet */
|
||||
fun openTokenActionSheet(userWallet: UserWallet, tokenActionList: ImmutableList<TokenActionButtonUM>)
|
||||
fun openTokenActionSheet(
|
||||
userWallet: UserWallet,
|
||||
tokenActionList: ImmutableList<TokenActionButtonUM>,
|
||||
offset: Offset,
|
||||
tokenRowUM: TangemTokenRowUM?,
|
||||
)
|
||||
|
||||
/** Open QR scanner screen */
|
||||
fun openQrScanner()
|
||||
|
|
|
|||
|
|
@ -155,18 +155,6 @@ sealed class WalletScreenAnalyticsEvent {
|
|||
|
||||
class DeleteWalletTapped : MainScreen(event = "Button - Delete Wallet Tapped")
|
||||
|
||||
class NoticeSeedPhraseSupport : MainScreen(event = "Notice - Seed Phrase Support")
|
||||
|
||||
class NoticeSeedPhraseSupportSecond : MainScreen(event = "Notice - Seed Phrase Support2")
|
||||
|
||||
class NoticeSeedPhraseSupportButtonNo : MainScreen(event = "Button - Support No")
|
||||
|
||||
class NoticeSeedPhraseSupportButtonYes : MainScreen(event = "Button - Support Yes")
|
||||
|
||||
class NoticeSeedPhraseSupportButtonUsed : MainScreen(event = "Button - Support Used")
|
||||
|
||||
class NoticeSeedPhraseSupportButtonDeclined : MainScreen(event = "Button - Support Declined")
|
||||
|
||||
class NoticeUnrecognizedQr : MainScreen(
|
||||
event = "Notice - Unrecognized QR",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -116,13 +116,12 @@ internal class WalletWarningsAnalyticsSender @Inject constructor(
|
|||
balanceState = balanceState,
|
||||
)
|
||||
}
|
||||
is WalletNotification.Critical.SeedPhraseNotification -> NoticeSeedPhraseSupport()
|
||||
is WalletNotification.Critical.SeedPhraseSecondNotification -> NoticeSeedPhraseSupportSecond()
|
||||
is WalletNotification.PushNotifications -> PushBanner()
|
||||
is WalletNotification.Warning.TangemPayRefreshNeeded -> null
|
||||
is WalletNotification.Warning.TangemPayUnreachable -> null
|
||||
is WalletNotification.UpgradeHotWalletPromo -> null
|
||||
is WalletNotification.TokenSyncCompleted -> null
|
||||
is WalletNotification.CreateTangemPayAccount -> null
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -162,8 +161,6 @@ internal class WalletWarningsAnalyticsSender @Inject constructor(
|
|||
balanceState = balanceState,
|
||||
)
|
||||
}
|
||||
is WalletNotificationUM.SeedPhraseNotification -> NoticeSeedPhraseSupport()
|
||||
is WalletNotificationUM.SeedPhraseSecondNotification -> NoticeSeedPhraseSupportSecond()
|
||||
is WalletNotificationUM.PushNotifications -> PushBanner()
|
||||
is WalletNotificationUM.UnlockWallets,
|
||||
is WalletNotificationUM.NoAccount,
|
||||
|
|
@ -171,6 +168,8 @@ internal class WalletWarningsAnalyticsSender @Inject constructor(
|
|||
WalletNotificationUM.SomeNetworksUnreachable,
|
||||
is WalletNotificationUM.UsedOutdatedData,
|
||||
is WalletNotificationUM.CloreMigration,
|
||||
is WalletNotificationUM.TangemPayRefreshNeeded,
|
||||
WalletNotificationUM.TangemPayUnreachable,
|
||||
-> null
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import com.tangem.core.ui.message.bottomSheetMessage
|
|||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.domain.wallets.usecase.SeedPhraseNotificationUseCase
|
||||
import com.tangem.feature.wallet.child.wallet.model.WalletActivationBannerType
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification
|
||||
|
|
@ -24,7 +23,6 @@ import javax.inject.Inject
|
|||
|
||||
@ModelScoped
|
||||
internal class WalletWarningsSingleEventSender @Inject constructor(
|
||||
private val seedPhraseNotificationUseCase: SeedPhraseNotificationUseCase,
|
||||
private val screenLifecycleProvider: ScreenLifecycleProvider,
|
||||
private val uiMessageSender: UiMessageSender,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
|
|
@ -32,11 +30,7 @@ internal class WalletWarningsSingleEventSender @Inject constructor(
|
|||
) {
|
||||
private val isActivationBottomSheetShown: ConcurrentHashMap<UserWalletId, Boolean> = ConcurrentHashMap()
|
||||
|
||||
suspend fun send(
|
||||
userWalletId: UserWalletId,
|
||||
displayedUiState: WalletState?,
|
||||
newWarnings: List<WalletNotification>,
|
||||
) {
|
||||
fun send(userWalletId: UserWalletId, displayedUiState: WalletState?, newWarnings: List<WalletNotification>) {
|
||||
if (screenLifecycleProvider.isBackgroundState.value) return
|
||||
if (newWarnings.isEmpty()) return
|
||||
if (displayedUiState == null || displayedUiState.pullToRefreshConfig.isRefreshing) return
|
||||
|
|
@ -51,9 +45,6 @@ internal class WalletWarningsSingleEventSender @Inject constructor(
|
|||
|
||||
events.forEach { event ->
|
||||
when (event) {
|
||||
is WalletNotification.Critical.SeedPhraseNotification -> {
|
||||
seedPhraseNotificationUseCase.notified(userWalletId = userWalletId)
|
||||
}
|
||||
is WalletNotification.FinishWalletActivation -> {
|
||||
// We check that map contains the first seen wallet (will return null instead false/true otherwise)
|
||||
// and for this wallet we haven't shown the activation bs yet (check that returns false, not true)
|
||||
|
|
@ -69,11 +60,7 @@ internal class WalletWarningsSingleEventSender @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
suspend fun send(
|
||||
userWalletId: UserWalletId,
|
||||
displayedWalletUM: WalletUM?,
|
||||
newNotifications: List<WalletNotificationUM>,
|
||||
) {
|
||||
fun send(userWalletId: UserWalletId, displayedWalletUM: WalletUM?, newNotifications: List<WalletNotificationUM>) {
|
||||
if (screenLifecycleProvider.isBackgroundState.value) return
|
||||
if (newNotifications.isEmpty()) return
|
||||
if (displayedWalletUM == null || displayedWalletUM.pullToRefreshConfig.isRefreshing) return
|
||||
|
|
@ -89,9 +76,6 @@ internal class WalletWarningsSingleEventSender @Inject constructor(
|
|||
|
||||
events.forEach { event ->
|
||||
when (event) {
|
||||
is WalletNotificationUM.SeedPhraseNotification -> {
|
||||
seedPhraseNotificationUseCase.notified(userWalletId = userWalletId)
|
||||
}
|
||||
is WalletNotificationUM.FinishWalletActivation -> {
|
||||
// We check that map contains the first seen wallet (will return null instead false/true otherwise)
|
||||
// and for this wallet we haven't shown the activation bs yet (check that returns false, not true)
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ import com.tangem.common.ui.userwallet.ext.walletInterationIcon
|
|||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.ui.components.notifications.NotificationConfig.ButtonsState
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.domain.account.models.AccountStatusList
|
||||
import com.tangem.domain.account.status.producer.SingleAccountStatusListProducer
|
||||
import com.tangem.domain.card.CardTypesResolver
|
||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||
import com.tangem.domain.core.lce.Lce
|
||||
import com.tangem.domain.demo.IsDemoCardUseCase
|
||||
import com.tangem.domain.hotwallet.CheckHotWalletUpgradeBannerUseCase
|
||||
import com.tangem.domain.hotwallet.GetAccessCodeSkippedUseCase
|
||||
|
|
@ -18,6 +18,8 @@ import com.tangem.domain.hotwallet.GetUpgradeBannerClosureTimestampUseCase
|
|||
import com.tangem.domain.hotwallet.ShouldShowUpgradeHotWalletBannerUseCase
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.TotalFiatBalance
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.domain.models.account.PaymentAccountStatusValue
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
|
|
@ -25,10 +27,10 @@ import com.tangem.domain.notifications.repository.NotificationsRepository
|
|||
import com.tangem.domain.promo.ShouldShowPromoWalletUseCase
|
||||
import com.tangem.domain.promo.models.PromoId
|
||||
import com.tangem.domain.settings.IsReadyToShowRateAppUseCase
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
import com.tangem.domain.wallets.models.SeedPhraseNotificationsStatus
|
||||
import com.tangem.domain.tokensync.model.TokenSyncProgress
|
||||
import com.tangem.domain.tokensync.usecase.ObserveTokenSyncUseCase
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
import com.tangem.domain.wallets.usecase.IsNeedToBackupUseCase
|
||||
import com.tangem.domain.wallets.usecase.SeedPhraseNotificationUseCase
|
||||
import com.tangem.feature.wallet.child.wallet.model.WalletActivationBannerType
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
|
|
@ -44,8 +46,8 @@ import kotlinx.collections.immutable.toImmutableList
|
|||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
import javax.inject.Inject
|
||||
|
||||
@Deprecated("Remove with main toggle [DesignFeatureToggles.isRedesignEnabled]")
|
||||
|
|
@ -56,7 +58,6 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
private val isReadyToShowRateAppUseCase: IsReadyToShowRateAppUseCase,
|
||||
private val isNeedToBackupUseCase: IsNeedToBackupUseCase,
|
||||
private val backupValidator: BackupValidator,
|
||||
private val seedPhraseNotificationUseCase: SeedPhraseNotificationUseCase,
|
||||
private val shouldShowPromoWalletUseCase: ShouldShowPromoWalletUseCase,
|
||||
private val notificationsRepository: NotificationsRepository,
|
||||
private val accountDependencies: AccountDependencies,
|
||||
|
|
@ -64,24 +65,26 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
private val shouldShowUpgradeHotWalletBannerUseCase: ShouldShowUpgradeHotWalletBannerUseCase,
|
||||
private val getUpgradeBannerClosureTimestampUseCase: GetUpgradeBannerClosureTimestampUseCase,
|
||||
private val checkHotWalletUpgradeBannerUseCase: CheckHotWalletUpgradeBannerUseCase,
|
||||
private val observeTokenSyncUseCase: ObserveTokenSyncUseCase,
|
||||
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
) {
|
||||
|
||||
@Suppress("UNCHECKED_CAST", "MagicNumber", "LongMethod", "CastNullableToNonNullableType")
|
||||
fun create(userWallet: UserWallet, clickIntents: WalletClickIntents): Flow<ImmutableList<WalletNotification>> {
|
||||
val cardTypesResolver = (userWallet as? UserWallet.Cold)?.scanResponse?.cardTypesResolver
|
||||
val params = SingleAccountStatusListProducer.Params(userWallet.walletId)
|
||||
val accountStatusListFlow = accountDependencies.singleAccountStatusListSupplier(params)
|
||||
|
||||
val accountStatusListFlow by lazy {
|
||||
val params = SingleAccountStatusListProducer.Params(userWallet.walletId)
|
||||
accountDependencies.singleAccountStatusListSupplier(params)
|
||||
.map { it.totalFiatBalance to it.flattenCurrencies() }
|
||||
.map { Lce.Content(it) }
|
||||
val tokenSyncProgressFlow = if (hotWalletFeatureToggles.isTokenSyncEnabled && userWallet is UserWallet.Hot) {
|
||||
observeTokenSyncUseCase(userWallet.walletId).distinctUntilChanged()
|
||||
} else {
|
||||
flowOf(TokenSyncProgress.Idle)
|
||||
}
|
||||
|
||||
return combine(
|
||||
accountStatusListFlow,
|
||||
isReadyToShowRateAppUseCase().distinctUntilChanged(),
|
||||
isNeedToBackupUseCase(userWallet.walletId).distinctUntilChanged(),
|
||||
seedPhraseNotificationUseCase(userWalletId = userWallet.walletId).distinctUntilChanged(),
|
||||
shouldShowPromoWalletUseCase(userWalletId = userWallet.walletId, promoId = PromoId.OnePlusOne)
|
||||
.distinctUntilChanged(),
|
||||
notificationsRepository.getShouldShowNotification(NotificationId.EnablePushesReminderNotification.key)
|
||||
|
|
@ -93,25 +96,29 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
.distinctUntilChanged(),
|
||||
getUpgradeBannerClosureTimestampUseCase(userWallet.walletId)
|
||||
.distinctUntilChanged(),
|
||||
tokenSyncProgressFlow,
|
||||
) { array -> array }
|
||||
.map { array ->
|
||||
val lceTokens = array[0] as Lce<TokenListError, Pair<TotalFiatBalance, List<CryptoCurrencyStatus>>>
|
||||
val totalFiatBalance = lceTokens.map { it.first }
|
||||
val flattenCurrencies = lceTokens.map { it.second }
|
||||
val accountStatusList = array[0] as AccountStatusList
|
||||
val isReadyToShowRating = array[1] as Boolean
|
||||
val isNeedToBackup = array[2] as Boolean
|
||||
val seedPhraseIssueStatus = array[3] as SeedPhraseNotificationsStatus
|
||||
val shouldShowOnePlusOnePromo = array[4] as Boolean
|
||||
val shouldShowEnablePushesReminderNotification = array[5] as Boolean
|
||||
val shouldAccessCodeSkipped = array[6] as Boolean
|
||||
val shouldShowYieldPromo = array[7] as Boolean
|
||||
val shouldShowUpgradeBanner = array[8] as Boolean
|
||||
val closureTimestamp = array[9] as? Long
|
||||
val shouldShowOnePlusOnePromo = array[3] as Boolean
|
||||
val shouldShowEnablePushesReminderNotification = array[4] as Boolean
|
||||
val shouldAccessCodeSkipped = array[5] as Boolean
|
||||
val shouldShowYieldPromo = array[6] as Boolean
|
||||
val shouldShowUpgradeBanner = array[7] as Boolean
|
||||
val closureTimestamp = array[8] as? Long
|
||||
val tokenSyncProgress = array[9] as TokenSyncProgress
|
||||
|
||||
val flattenCurrencies = accountStatusList.flattenCurrencies()
|
||||
val paymentAccountStatus = accountStatusList.accountStatuses
|
||||
.filterIsInstance<AccountStatus.Payment>()
|
||||
.firstOrNull()
|
||||
|
||||
buildList {
|
||||
addUsedOutdatedDataNotification(totalFiatBalance)
|
||||
addUsedOutdatedDataNotification(accountStatusList.totalFiatBalance)
|
||||
|
||||
addCriticalNotifications(userWallet, seedPhraseIssueStatus, clickIntents)
|
||||
addCriticalNotifications(userWallet, clickIntents)
|
||||
|
||||
addUpgradeHotWalletPromoNotification(
|
||||
userWallet = userWallet,
|
||||
|
|
@ -146,6 +153,12 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
clickIntents = clickIntents,
|
||||
)
|
||||
|
||||
addTokenSyncCompletedNotification(
|
||||
userWallet = userWallet,
|
||||
tokenSyncProgress = tokenSyncProgress,
|
||||
clickIntents = clickIntents,
|
||||
)
|
||||
|
||||
addPushReminderNotification(
|
||||
clickIntents = clickIntents,
|
||||
shouldShowPushReminderBanner = shouldShowEnablePushesReminderNotification &&
|
||||
|
|
@ -162,38 +175,65 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
if (!hasCriticalOrWarning) {
|
||||
addRateTheAppNotification(isReadyToShowRating, clickIntents)
|
||||
}
|
||||
|
||||
// add as last warning
|
||||
paymentAccountStatus?.let { paymentAccountStatus ->
|
||||
addTangemPayWarnings(
|
||||
status = paymentAccountStatus,
|
||||
userWallet = userWallet,
|
||||
walletClickIntents = clickIntents,
|
||||
)
|
||||
}
|
||||
}.toImmutableList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotification>.addUsedOutdatedDataNotification(
|
||||
totalFiatBalance: Lce<TokenListError, TotalFiatBalance>,
|
||||
private fun MutableList<WalletNotification>.addTangemPayWarnings(
|
||||
status: AccountStatus.Payment,
|
||||
userWallet: UserWallet,
|
||||
walletClickIntents: WalletClickIntents,
|
||||
) {
|
||||
val notification = when (status.value) {
|
||||
is PaymentAccountStatusValue.Error.NotSynced -> WalletNotification.Warning.TangemPayRefreshNeeded(
|
||||
buttonText = when (userWallet) {
|
||||
is UserWallet.Cold -> resourceReference(id = R.string.home_button_scan)
|
||||
is UserWallet.Hot -> resourceReference(id = R.string.tangempay_sync_needed_restore_access)
|
||||
},
|
||||
onRefreshClick = { walletClickIntents.onRefreshPayToken(userWallet) },
|
||||
shouldShowProgress = false,
|
||||
)
|
||||
is PaymentAccountStatusValue.NotCreated -> WalletNotification.CreateTangemPayAccount(
|
||||
onClick = { walletClickIntents.onOnboardingBannerClick(userWallet.walletId) },
|
||||
onCloseClick = { walletClickIntents.onOnboardingBannerCloseClick(userWallet.walletId) },
|
||||
)
|
||||
is PaymentAccountStatusValue.Error.Unavailable -> WalletNotification.Warning.TangemPayUnreachable
|
||||
is PaymentAccountStatusValue.Error.CardIssueFailed,
|
||||
is PaymentAccountStatusValue.Error.ExposedDevice,
|
||||
is PaymentAccountStatusValue.IssuingCard,
|
||||
is PaymentAccountStatusValue.Loaded,
|
||||
is PaymentAccountStatusValue.Loading,
|
||||
is PaymentAccountStatusValue.Locked,
|
||||
is PaymentAccountStatusValue.UnderReview,
|
||||
-> null
|
||||
}
|
||||
notification?.let(::add)
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotification>.addUsedOutdatedDataNotification(totalFiatBalance: TotalFiatBalance) {
|
||||
addIf(
|
||||
element = WalletNotification.UsedOutdatedData,
|
||||
condition = totalFiatBalance.fold(
|
||||
ifLoading = {
|
||||
(it as? TotalFiatBalance.Loaded)?.source == StatusSource.ONLY_CACHE
|
||||
},
|
||||
ifContent = {
|
||||
(it as? TotalFiatBalance.Loaded)?.source == StatusSource.ONLY_CACHE
|
||||
},
|
||||
ifError = { false },
|
||||
),
|
||||
condition = (totalFiatBalance as? TotalFiatBalance.Loaded)?.source == StatusSource.ONLY_CACHE,
|
||||
)
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotification>.addCriticalNotifications(
|
||||
userWallet: UserWallet,
|
||||
seedPhraseIssueStatus: SeedPhraseNotificationsStatus,
|
||||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
if (userWallet !is UserWallet.Cold) {
|
||||
return
|
||||
}
|
||||
|
||||
addSeedNotificationIfNeeded(userWallet, seedPhraseIssueStatus, clickIntents)
|
||||
|
||||
val cardTypesResolver = userWallet.scanResponse.cardTypesResolver
|
||||
addIf(
|
||||
element = WalletNotification.Critical.BackupError { clickIntents.onBackupErrorClick() },
|
||||
|
|
@ -218,43 +258,10 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotification>.addSeedNotificationIfNeeded(
|
||||
userWallet: UserWallet.Cold,
|
||||
seedPhraseIssueStatus: SeedPhraseNotificationsStatus,
|
||||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
val isNotificationAvailable = with(userWallet) {
|
||||
val isDemo = isDemoCardUseCase(cardId = userWallet.cardId)
|
||||
val isWalletWithSeedPhrase = scanResponse.cardTypesResolver.isWallet2() && userWallet.isImported
|
||||
|
||||
!isDemo && isWalletWithSeedPhrase
|
||||
}
|
||||
|
||||
when (seedPhraseIssueStatus) {
|
||||
SeedPhraseNotificationsStatus.SHOW_FIRST -> addIf(
|
||||
element = WalletNotification.Critical.SeedPhraseNotification(
|
||||
onDeclineClick = clickIntents::onSeedPhraseNotificationDecline,
|
||||
onConfirmClick = clickIntents::onSeedPhraseNotificationConfirm,
|
||||
),
|
||||
condition = isNotificationAvailable,
|
||||
)
|
||||
SeedPhraseNotificationsStatus.SHOW_SECOND -> addIf(
|
||||
element = WalletNotification.Critical.SeedPhraseSecondNotification(
|
||||
onDeclineClick = clickIntents::onSeedPhraseSecondNotificationReject,
|
||||
onConfirmClick = clickIntents::onSeedPhraseSecondNotificationAccept,
|
||||
),
|
||||
condition = isNotificationAvailable,
|
||||
)
|
||||
SeedPhraseNotificationsStatus.NOT_NEEDED -> {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotification>.addInformationalNotifications(
|
||||
userWallet: UserWallet,
|
||||
cardTypesResolver: CardTypesResolver?,
|
||||
flattenCurrencies: Lce<TokenListError, List<CryptoCurrencyStatus>>,
|
||||
flattenCurrencies: List<CryptoCurrencyStatus>,
|
||||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
addIf(
|
||||
|
|
@ -267,7 +274,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
|
||||
private fun MutableList<WalletNotification>.addMissingAddressesNotification(
|
||||
userWallet: UserWallet,
|
||||
flattenCurrencies: Lce<TokenListError, List<CryptoCurrencyStatus>>,
|
||||
flattenCurrencies: List<CryptoCurrencyStatus>,
|
||||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
val currencies = flattenCurrencies.getMissingAddressCurrencies()
|
||||
|
|
@ -285,10 +292,8 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private fun Lce<TokenListError, List<CryptoCurrencyStatus>>.getMissingAddressCurrencies(): List<CryptoCurrency> {
|
||||
val flattenCurrencies = getOrNull(isPartialContentAccepted = true) ?: return emptyList()
|
||||
|
||||
return flattenCurrencies
|
||||
private fun List<CryptoCurrencyStatus>.getMissingAddressCurrencies(): List<CryptoCurrency> {
|
||||
return this
|
||||
.filter { it.value is CryptoCurrencyStatus.MissedDerivation }
|
||||
.map(CryptoCurrencyStatus::currency)
|
||||
}
|
||||
|
|
@ -330,7 +335,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
|
||||
private fun MutableList<WalletNotification>.addWarningNotifications(
|
||||
cardTypesResolver: CardTypesResolver?,
|
||||
flattenCurrencies: Lce<TokenListError, List<CryptoCurrencyStatus>>,
|
||||
flattenCurrencies: List<CryptoCurrencyStatus>,
|
||||
isNeedToBackup: Boolean,
|
||||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
|
|
@ -355,7 +360,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
}
|
||||
|
||||
private fun MutableList<WalletNotification>.addCloreMigrationNotification(
|
||||
flattenCurrencies: Lce<TokenListError, List<CryptoCurrencyStatus>>,
|
||||
flattenCurrencies: List<CryptoCurrencyStatus>,
|
||||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
val cloreCurrency = flattenCurrencies.findCloreCurrency() ?: return
|
||||
|
|
@ -367,10 +372,8 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private fun Lce<TokenListError, List<CryptoCurrencyStatus>>.findCloreCurrency(): CryptoCurrencyStatus? {
|
||||
val currencies = getOrNull(isPartialContentAccepted = true) ?: return null
|
||||
|
||||
return currencies.find { currencyStatus ->
|
||||
private fun List<CryptoCurrencyStatus>.findCloreCurrency(): CryptoCurrencyStatus? {
|
||||
return this.find { currencyStatus ->
|
||||
BlockchainUtils.isClore(currencyStatus.currency.network.rawId)
|
||||
}
|
||||
}
|
||||
|
|
@ -388,10 +391,8 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private fun Lce<TokenListError, List<CryptoCurrencyStatus>>.hasUnreachableNetworks(): Boolean {
|
||||
val flattenCurrencies = getOrNull(isPartialContentAccepted = false) ?: return false
|
||||
|
||||
return flattenCurrencies.any { it.value is CryptoCurrencyStatus.Unreachable }
|
||||
private fun List<CryptoCurrencyStatus>.hasUnreachableNetworks(): Boolean {
|
||||
return this.any { it.value is CryptoCurrencyStatus.Unreachable }
|
||||
}
|
||||
|
||||
// Remove in first iteration of yield supply feature
|
||||
|
|
@ -403,6 +404,20 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
// }
|
||||
// }
|
||||
|
||||
private fun MutableList<WalletNotification>.addTokenSyncCompletedNotification(
|
||||
userWallet: UserWallet,
|
||||
tokenSyncProgress: TokenSyncProgress,
|
||||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
addIf(
|
||||
element = WalletNotification.TokenSyncCompleted(
|
||||
onCloseClick = { clickIntents.onDismissTokenSyncNotification(userWallet.walletId) },
|
||||
onManageTokensClick = { clickIntents.onTokenSyncManageClick(userWallet.walletId) },
|
||||
),
|
||||
condition = tokenSyncProgress is TokenSyncProgress.Completed,
|
||||
)
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotification>.addRateTheAppNotification(
|
||||
isReadyToShowRating: Boolean,
|
||||
clickIntents: WalletClickIntents,
|
||||
|
|
@ -427,7 +442,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
|
||||
private fun MutableList<WalletNotification>.addFinishWalletActivationNotification(
|
||||
userWallet: UserWallet,
|
||||
flattenCurrencies: Lce<TokenListError, List<CryptoCurrencyStatus>>,
|
||||
flattenCurrencies: List<CryptoCurrencyStatus>,
|
||||
clickIntents: WalletClickIntents,
|
||||
shouldAccessCodeSkipped: Boolean,
|
||||
) {
|
||||
|
|
@ -437,12 +452,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
val isAccessCodeRequired = userWallet.hotWalletId.authType == HotWalletId.AuthType.NoPassword &&
|
||||
!shouldAccessCodeSkipped
|
||||
val shouldShowFinishActivation = !isBackupExists || isAccessCodeRequired
|
||||
|
||||
val type = flattenCurrencies.fold(
|
||||
ifLoading = { return },
|
||||
ifContent = { it.getFinishWalletActivationType() },
|
||||
ifError = { WalletActivationBannerType.Attention },
|
||||
)
|
||||
val type = flattenCurrencies.getFinishWalletActivationType()
|
||||
|
||||
addIf(
|
||||
element = WalletNotification.FinishWalletActivation(
|
||||
|
|
@ -465,15 +475,14 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
|
||||
private suspend fun MutableList<WalletNotification>.addUpgradeHotWalletPromoNotification(
|
||||
userWallet: UserWallet,
|
||||
flattenCurrencies: Lce<TokenListError, List<CryptoCurrencyStatus>>,
|
||||
flattenCurrencies: List<CryptoCurrencyStatus>,
|
||||
clickIntents: WalletClickIntents,
|
||||
shouldShowUpgradeBanner: Boolean,
|
||||
closureTimestamp: Long?,
|
||||
) {
|
||||
if (userWallet !is UserWallet.Hot) return
|
||||
|
||||
val currencies = flattenCurrencies.getOrNull(isPartialContentAccepted = true).orEmpty()
|
||||
val hasBalance = currencies.any { it.value.amount.orZero().isPositive() }
|
||||
val hasBalance = flattenCurrencies.any { it.value.amount.orZero().isPositive() }
|
||||
|
||||
val shouldShow = checkHotWalletUpgradeBannerUseCase(
|
||||
walletId = userWallet.walletId,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.feature.wallet.presentation.wallet.domain
|
|||
import com.tangem.common.ui.userwallet.ext.walletInterationIcon
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.ui.ds.message.TangemMessageEffect
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.domain.account.status.producer.SingleAccountStatusListProducer
|
||||
import com.tangem.domain.card.CardTypesResolver
|
||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||
|
|
@ -10,14 +11,15 @@ import com.tangem.domain.demo.IsDemoCardUseCase
|
|||
import com.tangem.domain.hotwallet.GetAccessCodeSkippedUseCase
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.TotalFiatBalance
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.domain.models.account.PaymentAccountStatusValue
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.isMultiCurrency
|
||||
import com.tangem.domain.wallets.models.SeedPhraseNotificationsStatus
|
||||
import com.tangem.domain.wallets.usecase.IsNeedToBackupUseCase
|
||||
import com.tangem.domain.wallets.usecase.SeedPhraseNotificationUseCase
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.account.AccountDependencies
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotificationUM
|
||||
import com.tangem.hot.sdk.model.HotWalletId
|
||||
|
|
@ -40,7 +42,6 @@ internal class GetWalletNotificationsFactory @Inject constructor(
|
|||
private val isDemoCardUseCase: IsDemoCardUseCase,
|
||||
private val isNeedToBackupUseCase: IsNeedToBackupUseCase,
|
||||
private val backupValidator: BackupValidator,
|
||||
private val seedPhraseNotificationUseCase: SeedPhraseNotificationUseCase,
|
||||
private val accountDependencies: AccountDependencies,
|
||||
private val getAccessCodeSkippedUseCase: GetAccessCodeSkippedUseCase,
|
||||
private val hasSingleWalletSignedHashesUseCase: HasSingleWalletSignedHashesUseCase,
|
||||
|
|
@ -54,16 +55,19 @@ internal class GetWalletNotificationsFactory @Inject constructor(
|
|||
return combine(
|
||||
flow = accountStatusListFlow,
|
||||
flow2 = isNeedToBackupUseCase(userWallet.walletId).distinctUntilChanged(),
|
||||
flow3 = seedPhraseNotificationUseCase(userWalletId = userWallet.walletId).distinctUntilChanged(),
|
||||
flow4 = getAccessCodeSkippedUseCase(userWallet.walletId).distinctUntilChanged(),
|
||||
) { accountList, isNeedToBackup, seedPhraseIssueStatus, shouldAccessCodeSkipped ->
|
||||
flow3 = getAccessCodeSkippedUseCase(userWallet.walletId).distinctUntilChanged(),
|
||||
) { accountList, isNeedToBackup, shouldAccessCodeSkipped ->
|
||||
val totalFiatBalance = accountList.totalFiatBalance
|
||||
val flattenCurrencies = accountList.flattenCurrencies()
|
||||
|
||||
val paymentAccountStatus = accountList.accountStatuses
|
||||
.filterIsInstance<AccountStatus.Payment>()
|
||||
.firstOrNull()
|
||||
|
||||
buildList {
|
||||
addUsedOutdatedDataNotification(totalFiatBalance)
|
||||
|
||||
addCriticalNotifications(userWallet, seedPhraseIssueStatus, clickIntents)
|
||||
addCriticalNotifications(userWallet, clickIntents)
|
||||
|
||||
addFinishWalletActivationNotification(
|
||||
userWallet = userWallet,
|
||||
|
|
@ -86,6 +90,14 @@ internal class GetWalletNotificationsFactory @Inject constructor(
|
|||
isNeedToBackup = isNeedToBackup,
|
||||
clickIntents = clickIntents,
|
||||
)
|
||||
|
||||
if (paymentAccountStatus != null) {
|
||||
addTangemPayWarnings(
|
||||
status = paymentAccountStatus,
|
||||
userWallet = userWallet,
|
||||
walletClickIntents = clickIntents,
|
||||
)
|
||||
}
|
||||
}.sortedBy { it.type.ordinal }.toImmutableList()
|
||||
}
|
||||
}
|
||||
|
|
@ -99,15 +111,12 @@ internal class GetWalletNotificationsFactory @Inject constructor(
|
|||
|
||||
private fun MutableList<WalletNotificationUM>.addCriticalNotifications(
|
||||
userWallet: UserWallet,
|
||||
seedPhraseIssueStatus: SeedPhraseNotificationsStatus,
|
||||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
if (userWallet !is UserWallet.Cold) {
|
||||
return
|
||||
}
|
||||
|
||||
addSeedNotificationIfNeeded(userWallet, seedPhraseIssueStatus, clickIntents)
|
||||
|
||||
val cardTypesResolver = userWallet.scanResponse.cardTypesResolver
|
||||
addIf(
|
||||
element = WalletNotificationUM.BackupError { clickIntents.onSupportClick() },
|
||||
|
|
@ -207,6 +216,34 @@ internal class GetWalletNotificationsFactory @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotificationUM>.addTangemPayWarnings(
|
||||
status: AccountStatus.Payment,
|
||||
userWallet: UserWallet,
|
||||
walletClickIntents: WalletClickIntents,
|
||||
) {
|
||||
val notification = when (status.value) {
|
||||
is PaymentAccountStatusValue.Error.NotSynced -> WalletNotificationUM.TangemPayRefreshNeeded(
|
||||
buttonText = when (userWallet) {
|
||||
is UserWallet.Cold -> resourceReference(id = R.string.home_button_scan)
|
||||
is UserWallet.Hot -> resourceReference(id = R.string.tangempay_sync_needed_restore_access)
|
||||
},
|
||||
onRefreshClick = { walletClickIntents.onRefreshPayToken(userWallet) },
|
||||
shouldShowProgress = false,
|
||||
)
|
||||
is PaymentAccountStatusValue.NotCreated -> null // TODO(Main redesign)
|
||||
is PaymentAccountStatusValue.Error.Unavailable -> WalletNotificationUM.TangemPayUnreachable
|
||||
is PaymentAccountStatusValue.Error.CardIssueFailed,
|
||||
is PaymentAccountStatusValue.Error.ExposedDevice,
|
||||
is PaymentAccountStatusValue.IssuingCard,
|
||||
is PaymentAccountStatusValue.Loaded,
|
||||
is PaymentAccountStatusValue.Loading,
|
||||
is PaymentAccountStatusValue.Locked,
|
||||
is PaymentAccountStatusValue.UnderReview,
|
||||
-> null
|
||||
}
|
||||
notification?.let(::add)
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotificationUM>.addNoAccountWarning(cryptoCurrencyStatus: CryptoCurrencyStatus?) {
|
||||
val noAccountStatus = cryptoCurrencyStatus?.value as? CryptoCurrencyStatus.NoAccount
|
||||
if (noAccountStatus != null) {
|
||||
|
|
@ -279,37 +316,6 @@ internal class GetWalletNotificationsFactory @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotificationUM>.addSeedNotificationIfNeeded(
|
||||
userWallet: UserWallet.Cold,
|
||||
seedPhraseIssueStatus: SeedPhraseNotificationsStatus,
|
||||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
val isNotificationAvailable = with(userWallet) {
|
||||
val isDemo = isDemoCardUseCase(cardId = userWallet.cardId)
|
||||
val isWalletWithSeedPhrase = scanResponse.cardTypesResolver.isWallet2() && userWallet.isImported
|
||||
|
||||
!isDemo && isWalletWithSeedPhrase
|
||||
}
|
||||
|
||||
when (seedPhraseIssueStatus) {
|
||||
SeedPhraseNotificationsStatus.SHOW_FIRST -> addIf(
|
||||
element = WalletNotificationUM.SeedPhraseNotification(
|
||||
onDeclineClick = clickIntents::onSeedPhraseNotificationDecline,
|
||||
onConfirmClick = clickIntents::onSeedPhraseNotificationConfirm,
|
||||
),
|
||||
condition = isNotificationAvailable,
|
||||
)
|
||||
SeedPhraseNotificationsStatus.SHOW_SECOND -> addIf(
|
||||
element = WalletNotificationUM.SeedPhraseSecondNotification(
|
||||
onDeclineClick = clickIntents::onSeedPhraseSecondNotificationReject,
|
||||
onConfirmClick = clickIntents::onSeedPhraseSecondNotificationAccept,
|
||||
),
|
||||
condition = isNotificationAvailable,
|
||||
)
|
||||
SeedPhraseNotificationsStatus.NOT_NEEDED -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun hasSignedHashes(
|
||||
selectedWallet: UserWallet,
|
||||
cryptoCurrencyStatus: CryptoCurrencyStatus?,
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ import com.tangem.domain.demo.models.DemoConfig
|
|||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@ModelScoped
|
||||
|
|
@ -42,7 +42,7 @@ class HasSingleWalletSignedHashesUseCase @Inject constructor(
|
|||
},
|
||||
)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
Timber.w(e, "Unable to validate signature count: user wallet not found")
|
||||
TangemLogger.w("Unable to validate signature count: user wallet not found", e)
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
|||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import javax.inject.Inject
|
||||
|
||||
@ModelScoped
|
||||
|
|
@ -58,7 +58,7 @@ internal class OnrampStatusFactory @Inject constructor(
|
|||
if (!onrampTx.activeStatus.isTerminal) {
|
||||
getOnrampStatusUseCase(userWallet = userWallet, onrampTx.info.txId).fold(
|
||||
ifLeft = {
|
||||
Timber.e("Couldn't update onramp status. $it")
|
||||
TangemLogger.e("Couldn't update onramp status. $it")
|
||||
},
|
||||
ifRight = { statusModel ->
|
||||
val txId = statusModel.txId
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.domain
|
||||
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import com.tangem.domain.account.status.producer.SingleAccountStatusListProducer
|
||||
import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
|
||||
import timber.log.Timber
|
||||
|
||||
internal fun GetSelectedWalletSyncUseCase.unwrap(): UserWallet? {
|
||||
return this().fold(
|
||||
ifLeft = {
|
||||
Timber.e("Impossible to get selected wallet $it")
|
||||
ifLeft = { error ->
|
||||
TangemLogger.e("Impossible to get selected wallet $error")
|
||||
null
|
||||
},
|
||||
ifRight = { it },
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import com.tangem.domain.card.common.util.cardTypesResolver
|
|||
import com.tangem.domain.card.common.util.getCardsCount
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TokenSyncProgressUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletAdditionalInfo
|
||||
import java.math.BigDecimal
|
||||
|
||||
|
|
@ -28,7 +29,11 @@ internal object WalletAdditionalInfoFactory {
|
|||
* @param wallet current wallet
|
||||
* @param currencyAmount amount of currency
|
||||
*/
|
||||
fun resolve(wallet: UserWallet, currencyAmount: BigDecimal? = null): WalletAdditionalInfo {
|
||||
fun resolve(
|
||||
wallet: UserWallet,
|
||||
currencyAmount: BigDecimal? = null,
|
||||
syncProgress: TokenSyncProgressUM = TokenSyncProgressUM.Idle,
|
||||
): WalletAdditionalInfo {
|
||||
return when (wallet) {
|
||||
is UserWallet.Cold -> {
|
||||
if (wallet.isMultiCurrency) {
|
||||
|
|
@ -37,19 +42,26 @@ internal object WalletAdditionalInfoFactory {
|
|||
wallet.resolveSingleCurrencyInfo(currencyAmount)
|
||||
}
|
||||
}
|
||||
is UserWallet.Hot -> wallet.resolveAdditionalInfo()
|
||||
is UserWallet.Hot -> wallet.resolveAdditionalInfo(syncProgress)
|
||||
}
|
||||
}
|
||||
|
||||
private fun UserWallet.Hot.resolveAdditionalInfo(): WalletAdditionalInfo {
|
||||
private fun UserWallet.Hot.resolveAdditionalInfo(syncProgress: TokenSyncProgressUM): WalletAdditionalInfo {
|
||||
val content = if (syncProgress is TokenSyncProgressUM.InProgress) {
|
||||
WalletAdditionalInfo.Content.SyncProgress(syncProgress.progressPercent)
|
||||
} else {
|
||||
WalletAdditionalInfo.Content.Text(
|
||||
TextReference.Res(R.string.hw_mobile_wallet) +
|
||||
when {
|
||||
isLocked -> DIVIDER + TextReference.Res(R.string.common_locked)
|
||||
backedUp.not() -> DIVIDER + TextReference.Res(R.string.hw_backup_no_backup)
|
||||
else -> TextReference.Str("")
|
||||
},
|
||||
)
|
||||
}
|
||||
return WalletAdditionalInfo(
|
||||
hideable = false,
|
||||
content = TextReference.Res(R.string.hw_mobile_wallet) +
|
||||
when {
|
||||
isLocked -> DIVIDER + TextReference.Res(R.string.common_locked)
|
||||
backedUp.not() -> DIVIDER + TextReference.Res(R.string.hw_backup_no_backup)
|
||||
else -> TextReference.Str("")
|
||||
},
|
||||
content = content,
|
||||
isHotBackedUp = backedUp,
|
||||
)
|
||||
}
|
||||
|
|
@ -58,9 +70,11 @@ internal object WalletAdditionalInfoFactory {
|
|||
return if (isLocked) {
|
||||
WalletAdditionalInfo(
|
||||
hideable = false,
|
||||
content = getBackupInfoWithDivider(
|
||||
backupCardsCount = getCardsCount(),
|
||||
) + TextReference.Res(R.string.common_locked),
|
||||
content = WalletAdditionalInfo.Content.Text(
|
||||
getBackupInfoWithDivider(
|
||||
backupCardsCount = getCardsCount(),
|
||||
) + TextReference.Res(R.string.common_locked),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
val cardTypeResolver = scanResponse.cardTypesResolver
|
||||
|
|
@ -76,8 +90,10 @@ internal object WalletAdditionalInfoFactory {
|
|||
return if (isImported) {
|
||||
WalletAdditionalInfo(
|
||||
hideable = false,
|
||||
content = getBackupInfoWithDivider(backupCardsCount = getCardsCount()) + TextReference.Res(
|
||||
id = R.string.common_seed_phrase,
|
||||
content = WalletAdditionalInfo.Content.Text(
|
||||
getBackupInfoWithDivider(backupCardsCount = getCardsCount()) + TextReference.Res(
|
||||
id = R.string.common_seed_phrase,
|
||||
),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
|
|
@ -94,7 +110,7 @@ internal object WalletAdditionalInfoFactory {
|
|||
}
|
||||
|
||||
private fun getBackupInfo(backupCardsCount: Int?): WalletAdditionalInfo {
|
||||
val content = if (backupCardsCount != null) {
|
||||
val ref = if (backupCardsCount != null) {
|
||||
getBackupInfoTextReference(count = backupCardsCount)
|
||||
} else {
|
||||
TextReference.EMPTY
|
||||
|
|
@ -102,7 +118,7 @@ internal object WalletAdditionalInfoFactory {
|
|||
|
||||
return WalletAdditionalInfo(
|
||||
hideable = false,
|
||||
content = content,
|
||||
content = WalletAdditionalInfo.Content.Text(ref),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -118,7 +134,7 @@ internal object WalletAdditionalInfoFactory {
|
|||
return if (isLocked) {
|
||||
WalletAdditionalInfo(
|
||||
hideable = false,
|
||||
content = TextReference.Res(R.string.common_locked),
|
||||
content = WalletAdditionalInfo.Content.Text(TextReference.Res(R.string.common_locked)),
|
||||
)
|
||||
} else {
|
||||
val blockchain = scanResponse.cardTypesResolver.getBlockchain()
|
||||
|
|
@ -126,7 +142,7 @@ internal object WalletAdditionalInfoFactory {
|
|||
|
||||
WalletAdditionalInfo(
|
||||
hideable = true,
|
||||
content = TextReference.Str(value = amount.orEmpty()),
|
||||
content = WalletAdditionalInfo.Content.Text(TextReference.Str(value = amount.orEmpty())),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import kotlinx.coroutines.supervisorScope
|
|||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
|
@ -45,7 +45,7 @@ internal class WalletContentFetcher @Inject constructor(
|
|||
* (doesn't matter if it is active or not), then skip the update process.
|
||||
*/
|
||||
if (!forceUpdate && savedJobHolder != null && !savedJobHolder.isEmpty()) {
|
||||
Timber.d("Skip fetching for $userWalletId")
|
||||
TangemLogger.d("Skip fetching for $userWalletId")
|
||||
|
||||
return@withContext
|
||||
}
|
||||
|
|
@ -55,7 +55,7 @@ internal class WalletContentFetcher @Inject constructor(
|
|||
* then cancel the previous update.
|
||||
*/
|
||||
if (forceUpdate && savedJobHolder?.isActive == true) {
|
||||
Timber.d("Cancel old fetching for $userWalletId")
|
||||
TangemLogger.d("Cancel old fetching for $userWalletId")
|
||||
|
||||
savedJobHolder.cancel()
|
||||
}
|
||||
|
|
@ -63,7 +63,7 @@ internal class WalletContentFetcher @Inject constructor(
|
|||
JobHolder().also { fetchingJobMap[userWalletId] = it }
|
||||
}
|
||||
|
||||
Timber.d("Start fetching for $userWalletId")
|
||||
TangemLogger.d("Start fetching for $userWalletId")
|
||||
|
||||
val maybeResult = launch {
|
||||
walletBalanceFetcher(
|
||||
|
|
@ -71,11 +71,11 @@ internal class WalletContentFetcher @Inject constructor(
|
|||
userWalletId = userWalletId,
|
||||
isPaymentAccountRefactorEnabled = tangemPayFeatureToggles.isTangemPayAccountsRefactorEnabled,
|
||||
),
|
||||
).onLeft(Timber::e)
|
||||
).onLeft { TangemLogger.e("Error", it) }
|
||||
}
|
||||
.saveInAndJoin(jobHolder)
|
||||
|
||||
Timber.d("Finish fetching with result $maybeResult for $userWalletId")
|
||||
TangemLogger.d("Finish fetching with result $maybeResult for $userWalletId")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ package com.tangem.feature.wallet.presentation.wallet.domain
|
|||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.models.wallet.copy
|
||||
import com.tangem.domain.wallets.repository.WalletNamesMigrationRepository
|
||||
import timber.log.Timber
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
|
||||
class WalletNameMigrationUseCase(
|
||||
private val userWalletsListRepository: UserWalletsListRepository,
|
||||
|
|
@ -17,13 +17,13 @@ class WalletNameMigrationUseCase(
|
|||
|
||||
val wallets = userWalletsListRepository.userWalletsSync()
|
||||
val existingNames: MutableSet<String> = mutableSetOf()
|
||||
wallets.forEach {
|
||||
val defaultName = it.name
|
||||
wallets.forEach { wallet ->
|
||||
val defaultName = wallet.name
|
||||
val suggestedWalletName = suggestedWalletName(defaultName, existingNames)
|
||||
if (defaultName != suggestedWalletName) {
|
||||
userWalletsListRepository.saveWithoutLock(it.copy(name = suggestedWalletName), canOverride = true)
|
||||
userWalletsListRepository.saveWithoutLock(wallet.copy(name = suggestedWalletName), canOverride = true)
|
||||
}
|
||||
Timber.tag("Migrated names").e(it.walletId.toString() + " " + suggestedWalletName)
|
||||
TangemLogger.withTag("Migrated names").e(wallet.walletId.toString() + " " + suggestedWalletName)
|
||||
}
|
||||
|
||||
walletNamesMigrationRepository.setMigrationDone()
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import com.tangem.domain.models.wallet.isLocked
|
|||
import kotlinx.coroutines.CloseableCoroutineDispatcher
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.newSingleThreadContext
|
||||
import timber.log.Timber
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
|
|
@ -45,19 +45,19 @@ internal class WalletScreenContentLoader @Inject constructor(
|
|||
storage.remove(id)
|
||||
loadInternal(userWallet, coroutineScope, isRefresh = true)
|
||||
} else {
|
||||
Timber.d("$id content loading has already started")
|
||||
TangemLogger.d("$id content loading has already started")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Cancel loading by [id] */
|
||||
fun cancel(id: UserWalletId) {
|
||||
Timber.d("$id content loading is canceled")
|
||||
TangemLogger.d("$id content loading is canceled")
|
||||
storage.remove(id)
|
||||
}
|
||||
|
||||
fun cancelAll() {
|
||||
Timber.d("All content loading is canceled")
|
||||
TangemLogger.d("All content loading is canceled")
|
||||
storage.clear()
|
||||
singleBackgroundDispatcher.close()
|
||||
}
|
||||
|
|
@ -69,11 +69,11 @@ internal class WalletScreenContentLoader @Inject constructor(
|
|||
)
|
||||
|
||||
if (loader == null) {
|
||||
Timber.e("Impossible to create loader for $userWallet")
|
||||
TangemLogger.e("Impossible to create loader for $userWallet")
|
||||
return
|
||||
}
|
||||
|
||||
Timber.d("${userWallet.walletId} content loading is ${if (isRefresh) "re" else ""}started")
|
||||
TangemLogger.d("${userWallet.walletId} content loading is ${if (isRefresh) "re" else ""}started")
|
||||
|
||||
loader.subscribers
|
||||
.map { it.subscribe(coroutineScope, singleBackgroundDispatcher) }
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
|
|||
import com.tangem.core.ui.DesignFeatureToggles
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.subscribers.*
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
|
@ -17,11 +18,13 @@ internal class MultiWalletContentLoader @AssistedInject constructor(
|
|||
private val walletNotificationsSubscriberFactory: WalletNotificationsSubscriber.Factory,
|
||||
private val multiWalletActionButtonsSubscriberFactory: MultiWalletActionButtonsSubscriber.Factory,
|
||||
private val tangemPayMainSubscriberFactory: TangemPayMainSubscriber.Factory,
|
||||
private val tokenSyncSubscriberFactory: TokenSyncSubscriber.Factory,
|
||||
private val tokenListAnalyticsSubscriberFactory: TokenListAnalyticsSubscriber.Factory,
|
||||
private val designFeatureToggles: DesignFeatureToggles,
|
||||
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
) : WalletContentLoader(id = userWallet.walletId) {
|
||||
|
||||
override fun create(): List<WalletSubscriber> = listOf(
|
||||
override fun create(): List<WalletSubscriber> = listOfNotNull(
|
||||
accountListSubscriberFactory.create(userWallet),
|
||||
walletNFTListSubscriberFactory.create(userWallet),
|
||||
checkWalletWithFundsSubscriberFactory.create(userWallet),
|
||||
|
|
@ -33,6 +36,11 @@ internal class MultiWalletContentLoader @AssistedInject constructor(
|
|||
multiWalletActionButtonsSubscriberFactory.create(userWallet),
|
||||
tangemPayMainSubscriberFactory.create(userWallet),
|
||||
tokenListAnalyticsSubscriberFactory.create(userWallet),
|
||||
if (hotWalletFeatureToggles.isTokenSyncEnabled && userWallet is UserWallet.Hot) {
|
||||
tokenSyncSubscriberFactory.create(userWallet)
|
||||
} else {
|
||||
null
|
||||
},
|
||||
)
|
||||
|
||||
@AssistedFactory
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import kotlinx.collections.immutable.persistentListOf
|
|||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import timber.log.Timber
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ internal class WalletStateController @Inject constructor(
|
|||
}
|
||||
|
||||
fun update(transformer: WalletScreenStateTransformer) {
|
||||
Timber.d("Applying: ${transformer::class.simpleName}")
|
||||
TangemLogger.d("Applying: ${transformer::class.simpleName}")
|
||||
mutableUiState.update(function = transformer::transform)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.model
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.runtime.Stable
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
|
@ -13,11 +14,14 @@ import kotlinx.serialization.Serializable
|
|||
* @property isWarning if warning row
|
||||
* @property isEnabled enabled
|
||||
*/
|
||||
@Stable
|
||||
@Serializable
|
||||
data class TokenActionButtonUM(
|
||||
val id: String,
|
||||
val text: TextReference,
|
||||
@DrawableRes val iconResId: Int,
|
||||
val onClick: () -> Unit,
|
||||
val isWarning: Boolean,
|
||||
val isEnabled: Boolean = true,
|
||||
val hasDivider: Boolean = false,
|
||||
)
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.model
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
|
||||
@Immutable
|
||||
internal sealed class TokenSyncProgressUM {
|
||||
|
||||
data object Idle : TokenSyncProgressUM()
|
||||
|
||||
data class InProgress(val progressPercent: Int) : TokenSyncProgressUM()
|
||||
|
||||
data object Completed : TokenSyncProgressUM()
|
||||
}
|
||||
|
|
@ -6,7 +6,12 @@ import com.tangem.core.ui.extensions.TextReference
|
|||
@Immutable
|
||||
data class WalletAdditionalInfo(
|
||||
val hideable: Boolean,
|
||||
val content: TextReference,
|
||||
val content: Content,
|
||||
val isHotBackedUp: Boolean = false,
|
||||
val shouldShowProgress: Boolean = false,
|
||||
)
|
||||
) {
|
||||
@Immutable
|
||||
sealed interface Content {
|
||||
data class Text(val text: TextReference) : Content
|
||||
data class SyncProgress(val progressPercent: Int) : Content
|
||||
}
|
||||
}
|
||||
|
|
@ -9,24 +9,6 @@ import com.tangem.feature.wallet.impl.R
|
|||
|
||||
internal object WalletAlertUM {
|
||||
|
||||
fun seedPhraseConfirm(onClick: () -> Unit): DialogMessage {
|
||||
return DialogMessage(
|
||||
message = resourceReference(R.string.warning_seedphrase_issue_answer_yes),
|
||||
firstActionBuilder = {
|
||||
okAction(onClick = onClick)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fun seedPhraseDismiss(onClick: () -> Unit): DialogMessage {
|
||||
return DialogMessage(
|
||||
message = resourceReference(R.string.warning_seedphrase_issue_answer_no),
|
||||
firstActionBuilder = {
|
||||
okAction(onClick = onClick)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fun unableHideToken(cryptoCurrency: CryptoCurrency): DialogMessage {
|
||||
return DialogMessage(
|
||||
title = resourceReference(
|
||||
|
|
|
|||
|
|
@ -85,7 +85,10 @@ internal sealed interface WalletCardState {
|
|||
|
||||
private companion object {
|
||||
val defaultAdditionalInfo: WalletAdditionalInfo
|
||||
get() = WalletAdditionalInfo(hideable = true, content = EMPTY_BALANCE_TEXT)
|
||||
get() = WalletAdditionalInfo(
|
||||
hideable = true,
|
||||
content = WalletAdditionalInfo.Content.Text(EMPTY_BALANCE_TEXT),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.model
|
||||
|
||||
import com.tangem.core.ui.ds.row.token.TangemTokenRowUM
|
||||
import com.tangem.domain.models.TokenReceiveConfig
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.account.AccountName
|
||||
|
|
@ -34,6 +35,9 @@ internal sealed interface WalletDialogConfig {
|
|||
@Serializable
|
||||
data class TokenActionList(
|
||||
val actionList: ImmutableList<TokenActionButtonUM>,
|
||||
val tokenRowUM: TangemTokenRowUM?,
|
||||
val offsetY: Float,
|
||||
val offsetX: Float,
|
||||
) : WalletDialogConfig
|
||||
|
||||
@Serializable
|
||||
|
|
|
|||
|
|
@ -55,34 +55,6 @@ sealed class WalletNotification(val config: NotificationConfig) {
|
|||
onClick = onSupportClick,
|
||||
),
|
||||
)
|
||||
|
||||
data class SeedPhraseNotification(
|
||||
val onDeclineClick: () -> Unit,
|
||||
val onConfirmClick: () -> Unit,
|
||||
) : Critical(
|
||||
title = resourceReference(R.string.warning_seedphrase_issue_title),
|
||||
subtitle = resourceReference(R.string.warning_seedphrase_issue_message),
|
||||
buttonsState = NotificationConfig.ButtonsState.SecondaryPairButtonsConfig(
|
||||
leftText = resourceReference(R.string.common_no),
|
||||
onLeftClick = onDeclineClick,
|
||||
rightText = resourceReference(R.string.common_yes),
|
||||
onRightClick = onConfirmClick,
|
||||
),
|
||||
)
|
||||
|
||||
data class SeedPhraseSecondNotification(
|
||||
val onDeclineClick: () -> Unit,
|
||||
val onConfirmClick: () -> Unit,
|
||||
) : Critical(
|
||||
title = resourceReference(R.string.warning_seedphrase_action_required_title),
|
||||
subtitle = resourceReference(R.string.warning_seedphrase_contacted_support),
|
||||
buttonsState = NotificationConfig.ButtonsState.SecondaryPairButtonsConfig(
|
||||
leftText = resourceReference(R.string.seed_warning_no),
|
||||
onLeftClick = onDeclineClick,
|
||||
rightText = resourceReference(R.string.seed_warning_yes),
|
||||
onRightClick = onConfirmClick,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
sealed class Warning(
|
||||
|
|
@ -151,7 +123,6 @@ sealed class WalletNotification(val config: NotificationConfig) {
|
|||
)
|
||||
|
||||
data class TangemPayRefreshNeeded(
|
||||
@DrawableRes private val tangemIcon: Int?,
|
||||
private val onRefreshClick: () -> Unit,
|
||||
private val buttonText: TextReference,
|
||||
private val shouldShowProgress: Boolean,
|
||||
|
|
@ -160,7 +131,7 @@ sealed class WalletNotification(val config: NotificationConfig) {
|
|||
subtitle = resourceReference(id = R.string.tangempay_use_tangem_device_to_restore_payment_account),
|
||||
buttonsState = ButtonsState.PrimaryButtonConfig(
|
||||
text = buttonText,
|
||||
iconResId = tangemIcon,
|
||||
iconResId = R.drawable.ic_tangem_24,
|
||||
onClick = onRefreshClick,
|
||||
shouldShowProgress = shouldShowProgress,
|
||||
),
|
||||
|
|
@ -480,4 +451,11 @@ sealed class WalletNotification(val config: NotificationConfig) {
|
|||
),
|
||||
),
|
||||
)
|
||||
|
||||
data class CreateTangemPayAccount(val onClick: () -> Unit, val onCloseClick: () -> Unit) : WalletNotification(
|
||||
config = NotificationConfig(
|
||||
subtitle = resourceReference(R.string.tangempay_onboarding_banner_description),
|
||||
iconResId = R.drawable.img_tangem_pay_visa_banner,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -7,10 +7,7 @@ import com.tangem.core.ui.ds.image.TangemIconUM
|
|||
import com.tangem.core.ui.ds.message.TangemMessageButtonUM
|
||||
import com.tangem.core.ui.ds.message.TangemMessageEffect
|
||||
import com.tangem.core.ui.ds.message.TangemMessageUM
|
||||
import com.tangem.core.ui.extensions.pluralReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
|
@ -143,64 +140,6 @@ internal sealed class WalletNotificationUM(val messageUM: TangemMessageUM, val t
|
|||
type = WalletNotificationType.Critical,
|
||||
)
|
||||
|
||||
data class SeedPhraseNotification(
|
||||
val onDeclineClick: () -> Unit,
|
||||
val onConfirmClick: () -> Unit,
|
||||
) : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "SeedPhraseIssueNotification",
|
||||
title = resourceReference(id = R.string.warning_seedphrase_issue_title),
|
||||
subtitle = resourceReference(id = R.string.warning_seedphrase_issue_message),
|
||||
messageEffect = TangemMessageEffect.Warning,
|
||||
buttonsUM = persistentListOf(
|
||||
TangemMessageButtonUM(
|
||||
text = resourceReference(id = R.string.common_no),
|
||||
type = TangemButtonType.PrimaryInverse,
|
||||
onClick = onDeclineClick,
|
||||
),
|
||||
TangemMessageButtonUM(
|
||||
text = resourceReference(id = R.string.common_yes),
|
||||
type = TangemButtonType.PrimaryInverse,
|
||||
onClick = onConfirmClick,
|
||||
),
|
||||
),
|
||||
iconUM = TangemIconUM.Icon(
|
||||
iconRes = R.drawable.ic_attention_default_24,
|
||||
tintReference = { TangemTheme.colors2.graphic.neutral.primary },
|
||||
),
|
||||
),
|
||||
type = WalletNotificationType.Critical,
|
||||
)
|
||||
|
||||
data class SeedPhraseSecondNotification(
|
||||
val onDeclineClick: () -> Unit,
|
||||
val onConfirmClick: () -> Unit,
|
||||
) : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "SeedPhraseSecondIssueNotification",
|
||||
title = resourceReference(id = R.string.warning_seedphrase_action_required_title),
|
||||
subtitle = resourceReference(id = R.string.warning_seedphrase_contacted_support),
|
||||
messageEffect = TangemMessageEffect.Warning,
|
||||
iconUM = TangemIconUM.Icon(
|
||||
iconRes = R.drawable.ic_attention_default_24,
|
||||
tintReference = { TangemTheme.colors2.graphic.neutral.primary },
|
||||
),
|
||||
buttonsUM = persistentListOf(
|
||||
TangemMessageButtonUM(
|
||||
text = resourceReference(id = R.string.seed_warning_no),
|
||||
type = TangemButtonType.PrimaryInverse,
|
||||
onClick = onDeclineClick,
|
||||
),
|
||||
TangemMessageButtonUM(
|
||||
text = resourceReference(id = R.string.seed_warning_yes),
|
||||
type = TangemButtonType.PrimaryInverse,
|
||||
onClick = onConfirmClick,
|
||||
),
|
||||
),
|
||||
),
|
||||
type = WalletNotificationType.Critical,
|
||||
)
|
||||
|
||||
data class MissingBackup(val onClick: () -> Unit) : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "MissingBackupNotification",
|
||||
|
|
@ -355,6 +294,43 @@ internal sealed class WalletNotificationUM(val messageUM: TangemMessageUM, val t
|
|||
),
|
||||
type = WalletNotificationType.Warning,
|
||||
)
|
||||
|
||||
data class TangemPayRefreshNeeded(
|
||||
private val onRefreshClick: () -> Unit,
|
||||
private val buttonText: TextReference,
|
||||
private val shouldShowProgress: Boolean,
|
||||
) : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "TangemPayRefreshNeeded",
|
||||
title = resourceReference(id = R.string.tangempay_payment_account_sync_needed),
|
||||
subtitle = resourceReference(id = R.string.tangempay_use_tangem_device_to_restore_payment_account),
|
||||
buttonsUM = persistentListOf(
|
||||
TangemMessageButtonUM(
|
||||
text = buttonText,
|
||||
iconRes = R.drawable.ic_tangem_24,
|
||||
onClick = onRefreshClick,
|
||||
type = TangemButtonType.Primary,
|
||||
isLoading = shouldShowProgress,
|
||||
),
|
||||
),
|
||||
messageEffect = TangemMessageEffect.Card,
|
||||
isCentered = true,
|
||||
),
|
||||
type = WalletNotificationType.Warning,
|
||||
)
|
||||
|
||||
data object TangemPayUnreachable : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "TangemPayUnreachable",
|
||||
title = resourceReference(id = R.string.tangempay_temporarily_unavailable),
|
||||
subtitle = resourceReference(id = R.string.tangempay_service_unreachable_try_later),
|
||||
iconUM = TangemIconUM.Icon(
|
||||
iconRes = R.drawable.ic_attention_default_24,
|
||||
tintReference = { TangemTheme.colors2.graphic.status.attention },
|
||||
),
|
||||
),
|
||||
type = WalletNotificationType.Warning,
|
||||
)
|
||||
// endregion
|
||||
|
||||
// region Promo
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.holder.LockedTx
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.model.holder.LockedWalletStateHolder
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.holder.TxHistoryStateHolder
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.holder.WalletStateHolder
|
||||
import com.tangem.features.tangempay.entity.TangemPayMainUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
|
||||
|
|
@ -24,6 +25,9 @@ internal sealed interface WalletState : WalletStateHolder {
|
|||
abstract val nftState: WalletNFTItemUM
|
||||
abstract val type: WalletType
|
||||
abstract val tangemPayState: TangemPayState
|
||||
abstract val tangemPayMainUM: TangemPayMainUM
|
||||
abstract val isTangemPayRefactorEnabled: Boolean // TANGEM_PAY_ACCOUNTS_REFACTOR_ENABLED
|
||||
abstract val tokenSyncProgressUM: TokenSyncProgressUM
|
||||
|
||||
data class Content(
|
||||
override val pullToRefreshConfig: PullToRefreshConfig,
|
||||
|
|
@ -35,6 +39,9 @@ internal sealed interface WalletState : WalletStateHolder {
|
|||
override val nftState: WalletNFTItemUM,
|
||||
override val type: WalletType,
|
||||
override val tangemPayState: TangemPayState,
|
||||
override val tangemPayMainUM: TangemPayMainUM,
|
||||
override val isTangemPayRefactorEnabled: Boolean,
|
||||
override val tokenSyncProgressUM: TokenSyncProgressUM = TokenSyncProgressUM.Idle,
|
||||
) : MultiCurrency()
|
||||
|
||||
data class Locked(
|
||||
|
|
@ -54,6 +61,9 @@ internal sealed interface WalletState : WalletStateHolder {
|
|||
override val tokensListState = WalletTokensListState.ContentState.Locked
|
||||
override val nftState: WalletNFTItemUM = WalletNFTItemUM.Hidden
|
||||
override val tangemPayState: TangemPayState = TangemPayState.Empty
|
||||
override val tangemPayMainUM: TangemPayMainUM = TangemPayMainUM.Empty
|
||||
override val isTangemPayRefactorEnabled: Boolean = false
|
||||
override val tokenSyncProgressUM: TokenSyncProgressUM = TokenSyncProgressUM.Idle
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.feature.wallet.presentation.wallet.state.model
|
|||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig
|
||||
import com.tangem.core.ui.ds.button.TangemButtonUM
|
||||
import com.tangem.features.tangempay.entity.TangemPayMainUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
|
@ -23,7 +24,7 @@ internal sealed interface WalletUM {
|
|||
|
||||
val type: WalletType
|
||||
|
||||
val tangemPayState: TangemPayState
|
||||
val tangemPayMainUM: TangemPayMainUM
|
||||
|
||||
data class Content(
|
||||
override val pullToRefreshConfig: PullToRefreshConfig,
|
||||
|
|
@ -34,7 +35,7 @@ internal sealed interface WalletUM {
|
|||
override val tokensListUM: WalletTokensListUM,
|
||||
override val nftState: WalletNFTItemUM,
|
||||
override val type: WalletType,
|
||||
override val tangemPayState: TangemPayState,
|
||||
override val tangemPayMainUM: TangemPayMainUM,
|
||||
) : WalletUM
|
||||
|
||||
data class Locked(
|
||||
|
|
@ -47,6 +48,6 @@ internal sealed interface WalletUM {
|
|||
override val pullToRefreshConfig = PullToRefreshConfig(false, {})
|
||||
override val tokensListUM: WalletTokensListUM = WalletTokensListUM.Locked
|
||||
override val nftState: WalletNFTItemUM = WalletNFTItemUM.Hidden
|
||||
override val tangemPayState: TangemPayState = TangemPayState.Empty
|
||||
override val tangemPayMainUM: TangemPayMainUM = TangemPayMainUM.Empty
|
||||
}
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@ internal class AddWalletTransformer(
|
|||
private val clickIntents: WalletClickIntents,
|
||||
private val walletImageResolver: WalletImageResolver,
|
||||
private val getWalletIconUseCase: GetWalletIconUseCase,
|
||||
private val isTangemPayRefactorEnabled: Boolean,
|
||||
) : WalletScreenStateTransformer {
|
||||
|
||||
private val walletLoadingStateFactory by lazy {
|
||||
|
|
@ -20,6 +21,7 @@ internal class AddWalletTransformer(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isTangemPayRefactorEnabled = isTangemPayRefactorEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.WalletScreenSta
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import timber.log.Timber
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
|
||||
internal class DeleteWalletTransformer(
|
||||
private val selectedWalletIndex: Int,
|
||||
|
|
@ -31,7 +31,7 @@ internal class DeleteWalletTransformer(
|
|||
wallets = (prevState.wallets - deletedWalletState).toImmutableList(),
|
||||
)
|
||||
else -> {
|
||||
Timber.e("Wallets does not contain deleted wallet")
|
||||
TangemLogger.e("Wallets does not contain deleted wallet")
|
||||
prevState
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ internal class InitializeWalletsTransformer(
|
|||
private val walletImageResolver: WalletImageResolver,
|
||||
private val getWalletIconUseCase: GetWalletIconUseCase,
|
||||
private val isMainScreenQrScanningEnabled: Boolean = false,
|
||||
private val isTangemPayRefactorEnabled: Boolean,
|
||||
) : WalletScreenStateTransformer {
|
||||
|
||||
private val walletLoadingStateFactory by lazy {
|
||||
|
|
@ -35,6 +36,7 @@ internal class InitializeWalletsTransformer(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isTangemPayRefactorEnabled = isTangemPayRefactorEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ internal class ReinitializeNewWalletTransformer(
|
|||
private val clickIntents: WalletClickIntents,
|
||||
private val walletImageResolver: WalletImageResolver,
|
||||
private val getWalletIconUseCase: GetWalletIconUseCase,
|
||||
private val isTangemPayRefactorEnabled: Boolean,
|
||||
) : WalletScreenStateTransformer {
|
||||
|
||||
private val walletLoadingStateFactory by lazy {
|
||||
|
|
@ -31,6 +32,7 @@ internal class ReinitializeNewWalletTransformer(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isTangemPayRefactorEnabled = isTangemPayRefactorEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ internal class ReinitializeWalletTransformer(
|
|||
private val clickIntents: WalletClickIntents,
|
||||
private val walletImageResolver: WalletImageResolver,
|
||||
private val getWalletIconUseCase: GetWalletIconUseCase,
|
||||
private val isTangemPayRefactorEnabled: Boolean,
|
||||
) : WalletStateTransformer(userWalletId = userWallet.walletId) {
|
||||
|
||||
private val walletLoadingStateFactory by lazy {
|
||||
|
|
@ -27,6 +28,7 @@ internal class ReinitializeWalletTransformer(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isTangemPayRefactorEnabled = isTangemPayRefactorEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import timber.log.Timber
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
|
||||
/**
|
||||
* Transformer that renames wallets
|
||||
|
|
@ -51,7 +51,7 @@ internal class RenameWalletsTransformer(
|
|||
is WalletState.MultiCurrency.Locked,
|
||||
is WalletState.SingleCurrency.Locked,
|
||||
-> {
|
||||
Timber.e("Impossible to rename wallet in locked state")
|
||||
TangemLogger.e("Impossible to rename wallet in locked state")
|
||||
prevState
|
||||
}
|
||||
}
|
||||
|
|
@ -63,7 +63,7 @@ internal class RenameWalletsTransformer(
|
|||
prevState.copy(walletsBalanceUM = prevState.walletsBalanceUM.copySealed(name = newName))
|
||||
}
|
||||
is WalletUM.Locked -> {
|
||||
Timber.e("Impossible to rename wallet in locked state")
|
||||
TangemLogger.e("Impossible to rename wallet in locked state")
|
||||
prevState
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import timber.log.Timber
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
|
||||
internal class SetCryptoCurrencyActionsTransformer(
|
||||
private val tokenActionsState: TokenActionsState,
|
||||
|
|
@ -26,11 +26,11 @@ internal class SetCryptoCurrencyActionsTransformer(
|
|||
prevState.copy(buttons = tokenActionsState.toManageButtons())
|
||||
}
|
||||
is WalletState.SingleCurrency.Locked -> {
|
||||
Timber.w("Impossible to load primary currency status for locked wallet")
|
||||
TangemLogger.w("Impossible to load primary currency status for locked wallet")
|
||||
prevState
|
||||
}
|
||||
is WalletState.MultiCurrency -> {
|
||||
Timber.w("Impossible to load crypto currency actions for multi-currency wallet")
|
||||
TangemLogger.w("Impossible to load crypto currency actions for multi-currency wallet")
|
||||
prevState
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.SingleWalletOnrampTransactionConverter
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import timber.log.Timber
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
|
||||
internal class SetExpressStatusesTransformer(
|
||||
userWalletId: UserWalletId,
|
||||
|
|
@ -47,11 +47,11 @@ internal class SetExpressStatusesTransformer(
|
|||
)
|
||||
}
|
||||
is WalletState.SingleCurrency.Locked -> {
|
||||
Timber.w("Impossible to load express statuses for locked wallet")
|
||||
TangemLogger.w("Impossible to load express statuses for locked wallet")
|
||||
prevState
|
||||
}
|
||||
is WalletState.MultiCurrency -> {
|
||||
Timber.w("Impossible to load express statuses for multi-currency wallet")
|
||||
TangemLogger.w("Impossible to load express statuses for multi-currency wallet")
|
||||
prevState
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.SingleWalletCardStateConverter
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.SingleWalletMarketPriceConverter
|
||||
import timber.log.Timber
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
|
||||
@Deprecated("Remove with main toggle [DesignFeatureToggles.isRedesignEnabled]")
|
||||
internal class SetPrimaryCurrencyTransformer(
|
||||
|
|
@ -27,11 +27,11 @@ internal class SetPrimaryCurrencyTransformer(
|
|||
)
|
||||
}
|
||||
is WalletState.SingleCurrency.Locked -> {
|
||||
Timber.w("Impossible to load primary currency status for locked wallet")
|
||||
TangemLogger.w("Impossible to load primary currency status for locked wallet")
|
||||
prevState
|
||||
}
|
||||
is WalletState.MultiCurrency -> {
|
||||
Timber.w("Impossible to load primary currency status for multi-currency wallet")
|
||||
TangemLogger.w("Impossible to load primary currency status for multi-currency wallet")
|
||||
prevState
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
|||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.utils.disableButtons
|
||||
import timber.log.Timber
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import java.math.BigDecimal
|
||||
|
||||
internal class SetTokenListErrorTransformer(
|
||||
|
|
@ -39,11 +39,11 @@ internal class SetTokenListErrorTransformer(
|
|||
)
|
||||
}
|
||||
is WalletState.MultiCurrency.Locked -> {
|
||||
Timber.w("Impossible to load tokens list for locked wallet")
|
||||
TangemLogger.w("Impossible to load tokens list for locked wallet")
|
||||
prevState
|
||||
}
|
||||
is WalletState.SingleCurrency -> {
|
||||
Timber.w("Impossible to load tokens list for single-currency wallet")
|
||||
TangemLogger.w("Impossible to load tokens list for single-currency wallet")
|
||||
prevState
|
||||
}
|
||||
}
|
||||
|
|
@ -61,14 +61,14 @@ internal class SetTokenListErrorTransformer(
|
|||
walletsBalanceUM = walletUM.walletsBalanceUM.toLoadedState(),
|
||||
tokensListUM = WalletTokensListUM.Empty(
|
||||
onEmptyClick = {
|
||||
clickIntents.onManageTokensClick(walletUM.walletsBalanceUM.id)
|
||||
clickIntents.onTokenSyncManageClick(walletUM.walletsBalanceUM.id)
|
||||
},
|
||||
),
|
||||
buttons = walletUM.disableButtons(),
|
||||
)
|
||||
}
|
||||
is WalletUM.Locked -> {
|
||||
Timber.w("Impossible to load tokens list for locked wallet")
|
||||
TangemLogger.w("Impossible to load tokens list for locked wallet")
|
||||
walletUM
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.transformers
|
||||
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.staking.model.StakingAvailability
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.MultiWalletBalanceUMTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.MultiWalletCardStateConverter
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.TokenListStateConverter
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.WalletTokensListUMConverter
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.utils.enableButtons
|
||||
import timber.log.Timber
|
||||
import com.tangem.features.tangempay.entity.TangemPayMainUM
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import java.math.BigDecimal
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class SetTokenListTransformer(
|
||||
private val params: TokenConverterParams,
|
||||
private val userWallet: UserWallet,
|
||||
|
|
@ -23,24 +23,33 @@ internal class SetTokenListTransformer(
|
|||
private val stakingAvailabilityMap: Map<CryptoCurrency, StakingAvailability> = emptyMap(),
|
||||
private val shouldShowMainPromo: Boolean,
|
||||
private val isAccountsModeEnabled: Boolean,
|
||||
private val isRedesignEnabled: Boolean,
|
||||
) : WalletStateTransformer(userWallet.walletId) {
|
||||
|
||||
private val tangemPayConverter by lazy {
|
||||
TangemPayMainBlockConverter(
|
||||
tangemPayClickIntents = clickIntents,
|
||||
isRedesignEnabled = isRedesignEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
override fun transform(prevState: WalletState): WalletState {
|
||||
return when (prevState) {
|
||||
is WalletState.MultiCurrency.Content -> {
|
||||
prevState.copy(
|
||||
walletCardState = prevState.walletCardState.toLoadedState(),
|
||||
tokensListState = prevState.tokensListState.toLoadedState(),
|
||||
tangemPayMainUM = prevState.tangemPayMainUM.toLoadedState(),
|
||||
buttons = prevState.enableButtons(),
|
||||
)
|
||||
}
|
||||
is WalletState.MultiCurrency.Locked -> {
|
||||
Timber.w("Impossible to load tokens list for locked wallet")
|
||||
TangemLogger.w("Impossible to load tokens list for locked wallet")
|
||||
prevState
|
||||
}
|
||||
is WalletState.SingleCurrency,
|
||||
-> {
|
||||
Timber.w("Impossible to load tokens list for single-currency wallet")
|
||||
TangemLogger.w("Impossible to load tokens list for single-currency wallet")
|
||||
prevState
|
||||
}
|
||||
}
|
||||
|
|
@ -51,12 +60,13 @@ internal class SetTokenListTransformer(
|
|||
is WalletUM.Content -> {
|
||||
walletUM.copy(
|
||||
walletsBalanceUM = walletUM.walletsBalanceUM.toLoadedState2(),
|
||||
tangemPayMainUM = walletUM.tangemPayMainUM.toLoadedState(),
|
||||
tokensListUM = toLoadedState(),
|
||||
buttons = walletUM.enableButtons(),
|
||||
)
|
||||
}
|
||||
is WalletUM.Locked -> {
|
||||
Timber.w("Impossible to load tokens list for locked wallet")
|
||||
TangemLogger.w("Impossible to load tokens list for locked wallet")
|
||||
walletUM
|
||||
}
|
||||
}
|
||||
|
|
@ -97,11 +107,22 @@ internal class SetTokenListTransformer(
|
|||
).convert(value = this)
|
||||
}
|
||||
|
||||
private fun TangemPayMainUM.toLoadedState(): TangemPayMainUM {
|
||||
val paymentAccountStatus = when (params) {
|
||||
is TokenConverterParams.Account -> params.accountList.accountStatuses
|
||||
.filterIsInstance<AccountStatus.Payment>()
|
||||
.firstOrNull()
|
||||
is TokenConverterParams.Wallet -> null
|
||||
} ?: return this
|
||||
|
||||
return tangemPayConverter.convert(paymentAccountStatus)
|
||||
}
|
||||
|
||||
private fun toLoadedState(): WalletTokensListUM {
|
||||
if (params !is TokenConverterParams.Account) {
|
||||
return WalletTokensListUM.Empty(
|
||||
onEmptyClick = {
|
||||
clickIntents.onManageTokensClick(userWallet.walletId)
|
||||
clickIntents.onTokenSyncManageClick(userWallet.walletId)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,51 +1,34 @@
|
|||
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.domain.models.wallet.UserWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TokenSyncProgressUM
|
||||
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) {
|
||||
private val userWallet: UserWallet,
|
||||
private val progress: TokenSyncProgressUM,
|
||||
) : WalletStateTransformer(userWallet.walletId) {
|
||||
|
||||
override fun transform(prevState: WalletState): WalletState {
|
||||
return when (prevState) {
|
||||
is WalletState.MultiCurrency.Content -> {
|
||||
val updatedCardState = updateCardState(prevState.walletCardState)
|
||||
prevState.copy(walletCardState = updatedCardState)
|
||||
}
|
||||
else -> {
|
||||
prevState
|
||||
}
|
||||
is WalletState.MultiCurrency.Content -> prevState.copy(
|
||||
walletCardState = updateCardState(prevState.walletCardState),
|
||||
tokenSyncProgressUM = progress,
|
||||
)
|
||||
else -> prevState
|
||||
}
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return walletUM
|
||||
}
|
||||
override fun transform(walletUM: WalletUM): WalletUM = 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,
|
||||
)
|
||||
val additionalInfo = WalletAdditionalInfoFactory.resolve(wallet = userWallet, syncProgress = progress)
|
||||
return when (cardState) {
|
||||
is WalletCardState.Loading -> {
|
||||
cardState.copy(additionalInfo = additionalInfo)
|
||||
}
|
||||
is WalletCardState.Content -> {
|
||||
cardState.copy(additionalInfo = additionalInfo)
|
||||
}
|
||||
is WalletCardState.Loading -> cardState.copy(additionalInfo = additionalInfo)
|
||||
is WalletCardState.Content -> cardState.copy(additionalInfo = additionalInfo)
|
||||
else -> cardState
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.TxHistoryItemStateConverter
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import timber.log.Timber
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
|
||||
internal class SetTxHistoryCountErrorTransformer(
|
||||
private val userWallet: UserWallet,
|
||||
|
|
@ -46,7 +46,7 @@ internal class SetTxHistoryCountErrorTransformer(
|
|||
is WalletState.SingleCurrency.Locked,
|
||||
is WalletState.MultiCurrency,
|
||||
-> {
|
||||
Timber.w("Impossible to load transactions history for multi-currency wallet")
|
||||
TangemLogger.w("Impossible to load transactions history for multi-currency wallet")
|
||||
prevState
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import timber.log.Timber
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
|
||||
internal class SetTxHistoryCountTransformer(
|
||||
userWalletId: UserWalletId,
|
||||
|
|
@ -24,11 +24,11 @@ internal class SetTxHistoryCountTransformer(
|
|||
)
|
||||
is WalletState.SingleCurrency.Locked,
|
||||
-> {
|
||||
Timber.w("Impossible to load transactions history for locked wallet")
|
||||
TangemLogger.w("Impossible to load transactions history for locked wallet")
|
||||
prevState
|
||||
}
|
||||
is WalletState.MultiCurrency -> {
|
||||
Timber.w("Impossible to load transactions history for multi-currency wallet")
|
||||
TangemLogger.w("Impossible to load transactions history for multi-currency wallet")
|
||||
prevState
|
||||
}
|
||||
}
|
||||
|
|
@ -40,7 +40,7 @@ internal class SetTxHistoryCountTransformer(
|
|||
|
||||
private fun TxHistoryState.toLoadingState(): TxHistoryState {
|
||||
return if (this is TxHistoryState.Content) {
|
||||
Timber.d("Load transactions history: $transactionsCount")
|
||||
TangemLogger.d("Load transactions history: $transactionsCount")
|
||||
|
||||
copy(
|
||||
contentItems = contentItems.apply {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import com.tangem.domain.txhistory.models.TxHistoryListError
|
|||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import timber.log.Timber
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
|
||||
internal class SetTxHistoryItemsErrorTransformer(
|
||||
userWalletId: UserWalletId,
|
||||
|
|
@ -18,11 +18,11 @@ internal class SetTxHistoryItemsErrorTransformer(
|
|||
return when (prevState) {
|
||||
is WalletState.SingleCurrency.Content -> prevState.copy(txHistoryState = createErrorState())
|
||||
is WalletState.SingleCurrency.Locked -> {
|
||||
Timber.w("Impossible to load transactions history for locked wallet")
|
||||
TangemLogger.w("Impossible to load transactions history for locked wallet")
|
||||
prevState
|
||||
}
|
||||
is WalletState.MultiCurrency -> {
|
||||
Timber.w("Impossible to load transactions history for multi-currency wallet")
|
||||
TangemLogger.w("Impossible to load transactions history for multi-currency wallet")
|
||||
prevState
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.TxHistoryItemFlowConverter
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import timber.log.Timber
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
|
||||
internal class SetTxHistoryItemsTransformer(
|
||||
userWallet: UserWallet,
|
||||
|
|
@ -23,11 +23,11 @@ internal class SetTxHistoryItemsTransformer(
|
|||
txHistoryState = prevState.txHistoryState.toContentState(),
|
||||
)
|
||||
is WalletState.SingleCurrency.Locked -> {
|
||||
Timber.w("Impossible to load transactions history for locked wallet")
|
||||
TangemLogger.w("Impossible to load transactions history for locked wallet")
|
||||
prevState
|
||||
}
|
||||
is WalletState.MultiCurrency -> {
|
||||
Timber.w("Impossible to load transactions history for multi-currency wallet")
|
||||
TangemLogger.w("Impossible to load transactions history for multi-currency wallet")
|
||||
prevState
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import timber.log.Timber
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
|
||||
internal class SetWarningsTransformer(
|
||||
userWalletId: UserWalletId,
|
||||
|
|
@ -23,7 +23,7 @@ internal class SetWarningsTransformer(
|
|||
is WalletState.MultiCurrency.Locked,
|
||||
is WalletState.SingleCurrency.Locked,
|
||||
-> {
|
||||
Timber.w("Impossible to update notifications for locked wallet")
|
||||
TangemLogger.w("Impossible to update notifications for locked wallet")
|
||||
prevState
|
||||
}
|
||||
}
|
||||
|
|
@ -36,7 +36,7 @@ internal class SetWarningsTransformer(
|
|||
notificationsCarousel = notificationsCarousel,
|
||||
)
|
||||
is WalletUM.Locked -> {
|
||||
Timber.w("Impossible to update notifications for locked wallet")
|
||||
TangemLogger.w("Impossible to update notifications for locked wallet")
|
||||
walletUM
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ internal class TangemPayRefreshNeededStateTransformer(
|
|||
override fun transform(prevState: WalletState): WalletState {
|
||||
val tangemPayState = TangemPayState.RefreshNeeded(
|
||||
notification = TangemPayRefreshNeeded(
|
||||
tangemIcon = R.drawable.ic_tangem_24,
|
||||
buttonText = when (userWallet) {
|
||||
is UserWallet.Cold -> resourceReference(id = R.string.home_button_scan)
|
||||
is UserWallet.Hot -> resourceReference(id = R.string.tangempay_sync_needed_restore_access)
|
||||
|
|
|
|||
|
|
@ -5,9 +5,11 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
internal class TangemPayRefreshShowProgressTransformer(
|
||||
userWalletId: UserWalletId,
|
||||
private val shouldShowProgress: Boolean,
|
||||
) : WalletStateTransformer(userWalletId) {
|
||||
|
||||
override fun transform(prevState: WalletState): WalletState {
|
||||
|
|
@ -15,11 +17,19 @@ internal class TangemPayRefreshShowProgressTransformer(
|
|||
val refreshNeededState = multiContentState.tangemPayState as? TangemPayState.RefreshNeeded ?: return prevState
|
||||
val refreshNotification =
|
||||
refreshNeededState.notification as? WalletNotification.Warning.TangemPayRefreshNeeded ?: return prevState
|
||||
val newWarnings = prevState.warnings.map { warning ->
|
||||
if (warning is WalletNotification.Warning.TangemPayRefreshNeeded) {
|
||||
warning.copy(shouldShowProgress = shouldShowProgress)
|
||||
} else {
|
||||
warning
|
||||
}
|
||||
}
|
||||
|
||||
return multiContentState.copy(
|
||||
tangemPayState = refreshNeededState.copy(
|
||||
notification = refreshNotification.copy(shouldShowProgress = true),
|
||||
notification = refreshNotification.copy(shouldShowProgress = shouldShowProgress),
|
||||
),
|
||||
warnings = newWarnings.toImmutableList(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,13 +11,14 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletLoadingStateFactory
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import timber.log.Timber
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
|
||||
internal class UnlockWalletTransformer(
|
||||
private val unlockedWallets: List<UserWallet>,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
private val walletImageResolver: WalletImageResolver,
|
||||
private val getWalletIconUseCase: GetWalletIconUseCase,
|
||||
private val isTangemPayRefactorEnabled: Boolean,
|
||||
) : WalletScreenStateTransformer {
|
||||
|
||||
private val walletLoadingStateFactory by lazy {
|
||||
|
|
@ -25,6 +26,7 @@ internal class UnlockWalletTransformer(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isTangemPayRefactorEnabled = isTangemPayRefactorEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -65,7 +67,7 @@ internal class UnlockWalletTransformer(
|
|||
is WalletState.MultiCurrency.Content,
|
||||
is WalletState.SingleCurrency.Content,
|
||||
-> {
|
||||
Timber.e("Impossible to unlock wallet with not locked state")
|
||||
TangemLogger.e("Impossible to unlock wallet with not locked state")
|
||||
prevState
|
||||
}
|
||||
}
|
||||
|
|
@ -77,7 +79,7 @@ internal class UnlockWalletTransformer(
|
|||
userWallet = unlockedWallet,
|
||||
)
|
||||
is WalletUM.Content -> {
|
||||
Timber.e("Impossible to unlock wallet with not locked state")
|
||||
TangemLogger.e("Impossible to unlock wallet with not locked state")
|
||||
walletUM
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,10 +4,11 @@ import com.tangem.domain.card.common.util.getCardsCount
|
|||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletImageResolver
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TokenSyncProgressUM
|
||||
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
|
||||
import timber.log.Timber
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
|
||||
internal class UpdateWalletCardsCountTransformer(
|
||||
private val userWallet: UserWallet,
|
||||
|
|
@ -17,7 +18,9 @@ internal class UpdateWalletCardsCountTransformer(
|
|||
override fun transform(prevState: WalletState): WalletState {
|
||||
return when (prevState) {
|
||||
is WalletState.MultiCurrency.Content -> {
|
||||
prevState.copy(walletCardState = prevState.walletCardState.toUpdatedState())
|
||||
prevState.copy(
|
||||
walletCardState = prevState.walletCardState.toUpdatedState(prevState.tokenSyncProgressUM),
|
||||
)
|
||||
}
|
||||
is WalletState.SingleCurrency.Content -> {
|
||||
prevState.copy(walletCardState = prevState.walletCardState.toUpdatedState())
|
||||
|
|
@ -25,7 +28,7 @@ internal class UpdateWalletCardsCountTransformer(
|
|||
is WalletState.MultiCurrency.Locked,
|
||||
is WalletState.SingleCurrency.Locked,
|
||||
-> {
|
||||
Timber.e("Impossible to update wallet cards count for locked wallet")
|
||||
TangemLogger.e("Impossible to update wallet cards count for locked wallet")
|
||||
prevState
|
||||
}
|
||||
}
|
||||
|
|
@ -35,10 +38,12 @@ internal class UpdateWalletCardsCountTransformer(
|
|||
return walletUM // todo redesign main
|
||||
}
|
||||
|
||||
private fun WalletCardState.toUpdatedState(): WalletCardState {
|
||||
private fun WalletCardState.toUpdatedState(
|
||||
syncProgress: TokenSyncProgressUM = TokenSyncProgressUM.Idle,
|
||||
): WalletCardState {
|
||||
return when (this) {
|
||||
is WalletCardState.Content -> copy(
|
||||
additionalInfo = WalletAdditionalInfoFactory.resolve(wallet = userWallet),
|
||||
additionalInfo = WalletAdditionalInfoFactory.resolve(wallet = userWallet, syncProgress = syncProgress),
|
||||
imageResId = walletImageResolver.resolve(userWallet = userWallet),
|
||||
cardCount = (userWallet as? UserWallet.Cold)?.getCardsCount(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -23,11 +23,25 @@ internal class MultiWalletCurrencyActionsConverter(
|
|||
) : Converter<TokenActionsState, ImmutableList<TokenActionButtonUM>> {
|
||||
|
||||
override fun convert(value: TokenActionsState): ImmutableList<TokenActionButtonUM> {
|
||||
return value.states
|
||||
.filterIfSingleWithToken()
|
||||
val actionList = value.states.filterIfSingleWithToken()
|
||||
.mapNotNull {
|
||||
mapTokenActionState(actionsState = it, cryptoCurrencyStatus = value.cryptoCurrencyStatus)
|
||||
}
|
||||
|
||||
return actionList
|
||||
.mapIndexed { index, action ->
|
||||
val analyticsAction = TokenActionsState.ActionState.Analytics::class.java.simpleName
|
||||
val hideTokenAction = TokenActionsState.ActionState.HideToken::class.java.simpleName
|
||||
|
||||
if (
|
||||
action.id == analyticsAction ||
|
||||
index != actionList.lastIndex && actionList[index + 1].id == hideTokenAction
|
||||
) {
|
||||
action.copy(hasDivider = true)
|
||||
} else {
|
||||
action
|
||||
}
|
||||
}
|
||||
.toImmutableList()
|
||||
}
|
||||
|
||||
|
|
@ -111,6 +125,7 @@ internal class MultiWalletCurrencyActionsConverter(
|
|||
}
|
||||
|
||||
return TokenActionButtonUM(
|
||||
id = actionsState::class.java.simpleName,
|
||||
text = title,
|
||||
iconResId = icon,
|
||||
onClick = action,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,126 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.transformers.converter
|
||||
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import com.tangem.common.ui.R
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.format.bigdecimal.fiat
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.format.bigdecimal.formatStyled
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.domain.models.account.PaymentAccountStatusValue
|
||||
import com.tangem.domain.models.kyc.KycStatus
|
||||
import com.tangem.domain.pay.TangemPayDetailsConfig
|
||||
import com.tangem.domain.visa.model.TangemPayCardFrozenState
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.TangemPayIntents
|
||||
import com.tangem.features.tangempay.entity.TangemPayMainUM
|
||||
import com.tangem.utils.converter.Converter
|
||||
import java.math.BigDecimal
|
||||
import java.util.Currency
|
||||
|
||||
private const val POLYGON_CHAIN_ID = 137
|
||||
|
||||
internal class TangemPayMainBlockConverter(
|
||||
private val tangemPayClickIntents: TangemPayIntents,
|
||||
private val isRedesignEnabled: Boolean,
|
||||
) : Converter<AccountStatus.Payment, TangemPayMainUM> {
|
||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||
override fun convert(value: AccountStatus.Payment): TangemPayMainUM {
|
||||
return when (val statusValue = value.value) {
|
||||
is PaymentAccountStatusValue.Error.CardIssueFailed -> TangemPayMainUM.FailedToIssue(
|
||||
onClick = { tangemPayClickIntents.onIssuingFailedClicked(statusValue.customerId) },
|
||||
)
|
||||
is PaymentAccountStatusValue.Error.ExposedDevice -> TangemPayMainUM.ExposedDevice
|
||||
is PaymentAccountStatusValue.Error.NotSynced -> TangemPayMainUM.SyncNeeded
|
||||
is PaymentAccountStatusValue.Error.Unavailable -> TangemPayMainUM.TemporaryUnavailable
|
||||
is PaymentAccountStatusValue.IssuingCard -> TangemPayMainUM.IssuingCard(
|
||||
onClick = { tangemPayClickIntents.onIssuingCardClicked() },
|
||||
)
|
||||
is PaymentAccountStatusValue.UnderReview -> TangemPayMainUM.UnderReview(
|
||||
subtitle = when (statusValue.kycStatus) {
|
||||
KycStatus.REJECTED -> TextReference.Res(R.string.tangempay_kyc_has_failed)
|
||||
else -> TextReference.Res(R.string.tangempay_kyc_in_progress)
|
||||
},
|
||||
onClick = {
|
||||
when (statusValue.kycStatus) {
|
||||
KycStatus.REJECTED -> tangemPayClickIntents.onKycRejectedClicked(
|
||||
userWalletId = value.account.userWalletId,
|
||||
customerId = statusValue.customerId,
|
||||
)
|
||||
else -> tangemPayClickIntents.onKycProgressClicked(value.account.userWalletId)
|
||||
}
|
||||
},
|
||||
)
|
||||
is PaymentAccountStatusValue.NotCreated -> TangemPayMainUM.Empty
|
||||
is PaymentAccountStatusValue.Loading -> TangemPayMainUM.Loading
|
||||
is PaymentAccountStatusValue.Locked -> TangemPayMainUM.Content(
|
||||
subtitle = stringReference("*${statusValue.lastFourDigits}"),
|
||||
isBalanceFlickering = statusValue.source == StatusSource.CACHE,
|
||||
balance = getBalanceText(
|
||||
currencyCode = statusValue.currencyCode,
|
||||
balance = statusValue.fiatBalance.availableBalance,
|
||||
),
|
||||
balanceSubtitle = stringReference("USDC"), // TODO hardcode for now
|
||||
shouldShowOnlyCacheWarning = statusValue.source == StatusSource.ONLY_CACHE,
|
||||
onClick = {
|
||||
tangemPayClickIntents.openDetails(
|
||||
value.account.userWalletId,
|
||||
TangemPayDetailsConfig(
|
||||
customerId = statusValue.customerId,
|
||||
cardId = statusValue.cardId,
|
||||
isPinSet = statusValue.isPinSet,
|
||||
cardFrozenState = TangemPayCardFrozenState.Frozen,
|
||||
cardNumberEnd = statusValue.lastFourDigits,
|
||||
chainId = POLYGON_CHAIN_ID,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
is PaymentAccountStatusValue.Loaded -> TangemPayMainUM.Content(
|
||||
subtitle = stringReference("*${statusValue.lastFourDigits}"),
|
||||
isBalanceFlickering = statusValue.source == StatusSource.CACHE,
|
||||
balance = getBalanceText(
|
||||
currencyCode = statusValue.currencyCode,
|
||||
balance = statusValue.fiatBalance.availableBalance,
|
||||
),
|
||||
balanceSubtitle = stringReference("USDC"), // TODO hardcode for now
|
||||
shouldShowOnlyCacheWarning = statusValue.source == StatusSource.ONLY_CACHE,
|
||||
onClick = {
|
||||
tangemPayClickIntents.openDetails(
|
||||
value.account.userWalletId,
|
||||
TangemPayDetailsConfig(
|
||||
customerId = statusValue.customerId,
|
||||
cardId = statusValue.cardId,
|
||||
isPinSet = statusValue.isPinSet,
|
||||
cardFrozenState = TangemPayCardFrozenState.Unfrozen,
|
||||
cardNumberEnd = statusValue.lastFourDigits,
|
||||
chainId = POLYGON_CHAIN_ID,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBalanceText(currencyCode: String, balance: BigDecimal): TextReference {
|
||||
val currency = Currency.getInstance(currencyCode)
|
||||
val formattedBalance = if (isRedesignEnabled) {
|
||||
balance.formatStyled {
|
||||
fiat(
|
||||
fiatCurrencyCode = currency.currencyCode,
|
||||
fiatCurrencySymbol = currency.symbol,
|
||||
spanStyleReference = { SpanStyle(color = TangemTheme.colors2.text.neutral.secondary) },
|
||||
)
|
||||
}
|
||||
} else {
|
||||
stringReference(
|
||||
balance.format {
|
||||
fiat(fiatCurrencyCode = currency.currencyCode, fiatCurrencySymbol = currency.symbol)
|
||||
},
|
||||
)
|
||||
}
|
||||
return formattedBalance
|
||||
}
|
||||
}
|
||||
|
|
@ -76,8 +76,13 @@ internal class WalletTokenCurrencyItemConverter(
|
|||
onItemLongClick = when (value.value) {
|
||||
CryptoCurrencyStatus.Loading -> null
|
||||
else -> {
|
||||
{
|
||||
clickIntents.onTokenItemLongClick(accountId, value)
|
||||
{ offset, tokenRowUM ->
|
||||
clickIntents.onTokenItemLongClickV2(
|
||||
accountId = accountId,
|
||||
cryptoCurrencyStatus = value,
|
||||
offset = offset,
|
||||
tokenRowUM = tokenRowUM,
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -76,20 +76,17 @@ internal class WalletTokensListUMConverter(
|
|||
onEmptyClick = { clickIntents.onManageTokensClick(value.mainAccount.accountId) },
|
||||
)
|
||||
} else {
|
||||
val isCollapsable = value.accountStatuses.count {
|
||||
it is AccountStatus.CryptoPortfolio && it.account.tokensCount > 0
|
||||
} > 1
|
||||
|
||||
val tokenListUM = value.accountStatuses
|
||||
.filterIsInstance<AccountStatus.CryptoPortfolio>()
|
||||
.asSequence()
|
||||
.flatMap { accountStatus ->
|
||||
if (isAccountsModeEnabled) {
|
||||
val isCollapsable = accountStatus.tokenList.flattenCurrencies().isNotEmpty()
|
||||
val isExpanded = expandedAccounts.contains(accountStatus.account.accountId)
|
||||
sequenceOf(
|
||||
TokensListItemUM2.Portfolio(
|
||||
tokenRowUM = accountRowConverter.convert(accountStatus),
|
||||
isExpanded = isExpanded || !isCollapsable,
|
||||
isExpanded = isExpanded,
|
||||
isCollapsable = isCollapsable,
|
||||
onEmptyClick = { clickIntents.onManageTokensClick(accountStatus.account.accountId) },
|
||||
tokenList = getTokenListItems(
|
||||
|
|
@ -166,7 +163,7 @@ internal class WalletTokensListUMConverter(
|
|||
return if (accountList.flattenCurrencies().size > 1 && !selectedWallet.isSingleWalletWithToken()) {
|
||||
TangemButtonUM(
|
||||
text = resourceReference(R.string.organize_tokens_title),
|
||||
isEnabled = accountList.totalFiatBalance is TotalFiatBalance.Loading,
|
||||
isEnabled = accountList.totalFiatBalance !is TotalFiatBalance.Loading,
|
||||
size = TangemButtonSize.X9,
|
||||
shape = TangemButtonShape.Rounded,
|
||||
type = TangemButtonType.PrimaryInverse,
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import com.tangem.feature.wallet.impl.R
|
|||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletImageResolver
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.*
|
||||
import com.tangem.features.tangempay.entity.TangemPayMainUM
|
||||
import com.tangem.utils.extensions.addIf
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
|
|
@ -33,6 +34,7 @@ internal class WalletLoadingStateFactory(
|
|||
private val clickIntents: WalletClickIntents,
|
||||
private val walletImageResolver: WalletImageResolver,
|
||||
private val getWalletIconUseCase: GetWalletIconUseCase,
|
||||
private val isTangemPayRefactorEnabled: Boolean,
|
||||
) {
|
||||
|
||||
fun create(userWallet: UserWallet): WalletState {
|
||||
|
|
@ -67,7 +69,7 @@ internal class WalletLoadingStateFactory(
|
|||
is UserWallet.Cold -> WalletType.Cold
|
||||
is UserWallet.Hot -> WalletType.Hot
|
||||
},
|
||||
tangemPayState = TangemPayState.Empty,
|
||||
tangemPayMainUM = TangemPayMainUM.Empty,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -82,6 +84,8 @@ internal class WalletLoadingStateFactory(
|
|||
nftState = WalletNFTItemUM.Hidden,
|
||||
type = WalletType.Hot,
|
||||
tangemPayState = TangemPayState.Empty,
|
||||
tangemPayMainUM = TangemPayMainUM.Empty,
|
||||
isTangemPayRefactorEnabled = isTangemPayRefactorEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -96,6 +100,8 @@ internal class WalletLoadingStateFactory(
|
|||
nftState = WalletNFTItemUM.Hidden,
|
||||
type = WalletType.Cold,
|
||||
tangemPayState = TangemPayState.Empty,
|
||||
tangemPayMainUM = TangemPayMainUM.Empty,
|
||||
isTangemPayRefactorEnabled = isTangemPayRefactorEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@ import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetTokenListErrorTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetTokenListTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.TokenConverterParams
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import timber.log.Timber
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
|
|
@ -103,6 +103,7 @@ internal abstract class BasicAccountListSubscriber : BasicWalletSubscriber() {
|
|||
stakingAvailabilityMap = stakingAvailabilityMap,
|
||||
shouldShowMainPromo = shouldShowMainPromo,
|
||||
isAccountsModeEnabled = isAccountMode,
|
||||
isRedesignEnabled = true,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -126,7 +127,7 @@ internal abstract class BasicAccountListSubscriber : BasicWalletSubscriber() {
|
|||
?: return
|
||||
},
|
||||
ifError = { e ->
|
||||
Timber.e("Failed to load token list: $e")
|
||||
TangemLogger.e("Failed to load token list: $e")
|
||||
stateController.update(
|
||||
SetTokenListErrorTransformer(
|
||||
selectedWallet = userWallet,
|
||||
|
|
@ -165,6 +166,7 @@ internal abstract class BasicAccountListSubscriber : BasicWalletSubscriber() {
|
|||
stakingAvailabilityMap = stakingAvailabilityMap,
|
||||
shouldShowMainPromo = shouldShowMainPromo,
|
||||
isAccountsModeEnabled = false,
|
||||
isRedesignEnabled = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import kotlinx.coroutines.flow.Flow
|
|||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class TangemPayMainSubscriber @AssistedInject constructor(
|
||||
|
|
@ -67,7 +67,7 @@ internal class TangemPayMainSubscriber @AssistedInject constructor(
|
|||
}
|
||||
TangemPayCustomerInfoError.UnknownError -> {
|
||||
// hide TangemPay block
|
||||
Timber.e("Failed when loading main screen TangemPay info: $tangemPayError")
|
||||
TangemLogger.e("Failed when loading main screen TangemPay info: $tangemPayError")
|
||||
stateController.update(
|
||||
transformer = TangemPayHiddenStateTransformer(userWalletId),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.subscribers
|
||||
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.tokensync.model.TokenSyncProgress
|
||||
import com.tangem.domain.tokensync.usecase.ObserveTokenSyncUseCase
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TokenSyncProgressUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetTokenSyncProgressTransformer
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
||||
internal class TokenSyncSubscriber @AssistedInject constructor(
|
||||
@Assisted private val userWallet: UserWallet,
|
||||
private val stateController: WalletStateController,
|
||||
private val observeTokenSyncUseCase: ObserveTokenSyncUseCase,
|
||||
) : WalletSubscriber() {
|
||||
|
||||
override fun create(coroutineScope: CoroutineScope): Flow<*> {
|
||||
return observeTokenSyncUseCase(userWallet.walletId)
|
||||
.onEach { current -> handleProgress(userWallet, current) }
|
||||
}
|
||||
|
||||
private fun handleProgress(userWallet: UserWallet, current: TokenSyncProgress) {
|
||||
val progressUM = when (current) {
|
||||
is TokenSyncProgress.InProgress -> TokenSyncProgressUM.InProgress(current.progressPercent)
|
||||
is TokenSyncProgress.Completed -> TokenSyncProgressUM.Completed
|
||||
is TokenSyncProgress.Idle -> TokenSyncProgressUM.Idle
|
||||
}
|
||||
stateController.update(
|
||||
SetTokenSyncProgressTransformer(
|
||||
userWallet = userWallet,
|
||||
progress = progressUM,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(userWallet: UserWallet): TokenSyncSubscriber
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ import kotlinx.coroutines.Job
|
|||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import timber.log.Timber
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
|
||||
/**
|
||||
* Component for implementation of flow subscription
|
||||
|
|
@ -18,7 +18,7 @@ internal abstract class WalletSubscriber {
|
|||
protected abstract fun create(coroutineScope: CoroutineScope): Flow<*>
|
||||
|
||||
fun subscribe(coroutineScope: CoroutineScope, dispatchers: CoroutineDispatcher): Job {
|
||||
Timber.d("Subscribe on ${this::class.simpleName}")
|
||||
TangemLogger.d("Subscribe on ${this::class.simpleName}")
|
||||
|
||||
return create(coroutineScope)
|
||||
.flowOn(dispatchers)
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@ import com.tangem.common.ui.bottomsheet.chooseaddress.ChooseAddressBottomSheetCo
|
|||
import com.tangem.common.ui.expressStatus.ExpressStatusBottomSheet
|
||||
import com.tangem.common.ui.expressStatus.ExpressStatusBottomSheetConfig
|
||||
import com.tangem.common.ui.expressStatus.expressTransactionsItems
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.components.atoms.handComposableComponentHeight
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheetDraggableHeaderLegacy
|
||||
|
|
@ -60,6 +59,7 @@ import com.tangem.core.ui.components.sheetscaffold.*
|
|||
import com.tangem.core.ui.components.snackbar.CopiedTextSnackbar
|
||||
import com.tangem.core.ui.components.snackbar.TangemSnackbar
|
||||
import com.tangem.core.ui.components.transactions.state.TxHistoryState
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.event.StateEvent
|
||||
import com.tangem.core.ui.extensions.softLayerShadow
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
|
|
@ -84,6 +84,8 @@ import com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency
|
|||
import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency.marketPriceBlock
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.visa.TangemPayMainScreenBlock
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.utils.changeWalletAnimator
|
||||
import com.tangem.features.tangempay.component.TangemPayMainBlockComponent
|
||||
import com.tangem.features.tangempay.entity.TangemPayMainUM
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -92,6 +94,7 @@ import kotlin.math.roundToInt
|
|||
@Composable
|
||||
internal fun WalletScreen(
|
||||
state: WalletScreenState,
|
||||
tangemPayComponent: TangemPayMainBlockComponent,
|
||||
promoBannersBlockComponent: ComposableContentComponent? = null,
|
||||
bottomSheetContent: @Composable (() -> Unit),
|
||||
bottomSheetHeaderHeightProvider: () -> Dp,
|
||||
|
|
@ -106,6 +109,7 @@ internal fun WalletScreen(
|
|||
|
||||
WalletContent(
|
||||
state = state,
|
||||
tangemPayComponent = tangemPayComponent,
|
||||
walletsListState = walletsListState,
|
||||
snackbarHostState = snackbarHostState,
|
||||
isAutoScroll = isAutoScroll,
|
||||
|
|
@ -128,6 +132,7 @@ internal fun WalletScreen(
|
|||
@Composable
|
||||
private fun WalletContent(
|
||||
state: WalletScreenState,
|
||||
tangemPayComponent: TangemPayMainBlockComponent,
|
||||
walletsListState: LazyListState,
|
||||
snackbarHostState: SnackbarHostState,
|
||||
isAutoScroll: State<Boolean>,
|
||||
|
|
@ -220,18 +225,12 @@ private fun WalletContent(
|
|||
}
|
||||
}
|
||||
|
||||
if (selectedWallet is WalletState.MultiCurrency) {
|
||||
item(
|
||||
key = "TangemPayMainScreenBlock",
|
||||
contentType = selectedWallet.tangemPayState::class.java,
|
||||
) {
|
||||
TangemPayMainScreenBlock(
|
||||
state = selectedWallet.tangemPayState,
|
||||
isBalanceHidden = state.isHidingMode,
|
||||
modifier = itemModifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
tangemPayItem(
|
||||
modifier = itemModifier,
|
||||
state = selectedWallet,
|
||||
isHidingMode = state.isHidingMode,
|
||||
tangemPayComponent = tangemPayComponent,
|
||||
)
|
||||
|
||||
(selectedWallet as? WalletState.SingleCurrency)?.let { walletState ->
|
||||
walletState.marketPriceBlockState?.let { marketPriceBlockState ->
|
||||
|
|
@ -749,6 +748,25 @@ internal fun LazyListScope.nftCollections(state: WalletState, itemModifier: Modi
|
|||
}
|
||||
}
|
||||
|
||||
internal fun LazyListScope.tangemPayItem(
|
||||
state: WalletState,
|
||||
isHidingMode: Boolean,
|
||||
tangemPayComponent: TangemPayMainBlockComponent,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
if (state !is WalletState.MultiCurrency) return
|
||||
|
||||
if (state.isTangemPayRefactorEnabled) {
|
||||
with(tangemPayComponent) {
|
||||
tangemPayMainContent(modifier = modifier, state = state.tangemPayMainUM, isBalanceHidden = isHidingMode)
|
||||
}
|
||||
} else {
|
||||
item(key = "TangemPayMainScreenBlock", contentType = state.tangemPayState::class.java) {
|
||||
TangemPayMainScreenBlock(modifier = modifier, state = state.tangemPayState, isBalanceHidden = isHidingMode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ShowBottomSheet(bottomSheetConfig: TangemBottomSheetConfig?) {
|
||||
if (bottomSheetConfig != null) {
|
||||
|
|
@ -767,6 +785,14 @@ private fun WalletScreen_Preview(@PreviewParameter(WalletScreenPreviewProvider::
|
|||
TangemThemePreview {
|
||||
WalletScreen(
|
||||
state = data,
|
||||
tangemPayComponent = object : TangemPayMainBlockComponent {
|
||||
override fun LazyListScope.tangemPayMainContent(
|
||||
state: TangemPayMainUM,
|
||||
isBalanceHidden: Boolean,
|
||||
modifier: Modifier,
|
||||
) {
|
||||
}
|
||||
},
|
||||
bottomSheetContent = {
|
||||
Text("Markets Content")
|
||||
},
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import androidx.compose.foundation.background
|
|||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.gestures.detectTapGestures
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.pager.HorizontalPager
|
||||
|
|
@ -49,6 +50,7 @@ import com.tangem.core.ui.components.background.northernlights.NorthernLightsBac
|
|||
import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheetDraggableHeader
|
||||
import com.tangem.core.ui.components.bottomsheets.state.BottomSheetState
|
||||
import com.tangem.core.ui.components.containers.pullToRefresh.TangemPullToRefreshSlidingContainer
|
||||
import com.tangem.core.ui.components.haze.hazeEffectTangem
|
||||
import com.tangem.core.ui.components.haze.hazeSourceTangem
|
||||
import com.tangem.core.ui.components.rememberIsKeyboardVisible
|
||||
import com.tangem.core.ui.components.sheetscaffold.*
|
||||
|
|
@ -57,6 +59,7 @@ import com.tangem.core.ui.ds.topbar.collapsing.TangemCollapsingTopBar
|
|||
import com.tangem.core.ui.ds.topbar.collapsing.rememberTangemExitUntilCollapsedScrollBehavior
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.res.*
|
||||
import com.tangem.core.ui.utils.TangemSharedTransitionLayout
|
||||
import com.tangem.feature.wallet.presentation.common.preview.WalletScreenPreviewData
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.NOT_INITIALIZED_WALLET_INDEX
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletBalanceUM
|
||||
|
|
@ -68,6 +71,10 @@ import com.tangem.feature.wallet.presentation.wallet.ui.components.common.Wallet
|
|||
import com.tangem.feature.wallet.presentation.wallet.ui.components.common.WalletPagerIndicator
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.common.WalletTopBar
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.utils.lazyListStateMapSaver
|
||||
import com.tangem.features.tangempay.component.TangemPayMainBlockComponent
|
||||
import com.tangem.features.tangempay.entity.TangemPayMainUM
|
||||
import dev.chrisbanes.haze.HazeProgressive
|
||||
import dev.chrisbanes.haze.HazeTint
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.math.abs
|
||||
|
||||
|
|
@ -77,6 +84,8 @@ private const val MARKET_HINT_THRESHOLD = 0.5f
|
|||
@Composable
|
||||
internal fun WalletScreen2(
|
||||
state: WalletScreenState,
|
||||
tangemPayComponent: TangemPayMainBlockComponent,
|
||||
modifier: Modifier = Modifier,
|
||||
bottomSheetContent: @Composable (() -> Unit),
|
||||
bottomSheetHeaderHeightProvider: () -> Dp,
|
||||
onBottomSheetStateChange: (BottomSheetState) -> Unit,
|
||||
|
|
@ -91,12 +100,28 @@ internal fun WalletScreen2(
|
|||
pageCount = { state.wallets2.size },
|
||||
)
|
||||
|
||||
val listStates = rememberSaveable(saver = lazyListStateMapSaver(walletsPagerState.pageCount)) {
|
||||
mutableMapOf<Int, LazyListState>().apply {
|
||||
repeat(walletsPagerState.pageCount) { index -> put(index, LazyListState()) }
|
||||
}
|
||||
}
|
||||
|
||||
val isTopOverscrollEnabled by remember {
|
||||
derivedStateOf {
|
||||
val listState = listStates[walletsPagerState.currentPage] ?: return@derivedStateOf false
|
||||
listState.layoutInfo.totalItemsCount > 0 &&
|
||||
!listState.canScrollBackward && !listState.canScrollForward ||
|
||||
listState.canScrollBackward && !listState.canScrollForward
|
||||
}
|
||||
}
|
||||
|
||||
val partialCollapsedHeight = 64.dp + statusBarHeight
|
||||
val balanceBlockHeight = 320.dp + partialCollapsedHeight
|
||||
val behavior = rememberTangemExitUntilCollapsedScrollBehavior(
|
||||
expandedHeight = balanceBlockHeight,
|
||||
partialCollapsedHeight = partialCollapsedHeight,
|
||||
snapAnimationSpec = spring(stiffness = Spring.StiffnessMedium),
|
||||
isTopOverscrollEnabled = isTopOverscrollEnabled,
|
||||
)
|
||||
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
|
@ -104,10 +129,13 @@ internal fun WalletScreen2(
|
|||
WalletContent2(
|
||||
state = state,
|
||||
walletsPagerState = walletsPagerState,
|
||||
tangemPayComponent = tangemPayComponent,
|
||||
behavior = behavior,
|
||||
bottomSheetContent = bottomSheetContent,
|
||||
bottomSheetHeaderHeightProvider = bottomSheetHeaderHeightProvider,
|
||||
onBottomSheetStateChange = onBottomSheetStateChange,
|
||||
modifier = modifier,
|
||||
listStates = listStates,
|
||||
)
|
||||
|
||||
WalletEventEffect(
|
||||
|
|
@ -128,7 +156,10 @@ internal fun WalletScreen2(
|
|||
private fun WalletContent2(
|
||||
state: WalletScreenState,
|
||||
walletsPagerState: PagerState,
|
||||
tangemPayComponent: TangemPayMainBlockComponent,
|
||||
behavior: TangemCollapsingAppBarBehavior,
|
||||
listStates: Map<Int, LazyListState>,
|
||||
modifier: Modifier = Modifier,
|
||||
bottomSheetHeaderHeightProvider: () -> Dp,
|
||||
onBottomSheetStateChange: (BottomSheetState) -> Unit,
|
||||
bottomSheetContent: @Composable (() -> Unit),
|
||||
|
|
@ -144,6 +175,7 @@ private fun WalletContent2(
|
|||
}
|
||||
|
||||
BaseScaffoldWithMarkets(
|
||||
modifier = modifier,
|
||||
state = state,
|
||||
bottomSheetHeaderHeightProvider = bottomSheetHeaderHeightProvider,
|
||||
onBottomSheetStateChange = onBottomSheetStateChange,
|
||||
|
|
@ -168,12 +200,6 @@ private fun WalletContent2(
|
|||
}
|
||||
}
|
||||
|
||||
val listStates = rememberSaveable(saver = lazyListStateMapSaver(walletsPagerState.pageCount)) {
|
||||
mutableMapOf<Int, LazyListState>().apply {
|
||||
repeat(walletsPagerState.pageCount) { index -> put(index, LazyListState()) }
|
||||
}
|
||||
}
|
||||
|
||||
val canPagerScroll by remember { derivedStateOf { behavior.state.heightOffset == 0f } }
|
||||
|
||||
val pullToRefreshState = rememberPullToRefreshState()
|
||||
|
|
@ -181,7 +207,7 @@ private fun WalletContent2(
|
|||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.hazeSourceTangem(zIndex = -1f),
|
||||
.hazeSourceTangem(zIndex = -2f),
|
||||
) {
|
||||
NorthernLightsBackground(
|
||||
containerColor = if (LocalIsInDarkTheme.current) {
|
||||
|
|
@ -201,10 +227,20 @@ private fun WalletContent2(
|
|||
behavior = behavior,
|
||||
)
|
||||
|
||||
val overlay = TangemTheme.colors2.overlay.overlayPrimary
|
||||
|
||||
HorizontalPager(
|
||||
state = walletsPagerState,
|
||||
userScrollEnabled = canPagerScroll,
|
||||
beyondViewportPageCount = 1,
|
||||
modifier = Modifier.hazeEffectTangem {
|
||||
fallbackTint = HazeTint(color = overlay)
|
||||
progressive = HazeProgressive.verticalGradient(
|
||||
startIntensity = 1f,
|
||||
endIntensity = 1f,
|
||||
preferPerformance = true,
|
||||
)
|
||||
},
|
||||
) { currentWalletIndex ->
|
||||
val listState = listStates[currentWalletIndex] ?: rememberLazyListState()
|
||||
|
||||
|
|
@ -214,7 +250,8 @@ private fun WalletContent2(
|
|||
|
||||
LaunchedEffect(walletsPagerState.currentPage, currentWallet.walletsBalanceUM) {
|
||||
if (walletsPagerState.currentPage == currentWalletIndex) {
|
||||
walletBalance = (currentWallet.walletsBalanceUM as? WalletBalanceUM.Content)?.balanceInAppBar
|
||||
walletBalance =
|
||||
(currentWallet.walletsBalanceUM as? WalletBalanceUM.Content)?.balanceInAppBar
|
||||
}
|
||||
}
|
||||
LaunchedEffect(walletsPagerState.currentPage, currentWallet.pullToRefreshConfig) {
|
||||
|
|
@ -234,38 +271,45 @@ private fun WalletContent2(
|
|||
|
||||
val pageSlideAlpha by rememberPageAlpha(walletsPagerState, currentWalletIndex)
|
||||
|
||||
TangemPullToRefreshSlidingContainer(
|
||||
state = pullToRefreshState,
|
||||
config = currentWallet.pullToRefreshConfig,
|
||||
modifier = Modifier.alpha(pageSlideAlpha),
|
||||
indicatorOffset = with(LocalDensity.current) {
|
||||
behavior.state.partialHeightLimit.toDp()
|
||||
},
|
||||
TangemSharedTransitionLayout(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.alpha(pageSlideAlpha),
|
||||
) {
|
||||
TangemCollapsingTopBar(
|
||||
state = behavior.state,
|
||||
collapsingPart = {
|
||||
WalletBalance(
|
||||
behavior = behavior,
|
||||
walletBalanceUM = currentWallet.walletsBalanceUM,
|
||||
buttons = currentWallet.buttons,
|
||||
isBalanceHidden = state.isHidingMode,
|
||||
)
|
||||
TangemPullToRefreshSlidingContainer(
|
||||
state = pullToRefreshState,
|
||||
config = currentWallet.pullToRefreshConfig,
|
||||
indicatorOffset = with(LocalDensity.current) {
|
||||
behavior.state.partialHeightLimit.toDp()
|
||||
},
|
||||
body = {
|
||||
WalletListContent(
|
||||
currentWallet = currentWallet,
|
||||
listState = listState,
|
||||
isBalanceHidden = state.isHidingMode,
|
||||
contentPadding = contentPadding,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.nestedScroll(behavior.nestedScrollConnection),
|
||||
)
|
||||
},
|
||||
)
|
||||
) {
|
||||
TangemCollapsingTopBar(
|
||||
state = behavior.state,
|
||||
collapsingPart = {
|
||||
WalletBalance(
|
||||
behavior = behavior,
|
||||
walletBalanceUM = currentWallet.walletsBalanceUM,
|
||||
buttons = currentWallet.buttons,
|
||||
isBalanceHidden = state.isHidingMode,
|
||||
)
|
||||
},
|
||||
body = {
|
||||
WalletListContent(
|
||||
currentWallet = currentWallet,
|
||||
listState = listState,
|
||||
isBalanceHidden = state.isHidingMode,
|
||||
contentPadding = contentPadding,
|
||||
tangemPayComponent = tangemPayComponent,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.nestedScroll(behavior.nestedScrollConnection),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
val peekHeight = bottomSheetHeaderHeightProvider() + handComposableComponentHeight + bottomBarHeight
|
||||
val peekHeight =
|
||||
bottomSheetHeaderHeightProvider() + handComposableComponentHeight + bottomBarHeight
|
||||
MarketsHint(
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomCenter)
|
||||
|
|
@ -565,6 +609,14 @@ private fun WalletScreen2_Preview(@PreviewParameter(WalletScreen2PreviewProvider
|
|||
TangemThemePreviewRedesign {
|
||||
WalletScreen2(
|
||||
state = data,
|
||||
tangemPayComponent = object : TangemPayMainBlockComponent {
|
||||
override fun LazyListScope.tangemPayMainContent(
|
||||
state: TangemPayMainUM,
|
||||
isBalanceHidden: Boolean,
|
||||
modifier: Modifier,
|
||||
) {
|
||||
}
|
||||
},
|
||||
bottomSheetContent = {
|
||||
Text("Markets Content")
|
||||
},
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ package com.tangem.feature.wallet.presentation.wallet.ui.components
|
|||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.tangem.core.ui.ds.button.TangemButton
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.visa.TangemPayMainScreenBlock
|
||||
import com.tangem.features.tangempay.component.TangemPayMainBlockComponent
|
||||
import com.tangem.features.tangempay.entity.TangemPayMainUM
|
||||
|
||||
internal fun LazyListScope.nftCollections2(state: WalletUM, itemModifier: Modifier) {
|
||||
(state as? WalletUM.Content)?.let { content ->
|
||||
|
|
@ -33,17 +33,13 @@ internal fun LazyListScope.organizeTokens2(state: WalletUM, itemModifier: Modifi
|
|||
}
|
||||
}
|
||||
|
||||
internal fun LazyListScope.tangemPay(walletUM: WalletUM, isBalanceHiding: Boolean, modifier: Modifier = Modifier) {
|
||||
if (walletUM is WalletState.MultiCurrency) {
|
||||
item(
|
||||
key = "TangemPayMainScreenBlock",
|
||||
contentType = walletUM.tangemPayState::class.java,
|
||||
) {
|
||||
TangemPayMainScreenBlock(
|
||||
state = walletUM.tangemPayState,
|
||||
isBalanceHidden = isBalanceHiding,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
internal fun LazyListScope.tangemPay(
|
||||
tangemPayComponent: TangemPayMainBlockComponent,
|
||||
tangemPayUM: TangemPayMainUM,
|
||||
isBalanceHidden: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
with(tangemPayComponent) {
|
||||
tangemPayMainContent(modifier = modifier, state = tangemPayUM, isBalanceHidden = isBalanceHidden)
|
||||
}
|
||||
}
|
||||
|
|
@ -41,6 +41,9 @@ import com.tangem.core.ui.extensions.TextReference
|
|||
import com.tangem.core.ui.extensions.conditional
|
||||
import com.tangem.core.ui.extensions.orMaskWithStars
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.core.ui.res.TangemDimens
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
|
|
@ -156,16 +159,10 @@ private fun CardContainer(state: WalletCardState, isBalanceHidden: Boolean, item
|
|||
.padding(vertical = TangemTheme.dimens.spacing8),
|
||||
)
|
||||
|
||||
val additionalText by remember(state.additionalInfo, isBalanceHidden) {
|
||||
mutableStateOf(
|
||||
state.additionalInfo?.content?.orMaskWithStars(
|
||||
maskWithStars = state.additionalInfo?.hideable == true && isBalanceHidden,
|
||||
),
|
||||
)
|
||||
}
|
||||
AdditionalInfo(
|
||||
text = additionalText,
|
||||
showProgress = state.additionalInfo?.shouldShowProgress == true,
|
||||
content = state.additionalInfo?.content,
|
||||
hideable = state.additionalInfo?.hideable == true,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
modifier = Modifier.conditional(
|
||||
state.imageResId == null,
|
||||
) { fillMaxWidth() },
|
||||
|
|
@ -300,28 +297,53 @@ private fun Modifier.nonContentBalanceSize(dimens: TangemDimens): Modifier {
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun AdditionalInfo(text: TextReference?, showProgress: Boolean, modifier: Modifier = Modifier) {
|
||||
private fun AdditionalInfo(
|
||||
content: WalletAdditionalInfo.Content?,
|
||||
hideable: Boolean,
|
||||
isBalanceHidden: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
AnimatedContent(
|
||||
targetState = text,
|
||||
targetState = content,
|
||||
contentKey = { con ->
|
||||
when (con) {
|
||||
is WalletAdditionalInfo.Content.Text -> con
|
||||
is WalletAdditionalInfo.Content.SyncProgress -> WalletAdditionalInfo.Content.SyncProgress::class
|
||||
null -> null
|
||||
}
|
||||
},
|
||||
label = "Update the additional text",
|
||||
modifier = modifier,
|
||||
transitionSpec = {
|
||||
fadeIn(animationSpec = tween(durationMillis = 220, delayMillis = 90)) togetherWith
|
||||
fadeOut(animationSpec = tween(durationMillis = 90))
|
||||
},
|
||||
) { animatedText ->
|
||||
if (animatedText != null) {
|
||||
) { animatedContent ->
|
||||
if (animatedContent != null) {
|
||||
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,
|
||||
)
|
||||
when (animatedContent) {
|
||||
is WalletAdditionalInfo.Content.Text -> {
|
||||
AdditionalInfoText(
|
||||
text = animatedContent.text.orMaskWithStars(
|
||||
maskWithStars = hideable && isBalanceHidden,
|
||||
),
|
||||
)
|
||||
}
|
||||
is WalletAdditionalInfo.Content.SyncProgress -> {
|
||||
AdditionalInfoText(
|
||||
text = resourceReference(
|
||||
id = R.string.initial_wallet_sync_restore_progress,
|
||||
formatArgs = wrappedList(animatedContent.progressPercent),
|
||||
),
|
||||
)
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size16),
|
||||
color = TangemTheme.colors.icon.accent,
|
||||
strokeWidth = TangemTheme.dimens.size2,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -396,7 +418,7 @@ private class WalletCardStateProvider : CollectionPreviewParameterProvider<Walle
|
|||
title = "Title",
|
||||
additionalInfo = WalletAdditionalInfo(
|
||||
hideable = false,
|
||||
content = TextReference.Str("3 cards"),
|
||||
content = WalletAdditionalInfo.Content.Text(TextReference.Str("3 cards")),
|
||||
),
|
||||
),
|
||||
WalletPreviewDataLegacy.walletCardContentState.copy(
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ import com.tangem.common.ui.notifications.notificationsCarousel
|
|||
import com.tangem.core.ui.components.transactions.state.TxHistoryState
|
||||
import com.tangem.core.ui.components.transactions.txHistoryItems
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.utils.TangemSharedTransitionLayout
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency.tokensListItems
|
||||
|
|
@ -23,6 +22,7 @@ import com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency
|
|||
import com.tangem.feature.wallet.presentation.wallet.ui.components.nftCollections2
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.organizeTokens2
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.tangemPay
|
||||
import com.tangem.features.tangempay.component.TangemPayMainBlockComponent
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
||||
@Composable
|
||||
|
|
@ -30,6 +30,7 @@ internal fun WalletListContent(
|
|||
currentWallet: WalletUM,
|
||||
isBalanceHidden: Boolean,
|
||||
listState: LazyListState,
|
||||
tangemPayComponent: TangemPayMainBlockComponent,
|
||||
contentPadding: PaddingValues,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
|
|
@ -38,40 +39,40 @@ internal fun WalletListContent(
|
|||
val movableItemModifier = Modifier.padding(horizontal = TangemTheme.dimens2.x3)
|
||||
val itemModifier = movableItemModifier.padding(top = TangemTheme.dimens2.x3)
|
||||
|
||||
TangemSharedTransitionLayout(modifier) {
|
||||
LazyColumn(
|
||||
state = listState,
|
||||
contentPadding = contentPadding,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
overscrollEffect = rememberOverscrollEffect(),
|
||||
) {
|
||||
notifications(
|
||||
notifications = currentWallet.notifications.map { it.messageUM }.toPersistentList(),
|
||||
contentColor = containerColor,
|
||||
modifier = movableItemModifier,
|
||||
)
|
||||
notificationsCarousel(
|
||||
containerColor = containerColor,
|
||||
modifier = movableItemModifier,
|
||||
notifications = currentWallet.notificationsCarousel.map { it.messageUM }.toPersistentList(),
|
||||
)
|
||||
LazyColumn(
|
||||
modifier = modifier,
|
||||
state = listState,
|
||||
contentPadding = contentPadding,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
overscrollEffect = rememberOverscrollEffect(),
|
||||
) {
|
||||
notifications(
|
||||
notifications = currentWallet.notifications.map { it.messageUM }.toPersistentList(),
|
||||
contentColor = containerColor,
|
||||
modifier = movableItemModifier,
|
||||
)
|
||||
notificationsCarousel(
|
||||
containerColor = containerColor,
|
||||
modifier = movableItemModifier,
|
||||
notifications = currentWallet.notificationsCarousel.map { it.messageUM }.toPersistentList(),
|
||||
)
|
||||
|
||||
tangemPay(
|
||||
walletUM = currentWallet,
|
||||
isBalanceHiding = isBalanceHidden,
|
||||
modifier = itemModifier,
|
||||
)
|
||||
tangemPay(
|
||||
tangemPayComponent = tangemPayComponent,
|
||||
tangemPayUM = currentWallet.tangemPayMainUM,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
modifier = itemModifier,
|
||||
)
|
||||
|
||||
tokensListItems2(
|
||||
walletTokensListUM = currentWallet.tokensListUM,
|
||||
modifier = movableItemModifier,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
)
|
||||
tokensListItems2(
|
||||
walletTokensListUM = currentWallet.tokensListUM,
|
||||
modifier = movableItemModifier,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
)
|
||||
|
||||
nftCollections2(state = currentWallet, itemModifier = itemModifier)
|
||||
nftCollections2(state = currentWallet, itemModifier = itemModifier)
|
||||
|
||||
organizeTokens2(state = currentWallet, itemModifier = itemModifier)
|
||||
}
|
||||
organizeTokens2(state = currentWallet, itemModifier = itemModifier)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,10 +3,13 @@ package com.tangem.feature.wallet.presentation.wallet.ui.components.common
|
|||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.tangem.common.ui.notifications.CreatePaymentAccountNotification
|
||||
import com.tangem.core.ui.components.notifications.NoteMigrationNotification
|
||||
import com.tangem.core.ui.components.notifications.Notification
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.res.ForceDarkTheme
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
|
|
@ -49,6 +52,16 @@ internal fun LazyListScope.notifications(configs: ImmutableList<WalletNotificati
|
|||
)
|
||||
}
|
||||
}
|
||||
is WalletNotification.CreateTangemPayAccount -> {
|
||||
CreatePaymentAccountNotification(
|
||||
modifier = modifier.animateItem(fadeInSpec = null, fadeOutSpec = null),
|
||||
onClick = item.onClick,
|
||||
onCloseClick = item.onCloseClick,
|
||||
image = R.drawable.img_tangem_pay_visa_banner,
|
||||
title = resourceReference(R.string.tangempay_onboarding_banner_title),
|
||||
subtitle = resourceReference(R.string.tangempay_onboarding_banner_description),
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
Notification(
|
||||
config = item.config,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import androidx.compose.animation.core.animateFloatAsState
|
|||
import androidx.compose.animation.core.animateIntAsState
|
||||
import androidx.compose.animation.core.snap
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.combinedClickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
|
|
@ -17,8 +18,12 @@ import androidx.compose.material3.Text
|
|||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.layout.positionInWindow
|
||||
import androidx.compose.ui.layout.positionOnScreen
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
|
|
@ -155,12 +160,19 @@ private fun LazyListScope.tokenItem(
|
|||
backgroundColor = TangemTheme.colors2.surface.level3,
|
||||
)
|
||||
|
||||
var position by remember { mutableStateOf(Offset.Zero) }
|
||||
when (val tokenRowUM = listItem.tokenRowUM) {
|
||||
is TangemTokenRowUM -> TangemTokenRow(
|
||||
tokenRowUM = tokenRowUM,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
reorderableState = null,
|
||||
modifier = itemModifier,
|
||||
modifier = itemModifier
|
||||
.onGloballyPositioned { position = it.positionOnScreen() }
|
||||
.combinedClickable(
|
||||
enabled = tokenRowUM.onItemClick != null || tokenRowUM.onItemLongClick != null,
|
||||
onClick = tokenRowUM.onItemClick ?: {},
|
||||
onLongClick = { tokenRowUM.onItemLongClick?.invoke(position, tokenRowUM) },
|
||||
),
|
||||
)
|
||||
is TangemHeaderRowUM -> TangemHeaderRow(
|
||||
headerRowUM = tokenRowUM,
|
||||
|
|
@ -170,6 +182,7 @@ private fun LazyListScope.tokenItem(
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("LongMethod")
|
||||
private fun LazyListScope.portfolioItem(
|
||||
listItem: TokensListItemUM2.Portfolio,
|
||||
index: Int,
|
||||
|
|
@ -220,12 +233,23 @@ private fun LazyListScope.portfolioItem(
|
|||
.testTag(MainScreenTestTags.TOKEN_LIST_ITEM)
|
||||
.semantics { lazyListItemPosition = tokenIndex + 1 }
|
||||
|
||||
var position by remember { mutableStateOf(Offset.Zero) }
|
||||
when (val tokenRowUM = item.tokenRowUM) {
|
||||
is TangemTokenRowUM -> TangemTokenRow(
|
||||
tokenRowUM = tokenRowUM,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
reorderableState = null,
|
||||
modifier = itemModifier,
|
||||
modifier = itemModifier
|
||||
.onGloballyPositioned {
|
||||
position = it.positionInWindow()
|
||||
}
|
||||
.combinedClickable(
|
||||
enabled = tokenRowUM.onItemClick != null || tokenRowUM.onItemLongClick != null,
|
||||
onClick = tokenRowUM.onItemClick ?: {},
|
||||
onLongClick = {
|
||||
tokenRowUM.onItemLongClick?.invoke(position, tokenRowUM)
|
||||
},
|
||||
),
|
||||
)
|
||||
is TangemHeaderRowUM -> TangemHeaderRow(
|
||||
headerRowUM = tokenRowUM,
|
||||
|
|
@ -343,7 +367,8 @@ internal fun PortfolioRowItem(
|
|||
val composables = remember {
|
||||
SharedTokenRowComposables(
|
||||
icon = { modifier ->
|
||||
val size = if (isExpandedWrapped) AccountIconSize.ExtraSmall else AccountIconSize.Default
|
||||
val size =
|
||||
if (isExpandedWrapped) AccountIconSize.ExtraSmall else AccountIconSize.Default
|
||||
val headIcon = item.tokenRowUM.headIconUM
|
||||
val sizedHeadIcon = if (headIcon is TangemIconUM.Currency) {
|
||||
headIcon.copy(
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import com.tangem.core.ui.res.TangemTheme
|
|||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState.Progress
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification.Warning.TangemPayRefreshNeeded
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency.TangemPayCardMainBlock
|
||||
|
||||
|
|
@ -41,7 +42,6 @@ private fun TangemPayMainScreenBlockPreview() {
|
|||
TangemPayMainScreenBlock(
|
||||
state = TangemPayState.RefreshNeeded(
|
||||
TangemPayRefreshNeeded(
|
||||
tangemIcon = R.drawable.ic_tangem_24,
|
||||
buttonText = resourceReference(id = R.string.home_button_scan),
|
||||
onRefreshClick = {},
|
||||
shouldShowProgress = false,
|
||||
|
|
@ -49,13 +49,30 @@ private fun TangemPayMainScreenBlockPreview() {
|
|||
),
|
||||
isBalanceHidden = false,
|
||||
)
|
||||
TangemPayMainScreenBlock(
|
||||
state = TangemPayState.TemporaryUnavailable(WalletNotification.Warning.TangemPayUnreachable),
|
||||
isBalanceHidden = false,
|
||||
)
|
||||
TangemPayMainScreenBlock(
|
||||
state = TangemPayState.OnboardingBanner(onClick = {}, closeOnClick = {}),
|
||||
isBalanceHidden = false,
|
||||
)
|
||||
|
||||
TangemPayMainScreenBlock(state = TangemPayState.ExposedDevice, isBalanceHidden = false)
|
||||
TangemPayMainScreenBlock(
|
||||
state = TangemPayState.FailedIssue(
|
||||
title = TextReference.Res(R.string.tangempay_payment_account),
|
||||
description = TextReference.Res(R.string.tangempay_failed_to_issue_card),
|
||||
iconRes = R.drawable.ic_alert_24,
|
||||
onButtonClick = { },
|
||||
),
|
||||
isBalanceHidden = false,
|
||||
)
|
||||
|
||||
TangemPayMainScreenBlock(
|
||||
Progress(
|
||||
title = TextReference.Res(R.string.tangempay_kyc_in_progress_notification_title),
|
||||
description = TextReference.EMPTY,
|
||||
title = TextReference.Res(R.string.tangempay_payment_account),
|
||||
description = TextReference.Res(R.string.tangempay_kyc_in_progress),
|
||||
buttonText = TextReference.Res(R.string.tangempay_kyc_in_progress_notification_button),
|
||||
iconRes = R.drawable.ic_promo_kyc_36,
|
||||
onButtonClick = {},
|
||||
|
|
@ -65,19 +82,8 @@ private fun TangemPayMainScreenBlockPreview() {
|
|||
|
||||
TangemPayMainScreenBlock(
|
||||
Progress(
|
||||
title = TextReference.Res(R.string.tangempay_issue_card_notification_title),
|
||||
description = TextReference.EMPTY,
|
||||
buttonText = TextReference.Res(R.string.common_continue),
|
||||
iconRes = R.drawable.ic_tangem_pay_promo_card_36,
|
||||
onButtonClick = {},
|
||||
),
|
||||
isBalanceHidden = false,
|
||||
)
|
||||
|
||||
TangemPayMainScreenBlock(
|
||||
Progress(
|
||||
title = TextReference.Res(R.string.tangempay_issue_card_notification_title),
|
||||
description = TextReference.Res(R.string.tangempay_issue_card_notification_description),
|
||||
title = TextReference.Res(R.string.tangempay_payment_account),
|
||||
description = TextReference.Res(R.string.tangempay_issuing_your_card),
|
||||
buttonText = TextReference.EMPTY,
|
||||
iconRes = R.drawable.ic_tangem_pay_promo_card_36,
|
||||
onButtonClick = {},
|
||||
|
|
|
|||
|
|
@ -67,7 +67,6 @@ private fun TangemPayRefreshBlockPreview() {
|
|||
TangemPayRefreshBlock(
|
||||
state = TangemPayState.RefreshNeeded(
|
||||
TangemPayRefreshNeeded(
|
||||
tangemIcon = R.drawable.ic_tangem_24,
|
||||
buttonText = resourceReference(id = R.string.tangempay_sync_needed_restore_access),
|
||||
onRefreshClick = {},
|
||||
shouldShowProgress = true,
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ import kotlinx.coroutines.test.advanceUntilIdle
|
|||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import timber.log.Timber
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class DefaultPromoDeeplinkHandlerTest {
|
||||
|
|
@ -83,7 +82,6 @@ class DefaultPromoDeeplinkHandlerTest {
|
|||
messages = mutableListOf()
|
||||
every { uiMessageSender.send(capture(messages)) } just runs
|
||||
|
||||
Timber.uprootAll()
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue