diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml
index 51b0328c1d..0fe3d3cfba 100644
--- a/core/res/src/main/res/values-de/strings.xml
+++ b/core/res/src/main/res/values-de/strings.xml
@@ -562,6 +562,10 @@
Eigenschaften
Unbetitelte Sammlung
%1$d NFTs in der %2$d Sammlung
+
+
+ - %1$d NFTs in der %2$d Sammlung
+
Tippe hier, um das erste NFT zu erhalten
NFT-Sammlungen
Die Daten konnten nicht geladen werden
diff --git a/core/res/src/main/res/values-fr/strings.xml b/core/res/src/main/res/values-fr/strings.xml
index 6758225e1c..b7102eaf1b 100644
--- a/core/res/src/main/res/values-fr/strings.xml
+++ b/core/res/src/main/res/values-fr/strings.xml
@@ -520,6 +520,10 @@
Certaines données peuvent ne pas se charger
Problèmes de chargement temporaires
%1$d NFT dans la collection %2$d
+
+
+ - %1$d NFT dans la collection %2$d
+
Appuyez ici pour recevoir le premier NFT
Collections NFT
Impossible de charger les données
diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml
index 10a640eece..3c9bb51610 100644
--- a/core/res/src/main/res/values-ja/strings.xml
+++ b/core/res/src/main/res/values-ja/strings.xml
@@ -560,6 +560,9 @@
特徴
無題のコレクション
%2$dコレクションの%1$dNFT
+
+ - %2$dコレクションの%1$dNFT
+
ここをタップして最初のNFTを受け取ります
NFTコレクション
データを読み込めません
@@ -1085,6 +1088,7 @@
%sを使用するか、カード / リングをスキャンしてウォレットにアクセスしてください
接続に失敗しました:このdAppは、サポートされていないWallet Connectバージョン1.0を使用しています。正常に接続するには、dAppがWallet Connectバージョン2.0をサポートしていることを確認してください。
最新の機能とニュースをお届けします
+ 受信取引の通知を受け取る
新しいプロモーション情報をいち早く入手しましょう
プッシュ通知を使用しますか?
新しいウォレットを追加
diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml
index 45c1636058..2992c78399 100644
--- a/core/res/src/main/res/values-ru/strings.xml
+++ b/core/res/src/main/res/values-ru/strings.xml
@@ -569,6 +569,12 @@
Отправить NFT
Черты
%1$d NFTs в %2$d коллекциях
+
+
+
+
+ - %1$d NFTs в %2$d коллекциях
+
Нажмите здесь, чтобы получить первую NFT
NFT коллекции
Невозможно загрузить данные
diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml
index c0aae1035e..232815179b 100644
--- a/core/res/src/main/res/values/strings.xml
+++ b/core/res/src/main/res/values/strings.xml
@@ -1,5 +1,6 @@
+ Required minimum XLM reserve %1$s
Can’t find your token? Go to the Market section on the main page and add it to your portfolio for purchase
Can’t find your token? Go to the Market section on the main page and add it to your portfolio for selling.
Sell
@@ -271,6 +272,7 @@
%s hashes
Device ID
Contact support
+ Open support chat
Link More Cards
App Currency
Flip-to-Hide Balances
@@ -569,6 +571,10 @@
Traits
Untitled collection
%1$d NFTs in %2$d collections
+
+
+ - %1$d NFTs in %2$d collections
+
Tap here to receive first NFT
NFT collections
Unable to load the data
@@ -1077,6 +1083,8 @@
from: %s
to: %s
validator: %s
+ Notifications are enabled but won\'t work until you allow notifications in your device settings.
+ Transaction Notifications
Minimum %s
The minimum transaction amount is %1$s.
Tron network fees for popular tokens can be higher. Staking TRX may help reduce transaction costs.
@@ -1293,6 +1301,7 @@
Your review keeps us motivated to make Tangem Wallet even better
Enjoying Tangem?
You must associate your token before receiving tokens
+ You must open trustline before receiving tokens
Network rent fee required
Action required
Did you contact support via the app within 7 days of creating your wallet? If yes, or if you\'re unsure, click \'Yes\' and follow the instructions.
@@ -1308,6 +1317,9 @@
Swipe down to refresh or try again later.
Some networks are unreachable
Some token balances could not be updated
+ Open trustline
+ Open trustline subtiile
+ Open trustline title
This is a Testnet card. It cannot process transactions and should only be used for testing and development purposes.
For testing purposes only
Balance may be outdated. Refresh the page.
diff --git a/data/settings/src/main/java/com/tangem/data/settings/DefaultPermissionRepository.kt b/data/settings/src/main/java/com/tangem/data/settings/DefaultPermissionRepository.kt
index e2528964fe..57c4716bab 100644
--- a/data/settings/src/main/java/com/tangem/data/settings/DefaultPermissionRepository.kt
+++ b/data/settings/src/main/java/com/tangem/data/settings/DefaultPermissionRepository.kt
@@ -1,5 +1,8 @@
package com.tangem.data.settings
+import android.content.Context
+import android.content.pm.PackageManager
+import androidx.core.content.ContextCompat
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.PreferencesKeys.getShouldShowInitialPermissionScreen
import com.tangem.datasource.local.preferences.PreferencesKeys.getShouldShowPermission
@@ -9,6 +12,7 @@ import com.tangem.domain.settings.repositories.PermissionRepository
internal class DefaultPermissionRepository(
private val appPreferencesStore: AppPreferencesStore,
+ private val context: Context,
) : PermissionRepository {
override suspend fun shouldInitiallyShowPermissionScreen(permission: String): Boolean {
@@ -32,4 +36,12 @@ internal class DefaultPermissionRepository(
override suspend fun neverAskPermission(permission: String) {
appPreferencesStore.store(key = getShouldShowPermission(permission), value = false)
}
+
+ override fun hasRuntimePermission(permission: String): Boolean {
+ return context.isPermissionGranted(permission)
+ }
+
+ private fun Context.isPermissionGranted(permission: String): Boolean {
+ return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
+ }
}
\ No newline at end of file
diff --git a/data/settings/src/main/java/com/tangem/data/settings/di/SettingsDataModule.kt b/data/settings/src/main/java/com/tangem/data/settings/di/SettingsDataModule.kt
index 4f04ee135b..8728678fe4 100644
--- a/data/settings/src/main/java/com/tangem/data/settings/di/SettingsDataModule.kt
+++ b/data/settings/src/main/java/com/tangem/data/settings/di/SettingsDataModule.kt
@@ -1,5 +1,6 @@
package com.tangem.data.settings.di
+import android.content.Context
import com.tangem.data.settings.DefaultAppRatingRepository
import com.tangem.data.settings.DefaultPermissionRepository
import com.tangem.data.settings.DefaultSettingsRepository
@@ -13,6 +14,7 @@ import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
+import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@@ -44,7 +46,13 @@ internal object SettingsDataModule {
@Provides
@Singleton
- fun providePushPermissionRepository(appPreferencesStore: AppPreferencesStore): PermissionRepository {
- return DefaultPermissionRepository(appPreferencesStore = appPreferencesStore)
+ fun providePushPermissionRepository(
+ appPreferencesStore: AppPreferencesStore,
+ @ApplicationContext context: Context,
+ ): PermissionRepository {
+ return DefaultPermissionRepository(
+ appPreferencesStore = appPreferencesStore,
+ context = context,
+ )
}
}
\ No newline at end of file
diff --git a/domain/settings/src/main/java/com/tangem/domain/settings/repositories/PermissionRepository.kt b/domain/settings/src/main/java/com/tangem/domain/settings/repositories/PermissionRepository.kt
index 21b476b233..2eec19c414 100644
--- a/domain/settings/src/main/java/com/tangem/domain/settings/repositories/PermissionRepository.kt
+++ b/domain/settings/src/main/java/com/tangem/domain/settings/repositories/PermissionRepository.kt
@@ -24,4 +24,9 @@ interface PermissionRepository {
* Permanently deny [permission] and never request again
*/
suspend fun neverAskPermission(permission: String)
+
+ /**
+ * Return is [permission] granted or not.
+ */
+ fun hasRuntimePermission(permission: String): Boolean
}
\ No newline at end of file
diff --git a/features/wallet-settings/impl/build.gradle.kts b/features/wallet-settings/impl/build.gradle.kts
index 189f291d65..2de59a0dba 100644
--- a/features/wallet-settings/impl/build.gradle.kts
+++ b/features/wallet-settings/impl/build.gradle.kts
@@ -36,6 +36,7 @@ dependencies {
implementation(projects.domain.wallets.models)
implementation(projects.domain.demo)
implementation(projects.domain.nft)
+ implementation(projects.domain.settings)
implementation(projects.domain.notifications.toggles)
implementation(projects.domain.notifications.models)
implementation(projects.domain.notifications)
diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/component/preview/PreviewWalletSettingsComponent.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/component/preview/PreviewWalletSettingsComponent.kt
index 2df0907822..55a9a005e0 100644
--- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/component/preview/PreviewWalletSettingsComponent.kt
+++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/component/preview/PreviewWalletSettingsComponent.kt
@@ -35,6 +35,7 @@ internal class PreviewWalletSettingsComponent : WalletSettingsComponent {
isNotificationsFeatureEnabled = true,
onCheckedNotificationsChanged = {},
onNotificationsDescriptionClick = {},
+ isNotificationsPermissionGranted = false,
),
requestPushNotificationsPermission = false,
onPushNotificationPermissionGranted = {},
diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/entity/WalletSettingsItemUM.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/entity/WalletSettingsItemUM.kt
index 4eabd5a71b..490fb2b00e 100644
--- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/entity/WalletSettingsItemUM.kt
+++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/entity/WalletSettingsItemUM.kt
@@ -37,4 +37,10 @@ internal sealed class WalletSettingsItemUM {
val more: TextReference,
val onClick: () -> Unit,
) : WalletSettingsItemUM()
+
+ data class NotificationPermission(
+ override val id: String,
+ val title: TextReference,
+ val description: TextReference,
+ ) : WalletSettingsItemUM()
}
\ No newline at end of file
diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt
index 071c769167..c841e7acb9 100644
--- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt
+++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt
@@ -1,5 +1,6 @@
package com.tangem.feature.walletsettings.model
+import android.os.Build
import arrow.core.getOrElse
import com.arkivanov.decompose.router.slot.SlotNavigation
import com.arkivanov.decompose.router.slot.activate
@@ -22,6 +23,7 @@ import com.tangem.domain.nft.DisableWalletNFTUseCase
import com.tangem.domain.nft.EnableWalletNFTUseCase
import com.tangem.domain.nft.GetWalletNFTEnabledUseCase
import com.tangem.domain.notifications.toggles.NotificationsFeatureToggles
+import com.tangem.domain.settings.repositories.PermissionRepository
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.isMultiCurrency
import com.tangem.domain.wallets.models.requireColdWallet
@@ -65,6 +67,7 @@ internal class WalletSettingsModel @Inject constructor(
private val getWalletNotificationsEnabledUseCase: GetWalletNotificationsEnabledUseCase,
private val setNotificationsEnabledUseCase: SetNotificationsEnabledUseCase,
private val settingsManager: SettingsManager,
+ private val permissionsRepository: PermissionRepository,
) : Model() {
val params: WalletSettingsComponent.Params = paramsContainer.require()
@@ -98,6 +101,7 @@ internal class WalletSettingsModel @Inject constructor(
isNFTEnabled = nftEnabled,
isNotificationsEnabled = notificationsEnabled,
isNotificationsFeatureEnabled = notificationsToggles.isNotificationsEnabled,
+ isNotificationsPermissionGranted = isNotificationsPermissionGranted(),
),
)
}
@@ -105,6 +109,16 @@ internal class WalletSettingsModel @Inject constructor(
.launchIn(modelScope)
}
+ private fun isNotificationsPermissionGranted(): Boolean {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ permissionsRepository.hasRuntimePermission(
+ android.Manifest.permission.POST_NOTIFICATIONS,
+ )
+ } else {
+ true
+ }
+ }
+
private fun buildItems(
userWallet: UserWallet,
dialogNavigation: SlotNavigation,
@@ -113,6 +127,7 @@ internal class WalletSettingsModel @Inject constructor(
isNFTEnabled: Boolean,
isNotificationsFeatureEnabled: Boolean,
isNotificationsEnabled: Boolean,
+ isNotificationsPermissionGranted: Boolean,
): PersistentList = itemsBuilder.buildItems(
userWalletId = userWallet.walletId,
userWalletName = userWallet.name,
@@ -147,6 +162,7 @@ internal class WalletSettingsModel @Inject constructor(
onReferralClick = { onReferralClick(userWallet) },
isNotificationsEnabled = isNotificationsEnabled,
isNotificationsFeatureEnabled = isNotificationsFeatureEnabled,
+ isNotificationsPermissionGranted = isNotificationsPermissionGranted,
onCheckedNotificationsChanged = ::onCheckedNotificationsChange,
onNotificationsDescriptionClick = ::onNotificationsDescriptionClick,
)
diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/ui/WalletSettingsScreen.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/ui/WalletSettingsScreen.kt
index f934bc6c3e..64dc1120ee 100644
--- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/ui/WalletSettingsScreen.kt
+++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/ui/WalletSettingsScreen.kt
@@ -21,6 +21,8 @@ import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
import com.tangem.core.ui.components.block.BlockCard
import com.tangem.core.ui.components.block.BlockItem
import com.tangem.core.ui.components.items.DescriptionItem
+import com.tangem.core.ui.components.notifications.Notification
+import com.tangem.core.ui.components.notifications.NotificationConfig
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme
@@ -109,6 +111,10 @@ private fun Content(state: WalletSettingsUM, modifier: Modifier = Modifier) {
yOffset = DESCRIPTION_OFFSET,
onDescriptionClick = item.onClick,
)
+ is WalletSettingsItemUM.NotificationPermission -> NotificationAlertBlock(
+ modifier = itemModifier,
+ model = item,
+ )
}
}
}
@@ -216,6 +222,18 @@ private fun SwitchBlock(model: WalletSettingsItemUM.WithSwitch, modifier: Modifi
}
}
+@Composable
+private fun NotificationAlertBlock(model: WalletSettingsItemUM.NotificationPermission, modifier: Modifier = Modifier) {
+ Notification(
+ config = NotificationConfig(
+ title = model.title,
+ subtitle = model.description,
+ iconResId = R.drawable.ic_alert_triangle_20,
+ ),
+ modifier = modifier,
+ )
+}
+
@Composable
private fun DescriptionWithMoreBlock(
model: WalletSettingsItemUM.DescriptionWithMore,
diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/ItemsBuilder.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/ItemsBuilder.kt
index 17a2b47350..0feb7b0851 100644
--- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/ItemsBuilder.kt
+++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/ItemsBuilder.kt
@@ -36,6 +36,7 @@ internal class ItemsBuilder @Inject constructor(
onCheckedNFTChange: (Boolean) -> Unit,
isNotificationsFeatureEnabled: Boolean,
isNotificationsEnabled: Boolean,
+ isNotificationsPermissionGranted: Boolean,
onCheckedNotificationsChanged: (Boolean) -> Unit,
onNotificationsDescriptionClick: () -> Unit,
forgetWallet: () -> Unit,
@@ -61,24 +62,34 @@ internal class ItemsBuilder @Inject constructor(
onReferralClick = onReferralClick,
),
)
- .run {
- if (isNotificationsFeatureEnabled) {
- add(
- buildNotificationsSwitchItem(
- isNotificationsEnabled,
- onCheckedNotificationsChanged,
- ),
- ).add(
- buildNotificationsDescriptionItem(
- onDescriptionClick = onNotificationsDescriptionClick,
- ),
- )
- } else {
- this
- }
- }
+ .addAll(
+ buildNotificationItems(
+ isNotificationsFeatureEnabled = isNotificationsFeatureEnabled,
+ isNotificationsPermissionGranted = isNotificationsPermissionGranted,
+ isNotificationsEnabled = isNotificationsEnabled,
+ onCheckedNotificationsChanged = onCheckedNotificationsChanged,
+ onNotificationsDescriptionClick = onNotificationsDescriptionClick,
+ ),
+ )
.add(buildForgetItem(forgetWallet))
+ private fun buildNotificationItems(
+ isNotificationsFeatureEnabled: Boolean,
+ isNotificationsPermissionGranted: Boolean,
+ isNotificationsEnabled: Boolean,
+ onCheckedNotificationsChanged: (Boolean) -> Unit,
+ onNotificationsDescriptionClick: () -> Unit,
+ ): List {
+ if (!isNotificationsFeatureEnabled) return emptyList()
+ return buildList {
+ if (!isNotificationsPermissionGranted) {
+ add(buildNotificationsPermissionItem())
+ }
+ add(buildNotificationsSwitchItem(isNotificationsEnabled, onCheckedNotificationsChanged))
+ add(buildNotificationsDescriptionItem(onNotificationsDescriptionClick))
+ }
+ }
+
private fun buildNameItem(walletName: String, isRenameWalletAvailable: Boolean, renameWallet: () -> Unit) =
WalletSettingsItemUM.WithText(
id = "wallet_name",
@@ -96,6 +107,12 @@ internal class ItemsBuilder @Inject constructor(
onCheckedChange = onCheckedNFTChange,
)
+ private fun buildNotificationsPermissionItem() = WalletSettingsItemUM.NotificationPermission(
+ id = "notifications_permission",
+ title = resourceReference(id = R.string.transaction_notifications_warning_title),
+ description = resourceReference(id = R.string.transaction_notifications_warning_description),
+ )
+
private fun buildNotificationsSwitchItem(isNFTEnabled: Boolean, onCheckedNFTChange: (Boolean) -> Unit) =
WalletSettingsItemUM.WithSwitch(
id = "notifications",