Updated on 2026-08-14
This commit is contained in:
parent
e2791d9b35
commit
afcde269ce
24 changed files with 243 additions and 131 deletions
|
|
@ -34,6 +34,7 @@ import com.tangem.domain.tokens.repository.CurrenciesRepository
|
|||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.legacy.WalletManagersRepository
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import com.tangem.features.tokendetails.featuretoggles.TokenDetailsFeatureToggles
|
||||
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
|
||||
import com.tangem.tap.common.analytics.AnalyticsFactory
|
||||
|
|
@ -44,6 +45,7 @@ import com.tangem.tap.common.analytics.handlers.appsFlyer.AppsFlyerAnalyticsHand
|
|||
import com.tangem.tap.common.analytics.handlers.firebase.FirebaseAnalyticsHandler
|
||||
import com.tangem.tap.common.analytics.topup.TopUpController
|
||||
import com.tangem.tap.common.chat.ChatManager
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.feedback.AdditionalFeedbackInfo
|
||||
import com.tangem.tap.common.feedback.FeedbackManager
|
||||
import com.tangem.tap.common.images.createCoilImageLoader
|
||||
|
|
@ -207,34 +209,15 @@ internal class TapApplication : Application(), ImageLoaderFactory {
|
|||
|
||||
@Inject
|
||||
lateinit var getAppThemeModeUseCase: GetAppThemeModeUseCase
|
||||
|
||||
@Inject
|
||||
lateinit var walletsRepository: WalletsRepository
|
||||
// endregion Injected
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
store = Store(
|
||||
reducer = { action, state -> appReducer(action, state, appStateHolder) },
|
||||
middleware = AppState.getMiddleware(),
|
||||
state = AppState(
|
||||
daggerGraphState = DaggerGraphState(
|
||||
assetReader = assetReader,
|
||||
networkConnectionManager = networkConnectionManager,
|
||||
customTokenFeatureToggles = customTokenFeatureToggles,
|
||||
walletFeatureToggles = walletFeatureToggles,
|
||||
walletConnectRepository = walletConnect2Repository,
|
||||
walletConnectSessionsRepository = walletConnectSessionsRepository,
|
||||
tokenDetailsFeatureToggles = tokenDetailsFeatureToggles,
|
||||
scanCardProcessor = scanCardProcessor,
|
||||
appCurrencyRepository = appCurrencyRepository,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
appStateHolder = appStateHolder,
|
||||
currenciesRepository = currenciesRepository,
|
||||
appThemeModeRepository = appThemeModeRepository,
|
||||
balanceHidingRepository = balanceHidingRepository,
|
||||
detailsFeatureToggles = detailsFeatureToggles,
|
||||
),
|
||||
),
|
||||
)
|
||||
store = createReduxStore()
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
Logger.addLogAdapter(AndroidLogAdapter(TimberFormatStrategy()))
|
||||
|
|
@ -254,17 +237,17 @@ internal class TapApplication : Application(), ImageLoaderFactory {
|
|||
preferencesStorage = preferencesDataSource
|
||||
walletConnectRepository = WalletConnectRepository(this)
|
||||
|
||||
val configLoader = FeaturesLocalLoader(assetReader, MoshiConverter.sdkMoshi, BuildConfig.ENVIRONMENT)
|
||||
initUserWalletsListManager()
|
||||
|
||||
// TODO: Try to performance and user experience.
|
||||
// [REDACTED_JIRA]
|
||||
runBlocking {
|
||||
initUserWalletsListManager()
|
||||
featureTogglesManager.init()
|
||||
appRatingRepository.initialize()
|
||||
walletsRepository.initialize()
|
||||
// learn2earnInteractor.init()
|
||||
}
|
||||
|
||||
val configLoader = FeaturesLocalLoader(assetReader, MoshiConverter.sdkMoshi, BuildConfig.ENVIRONMENT)
|
||||
initConfigManager(configLoader, ::initWithConfigDependency)
|
||||
initWarningMessagesManager()
|
||||
|
||||
|
|
@ -296,6 +279,33 @@ internal class TapApplication : Application(), ImageLoaderFactory {
|
|||
walletConnect2Repository.init(projectId = configManager.config.walletConnectProjectId)
|
||||
}
|
||||
|
||||
private fun createReduxStore(): Store<AppState> {
|
||||
return Store(
|
||||
reducer = { action, state -> appReducer(action, state, appStateHolder) },
|
||||
middleware = AppState.getMiddleware(),
|
||||
state = AppState(
|
||||
daggerGraphState = DaggerGraphState(
|
||||
assetReader = assetReader,
|
||||
networkConnectionManager = networkConnectionManager,
|
||||
customTokenFeatureToggles = customTokenFeatureToggles,
|
||||
walletFeatureToggles = walletFeatureToggles,
|
||||
walletConnectRepository = walletConnect2Repository,
|
||||
walletConnectSessionsRepository = walletConnectSessionsRepository,
|
||||
tokenDetailsFeatureToggles = tokenDetailsFeatureToggles,
|
||||
scanCardProcessor = scanCardProcessor,
|
||||
appCurrencyRepository = appCurrencyRepository,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
appStateHolder = appStateHolder,
|
||||
currenciesRepository = currenciesRepository,
|
||||
appThemeModeRepository = appThemeModeRepository,
|
||||
balanceHidingRepository = balanceHidingRepository,
|
||||
detailsFeatureToggles = detailsFeatureToggles,
|
||||
walletsRepository = walletsRepository,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun initTopUpController() {
|
||||
val topUpController = TopUpController(
|
||||
scanResponseProvider = {
|
||||
|
|
@ -356,11 +366,7 @@ internal class TapApplication : Application(), ImageLoaderFactory {
|
|||
store: Store<AppState>,
|
||||
) {
|
||||
fun initAdditionalFeedbackInfo(context: Context): AdditionalFeedbackInfo {
|
||||
return AdditionalFeedbackInfo(
|
||||
userWalletsListManager = userWalletsListManager,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
walletFeatureToggles = walletFeatureToggles,
|
||||
).apply {
|
||||
return AdditionalFeedbackInfo().apply {
|
||||
appVersion = try {
|
||||
// TODO don't use deprecated method
|
||||
val pInfo = context.packageManager.getPackageInfo(context.packageName, 0)
|
||||
|
|
@ -403,13 +409,13 @@ internal class TapApplication : Application(), ImageLoaderFactory {
|
|||
store.dispatch(GlobalAction.SetWarningManager(WarningMessagesManager()))
|
||||
}
|
||||
|
||||
private fun initUserWalletsListManager() {
|
||||
val manager = if (preferencesStorage.shouldSaveUserWallets) {
|
||||
private suspend fun initUserWalletsListManager() {
|
||||
val manager = if (walletsRepository.shouldSaveUserWalletsSync()) {
|
||||
UserWalletsListManager.provideBiometricImplementation(applicationContext)
|
||||
} else {
|
||||
UserWalletsListManager.provideRuntimeImplementation()
|
||||
}
|
||||
|
||||
store.dispatch(GlobalAction.UpdateUserWalletsListManager(manager))
|
||||
store.dispatchOnMain(GlobalAction.UpdateUserWalletsListManager(manager))
|
||||
}
|
||||
}
|
||||
|
|
@ -6,35 +6,10 @@ import com.tangem.blockchain.common.address.Address
|
|||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.userwallets.UserWalletIdBuilder
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
|
||||
import com.tangem.tap.common.extensions.stripZeroPlainString
|
||||
import com.tangem.tap.scope
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
||||
class AdditionalFeedbackInfo(
|
||||
userWalletsListManager: UserWalletsListManager,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
walletFeatureToggles: WalletFeatureToggles,
|
||||
) {
|
||||
|
||||
init {
|
||||
if (walletFeatureToggles.isRedesignedScreenEnabled) {
|
||||
userWalletsListManager.selectedUserWallet
|
||||
.distinctUntilChanged()
|
||||
.onEach { userWallet ->
|
||||
setCardInfo(data = userWallet.scanResponse)
|
||||
|
||||
walletManagersFacade.getAll(userWalletId = userWallet.walletId)
|
||||
.onEach(::setWalletsInfo)
|
||||
.launchIn(scope)
|
||||
}
|
||||
.launchIn(scope)
|
||||
}
|
||||
}
|
||||
class AdditionalFeedbackInfo {
|
||||
|
||||
class EmailWalletInfo(
|
||||
var blockchain: Blockchain = Blockchain.Unknown,
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ import com.tangem.tap.proxy.redux.DaggerGraphState
|
|||
import com.tangem.tap.scope
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.tap.walletCurrenciesManager
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import org.rekotlin.Action
|
||||
import org.rekotlin.DispatchFunction
|
||||
|
|
@ -174,6 +175,26 @@ private fun handleAction(action: Action, appState: () -> AppState?, dispatch: Di
|
|||
is GlobalAction.SetTopUpController -> {
|
||||
walletCurrenciesManager.addListener(action.topUpController)
|
||||
}
|
||||
is GlobalAction.UpdateUserWalletsListManager -> {
|
||||
/*
|
||||
* If UserWalletsListManager's implementation is changed,
|
||||
* then all selectedUserWallet's observers is became irrelevant
|
||||
*/
|
||||
action.manager.selectedUserWallet
|
||||
.distinctUntilChanged()
|
||||
.onEach { userWallet ->
|
||||
store.state.globalState.feedbackManager?.infoHolder?.let { infoHolder ->
|
||||
infoHolder.setCardInfo(data = userWallet.scanResponse)
|
||||
|
||||
store.state.daggerGraphState.get(DaggerGraphState::walletManagersFacade)
|
||||
.getAll(userWalletId = userWallet.walletId)
|
||||
.onEach(infoHolder::setWalletsInfo)
|
||||
.launchIn(scope)
|
||||
}
|
||||
}
|
||||
.flowOn(Dispatchers.IO)
|
||||
.launchIn(scope)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -68,6 +68,14 @@ internal object WalletsDomainModule {
|
|||
return DeleteWalletUseCase(walletsStateHolder = walletsStateHolder)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ViewModelScoped
|
||||
fun providesShouldSaveUserWalletsSyncUseCase(
|
||||
walletsRepository: WalletsRepository,
|
||||
): ShouldSaveUserWalletsSyncUseCase {
|
||||
return ShouldSaveUserWalletsSyncUseCase(walletsRepository = walletsRepository)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ViewModelScoped
|
||||
fun providesShouldSaveUserWalletsUseCase(walletsRepository: WalletsRepository): ShouldSaveUserWalletsUseCase {
|
||||
|
|
|
|||
|
|
@ -81,7 +81,8 @@ class TapWalletManager(
|
|||
store.dispatchWalletAction(action = WalletAction.UserWalletChanged(userWallet))
|
||||
store.dispatchWalletAction(
|
||||
action = WalletAction.UpdateCanSaveUserWallets(
|
||||
canSaveUserWallets = preferencesStorage.shouldSaveUserWallets,
|
||||
canSaveUserWallets = store.state.daggerGraphState.get(DaggerGraphState::walletsRepository)
|
||||
.shouldSaveUserWalletsSync(),
|
||||
),
|
||||
)
|
||||
store.dispatch(TwinCardsAction.IfTwinsPrepareState(scanResponse))
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ sealed class DetailsAction : Action {
|
|||
data class PrepareScreen(
|
||||
val scanResponse: ScanResponse,
|
||||
val darkThemeSwitchEnabled: Boolean,
|
||||
val shouldSaveUserWallets: Boolean,
|
||||
) : DetailsAction()
|
||||
|
||||
object ReCreateTwinsWallet : DetailsAction()
|
||||
|
|
|
|||
|
|
@ -291,7 +291,8 @@ class DetailsMiddleware {
|
|||
|
||||
private fun toggleSaveWallets(state: DetailsState, enable: Boolean) = scope.launch {
|
||||
// Nothing to change
|
||||
if (preferencesStorage.shouldSaveUserWallets == enable) {
|
||||
val walletsRepository = store.state.daggerGraphState.get(DaggerGraphState::walletsRepository)
|
||||
if (walletsRepository.shouldSaveUserWalletsSync() == enable) {
|
||||
store.dispatchWithMain(DetailsAction.AppSettings.SwitchPrivacySetting.Success)
|
||||
return@launch
|
||||
}
|
||||
|
|
@ -379,7 +380,8 @@ class DetailsMiddleware {
|
|||
Analytics.send(Settings.AppSettings.SaveWalletSwitcherChanged(AnalyticsParam.OnOffState.On))
|
||||
|
||||
preferencesStorage.shouldShowSaveUserWalletScreen = false
|
||||
preferencesStorage.shouldSaveUserWallets = true
|
||||
store.state.daggerGraphState.get(DaggerGraphState::walletsRepository)
|
||||
.saveShouldSaveUserWallets(item = true)
|
||||
|
||||
store.dispatchWithMain(WalletAction.UpdateCanSaveUserWallets(canSaveUserWallets = true))
|
||||
}
|
||||
|
|
@ -395,7 +397,8 @@ class DetailsMiddleware {
|
|||
Analytics.send(Settings.AppSettings.SaveWalletSwitcherChanged(AnalyticsParam.OnOffState.Off))
|
||||
deleteSavedAccessCodes()
|
||||
updateUserWalletsListManager(enableUserWalletsSaving = false)
|
||||
preferencesStorage.shouldSaveUserWallets = false
|
||||
store.state.daggerGraphState.get(DaggerGraphState::walletsRepository)
|
||||
.saveShouldSaveUserWallets(item = false)
|
||||
|
||||
store.dispatchWithMain(WalletAction.UpdateCanSaveUserWallets(canSaveUserWallets = true))
|
||||
store.dispatchWithMain(NavigationAction.PopBackTo(AppScreen.Home))
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ private fun handlePrepareScreen(action: DetailsAction.PrepareScreen): DetailsSta
|
|||
createBackupAllowed = action.scanResponse.card.backupStatus == CardDTO.BackupStatus.NoBackup,
|
||||
appSettingsState = AppSettingsState(
|
||||
isBiometricsAvailable = tangemSdkManager.canUseBiometry,
|
||||
saveWallets = preferencesStorage.shouldSaveUserWallets,
|
||||
saveWallets = action.shouldSaveUserWallets,
|
||||
saveAccessCodes = preferencesStorage.shouldSaveAccessCodes,
|
||||
selectedFiatCurrency = store.state.globalState.appCurrency,
|
||||
selectedThemeMode = runBlocking {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import com.tangem.core.analytics.Analytics
|
|||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.core.ui.screen.ComposeFragment
|
||||
import com.tangem.core.ui.theme.AppThemeModeHolder
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import com.tangem.tap.common.analytics.events.Settings
|
||||
import com.tangem.tap.features.details.DarkThemeFeatureToggle
|
||||
import com.tangem.tap.features.details.redux.DetailsState
|
||||
|
|
@ -24,11 +25,14 @@ internal class DetailsFragment : ComposeFragment(), StoreSubscriber<DetailsState
|
|||
@Inject
|
||||
lateinit var darkThemeFeatureToggle: DarkThemeFeatureToggle
|
||||
|
||||
@Inject
|
||||
lateinit var walletsRepository: WalletsRepository
|
||||
|
||||
private lateinit var detailsViewModel: DetailsViewModel
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
detailsViewModel = DetailsViewModel(store, darkThemeFeatureToggle)
|
||||
detailsViewModel = DetailsViewModel(store, darkThemeFeatureToggle, walletsRepository)
|
||||
Analytics.send(Settings.ScreenOpened())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import com.tangem.core.ui.event.consumedEvent
|
|||
import com.tangem.core.ui.event.triggeredEvent
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import com.tangem.tap.common.analytics.events.Settings
|
||||
import com.tangem.tap.common.extensions.dispatchWithMain
|
||||
import com.tangem.tap.common.feedback.FeedbackEmail
|
||||
|
|
@ -36,10 +37,12 @@ import kotlinx.coroutines.flow.launchIn
|
|||
import kotlinx.coroutines.flow.onEach
|
||||
import org.rekotlin.Store
|
||||
|
||||
// TODO: change to Android ViewModel [REDACTED_JIRA]
|
||||
internal class DetailsViewModel(
|
||||
private val store: Store<AppState>,
|
||||
private val darkThemeFeatureToggle: DarkThemeFeatureToggle,
|
||||
) { // TODO: change to Android ViewModel
|
||||
private val walletsRepository: WalletsRepository,
|
||||
) {
|
||||
|
||||
var detailsScreenState: MutableState<DetailsScreenState> = mutableStateOf(updateState(store.state.detailsState))
|
||||
private set
|
||||
|
|
@ -186,8 +189,9 @@ internal class DetailsViewModel(
|
|||
.onEach { selectedUserWallet ->
|
||||
store.dispatchWithMain(
|
||||
DetailsAction.PrepareScreen(
|
||||
selectedUserWallet.scanResponse,
|
||||
darkThemeFeatureToggle.isDarkThemeEnabled,
|
||||
scanResponse = selectedUserWallet.scanResponse,
|
||||
darkThemeSwitchEnabled = darkThemeFeatureToggle.isDarkThemeEnabled,
|
||||
shouldSaveUserWallets = walletsRepository.shouldSaveUserWalletsSync(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import com.tangem.tap.common.extensions.onUserWalletSelected
|
|||
import com.tangem.tap.common.extensions.removeContext
|
||||
import com.tangem.tap.common.extensions.setContext
|
||||
import com.tangem.tap.features.saveWallet.redux.SaveWalletAction
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
|
@ -70,40 +71,39 @@ object OnboardingHelper {
|
|||
backupCardsIds: List<String>? = null,
|
||||
) {
|
||||
Analytics.setContext(scanResponse)
|
||||
when {
|
||||
// When should save user wallets, then save card without navigate to save wallet screen
|
||||
preferencesStorage.shouldSaveUserWallets -> scope.launch {
|
||||
proceedWithScanResponse(scanResponse, backupCardsIds)
|
||||
scope.launch {
|
||||
when {
|
||||
// When should save user wallets, then save card without navigate to save wallet screen
|
||||
store.state.daggerGraphState.get(DaggerGraphState::walletsRepository).shouldSaveUserWalletsSync() -> {
|
||||
proceedWithScanResponse(scanResponse, backupCardsIds)
|
||||
|
||||
store.dispatchOnMain(
|
||||
SaveWalletAction.ProvideBackupInfo(
|
||||
scanResponse = scanResponse,
|
||||
accessCode = accessCode,
|
||||
backupCardsIds = backupCardsIds?.toSet(),
|
||||
),
|
||||
)
|
||||
store.dispatchOnMain(SaveWalletAction.Save)
|
||||
}
|
||||
// When should not save user wallets but device has biometry and save wallet screen has not been shown,
|
||||
// then open save wallet screen
|
||||
tangemSdkManager.canUseBiometry &&
|
||||
preferencesStorage.shouldShowSaveUserWalletScreen -> scope.launch {
|
||||
proceedWithScanResponse(scanResponse, backupCardsIds)
|
||||
store.dispatchOnMain(
|
||||
SaveWalletAction.ProvideBackupInfo(
|
||||
scanResponse = scanResponse,
|
||||
accessCode = accessCode,
|
||||
backupCardsIds = backupCardsIds?.toSet(),
|
||||
),
|
||||
)
|
||||
store.dispatchOnMain(SaveWalletAction.Save)
|
||||
}
|
||||
// When should not save user wallets but device has biometry and save wallet screen has not been shown,
|
||||
// then open save wallet screen
|
||||
tangemSdkManager.canUseBiometry && preferencesStorage.shouldShowSaveUserWalletScreen -> {
|
||||
proceedWithScanResponse(scanResponse, backupCardsIds)
|
||||
|
||||
delay(timeMillis = 1_200)
|
||||
delay(timeMillis = 1_200)
|
||||
|
||||
store.dispatchOnMain(
|
||||
SaveWalletAction.ProvideBackupInfo(
|
||||
scanResponse = scanResponse,
|
||||
accessCode = accessCode,
|
||||
backupCardsIds = backupCardsIds?.toSet(),
|
||||
),
|
||||
)
|
||||
store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.SaveWallet))
|
||||
}
|
||||
// If device has no biometry and save wallet screen has been shown, then go through old scenario
|
||||
else -> scope.launch {
|
||||
proceedWithScanResponse(scanResponse, backupCardsIds)
|
||||
store.dispatchOnMain(
|
||||
SaveWalletAction.ProvideBackupInfo(
|
||||
scanResponse = scanResponse,
|
||||
accessCode = accessCode,
|
||||
backupCardsIds = backupCardsIds?.toSet(),
|
||||
),
|
||||
)
|
||||
store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.SaveWallet))
|
||||
}
|
||||
// If device has no biometry and save wallet screen has been shown, then go through old scenario
|
||||
else -> proceedWithScanResponse(scanResponse, backupCardsIds)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import com.tangem.tap.features.wallet.models.Currency
|
|||
import com.tangem.tap.features.wallet.redux.ProgressState
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.features.wallet.redux.models.WalletDialog
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import org.rekotlin.Action
|
||||
|
|
@ -292,10 +293,14 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
|
|||
OnboardingHelper.trySaveWalletAndNavigateToWalletScreen(scanResponse)
|
||||
}
|
||||
CreateTwinWalletMode.RecreateWallet -> {
|
||||
if (preferencesStorage.shouldSaveUserWallets) {
|
||||
OnboardingHelper.trySaveWalletAndNavigateToWalletScreen(scanResponse)
|
||||
} else {
|
||||
store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Home))
|
||||
scope.launch {
|
||||
val walletsRepository = store.state.daggerGraphState.get(DaggerGraphState::walletsRepository)
|
||||
|
||||
if (walletsRepository.shouldSaveUserWalletsSync()) {
|
||||
OnboardingHelper.trySaveWalletAndNavigateToWalletScreen(scanResponse)
|
||||
} else {
|
||||
store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Home))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,10 +107,11 @@ internal class SaveWalletMiddleware {
|
|||
store.dispatchWithMain(SaveWalletAction.Save.Error(error))
|
||||
}
|
||||
.doOnSuccess {
|
||||
preferencesStorage.shouldSaveUserWallets = true
|
||||
store.state.daggerGraphState.get(DaggerGraphState::walletsRepository)
|
||||
.saveShouldSaveUserWallets(item = true)
|
||||
|
||||
// Enable saving access codes only if this is the first time user save the wallet
|
||||
if (isFirstSavedWallet) {
|
||||
preferencesStorage.shouldSaveAccessCodes = true
|
||||
store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository)
|
||||
.setAccessCodeRequestPolicy(
|
||||
isBiometricsRequestPolicy = userWallet.hasAccessCode,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import com.tangem.domain.card.ScanCardUseCase
|
|||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import com.tangem.features.tester.api.TesterRouter
|
||||
import com.tangem.features.tokendetails.featuretoggles.TokenDetailsFeatureToggles
|
||||
import com.tangem.features.tokendetails.navigation.TokenDetailsRouter
|
||||
|
|
@ -44,6 +45,7 @@ data class DaggerGraphState(
|
|||
val appThemeModeRepository: AppThemeModeRepository? = null,
|
||||
val balanceHidingRepository: BalanceHidingRepository? = null,
|
||||
val detailsFeatureToggles: DetailsFeatureToggles? = null,
|
||||
val walletsRepository: WalletsRepository? = null,
|
||||
|
||||
// FIXME: It is used only for TokensList screen. Remove after refactoring of TokensList
|
||||
val currenciesRepository: CurrenciesRepository? = null,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
package com.tangem.datasource.di
|
||||
|
||||
import android.content.Context
|
||||
import com.tangem.datasource.local.datastore.BooleanSharedPreferencesDataStore
|
||||
import com.tangem.datasource.local.settings.*
|
||||
import com.tangem.datasource.local.userwallet.DefaultShouldSaveUserWalletStore
|
||||
import com.tangem.datasource.local.userwallet.ShouldSaveUserWalletStore
|
||||
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 WalletsDataModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideShouldSaveUserWalletsStore(@ApplicationContext context: Context): ShouldSaveUserWalletStore {
|
||||
return DefaultShouldSaveUserWalletStore(
|
||||
store = BooleanSharedPreferencesDataStore(preferencesName = "tapPrefs", context = context),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package com.tangem.datasource.local.userwallet
|
||||
|
||||
import com.tangem.datasource.local.datastore.BooleanSharedPreferencesDataStore
|
||||
import com.tangem.datasource.local.datastore.core.KeylessDataStoreDecorator
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface ShouldSaveUserWalletStore {
|
||||
|
||||
fun get(): Flow<Boolean>
|
||||
|
||||
suspend fun getSyncOrNull(): Boolean?
|
||||
|
||||
suspend fun store(item: Boolean)
|
||||
}
|
||||
|
||||
internal class DefaultShouldSaveUserWalletStore(
|
||||
store: BooleanSharedPreferencesDataStore,
|
||||
) : ShouldSaveUserWalletStore, KeylessDataStoreDecorator<Boolean>(
|
||||
wrappedDataStore = store,
|
||||
key = "saveUserWallets",
|
||||
)
|
||||
|
|
@ -56,12 +56,6 @@ class PreferencesDataSource @Inject internal constructor(applicationContext: Con
|
|||
putBoolean(SAVE_WALLET_DIALOG_SHOWN_KEY, value)
|
||||
}
|
||||
|
||||
var shouldSaveUserWallets: Boolean
|
||||
get() = preferences.getBoolean(SAVE_USER_WALLETS_KEY, false)
|
||||
set(value) = preferences.edit {
|
||||
putBoolean(SAVE_USER_WALLETS_KEY, value)
|
||||
}
|
||||
|
||||
var shouldSaveAccessCodes: Boolean
|
||||
get() = preferences.getBoolean(SAVE_ACCESS_CODES_KEY, false)
|
||||
set(value) = preferences.edit {
|
||||
|
|
@ -102,7 +96,6 @@ class PreferencesDataSource @Inject internal constructor(applicationContext: Con
|
|||
private const val ZENDESK_FIRST_LAUNCH_KEY = "chatFirstLaunchKey"
|
||||
private const val SPRINKLR_FIRST_LAUNCH_KEY = "sprinklrFirstLaunch"
|
||||
private const val SAVE_WALLET_DIALOG_SHOWN_KEY = "saveUserWalletShown"
|
||||
private const val SAVE_USER_WALLETS_KEY = "saveUserWallets"
|
||||
private const val SAVE_ACCESS_CODES_KEY = "saveAccessCodes"
|
||||
private const val APPLICATION_STOPPED_KEY = "applicationStopped"
|
||||
private const val OPEN_WELCOME_ON_RESUME_KEY = "openWelcomeOnResume"
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation(projects.core.datasource)
|
||||
implementation(projects.core.utils)
|
||||
implementation(projects.data.source.preferences)
|
||||
implementation(projects.domain.wallets)
|
||||
|
|
|
|||
|
|
@ -1,16 +1,29 @@
|
|||
package com.tangem.data.wallets
|
||||
|
||||
import com.tangem.data.source.preferences.PreferencesDataSource
|
||||
import com.tangem.datasource.local.userwallet.ShouldSaveUserWalletStore
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
internal class DefaultWalletsRepository(
|
||||
private val preferencesDataSource: PreferencesDataSource,
|
||||
private val shouldSaveUserWalletStore: ShouldSaveUserWalletStore,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : WalletsRepository {
|
||||
|
||||
override suspend fun shouldSaveUserWallets(): Boolean {
|
||||
return withContext(dispatchers.io) { preferencesDataSource.shouldSaveUserWallets }
|
||||
override suspend fun initialize() {
|
||||
withContext(dispatchers.io) {
|
||||
shouldSaveUserWalletStore.getSyncOrNull() ?: shouldSaveUserWalletStore.store(item = false)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun shouldSaveUserWalletsSync(): Boolean {
|
||||
return withContext(dispatchers.io) { shouldSaveUserWalletStore.getSyncOrNull() ?: false }
|
||||
}
|
||||
|
||||
override fun shouldSaveUserWallets(): Flow<Boolean> = shouldSaveUserWalletStore.get()
|
||||
|
||||
override suspend fun saveShouldSaveUserWallets(item: Boolean) {
|
||||
withContext(dispatchers.io) { shouldSaveUserWalletStore.store(item = item) }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
package com.tangem.data.wallets.di
|
||||
|
||||
import com.tangem.data.source.preferences.PreferencesDataSource
|
||||
import com.tangem.data.wallets.DefaultWalletsRepository
|
||||
import com.tangem.datasource.local.userwallet.ShouldSaveUserWalletStore
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.Module
|
||||
|
|
@ -17,11 +17,11 @@ object WalletsDataModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
fun providesWalletsRepository(
|
||||
preferencesDataSource: PreferencesDataSource,
|
||||
shouldSaveUserWalletStore: ShouldSaveUserWalletStore,
|
||||
coroutineDispatcherProvider: CoroutineDispatcherProvider,
|
||||
): WalletsRepository {
|
||||
return DefaultWalletsRepository(
|
||||
preferencesDataSource = preferencesDataSource,
|
||||
shouldSaveUserWalletStore = shouldSaveUserWalletStore,
|
||||
dispatchers = coroutineDispatcherProvider,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,14 @@
|
|||
package com.tangem.domain.wallets.repository
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface WalletsRepository {
|
||||
|
||||
suspend fun shouldSaveUserWallets(): Boolean
|
||||
suspend fun initialize()
|
||||
|
||||
suspend fun shouldSaveUserWalletsSync(): Boolean
|
||||
|
||||
fun shouldSaveUserWallets(): Flow<Boolean>
|
||||
|
||||
suspend fun saveShouldSaveUserWallets(item: Boolean)
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package com.tangem.domain.wallets.usecase
|
||||
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
|
||||
class ShouldSaveUserWalletsSyncUseCase(private val walletsRepository: WalletsRepository) {
|
||||
|
||||
suspend operator fun invoke(): Boolean = walletsRepository.shouldSaveUserWalletsSync()
|
||||
}
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
package com.tangem.domain.wallets.usecase
|
||||
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class ShouldSaveUserWalletsUseCase(private val walletsRepository: WalletsRepository) {
|
||||
|
||||
suspend operator fun invoke(): Boolean = walletsRepository.shouldSaveUserWallets()
|
||||
operator fun invoke(): Flow<Boolean> = walletsRepository.shouldSaveUserWallets()
|
||||
}
|
||||
|
|
@ -106,6 +106,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
private val shouldShowSaveWalletScreenUseCase: ShouldShowSaveWalletScreenUseCase,
|
||||
private val canUseBiometryUseCase: CanUseBiometryUseCase,
|
||||
private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase,
|
||||
private val shouldSaveUserWalletsSyncUseCase: ShouldSaveUserWalletsSyncUseCase,
|
||||
private val isBalanceHiddenUseCase: IsBalanceHiddenUseCase,
|
||||
private val listenToFlipsUseCase: ListenToFlipsUseCase,
|
||||
private val removeCurrencyUseCase: RemoveCurrencyUseCase,
|
||||
|
|
@ -182,12 +183,18 @@ internal class WalletViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
getWalletsUseCase()
|
||||
.flowWithLifecycle(owner.lifecycle)
|
||||
.distinctUntilChanged()
|
||||
.onEach(::updateWallets)
|
||||
.flowOn(dispatchers.io)
|
||||
.launchIn(viewModelScope)
|
||||
viewModelScope.launch(dispatchers.io) {
|
||||
shouldSaveUserWalletsUseCase()
|
||||
.flowWithLifecycle(owner.lifecycle)
|
||||
.collectLatest {
|
||||
getWalletsUseCase()
|
||||
.flowWithLifecycle(owner.lifecycle)
|
||||
.distinctUntilChanged()
|
||||
.onEach(::updateWallets)
|
||||
.flowOn(dispatchers.io)
|
||||
.launchIn(viewModelScope)
|
||||
}
|
||||
}
|
||||
|
||||
isBalanceHiddenUseCase()
|
||||
.flowWithLifecycle(owner.lifecycle)
|
||||
|
|
@ -274,7 +281,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
|
||||
override fun onBackClick() {
|
||||
viewModelScope.launch(dispatchers.main) {
|
||||
router.popBackStack(screen = if (shouldSaveUserWalletsUseCase()) AppScreen.Welcome else AppScreen.Home)
|
||||
router.popBackStack(screen = if (shouldSaveUserWalletsSyncUseCase()) AppScreen.Welcome else AppScreen.Home)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue