Updated on 2026-08-14
This commit is contained in:
parent
938d7baee1
commit
5d1cd85382
30 changed files with 332 additions and 204 deletions
|
|
@ -22,6 +22,7 @@ dependencies {
|
|||
implementation(project(":core:utils"))
|
||||
implementation(project(":libs:crypto"))
|
||||
implementation(project(":libs:auth"))
|
||||
implementation(project(":data:source:preferences"))
|
||||
|
||||
/** Features */
|
||||
implementation(project(":features:onboarding"))
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import com.tangem.datasource.config.models.Config
|
|||
import com.tangem.datasource.connection.NetworkConnectionManager
|
||||
import com.tangem.domain.DomainLayer
|
||||
import com.tangem.domain.common.LogConfig
|
||||
import com.tangem.data.source.preferences.PreferencesDataSource
|
||||
import com.tangem.tap.common.IntentHandler
|
||||
import com.tangem.tap.common.analytics.AnalyticsFactory
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
|
||||
|
|
@ -51,7 +52,6 @@ import com.tangem.tap.domain.walletStores.repository.di.provideDefaultImplementa
|
|||
import com.tangem.tap.domain.walletconnect.WalletConnectRepository
|
||||
import com.tangem.tap.features.customtoken.api.featuretoggles.CustomTokenFeatureToggles
|
||||
import com.tangem.tap.features.tokens.api.featuretoggles.TokensListFeatureToggles
|
||||
import com.tangem.tap.persistence.PreferencesStorage
|
||||
import com.tangem.tap.proxy.AppStateHolder
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.wallet.BuildConfig
|
||||
|
|
@ -66,7 +66,7 @@ lateinit var store: Store<AppState>
|
|||
|
||||
lateinit var foregroundActivityObserver: ForegroundActivityObserver
|
||||
lateinit var activityResultCaller: ActivityResultCaller
|
||||
lateinit var preferencesStorage: PreferencesStorage
|
||||
lateinit var preferencesStorage: PreferencesDataSource
|
||||
lateinit var walletConnectRepository: WalletConnectRepository
|
||||
lateinit var shopService: TangemShopService
|
||||
lateinit var userTokensRepository: UserTokensRepository
|
||||
|
|
@ -134,6 +134,9 @@ class TapApplication : Application(), ImageLoaderFactory {
|
|||
@Inject
|
||||
lateinit var customTokenFeatureToggles: CustomTokenFeatureToggles
|
||||
|
||||
@Inject
|
||||
lateinit var preferencesDataSource: PreferencesDataSource
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
|
|
@ -161,7 +164,7 @@ class TapApplication : Application(), ImageLoaderFactory {
|
|||
registerActivityLifecycleCallbacks(foregroundActivityObserver.callbacks)
|
||||
|
||||
DomainLayer.init()
|
||||
preferencesStorage = PreferencesStorage(this)
|
||||
preferencesStorage = preferencesDataSource
|
||||
walletConnectRepository = WalletConnectRepository(this)
|
||||
|
||||
val configLoader = FeaturesLocalLoader(assetReader, MoshiConverter.sdkMoshi, BuildConfig.ENVIRONMENT)
|
||||
|
|
@ -246,7 +249,7 @@ class TapApplication : Application(), ImageLoaderFactory {
|
|||
|
||||
private fun initFeedbackManager(
|
||||
context: Context,
|
||||
preferencesStorage: PreferencesStorage,
|
||||
preferencesStorage: PreferencesDataSource,
|
||||
foregroundActivityObserver: ForegroundActivityObserver,
|
||||
store: Store<AppState>,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -3,9 +3,11 @@ package com.tangem.tap.common.analytics.topup
|
|||
import com.tangem.common.extensions.guard
|
||||
import com.tangem.common.extensions.isZero
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.data.source.preferences.model.DataSourceTopupInfo
|
||||
import com.tangem.data.source.preferences.storage.ToppedUpWalletStorage
|
||||
import com.tangem.domain.common.CardTypesResolver
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.common.util.UserWalletId
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.tap.common.analytics.converters.TopUpEventConverter
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
|
|
@ -19,7 +21,6 @@ import com.tangem.tap.domain.tokens.models.BlockchainNetwork
|
|||
import com.tangem.tap.domain.walletCurrencies.WalletCurrenciesManager
|
||||
import com.tangem.tap.domain.walletStores.WalletStoresManager
|
||||
import com.tangem.tap.features.wallet.models.Currency
|
||||
import com.tangem.tap.persistence.ToppedUpWalletStorage
|
||||
import com.tangem.tap.scope
|
||||
import kotlinx.coroutines.launch
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -90,9 +91,9 @@ class TopUpController(
|
|||
|
||||
val isToppedUpInPast = findToppedUpCurrenciesInPast(walletDataModels).isNotEmpty()
|
||||
if (isToppedUpInPast) {
|
||||
val newWalletInfo = ToppedUpWalletStorage.TopupInfo(
|
||||
val newWalletInfo = DataSourceTopupInfo(
|
||||
walletId = userWalletId.stringValue,
|
||||
cardBalanceState = AnalyticsParam.CardBalanceState.Full,
|
||||
cardBalanceState = DataSourceTopupInfo.CardBalanceState.Full,
|
||||
)
|
||||
topupWalletStorage.save(newWalletInfo)
|
||||
return@launch
|
||||
|
|
@ -109,9 +110,9 @@ class TopUpController(
|
|||
fun registerEmptyWallet(scanResponse: ScanResponse) {
|
||||
UserWalletIdBuilder.scanResponse(scanResponse).build()?.let {
|
||||
topupWalletStorage.save(
|
||||
ToppedUpWalletStorage.TopupInfo(
|
||||
DataSourceTopupInfo(
|
||||
walletId = it.stringValue,
|
||||
cardBalanceState = AnalyticsParam.CardBalanceState.Empty,
|
||||
cardBalanceState = DataSourceTopupInfo.CardBalanceState.Empty,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -129,17 +130,28 @@ class TopUpController(
|
|||
cardTypesResolver: CardTypesResolver,
|
||||
) {
|
||||
val topupInfo = topupWalletStorage.restore(userWalletId.stringValue).guard {
|
||||
val topupInfo = ToppedUpWalletStorage.TopupInfo(
|
||||
val topupInfo = DataSourceTopupInfo(
|
||||
walletId = userWalletId.stringValue,
|
||||
cardBalanceState = cardBalanceState,
|
||||
cardBalanceState = when (cardBalanceState) {
|
||||
AnalyticsParam.CardBalanceState.BlockchainError ->
|
||||
DataSourceTopupInfo.CardBalanceState.BlockchainError
|
||||
AnalyticsParam.CardBalanceState.CustomToken ->
|
||||
DataSourceTopupInfo.CardBalanceState.CustomToken
|
||||
AnalyticsParam.CardBalanceState.Empty ->
|
||||
DataSourceTopupInfo.CardBalanceState.Empty
|
||||
AnalyticsParam.CardBalanceState.Full ->
|
||||
DataSourceTopupInfo.CardBalanceState.Full
|
||||
},
|
||||
)
|
||||
topupWalletStorage.save(topupInfo)
|
||||
return
|
||||
}
|
||||
if (topupInfo.isToppedUp) return
|
||||
|
||||
if (!topupInfo.isToppedUp && cardBalanceState.isToppedUp()) {
|
||||
topupWalletStorage.save(topupInfo.copy(cardBalanceState = AnalyticsParam.CardBalanceState.Full))
|
||||
val isToppedUp = topupInfo.cardBalanceState == DataSourceTopupInfo.CardBalanceState.Full
|
||||
if (isToppedUp) return
|
||||
|
||||
if (cardBalanceState.isToppedUp()) {
|
||||
topupWalletStorage.save(topupInfo.copy(cardBalanceState = DataSourceTopupInfo.CardBalanceState.Full))
|
||||
TopUpEventConverter().convert(cardTypesResolver)?.let {
|
||||
Analytics.send(it)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,19 +2,19 @@ package com.tangem.tap.common.chat
|
|||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import com.tangem.tap.ForegroundActivityObserver
|
||||
import com.tangem.datasource.config.models.ChatConfig
|
||||
import com.tangem.tap.common.chat.opener.ChatOpener
|
||||
import com.tangem.datasource.config.models.SprinklrConfig
|
||||
import com.tangem.datasource.config.models.ZendeskConfig
|
||||
import com.tangem.data.source.preferences.PreferencesDataSource
|
||||
import com.tangem.tap.ForegroundActivityObserver
|
||||
import com.tangem.tap.common.chat.opener.ChatOpener
|
||||
import com.tangem.tap.common.chat.opener.implementation.SprinklrChatOpener
|
||||
import com.tangem.tap.common.chat.opener.implementation.ZendeskChatOpener
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.persistence.PreferencesStorage
|
||||
import org.rekotlin.Store
|
||||
|
||||
class ChatManager(
|
||||
private val preferencesStorage: PreferencesStorage,
|
||||
private val preferencesStorage: PreferencesDataSource,
|
||||
private val foregroundActivityObserver: ForegroundActivityObserver,
|
||||
private val store: Store<AppState>,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -5,11 +5,12 @@ import com.tangem.common.core.TangemSdkError
|
|||
import com.tangem.common.extensions.guard
|
||||
import com.tangem.datasource.config.models.Config
|
||||
import com.tangem.domain.common.LogConfig
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.models.scan.ProductType
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.tap.common.entities.FiatCurrency
|
||||
import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
|
|
@ -75,7 +76,9 @@ private fun handleAction(action: Action, appState: () -> AppState?, dispatch: Di
|
|||
is GlobalAction.RestoreAppCurrency -> {
|
||||
store.dispatch(
|
||||
GlobalAction.RestoreAppCurrency.Success(
|
||||
preferencesStorage.fiatCurrenciesPrefStorage.getAppCurrency(),
|
||||
preferencesStorage.fiatCurrenciesPrefStorage.getAppCurrency()
|
||||
?.run { FiatCurrency(code, name, symbol) }
|
||||
?: FiatCurrency.Default,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,9 +19,6 @@ import com.tangem.common.tlv.Tlv
|
|||
import com.tangem.common.tlv.TlvDecoder
|
||||
import com.tangem.crypto.CryptoUtils
|
||||
import com.tangem.crypto.hdWallet.DerivationPath
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.models.scan.ProductType
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.common.TapWorkarounds.isExcluded
|
||||
import com.tangem.domain.common.TapWorkarounds.isNotSupportedInThatRelease
|
||||
import com.tangem.domain.common.TapWorkarounds.isSaltPay
|
||||
|
|
@ -29,6 +26,9 @@ import com.tangem.domain.common.TapWorkarounds.isStart2Coin
|
|||
import com.tangem.domain.common.TapWorkarounds.isTangemTwins
|
||||
import com.tangem.domain.common.TapWorkarounds.useOldStyleDerivation
|
||||
import com.tangem.domain.common.TwinsHelper
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.models.scan.ProductType
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.operations.PreflightReadMode
|
||||
import com.tangem.operations.PreflightReadTask
|
||||
import com.tangem.operations.ScanTask
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.tap.features.disclaimer
|
||||
|
||||
import com.tangem.tap.persistence.DisclaimerPrefStorage
|
||||
import com.tangem.data.source.preferences.storage.DisclaimerPrefStorage
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
package com.tangem.tap.features.disclaimer
|
||||
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.common.TapWorkarounds.isSaltPay
|
||||
import com.tangem.domain.common.TapWorkarounds.isStart2Coin
|
||||
import com.tangem.tap.persistence.DisclaimerPrefStorage
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.data.source.preferences.storage.DisclaimerPrefStorage
|
||||
import com.tangem.tap.preferencesStorage
|
||||
import java.util.*
|
||||
import java.util.Locale
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import com.tangem.tap.domain.extensions.getOrLoadCardArtworkUrl
|
|||
import com.tangem.tap.features.wallet.models.Currency
|
||||
import com.tangem.tap.features.wallet.models.hasPendingTransactions
|
||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
||||
import com.tangem.tap.persistence.UsedCardsPrefStorage
|
||||
import com.tangem.data.source.preferences.storage.UsedCardsPrefStorage
|
||||
import timber.log.Timber
|
||||
import java.math.BigDecimal
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@ package com.tangem.tap.features.wallet.redux.middlewares
|
|||
|
||||
import com.tangem.common.extensions.guard
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.datasource.api.tangemTech.models.CurrenciesResponse
|
||||
import com.tangem.data.source.preferences.model.DataSourceCurrency
|
||||
import com.tangem.data.source.preferences.model.DataSourceFiatCurrency
|
||||
import com.tangem.data.source.preferences.storage.FiatCurrenciesPrefStorage
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.MainScreen
|
||||
import com.tangem.tap.common.entities.FiatCurrency
|
||||
|
|
@ -14,7 +16,6 @@ import com.tangem.tap.features.wallet.domain.WalletRepository
|
|||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.features.wallet.redux.models.WalletDialog
|
||||
import com.tangem.tap.features.walletSelector.redux.WalletSelectorAction
|
||||
import com.tangem.tap.persistence.FiatCurrenciesPrefStorage
|
||||
import com.tangem.tap.scope
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.tap.userWalletsListManager
|
||||
|
|
@ -47,8 +48,10 @@ class AppCurrencyMiddleware(
|
|||
|
||||
scope.launch {
|
||||
runCatching { walletRepository.getCurrencyList() }
|
||||
.onSuccess {
|
||||
val currenciesList = it.currencies
|
||||
.onSuccess { response ->
|
||||
val currenciesList = response.currencies
|
||||
.map { with(it) { DataSourceCurrency(id, code, name, rateBTC, unit, type) } }
|
||||
|
||||
if (currenciesList.isNotEmpty() && currenciesList.toSet() != storedFiatCurrencies.toSet()) {
|
||||
fiatCurrenciesPrefStorage.save(currenciesList)
|
||||
store.dispatchDialogShow(
|
||||
|
|
@ -64,7 +67,9 @@ class AppCurrencyMiddleware(
|
|||
|
||||
private fun selectCurrency(action: WalletAction.AppCurrencyAction.SelectAppCurrency) {
|
||||
Analytics.send(MainScreen.MainCurrencyChanged(AnalyticsParam.CurrencyType.FiatCurrency(action.fiatCurrency)))
|
||||
fiatCurrenciesPrefStorage.saveAppCurrency(action.fiatCurrency)
|
||||
fiatCurrenciesPrefStorage.saveAppCurrency(
|
||||
with(action.fiatCurrency) { DataSourceFiatCurrency(code, name, symbol) },
|
||||
)
|
||||
store.dispatch(GlobalAction.ChangeAppCurrency(action.fiatCurrency))
|
||||
store.dispatch(DetailsAction.ChangeAppCurrency(action.fiatCurrency))
|
||||
store.dispatch(WalletSelectorAction.ChangeAppCurrency(action.fiatCurrency))
|
||||
|
|
@ -77,7 +82,7 @@ class AppCurrencyMiddleware(
|
|||
}
|
||||
}
|
||||
|
||||
private fun List<CurrenciesResponse.Currency>.mapToUiModel(): List<FiatCurrency> {
|
||||
private fun List<DataSourceCurrency>.mapToUiModel(): List<FiatCurrency> {
|
||||
return this.map {
|
||||
FiatCurrency(
|
||||
code = it.code,
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
package com.tangem.tap.persistence
|
||||
|
||||
import com.squareup.moshi.FromJson
|
||||
import com.squareup.moshi.ToJson
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
|
||||
class CardBalanceStateAdapter {
|
||||
|
||||
@ToJson
|
||||
fun toJson(src: AnalyticsParam.CardBalanceState): String = src.value
|
||||
|
||||
@FromJson
|
||||
fun fromJson(json: String): AnalyticsParam.CardBalanceState {
|
||||
return when (json) {
|
||||
AnalyticsParam.CardBalanceState.Empty.value -> AnalyticsParam.CardBalanceState.Empty
|
||||
AnalyticsParam.CardBalanceState.Full.value -> AnalyticsParam.CardBalanceState.Full
|
||||
else -> error("CardBalanceState not found")
|
||||
}
|
||||
}
|
||||
}
|
||||
1
data/source/preferences/.gitignore
vendored
Normal file
1
data/source/preferences/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/build
|
||||
17
data/source/preferences/build.gradle.kts
Normal file
17
data/source/preferences/build.gradle.kts
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
plugins {
|
||||
alias(deps.plugins.kotlin.android)
|
||||
alias(deps.plugins.kotlin.kapt)
|
||||
alias(deps.plugins.android.library)
|
||||
id("configuration")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(deps.androidx.core.ktx)
|
||||
implementation(deps.moshi)
|
||||
implementation(deps.moshi.kotlin)
|
||||
implementation(deps.hilt.android)
|
||||
kapt(deps.hilt.kapt)
|
||||
|
||||
// For MoshiJsonConverter
|
||||
implementation(deps.tangem.card.core)
|
||||
}
|
||||
2
data/source/preferences/src/main/AndroidManifest.xml
Normal file
2
data/source/preferences/src/main/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.tangem.data.source.preferences" />
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
package com.tangem.data.source.preferences
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.core.content.edit
|
||||
import java.util.*
|
||||
|
||||
@Deprecated("Create repository instead")
|
||||
class AppRatingLaunchObserver internal constructor(
|
||||
private val preferences: SharedPreferences,
|
||||
private val launchCounts: Int,
|
||||
) {
|
||||
|
||||
private val deferShowing = 20
|
||||
private val firstShowing = 3
|
||||
private var fundsFoundDate: Calendar? = null
|
||||
|
||||
init {
|
||||
val msWhenFundsWasFound = preferences.getLong(K_FUNDS_FOUND_DATE, FUNDS_FOUND_DATE_UNDEFINED)
|
||||
if (msWhenFundsWasFound != FUNDS_FOUND_DATE_UNDEFINED) {
|
||||
fundsFoundDate = Calendar.getInstance().apply { timeInMillis = msWhenFundsWasFound }
|
||||
}
|
||||
}
|
||||
|
||||
fun foundWalletWithFunds() {
|
||||
if (fundsFoundDate != null) return
|
||||
|
||||
fundsFoundDate = Calendar.getInstance()
|
||||
preferences.edit(true) {
|
||||
putLong(K_FUNDS_FOUND_DATE, fundsFoundDate!!.timeInMillis).apply()
|
||||
putInt(K_SHOW_RATING_AT_LAUNCH_COUNT, launchCounts + firstShowing)
|
||||
}
|
||||
}
|
||||
|
||||
fun isReadyToShow(): Boolean {
|
||||
val fundsDate = fundsFoundDate ?: return false
|
||||
|
||||
if (!userWasInteractWithRating()) {
|
||||
val diff = Calendar.getInstance().timeInMillis - fundsDate.timeInMillis
|
||||
val diffInDays = diff / DAY_MILLIS
|
||||
return launchCounts >= getCounterOfNextShowing() && diffInDays >= firstShowing
|
||||
}
|
||||
|
||||
val nextShowing = getCounterOfNextShowing()
|
||||
return launchCounts >= nextShowing
|
||||
}
|
||||
|
||||
fun applyDelayedShowing() {
|
||||
updateNextShowing(launchCounts + deferShowing)
|
||||
}
|
||||
|
||||
fun setNeverToShow() {
|
||||
updateNextShowing(Int.MAX_VALUE)
|
||||
}
|
||||
|
||||
private fun updateNextShowing(at: Int) {
|
||||
val editor = preferences.edit()
|
||||
editor.putInt(K_SHOW_RATING_AT_LAUNCH_COUNT, at)
|
||||
editor.putBoolean(K_USER_WAS_INTERACT_WITH_RATING, true)
|
||||
editor.apply()
|
||||
}
|
||||
|
||||
private fun userWasInteractWithRating(): Boolean = preferences.getBoolean(K_USER_WAS_INTERACT_WITH_RATING, false)
|
||||
|
||||
private fun getCounterOfNextShowing(): Int = preferences.getInt(K_SHOW_RATING_AT_LAUNCH_COUNT, firstShowing)
|
||||
|
||||
companion object {
|
||||
private const val K_SHOW_RATING_AT_LAUNCH_COUNT = "showRatingDialogAtLaunchCount"
|
||||
private const val K_FUNDS_FOUND_DATE = "fundsFoundDate"
|
||||
private const val K_USER_WAS_INTERACT_WITH_RATING = "userWasInteractWithRating"
|
||||
private const val FUNDS_FOUND_DATE_UNDEFINED = -1L
|
||||
private const val DAY_MILLIS = 1000 * 60 * 60 * 24
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,21 @@
|
|||
package com.tangem.tap.persistence
|
||||
package com.tangem.data.source.preferences
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import androidx.core.content.edit
|
||||
import com.tangem.common.json.MoshiJsonConverter
|
||||
import com.tangem.datasource.api.common.BigDecimalAdapter
|
||||
import java.util.*
|
||||
import com.tangem.data.source.preferences.adapters.BigDecimalAdapter
|
||||
import com.tangem.data.source.preferences.adapters.CardBalanceStateAdapter
|
||||
import com.tangem.data.source.preferences.storage.DisclaimerPrefStorage
|
||||
import com.tangem.data.source.preferences.storage.FiatCurrenciesPrefStorage
|
||||
import com.tangem.data.source.preferences.storage.ToppedUpWalletStorage
|
||||
import com.tangem.data.source.preferences.storage.UsedCardsPrefStorage
|
||||
import javax.inject.Inject
|
||||
|
||||
class PreferencesStorage(applicationContext: Application) {
|
||||
// 🔥FIXME: Only logic to work with preferences must be here, must be separated to repositories
|
||||
// TODO: Replace shared preferences with DataStore
|
||||
@Deprecated("Create repository instead")
|
||||
class PreferencesDataSource @Inject internal constructor(applicationContext: Context) {
|
||||
|
||||
val appRatingLaunchObserver: AppRatingLaunchObserver
|
||||
val usedCardsPrefStorage: UsedCardsPrefStorage
|
||||
|
|
@ -73,8 +80,6 @@ class PreferencesStorage(applicationContext: Application) {
|
|||
putBoolean(OPEN_WELCOME_ON_RESUME_KEY, value)
|
||||
}
|
||||
|
||||
fun getCountOfLaunches(): Int = preferences.getInt(APP_LAUNCH_COUNT_KEY, 1)
|
||||
|
||||
fun saveTwinsOnboardingShown() {
|
||||
preferences.edit { putBoolean(TWINS_ONBOARDING_SHOWN_KEY, true) }
|
||||
}
|
||||
|
|
@ -83,6 +88,8 @@ class PreferencesStorage(applicationContext: Application) {
|
|||
return preferences.getBoolean(TWINS_ONBOARDING_SHOWN_KEY, false)
|
||||
}
|
||||
|
||||
private fun getCountOfLaunches(): Int = preferences.getInt(APP_LAUNCH_COUNT_KEY, 1)
|
||||
|
||||
private fun incrementLaunchCounter() {
|
||||
var count = preferences.getInt(APP_LAUNCH_COUNT_KEY, 0)
|
||||
preferences.edit { putInt(APP_LAUNCH_COUNT_KEY, ++count) }
|
||||
|
|
@ -100,72 +107,4 @@ class PreferencesStorage(applicationContext: Application) {
|
|||
private const val APPLICATION_STOPPED_KEY = "applicationStopped"
|
||||
private const val OPEN_WELCOME_ON_RESUME_KEY = "openWelcomeOnResume"
|
||||
}
|
||||
}
|
||||
|
||||
class AppRatingLaunchObserver(
|
||||
private val preferences: SharedPreferences,
|
||||
private val launchCounts: Int,
|
||||
) {
|
||||
|
||||
private val deferShowing = 20
|
||||
private val firstShowing = 3
|
||||
private var fundsFoundDate: Calendar? = null
|
||||
|
||||
init {
|
||||
val msWhenFundsWasFound = preferences.getLong(K_FUNDS_FOUND_DATE, FUNDS_FOUND_DATE_UNDEFINED)
|
||||
if (msWhenFundsWasFound != FUNDS_FOUND_DATE_UNDEFINED) {
|
||||
fundsFoundDate = Calendar.getInstance().apply { timeInMillis = msWhenFundsWasFound }
|
||||
}
|
||||
}
|
||||
|
||||
fun foundWalletWithFunds() {
|
||||
if (fundsFoundDate != null) return
|
||||
|
||||
fundsFoundDate = Calendar.getInstance()
|
||||
preferences.edit(true) {
|
||||
putLong(K_FUNDS_FOUND_DATE, fundsFoundDate!!.timeInMillis).apply()
|
||||
putInt(K_SHOW_RATING_AT_LAUNCH_COUNT, launchCounts + firstShowing)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
fun isReadyToShow(): Boolean {
|
||||
val fundsDate = fundsFoundDate ?: return false
|
||||
|
||||
if (!userWasInteractWithRating()) {
|
||||
val diff = Calendar.getInstance().timeInMillis - fundsDate.timeInMillis
|
||||
val diffInDays = diff / (1000 * 60 * 60 * 24)
|
||||
return launchCounts >= getCounterOfNextShowing() && diffInDays >= firstShowing
|
||||
}
|
||||
|
||||
val nextShowing = getCounterOfNextShowing()
|
||||
return launchCounts >= nextShowing
|
||||
}
|
||||
|
||||
fun applyDelayedShowing() {
|
||||
updateNextShowing(launchCounts + deferShowing)
|
||||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
fun setNeverToShow() {
|
||||
updateNextShowing(999999999)
|
||||
}
|
||||
|
||||
private fun updateNextShowing(at: Int) {
|
||||
val editor = preferences.edit()
|
||||
editor.putInt(K_SHOW_RATING_AT_LAUNCH_COUNT, at)
|
||||
editor.putBoolean(K_USER_WAS_INTERACT_WITH_RATING, true)
|
||||
editor.apply()
|
||||
}
|
||||
|
||||
private fun userWasInteractWithRating(): Boolean = preferences.getBoolean(K_USER_WAS_INTERACT_WITH_RATING, false)
|
||||
|
||||
private fun getCounterOfNextShowing(): Int = preferences.getInt(K_SHOW_RATING_AT_LAUNCH_COUNT, firstShowing)
|
||||
|
||||
companion object {
|
||||
private const val K_SHOW_RATING_AT_LAUNCH_COUNT = "showRatingDialogAtLaunchCount"
|
||||
private const val K_FUNDS_FOUND_DATE = "fundsFoundDate"
|
||||
private const val K_USER_WAS_INTERACT_WITH_RATING = "userWasInteractWithRating"
|
||||
private const val FUNDS_FOUND_DATE_UNDEFINED = -1L
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.tangem.data.source.preferences.adapters
|
||||
|
||||
import com.squareup.moshi.FromJson
|
||||
import com.squareup.moshi.ToJson
|
||||
import java.math.BigDecimal
|
||||
|
||||
class BigDecimalAdapter {
|
||||
@FromJson
|
||||
fun fromJson(value: String) = BigDecimal(value)
|
||||
|
||||
@ToJson
|
||||
fun toJson(value: BigDecimal) = value.toString()
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.tangem.data.source.preferences.adapters
|
||||
|
||||
import com.squareup.moshi.FromJson
|
||||
import com.squareup.moshi.ToJson
|
||||
import com.tangem.data.source.preferences.model.DataSourceTopupInfo
|
||||
|
||||
class CardBalanceStateAdapter {
|
||||
|
||||
@ToJson
|
||||
fun toJson(src: DataSourceTopupInfo.CardBalanceState): String = src.serializedName
|
||||
|
||||
@FromJson
|
||||
fun fromJson(json: String): DataSourceTopupInfo.CardBalanceState {
|
||||
return when (json) {
|
||||
DataSourceTopupInfo.CardBalanceState.Empty.serializedName -> DataSourceTopupInfo.CardBalanceState.Empty
|
||||
DataSourceTopupInfo.CardBalanceState.Full.serializedName -> DataSourceTopupInfo.CardBalanceState.Full
|
||||
else -> error("CardBalanceState not found")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package com.tangem.data.source.preferences.di
|
||||
|
||||
import android.content.Context
|
||||
import com.tangem.data.source.preferences.PreferencesDataSource
|
||||
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
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal object PreferencesStoreModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providePreferencesStore(@ApplicationContext context: Context) = PreferencesDataSource(context)
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package com.tangem.data.source.preferences.model
|
||||
|
||||
data class DataSourceCurrency(
|
||||
val id: String,
|
||||
val code: String,
|
||||
val name: String,
|
||||
val rateBTC: String,
|
||||
val unit: String,
|
||||
val type: String,
|
||||
)
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package com.tangem.data.source.preferences.model
|
||||
|
||||
data class DataSourceFiatCurrency(
|
||||
val code: String,
|
||||
val name: String,
|
||||
val symbol: String,
|
||||
)
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.tangem.data.source.preferences.model
|
||||
|
||||
data class DataSourceTopupInfo(
|
||||
val walletId: String,
|
||||
val cardBalanceState: CardBalanceState,
|
||||
) {
|
||||
enum class CardBalanceState(val serializedName: String) {
|
||||
Empty(serializedName = "Empty"),
|
||||
Full(serializedName = "Full"),
|
||||
CustomToken(serializedName = "Custom token"),
|
||||
BlockchainError(serializedName = "Blockchain error"),
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package com.tangem.data.source.preferences.model
|
||||
|
||||
internal data class DataSourceUsedCardInfo(
|
||||
val cardId: String,
|
||||
val isScanned: Boolean = false,
|
||||
val isActivationStarted: Boolean = false,
|
||||
val isActivationFinished: Boolean = false,
|
||||
)
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package com.tangem.data.source.preferences.model
|
||||
|
||||
internal data class DataSourceUsedCardInfoOld(
|
||||
val cardId: String,
|
||||
val isScanned: Boolean = false,
|
||||
val isActivationStarted: Boolean = false,
|
||||
)
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.tap.persistence
|
||||
package com.tangem.data.source.preferences.storage
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.core.content.edit
|
||||
|
|
@ -6,7 +6,8 @@ import androidx.core.content.edit
|
|||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class DisclaimerPrefStorage(
|
||||
@Deprecated("Create repository instead")
|
||||
class DisclaimerPrefStorage internal constructor(
|
||||
private val preferences: SharedPreferences,
|
||||
) {
|
||||
|
||||
|
|
@ -1,15 +1,16 @@
|
|||
package com.tangem.tap.persistence
|
||||
package com.tangem.data.source.preferences.storage
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.core.content.edit
|
||||
import com.tangem.common.json.MoshiJsonConverter
|
||||
import com.tangem.datasource.api.tangemTech.models.CurrenciesResponse
|
||||
import com.tangem.tap.common.entities.FiatCurrency
|
||||
import com.tangem.data.source.preferences.model.DataSourceCurrency
|
||||
import com.tangem.data.source.preferences.model.DataSourceFiatCurrency
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class FiatCurrenciesPrefStorage(
|
||||
@Deprecated("Create repository instead")
|
||||
class FiatCurrenciesPrefStorage internal constructor(
|
||||
private val preferences: SharedPreferences,
|
||||
private val converter: MoshiJsonConverter,
|
||||
) {
|
||||
|
|
@ -20,26 +21,26 @@ class FiatCurrenciesPrefStorage(
|
|||
}
|
||||
}
|
||||
|
||||
fun getAppCurrency(): FiatCurrency {
|
||||
fun getAppCurrency(): DataSourceFiatCurrency? {
|
||||
val json = preferences.getString(APP_CURRENCY_KEY, "")
|
||||
if (json.isNullOrBlank()) return FiatCurrency.Default
|
||||
if (json.isNullOrBlank()) return null
|
||||
|
||||
return converter.fromJson(json) ?: FiatCurrency.Default
|
||||
return converter.fromJson(json)
|
||||
}
|
||||
|
||||
fun saveAppCurrency(fiatCurrency: FiatCurrency) {
|
||||
fun saveAppCurrency(fiatCurrency: DataSourceFiatCurrency) {
|
||||
val json = converter.toJson(fiatCurrency)
|
||||
preferences.edit { putString(APP_CURRENCY_KEY, json) }
|
||||
}
|
||||
|
||||
fun save(currencies: List<CurrenciesResponse.Currency>) {
|
||||
fun save(currencies: List<DataSourceCurrency>) {
|
||||
val json: String = converter.toJson(currencies)
|
||||
return preferences.edit().putString(FIAT_CURRENCIES_KEY, json).apply()
|
||||
}
|
||||
|
||||
fun restore(): List<CurrenciesResponse.Currency> {
|
||||
fun restore(): List<DataSourceCurrency> {
|
||||
val json = preferences.getString(FIAT_CURRENCIES_KEY, "")
|
||||
val type = converter.typedList(CurrenciesResponse.Currency::class.java)
|
||||
val type = converter.typedList(DataSourceCurrency::class.java)
|
||||
if (json.isNullOrBlank()) return emptyList()
|
||||
|
||||
return converter.fromJson(json, type) ?: emptyList()
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package com.tangem.data.source.preferences.storage
|
||||
|
||||
internal interface Migration {
|
||||
fun migrate()
|
||||
}
|
||||
|
|
@ -1,51 +1,50 @@
|
|||
package com.tangem.tap.persistence
|
||||
package com.tangem.data.source.preferences.storage
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.core.content.edit
|
||||
import com.tangem.common.json.MoshiJsonConverter
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import timber.log.Timber
|
||||
import com.tangem.data.source.preferences.model.DataSourceTopupInfo
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class ToppedUpWalletStorage(
|
||||
@Deprecated("Create repository instead")
|
||||
class ToppedUpWalletStorage internal constructor(
|
||||
private val preferences: SharedPreferences,
|
||||
private val jsonConverter: MoshiJsonConverter,
|
||||
) {
|
||||
|
||||
private val walletList: MutableSet<TopupInfo> = mutableSetOf()
|
||||
private val walletList: MutableSet<DataSourceTopupInfo> = mutableSetOf()
|
||||
|
||||
init {
|
||||
walletList.addAll(restore())
|
||||
}
|
||||
|
||||
fun save(userWalletInfo: TopupInfo): Boolean {
|
||||
fun save(userWalletInfo: DataSourceTopupInfo): Boolean {
|
||||
walletList.removeAll { it.walletId == userWalletInfo.walletId }
|
||||
walletList.add(userWalletInfo)
|
||||
return save(walletList)
|
||||
}
|
||||
|
||||
fun restore(walletId: String): TopupInfo? {
|
||||
fun restore(walletId: String): DataSourceTopupInfo? {
|
||||
return walletList.firstOrNull { it.walletId == walletId }
|
||||
}
|
||||
|
||||
private fun save(userWallets: MutableSet<TopupInfo>): Boolean {
|
||||
private fun save(userWallets: MutableSet<DataSourceTopupInfo>): Boolean {
|
||||
return try {
|
||||
val json = jsonConverter.toJson(userWallets)
|
||||
preferences.edit(true) { putString(KEY, json) }
|
||||
true
|
||||
} catch (ex: Exception) {
|
||||
Timber.e(ex)
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun restore(): MutableSet<TopupInfo> {
|
||||
private fun restore(): MutableSet<DataSourceTopupInfo> {
|
||||
val json = preferences.getString(KEY, null) ?: return mutableSetOf()
|
||||
return try {
|
||||
val typedList = jsonConverter.typedList(TopupInfo::class.java)
|
||||
val listData = jsonConverter.fromJson<List<TopupInfo>>(json, typedList)!!
|
||||
val typedList = jsonConverter.typedList(DataSourceTopupInfo::class.java)
|
||||
val listData = jsonConverter.fromJson<List<DataSourceTopupInfo>>(json, typedList)!!
|
||||
listData.toMutableSet()
|
||||
} catch (ex: Exception) {
|
||||
preferences.edit(true) { remove(KEY) }
|
||||
|
|
@ -53,13 +52,6 @@ class ToppedUpWalletStorage(
|
|||
}
|
||||
}
|
||||
|
||||
data class TopupInfo(
|
||||
val walletId: String,
|
||||
val cardBalanceState: AnalyticsParam.CardBalanceState,
|
||||
) {
|
||||
val isToppedUp: Boolean = cardBalanceState == AnalyticsParam.CardBalanceState.Full
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val KEY = "userWalletsInfo"
|
||||
}
|
||||
|
|
@ -1,15 +1,16 @@
|
|||
package com.tangem.tap.persistence
|
||||
package com.tangem.data.source.preferences.storage
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.core.content.edit
|
||||
import com.tangem.common.json.MoshiJsonConverter
|
||||
import com.tangem.tap.common.extensions.replaceByOrAdd
|
||||
import timber.log.Timber
|
||||
import com.tangem.data.source.preferences.model.DataSourceUsedCardInfo
|
||||
import com.tangem.data.source.preferences.model.DataSourceUsedCardInfoOld
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class UsedCardsPrefStorage(
|
||||
@Deprecated("Create repository instead")
|
||||
class UsedCardsPrefStorage internal constructor(
|
||||
private val preferences: SharedPreferences,
|
||||
private val jsonConverter: MoshiJsonConverter,
|
||||
) {
|
||||
|
|
@ -26,7 +27,7 @@ class UsedCardsPrefStorage(
|
|||
fun scanned(cardId: String) {
|
||||
val restoredList = restore()
|
||||
val foundItem = findCardInfo(cardId, restoredList)?.copy(isScanned = true)
|
||||
?: UsedCardInfo(cardId, true)
|
||||
?: DataSourceUsedCardInfo(cardId, true)
|
||||
|
||||
save(foundItem, restoredList)
|
||||
}
|
||||
|
|
@ -38,14 +39,14 @@ class UsedCardsPrefStorage(
|
|||
fun activationStarted(cardId: String) {
|
||||
val restoredList = restore()
|
||||
val foundItem = findCardInfo(cardId, restoredList)?.copy(isActivationStarted = true)
|
||||
?: UsedCardInfo(cardId, isActivationStarted = true)
|
||||
?: DataSourceUsedCardInfo(cardId, isActivationStarted = true)
|
||||
|
||||
save(foundItem, restoredList)
|
||||
}
|
||||
|
||||
fun activationFinished(cardId: String) {
|
||||
val restoredList = restore()
|
||||
var foundItem = findCardInfo(cardId, restoredList) ?: UsedCardInfo(cardId)
|
||||
var foundItem = findCardInfo(cardId, restoredList) ?: DataSourceUsedCardInfo(cardId)
|
||||
foundItem = foundItem.copy(
|
||||
isActivationStarted = true,
|
||||
isActivationFinished = true,
|
||||
|
|
@ -67,33 +68,38 @@ class UsedCardsPrefStorage(
|
|||
return cardInfo.isActivationStarted && !cardInfo.isActivationFinished
|
||||
}
|
||||
|
||||
private fun findCardInfo(cardId: String, list: MutableList<UsedCardInfo>? = null): UsedCardInfo? {
|
||||
private fun findCardInfo(
|
||||
cardId: String,
|
||||
list: MutableList<DataSourceUsedCardInfo>? = null,
|
||||
): DataSourceUsedCardInfo? {
|
||||
val findInList = list ?: restore()
|
||||
return findInList.firstOrNull { it.cardId == cardId }
|
||||
}
|
||||
|
||||
private fun save(usedCardInfo: UsedCardInfo?, usedCardsInfo: MutableList<UsedCardInfo>) {
|
||||
private fun save(usedCardInfo: DataSourceUsedCardInfo?, usedCardsInfo: MutableList<DataSourceUsedCardInfo>) {
|
||||
val info = usedCardInfo ?: return
|
||||
|
||||
usedCardsInfo.replaceByOrAdd(info) { it.cardId == info.cardId }
|
||||
with(usedCardsInfo) {
|
||||
val index = indexOfFirst { it.cardId == info.cardId }
|
||||
if (index == -1) {
|
||||
add(info)
|
||||
} else {
|
||||
set(index, info)
|
||||
}
|
||||
}
|
||||
|
||||
save(usedCardsInfo)
|
||||
}
|
||||
|
||||
private fun save(list: MutableList<UsedCardInfo>): Boolean {
|
||||
return try {
|
||||
val json = jsonConverter.toJson(list)
|
||||
preferences.edit { putString(USED_CARDS_INFO_V2, json) }
|
||||
true
|
||||
} catch (ex: Exception) {
|
||||
Timber.e(ex)
|
||||
false
|
||||
}
|
||||
private fun save(list: MutableList<DataSourceUsedCardInfo>) {
|
||||
val json = jsonConverter.toJson(list)
|
||||
preferences.edit { putString(USED_CARDS_INFO_V2, json) }
|
||||
}
|
||||
|
||||
private fun restore(): MutableList<UsedCardInfo> {
|
||||
private fun restore(): MutableList<DataSourceUsedCardInfo> {
|
||||
val json = preferences.getString(USED_CARDS_INFO_V2, null) ?: return mutableListOf()
|
||||
return try {
|
||||
jsonConverter.fromJson(json, jsonConverter.typedList(UsedCardInfo::class.java))!!
|
||||
jsonConverter.fromJson(json, jsonConverter.typedList(DataSourceUsedCardInfo::class.java))!!
|
||||
} catch (ex: Exception) {
|
||||
preferences.edit(true) { remove(USED_CARDS_INFO_V2) }
|
||||
mutableListOf()
|
||||
|
|
@ -113,7 +119,7 @@ class UsedCardsPrefStorage(
|
|||
if (restoredCardsInfo.isEmpty()) return
|
||||
|
||||
val newCardsInfo = restoredCardsInfo.map { cardInfo ->
|
||||
UsedCardInfo(
|
||||
DataSourceUsedCardInfo(
|
||||
cardId = cardInfo.cardId,
|
||||
isScanned = cardInfo.isScanned,
|
||||
isActivationStarted = true,
|
||||
|
|
@ -123,10 +129,13 @@ class UsedCardsPrefStorage(
|
|||
storage.save(newCardsInfo)
|
||||
}
|
||||
|
||||
private fun restore(): MutableList<UsedCardInfoOld> {
|
||||
private fun restore(): MutableList<DataSourceUsedCardInfoOld> {
|
||||
val json = storage.preferences.getString(USED_CARDS_INFO, null) ?: return mutableListOf()
|
||||
return try {
|
||||
storage.jsonConverter.fromJson(json, storage.jsonConverter.typedList(UsedCardInfoOld::class.java))!!
|
||||
storage.jsonConverter.fromJson(
|
||||
json,
|
||||
storage.jsonConverter.typedList(DataSourceUsedCardInfoOld::class.java),
|
||||
)!!
|
||||
} catch (ex: Exception) {
|
||||
mutableListOf()
|
||||
} finally {
|
||||
|
|
@ -134,21 +143,4 @@ class UsedCardsPrefStorage(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private data class UsedCardInfo(
|
||||
val cardId: String,
|
||||
val isScanned: Boolean = false,
|
||||
val isActivationStarted: Boolean = false,
|
||||
val isActivationFinished: Boolean = false,
|
||||
)
|
||||
|
||||
private data class UsedCardInfoOld(
|
||||
val cardId: String,
|
||||
val isScanned: Boolean = false,
|
||||
val isActivationStarted: Boolean = false,
|
||||
)
|
||||
}
|
||||
|
||||
private interface Migration {
|
||||
fun migrate()
|
||||
}
|
||||
|
|
@ -69,4 +69,8 @@ include(":domain:legacy")
|
|||
|
||||
include(":domain:core")
|
||||
include(":domain:card")
|
||||
// endregion Domain modules
|
||||
// endregion Domain modules
|
||||
|
||||
// region Data modules
|
||||
include(":data:source:preferences")
|
||||
// endregion Data modules
|
||||
Loading…
Add table
Add a link
Reference in a new issue