Updated on 2026-08-14
This commit is contained in:
commit
c6c1fd3044
42 changed files with 430 additions and 297 deletions
|
|
@ -121,8 +121,12 @@ class DetailsMiddleware {
|
|||
|
||||
val selectedUserWallet = userWalletsListManager.selectedUserWalletSync
|
||||
if (selectedUserWallet != null) {
|
||||
store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Wallet))
|
||||
store.onUserWalletSelected(selectedUserWallet)
|
||||
if (userWalletsListManager.isLockedSync) {
|
||||
store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Welcome))
|
||||
} else {
|
||||
store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Wallet))
|
||||
store.onUserWalletSelected(selectedUserWallet)
|
||||
}
|
||||
} else {
|
||||
userWalletsListManager.lock()
|
||||
store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Home))
|
||||
|
|
@ -232,6 +236,7 @@ class DetailsMiddleware {
|
|||
}
|
||||
|
||||
private fun enrollBiometrics() {
|
||||
Analytics.send(Settings.AppSettings.ButtonEnableBiometricAuthentication)
|
||||
store.dispatchOnMain(NavigationAction.OpenBiometricsSettings)
|
||||
}
|
||||
|
||||
|
|
@ -268,14 +273,18 @@ class DetailsMiddleware {
|
|||
Timber.e(error, "Wallet saving failed")
|
||||
}
|
||||
.doOnSuccess {
|
||||
Analytics.send(Settings.AppSettings.SaveWalletSwitcherChanged(AnalyticsParam.OnOffState.On))
|
||||
|
||||
preferencesStorage.shouldShowSaveUserWalletScreen = false
|
||||
preferencesStorage.shouldSaveUserWallets = true
|
||||
|
||||
store.dispatchOnMain(
|
||||
DetailsAction.AppSettings.SwitchPrivacySetting.Success(
|
||||
setting = PrivacySetting.SaveWallets,
|
||||
enable = true,
|
||||
),
|
||||
)
|
||||
|
||||
store.onUserWalletSelected(userWallet)
|
||||
}
|
||||
}
|
||||
|
|
@ -284,22 +293,29 @@ class DetailsMiddleware {
|
|||
userWalletsListManager.clear()
|
||||
.flatMap { walletStoresManager.clear() }
|
||||
.doOnSuccess {
|
||||
Analytics.send(Settings.AppSettings.SaveWalletSwitcherChanged(AnalyticsParam.OnOffState.Off))
|
||||
|
||||
preferencesStorage.shouldSaveUserWallets = false
|
||||
|
||||
store.dispatchOnMain(
|
||||
DetailsAction.AppSettings.SwitchPrivacySetting.Success(
|
||||
setting = PrivacySetting.SaveWallets,
|
||||
enable = false,
|
||||
),
|
||||
)
|
||||
|
||||
store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Home))
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveAccessCodes(state: DetailsState) {
|
||||
Analytics.send(Settings.AppSettings.SaveAccessCodeSwitcherChanged(AnalyticsParam.OnOffState.On))
|
||||
|
||||
preferencesStorage.shouldSaveAccessCodes = true
|
||||
tangemSdkManager.setAccessCodeRequestPolicy(
|
||||
useBiometricsForAccessCode = state.scanResponse?.card?.isAccessCodeSet == true,
|
||||
)
|
||||
|
||||
store.dispatchOnMain(
|
||||
DetailsAction.AppSettings.SwitchPrivacySetting.Success(
|
||||
setting = PrivacySetting.SaveAccessCode,
|
||||
|
|
@ -311,10 +327,13 @@ class DetailsMiddleware {
|
|||
private suspend fun deleteSavedAccessCodes() {
|
||||
tangemSdkManager.clearSavedUserCodes()
|
||||
.doOnSuccess {
|
||||
Analytics.send(Settings.AppSettings.SaveAccessCodeSwitcherChanged(AnalyticsParam.OnOffState.Off))
|
||||
|
||||
preferencesStorage.shouldSaveAccessCodes = false
|
||||
tangemSdkManager.setAccessCodeRequestPolicy(
|
||||
useBiometricsForAccessCode = false,
|
||||
)
|
||||
|
||||
store.dispatchOnMain(
|
||||
DetailsAction.AppSettings.SwitchPrivacySetting.Success(
|
||||
setting = PrivacySetting.SaveAccessCode,
|
||||
|
|
|
|||
|
|
@ -93,9 +93,14 @@ private fun readCard() = scope.launch {
|
|||
userWalletsListManager.save(userWallet)
|
||||
.doOnFailure { error ->
|
||||
Timber.e(error, "Unable to save user wallet")
|
||||
tangemSdkManager.setAccessCodeRequestPolicy(useBiometricsForAccessCode = false)
|
||||
store.onCardScanned(scanResponse)
|
||||
}
|
||||
.doOnSuccess {
|
||||
tangemSdkManager.setAccessCodeRequestPolicy(
|
||||
useBiometricsForAccessCode = preferencesStorage.shouldSaveAccessCodes &&
|
||||
userWallet.hasAccessCode,
|
||||
)
|
||||
store.onUserWalletSelected(userWallet)
|
||||
}
|
||||
.doOnResult {
|
||||
|
|
|
|||
|
|
@ -1,16 +1,20 @@
|
|||
package com.tangem.tap.features.onboarding
|
||||
|
||||
import com.tangem.common.doOnSuccess
|
||||
import com.tangem.domain.common.ProductType
|
||||
import com.tangem.domain.common.ScanResponse
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.onCardScanned
|
||||
import com.tangem.tap.common.extensions.onUserWalletSelected
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.domain.model.builders.UserWalletBuilder
|
||||
import com.tangem.tap.features.saveWallet.redux.SaveWalletAction
|
||||
import com.tangem.tap.preferencesStorage
|
||||
import com.tangem.tap.scope
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.tap.tangemSdkManager
|
||||
import com.tangem.tap.userWalletsListManager
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
|
@ -55,6 +59,18 @@ class OnboardingHelper {
|
|||
backupCardsIds: List<String>? = null,
|
||||
) {
|
||||
when {
|
||||
// When should save user wallets but manager is locked, then unlock manager with card
|
||||
preferencesStorage.shouldSaveUserWallets &&
|
||||
userWalletsListManager.isLockedSync -> scope.launch {
|
||||
val userWallet = UserWalletBuilder(scanResponse).build()
|
||||
|
||||
tangemSdkManager.setAccessCodeRequestPolicy(useBiometricsForAccessCode = false)
|
||||
userWalletsListManager.unlockWithCard(userWallet)
|
||||
.doOnSuccess {
|
||||
store.onUserWalletSelected(userWallet)
|
||||
}
|
||||
}
|
||||
// When should save user wallets, then save card without navigate to save wallet screen
|
||||
preferencesStorage.shouldSaveUserWallets -> scope.launch {
|
||||
store.dispatchOnMain(
|
||||
SaveWalletAction.ProvideBackupInfo(
|
||||
|
|
@ -65,6 +81,8 @@ class OnboardingHelper {
|
|||
)
|
||||
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 {
|
||||
delay(timeMillis = 1_200)
|
||||
|
|
@ -77,6 +95,7 @@ class OnboardingHelper {
|
|||
)
|
||||
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 {
|
||||
store.onCardScanned(scanResponse)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -234,7 +234,6 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
|
|||
|
||||
when (action) {
|
||||
is BackupAction.StartBackup -> {
|
||||
tangemSdkManager.setAccessCodeRequestPolicy(useBiometricsForAccessCode = false)
|
||||
Analytics.send(Onboarding.Backup.Started())
|
||||
backupService.discardSavedBackup()
|
||||
val primaryCard = scanResponse?.primaryCard
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@ import com.tangem.common.CompletionResult
|
|||
import com.tangem.common.doOnFailure
|
||||
import com.tangem.common.doOnSuccess
|
||||
import com.tangem.common.flatMap
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.MainScreen
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.onUserWalletSelected
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
|
|
@ -36,9 +40,9 @@ internal class SaveWalletMiddleware {
|
|||
is SaveWalletAction.Save -> saveWalletIfBiometricsEnrolled(state)
|
||||
is SaveWalletAction.EnrollBiometrics.Enroll -> enrollBiometrics()
|
||||
is SaveWalletAction.SaveWalletWasShown -> saveWalletWasShown()
|
||||
is SaveWalletAction.Dismiss -> dismiss(state)
|
||||
is SaveWalletAction.Save.Success,
|
||||
is SaveWalletAction.ProvideBackupInfo,
|
||||
is SaveWalletAction.Dismiss,
|
||||
is SaveWalletAction.CloseError,
|
||||
is SaveWalletAction.Save.Error,
|
||||
is SaveWalletAction.EnrollBiometrics,
|
||||
|
|
@ -74,6 +78,13 @@ internal class SaveWalletMiddleware {
|
|||
?: store.state.globalState.scanResponse
|
||||
?: return
|
||||
|
||||
if (state.backupInfo != null) {
|
||||
// TODO: Remove after onboarding refactoring
|
||||
Analytics.send(Onboarding.EnableBiometrics(AnalyticsParam.OnOffState.On))
|
||||
} else {
|
||||
Analytics.send(MainScreen.EnableBiometrics(AnalyticsParam.OnOffState.On))
|
||||
}
|
||||
|
||||
scope.launch {
|
||||
val userWallet = UserWalletBuilder(scanResponse)
|
||||
.backupCardsIds(state.backupInfo?.backupCardsIds)
|
||||
|
|
@ -83,6 +94,7 @@ internal class SaveWalletMiddleware {
|
|||
|
||||
saveAccessCodeIfNeeded(state.backupInfo?.accessCode, userWallet.cardsInWallet)
|
||||
.flatMap { userWalletsListManager.save(userWallet, canOverride = true) }
|
||||
.flatMap { userWalletsListManager.selectWallet(userWallet.walletId) }
|
||||
.doOnFailure { error ->
|
||||
store.dispatchOnMain(SaveWalletAction.Save.Error(error))
|
||||
}
|
||||
|
|
@ -93,21 +105,29 @@ internal class SaveWalletMiddleware {
|
|||
preferencesStorage.shouldSaveAccessCodes = isFirstSavedWallet ||
|
||||
preferencesStorage.shouldSaveAccessCodes
|
||||
|
||||
val isSavedWalletSelected =
|
||||
userWalletsListManager.selectedUserWalletSync?.walletId == userWallet.walletId
|
||||
|
||||
tangemSdkManager.setAccessCodeRequestPolicy(
|
||||
useBiometricsForAccessCode = preferencesStorage.shouldSaveAccessCodes &&
|
||||
userWallet.hasAccessCode,
|
||||
)
|
||||
|
||||
store.dispatchOnMain(SaveWalletAction.Save.Success)
|
||||
|
||||
if (isSavedWalletSelected) {
|
||||
store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Wallet))
|
||||
store.onUserWalletSelected(userWallet)
|
||||
} else {
|
||||
store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.WalletSelector))
|
||||
}
|
||||
store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Wallet))
|
||||
store.onUserWalletSelected(userWallet)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun dismiss(state: SaveWalletState) {
|
||||
if (state.backupInfo != null) {
|
||||
// TODO: Remove after onboarding refactoring
|
||||
Analytics.send(Onboarding.EnableBiometrics(AnalyticsParam.OnOffState.Off))
|
||||
} else {
|
||||
Analytics.send(MainScreen.EnableBiometrics(AnalyticsParam.OnOffState.Off))
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveWalletWasShown() {
|
||||
preferencesStorage.shouldShowSaveUserWalletScreen = false
|
||||
}
|
||||
|
|
@ -118,13 +138,10 @@ internal class SaveWalletMiddleware {
|
|||
): CompletionResult<Unit> {
|
||||
return when {
|
||||
accessCode != null -> {
|
||||
tangemSdkManager.unlockBiometricKeys()
|
||||
.flatMap {
|
||||
tangemSdkManager.saveAccessCode(
|
||||
accessCode = accessCode,
|
||||
cardsIds = cardsInWallet,
|
||||
)
|
||||
}
|
||||
tangemSdkManager.saveAccessCode(
|
||||
accessCode = accessCode,
|
||||
cardsIds = cardsInWallet,
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
CompletionResult.Success(Unit)
|
||||
|
|
|
|||
|
|
@ -5,12 +5,10 @@ import android.view.Menu
|
|||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.transition.TransitionInflater
|
||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import com.google.accompanist.appcompattheme.AppCompatTheme
|
||||
|
|
@ -22,6 +20,8 @@ import com.tangem.tap.common.extensions.dispatchNotification
|
|||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.getString
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.features.BaseFragment
|
||||
import com.tangem.tap.features.addBackPressHandler
|
||||
import com.tangem.tap.features.tokens.redux.ContractAddress
|
||||
import com.tangem.tap.features.tokens.redux.TokenWithBlockchain
|
||||
import com.tangem.tap.features.tokens.redux.TokensAction
|
||||
|
|
@ -40,8 +40,7 @@ import kotlinx.coroutines.flow.launchIn
|
|||
import kotlinx.coroutines.flow.onEach
|
||||
import org.rekotlin.StoreSubscriber
|
||||
|
||||
class AddTokensFragment : Fragment(R.layout.fragment_add_tokens),
|
||||
StoreSubscriber<TokensState> {
|
||||
class AddTokensFragment : BaseFragment(R.layout.fragment_add_tokens), StoreSubscriber<TokensState> {
|
||||
|
||||
private val binding: FragmentAddTokensBinding by viewBinding(FragmentAddTokensBinding::bind)
|
||||
private var tokensState: MutableState<TokensState> = mutableStateOf(store.state.tokensState)
|
||||
|
|
@ -51,33 +50,7 @@ class AddTokensFragment : Fragment(R.layout.fragment_add_tokens),
|
|||
super.onCreate(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
Analytics.send(ManageTokens.ScreenOpened())
|
||||
|
||||
activity?.onBackPressedDispatcher?.addCallback(
|
||||
this,
|
||||
object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
store.dispatch(TokensAction.ResetState)
|
||||
}
|
||||
},
|
||||
)
|
||||
val inflater = TransitionInflater.from(requireContext())
|
||||
enterTransition = inflater.inflateTransition(R.transition.slide_right)
|
||||
exitTransition = inflater.inflateTransition(R.transition.fade)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
store.subscribe(this) { state ->
|
||||
state.skipRepeats { oldState, newState ->
|
||||
oldState.tokensState == newState.tokensState
|
||||
}.select { it.tokensState }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
store.unsubscribe(this)
|
||||
addBackPressHandler(this)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) = with(binding) {
|
||||
|
|
@ -96,11 +69,7 @@ class AddTokensFragment : Fragment(R.layout.fragment_add_tokens),
|
|||
}
|
||||
|
||||
val onLoadMore = {
|
||||
store.dispatch(
|
||||
TokensAction.LoadMore(
|
||||
scanResponse = store.state.globalState.scanResponse,
|
||||
),
|
||||
)
|
||||
store.dispatch(TokensAction.LoadMore(scanResponse = store.state.globalState.scanResponse))
|
||||
}
|
||||
|
||||
cvCurrencies.setContent {
|
||||
|
|
@ -115,24 +84,23 @@ class AddTokensFragment : Fragment(R.layout.fragment_add_tokens),
|
|||
}
|
||||
}
|
||||
|
||||
override fun newState(state: TokensState) {
|
||||
if (activity == null || view == null) return
|
||||
val toolbarTitle =
|
||||
if (state.allowToAdd) R.string.main_manage_tokens else R.string.search_tokens_title
|
||||
tokensState.value = state
|
||||
binding.toolbar.title = getString(toolbarTitle)
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
store.subscribe(this) { state ->
|
||||
state
|
||||
.skipRepeats { oldState, newState -> oldState.tokensState == newState.tokensState }
|
||||
.select { it.tokensState }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
return when (item.itemId) {
|
||||
R.id.menu_search -> true
|
||||
R.id.menu_navigate_add_custom_token -> {
|
||||
Analytics.send(ManageTokens.ButtonCustomToken())
|
||||
store.dispatch(TokensAction.PrepareAndNavigateToAddCustomToken)
|
||||
true
|
||||
}
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
}
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
store.unsubscribe(this)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
store.dispatch(TokensAction.ResetState)
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
|
|
@ -156,25 +124,50 @@ class AddTokensFragment : Fragment(R.layout.fragment_add_tokens),
|
|||
return super.onCreateOptionsMenu(menu, inflater)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
return when (item.itemId) {
|
||||
R.id.menu_search -> true
|
||||
R.id.menu_navigate_add_custom_token -> {
|
||||
Analytics.send(ManageTokens.ButtonCustomToken())
|
||||
store.dispatch(TokensAction.PrepareAndNavigateToAddCustomToken)
|
||||
true
|
||||
}
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
||||
|
||||
override fun configureTransitions() {
|
||||
super.configureTransitions()
|
||||
val inflater = TransitionInflater.from(requireContext())
|
||||
enterTransition = inflater.inflateTransition(R.transition.slide_right)
|
||||
exitTransition = inflater.inflateTransition(R.transition.fade)
|
||||
}
|
||||
|
||||
override fun handleOnBackPressed() {
|
||||
super.handleOnBackPressed()
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
store.dispatch(TokensAction.ResetState)
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun newState(state: TokensState) {
|
||||
if (activity == null || view == null) return
|
||||
val toolbarTitle =
|
||||
if (state.allowToAdd) R.string.main_manage_tokens else R.string.search_tokens_title
|
||||
tokensState.value = state
|
||||
binding.toolbar.title = getString(toolbarTitle)
|
||||
}
|
||||
}
|
||||
|
||||
fun SearchView.inputtedTextAsFlow(): Flow<String> = callbackFlow {
|
||||
val watcher =
|
||||
setOnQueryTextListener(
|
||||
object : SearchView.OnQueryTextListener {
|
||||
override fun onQueryTextSubmit(query: String?): Boolean {
|
||||
return false
|
||||
}
|
||||
val watcher = setOnQueryTextListener(
|
||||
object : SearchView.OnQueryTextListener {
|
||||
override fun onQueryTextSubmit(query: String?): Boolean = false
|
||||
|
||||
override fun onQueryTextChange(newText: String?): Boolean {
|
||||
trySend(newText ?: "")
|
||||
return false
|
||||
}
|
||||
},
|
||||
)
|
||||
override fun onQueryTextChange(newText: String?): Boolean {
|
||||
trySend(newText ?: "")
|
||||
return false
|
||||
}
|
||||
},
|
||||
)
|
||||
awaitClose { (watcher) }
|
||||
}
|
||||
|
|
@ -83,25 +83,21 @@ fun CurrenciesScreen(
|
|||
|
||||
Scaffold(
|
||||
floatingActionButton = {
|
||||
if (tokensState.value.allowToAdd) SaveChangesButton(isKeyboardOpen) {
|
||||
onSaveChanges(addedTokensState.value, addedBlockchainsState.value)
|
||||
if (tokensState.value.allowToAdd) {
|
||||
SaveChangesButton(isKeyboardOpen) {
|
||||
onSaveChanges(addedTokensState.value, addedBlockchainsState.value)
|
||||
}
|
||||
}
|
||||
},
|
||||
floatingActionButtonPosition = FabPosition.Center,
|
||||
) {
|
||||
|
||||
AnimatedVisibility(
|
||||
visible = tokensState.value.loadCoinsState == LoadCoinsState.LOADING,
|
||||
enter = fadeIn(),
|
||||
exit = fadeOut(),
|
||||
) {
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
) {
|
||||
CircularProgressIndicator(
|
||||
color = Color(0xFF1ACE80),
|
||||
)
|
||||
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||
CircularProgressIndicator(color = Color(0xFF1ACE80))
|
||||
}
|
||||
}
|
||||
AnimatedVisibility(
|
||||
|
|
@ -148,21 +144,19 @@ private fun toggleBlockchain(
|
|||
currencySymbol = blockchain.currency,
|
||||
),
|
||||
)
|
||||
} else if (isAddedOnMainScreen) {
|
||||
store.dispatchDialogShow(
|
||||
WalletDialog.RemoveWalletDialog(
|
||||
currencyTitle = blockchain.name,
|
||||
onOk = {
|
||||
analyticsCurrencyTypeParam.sendOn()
|
||||
addedBlockchainsState.removeAndNotify(blockchain)
|
||||
},
|
||||
),
|
||||
)
|
||||
} else {
|
||||
if (isAddedOnMainScreen) {
|
||||
store.dispatchDialogShow(
|
||||
WalletDialog.RemoveWalletDialog(
|
||||
currencyTitle = blockchain.name,
|
||||
onOk = {
|
||||
analyticsCurrencyTypeParam.sendOn()
|
||||
addedBlockchainsState.removeAndNotify(blockchain)
|
||||
},
|
||||
),
|
||||
)
|
||||
} else {
|
||||
analyticsCurrencyTypeParam.sendOff()
|
||||
addedBlockchainsState.removeAndNotify(blockchain)
|
||||
}
|
||||
analyticsCurrencyTypeParam.sendOff()
|
||||
addedBlockchainsState.removeAndNotify(blockchain)
|
||||
}
|
||||
} else {
|
||||
analyticsCurrencyTypeParam.sendOn()
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.tap.domain.tokens.Contract
|
||||
import com.tangem.tap.domain.tokens.Currency
|
||||
import com.tangem.tap.features.tokens.redux.ContractAddress
|
||||
import com.tangem.tap.features.tokens.redux.TokenWithBlockchain
|
||||
|
|
@ -30,22 +31,20 @@ fun CurrencyExpandedContent(
|
|||
exit = fadeOut() + shrinkVertically(),
|
||||
) {
|
||||
val blockchains = currency.contracts.map { it.blockchain }
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
) {
|
||||
Column(modifier = Modifier.fillMaxWidth()) {
|
||||
blockchains.mapIndexed { index, blockchain ->
|
||||
val contract = currency.contracts.firstOrNull { it.blockchain == blockchain }
|
||||
val currencyContract = currency.contracts
|
||||
.firstOrNull { it.blockchain == blockchain }
|
||||
?: return@mapIndexed
|
||||
|
||||
val added = if (contract.address != null) {
|
||||
addedTokens.map { it.token.contractAddress }.contains(contract.address)
|
||||
val added = if (currencyContract.address != null) {
|
||||
addedTokens.any(currencyContract::isInclude)
|
||||
} else {
|
||||
addedBlockchains.contains(blockchain)
|
||||
}
|
||||
NetworkItem(
|
||||
currency = currency,
|
||||
contract = contract,
|
||||
contract = currencyContract,
|
||||
blockchain = blockchain,
|
||||
allowToAdd = allowToAdd,
|
||||
added = added,
|
||||
|
|
@ -57,4 +56,7 @@ fun CurrencyExpandedContent(
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Contract.isInclude(addedToken: TokenWithBlockchain): Boolean =
|
||||
address == addedToken.token.contractAddress && blockchain == addedToken.blockchain
|
||||
|
|
@ -8,6 +8,7 @@ import com.tangem.common.extensions.guard
|
|||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.MainScreen
|
||||
import com.tangem.tap.common.analytics.events.Token.ButtonRemoveToken
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
import com.tangem.tap.common.extensions.dispatchErrorNotification
|
||||
|
|
@ -181,6 +182,7 @@ class MultiWalletMiddleware {
|
|||
selectedWallet: UserWallet,
|
||||
state: WalletState?,
|
||||
) = scope.launch {
|
||||
Analytics.send(MainScreen.CardWasScanned())
|
||||
ScanCardProcessor.scan(
|
||||
cardId = selectedWallet.cardId,
|
||||
additionalBlockchainsToDerive = state?.missingDerivations?.map { it.blockchain },
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.tangem.domain.common.extensions.withMainContext
|
|||
import com.tangem.operations.attestation.Attestation
|
||||
import com.tangem.operations.attestation.OnlineCardVerifier
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.MainScreen
|
||||
import com.tangem.tap.common.analytics.events.Token
|
||||
import com.tangem.tap.common.extensions.copyToClipboard
|
||||
import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
|
||||
|
|
@ -349,9 +350,11 @@ class WalletMiddleware {
|
|||
private fun changeWallet() {
|
||||
when {
|
||||
userWalletsListManager.hasSavedUserWallets -> {
|
||||
Analytics.send(MainScreen.ButtonMyWallets())
|
||||
store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.WalletSelector))
|
||||
}
|
||||
else -> {
|
||||
Analytics.send(MainScreen.ButtonScanCard())
|
||||
store.dispatch(WalletAction.Scan)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@ class MultiWalletView : WalletView() {
|
|||
btnAddToken.show()
|
||||
}
|
||||
|
||||
|
||||
override fun onViewCreated() {
|
||||
setupWalletsRecyclerView()
|
||||
}
|
||||
|
|
@ -69,7 +68,7 @@ class MultiWalletView : WalletView() {
|
|||
val fragment = fragment ?: return
|
||||
val binding = binding ?: return
|
||||
|
||||
handleTotalBalance(binding, state.totalBalance, state.state)
|
||||
handleTotalBalance(binding, state.totalBalance, state.state, state.walletsData.size)
|
||||
handleBackupWarning(binding, state.showBackupWarning)
|
||||
handleRescanWarning(binding, state.missingDerivations.isNotEmpty())
|
||||
setupWalletCardNumber(binding, state.walletCardsCount)
|
||||
|
|
@ -137,29 +136,34 @@ class MultiWalletView : WalletView() {
|
|||
binding: FragmentWalletBinding,
|
||||
totalBalance: TotalBalance?,
|
||||
progressState: ProgressState,
|
||||
walletsCount: Int,
|
||||
) = with(binding.lCardTotalBalance) {
|
||||
if (totalBalance == null) {
|
||||
veilBalance.animateVisibility(show = true)
|
||||
root.isVisible = progressState == ProgressState.Loading
|
||||
if (walletsCount == 0) {
|
||||
root.isVisible = false
|
||||
} else {
|
||||
root.isVisible = true
|
||||
if (totalBalance == null) {
|
||||
veilBalance.animateVisibility(show = true)
|
||||
root.isVisible = progressState == ProgressState.Loading
|
||||
} else {
|
||||
root.isVisible = true
|
||||
|
||||
// Skip changes when on refreshing state
|
||||
if (totalBalance.state == ProgressState.Refreshing || progressState == ProgressState.Refreshing) {
|
||||
return@with
|
||||
}
|
||||
// Skip changes when on refreshing state
|
||||
if (totalBalance.state == ProgressState.Refreshing || progressState == ProgressState.Refreshing) {
|
||||
return@with
|
||||
}
|
||||
|
||||
veilBalance.animateVisibility(show = totalBalance.state == ProgressState.Loading)
|
||||
tvBalance.animateVisibility(show = totalBalance.state != ProgressState.Loading)
|
||||
tvProcessing.animateVisibility(show = totalBalance.state == ProgressState.Error)
|
||||
veilBalance.animateVisibility(show = totalBalance.state == ProgressState.Loading)
|
||||
tvBalance.animateVisibility(show = totalBalance.state != ProgressState.Loading)
|
||||
tvProcessing.animateVisibility(show = totalBalance.state == ProgressState.Error)
|
||||
|
||||
tvBalance.text = totalBalance.fiatAmount.formatAmountAsSpannedString(
|
||||
currencySymbol = totalBalance.fiatCurrency.symbol,
|
||||
)
|
||||
tvCurrencyName.text = totalBalance.fiatCurrency.code
|
||||
tvBalance.text = totalBalance.fiatAmount.formatAmountAsSpannedString(
|
||||
currencySymbol = totalBalance.fiatCurrency.symbol,
|
||||
)
|
||||
tvCurrencyName.text = totalBalance.fiatCurrency.code
|
||||
|
||||
tvCurrencyName.setOnClickListener {
|
||||
store.dispatch(WalletAction.AppCurrencyAction.ChooseAppCurrency)
|
||||
tvCurrencyName.setOnClickListener {
|
||||
store.dispatch(WalletAction.AppCurrencyAction.ChooseAppCurrency)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,15 +8,16 @@ data class UserWalletModel(
|
|||
val artworkUrl: String,
|
||||
val type: Type,
|
||||
val fiatBalance: TotalFiatBalance,
|
||||
val isLocked: Boolean,
|
||||
) {
|
||||
sealed interface Type {
|
||||
data class SingleCurrency(
|
||||
val blockchainName: String? = null,
|
||||
val blockchainName: String,
|
||||
) : Type
|
||||
|
||||
data class MultiCurrency(
|
||||
val cardsInWallet: Int,
|
||||
val tokensCount: Int = 0,
|
||||
val tokensCount: Int,
|
||||
) : Type
|
||||
}
|
||||
}
|
||||
|
|
@ -37,6 +37,10 @@ internal sealed interface WalletSelectorAction : Action {
|
|||
val walletId: String,
|
||||
) : WalletSelectorAction
|
||||
|
||||
data class UnlockWalletWithCard(
|
||||
val walletId: String,
|
||||
) : WalletSelectorAction
|
||||
|
||||
data class RenameWallet(
|
||||
val walletId: String,
|
||||
val newName: String,
|
||||
|
|
@ -56,5 +60,6 @@ internal sealed interface WalletSelectorAction : Action {
|
|||
) : WalletSelectorAction
|
||||
|
||||
data class HandleError(val error: TangemError) : WalletSelectorAction
|
||||
|
||||
object CloseError : WalletSelectorAction
|
||||
}
|
||||
|
|
@ -7,6 +7,8 @@ import com.tangem.common.flatMap
|
|||
import com.tangem.common.map
|
||||
import com.tangem.domain.common.ScanResponse
|
||||
import com.tangem.domain.common.util.UserWalletId
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.MyWallets
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.onUserWalletSelected
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
|
|
@ -24,7 +26,6 @@ import com.tangem.tap.tangemSdkManager
|
|||
import com.tangem.tap.totalFiatBalanceCalculator
|
||||
import com.tangem.tap.userWalletsListManager
|
||||
import com.tangem.tap.walletStoresManager
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.launch
|
||||
import org.rekotlin.Middleware
|
||||
import timber.log.Timber
|
||||
|
|
@ -60,6 +61,9 @@ internal class WalletSelectorMiddleware {
|
|||
is WalletSelectorAction.SelectWallet -> {
|
||||
selectWallet(action.walletId)
|
||||
}
|
||||
is WalletSelectorAction.UnlockWalletWithCard -> {
|
||||
unlockWalletWithCard(action.walletId)
|
||||
}
|
||||
is WalletSelectorAction.RemoveWallets -> {
|
||||
removeWallets(action.walletIdsToRemove, state)
|
||||
}
|
||||
|
|
@ -105,6 +109,8 @@ internal class WalletSelectorMiddleware {
|
|||
}
|
||||
|
||||
private fun unlockWalletsWithBiometry() {
|
||||
Analytics.send(MyWallets.Button.UnlockWithBiometrics)
|
||||
|
||||
scope.launch {
|
||||
userWalletsListManager.unlockWithBiometry()
|
||||
.doOnFailure { error ->
|
||||
|
|
@ -117,6 +123,8 @@ internal class WalletSelectorMiddleware {
|
|||
}
|
||||
|
||||
private fun addWallet() = scope.launch {
|
||||
Analytics.send(MyWallets.Button.ScanNewCard)
|
||||
|
||||
scanCardInternal { scanResponse ->
|
||||
val userWallet = UserWalletBuilder(scanResponse).build()
|
||||
|
||||
|
|
@ -125,15 +133,13 @@ internal class WalletSelectorMiddleware {
|
|||
store.dispatchOnMain(WalletSelectorAction.AddWallet.Error(error))
|
||||
}
|
||||
.doOnSuccess {
|
||||
val selectedWallet = userWalletsListManager.selectedUserWallet.first()
|
||||
val isSavedWalletSelected = userWallet == selectedWallet
|
||||
store.dispatchOnMain(WalletSelectorAction.AddWallet.Success)
|
||||
Analytics.send(MyWallets.CardWasScanned)
|
||||
|
||||
if (isSavedWalletSelected) {
|
||||
updateAccessCodeRequestPolicy(selectedWallet)
|
||||
store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Wallet))
|
||||
store.onUserWalletSelected(selectedWallet)
|
||||
}
|
||||
userWalletsListManager.selectWallet(userWallet.walletId)
|
||||
store.dispatchOnMain(WalletSelectorAction.AddWallet.Success)
|
||||
updateAccessCodeRequestPolicy(userWallet)
|
||||
store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Wallet))
|
||||
store.onUserWalletSelected(userWallet)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -152,7 +158,43 @@ internal class WalletSelectorMiddleware {
|
|||
}
|
||||
}
|
||||
|
||||
private fun unlockWalletWithCard(id: String) {
|
||||
scope.launch {
|
||||
userWalletsListManager.get(UserWalletId(id))
|
||||
.flatMap { userWallet ->
|
||||
updateUserWalletWithScannedCard(userWallet)
|
||||
}
|
||||
.flatMap { updatedUserWallet ->
|
||||
unlockUserWallet(updatedUserWallet)
|
||||
}
|
||||
.doOnFailure { error ->
|
||||
store.dispatchOnMain(WalletSelectorAction.HandleError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun updateUserWalletWithScannedCard(userWallet: UserWallet): CompletionResult<UserWallet> {
|
||||
return tangemSdkManager.scanCard(userWallet.cardId)
|
||||
.map { scannedCard ->
|
||||
userWallet.copy(
|
||||
scanResponse = userWallet.scanResponse.copy(
|
||||
card = scannedCard,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun unlockUserWallet(userWallet: UserWallet): CompletionResult<Unit> {
|
||||
return userWalletsListManager.unlockWithCard(userWallet)
|
||||
.doOnSuccess {
|
||||
store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Wallet))
|
||||
store.onUserWalletSelected(userWallet)
|
||||
}
|
||||
}
|
||||
|
||||
private fun removeWallets(walletIdsToRemove: List<String>, state: WalletSelectorState) {
|
||||
Analytics.send(MyWallets.Button.DeleteWalletTapped)
|
||||
|
||||
scope.launch {
|
||||
when (walletIdsToRemove.size) {
|
||||
state.wallets.size -> clearUserWallets()
|
||||
|
|
@ -165,6 +207,8 @@ internal class WalletSelectorMiddleware {
|
|||
}
|
||||
|
||||
private fun renameWallet(walletId: String, newName: String) {
|
||||
Analytics.send(MyWallets.Button.EditWalletTapped)
|
||||
|
||||
scope.launch {
|
||||
userWalletsListManager.get(walletId = UserWalletId(walletId))
|
||||
.map { it.copy(name = newName) }
|
||||
|
|
@ -221,7 +265,7 @@ internal class WalletSelectorMiddleware {
|
|||
private fun updateAccessCodeRequestPolicy(userWallet: UserWallet) {
|
||||
tangemSdkManager.setAccessCodeRequestPolicy(
|
||||
useBiometricsForAccessCode = preferencesStorage.shouldSaveAccessCodes &&
|
||||
userWallet.scanResponse.card.isAccessCodeSet,
|
||||
userWallet.hasAccessCode,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -233,13 +277,7 @@ internal class WalletSelectorMiddleware {
|
|||
is UserWalletModel.Type.MultiCurrency -> type.copy(
|
||||
tokensCount = walletStores.flatMap { it.walletsData }.size,
|
||||
)
|
||||
is UserWalletModel.Type.SingleCurrency -> type.copy(
|
||||
blockchainName = walletStores
|
||||
.firstOrNull()
|
||||
?.blockchainNetwork
|
||||
?.blockchain
|
||||
?.fullName,
|
||||
)
|
||||
is UserWalletModel.Type.SingleCurrency -> type
|
||||
},
|
||||
fiatBalance = totalFiatBalanceCalculator.calculate(
|
||||
prevAmount = fiatBalance.amount,
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ internal object WalletSelectorReducer {
|
|||
)
|
||||
is WalletSelectorAction.WalletStoresChanged,
|
||||
is WalletSelectorAction.SelectWallet,
|
||||
is WalletSelectorAction.UnlockWalletWithCard,
|
||||
is WalletSelectorAction.RemoveWallets,
|
||||
is WalletSelectorAction.RenameWallet,
|
||||
-> state
|
||||
|
|
@ -66,10 +67,14 @@ internal object WalletSelectorReducer {
|
|||
return this.map { userWallet ->
|
||||
prevWallets
|
||||
.find { it.id == userWallet.walletId.stringValue }
|
||||
?.copy(
|
||||
name = userWallet.name,
|
||||
artworkUrl = userWallet.artworkUrl,
|
||||
)
|
||||
?.let {
|
||||
it.copy(
|
||||
name = userWallet.name,
|
||||
artworkUrl = userWallet.artworkUrl,
|
||||
isLocked = userWallet.isLocked,
|
||||
type = userWallet.getType(prevType = it.type),
|
||||
)
|
||||
}
|
||||
?: with(userWallet) {
|
||||
UserWalletModel(
|
||||
id = walletId.stringValue,
|
||||
|
|
@ -77,6 +82,7 @@ internal object WalletSelectorReducer {
|
|||
artworkUrl = artworkUrl,
|
||||
type = getType(),
|
||||
fiatBalance = TotalFiatBalance.Loading,
|
||||
isLocked = isLocked,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -90,15 +96,18 @@ internal object WalletSelectorReducer {
|
|||
}
|
||||
}
|
||||
|
||||
private fun UserWallet.getType(): UserWalletModel.Type {
|
||||
private fun UserWallet.getType(prevType: UserWalletModel.Type? = null): UserWalletModel.Type {
|
||||
return if (scanResponse.card.isMultiwalletAllowed) {
|
||||
UserWalletModel.Type.MultiCurrency(
|
||||
cardsInWallet = (scanResponse.card.backupStatus as? CardDTO.BackupStatus.Active)
|
||||
?.cardCount?.inc()
|
||||
?: 1,
|
||||
tokensCount = (prevType as? UserWalletModel.Type.MultiCurrency)?.tokensCount ?: 0,
|
||||
)
|
||||
} else {
|
||||
UserWalletModel.Type.SingleCurrency()
|
||||
UserWalletModel.Type.SingleCurrency(
|
||||
blockchainName = scanResponse.getBlockchain().fullName,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -60,6 +60,7 @@ private fun List<UserWalletModel>.toUiModels(
|
|||
name = name,
|
||||
imageUrl = artworkUrl,
|
||||
balance = balance,
|
||||
isLocked = isLocked,
|
||||
cardsInWallet = type.cardsInWallet,
|
||||
tokensCount = type.tokensCount,
|
||||
)
|
||||
|
|
@ -68,6 +69,7 @@ private fun List<UserWalletModel>.toUiModels(
|
|||
name = name,
|
||||
imageUrl = artworkUrl,
|
||||
balance = balance,
|
||||
isLocked = isLocked,
|
||||
tokenName = type.blockchainName ?: "—",
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.tap.features.walletSelector.ui
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
|
|
@ -14,6 +16,8 @@ import androidx.compose.ui.platform.rememberNestedScrollInteropConnection
|
|||
import androidx.fragment.app.viewModels
|
||||
import com.tangem.core.ui.fragments.ComposeBottomSheetFragment
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.MyWallets
|
||||
import com.tangem.tap.features.details.ui.cardsettings.resolveReference
|
||||
import com.tangem.tap.features.walletSelector.ui.components.RenameWalletDialogContent
|
||||
import com.tangem.tap.features.walletSelector.ui.components.WalletSelectorScreenContent
|
||||
|
|
@ -22,6 +26,12 @@ import com.tangem.tap.features.walletSelector.ui.model.RenameWalletDialog
|
|||
internal class WalletSelectorBottomSheetFragment : ComposeBottomSheetFragment<WalletSelectorScreenState>() {
|
||||
private val viewModel by viewModels<WalletSelectorViewModel>()
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
Analytics.send(MyWallets.MyWalletsScreenOpened)
|
||||
|
||||
return super.onCreateDialog(savedInstanceState)
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun provideState(): State<WalletSelectorScreenState> {
|
||||
return viewModel.state.collectAsState()
|
||||
|
|
|
|||
|
|
@ -37,7 +37,9 @@ internal class WalletSelectorViewModel : ViewModel(), StoreSubscriber<WalletSele
|
|||
|
||||
fun walletClicked(walletId: String) = with(state.value) {
|
||||
when {
|
||||
isLocked -> Unit
|
||||
isLocked -> {
|
||||
store.dispatch(WalletSelectorAction.UnlockWalletWithCard(walletId))
|
||||
}
|
||||
editingWalletsIds.isNotEmpty() && !editingWalletsIds.contains(walletId) -> {
|
||||
editWallet(walletId)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ internal object MockData {
|
|||
),
|
||||
name = "Wallet",
|
||||
imageUrl = "https://app.tangem.com/cards/card_default.png",
|
||||
isLocked = false,
|
||||
tokensCount = 12,
|
||||
cardsInWallet = 3,
|
||||
)
|
||||
|
|
@ -26,6 +27,7 @@ internal object MockData {
|
|||
),
|
||||
name = "Wallet",
|
||||
imageUrl = "https://app.tangem.com/cards/card_default.png",
|
||||
isLocked = false,
|
||||
tokenName = "Ethereum",
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,6 @@ internal fun WalletSelectorScreenContent(
|
|||
singleCurrencyWallets = state.singleCurrencyWallets,
|
||||
selectedWalletId = state.selectedWalletId,
|
||||
checkedWalletIds = state.editingWalletsIds,
|
||||
isLocked = state.isLocked,
|
||||
onWalletClick = onWalletClick,
|
||||
onWalletLongClick = onWalletLongClick,
|
||||
)
|
||||
|
|
@ -141,7 +140,6 @@ private fun WalletsList(
|
|||
singleCurrencyWallets: List<UserWalletItem>,
|
||||
selectedWalletId: String?,
|
||||
checkedWalletIds: List<String>,
|
||||
isLocked: Boolean,
|
||||
onWalletClick: (walletId: String) -> Unit,
|
||||
onWalletLongClick: (walletId: String) -> Unit,
|
||||
) {
|
||||
|
|
@ -166,7 +164,6 @@ private fun WalletsList(
|
|||
wallet = wallet,
|
||||
isSelected = wallet.id == selectedWalletId,
|
||||
isChecked = wallet.id in checkedWalletIds,
|
||||
isLocked = isLocked && wallet.id != selectedWalletId,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ internal fun WalletItem(
|
|||
wallet: UserWalletItem,
|
||||
isSelected: Boolean,
|
||||
isChecked: Boolean,
|
||||
isLocked: Boolean,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier,
|
||||
|
|
@ -59,7 +58,7 @@ internal fun WalletItem(
|
|||
SpacerW6()
|
||||
TokensInfo(
|
||||
modifier = Modifier.weight(weight = .4f),
|
||||
isLocked = isLocked,
|
||||
isLocked = wallet.isLocked,
|
||||
balance = wallet.balance,
|
||||
tokensCount = (wallet as? MultiCurrencyUserWalletItem)?.tokensCount,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
package com.tangem.tap.features.walletSelector.ui.model
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.tap.features.details.ui.cardsettings.TextReference
|
||||
import com.tangem.wallet.R
|
||||
|
||||
@Immutable
|
||||
internal sealed interface UserWalletItem {
|
||||
val id: String
|
||||
val name: String
|
||||
val imageUrl: String
|
||||
val balance: Balance
|
||||
val isLocked: Boolean
|
||||
|
||||
val headerText: TextReference
|
||||
get() = when (this) {
|
||||
|
|
@ -17,7 +16,6 @@ internal sealed interface UserWalletItem {
|
|||
is SingleCurrencyUserWalletItem -> TextReference.Res(R.string.user_wallet_list_single_header)
|
||||
}
|
||||
|
||||
@Immutable
|
||||
data class Balance(
|
||||
val amount: String,
|
||||
val isLoading: Boolean,
|
||||
|
|
@ -29,6 +27,7 @@ internal data class MultiCurrencyUserWalletItem(
|
|||
override val name: String,
|
||||
override val imageUrl: String,
|
||||
override val balance: UserWalletItem.Balance,
|
||||
override val isLocked: Boolean,
|
||||
val tokensCount: Int,
|
||||
val cardsInWallet: Int,
|
||||
) : UserWalletItem
|
||||
|
|
@ -38,5 +37,6 @@ internal data class SingleCurrencyUserWalletItem(
|
|||
override val name: String,
|
||||
override val imageUrl: String,
|
||||
override val balance: UserWalletItem.Balance,
|
||||
override val isLocked: Boolean,
|
||||
val tokenName: String,
|
||||
) : UserWalletItem
|
||||
|
|
@ -61,7 +61,7 @@ internal class WelcomeMiddleware {
|
|||
if (selectedUserWallet != null) {
|
||||
tangemSdkManager.setAccessCodeRequestPolicy(
|
||||
useBiometricsForAccessCode = preferencesStorage.shouldSaveAccessCodes &&
|
||||
selectedUserWallet.scanResponse.card.isAccessCodeSet,
|
||||
selectedUserWallet.hasAccessCode,
|
||||
)
|
||||
|
||||
store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.Wallet))
|
||||
|
|
@ -78,14 +78,12 @@ internal class WelcomeMiddleware {
|
|||
scanCardInternal { scanResponse ->
|
||||
val userWallet = UserWalletBuilder(scanResponse).build()
|
||||
|
||||
tangemSdkManager.setAccessCodeRequestPolicy(useBiometricsForAccessCode = false)
|
||||
userWalletsListManager.unlockWithCard(userWallet)
|
||||
.doOnFailure { error ->
|
||||
store.dispatchOnMain(WelcomeAction.ProceedWithCard.Error(error))
|
||||
}
|
||||
.doOnSuccess {
|
||||
tangemSdkManager.setAccessCodeRequestPolicy(
|
||||
useBiometricsForAccessCode = false,
|
||||
)
|
||||
store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.Wallet))
|
||||
store.dispatchOnMain(WelcomeAction.ProceedWithCard.Success)
|
||||
store.onUserWalletSelected(userWallet)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue