Updated on 2026-08-14

This commit is contained in:
Tangem 2025-09-03 11:46:59 +05:00
parent 7f950708d7
commit f80ce6c175
7 changed files with 60 additions and 28 deletions

View file

@ -5,12 +5,14 @@ import com.tangem.datasource.api.tangemTech.models.GeoResponse
import com.tangem.datasource.local.logs.AppLogsStore import com.tangem.datasource.local.logs.AppLogsStore
import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.PreferencesKeys import com.tangem.datasource.local.preferences.PreferencesKeys
import com.tangem.datasource.local.preferences.utils.get
import com.tangem.datasource.local.preferences.utils.getSyncOrDefault import com.tangem.datasource.local.preferences.utils.getSyncOrDefault
import com.tangem.datasource.local.preferences.utils.store import com.tangem.datasource.local.preferences.utils.store
import com.tangem.domain.settings.repositories.SettingsRepository import com.tangem.domain.settings.repositories.SettingsRepository
import com.tangem.domain.settings.usercountry.models.GB_COUNTRY import com.tangem.domain.settings.usercountry.models.GB_COUNTRY
import com.tangem.domain.settings.usercountry.models.UserCountry import com.tangem.domain.settings.usercountry.models.UserCountry
import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ -56,7 +58,14 @@ internal class DefaultSettingsRepository(
appLogsStore.deleteDeprecatedLogs(maxSize) appLogsStore.deleteDeprecatedLogs(maxSize)
} }
override suspend fun isSendTapHelpPreviewEnabled(): Boolean { override fun isSendTapHelpPreviewEnabled(): Flow<Boolean> {
return appPreferencesStore.get(
key = PreferencesKeys.SEND_TAP_HELP_PREVIEW_KEY,
default = true,
)
}
override suspend fun isSendTapHelpPreviewEnabledSync(): Boolean {
return appPreferencesStore.getSyncOrDefault( return appPreferencesStore.getSyncOrDefault(
key = PreferencesKeys.SEND_TAP_HELP_PREVIEW_KEY, key = PreferencesKeys.SEND_TAP_HELP_PREVIEW_KEY,
default = true, default = true,

View file

@ -10,5 +10,7 @@ import com.tangem.domain.settings.repositories.SettingsRepository
*/ */
class IsSendTapHelpEnabledUseCase(private val settingsRepository: SettingsRepository) { class IsSendTapHelpEnabledUseCase(private val settingsRepository: SettingsRepository) {
suspend operator fun invoke() = Either.catch { settingsRepository.isSendTapHelpPreviewEnabled() } operator fun invoke() = Either.catch { settingsRepository.isSendTapHelpPreviewEnabled() }
suspend fun invokeSync() = Either.catch { settingsRepository.isSendTapHelpPreviewEnabledSync() }
} }

View file

@ -1,6 +1,7 @@
package com.tangem.domain.settings.repositories package com.tangem.domain.settings.repositories
import com.tangem.domain.settings.usercountry.models.UserCountry import com.tangem.domain.settings.usercountry.models.UserCountry
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
@Suppress("TooManyFunctions") @Suppress("TooManyFunctions")
@ -16,7 +17,9 @@ interface SettingsRepository {
fun deleteDeprecatedLogs(maxSize: Int) fun deleteDeprecatedLogs(maxSize: Int)
suspend fun isSendTapHelpPreviewEnabled(): Boolean fun isSendTapHelpPreviewEnabled(): Flow<Boolean>
suspend fun isSendTapHelpPreviewEnabledSync(): Boolean
suspend fun setSendTapHelpPreviewAvailability(isEnabled: Boolean) suspend fun setSendTapHelpPreviewAvailability(isEnabled: Boolean)

View file

@ -13,6 +13,7 @@ import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.core.navigation.url.UrlOpener import com.tangem.core.navigation.url.UrlOpener
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.settings.NeverShowTapHelpUseCase
import com.tangem.domain.transaction.usecase.IsFeeApproximateUseCase import com.tangem.domain.transaction.usecase.IsFeeApproximateUseCase
import com.tangem.features.send.v2.api.analytics.CommonSendAnalyticEvents import com.tangem.features.send.v2.api.analytics.CommonSendAnalyticEvents
import com.tangem.features.send.v2.api.analytics.CommonSendAnalyticEvents.NonceInserted import com.tangem.features.send.v2.api.analytics.CommonSendAnalyticEvents.NonceInserted
@ -46,6 +47,7 @@ internal class FeeSelectorModel @Inject constructor(
private val urlOpener: UrlOpener, private val urlOpener: UrlOpener,
private val isFeeApproximateUseCase: IsFeeApproximateUseCase, private val isFeeApproximateUseCase: IsFeeApproximateUseCase,
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
private val neverShowTapHelpUseCase: NeverShowTapHelpUseCase,
private val feeSelectorReloadListener: FeeSelectorReloadListener, private val feeSelectorReloadListener: FeeSelectorReloadListener,
private val feeSelectorCheckReloadListener: FeeSelectorCheckReloadListener, private val feeSelectorCheckReloadListener: FeeSelectorCheckReloadListener,
private val feeSelectorCheckReloadTrigger: FeeSelectorCheckReloadTrigger, private val feeSelectorCheckReloadTrigger: FeeSelectorCheckReloadTrigger,
@ -185,7 +187,10 @@ internal class FeeSelectorModel @Inject constructor(
source = SendScreenSource.Fee, source = SendScreenSource.Fee,
), ),
) )
feeSelectorBottomSheet.activate(Unit) modelScope.launch {
neverShowTapHelpUseCase()
feeSelectorBottomSheet.activate(Unit)
}
} }
private fun subscribeOnFeeReloadTriggerUpdates() { private fun subscribeOnFeeReloadTriggerUpdates() {

View file

@ -20,6 +20,7 @@ import com.tangem.core.navigation.url.UrlOpener
import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.extensions.wrappedList import com.tangem.core.ui.extensions.wrappedList
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
import com.tangem.domain.feedback.GetCardInfoUseCase import com.tangem.domain.feedback.GetCardInfoUseCase
import com.tangem.domain.feedback.SaveBlockchainErrorUseCase import com.tangem.domain.feedback.SaveBlockchainErrorUseCase
import com.tangem.domain.feedback.SendFeedbackEmailUseCase import com.tangem.domain.feedback.SendFeedbackEmailUseCase
@ -28,7 +29,6 @@ import com.tangem.domain.feedback.models.FeedbackEmailType
import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.requireColdWallet import com.tangem.domain.models.wallet.requireColdWallet
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
import com.tangem.domain.settings.IsSendTapHelpEnabledUseCase import com.tangem.domain.settings.IsSendTapHelpEnabledUseCase
import com.tangem.domain.settings.NeverShowTapHelpUseCase import com.tangem.domain.settings.NeverShowTapHelpUseCase
import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase
@ -170,6 +170,7 @@ internal class SendConfirmModel @Inject constructor(
subscribeOnCheckFeeResultUpdates() subscribeOnCheckFeeResultUpdates()
initialState() initialState()
subscribeOnBalanceHidden() subscribeOnBalanceHidden()
subscribeOnTapHelpUpdates()
} }
fun updateState(state: SendUM) { fun updateState(state: SendUM) {
@ -234,10 +235,6 @@ internal class SendConfirmModel @Inject constructor(
override fun showEditDestination() { override fun showEditDestination() {
modelScope.launch { modelScope.launch {
neverShowTapHelpUseCase() neverShowTapHelpUseCase()
_uiState.update {
val confirmUM = it.confirmUM as? ConfirmUM.Content
it.copy(confirmUM = confirmUM?.copy(showTapHelp = false) ?: it.confirmUM)
}
analyticsEventHandler.send( analyticsEventHandler.send(
CommonSendAnalyticEvents.ScreenReopened( CommonSendAnalyticEvents.ScreenReopened(
categoryName = analyticsCategoryName, categoryName = analyticsCategoryName,
@ -251,10 +248,6 @@ internal class SendConfirmModel @Inject constructor(
override fun showEditAmount() { override fun showEditAmount() {
modelScope.launch { modelScope.launch {
neverShowTapHelpUseCase() neverShowTapHelpUseCase()
_uiState.update {
val confirmUM = it.confirmUM as? ConfirmUM.Content
it.copy(confirmUM = confirmUM?.copy(showTapHelp = false) ?: it.confirmUM)
}
analyticsEventHandler.send( analyticsEventHandler.send(
CommonSendAnalyticEvents.ScreenReopened( CommonSendAnalyticEvents.ScreenReopened(
categoryName = analyticsCategoryName, categoryName = analyticsCategoryName,
@ -268,10 +261,6 @@ internal class SendConfirmModel @Inject constructor(
override fun showEditFee() { override fun showEditFee() {
modelScope.launch { modelScope.launch {
neverShowTapHelpUseCase() neverShowTapHelpUseCase()
_uiState.update {
val confirmUM = it.confirmUM as? ConfirmUM.Content
it.copy(confirmUM = confirmUM?.copy(showTapHelp = false) ?: it.confirmUM)
}
analyticsEventHandler.send( analyticsEventHandler.send(
CommonSendAnalyticEvents.ScreenReopened( CommonSendAnalyticEvents.ScreenReopened(
categoryName = analyticsCategoryName, categoryName = analyticsCategoryName,
@ -356,7 +345,7 @@ internal class SendConfirmModel @Inject constructor(
val confirmUM = uiState.value.confirmUM val confirmUM = uiState.value.confirmUM
modelScope.launch { modelScope.launch {
val isShowTapHelp = isSendTapHelpEnabledUseCase().getOrElse { false } val isShowTapHelp = isSendTapHelpEnabledUseCase.invokeSync().getOrElse { false }
if (confirmUM is ConfirmUM.Empty) { if (confirmUM is ConfirmUM.Empty) {
_uiState.update { _uiState.update {
it.copy( it.copy(
@ -372,6 +361,16 @@ internal class SendConfirmModel @Inject constructor(
} }
} }
private fun subscribeOnTapHelpUpdates() {
isSendTapHelpEnabledUseCase().getOrNull()
?.onEach { showTapHelp ->
_uiState.update {
val confirmUM = it.confirmUM as? ConfirmUM.Content
it.copy(confirmUM = confirmUM?.copy(showTapHelp = showTapHelp) ?: it.confirmUM)
}
}?.launchIn(modelScope)
}
private fun subscribeOnNotificationsUpdateTrigger() { private fun subscribeOnNotificationsUpdateTrigger() {
notificationsUpdateListener.hasErrorFlow notificationsUpdateListener.hasErrorFlow
.onEach { hasError -> .onEach { hasError ->

View file

@ -138,6 +138,7 @@ internal class NFTSendConfirmModel @Inject constructor(
configConfirmNavigation() configConfirmNavigation()
subscribeOnNotificationsUpdateTrigger() subscribeOnNotificationsUpdateTrigger()
subscribeOnCheckFeeResultUpdates() subscribeOnCheckFeeResultUpdates()
subscribeOnTapHelpUpdates()
initialState() initialState()
} }
@ -178,10 +179,6 @@ internal class NFTSendConfirmModel @Inject constructor(
override fun showEditDestination() { override fun showEditDestination() {
modelScope.launch { modelScope.launch {
neverShowTapHelpUseCase() neverShowTapHelpUseCase()
_uiState.update {
val confirmUM = it.confirmUM as? ConfirmUM.Content
it.copy(confirmUM = confirmUM?.copy(showTapHelp = false) ?: it.confirmUM)
}
analyticsEventHandler.send( analyticsEventHandler.send(
CommonSendAnalyticEvents.ScreenReopened( CommonSendAnalyticEvents.ScreenReopened(
categoryName = analyticsCategoryName, categoryName = analyticsCategoryName,
@ -195,10 +192,6 @@ internal class NFTSendConfirmModel @Inject constructor(
override fun showEditFee() { override fun showEditFee() {
modelScope.launch { modelScope.launch {
neverShowTapHelpUseCase() neverShowTapHelpUseCase()
_uiState.update {
val confirmUM = it.confirmUM as? ConfirmUM.Content
it.copy(confirmUM = confirmUM?.copy(showTapHelp = false) ?: it.confirmUM)
}
analyticsEventHandler.send( analyticsEventHandler.send(
CommonSendAnalyticEvents.ScreenReopened( CommonSendAnalyticEvents.ScreenReopened(
categoryName = analyticsCategoryName, categoryName = analyticsCategoryName,
@ -270,7 +263,7 @@ internal class NFTSendConfirmModel @Inject constructor(
} }
modelScope.launch { modelScope.launch {
val isShowTapHelp = isSendTapHelpEnabledUseCase().getOrElse { false } val isShowTapHelp = isSendTapHelpEnabledUseCase.invokeSync().getOrElse { false }
if (confirmUM is ConfirmUM.Empty || isEmptyFee) { if (confirmUM is ConfirmUM.Empty || isEmptyFee) {
_uiState.update { _uiState.update {
it.copy( it.copy(
@ -285,6 +278,16 @@ internal class NFTSendConfirmModel @Inject constructor(
} }
} }
private fun subscribeOnTapHelpUpdates() {
isSendTapHelpEnabledUseCase().getOrNull()
?.onEach { showTapHelp ->
_uiState.update {
val confirmUM = it.confirmUM as? ConfirmUM.Content
it.copy(confirmUM = confirmUM?.copy(showTapHelp = showTapHelp) ?: it.confirmUM)
}
}?.launchIn(modelScope)
}
private fun subscribeOnNotificationsUpdateTrigger() { private fun subscribeOnNotificationsUpdateTrigger() {
notificationsUpdateListener.hasErrorFlow notificationsUpdateListener.hasErrorFlow
.onEach { hasError -> .onEach { hasError ->

View file

@ -142,6 +142,7 @@ internal class SendWithSwapConfirmModel @Inject constructor(
configConfirmNavigation() configConfirmNavigation()
initialState() initialState()
subscribeOnNotificationUpdates() subscribeOnNotificationUpdates()
subscribeOnTapHelpUpdates()
} }
override fun onFeeResult(feeSelectorUM: FeeSelectorUM) { override fun onFeeResult(feeSelectorUM: FeeSelectorUM) {
@ -313,7 +314,7 @@ internal class SendWithSwapConfirmModel @Inject constructor(
val confirmUM = uiState.value.confirmUM val confirmUM = uiState.value.confirmUM
modelScope.launch { modelScope.launch {
val isShowTapHelp = isSendTapHelpEnabledUseCase().getOrElse { false } val isShowTapHelp = isSendTapHelpEnabledUseCase.invokeSync().getOrElse { false }
if (confirmUM is ConfirmUM.Empty) { if (confirmUM is ConfirmUM.Empty) {
uiState.update { uiState.update {
it.copy( it.copy(
@ -327,6 +328,16 @@ internal class SendWithSwapConfirmModel @Inject constructor(
} }
} }
private fun subscribeOnTapHelpUpdates() {
isSendTapHelpEnabledUseCase().getOrNull()
?.onEach { showTapHelp ->
uiState.update {
val confirmUM = it.confirmUM as? ConfirmUM.Content
it.copy(confirmUM = confirmUM?.copy(showTapHelp = showTapHelp) ?: it.confirmUM)
}
}?.launchIn(modelScope)
}
private fun updateConfirmNotifications() { private fun updateConfirmNotifications() {
modelScope.launch { modelScope.launch {
sendNotificationsUpdateTrigger.triggerUpdate( sendNotificationsUpdateTrigger.triggerUpdate(