Updated on 2026-08-14

This commit is contained in:
Tangem 2026-06-23 08:40:33 +03:00
parent 0f8519007b
commit 428f1076f0
11 changed files with 248 additions and 185 deletions

View file

@ -52,16 +52,16 @@ interface TangemTechApi {
@Body userTokens: UserTokensResponse,
): ApiResponse<Unit>
@GET("/v1/wallets/{wallet_id}/notification-preferences")
@GET("/api/v1/notification-preferences/{wallet_id}")
suspend fun getPushNotificationPreferences(
@Path("wallet_id") walletId: String,
): ApiResponse<PushNotificationPreferencesResponse>
@PUT("/v1/wallets/{wallet_id}/notification-preferences")
@PUT("/api/v1/notification-preferences/{wallet_id}")
suspend fun updatePushNotificationPreferences(
@Path("wallet_id") walletId: String,
@Body body: PushNotificationPreferencesBody,
): ApiResponse<Unit>
): ApiResponse<PushNotificationPreferencesResponse>
// region Referral
/** Returns referral status by [walletId] */

View file

@ -1,10 +0,0 @@
package com.tangem.datasource.api.tangemTech.models
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class PushNotificationPreferenceState(
@Json(name = "isEnabled") val isEnabled: Boolean,
@Json(name = "isVisible") val isVisible: Boolean,
)

View file

@ -5,10 +5,10 @@ import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class PushNotificationPreferencesBody(
@Json(name = "transactionAlerts")
val areTransactionAlertsEnabled: Boolean,
@Json(name = "offersUpdates")
val areOffersUpdatesEnabled: Boolean,
@Json(name = "priceAlerts")
@Json(name = "transactionEventsEnabled")
val areTransactionEventsEnabled: Boolean,
@Json(name = "offerUpdatesEnabled")
val areOfferUpdatesEnabled: Boolean,
@Json(name = "priceAlertsEnabled")
val arePriceAlertsEnabled: Boolean,
)

View file

@ -5,7 +5,7 @@ import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class PushNotificationPreferencesResponse(
@Json(name = "transactionAlerts") val transactionAlerts: PushNotificationPreferenceState,
@Json(name = "offersUpdates") val offersUpdates: PushNotificationPreferenceState,
@Json(name = "priceAlerts") val priceAlerts: PushNotificationPreferenceState,
@Json(name = "transactionEventsEnabled") val areTransactionEventsEnabled: Boolean,
@Json(name = "offerUpdatesEnabled") val areOfferUpdatesEnabled: Boolean,
@Json(name = "priceAlertsEnabled") val arePriceAlertsEnabled: Boolean,
)

View file

@ -1,54 +1,49 @@
package com.tangem.data.pushnotificationpreferences
import arrow.core.Either
import com.tangem.data.pushnotificationpreferences.converters.PushNotificationPreferencesConverter
import com.tangem.datasource.api.common.response.getOrThrow
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.models.PushNotificationPreferencesBody
import com.tangem.datasource.local.datastore.RuntimeSharedStore
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.PreferencesKeys
import com.tangem.datasource.local.preferences.utils.getObjectMapSync
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.pushnotificationpreferences.models.PushNotificationCategory
import com.tangem.domain.pushnotificationpreferences.models.PushNotificationPreference
import com.tangem.domain.pushnotificationpreferences.models.WalletPushNotificationPreferences
import com.tangem.domain.pushnotificationpreferences.repository.WalletPushNotificationPreferencesRepository
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import java.util.concurrent.ConcurrentHashMap
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
/**
* In-memory cache implementation of [WalletPushNotificationPreferencesRepository].
*
* Mock-mode (current): defaults are computed locally and writes are kept in-memory only.
* Real-mode (when Variant C BE is ready): replace TODO blocks with [TangemTechApi] calls.
*
* Defaults for existing users (until BE migration runs): TX read from
* [PreferencesKeys.NOTIFICATIONS_ENABLED_STATES_KEY] (default true), Offers&Updates = true, Price Alerts = false,
* isVisible = true for all three.
* Preferences are cached in-memory (non-persistent); writes are full-replace PUTs and the server echo
* is cached as the source of truth.
*/
internal class DefaultWalletPushNotificationPreferencesRepository(
private val appPreferencesStore: AppPreferencesStore,
@Suppress("unused") private val tangemTechApi: TangemTechApi,
private val tangemTechApi: TangemTechApi,
private val cache: RuntimeSharedStore<Map<String, WalletPushNotificationPreferences>>,
private val dispatchers: CoroutineDispatcherProvider,
) : WalletPushNotificationPreferencesRepository {
private val walletMutexes = ConcurrentHashMap<String, Mutex>()
override suspend fun preload(userWalletId: UserWalletId) {
if (cache.getSyncOrNull()?.containsKey(userWalletId.stringValue) == true) return
val preferences = withContext(dispatchers.io) {
// TODO: uncomment when api is ready
// val response = tangemTechApi.getPushNotificationPreferences(userWalletId.stringValue).getOrThrow()
// PushNotificationPreferencesConverter.convert(response)
loadDefaults(userWalletId)
}
cache.update(default = emptyMap()) { current ->
if (current.containsKey(userWalletId.stringValue)) {
current
} else {
current + (userWalletId.stringValue to preferences)
if (isCached(userWalletId)) return
mutexFor(userWalletId).withLock {
if (isCached(userWalletId)) return
val preferences = fetch(userWalletId)
cache.update(default = emptyMap()) { current ->
if (current.containsKey(userWalletId.stringValue)) {
current
} else {
current + (userWalletId.stringValue to preferences)
}
}
}
}
@ -64,9 +59,11 @@ internal class DefaultWalletPushNotificationPreferencesRepository(
category: PushNotificationCategory,
isEnabled: Boolean,
): Either<Throwable, Unit> = Either.catch {
val current = cache.getSyncOrNull()?.get(userWalletId.stringValue) ?: loadDefaults(userWalletId)
val updated = current.withCategory(category, isEnabled)
putAndCommit(userWalletId, updated)
mutexFor(userWalletId).withLock {
val current = currentOrFetch(userWalletId)
val updated = current.withCategory(category, isEnabled)
putAndCommit(userWalletId, updated)
}
}
override suspend fun setAllPreferences(
@ -75,39 +72,45 @@ internal class DefaultWalletPushNotificationPreferencesRepository(
offersUpdates: Boolean,
priceAlerts: Boolean,
): Either<Throwable, Unit> = Either.catch {
val current = cache.getSyncOrNull()?.get(userWalletId.stringValue) ?: loadDefaults(userWalletId)
val updated = current.copy(
transactionAlerts = current.transactionAlerts.copy(isEnabled = transactionAlerts),
offersUpdates = current.offersUpdates.copy(isEnabled = offersUpdates),
priceAlerts = current.priceAlerts.copy(isEnabled = priceAlerts),
)
putAndCommit(userWalletId, updated)
mutexFor(userWalletId).withLock {
val current = currentOrFetch(userWalletId)
val updated = current.copy(
transactionAlerts = current.transactionAlerts.copy(isEnabled = transactionAlerts),
offersUpdates = current.offersUpdates.copy(isEnabled = offersUpdates),
priceAlerts = current.priceAlerts.copy(isEnabled = priceAlerts),
)
putAndCommit(userWalletId, updated)
}
}
// Cache, or a freshly fetched server snapshot, so a full-replace PUT never carries fabricated defaults.
private suspend fun currentOrFetch(userWalletId: UserWalletId): WalletPushNotificationPreferences =
cache.getSyncOrNull()?.get(userWalletId.stringValue) ?: fetch(userWalletId)
private suspend fun fetch(userWalletId: UserWalletId): WalletPushNotificationPreferences =
withContext(dispatchers.io) {
val response = tangemTechApi.getPushNotificationPreferences(userWalletId.stringValue).getOrThrow()
PushNotificationPreferencesConverter.convert(response)
}
private suspend fun isCached(userWalletId: UserWalletId): Boolean =
cache.getSyncOrNull()?.containsKey(userWalletId.stringValue) == true
private fun mutexFor(userWalletId: UserWalletId): Mutex =
walletMutexes.computeIfAbsent(userWalletId.stringValue) { Mutex() }
private suspend fun putAndCommit(userWalletId: UserWalletId, updated: WalletPushNotificationPreferences) {
withContext(dispatchers.io) {
// TODO: uncomment when api is ready
// tangemTechApi.updatePushNotificationPreferences(
// walletId = userWalletId.stringValue,
// body = PushNotificationPreferencesBody(
// areTransactionAlertsEnabled = updated.transactionAlerts.isEnabled,
// areOffersUpdatesEnabled = updated.offersUpdates.isEnabled,
// arePriceAlertsEnabled = updated.priceAlerts.isEnabled,
// ),
// ).getOrThrow()
val applied = withContext(dispatchers.io) {
val response = tangemTechApi.updatePushNotificationPreferences(
walletId = userWalletId.stringValue,
body = PushNotificationPreferencesBody(
areTransactionEventsEnabled = updated.transactionAlerts.isEnabled,
areOfferUpdatesEnabled = updated.offersUpdates.isEnabled,
arePriceAlertsEnabled = updated.priceAlerts.isEnabled,
),
).getOrThrow()
PushNotificationPreferencesConverter.convert(response)
}
cache.update(default = emptyMap()) { it + (userWalletId.stringValue to updated) }
}
// TODO remove when api is ready, use api methods to load real settings
private suspend fun loadDefaults(userWalletId: UserWalletId): WalletPushNotificationPreferences {
val areTransactionAlertsEnabled = appPreferencesStore
.getObjectMapSync<Boolean>(PreferencesKeys.NOTIFICATIONS_ENABLED_STATES_KEY)[userWalletId.stringValue] !=
false
return WalletPushNotificationPreferences(
transactionAlerts = PushNotificationPreference(isEnabled = areTransactionAlertsEnabled, isVisible = true),
offersUpdates = PushNotificationPreference(isEnabled = true, isVisible = true),
priceAlerts = PushNotificationPreference(isEnabled = false, isVisible = true),
)
cache.update(default = emptyMap()) { it + (userWalletId.stringValue to applied) }
}
}

View file

@ -1,6 +1,5 @@
package com.tangem.data.pushnotificationpreferences.converters
import com.tangem.datasource.api.tangemTech.models.PushNotificationPreferenceState
import com.tangem.datasource.api.tangemTech.models.PushNotificationPreferencesResponse
import com.tangem.domain.pushnotificationpreferences.models.PushNotificationPreference
import com.tangem.domain.pushnotificationpreferences.models.WalletPushNotificationPreferences
@ -11,11 +10,8 @@ internal object PushNotificationPreferencesConverter :
override fun convert(value: PushNotificationPreferencesResponse): WalletPushNotificationPreferences =
WalletPushNotificationPreferences(
transactionAlerts = value.transactionAlerts.toDomain(),
offersUpdates = value.offersUpdates.toDomain(),
priceAlerts = value.priceAlerts.toDomain(),
transactionAlerts = PushNotificationPreference(isEnabled = value.areTransactionEventsEnabled),
offersUpdates = PushNotificationPreference(isEnabled = value.areOfferUpdatesEnabled),
priceAlerts = PushNotificationPreference(isEnabled = value.arePriceAlertsEnabled),
)
private fun PushNotificationPreferenceState.toDomain(): PushNotificationPreference =
PushNotificationPreference(isEnabled = isEnabled, isVisible = isVisible)
}

View file

@ -3,7 +3,6 @@ package com.tangem.data.pushnotificationpreferences.di
import com.tangem.data.pushnotificationpreferences.DefaultWalletPushNotificationPreferencesRepository
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.local.datastore.RuntimeSharedStore
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.domain.pushnotificationpreferences.repository.WalletPushNotificationPreferencesRepository
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.Module
@ -19,11 +18,9 @@ internal object PushNotificationPreferencesModule {
@Singleton
@Provides
fun providesWalletPushNotificationPreferencesRepository(
appPreferencesStore: AppPreferencesStore,
tangemTechApi: TangemTechApi,
dispatchers: CoroutineDispatcherProvider,
): WalletPushNotificationPreferencesRepository = DefaultWalletPushNotificationPreferencesRepository(
appPreferencesStore = appPreferencesStore,
tangemTechApi = tangemTechApi,
cache = RuntimeSharedStore(),
dispatchers = dispatchers,

View file

@ -1,141 +1,220 @@
package com.tangem.data.pushnotificationpreferences
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.emptyPreferences
import app.cash.turbine.test
import arrow.core.Either
import com.google.common.truth.Truth.assertThat
import com.squareup.moshi.Moshi
import com.tangem.datasource.api.common.response.ApiResponse
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.models.PushNotificationPreferencesBody
import com.tangem.datasource.api.tangemTech.models.PushNotificationPreferencesResponse
import com.tangem.datasource.local.datastore.RuntimeSharedStore
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.pushnotificationpreferences.models.PushNotificationCategory
import com.tangem.domain.pushnotificationpreferences.models.PushNotificationPreference
import com.tangem.domain.pushnotificationpreferences.models.WalletPushNotificationPreferences
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.mockk
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test
class DefaultWalletPushNotificationPreferencesRepositoryTest {
private val tangemTechApi: TangemTechApi = mockk()
private val preferencesDataStore: DataStore<Preferences> = mockk()
private val appPreferencesStore = AppPreferencesStore(
moshi = Moshi.Builder().build(),
dispatchers = TestingCoroutineDispatcherProvider(),
preferencesDataStore = preferencesDataStore,
)
private val userWalletId = UserWalletId(stringValue = "0011223344556677")
private val otherWalletId = UserWalletId(stringValue = "ffeeddccbbaa9988")
private val repository = DefaultWalletPushNotificationPreferencesRepository(
appPreferencesStore = appPreferencesStore,
tangemTechApi = tangemTechApi,
cache = RuntimeSharedStore(),
dispatchers = TestingCoroutineDispatcherProvider(),
)
@Test
fun `GIVEN no prior state WHEN preload THEN cache contains defaults`() = runTest {
coEvery { preferencesDataStore.data } returns flowOf(emptyPreferences())
fun `GIVEN server returns prefs WHEN preload THEN cache holds converted server state`() = runTest {
// Arrange
stubGet(userWalletId, transaction = true, offers = true, price = false)
// Act
repository.preload(userWalletId)
// Assert
repository.observePreferences(userWalletId).test {
assertThat(awaitItem()).isEqualTo(defaults(transactionAlertsEnabled = true))
assertThat(awaitItem()).isEqualTo(prefs(transaction = true, offers = true, price = false))
}
coVerify(exactly = 1) { tangemTechApi.getPushNotificationPreferences(userWalletId.stringValue) }
}
@Test
fun `GIVEN preload already done WHEN preload called again THEN no-op`() = runTest {
coEvery { preferencesDataStore.data } returns flowOf(emptyPreferences())
fun `GIVEN already preloaded WHEN preload called again THEN no second GET`() = runTest {
// Arrange
stubGet(userWalletId, transaction = true, offers = true, price = false)
// Act
repository.preload(userWalletId)
repository.preload(userWalletId)
// Assert
coVerify(exactly = 1) { tangemTechApi.getPushNotificationPreferences(userWalletId.stringValue) }
}
@Test
fun `GIVEN cache miss WHEN updatePreference THEN fetches baseline AND sends full-replace PUT AND caches echo`() =
runTest {
// Arrange
stubGet(userWalletId, transaction = true, offers = true, price = false)
stubPut(userWalletId, transaction = true, offers = true, price = true)
// Act
val result = repository.updatePreference(
userWalletId = userWalletId,
category = PushNotificationCategory.PriceAlerts,
isEnabled = true,
)
// Assert
assertThat(result).isInstanceOf(Either.Right::class.java)
// The full-replace body changes only the tapped category on top of the server baseline.
coVerify(exactly = 1) {
tangemTechApi.updatePushNotificationPreferences(
userWalletId.stringValue,
PushNotificationPreferencesBody(
areTransactionEventsEnabled = true,
areOfferUpdatesEnabled = true,
arePriceAlertsEnabled = true,
),
)
}
repository.observePreferences(userWalletId).test {
assertThat(awaitItem()).isEqualTo(prefs(transaction = true, offers = true, price = true))
}
}
@Test
fun `GIVEN preloaded state WHEN updatePreference THEN only the tapped category changes in the PUT body`() = runTest {
// Arrange
stubGet(userWalletId, transaction = true, offers = true, price = false)
stubPut(userWalletId, transaction = true, offers = false, price = false)
// Act
repository.preload(userWalletId)
repository.updatePreference(userWalletId, PushNotificationCategory.OffersUpdates, isEnabled = false)
// Assert
coVerify(exactly = 1) {
tangemTechApi.updatePushNotificationPreferences(
userWalletId.stringValue,
PushNotificationPreferencesBody(
areTransactionEventsEnabled = true,
areOfferUpdatesEnabled = false,
arePriceAlertsEnabled = false,
),
)
}
}
@Test
fun `GIVEN write fails WHEN updatePreference THEN returns Left`() = runTest {
// Arrange
stubGet(userWalletId, transaction = true, offers = true, price = false)
repository.preload(userWalletId)
coEvery { tangemTechApi.updatePushNotificationPreferences(any(), any()) } throws IllegalStateException("boom")
// Act
val result = repository.updatePreference(userWalletId, PushNotificationCategory.OffersUpdates, isEnabled = false)
// Assert
assertThat(result).isInstanceOf(Either.Left::class.java)
}
@Test
fun `GIVEN different wallets WHEN observed THEN each keeps its own server state`() = runTest {
// Arrange
stubGet(userWalletId, transaction = false, offers = false, price = false)
stubGet(otherWalletId, transaction = true, offers = true, price = true)
// Assert
repository.observePreferences(userWalletId).test {
assertThat(awaitItem()).isEqualTo(prefs(transaction = false, offers = false, price = false))
}
repository.observePreferences(otherWalletId).test {
assertThat(awaitItem()).isEqualTo(prefs(transaction = true, offers = true, price = true))
}
}
@Test
fun `GIVEN concurrent collectors WHEN preload races THEN a single GET is issued`() = runTest {
// Arrange
val gate = CompletableDeferred<Unit>()
coEvery { tangemTechApi.getPushNotificationPreferences(userWalletId.stringValue) } coAnswers {
gate.await()
ApiResponse.Success(PushNotificationPreferencesResponse(true, true, false))
}
// Act
launch { repository.preload(userWalletId) }
runCurrent()
launch { repository.preload(userWalletId) }
runCurrent()
gate.complete(Unit)
advanceUntilIdle()
// Assert
coVerify(exactly = 1) { tangemTechApi.getPushNotificationPreferences(userWalletId.stringValue) }
}
@Test
fun `GIVEN concurrent writes WHEN updatePreference races THEN serialized so no update is lost`() = runTest {
// Arrange
stubGet(userWalletId, transaction = true, offers = true, price = false)
val gate = CompletableDeferred<Unit>()
coEvery { tangemTechApi.updatePushNotificationPreferences(eq(userWalletId.stringValue), any()) } coAnswers {
val body = arg<PushNotificationPreferencesBody>(1)
gate.await()
ApiResponse.Success(
PushNotificationPreferencesResponse(
body.areTransactionEventsEnabled,
body.areOfferUpdatesEnabled,
body.arePriceAlertsEnabled,
),
)
}
repository.preload(userWalletId)
// Act
launch { repository.updatePreference(userWalletId, PushNotificationCategory.OffersUpdates, isEnabled = false) }
runCurrent()
launch { repository.updatePreference(userWalletId, PushNotificationCategory.PriceAlerts, isEnabled = true) }
runCurrent()
gate.complete(Unit)
advanceUntilIdle()
// Assert
coVerify(exactly = 2) { tangemTechApi.updatePushNotificationPreferences(eq(userWalletId.stringValue), any()) }
repository.observePreferences(userWalletId).test {
val item = awaitItem()
assertThat(item.offersUpdates.isEnabled).isFalse()
assertThat(awaitItem()).isEqualTo(prefs(transaction = true, offers = false, price = true))
}
}
@Test
fun `GIVEN cache miss WHEN updatePreference THEN loads defaults and applies update`() = runTest {
coEvery { preferencesDataStore.data } returns flowOf(emptyPreferences())
val result = repository.updatePreference(
userWalletId = userWalletId,
category = PushNotificationCategory.PriceAlerts,
isEnabled = true,
)
assertThat(result).isInstanceOf(Either.Right::class.java)
repository.observePreferences(userWalletId).test {
val item = awaitItem()
assertThat(item.priceAlerts.isEnabled).isTrue()
assertThat(item.offersUpdates.isEnabled).isTrue()
assertThat(item.transactionAlerts.isEnabled).isTrue()
}
private fun stubGet(id: UserWalletId, transaction: Boolean, offers: Boolean, price: Boolean) {
coEvery { tangemTechApi.getPushNotificationPreferences(id.stringValue) } returns
ApiResponse.Success(PushNotificationPreferencesResponse(transaction, offers, price))
}
@Test
fun `GIVEN preloaded state WHEN updatePreference for each category THEN updates only that category`() = runTest {
coEvery { preferencesDataStore.data } returns flowOf(emptyPreferences())
repository.preload(userWalletId)
repository.updatePreference(userWalletId, PushNotificationCategory.TransactionAlerts, isEnabled = false)
repository.updatePreference(userWalletId, PushNotificationCategory.OffersUpdates, isEnabled = false)
repository.updatePreference(userWalletId, PushNotificationCategory.PriceAlerts, isEnabled = true)
repository.observePreferences(userWalletId).test {
val item = awaitItem()
assertThat(item.transactionAlerts.isEnabled).isFalse()
assertThat(item.offersUpdates.isEnabled).isFalse()
assertThat(item.priceAlerts.isEnabled).isTrue()
}
private fun stubPut(id: UserWalletId, transaction: Boolean, offers: Boolean, price: Boolean) {
coEvery { tangemTechApi.updatePushNotificationPreferences(eq(id.stringValue), any()) } returns
ApiResponse.Success(PushNotificationPreferencesResponse(transaction, offers, price))
}
@Test
fun `GIVEN no subscription yet WHEN observePreferences subscribed THEN triggers preload and emits defaults`() =
runTest {
coEvery { preferencesDataStore.data } returns flowOf(emptyPreferences())
repository.observePreferences(userWalletId).test {
val item = awaitItem()
assertThat(item).isEqualTo(defaults(transactionAlertsEnabled = true))
}
}
@Test
fun `GIVEN updates for different wallets WHEN observed independently THEN each wallet has its own state`() =
runTest {
coEvery { preferencesDataStore.data } returns flowOf(emptyPreferences())
repository.updatePreference(userWalletId, PushNotificationCategory.OffersUpdates, isEnabled = false)
repository.updatePreference(otherWalletId, PushNotificationCategory.PriceAlerts, isEnabled = true)
repository.observePreferences(userWalletId).test {
val item = awaitItem()
assertThat(item.offersUpdates.isEnabled).isFalse()
assertThat(item.priceAlerts.isEnabled).isFalse()
}
repository.observePreferences(otherWalletId).test {
val item = awaitItem()
assertThat(item.offersUpdates.isEnabled).isTrue()
assertThat(item.priceAlerts.isEnabled).isTrue()
}
}
private fun defaults(transactionAlertsEnabled: Boolean) = WalletPushNotificationPreferences(
transactionAlerts = PushNotificationPreference(isEnabled = transactionAlertsEnabled, isVisible = true),
offersUpdates = PushNotificationPreference(isEnabled = true, isVisible = true),
priceAlerts = PushNotificationPreference(isEnabled = false, isVisible = true),
private fun prefs(transaction: Boolean, offers: Boolean, price: Boolean) = WalletPushNotificationPreferences(
transactionAlerts = PushNotificationPreference(isEnabled = transaction),
offersUpdates = PushNotificationPreference(isEnabled = offers),
priceAlerts = PushNotificationPreference(isEnabled = price),
)
}

View file

@ -2,5 +2,4 @@ package com.tangem.domain.pushnotificationpreferences.models
data class PushNotificationPreference(
val isEnabled: Boolean,
val isVisible: Boolean,
)

View file

@ -163,7 +163,6 @@ internal class PushNotificationSettingsModel @Inject constructor(
return TOGGLE_ORDER
.asSequence()
.map { id -> id.spec(prefs) }
.filter { it.preference.isVisible }
.map { spec ->
ToggleUM(
id = spec.id,

View file

@ -286,14 +286,14 @@ class PushNotificationSettingsModelTest {
}
private fun allFalse() = WalletPushNotificationPreferences(
transactionAlerts = PushNotificationPreference(isEnabled = false, isVisible = true),
offersUpdates = PushNotificationPreference(isEnabled = false, isVisible = true),
priceAlerts = PushNotificationPreference(isEnabled = false, isVisible = true),
transactionAlerts = PushNotificationPreference(isEnabled = false),
offersUpdates = PushNotificationPreference(isEnabled = false),
priceAlerts = PushNotificationPreference(isEnabled = false),
)
private fun anyOn() = WalletPushNotificationPreferences(
transactionAlerts = PushNotificationPreference(isEnabled = true, isVisible = true),
offersUpdates = PushNotificationPreference(isEnabled = false, isVisible = true),
priceAlerts = PushNotificationPreference(isEnabled = false, isVisible = true),
transactionAlerts = PushNotificationPreference(isEnabled = true),
offersUpdates = PushNotificationPreference(isEnabled = false),
priceAlerts = PushNotificationPreference(isEnabled = false),
)
}