diff --git a/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationId.kt b/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationId.kt
index 4b770200d0..2cc28a8b18 100644
--- a/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationId.kt
+++ b/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationId.kt
@@ -8,4 +8,5 @@ package com.tangem.common.ui.notifications
*/
enum class NotificationId(val key: String) {
SendViaSwapTokenSelectorNotification("SendViaSwapTokenSelectorNotificationKey"),
+ EnablePushesReminderNotification("EnablePushesReminderNotification"),
}
\ No newline at end of file
diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/showcase/Showcase.kt b/core/ui/src/main/java/com/tangem/core/ui/components/showcase/Showcase.kt
index 48f79e027f..e9347aa9b6 100644
--- a/core/ui/src/main/java/com/tangem/core/ui/components/showcase/Showcase.kt
+++ b/core/ui/src/main/java/com/tangem/core/ui/components/showcase/Showcase.kt
@@ -122,16 +122,18 @@ fun ShowcaseButtons(
private fun Showcase_Preview() {
TangemThemePreview {
Showcase(
- headerIconRes = R.drawable.ic_notifications_unread_24,
+ headerIconRes = R.drawable.ic_notification_56,
headerText = resourceReference(R.string.user_push_notification_agreement_header),
showcaseItems = persistentListOf(
ShowcaseItemModel(
- R.drawable.ic_rocket_launch_24,
- resourceReference(R.string.user_push_notification_agreement_argument_one),
+ iconRes = R.drawable.ic_rocket_launch_24,
+ title = resourceReference(R.string.user_push_notification_agreement_argument_one_title),
+ subTitle = resourceReference(R.string.user_push_notification_agreement_argument_one_subtitle),
),
ShowcaseItemModel(
- R.drawable.ic_storefront_24,
- resourceReference(R.string.user_push_notification_agreement_argument_two),
+ iconRes = R.drawable.ic_storefront_24,
+ title = resourceReference(R.string.user_push_notification_agreement_argument_two_title),
+ subTitle = resourceReference(R.string.user_push_notification_agreement_argument_two_subtitle),
),
),
primaryButton = ShowcaseButtonModel(resourceReference(R.string.common_allow), {}),
diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/showcase/ShowcaseContent.kt b/core/ui/src/main/java/com/tangem/core/ui/components/showcase/ShowcaseContent.kt
index 336172a208..c4ff5a39e2 100644
--- a/core/ui/src/main/java/com/tangem/core/ui/components/showcase/ShowcaseContent.kt
+++ b/core/ui/src/main/java/com/tangem/core/ui/components/showcase/ShowcaseContent.kt
@@ -63,7 +63,8 @@ fun ShowcaseContent(
repeat(showcaseItems.size) { index ->
ShowcaseItem(
iconRes = showcaseItems[index].iconRes,
- text = showcaseItems[index].text,
+ title = showcaseItems[index].title,
+ subtitle = showcaseItems[index].subTitle,
)
}
}
diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/showcase/ShowcaseItem.kt b/core/ui/src/main/java/com/tangem/core/ui/components/showcase/ShowcaseItem.kt
index 2f098c6720..4fe07dc38e 100644
--- a/core/ui/src/main/java/com/tangem/core/ui/components/showcase/ShowcaseItem.kt
+++ b/core/ui/src/main/java/com/tangem/core/ui/components/showcase/ShowcaseItem.kt
@@ -1,33 +1,47 @@
package com.tangem.core.ui.components.showcase
import androidx.annotation.DrawableRes
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.*
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.unit.dp
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
@Composable
-internal fun ShowcaseItem(@DrawableRes iconRes: Int, text: TextReference) {
- Row {
+internal fun ShowcaseItem(@DrawableRes iconRes: Int, title: TextReference, subtitle: TextReference) {
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
Icon(
painter = painterResource(id = iconRes),
contentDescription = null,
tint = TangemTheme.colors.icon.primary1,
)
- Text(
- text = text.resolveReference(),
- style = TangemTheme.typography.body2,
- color = TangemTheme.colors.text.secondary,
+ Column(
modifier = Modifier
.fillMaxWidth()
.padding(start = TangemTheme.dimens.spacing20),
- )
+ verticalArrangement = Arrangement.spacedBy(3.dp),
+ ) {
+ Text(
+ text = title.resolveReference(),
+ style = TangemTheme.typography.subtitle1,
+ color = TangemTheme.colors.text.primary1,
+ modifier = Modifier.fillMaxWidth(),
+ )
+
+ Text(
+ text = subtitle.resolveReference(),
+ style = TangemTheme.typography.body2,
+ color = TangemTheme.colors.text.secondary,
+ modifier = Modifier.fillMaxWidth(),
+ )
+ }
}
}
\ No newline at end of file
diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/showcase/model/ShowcaseItemModel.kt b/core/ui/src/main/java/com/tangem/core/ui/components/showcase/model/ShowcaseItemModel.kt
index f9865aab9e..cac2da63c0 100644
--- a/core/ui/src/main/java/com/tangem/core/ui/components/showcase/model/ShowcaseItemModel.kt
+++ b/core/ui/src/main/java/com/tangem/core/ui/components/showcase/model/ShowcaseItemModel.kt
@@ -5,5 +5,6 @@ import com.tangem.core.ui.extensions.TextReference
data class ShowcaseItemModel(
@DrawableRes val iconRes: Int,
- val text: TextReference,
+ val title: TextReference,
+ val subTitle: TextReference,
)
\ No newline at end of file
diff --git a/core/ui/src/main/res/drawable-hdpi/img_push_reminder.webp b/core/ui/src/main/res/drawable-hdpi/img_push_reminder.webp
new file mode 100644
index 0000000000..47f81ba8f4
Binary files /dev/null and b/core/ui/src/main/res/drawable-hdpi/img_push_reminder.webp differ
diff --git a/core/ui/src/main/res/drawable-mdpi/img_push_reminder.webp b/core/ui/src/main/res/drawable-mdpi/img_push_reminder.webp
new file mode 100644
index 0000000000..1c1df20a6f
Binary files /dev/null and b/core/ui/src/main/res/drawable-mdpi/img_push_reminder.webp differ
diff --git a/core/ui/src/main/res/drawable-xhdpi/img_push_reminder.webp b/core/ui/src/main/res/drawable-xhdpi/img_push_reminder.webp
new file mode 100644
index 0000000000..f30b2ac133
Binary files /dev/null and b/core/ui/src/main/res/drawable-xhdpi/img_push_reminder.webp differ
diff --git a/core/ui/src/main/res/drawable-xxhdpi/img_push_reminder.webp b/core/ui/src/main/res/drawable-xxhdpi/img_push_reminder.webp
new file mode 100644
index 0000000000..274b3305f6
Binary files /dev/null and b/core/ui/src/main/res/drawable-xxhdpi/img_push_reminder.webp differ
diff --git a/core/ui/src/main/res/drawable-xxxhdpi/img_push_reminder.webp b/core/ui/src/main/res/drawable-xxxhdpi/img_push_reminder.webp
new file mode 100644
index 0000000000..fe2d4ec006
Binary files /dev/null and b/core/ui/src/main/res/drawable-xxxhdpi/img_push_reminder.webp differ
diff --git a/core/ui/src/main/res/drawable/ic_notification_56.xml b/core/ui/src/main/res/drawable/ic_notification_56.xml
new file mode 100644
index 0000000000..69a6c39afb
--- /dev/null
+++ b/core/ui/src/main/res/drawable/ic_notification_56.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
diff --git a/core/ui/src/main/res/drawable/ic_notification_square_24.xml b/core/ui/src/main/res/drawable/ic_notification_square_24.xml
new file mode 100644
index 0000000000..0a8e4b2db8
--- /dev/null
+++ b/core/ui/src/main/res/drawable/ic_notification_square_24.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/core/ui/src/main/res/drawable/ic_stars_24.xml b/core/ui/src/main/res/drawable/ic_stars_24.xml
new file mode 100644
index 0000000000..41a21a8f25
--- /dev/null
+++ b/core/ui/src/main/res/drawable/ic_stars_24.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/data/notifications/src/main/java/com/tangem/data/notifications/DefaultNotificationsRepository.kt b/data/notifications/src/main/java/com/tangem/data/notifications/DefaultNotificationsRepository.kt
index d386676472..7a9b4c6cbe 100644
--- a/data/notifications/src/main/java/com/tangem/data/notifications/DefaultNotificationsRepository.kt
+++ b/data/notifications/src/main/java/com/tangem/data/notifications/DefaultNotificationsRepository.kt
@@ -2,11 +2,13 @@ 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.domain.notifications.repository.NotificationsRepository
+import kotlinx.coroutines.flow.Flow
import javax.inject.Inject
class DefaultNotificationsRepository @Inject constructor(
@@ -17,6 +19,10 @@ class DefaultNotificationsRepository @Inject constructor(
return appPreferencesStore.getSyncOrDefault(PreferencesKeys.getShouldShowNotificationKey(key), true)
}
+ override fun getShouldShowNotification(key: String): Flow {
+ return appPreferencesStore.get(PreferencesKeys.getShouldShowNotificationKey(key), true)
+ }
+
override suspend fun setShouldShowNotifications(key: String, value: Boolean) {
appPreferencesStore.store(PreferencesKeys.getShouldShowNotificationKey(key), value)
}
diff --git a/domain/notifications/src/main/java/com/tangem/domain/notifications/repository/NotificationsRepository.kt b/domain/notifications/src/main/java/com/tangem/domain/notifications/repository/NotificationsRepository.kt
index 0f1d3cb606..00d20b0f04 100644
--- a/domain/notifications/src/main/java/com/tangem/domain/notifications/repository/NotificationsRepository.kt
+++ b/domain/notifications/src/main/java/com/tangem/domain/notifications/repository/NotificationsRepository.kt
@@ -1,5 +1,7 @@
package com.tangem.domain.notifications.repository
+import kotlinx.coroutines.flow.Flow
+
/**
* Repository interface for managing local notification logic and state.
*
@@ -20,6 +22,13 @@ interface NotificationsRepository {
*/
suspend fun shouldShowNotification(key: String): Boolean
+ /**
+ * Subscribe on whether a notification with the given [key] should be shown to the user.
+ * @param key The unique identifier for the notification.
+ * @return true if the notification should be shown, false otherwise.
+ */
+ fun getShouldShowNotification(key: String): Flow
+
/**
* Sets whether a notification with the given [key] should be shown to the user.
* @param key The unique identifier for the notification.
diff --git a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/ui/PushNotificationsBottomSheet.kt b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/ui/PushNotificationsBottomSheet.kt
index 07090215d9..73d7418dfc 100644
--- a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/ui/PushNotificationsBottomSheet.kt
+++ b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/ui/PushNotificationsBottomSheet.kt
@@ -53,20 +53,18 @@ internal fun PushNotificationsContent(
Column(modifier = Modifier.background(TangemTheme.colors.background.primary)) {
ShowcaseContent(
- headerIconRes = R.drawable.ic_notifications_unread_24,
+ headerIconRes = R.drawable.ic_notification_56,
headerText = resourceReference(R.string.user_push_notification_agreement_header),
showcaseItems = persistentListOf(
ShowcaseItemModel(
- R.drawable.ic_rocket_launch_24,
- resourceReference(R.string.user_push_notification_agreement_argument_one),
+ iconRes = R.drawable.ic_notification_square_24,
+ title = resourceReference(R.string.user_push_notification_agreement_argument_one_title),
+ subTitle = resourceReference(R.string.user_push_notification_agreement_argument_one_subtitle),
),
ShowcaseItemModel(
- R.drawable.ic_storefront_24,
- resourceReference(R.string.user_push_notification_agreement_argument_two),
- ),
- ShowcaseItemModel(
- R.drawable.ic_notifications_24,
- resourceReference(R.string.user_push_notification_agreement_argument_three),
+ iconRes = R.drawable.ic_stars_24,
+ title = resourceReference(R.string.user_push_notification_agreement_argument_two_title),
+ subTitle = resourceReference(R.string.user_push_notification_agreement_argument_two_subtitle),
),
),
modifier = Modifier.padding(top = TangemTheme.dimens.spacing40),
diff --git a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/ui/PushNotificationsScreen.kt b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/ui/PushNotificationsScreen.kt
index 81ec2b2743..835e3c725a 100644
--- a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/ui/PushNotificationsScreen.kt
+++ b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/ui/PushNotificationsScreen.kt
@@ -26,20 +26,18 @@ internal fun PushNotificationsScreen(
)
Showcase(
- headerIconRes = R.drawable.ic_notifications_unread_24,
+ headerIconRes = R.drawable.ic_notification_56,
headerText = resourceReference(R.string.user_push_notification_agreement_header),
showcaseItems = persistentListOf(
ShowcaseItemModel(
- R.drawable.ic_rocket_launch_24,
- resourceReference(R.string.user_push_notification_agreement_argument_one),
+ iconRes = R.drawable.ic_notification_square_24,
+ title = resourceReference(R.string.user_push_notification_agreement_argument_one_title),
+ subTitle = resourceReference(R.string.user_push_notification_agreement_argument_one_subtitle),
),
ShowcaseItemModel(
- R.drawable.ic_storefront_24,
- resourceReference(R.string.user_push_notification_agreement_argument_two),
- ),
- ShowcaseItemModel(
- R.drawable.ic_notifications_24,
- resourceReference(R.string.user_push_notification_agreement_argument_three),
+ iconRes = R.drawable.ic_stars_24,
+ title = resourceReference(R.string.user_push_notification_agreement_argument_two_title),
+ subTitle = resourceReference(R.string.user_push_notification_agreement_argument_two_subtitle),
),
),
primaryButton = ShowcaseButtonModel(
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletWarningsClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletWarningsClickIntents.kt
index 55390d5b9e..88c0ad0300 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletWarningsClickIntents.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletWarningsClickIntents.kt
@@ -1,18 +1,19 @@
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
import com.tangem.common.routing.AppRouter
+import com.tangem.common.ui.notifications.NotificationId
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.navigation.url.UrlOpener
import com.tangem.core.ui.extensions.resourceReference
-import com.tangem.domain.wallets.usecase.DerivePublicKeysUseCase
import com.tangem.domain.card.SetCardWasScannedUseCase
-import com.tangem.domain.feedback.GetWalletMetaInfoUseCase
import com.tangem.domain.core.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.models.currency.CryptoCurrency
@@ -20,17 +21,21 @@ import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.models.wallet.requireColdWallet
import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
+import com.tangem.domain.notifications.SetShouldShowNotificationUseCase
+import com.tangem.domain.notifications.repository.NotificationsRepository
import com.tangem.domain.onramp.model.OnrampSource
import com.tangem.domain.promo.ShouldShowPromoWalletUseCase
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
@@ -54,6 +59,7 @@ import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
+@Suppress("TooManyFunctions")
internal interface WalletWarningsClickIntents {
fun onAddBackupCardClick()
@@ -93,9 +99,13 @@ internal interface WalletWarningsClickIntents {
fun onSeedPhraseSecondNotificationReject()
fun onFinishWalletActivationClick()
+
+ fun onAllowPermissions()
+
+ fun onDenyPermissions()
}
-@Suppress("LargeClass", "LongParameterList")
+@Suppress("LargeClass", "LongParameterList", "TooManyFunctions")
@ModelScoped
internal class WalletWarningsClickIntentsImplementor @Inject constructor(
private val stateHolder: WalletStateController,
@@ -121,6 +131,9 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
private val appRouter: AppRouter,
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
private val userWalletsListRepository: UserWalletsListRepository,
+ private val setShouldShowNotificationUseCase: SetShouldShowNotificationUseCase,
+ private val notificationsRepository: NotificationsRepository,
+ private val permissionRepository: PermissionRepository,
) : BaseWalletClickIntents(), WalletWarningsClickIntents {
override fun onAddBackupCardClick() {
@@ -422,6 +435,39 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
appRouter.push(AppRoute.WalletActivation(userWallet.walletId))
}
+ override fun onAllowPermissions() {
+ if (isNotificationsPermissionGranted()) {
+ updateSubscribeOnPushPermissions(true)
+ } else {
+ walletEventSender.send(
+ event = WalletEvent.RequestPushPermissions(
+ onAllow = { updateSubscribeOnPushPermissions(true) },
+ onDeny = { updateSubscribeOnPushPermissions(false) },
+ ),
+ )
+ }
+ }
+
+ override fun onDenyPermissions() = updateSubscribeOnPushPermissions(false)
+
+ private fun updateSubscribeOnPushPermissions(shouldAllow: Boolean) {
+ modelScope.launch {
+ notificationsRepository.setUserAllowToSubscribeOnPushNotifications(shouldAllow)
+ setShouldShowNotificationUseCase(
+ key = NotificationId.EnablePushesReminderNotification.key,
+ value = 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 fetchCryptoCurrencies(userWalletId: UserWalletId, currencies: List) {
coroutineScope {
listOf(
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt
index 9228228cd4..62e98b08ac 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt
@@ -4,7 +4,7 @@ import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.decompose.di.ModelScoped
-import com.tangem.domain.tokens.model.analytics.TokenSwapPromoAnalyticsEvent
+import com.tangem.domain.tokens.model.analytics.TokenSwapPromoAnalyticsEvent.*
import com.tangem.domain.tokens.model.analytics.TokenSwapPromoAnalyticsEvent.Program
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.MainScreen
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification
@@ -49,11 +49,11 @@ internal class WalletWarningsAnalyticsSender @Inject constructor(
is WalletNotification.RateApp -> MainScreen.HowDoYouLikeTangem
is WalletNotification.Critical.BackupError -> MainScreen.BackupError
is WalletNotification.NoteMigration -> MainScreen.NotePromo
- is WalletNotification.SwapPromo -> TokenSwapPromoAnalyticsEvent.NoticePromotionBanner(
+ is WalletNotification.SwapPromo -> NoticePromotionBanner(
source = AnalyticsParam.ScreensSources.Main,
program = Program.Empty, // Use it on new promo action
)
- is WalletNotification.Sepa -> TokenSwapPromoAnalyticsEvent.NoticePromotionBanner(
+ is WalletNotification.Sepa -> NoticePromotionBanner(
source = AnalyticsParam.ScreensSources.Main,
program = Program.Sepa,
)
@@ -70,6 +70,7 @@ internal class WalletWarningsAnalyticsSender @Inject constructor(
-> null
is WalletNotification.Critical.SeedPhraseNotification -> MainScreen.NoticeSeedPhraseSupport
is WalletNotification.Critical.SeedPhraseSecondNotification -> MainScreen.NoticeSeedPhraseSupportSecond
+ is WalletNotification.PushNotifications -> null
}
}
}
\ No newline at end of file
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt
index 8243fa0635..fa7d183dce 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt
@@ -3,6 +3,7 @@
package com.tangem.feature.wallet.presentation.wallet.domain
import arrow.core.getOrElse
+import com.tangem.common.ui.notifications.NotificationId
import com.tangem.common.ui.userwallet.ext.walletInterationIcon
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.ui.components.notifications.NotificationConfig.ButtonsState
@@ -18,6 +19,7 @@ import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.tokenlist.TokenList
import com.tangem.domain.models.wallet.UserWallet
+import com.tangem.domain.notifications.repository.NotificationsRepository
import com.tangem.domain.onramp.GetOnrampCountryUseCase
import com.tangem.domain.onramp.OnrampSepaAvailableUseCase
import com.tangem.domain.promo.ShouldShowPromoWalletUseCase
@@ -33,16 +35,16 @@ import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification
import com.tangem.features.yield.supply.api.YieldSupplyFeatureToggles
import com.tangem.lib.crypto.BlockchainUtils.isBitcoin
-import com.tangem.utils.coroutines.combine6
import com.tangem.utils.extensions.addIf
import com.tangem.utils.extensions.isPositive
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
import timber.log.Timber
import javax.inject.Inject
-@Suppress("LongParameterList")
+@Suppress("LongParameterList", "LargeClass")
@ModelScoped
internal class GetMultiWalletWarningsFactory @Inject constructor(
private val tokenListStore: MultiWalletTokenListStore,
@@ -55,20 +57,31 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
private val getCryptoCurrenciesUseCase: GetCryptoCurrenciesUseCase,
private val onrampSepaAvailableUseCase: OnrampSepaAvailableUseCase,
private val getOnrampCountryUseCase: GetOnrampCountryUseCase,
+ private val notificationsRepository: NotificationsRepository,
private val yieldSupplyFeatureToggles: YieldSupplyFeatureToggles,
) {
+ @Suppress("UNCHECKED_CAST", "MagicNumber")
fun create(userWallet: UserWallet, clickIntents: WalletClickIntents): Flow> {
val cardTypesResolver = (userWallet as? UserWallet.Cold)?.scanResponse?.cardTypesResolver
- return combine6(
- flow1 = tokenListStore.getOrThrow(userWallet.walletId),
- flow2 = isReadyToShowRateAppUseCase(),
- flow3 = isNeedToBackupUseCase(userWallet.walletId),
- flow4 = seedPhraseNotificationUseCase(userWalletId = userWallet.walletId),
- flow5 = shouldShowPromoWalletUseCase(userWalletId = userWallet.walletId, promoId = PromoId.Referral),
- flow6 = shouldShowPromoWalletUseCase(userWalletId = userWallet.walletId, promoId = PromoId.Sepa),
- ) { maybeTokenList, isReadyToShowRating, isNeedToBackup, seedPhraseIssueStatus, shouldShowReferralPromo, shouldShowSepaBanner ->
+ return combine(
+ tokenListStore.getOrThrow(userWallet.walletId),
+ isReadyToShowRateAppUseCase(),
+ isNeedToBackupUseCase(userWallet.walletId),
+ seedPhraseNotificationUseCase(userWalletId = userWallet.walletId),
+ shouldShowPromoWalletUseCase(userWalletId = userWallet.walletId, promoId = PromoId.Referral),
+ shouldShowPromoWalletUseCase(userWalletId = userWallet.walletId, promoId = PromoId.Sepa),
+ notificationsRepository.getShouldShowNotification(NotificationId.EnablePushesReminderNotification.key),
+ ) { array ->
+ val maybeTokenList = array[0] as Lce
+ val isReadyToShowRating = array[1] as Boolean
+ val isNeedToBackup = array[2] as Boolean
+ val seedPhraseIssueStatus = array[3] as SeedPhraseNotificationsStatus
+ val shouldShowReferralPromo = array[4] as Boolean
+ val shouldShowSepaBanner = array[5] as Boolean
+ val shouldShowEnablePushesReminderNotification = array[6] as Boolean
+
buildList {
addUsedOutdatedDataNotification(maybeTokenList)
@@ -84,6 +97,12 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
addWarningNotifications(cardTypesResolver, maybeTokenList, isNeedToBackup, clickIntents)
+ addPushReminderNotification(
+ clickIntents = clickIntents,
+ shouldShowPushReminderBanner = shouldShowEnablePushesReminderNotification &&
+ !notificationsRepository.isUserAllowToSubscribeOnPushNotifications(),
+ )
+
addYieldSupplyNotifications(maybeTokenList)
val hasCriticalOrWarning = any { notification ->
@@ -305,6 +324,19 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
)
}
+ private fun MutableList.addPushReminderNotification(
+ clickIntents: WalletClickIntents,
+ shouldShowPushReminderBanner: Boolean,
+ ) {
+ addIf(
+ element = WalletNotification.PushNotifications(
+ onCloseClick = clickIntents::onDenyPermissions,
+ onEnabledClick = clickIntents::onAllowPermissions,
+ ),
+ condition = shouldShowPushReminderBanner,
+ )
+ }
+
private fun Lce.hasUnreachableNetworks(): Boolean {
val tokenList = getOrNull(isPartialContentAccepted = false) ?: return false
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletEvent.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletEvent.kt
index 662fdca3de..b3f535d8a2 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletEvent.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletEvent.kt
@@ -30,4 +30,9 @@ internal sealed class WalletEvent {
RIGHT,
}
}
+
+ data class RequestPushPermissions(
+ val onAllow: () -> Unit,
+ val onDeny: () -> Unit,
+ ) : WalletEvent()
}
\ No newline at end of file
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt
index a9f3f1beb1..bc42b5dc0b 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt
@@ -315,4 +315,23 @@ sealed class WalletNotification(val config: NotificationConfig) {
iconSize = 54.dp,
),
)
+
+ data class PushNotifications(
+ val onCloseClick: () -> Unit,
+ val onEnabledClick: () -> Unit,
+ ) : WalletNotification(
+ config = NotificationConfig(
+ title = resourceReference(R.string.user_push_notification_banner_title),
+ subtitle = resourceReference(R.string.user_push_notification_banner_subtitle),
+ iconResId = R.drawable.img_push_reminder,
+ onCloseClick = onCloseClick,
+ buttonsState = NotificationConfig.ButtonsState.PairButtonsConfig(
+ primaryText = resourceReference(id = R.string.common_enable),
+ onPrimaryClick = onEnabledClick,
+ secondaryText = resourceReference(id = R.string.common_later),
+ onSecondaryClick = onCloseClick,
+ ),
+ iconSize = 54.dp,
+ ),
+ )
}
\ No newline at end of file
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletEventEffect.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletEventEffect.kt
index 6553a234d3..f1e5840afa 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletEventEffect.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletEventEffect.kt
@@ -3,19 +3,20 @@ package com.tangem.feature.wallet.presentation.wallet.ui
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.SnackbarHostState
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.runtime.*
import androidx.compose.ui.platform.LocalContext
import com.tangem.core.res.getStringSafe
import com.tangem.core.ui.event.EventEffect
import com.tangem.core.ui.event.StateEvent
import com.tangem.core.ui.extensions.resolveReference
+import com.tangem.core.ui.utils.requestPermission
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletAlertState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletEvent
import com.tangem.feature.wallet.presentation.wallet.ui.utils.ReviewManagerRequester
import com.tangem.feature.wallet.presentation.wallet.ui.utils.animateScrollByIndex
import com.tangem.feature.wallet.presentation.wallet.ui.utils.demonstrateScrolling
+import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION
@Composable
internal fun WalletEventEffect(
@@ -28,6 +29,13 @@ internal fun WalletEventEffect(
val coroutineScope = rememberCoroutineScope()
val context = LocalContext.current
val resources = LocalContext.current.resources
+
+ var showPermissionRequest by remember { mutableStateOf Unit, () -> Unit>?>(null) }
+ HandlePermissionRequest(
+ permissionRequestParams = showPermissionRequest,
+ onPermissionRequestResult = { showPermissionRequest = null },
+ )
+
EventEffect(
event = event,
onTrigger = { value ->
@@ -56,7 +64,34 @@ internal fun WalletEventEffect(
is WalletEvent.DemonstrateWalletsScrollPreview -> {
walletsListState.demonstrateScrolling(coroutineScope = coroutineScope, direction = value.direction)
}
+ is WalletEvent.RequestPushPermissions -> {
+ showPermissionRequest = value.onAllow to value.onDeny
+ }
}
},
)
+}
+
+@Composable
+private fun HandlePermissionRequest(
+ permissionRequestParams: Pair<() -> Unit, () -> Unit>?,
+ onPermissionRequestResult: () -> Unit,
+) {
+ val actualPermissionLauncher = permissionRequestParams?.let { (onAllowExternal, onDenyExternal) ->
+ requestPermission(
+ onAllow = {
+ onAllowExternal()
+ onPermissionRequestResult()
+ },
+ onDeny = {
+ onDenyExternal()
+ onPermissionRequestResult()
+ },
+ permission = PUSH_PERMISSION,
+ )
+ }
+
+ LaunchedEffect(permissionRequestParams) {
+ actualPermissionLauncher?.invoke()
+ }
}
\ No newline at end of file