Updated on 2026-08-14

This commit is contained in:
Tangem 2025-10-13 12:22:50 +02:00
parent 46650fac2c
commit 35253cded5
9 changed files with 79 additions and 69 deletions

View file

@ -471,4 +471,20 @@ internal object WalletsDomainModule {
yieldSupplyMarketRepository = yieldSupplyMarketRepository,
)
}
@Provides
@Singleton
fun provideGetWalletsForAutomaticallyPushEnablingUseCase(
userWalletsListManager: UserWalletsListManager,
userWalletsListRepository: UserWalletsListRepository,
hotWalletFeatureToggles: HotWalletFeatureToggles,
dispatcherProvider: CoroutineDispatcherProvider,
): GetWalletsForAutomaticallyPushEnablingUseCase {
return GetWalletsForAutomaticallyPushEnablingUseCase(
userWalletsListManager = userWalletsListManager,
userWalletsListRepository = userWalletsListRepository,
shouldUseNewListRepository = hotWalletFeatureToggles.isHotWalletEnabled,
dispatchers = dispatcherProvider,
)
}
}

View file

@ -2,11 +2,7 @@ package com.tangem.data.notifications
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.PreferencesKeys
import com.tangem.datasource.local.preferences.utils.get
import com.tangem.datasource.local.preferences.utils.getObjectMapSync
import com.tangem.datasource.local.preferences.utils.getSyncOrDefault
import com.tangem.datasource.local.preferences.utils.getSyncOrNull
import com.tangem.datasource.local.preferences.utils.store
import com.tangem.datasource.local.preferences.utils.*
import com.tangem.domain.notifications.repository.NotificationsRepository
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject

View file

@ -1,27 +1,34 @@
package com.tangem.domain.wallets.usecase
import com.tangem.domain.common.wallets.UserWalletsListRepository
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.wallets.legacy.UserWalletsListManager
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.withContext
import javax.inject.Inject
/**
* Use case for retrieving wallets where automatically enabling push notifications was not applied.
* * This use case filters out wallets that have already had push notifications automatically enabled
* from the complete list of user wallets, returning only those wallets that still need to have
* push notifications automatically enabled.
* * @property userWalletsListManager Manager for user wallets list operations
* @property userWalletsListManager Manager for user wallets list operations
* @property userWalletsListRepository Repository for user wallets list operations
* @property dispatchers Coroutine dispatcher provider for background operations
*/
class GetWalletsForAutomaticallyPushEnablingUseCase @Inject constructor(
class GetWalletsForAutomaticallyPushEnablingUseCase(
private val userWalletsListManager: UserWalletsListManager,
private val userWalletsListRepository: UserWalletsListRepository,
private val shouldUseNewListRepository: Boolean,
private val dispatchers: CoroutineDispatcherProvider,
) {
suspend operator fun invoke(walletsListWherePushWasEnabled: List<UserWalletId>): List<UserWalletId> =
withContext(dispatchers.default) {
val allLocalWallets = userWalletsListManager.userWalletsSync.map { it.walletId }
val allLocalWallets = if (shouldUseNewListRepository) {
userWalletsListRepository.userWalletsSync().map { it.walletId }
} else {
userWalletsListManager.userWalletsSync.map { it.walletId }
}
allLocalWallets - walletsListWherePushWasEnabled.toSet()
}
}

View file

@ -3,7 +3,7 @@ package com.tangem.features.pushnotifications.impl.model
internal interface PushNotificationsClickIntents {
fun onAllowClick()
fun onLaterClick(isFromBs: Boolean)
fun onLaterClick()
fun onAllowPermission()

View file

@ -49,18 +49,15 @@ internal class PushNotificationsModel @Inject constructor(
analyticHandler.send(PushNotificationAnalyticEvents.ButtonAllow(source))
}
override fun onLaterClick(isFromBs: Boolean) {
modelScope.launch {
notificationsRepository.setUserAllowToSubscribeOnPushNotifications(false)
}
override fun onLaterClick() {
analyticHandler.send(PushNotificationAnalyticEvents.ButtonLater(source))
modelScope.launch {
if (isFromBs) {
neverRequestPermissionUseCase(PUSH_PERMISSION)
}
neverRequestPermissionUseCase(PUSH_PERMISSION)
neverToInitiallyAskPermissionUseCase(PUSH_PERMISSION)
params.modelCallbacks.onDenySystemPermission()
if (!params.isBottomSheet) {
if (params.isBottomSheet) {
notificationsRepository.setUserAllowToSubscribeOnPushNotifications(false)
} else {
params.nextRoute?.let { appRouter.push(it) }
}
}

View file

@ -41,7 +41,7 @@ internal fun PushNotificationsBottomSheet(config: TangemBottomSheetConfig, conte
@Composable
internal fun PushNotificationsContent(
onAllowClick: () -> Unit,
onLaterClick: (isFromBs: Boolean) -> Unit,
onLaterClick: () -> Unit,
onAllowPermission: () -> Unit,
onDenyPermission: () -> Unit,
) {
@ -77,9 +77,7 @@ internal fun PushNotificationsContent(
requestPushPermission()
},
secondaryButtonText = resourceReference(R.string.common_later),
onSecondaryClick = {
onLaterClick(true)
},
onSecondaryClick = onLaterClick,
)
}
}

View file

@ -15,7 +15,7 @@ import kotlinx.collections.immutable.persistentListOf
@Composable
internal fun PushNotificationsScreen(
onAllowClick: () -> Unit,
onLaterClick: (isFromBs: Boolean) -> Unit,
onLaterClick: () -> Unit,
onAllowPermission: () -> Unit,
onDenyPermission: () -> Unit,
) {
@ -49,9 +49,7 @@ internal fun PushNotificationsScreen(
),
secondaryButton = ShowcaseButtonModel(
buttonText = resourceReference(R.string.common_later),
onClick = {
onLaterClick(false)
},
onClick = onLaterClick,
),
modifier = Modifier.systemBarsPadding(),
)

View file

@ -41,7 +41,6 @@ import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvid
import com.tangem.features.biometry.AskBiometryComponent
import com.tangem.features.hotwallet.HotWalletFeatureToggles
import com.tangem.features.pushnotifications.api.PushNotificationsModelCallbacks
import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION
import com.tangem.features.tangempay.TangemPayFeatureToggles
import com.tangem.features.wallet.deeplink.WalletDeepLinkActionListener
import com.tangem.features.yield.supply.api.YieldSupplyFeatureToggles
@ -76,7 +75,6 @@ internal class WalletModel @Inject constructor(
private val selectedWalletAnalyticsSender: SelectedWalletAnalyticsSender,
private val walletNameMigrationUseCase: WalletNameMigrationUseCase,
private val refreshMultiCurrencyWalletQuotesUseCase: RefreshMultiCurrencyWalletQuotesUseCase,
private val shouldAskPermissionUseCase: ShouldAskPermissionUseCase,
private val walletImageResolver: WalletImageResolver,
private val tokenListStore: MultiWalletTokenListStore,
private val onrampStatusFactory: OnrampStatusFactory,
@ -238,19 +236,16 @@ internal class WalletModel @Inject constructor(
private fun subscribeOnPushNotificationsPermission() {
modelScope.launch {
val shouldAskPermission = shouldAskPermissionUseCase(PUSH_PERMISSION)
val afterUpdate = notificationsRepository.shouldShowSubscribeOnNotificationsAfterUpdate()
val shouldShow = notificationsRepository.shouldShowSubscribeOnNotificationsAfterUpdate()
val isBiometricsEnabled = shouldSaveUserWalletsSyncUseCase()
val isHuaweiDevice = getIsHuaweiDeviceWithoutGoogleServicesUseCase()
val shouldShowBottomSheet = shouldAskPermission || afterUpdate
Timber.d(
"push BS afterUpdate: $afterUpdate," +
"shouldAskPermission $shouldAskPermission," +
"push BS afterUpdate: $shouldShow," +
"isBiometricsEnabled $isBiometricsEnabled," +
"isHuaweiDevice $isHuaweiDevice",
)
if (!isBiometricsEnabled) return@launch
if (!shouldShowBottomSheet) return@launch
if (!shouldShow) return@launch
delay(timeMillis = 1_800)

View file

@ -1,6 +1,5 @@
package com.tangem.feature.wallet.child.wallet.model.intents
import android.os.Build
import arrow.core.getOrElse
import com.tangem.common.TangemBlogUrlBuilder
import com.tangem.common.routing.AppRoute.*
@ -32,16 +31,12 @@ import com.tangem.domain.promo.models.PromoId
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
import com.tangem.domain.settings.NeverToSuggestRateAppUseCase
import com.tangem.domain.settings.RemindToRateAppLaterUseCase
import com.tangem.domain.settings.repositories.PermissionRepository
import com.tangem.domain.staking.StakingIdFactory
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
import com.tangem.domain.tokens.model.analytics.TokenSwapPromoAnalyticsEvent
import com.tangem.domain.wallets.legacy.UserWalletsListManager.Lockable.UnlockType
import com.tangem.domain.wallets.models.UnlockWalletsError
import com.tangem.domain.wallets.usecase.DerivePublicKeysUseCase
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.domain.wallets.usecase.SeedPhraseNotificationUseCase
import com.tangem.domain.wallets.usecase.UnlockWalletsUseCase
import com.tangem.domain.wallets.usecase.*
import com.tangem.feature.wallet.child.wallet.model.WalletActivationBannerType
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
@ -139,8 +134,9 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
private val userWalletsListRepository: UserWalletsListRepository,
private val setShouldShowNotificationUseCase: SetShouldShowNotificationUseCase,
private val notificationsRepository: NotificationsRepository,
private val permissionRepository: PermissionRepository,
private val messageSender: UiMessageSender,
private val setNotificationsEnabledUseCase: SetNotificationsEnabledUseCase,
private val getWalletsListForEnablingUseCase: GetWalletsForAutomaticallyPushEnablingUseCase,
) : BaseWalletClickIntents(), WalletWarningsClickIntents {
private val finalizeWalletSetupAlertBS
@ -477,49 +473,42 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
override fun onAllowPermissions() {
analyticsEventHandler.send(WalletScreenAnalyticsEvent.PushBannerPromo.ButtonAllowPush)
if (isNotificationsPermissionGranted()) {
updateSubscribeOnPushPermissions(true)
} else {
walletEventSender.send(
event = WalletEvent.RequestPushPermissions(
onAllow = {
walletEventSender.send(
event = WalletEvent.RequestPushPermissions(
onAllow = {
modelScope.launch {
updateSubscribeOnPushPermissions(true)
analyticsEventHandler.send(
PushNotificationAnalyticEvents.PermissionStatus(isAllowed = true),
)
},
onDeny = {
enableNotificationsIfNeeded()
}
},
onDeny = {
modelScope.launch {
updateSubscribeOnPushPermissions(false)
analyticsEventHandler.send(
PushNotificationAnalyticEvents.PermissionStatus(isAllowed = false),
)
},
),
)
}
}
},
),
)
}
override fun onDenyPermissions() {
analyticsEventHandler.send(WalletScreenAnalyticsEvent.PushBannerPromo.ButtonLaterPush)
updateSubscribeOnPushPermissions(false)
}
private fun updateSubscribeOnPushPermissions(shouldAllow: Boolean) {
modelScope.launch {
notificationsRepository.setUserAllowToSubscribeOnPushNotifications(shouldAllow)
setShouldShowNotificationUseCase(
key = NotificationId.EnablePushesReminderNotification.key,
value = false,
)
analyticsEventHandler.send(WalletScreenAnalyticsEvent.PushBannerPromo.ButtonLaterPush)
updateSubscribeOnPushPermissions(false)
}
}
private fun isNotificationsPermissionGranted(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
permissionRepository.hasRuntimePermission(android.Manifest.permission.POST_NOTIFICATIONS)
} else {
true
}
private suspend fun updateSubscribeOnPushPermissions(shouldAllow: Boolean) {
notificationsRepository.setUserAllowToSubscribeOnPushNotifications(shouldAllow)
setShouldShowNotificationUseCase(
key = NotificationId.EnablePushesReminderNotification.key,
value = false,
)
}
private suspend fun fetchCryptoCurrencies(userWalletId: UserWalletId, currencies: List<CryptoCurrency>) {
@ -572,4 +561,18 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
null
}
}
private suspend fun enableNotificationsIfNeeded() {
val alreadyEnabledWallets = notificationsRepository.getWalletAutomaticallyEnabledList().map {
UserWalletId(it)
}
val walletsListWhichShouldBeEnabled = getWalletsListForEnablingUseCase(alreadyEnabledWallets)
walletsListWhichShouldBeEnabled.forEach { userWalletId ->
setNotificationsEnabledUseCase(userWalletId, true).onRight {
notificationsRepository.setNotificationsWasEnabledAutomatically(userWalletId.stringValue)
}.onLeft {
Timber.e(it)
}
}
}
}