Updated on 2026-08-14
This commit is contained in:
parent
361b6c05b6
commit
4c25513253
9 changed files with 136 additions and 3 deletions
|
|
@ -0,0 +1,23 @@
|
|||
package com.tangem.datasource.di
|
||||
|
||||
import com.tangem.datasource.local.accounts.AccountTokenMigrationStore
|
||||
import com.tangem.datasource.local.accounts.DefaultAccountTokenMigrationStore
|
||||
import com.tangem.datasource.local.datastore.RuntimeStateStore
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal object AccountsMigrationStoreModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideAccountTokenMigrationStore(): AccountTokenMigrationStore {
|
||||
return DefaultAccountTokenMigrationStore(
|
||||
runtimeStateStore = RuntimeStateStore(emptyMap()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.tangem.datasource.local.accounts
|
||||
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface AccountTokenMigrationStore {
|
||||
|
||||
fun get(userWalletId: UserWalletId): Flow<Pair<String, String>?>
|
||||
|
||||
suspend fun store(userWalletId: UserWalletId, value: Pair<String, String>)
|
||||
|
||||
suspend fun remove(userWalletId: UserWalletId)
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package com.tangem.datasource.local.accounts
|
||||
|
||||
import com.tangem.datasource.local.datastore.RuntimeStateStore
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
internal class DefaultAccountTokenMigrationStore(
|
||||
private val runtimeStateStore: RuntimeStateStore<Map<UserWalletId, Pair<String, String>>>,
|
||||
) : AccountTokenMigrationStore {
|
||||
|
||||
override fun get(userWalletId: UserWalletId): Flow<Pair<String, String>?> {
|
||||
return runtimeStateStore.get().map { it[userWalletId] }
|
||||
}
|
||||
|
||||
override suspend fun store(userWalletId: UserWalletId, value: Pair<String, String>) {
|
||||
runtimeStateStore.update { it + (userWalletId to value) }
|
||||
}
|
||||
|
||||
override suspend fun remove(userWalletId: UserWalletId) {
|
||||
runtimeStateStore.update { it - userWalletId }
|
||||
}
|
||||
}
|
||||
|
|
@ -269,7 +269,7 @@
|
|||
<string name="common_free">無料</string>
|
||||
<string name="common_from">送信元</string>
|
||||
<string name="common_generate_addresses">アドレスを同期する</string>
|
||||
<string name="common_get_started">もっと詳しく</string>
|
||||
<string name="common_get_started">はじめる</string>
|
||||
<string name="common_get_token">トークンを取得</string>
|
||||
<string name="common_go_to_provider">プロバイダーへ移動</string>
|
||||
<string name="common_go_to_token">トークンへ移動</string>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import com.tangem.data.common.account.WalletAccountsFetcher
|
|||
import com.tangem.data.common.account.WalletAccountsSaver
|
||||
import com.tangem.data.common.currency.UserTokensSaver
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.local.accounts.AccountTokenMigrationStore
|
||||
import com.tangem.datasource.local.datastore.RuntimeStateStore
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
|
|
@ -75,9 +76,11 @@ internal object AccountDataModule {
|
|||
fun provideMainAccountTokensMigration(
|
||||
accountsResponseStoreFactory: AccountsResponseStoreFactory,
|
||||
userTokensSaver: UserTokensSaver,
|
||||
accountTokenMigrationStore: AccountTokenMigrationStore,
|
||||
): MainAccountTokensMigration {
|
||||
return DefaultMainAccountTokensMigration(
|
||||
accountsResponseStoreFactory = accountsResponseStoreFactory,
|
||||
accountTokenMigrationStore = accountTokenMigrationStore,
|
||||
userTokensSaver = userTokensSaver,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
|||
import com.tangem.datasource.api.tangemTech.models.account.GetWalletAccountsResponse
|
||||
import com.tangem.datasource.api.tangemTech.models.account.WalletAccountDTO
|
||||
import com.tangem.datasource.api.tangemTech.models.account.toUserTokensResponse
|
||||
import com.tangem.datasource.local.accounts.AccountTokenMigrationStore
|
||||
import com.tangem.datasource.utils.getSyncOrNull
|
||||
import com.tangem.domain.account.tokens.MainAccountTokensMigration
|
||||
import com.tangem.domain.models.account.DerivationIndex
|
||||
|
|
@ -32,6 +33,7 @@ import timber.log.Timber
|
|||
*/
|
||||
internal class DefaultMainAccountTokensMigration(
|
||||
private val accountsResponseStoreFactory: AccountsResponseStoreFactory,
|
||||
private val accountTokenMigrationStore: AccountTokenMigrationStore,
|
||||
private val userTokensSaver: UserTokensSaver,
|
||||
) : MainAccountTokensMigration {
|
||||
|
||||
|
|
@ -80,6 +82,12 @@ internal class DefaultMainAccountTokensMigration(
|
|||
|
||||
store.updateData { updatedResponse }
|
||||
|
||||
val mainAccountName = mainAccount.name
|
||||
val selectedAccountName = selectedAccount.name
|
||||
if (mainAccountName != null && selectedAccountName != null) {
|
||||
accountTokenMigrationStore.store(userWalletId, mainAccountName to selectedAccountName)
|
||||
}
|
||||
|
||||
val userTokensResponse = updatedResponse.toUserTokensResponse()
|
||||
userTokensSaver.pushWithRetryer(
|
||||
userWalletId = userWalletId,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import com.tangem.data.common.currency.UserTokensSaver
|
|||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||
import com.tangem.datasource.api.tangemTech.models.account.GetWalletAccountsResponse
|
||||
import com.tangem.datasource.api.tangemTech.models.account.toUserTokensResponse
|
||||
import com.tangem.datasource.local.accounts.AccountTokenMigrationStore
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.account.DerivationIndex
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
|
|
@ -29,11 +30,12 @@ class DefaultMainAccountTokensMigrationTest {
|
|||
private val accountsResponseStoreFactory = mockk<AccountsResponseStoreFactory>()
|
||||
private val accountsResponseStore = mockk<AccountsResponseStore>()
|
||||
private val accountsResponseStoreFlow = MutableStateFlow<GetWalletAccountsResponse?>(value = null)
|
||||
|
||||
private val accountTokenMigrationStore = mockk<AccountTokenMigrationStore>(relaxUnitFun = true)
|
||||
private val userTokensSaver = mockk<UserTokensSaver>(relaxUnitFun = true)
|
||||
|
||||
private val migration = DefaultMainAccountTokensMigration(
|
||||
accountsResponseStoreFactory = accountsResponseStoreFactory,
|
||||
accountTokenMigrationStore = accountTokenMigrationStore,
|
||||
userTokensSaver = userTokensSaver,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ dependencies {
|
|||
implementation(projects.core.navigation)
|
||||
implementation(projects.core.analytics)
|
||||
implementation(projects.core.analytics.models)
|
||||
implementation(projects.core.datasource)
|
||||
implementation(projects.common.routing)
|
||||
implementation(projects.common.ui)
|
||||
|
||||
|
|
|
|||
|
|
@ -9,33 +9,52 @@ import com.arkivanov.decompose.ComponentContext
|
|||
import com.arkivanov.decompose.extensions.compose.subscribeAsState
|
||||
import com.arkivanov.decompose.router.slot.childSlot
|
||||
import com.arkivanov.decompose.router.slot.dismiss
|
||||
import com.arkivanov.essenty.lifecycle.subscribe
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.context.childByContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
|
||||
import com.tangem.core.ui.decompose.ComposableDialogComponent
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.message.DialogMessage
|
||||
import com.tangem.core.ui.message.EventMessageAction
|
||||
import com.tangem.core.ui.utils.requestPermission
|
||||
import com.tangem.datasource.local.accounts.AccountTokenMigrationStore
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.feature.walletsettings.component.NetworksAvailableForNotificationsComponent
|
||||
import com.tangem.feature.walletsettings.component.RenameWalletComponent
|
||||
import com.tangem.feature.walletsettings.component.WalletSettingsComponent
|
||||
import com.tangem.feature.walletsettings.entity.DialogConfig
|
||||
import com.tangem.feature.walletsettings.entity.NetworksAvailableForNotificationBSConfig
|
||||
import com.tangem.feature.walletsettings.impl.R
|
||||
import com.tangem.feature.walletsettings.model.WalletSettingsModel
|
||||
import com.tangem.feature.walletsettings.ui.WalletSettingsScreen
|
||||
import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION
|
||||
import com.tangem.utils.coroutines.JobHolder
|
||||
import com.tangem.utils.coroutines.saveIn
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
internal class DefaultWalletSettingsComponent @AssistedInject constructor(
|
||||
@Assisted context: AppComponentContext,
|
||||
@Assisted params: WalletSettingsComponent.Params,
|
||||
@Assisted private val params: WalletSettingsComponent.Params,
|
||||
private val renameWalletComponentFactory: RenameWalletComponent.Factory,
|
||||
private val networksAvailableForNotificationsComponent: NetworksAvailableForNotificationsComponent.Factory,
|
||||
private val accountTokenMigrationStore: AccountTokenMigrationStore,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
) : WalletSettingsComponent, AppComponentContext by context {
|
||||
|
||||
private val model: WalletSettingsModel = getOrCreateModel(params)
|
||||
|
||||
private val accountMigrationJobHolder = JobHolder()
|
||||
|
||||
private val bottomSheetSlot = childSlot(
|
||||
source = model.bottomSheetNavigation,
|
||||
serializer = null,
|
||||
|
|
@ -52,6 +71,17 @@ internal class DefaultWalletSettingsComponent @AssistedInject constructor(
|
|||
childFactory = ::dialogChild,
|
||||
)
|
||||
|
||||
init {
|
||||
lifecycle.subscribe(
|
||||
onResume = {
|
||||
if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
showMigrationAlertIfNeeded()
|
||||
}
|
||||
},
|
||||
onPause = { accountMigrationJobHolder.cancel() },
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
val state by model.state.collectAsStateWithLifecycle()
|
||||
|
|
@ -106,6 +136,36 @@ internal class DefaultWalletSettingsComponent @AssistedInject constructor(
|
|||
),
|
||||
)
|
||||
|
||||
private fun showMigrationAlertIfNeeded() {
|
||||
accountTokenMigrationStore.get(params.userWalletId)
|
||||
.distinctUntilChanged()
|
||||
.filterNotNull()
|
||||
.onEach { (fromAccount, toAccount) ->
|
||||
messageSender.send(
|
||||
DialogMessage(
|
||||
title = resourceReference(R.string.accounts_migration_alert_title),
|
||||
message = resourceReference(
|
||||
R.string.accounts_migration_alert_message,
|
||||
wrappedList(fromAccount, toAccount),
|
||||
),
|
||||
firstActionBuilder = {
|
||||
EventMessageAction(
|
||||
title = resourceReference(R.string.common_got_it),
|
||||
onClick = { /* no-op */ },
|
||||
)
|
||||
},
|
||||
onDismissRequest = {
|
||||
componentScope.launch {
|
||||
accountTokenMigrationStore.remove(params.userWalletId)
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
.launchIn(componentScope)
|
||||
.saveIn(accountMigrationJobHolder)
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : WalletSettingsComponent.Factory {
|
||||
override fun create(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue