From 7caeaf3a122d6b174f70013157450fc799dfd19d Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 2 Feb 2024 19:10:13 +0300 Subject: [PATCH 1/2] Updated on 2026-08-14 --- .../java/com/tangem/tap/TapApplication.kt | 5 ++++ .../di/domain/WalletManagersFacadeModule.kt | 6 ++-- .../com/tangem/tap/domain/TapWalletManager.kt | 13 ++++----- .../tap/proxy/redux/DaggerGraphState.kt | 2 ++ .../BlockchainWalletManagerFactoryModule.kt | 28 ++++++++++++++++++ .../DefaultBlockchainDataStorage.kt | 29 +++++++++++++++++++ .../DefaultWalletManagersFacade.kt | 6 ++-- .../utils/WalletManagerFactory.kt | 9 ++---- gradle/dependencies.toml | 2 +- 9 files changed, 78 insertions(+), 22 deletions(-) create mode 100644 core/datasource/src/main/java/com/tangem/datasource/di/BlockchainWalletManagerFactoryModule.kt create mode 100644 core/datasource/src/main/java/com/tangem/datasource/local/blockchain/DefaultBlockchainDataStorage.kt diff --git a/app/src/main/java/com/tangem/tap/TapApplication.kt b/app/src/main/java/com/tangem/tap/TapApplication.kt index f892dddee4..7e200d31b9 100644 --- a/app/src/main/java/com/tangem/tap/TapApplication.kt +++ b/app/src/main/java/com/tangem/tap/TapApplication.kt @@ -10,6 +10,7 @@ import com.orhanobut.logger.AndroidLogAdapter import com.orhanobut.logger.Logger import com.tangem.Log import com.tangem.LogFormat +import com.tangem.blockchain.common.WalletManagerFactory import com.tangem.blockchain.network.BlockchainSdkRetrofitBuilder import com.tangem.core.analytics.Analytics import com.tangem.core.analytics.filter.OneTimeEventFilter @@ -159,6 +160,9 @@ internal class TapApplication : Application(), ImageLoaderFactory { @Inject lateinit var testerFeatureToggles: TesterFeatureToggles + + @Inject + lateinit var blockchainWalletManagerFactory: WalletManagerFactory // endregion Injected override fun onCreate() { @@ -236,6 +240,7 @@ internal class TapApplication : Application(), ImageLoaderFactory { sendFeatureToggles = sendFeatureToggles, derivationsRepository = derivationsRepository, testerFeatureToggles = testerFeatureToggles, + blockchainWalletManagerFactory = blockchainWalletManagerFactory, ), ), ) diff --git a/app/src/main/java/com/tangem/tap/di/domain/WalletManagersFacadeModule.kt b/app/src/main/java/com/tangem/tap/di/domain/WalletManagersFacadeModule.kt index 02a52ce342..65a6dce65c 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/WalletManagersFacadeModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/WalletManagersFacadeModule.kt @@ -1,8 +1,8 @@ package com.tangem.tap.di.domain import com.squareup.moshi.Moshi +import com.tangem.blockchain.common.WalletManagerFactory import com.tangem.datasource.asset.AssetReader -import com.tangem.datasource.config.ConfigManager import com.tangem.datasource.di.SdkMoshi import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.datasource.local.walletmanager.WalletManagersStore @@ -24,7 +24,7 @@ internal object WalletManagersFacadeModule { fun provideWalletManagersFacade( walletManagersStore: WalletManagersStore, userWalletsStore: UserWalletsStore, - configManager: ConfigManager, + blockchainWalletManagerFactory: WalletManagerFactory, mnemonicRepository: MnemonicRepository, assetReader: AssetReader, @SdkMoshi moshi: Moshi, @@ -32,7 +32,7 @@ internal object WalletManagersFacadeModule { return DefaultWalletManagersFacade( walletManagersStore = walletManagersStore, userWalletsStore = userWalletsStore, - configManager = configManager, + blockchainWalletManagerFactory = blockchainWalletManagerFactory, assetReader = assetReader, moshi = moshi, mnemonic = mnemonicRepository.generateDefaultMnemonic(), diff --git a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt index 8d9ba42e6a..4379b387ab 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -1,23 +1,23 @@ package com.tangem.tap.domain -import com.tangem.blockchain.common.BlockchainSdkConfig import com.tangem.blockchain.common.Token import com.tangem.blockchain.common.Wallet import com.tangem.blockchain.common.WalletManagerFactory import com.tangem.core.analytics.Analytics +import com.tangem.core.analytics.models.Basic import com.tangem.datasource.config.ConfigManager import com.tangem.domain.common.extensions.withMainContext import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.wallets.models.UserWallet import com.tangem.operations.attestation.Attestation -import com.tangem.core.analytics.models.Basic import com.tangem.tap.common.extensions.setContext import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction import com.tangem.tap.features.disclaimer.createDisclaimer import com.tangem.tap.features.disclaimer.redux.DisclaimerAction import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction +import com.tangem.tap.proxy.redux.DaggerGraphState import com.tangem.tap.store import com.tangem.tap.tangemSdkManager import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider @@ -30,18 +30,15 @@ class TapWalletManager( private val dispatchers: CoroutineDispatcherProvider = AppCoroutineDispatcherProvider(), ) { - private val blockchainSdkConfig by lazy { - store.state.globalState.configManager?.config?.blockchainSdkConfig ?: BlockchainSdkConfig() - } - private var loadUserWalletDataJob: Job? = null set(value) { field?.cancel() field = value } - val walletManagerFactory: WalletManagerFactory - by lazy { WalletManagerFactory(blockchainSdkConfig) } + val walletManagerFactory: WalletManagerFactory by lazy { + store.state.daggerGraphState.get(DaggerGraphState::blockchainWalletManagerFactory) + } suspend fun onWalletSelected(userWallet: UserWallet, sendAnalyticsEvent: Boolean) { // If a previous job was running, it gets cancelled before the new one starts, diff --git a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt index b1839fae93..19875bc1be 100644 --- a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt +++ b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt @@ -1,5 +1,6 @@ package com.tangem.tap.proxy.redux +import com.tangem.blockchain.common.WalletManagerFactory import com.tangem.datasource.connection.NetworkConnectionManager import com.tangem.domain.appcurrency.repository.AppCurrencyRepository import com.tangem.domain.apptheme.repository.AppThemeModeRepository @@ -57,6 +58,7 @@ data class DaggerGraphState( val currenciesRepository: CurrenciesRepository? = null, val derivationsRepository: DerivationsRepository? = null, val testerFeatureToggles: TesterFeatureToggles? = null, + val blockchainWalletManagerFactory: WalletManagerFactory? = null, ) : StateType { inline fun get(getDependency: DaggerGraphState.() -> T?): T { diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/BlockchainWalletManagerFactoryModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/BlockchainWalletManagerFactoryModule.kt new file mode 100644 index 0000000000..aeec8933f9 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/di/BlockchainWalletManagerFactoryModule.kt @@ -0,0 +1,28 @@ +package com.tangem.datasource.di + +import com.tangem.blockchain.common.WalletManagerFactory +import com.tangem.datasource.config.ConfigManager +import com.tangem.datasource.local.blockchain.DefaultBlockchainDataStorage +import com.tangem.datasource.local.preferences.AppPreferencesStore +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +internal object BlockchainWalletManagerFactoryModule { + + @Provides + @Singleton + fun provideBlockchainWalletManagerFactory( + configManager: ConfigManager, + appPreferencesStore: AppPreferencesStore, + ): WalletManagerFactory { + return WalletManagerFactory( + config = configManager.config.blockchainSdkConfig, + blockchainDataStorage = DefaultBlockchainDataStorage(appPreferencesStore), + ) + } +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/blockchain/DefaultBlockchainDataStorage.kt b/core/datasource/src/main/java/com/tangem/datasource/local/blockchain/DefaultBlockchainDataStorage.kt new file mode 100644 index 0000000000..3f3d7192f5 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/local/blockchain/DefaultBlockchainDataStorage.kt @@ -0,0 +1,29 @@ +package com.tangem.datasource.local.blockchain + +import androidx.datastore.preferences.core.edit +import androidx.datastore.preferences.core.stringPreferencesKey +import com.tangem.blockchain.common.datastorage.BlockchainDataStorage +import com.tangem.datasource.local.preferences.AppPreferencesStore +import com.tangem.datasource.local.preferences.utils.getSyncOrNull + +/** + * [BlockchainDataStorage] implementation + * + * @property appPreferencesStore app preferences store + * +[REDACTED_AUTHOR] + */ +internal class DefaultBlockchainDataStorage( + private val appPreferencesStore: AppPreferencesStore, +) : BlockchainDataStorage { + + override suspend fun getOrNull(key: String): String? { + return appPreferencesStore.getSyncOrNull(key = stringPreferencesKey(name = key)) + } + + override suspend fun store(key: String, value: String) { + appPreferencesStore.edit { + it[stringPreferencesKey(key)] = value + } + } +} \ No newline at end of file diff --git a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/DefaultWalletManagersFacade.kt b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/DefaultWalletManagersFacade.kt index 213a569e11..f5bbe8c596 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/DefaultWalletManagersFacade.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/DefaultWalletManagersFacade.kt @@ -19,7 +19,6 @@ import com.tangem.blockchain.extensions.SimpleResult import com.tangem.crypto.bip39.Mnemonic import com.tangem.crypto.hdWallet.DerivationPath import com.tangem.datasource.asset.AssetReader -import com.tangem.datasource.config.ConfigManager import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.datasource.local.walletmanager.WalletManagersStore import com.tangem.domain.common.util.hasDerivation @@ -39,6 +38,7 @@ import kotlinx.coroutines.flow.Flow import timber.log.Timber import java.math.BigDecimal import java.util.EnumSet +import com.tangem.blockchain.common.WalletManagerFactory as BlockchainWalletManagerFactory @Suppress("LargeClass", "TooManyFunctions") // FIXME: Move to its own module and make internal @@ -46,7 +46,7 @@ import java.util.EnumSet class DefaultWalletManagersFacade( private val walletManagersStore: WalletManagersStore, private val userWalletsStore: UserWalletsStore, - configManager: ConfigManager, + blockchainWalletManagerFactory: BlockchainWalletManagerFactory, mnemonic: Mnemonic, assetReader: AssetReader, moshi: Moshi, @@ -54,7 +54,7 @@ class DefaultWalletManagersFacade( private val demoConfig by lazy { DemoConfig() } private val resultFactory by lazy { UpdateWalletManagerResultFactory() } - private val walletManagerFactory by lazy { WalletManagerFactory(configManager) } + private val walletManagerFactory by lazy { WalletManagerFactory(blockchainWalletManagerFactory) } private val sdkTokenConverter by lazy { SdkTokenConverter() } private val txHistoryStateConverter by lazy { SdkTransactionHistoryStateConverter() } private val txHistoryItemConverter by lazy { SdkTransactionHistoryItemConverter(assetReader, moshi) } diff --git a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/WalletManagerFactory.kt b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/WalletManagerFactory.kt index 9e83e20e3a..d00e6d64a1 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/WalletManagerFactory.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/WalletManagerFactory.kt @@ -3,23 +3,18 @@ package com.tangem.domain.walletmanager.utils import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.DerivationParams import com.tangem.blockchain.common.WalletManager -import com.tangem.blockchain.common.WalletManagerFactory import com.tangem.crypto.hdWallet.DerivationPath -import com.tangem.datasource.config.ConfigManager import com.tangem.domain.common.DerivationStyleProvider import com.tangem.domain.common.extensions.makeWalletManagerForApp import com.tangem.domain.common.util.derivationStyleProvider import com.tangem.domain.models.scan.ScanResponse import timber.log.Timber +import com.tangem.blockchain.common.WalletManagerFactory as BlockchainWalletManagerFactory internal class WalletManagerFactory( - private val configManager: ConfigManager, + private val sdkWalletManagerFactory: BlockchainWalletManagerFactory, ) { - private val sdkWalletManagerFactory by lazy { - WalletManagerFactory(configManager.config.blockchainSdkConfig) - } - fun createWalletManager( scanResponse: ScanResponse, blockchain: Blockchain, diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index f6b9405dcf..f807b5d3a4 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -85,7 +85,7 @@ spr-client = "3.6.2" # endregion Other libraries # region Tangem -tangemBlockchainSdk = "develop-471" +tangemBlockchainSdk = "develop-473" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "develop-324" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ From 1512c4e3172d4f5e9613e1a26e9c198b59bb8b51 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 2 Feb 2024 15:34:06 +0300 Subject: [PATCH 2/2] Updated on 2026-08-14 --- .../impl/presentation/state/StateRouter.kt | 18 +-- .../state/fee/FeeNotificationFactory.kt | 2 +- .../state/fee/SendFeeNotification.kt | 21 +--- .../ui/fee/SendSpeedAndFeeContent.kt | 107 ++++++++++++++---- .../presentation/ui/fee/SendSpeedSelector.kt | 33 ++++++ .../impl/presentation/ui/send/SendContent.kt | 10 +- .../presentation/viewmodel/SendViewModel.kt | 2 +- 7 files changed, 138 insertions(+), 55 deletions(-) diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/StateRouter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/StateRouter.kt index 4edb445226..f29ae7acb7 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/StateRouter.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/StateRouter.kt @@ -15,12 +15,16 @@ internal class StateRouter( fragmentManager.get()?.popBackStack() } - fun onBackClick() { - when (currentState.value) { - SendUiStateType.Recipient -> popBackStack() - SendUiStateType.Amount -> showRecipient() - SendUiStateType.Fee -> showAmount() - SendUiStateType.Send -> showFee() + fun onBackClick(isSuccess: Boolean = false) { + if (isSuccess) { + popBackStack() + } else { + when (currentState.value) { + SendUiStateType.Recipient -> popBackStack() + SendUiStateType.Amount -> showRecipient() + SendUiStateType.Fee -> showAmount() + SendUiStateType.Send -> showFee() + } } } @@ -54,7 +58,7 @@ internal class StateRouter( currentState.update { SendUiStateType.Fee } } - private fun showSend() { + fun showSend() { currentState.update { SendUiStateType.Send } } } \ No newline at end of file diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeNotificationFactory.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeNotificationFactory.kt index 244ed17cdd..d95031bd4e 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeNotificationFactory.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeNotificationFactory.kt @@ -70,7 +70,7 @@ internal class FeeNotificationFactory( val customAmount = customFee.firstOrNull() ?: return val customValue = customAmount.value.parseToBigDecimal(customAmount.decimals) if (selectedFee == FeeType.CUSTOM && minimumValue > customValue) { - add(SendFeeNotification.Informational.TooLow) + add(SendFeeNotification.Warning.TooLow) } } diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/SendFeeNotification.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/SendFeeNotification.kt index d58cb3cd98..f895fb4921 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/SendFeeNotification.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/SendFeeNotification.kt @@ -8,22 +8,6 @@ import com.tangem.features.send.impl.R sealed class SendFeeNotification(val config: NotificationConfig) { - sealed class Informational( - val title: TextReference, - val subtitle: TextReference, - ) : SendFeeNotification( - config = NotificationConfig( - title = title, - subtitle = subtitle, - iconResId = R.drawable.ic_alert_circle_24, - ), - ) { - object TooLow : Informational( - title = resourceReference(id = R.string.send_notification_transaction_delay_title), - subtitle = resourceReference(id = R.string.send_notification_transaction_delay_text), - ) - } - sealed class Warning( val title: TextReference, val subtitle: TextReference, @@ -36,6 +20,11 @@ sealed class SendFeeNotification(val config: NotificationConfig) { buttonsState = buttonsState, ), ) { + object TooLow : Warning( + title = resourceReference(id = R.string.send_notification_transaction_delay_title), + subtitle = resourceReference(id = R.string.send_notification_transaction_delay_text), + ) + data class TooHigh( val value: String, ) : Warning( diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedAndFeeContent.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedAndFeeContent.kt index b253efe2e5..0c1316c178 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedAndFeeContent.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedAndFeeContent.kt @@ -15,14 +15,15 @@ import com.tangem.core.ui.components.notifications.Notification import com.tangem.core.ui.res.TangemTheme import com.tangem.features.send.impl.presentation.state.SendStates import com.tangem.features.send.impl.presentation.state.fee.FeeSelectorState +import com.tangem.features.send.impl.presentation.state.fee.FeeType import com.tangem.features.send.impl.presentation.state.fee.SendFeeNotification import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.toImmutableList private const val FEE_SELECTOR_KEY = "FEE_SELECTOR_KEY" private const val FEE_CUSTOM_KEY = "FEE_CUSTOM_KEY" -@OptIn(ExperimentalFoundationApi::class) @Composable internal fun SendSpeedAndFeeContent(state: SendStates.FeeState?, clickIntents: SendClickIntents) { if (state == null) return @@ -36,46 +37,92 @@ internal fun SendSpeedAndFeeContent(state: SendStates.FeeState?, clickIntents: S horizontal = TangemTheme.dimens.spacing16, ), ) { - item( - key = FEE_SELECTOR_KEY, - ) { - SendSpeedSelector( - state = state, - clickIntents = clickIntents, - modifier = Modifier.animateItemPlacement(), - ) - } + feeSelector(state, clickIntents) + topNotifications(notifications) customFee(feeSendState) - notifications(notifications) - subtractButton( - receivedAmount = state.receivedAmount, - isSubtract = state.isSubtract, - isSubtractAvailable = state.isSubtractAvailable, - clickIntents = clickIntents, - ) + middleNotifications(notifications) + subtractButton(state, clickIntents) + bottomNotifications(notifications) } } @OptIn(ExperimentalFoundationApi::class) -internal fun LazyListScope.notifications(configs: ImmutableList, modifier: Modifier = Modifier) { +private fun LazyListScope.feeSelector(state: SendStates.FeeState, clickIntents: SendClickIntents) { + item( + key = FEE_SELECTOR_KEY, + ) { + SendSpeedSelector( + state = state, + clickIntents = clickIntents, + modifier = Modifier.animateItemPlacement(), + ) + } +} + +private fun LazyListScope.topNotifications( + configs: ImmutableList, + modifier: Modifier = Modifier, +) { + notifications( + configs = configs.filter { + it is SendFeeNotification.Error.ExceedsBalance || + it is SendFeeNotification.Warning.NetworkFeeUnreachable + }.toImmutableList(), + modifier = modifier, + ) +} + +private fun LazyListScope.middleNotifications( + configs: ImmutableList, + modifier: Modifier = Modifier, +) { + notifications( + configs = configs.filter { + it is SendFeeNotification.Warning.TooLow || + it is SendFeeNotification.Warning.TooHigh + }.toImmutableList(), + modifier = modifier, + ) +} + +private fun LazyListScope.bottomNotifications( + configs: ImmutableList, + modifier: Modifier = Modifier, +) { + notifications( + configs = configs.filterIsInstance().toImmutableList(), + isLast = true, + modifier = modifier, + ) +} + +@OptIn(ExperimentalFoundationApi::class) +private fun LazyListScope.notifications( + configs: ImmutableList, + modifier: Modifier = Modifier, + isLast: Boolean = false, +) { items( items = configs, key = { it::class.java }, contentType = { it::class.java }, itemContent = { + val bottomPadding = if (isLast) TangemTheme.dimens.spacing12 else TangemTheme.dimens.spacing0 Notification( config = it.config, modifier = modifier - .padding(top = TangemTheme.dimens.spacing12) + .padding( + top = TangemTheme.dimens.spacing12, + bottom = bottomPadding, + ) .animateItemPlacement(), containerColor = when (it) { is SendFeeNotification.Error.ExceedsBalance, is SendFeeNotification.Warning.NetworkFeeUnreachable, - -> TangemTheme.colors.background.primary + -> TangemTheme.colors.background.action else -> TangemTheme.colors.button.disabled }, iconTint = when (it) { - is SendFeeNotification.Informational -> TangemTheme.colors.icon.accent is SendFeeNotification.Error.ExceedsBalance -> { if (it.config.buttonsState == null) { TangemTheme.colors.icon.warning @@ -116,20 +163,30 @@ internal fun LazyListScope.customFee(feeSendState: FeeSelectorState, modifier: M @OptIn(ExperimentalFoundationApi::class) internal fun LazyListScope.subtractButton( - receivedAmount: String, - isSubtract: Boolean, - isSubtractAvailable: Boolean, + state: SendStates.FeeState, clickIntents: SendClickIntents, modifier: Modifier = Modifier, ) { + val receivedAmount = state.receivedAmount + val isSubtract = state.isSubtract + val isSubtractAvailable = state.isSubtractAvailable + val feeSendState = state.feeSelectorState if (isSubtractAvailable) { item { + val feeStateContent = feeSendState as? FeeSelectorState.Content + val isCustomAvailable = feeStateContent?.customValues.isNullOrEmpty().not() + val isCustomSelected = feeStateContent?.selectedFee == FeeType.CUSTOM + val topPadding = if (isCustomSelected && isCustomAvailable) { + TangemTheme.dimens.spacing12 + } else { + TangemTheme.dimens.spacing20 + } SendSpeedSubtract( receivingAmount = receivedAmount, isSubtract = isSubtract, onSelectClick = clickIntents::onSubtractSelect, modifier = modifier - .padding(vertical = TangemTheme.dimens.spacing12) + .padding(top = topPadding) .animateItemPlacement(), ) } diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedSelector.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedSelector.kt index db73ae5c7e..2721c1698e 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedSelector.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedSelector.kt @@ -4,6 +4,9 @@ import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.animateColorAsState +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* @@ -39,6 +42,7 @@ import com.tangem.features.send.impl.R import com.tangem.features.send.impl.presentation.state.SendStates import com.tangem.features.send.impl.presentation.state.fee.FeeSelectorState import com.tangem.features.send.impl.presentation.state.fee.FeeType +import com.tangem.features.send.impl.presentation.state.fee.SendFeeNotification import com.tangem.features.send.impl.presentation.ui.common.FooterContainer import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents import java.math.BigDecimal @@ -112,12 +116,17 @@ internal fun SendSpeedSelector( visible = fees.normal is Fee.Ethereum, label = "Custom fee appearance animation", ) { + val showWarning = state.notifications.any { + it is SendFeeNotification.Warning.TooHigh || + it is SendFeeNotification.Warning.TooLow + } SendSpeedSelectorItem( titleRes = R.string.common_fee_selector_option_custom, iconRes = R.drawable.ic_edit_24, isSelected = isSelected == FeeType.CUSTOM, onSelect = { clickIntents.onFeeSelectorClick(FeeType.CUSTOM) }, showDivider = fees.normal !is Fee.Ethereum, + showWarning = showWarning, ) } } @@ -224,6 +233,7 @@ private fun SendSpeedSelectorItem( symbolLength: Int? = null, isSelected: Boolean = false, showDivider: Boolean = true, + showWarning: Boolean = false, ) { val iconTint by animateColorAsState( targetValue = if (isSelected) { @@ -259,7 +269,10 @@ private fun SendSpeedSelectorItem( symbolLength = symbolLength, textStyle = textStyle, ) + } else { + SpacerWMax() } + WarningIcon(showWarning = showWarning) } if (showDivider) { Box( @@ -340,6 +353,26 @@ private fun RowScope.SelectorValueContent( ) } +@Composable +private fun WarningIcon(showWarning: Boolean = false) { + AnimatedVisibility( + visible = showWarning, + label = "Custom fee warning indicator", + enter = fadeIn(), + exit = fadeOut(), + ) { + Image( + painter = painterResource(R.drawable.ic_alert_triangle_20), + contentDescription = null, + modifier = Modifier + .padding( + vertical = TangemTheme.dimens.spacing12, + horizontal = TangemTheme.dimens.spacing14, + ), + ) + } +} + //region preview @Preview @Composable diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/send/SendContent.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/send/SendContent.kt index d014f71caa..694dac7048 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/send/SendContent.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/send/SendContent.kt @@ -67,16 +67,16 @@ internal fun SendContent(uiState: SendUiState) { walletBalance = amountState.walletBalance.resolveReference(), ) } - AmountBlock( - amountState = amountState, - isSuccess = isSuccess, - onClick = uiState.clickIntents::showAmount, - ) RecipientBlock( recipientState = recipientState, isSuccess = isSuccess, onClick = uiState.clickIntents::showRecipient, ) + AmountBlock( + amountState = amountState, + isSuccess = isSuccess, + onClick = uiState.clickIntents::showAmount, + ) FeeBlock( feeState = feeState, isSuccess = isSuccess, diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/viewmodel/SendViewModel.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/viewmodel/SendViewModel.kt index b02ffb58d7..a675d41dad 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/viewmodel/SendViewModel.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/viewmodel/SendViewModel.kt @@ -352,7 +352,7 @@ internal class SendViewModel @Inject constructor( // region screen state navigation override fun popBackStack() = stateRouter.popBackStack() - override fun onBackClick() = stateRouter.onBackClick() + override fun onBackClick() = stateRouter.onBackClick(uiState.sendState.isSuccess) override fun onNextClick() = stateRouter.onNextClick() override fun onPrevClick() = stateRouter.onPrevClick()