diff --git a/app/src/main/java/com/tangem/tap/di/domain/SettingsDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/SettingsDomainModule.kt index 2d8764fc7c..ac3b9c779e 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/SettingsDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/SettingsDomainModule.kt @@ -126,4 +126,18 @@ internal object SettingsDomainModule { fun provideDeleteDeprecatedLogsUseCase(settingsRepository: SettingsRepository): DeleteDeprecatedLogsUseCase { return DeleteDeprecatedLogsUseCase(settingsRepository) } + + @Provides + @ViewModelScoped + fun provideIsSendTapHelpPreviewEnabledUseCase( + settingsRepository: SettingsRepository, + ): IsSendTapHelpEnabledUseCase { + return IsSendTapHelpEnabledUseCase(settingsRepository = settingsRepository) + } + + @Provides + @ViewModelScoped + fun provideNeverToShowTapHelpUseCase(settingsRepository: SettingsRepository): NeverToShowTapHelpUseCase { + return NeverToShowTapHelpUseCase(settingsRepository = settingsRepository) + } } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt b/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt index 22d8aa8ea3..ab0ab7c350 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt @@ -63,6 +63,8 @@ object PreferencesKeys { val APP_LOGS_KEY by lazy { stringPreferencesKey(name = "app_logs") } + val SEND_TAP_HELP_PREVIEW_KEY by lazy { booleanPreferencesKey(name = "sendTapHelpPreview") } + fun getStart2CoinTOSAcceptedKey(region: String?) = booleanPreferencesKey(name = "start2Coin_tos_accepted_$region") } diff --git a/data/settings/src/main/java/com/tangem/data/settings/DefaultSettingsRepository.kt b/data/settings/src/main/java/com/tangem/data/settings/DefaultSettingsRepository.kt index 277d4fc31f..71e8f8d654 100644 --- a/data/settings/src/main/java/com/tangem/data/settings/DefaultSettingsRepository.kt +++ b/data/settings/src/main/java/com/tangem/data/settings/DefaultSettingsRepository.kt @@ -61,4 +61,18 @@ internal class DefaultSettingsRepository( ) } } + + override suspend fun isSendTapHelpPreviewEnabled(): Boolean { + return appPreferencesStore.getSyncOrDefault( + key = PreferencesKeys.SEND_TAP_HELP_PREVIEW_KEY, + default = true, + ) + } + + override suspend fun setSendTapHelpPreviewAvailability(isEnabled: Boolean) { + appPreferencesStore.store( + key = PreferencesKeys.SEND_TAP_HELP_PREVIEW_KEY, + value = isEnabled, + ) + } } \ No newline at end of file diff --git a/domain/settings/src/main/java/com/tangem/domain/settings/IsSendTapHelpEnabledUseCase.kt b/domain/settings/src/main/java/com/tangem/domain/settings/IsSendTapHelpEnabledUseCase.kt new file mode 100644 index 0000000000..1e828a0bc6 --- /dev/null +++ b/domain/settings/src/main/java/com/tangem/domain/settings/IsSendTapHelpEnabledUseCase.kt @@ -0,0 +1,13 @@ +package com.tangem.domain.settings + +import com.tangem.domain.settings.repositories.SettingsRepository + +/** + * Checks if tap help is enabled + * + * @property settingsRepository settings repository + */ +class IsSendTapHelpEnabledUseCase(private val settingsRepository: SettingsRepository) { + + suspend operator fun invoke(): Boolean = settingsRepository.isSendTapHelpPreviewEnabled() +} \ No newline at end of file diff --git a/domain/settings/src/main/java/com/tangem/domain/settings/NeverToShowTapHelpUseCase.kt b/domain/settings/src/main/java/com/tangem/domain/settings/NeverToShowTapHelpUseCase.kt new file mode 100644 index 0000000000..bf72970303 --- /dev/null +++ b/domain/settings/src/main/java/com/tangem/domain/settings/NeverToShowTapHelpUseCase.kt @@ -0,0 +1,13 @@ +package com.tangem.domain.settings + +import com.tangem.domain.settings.repositories.SettingsRepository + +/** + * Never to show tap help + * + * @property settingsRepository settings repository + */ +class NeverToShowTapHelpUseCase(private val settingsRepository: SettingsRepository) { + + suspend operator fun invoke() = settingsRepository.setSendTapHelpPreviewAvailability(isEnabled = false) +} \ No newline at end of file diff --git a/domain/settings/src/main/java/com/tangem/domain/settings/repositories/SettingsRepository.kt b/domain/settings/src/main/java/com/tangem/domain/settings/repositories/SettingsRepository.kt index 061ee78557..63a3ab3247 100644 --- a/domain/settings/src/main/java/com/tangem/domain/settings/repositories/SettingsRepository.kt +++ b/domain/settings/src/main/java/com/tangem/domain/settings/repositories/SettingsRepository.kt @@ -13,4 +13,8 @@ interface SettingsRepository { @Throws suspend fun deleteDeprecatedLogs(maxSize: Int) + + suspend fun isSendTapHelpPreviewEnabled(): Boolean + + suspend fun setSendTapHelpPreviewAvailability(isEnabled: Boolean) } \ No newline at end of file diff --git a/features/send/impl/build.gradle.kts b/features/send/impl/build.gradle.kts index db20b4afc2..587cb6d67c 100644 --- a/features/send/impl/build.gradle.kts +++ b/features/send/impl/build.gradle.kts @@ -72,6 +72,7 @@ dependencies { implementation(projects.domain.balanceHiding.models) implementation(projects.domain.qrScanning) implementation(projects.domain.qrScanning.models) + implementation(projects.domain.settings) /** Feature modules */ implementation(projects.features.send.api) diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendNotificationFactory.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendNotificationFactory.kt index 426ddab71a..0064f20684 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendNotificationFactory.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendNotificationFactory.kt @@ -39,7 +39,7 @@ internal class SendNotificationFactory( .filter { it.type == SendUiStateType.Send } .map { val state = currentStateProvider() - val sendState = state.sendState + val sendState = state.sendState ?: return@map persistentListOf() val feeState = state.feeState ?: return@map persistentListOf() val feeAmount = feeState.fee?.amount?.value ?: BigDecimal.ZERO val amountValue = state.amountState?.amountTextField?.cryptoAmount?.value ?: BigDecimal.ZERO @@ -60,7 +60,7 @@ internal class SendNotificationFactory( fun dismissNotificationState(clazz: Class): SendUiState { val state = currentStateProvider() - val sendState = state.sendState + val sendState = state.sendState ?: return state val notificationsToRemove = sendState.notifications.filterIsInstance(clazz) val updatedNotifications = sendState.notifications.toMutableList() updatedNotifications.removeAll(notificationsToRemove) diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendStateFactory.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendStateFactory.kt index 5f865ed61a..b5f1d0f72e 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendStateFactory.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendStateFactory.kt @@ -13,8 +13,9 @@ import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.usecase.ValidateWalletMemoUseCase import com.tangem.features.send.impl.R import com.tangem.features.send.impl.presentation.domain.AvailableWallet -import com.tangem.features.send.impl.presentation.state.amount.SendAmountSubtractConverter import com.tangem.features.send.impl.presentation.state.amount.SendAmountStateConverter +import com.tangem.features.send.impl.presentation.state.amount.SendAmountSubtractConverter +import com.tangem.features.send.impl.presentation.state.confirm.SendConfirmStateConverter import com.tangem.features.send.impl.presentation.state.fee.SendFeeStateConverter import com.tangem.features.send.impl.presentation.state.fields.SendAmountFieldConverter import com.tangem.features.send.impl.presentation.state.recipient.SendRecipientListConverter @@ -33,6 +34,7 @@ internal class SendStateFactory( private val appCurrencyProvider: Provider, private val cryptoCurrencyStatusProvider: Provider, private val feeCryptoCurrencyStatusProvider: Provider, + private val isTapHelpPreviewEnabledProvider: Provider, private val validateWalletMemoUseCase: ValidateWalletMemoUseCase, private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase, ) { @@ -72,7 +74,11 @@ internal class SendStateFactory( feeCryptoCurrencyStatusProvider = feeCryptoCurrencyStatusProvider, ) } - + private val confirmStateConverter by lazy(LazyThreadSafetyMode.NONE) { + SendConfirmStateConverter( + isTapHelpPreviewEnabledProvider = isTapHelpPreviewEnabledProvider, + ) + } private val recipientListStateConverter by lazy(LazyThreadSafetyMode.NONE) { SendRecipientListConverter( currentStateProvider = currentStateProvider, @@ -96,6 +102,7 @@ internal class SendStateFactory( recipientState = state.recipientState ?: recipientStateConverter.convert(SendRecipientStateConverter.Data("", null)), feeState = state.feeState ?: feeStateConverter.convert(Unit), + sendState = confirmStateConverter.convert(Unit), cryptoCurrencySymbol = cryptoCurrencyStatusProvider().currency.symbol, ) } @@ -236,21 +243,22 @@ internal class SendStateFactory( fun getSendingStateUpdate(isSending: Boolean): SendUiState { val state = currentStateProvider() - return state.copy(sendState = state.sendState.copy(isSending = isSending)) + return state.copy(sendState = state.sendState?.copy(isSending = isSending)) } fun getTransactionSendState(txData: TransactionData): SendUiState { val state = currentStateProvider() val cryptoCurrency = cryptoCurrencyStatusProvider().currency - + val sendState = state.sendState ?: return state val txUrl = getExplorerTransactionUrlUseCase( txHash = txData.hash.orEmpty(), networkId = cryptoCurrency.network.id, ).getOrElse { "" } return state.copy( - sendState = state.sendState.copy( + sendState = sendState.copy( transactionDate = txData.date?.timeInMillis ?: System.currentTimeMillis(), isSuccess = true, + showTapHelp = false, txUrl = txUrl, notifications = persistentListOf(), ), @@ -259,13 +267,23 @@ internal class SendStateFactory( fun getSendNotificationState(notifications: ImmutableList): SendUiState { val state = currentStateProvider() + val sendState = state.sendState ?: return state val hasErrorNotifications = notifications.any { it is SendNotification.Error } return state.copy( - sendState = state.sendState.copy( + sendState = sendState.copy( isPrimaryButtonEnabled = !hasErrorNotifications, notifications = notifications, + showTapHelp = sendState.showTapHelp && notifications.isEmpty(), ), ) } + + fun getHiddenTapHelpState(): SendUiState { + val state = currentStateProvider() + val sendState = state.sendState ?: return state + return state.copy( + sendState = sendState.copy(showTapHelp = false), + ) + } //endregion } \ No newline at end of file diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendUiState.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendUiState.kt index 00d7a9dbbe..5ac0949edf 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendUiState.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendUiState.kt @@ -15,7 +15,6 @@ import com.tangem.features.send.impl.presentation.state.fields.SendTextField import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.PersistentList -import kotlinx.collections.immutable.persistentListOf import java.math.BigDecimal /** @@ -29,7 +28,7 @@ internal data class SendUiState( val amountState: SendStates.AmountState? = null, val recipientState: SendStates.RecipientState? = null, val feeState: SendStates.FeeState? = null, - val sendState: SendStates.SendState = SendStates.SendState(), + val sendState: SendStates.SendState? = null, val isBalanceHidden: Boolean, val event: StateEvent, ) @@ -84,14 +83,15 @@ internal sealed class SendStates { data class SendState( override val type: SendUiStateType = SendUiStateType.Send, override val isPrimaryButtonEnabled: Boolean = true, - val isSending: Boolean = false, - val isSuccess: Boolean = false, - val isSubtract: Boolean = false, - val transactionDate: Long = 0L, - val txUrl: String = "", - val ignoreAmountReduce: Boolean = false, - val isFromConfirmation: Boolean = true, - val notifications: ImmutableList = persistentListOf(), + val isSending: Boolean, + val isSuccess: Boolean, + val isSubtract: Boolean, + val transactionDate: Long, + val txUrl: String, + val ignoreAmountReduce: Boolean, + val isFromConfirmation: Boolean, + val showTapHelp: Boolean, + val notifications: ImmutableList, ) : SendStates() } diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/amount/SendAmountSubtractConverter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/amount/SendAmountSubtractConverter.kt index 4d00bd9b2e..bcad6f7468 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/amount/SendAmountSubtractConverter.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/amount/SendAmountSubtractConverter.kt @@ -31,7 +31,7 @@ internal class SendAmountSubtractConverter( val fiatValue = decimalFiatValue.parseBigDecimal(fiatDecimals) return state.copy( - sendState = state.sendState.copy(isSubtract = true), + sendState = state.sendState?.copy(isSubtract = true), amountState = amountState.copy( amountTextField = amountTextField.copy( value = cryptoValue, diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendConfirmStateConverter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendConfirmStateConverter.kt new file mode 100644 index 0000000000..d5662a10b7 --- /dev/null +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendConfirmStateConverter.kt @@ -0,0 +1,25 @@ +package com.tangem.features.send.impl.presentation.state.confirm + +import com.tangem.features.send.impl.presentation.state.SendStates +import com.tangem.utils.Provider +import com.tangem.utils.converter.Converter +import kotlinx.collections.immutable.persistentListOf + +internal class SendConfirmStateConverter( + private val isTapHelpPreviewEnabledProvider: Provider, +) : Converter { + override fun convert(value: Unit): SendStates.SendState { + return SendStates.SendState( + isPrimaryButtonEnabled = true, + isSending = false, + isSuccess = false, + isSubtract = false, + transactionDate = 0L, + txUrl = "", + ignoreAmountReduce = false, + isFromConfirmation = true, + showTapHelp = isTapHelpPreviewEnabledProvider(), + notifications = persistentListOf(), + ) + } +} \ No newline at end of file diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendNavigationButtons.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendNavigationButtons.kt index 0344343e70..59028beb85 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendNavigationButtons.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendNavigationButtons.kt @@ -32,7 +32,8 @@ import com.tangem.features.send.impl.presentation.state.SendUiStateType @Composable internal fun SendNavigationButtons(uiState: SendUiState, currentState: SendUiCurrentScreen) { - val isSuccess = uiState.sendState.isSuccess + val sendState = uiState.sendState ?: return + val isSuccess = sendState.isSuccess val isSendingState = currentState.type == SendUiStateType.Send && !isSuccess val isSentState = currentState.type == SendUiStateType.Send && isSuccess Column( @@ -45,7 +46,7 @@ internal fun SendNavigationButtons(uiState: SendUiState, currentState: SendUiCur ) { SendingText(uiState = uiState, isVisible = isSendingState) SendDoneButtons( - txUrl = uiState.sendState.txUrl, + txUrl = sendState.txUrl, onExploreClick = uiState.clickIntents::onExploreClick, onShareClick = uiState.clickIntents::onShareClick, isVisible = isSentState, @@ -65,8 +66,9 @@ private fun SendNavigationButton( modifier: Modifier = Modifier, ) { val hapticFeedback = LocalHapticFeedback.current + val sendState = uiState.sendState ?: return val isEditingDisabled = uiState.isEditingDisabled - val isSuccess = uiState.sendState.isSuccess + val isSuccess = sendState.isSuccess val isFromConfirmation = currentState.isFromConfirmation val isCorrectScreen = currentState.type == SendUiStateType.Amount || currentState.type == SendUiStateType.Fee @@ -111,7 +113,7 @@ private fun SendNavigationButton( if (isSendingState) hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) buttonClick() }, - showProgress = uiState.sendState.isSending, + showProgress = sendState.isSending, modifier = Modifier.fillMaxWidth(), colors = TangemButtonsDefaults.primaryButtonColors, ) @@ -226,7 +228,7 @@ private fun isButtonEnabled(currentState: SendUiCurrentScreen, uiState: SendUiSt SendUiStateType.Amount -> uiState.amountState?.isPrimaryButtonEnabled ?: false SendUiStateType.Recipient -> uiState.recipientState?.isPrimaryButtonEnabled ?: false SendUiStateType.Fee -> uiState.feeState?.isPrimaryButtonEnabled ?: false - SendUiStateType.Send -> uiState.sendState.isPrimaryButtonEnabled + SendUiStateType.Send -> uiState.sendState?.isPrimaryButtonEnabled ?: false else -> true } } \ No newline at end of file diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendScreen.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendScreen.kt index 729c3c9a24..91c44b07ab 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendScreen.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendScreen.kt @@ -31,6 +31,7 @@ import kotlinx.coroutines.flow.StateFlow internal fun SendScreen(uiState: SendUiState, currentStateFlow: StateFlow) { val currentState = currentStateFlow.collectAsStateWithLifecycle() val snackbarHostState = remember { SnackbarHostState() } + val sendState = uiState.sendState ?: return BackHandler { uiState.clickIntents.onBackClick() } Column( modifier = Modifier @@ -44,7 +45,7 @@ internal fun SendScreen(uiState: SendUiState, currentStateFlow: StateFlow resourceReference(R.string.send_amount_label) SendUiStateType.Recipient -> resourceReference(R.string.send_recipient_label) SendUiStateType.Fee -> resourceReference(R.string.common_fee_selector_title) - SendUiStateType.Send -> if (!uiState.sendState.isSuccess) { + SendUiStateType.Send -> if (!sendState.isSuccess) { resourceReference(R.string.send_summary_title, wrappedList(uiState.cryptoCurrencySymbol)) } else { null 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 6cd08ba079..9dff71b1db 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 @@ -1,6 +1,7 @@ package com.tangem.features.send.impl.presentation.ui.send -import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.* +import androidx.compose.animation.core.MutableTransitionState import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.layout.* @@ -10,6 +11,8 @@ import androidx.compose.foundation.lazy.items import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -22,14 +25,16 @@ import com.tangem.features.send.impl.R import com.tangem.features.send.impl.presentation.state.SendNotification import com.tangem.features.send.impl.presentation.state.SendUiState import kotlinx.collections.immutable.ImmutableList +import kotlinx.coroutines.delay private const val TAP_HELP_KEY = "TAP_HELP_KEY" private const val BLOCKS_KEY = "BLOCKS_KEY" +private const val TAP_HELP_ANIMATION_DELAY = 500L @Suppress("LongMethod") @Composable internal fun SendContent(uiState: SendUiState) { - val sendState = uiState.sendState + val sendState = uiState.sendState ?: return LazyColumn( modifier = Modifier .fillMaxSize() @@ -37,7 +42,7 @@ internal fun SendContent(uiState: SendUiState) { verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12), ) { blocks(uiState) - tapHelp(isDisplay = sendState.notifications.isEmpty() && !uiState.sendState.isSuccess) + tapHelp(isDisplay = sendState.showTapHelp) notifications(sendState.notifications) } } @@ -46,7 +51,7 @@ private fun LazyListScope.blocks(uiState: SendUiState) { val amountState = uiState.amountState ?: return val recipientState = uiState.recipientState ?: return val feeState = uiState.feeState ?: return - val sendState = uiState.sendState + val sendState = uiState.sendState ?: return val isSuccess = sendState.isSuccess val timestamp = sendState.transactionDate @@ -84,8 +89,22 @@ private fun LazyListScope.blocks(uiState: SendUiState) { @OptIn(ExperimentalFoundationApi::class) private fun LazyListScope.tapHelp(isDisplay: Boolean, modifier: Modifier = Modifier) { - if (isDisplay) { - item(key = TAP_HELP_KEY) { + item(key = TAP_HELP_KEY) { + val animationState = remember { MutableTransitionState(false) } + + LaunchedEffect(key1 = isDisplay) { + delay(TAP_HELP_ANIMATION_DELAY) + animationState.targetState = isDisplay + } + + AnimatedVisibility( + visibleState = animationState, + label = "Tap Help Animation", + enter = slideInVertically( + initialOffsetY = { it / 2 }, + ).plus(fadeIn()), + exit = slideOutVertically().plus(fadeOut()), + ) { Column( horizontalAlignment = Alignment.CenterHorizontally, modifier = modifier 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 073fb98d89..588ea6b0a2 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 @@ -16,6 +16,8 @@ import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.qrscanning.usecases.ParseQrCodeUseCase import com.tangem.domain.redux.LegacyAction import com.tangem.domain.redux.ReduxStateHolder +import com.tangem.domain.settings.IsSendTapHelpEnabledUseCase +import com.tangem.domain.settings.NeverToShowTapHelpUseCase import com.tangem.domain.tokens.* import com.tangem.domain.tokens.error.CurrencyStatusError import com.tangem.domain.tokens.model.CryptoCurrency @@ -85,6 +87,8 @@ internal class SendViewModel @Inject constructor( private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase, private val analyticsEventHandler: AnalyticsEventHandler, private val parseQrCodeUseCase: ParseQrCodeUseCase, + private val isSendTapHelpEnabledUseCase: IsSendTapHelpEnabledUseCase, + private val neverToShowTapHelpUseCase: NeverToShowTapHelpUseCase, currencyChecksRepository: CurrencyChecksRepository, isFeeApproximateUseCase: IsFeeApproximateUseCase, getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase, @@ -120,6 +124,7 @@ internal class SendViewModel @Inject constructor( feeCryptoCurrencyStatusProvider = Provider { feeCryptoCurrencyStatus }, validateWalletMemoUseCase = validateWalletMemoUseCase, getExplorerTransactionUrlUseCase = getExplorerTransactionUrlUseCase, + isTapHelpPreviewEnabledProvider = Provider { isTapHelpPreviewEnabled }, ) private val amountStateFactory = AmountStateFactory( @@ -173,6 +178,7 @@ internal class SendViewModel @Inject constructor( private var userWallet: UserWallet by Delegates.notNull() private var isAmountSubtractAvailable: Boolean = false + private var isTapHelpPreviewEnabled: Boolean = false private var coinCryptoCurrencyStatus: CryptoCurrencyStatus by Delegates.notNull() private var cryptoCurrencyStatus: CryptoCurrencyStatus by Delegates.notNull() private var feeCryptoCurrencyStatus: CryptoCurrencyStatus by Delegates.notNull() @@ -192,6 +198,7 @@ internal class SendViewModel @Inject constructor( init { subscribeOnCurrencyStatusUpdates() subscribeOnBalanceHidden() + getTapHelpPreviewAvailability() } override fun onCreate(owner: LifecycleOwner) { @@ -286,6 +293,12 @@ internal class SendViewModel @Inject constructor( } } + private fun getTapHelpPreviewAvailability() { + viewModelScope.launch(dispatchers.main) { + isTapHelpPreviewEnabled = isSendTapHelpEnabledUseCase() + } + } + private fun getCoinCurrencyStatusUpdates(isSingleWalletWithToken: Boolean) = getNetworkCoinStatusUseCase( userWalletId = userWalletId, networkId = cryptoCurrency.network.id, @@ -344,7 +357,7 @@ internal class SendViewModel @Inject constructor( feeCryptoCurrencyStatus = feeCurrencyStatus when { - uiState.sendState.isSuccess -> { + uiState.sendState?.isSuccess == true -> { stateRouter.showSend() } transactionId != null && amount != null && destinationAddress != null -> { @@ -454,7 +467,7 @@ internal class SendViewModel @Inject constructor( // region screen state navigation override fun popBackStack() = stateRouter.popBackStack() - override fun onBackClick() = stateRouter.onBackClick(uiState.sendState.isSuccess) + override fun onBackClick() = stateRouter.onBackClick(isSuccess = uiState.sendState?.isSuccess == true) override fun onNextClick() { val currentState = stateRouter.currentState.value val isCurrentFee = currentState.type == SendUiStateType.Fee @@ -656,7 +669,7 @@ internal class SendViewModel @Inject constructor( // region send state clicks override fun onSendClick() { - val sendState = uiState.sendState + val sendState = uiState.sendState ?: return if (sendState.isSuccess) popBackStack() uiState = stateFactory.getSendingStateUpdate(isSending = true) @@ -670,16 +683,20 @@ internal class SendViewModel @Inject constructor( override fun showAmount() { stateRouter.showAmount(isFromConfirmation = true) + setNeverToShowTapHelp() analyticsEventHandler.send(SendAnalyticEvents.ScreenReopened(SendScreenSource.Amount)) } override fun showRecipient() { stateRouter.showRecipient(isFromConfirmation = true) + uiState = stateFactory.getHiddenTapHelpState() + setNeverToShowTapHelp() analyticsEventHandler.send(SendAnalyticEvents.ScreenReopened(SendScreenSource.Address)) } override fun showFee() { stateRouter.showFee(isFromConfirmation = true) + setNeverToShowTapHelp() analyticsEventHandler.send(SendAnalyticEvents.ScreenReopened(SendScreenSource.Fee)) } @@ -688,8 +705,9 @@ internal class SendViewModel @Inject constructor( } override fun onExploreClick() { + val sendState = uiState.sendState ?: return analyticsEventHandler.send(SendAnalyticEvents.ExploreButtonClicked) - innerRouter.openUrl(uiState.sendState.txUrl) + innerRouter.openUrl(sendState.txUrl) } override fun onShareClick() { @@ -772,8 +790,9 @@ internal class SendViewModel @Inject constructor( } private fun onCheckFeeUpdate() { - val isSuccess = uiState.sendState.isSuccess - val noErrorNotifications = uiState.sendState.notifications.none { it is SendNotification.Error } + val sendState = uiState.sendState ?: return + val isSuccess = sendState.isSuccess + val noErrorNotifications = sendState.notifications.none { it is SendNotification.Error } if (!isSuccess && noErrorNotifications) { viewModelScope.launch(dispatchers.main) { @@ -809,6 +828,13 @@ internal class SendViewModel @Inject constructor( } } } + + private fun setNeverToShowTapHelp() { + viewModelScope.launch(dispatchers.main) { + neverToShowTapHelpUseCase() + } + uiState = stateFactory.getHiddenTapHelpState() + } // endregion companion object {