Updated on 2026-08-14
This commit is contained in:
commit
5f68b1cc5a
8 changed files with 71 additions and 73 deletions
|
|
@ -1,22 +1,22 @@
|
|||
package com.tangem.tap.common.redux.legacy
|
||||
|
||||
import com.tangem.domain.apptheme.model.AppThemeMode
|
||||
import com.tangem.domain.redux.LegacyAction
|
||||
import com.tangem.tap.common.extensions.dispatchWithMain
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.features.details.redux.AppSettingsState
|
||||
import com.tangem.tap.features.details.redux.DetailsAction
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupStartedSource
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.tap.scope
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.tap.tangemSdkManager
|
||||
import com.tangem.utils.coroutines.JobHolder
|
||||
import com.tangem.utils.coroutines.saveIn
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.*
|
||||
import org.rekotlin.Middleware
|
||||
|
||||
internal object LegacyMiddleware {
|
||||
|
|
@ -42,10 +42,13 @@ internal object LegacyMiddleware {
|
|||
userWalletsListManager.selectedUserWallet
|
||||
.distinctUntilChanged()
|
||||
.onEach { selectedUserWallet ->
|
||||
val initializedAppSettingsStateContent = initializeAppSettingsState(
|
||||
shouldSaveUserWallets = walletsRepository.shouldSaveUserWalletsSync(),
|
||||
)
|
||||
store.dispatchWithMain(
|
||||
DetailsAction.PrepareScreen(
|
||||
scanResponse = selectedUserWallet.scanResponse,
|
||||
shouldSaveUserWallets = walletsRepository.shouldSaveUserWalletsSync(),
|
||||
initializedAppSettingsState = initializedAppSettingsStateContent,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -58,4 +61,22 @@ internal object LegacyMiddleware {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* LEGACY: We need to initialize [AppSettingsState] async to avoid drawing blocking
|
||||
* previously it was initialized in runBlocking and blocked details screen
|
||||
*/
|
||||
private suspend fun initializeAppSettingsState(shouldSaveUserWallets: Boolean): AppSettingsState {
|
||||
return AppSettingsState(
|
||||
isBiometricsAvailable = tangemSdkManager.checkCanUseBiometry(),
|
||||
saveWallets = shouldSaveUserWallets,
|
||||
saveAccessCodes = store.inject(DaggerGraphState::settingsRepository).shouldSaveAccessCodes(),
|
||||
selectedAppCurrency = store.state.globalState.appCurrency,
|
||||
selectedThemeMode = store.inject(DaggerGraphState::appThemeModeRepository).getAppThemeMode().firstOrNull()
|
||||
?: AppThemeMode.DEFAULT,
|
||||
isHidingEnabled = store.inject(DaggerGraphState::balanceHidingRepository)
|
||||
.getBalanceHidingSettings().isHidingEnabledInSettings,
|
||||
needEnrollBiometrics = runCatching(tangemSdkManager::needEnrollBiometrics).getOrNull() ?: false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -10,7 +10,7 @@ sealed class DetailsAction : Action {
|
|||
|
||||
data class PrepareScreen(
|
||||
val scanResponse: ScanResponse,
|
||||
val shouldSaveUserWallets: Boolean,
|
||||
val initializedAppSettingsState: AppSettingsState,
|
||||
) : DetailsAction()
|
||||
|
||||
sealed class AppSettings : DetailsAction() {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,6 @@
|
|||
package com.tangem.tap.features.details.redux
|
||||
|
||||
import com.tangem.domain.apptheme.model.AppThemeMode
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.tap.tangemSdkManager
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.rekotlin.Action
|
||||
|
||||
object DetailsReducer {
|
||||
|
|
@ -36,27 +29,7 @@ private fun internalReduce(action: Action, state: AppState): DetailsState {
|
|||
private fun handlePrepareScreen(action: DetailsAction.PrepareScreen): DetailsState {
|
||||
return DetailsState(
|
||||
scanResponse = action.scanResponse,
|
||||
appSettingsState = AppSettingsState(
|
||||
isBiometricsAvailable = runBlocking {
|
||||
tangemSdkManager.checkCanUseBiometry()
|
||||
},
|
||||
saveWallets = action.shouldSaveUserWallets,
|
||||
saveAccessCodes = runBlocking {
|
||||
store.inject(DaggerGraphState::settingsRepository).shouldSaveAccessCodes()
|
||||
},
|
||||
selectedAppCurrency = store.state.globalState.appCurrency,
|
||||
selectedThemeMode = runBlocking {
|
||||
store.inject(DaggerGraphState::appThemeModeRepository).getAppThemeMode().firstOrNull()
|
||||
?: AppThemeMode.DEFAULT
|
||||
},
|
||||
isHidingEnabled = runBlocking {
|
||||
store.inject(DaggerGraphState::balanceHidingRepository)
|
||||
.getBalanceHidingSettings().isHidingEnabledInSettings
|
||||
},
|
||||
needEnrollBiometrics = runBlocking {
|
||||
runCatching(tangemSdkManager::needEnrollBiometrics).getOrNull() ?: false
|
||||
},
|
||||
),
|
||||
appSettingsState = action.initializedAppSettingsState,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@ package com.tangem.datasource.local.datastore
|
|||
|
||||
import com.tangem.datasource.local.datastore.core.StringKeyDataStore
|
||||
import kotlinx.coroutines.flow.*
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
internal class RuntimeDataStore<Data : Any> : StringKeyDataStore<Data> {
|
||||
|
||||
private val store: MutableSharedFlow<HashMap<String, Data>?> = MutableSharedFlow(replay = 1)
|
||||
private val store: MutableSharedFlow<ConcurrentHashMap<String, Data>?> = MutableSharedFlow(replay = 1)
|
||||
|
||||
init {
|
||||
store.tryEmit(value = null)
|
||||
|
|
@ -61,7 +62,7 @@ internal class RuntimeDataStore<Data : Any> : StringKeyDataStore<Data> {
|
|||
|
||||
override suspend fun remove(keys: Collection<String>) {
|
||||
updateValue { value ->
|
||||
HashMap(value.filterKeys { it !in keys })
|
||||
ConcurrentHashMap(value.filterKeys { it !in keys })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -69,8 +70,10 @@ internal class RuntimeDataStore<Data : Any> : StringKeyDataStore<Data> {
|
|||
store.emit(value = null)
|
||||
}
|
||||
|
||||
private suspend inline fun updateValue(update: (HashMap<String, Data>) -> HashMap<String, Data>) {
|
||||
val storedData = store.firstOrNull() ?: hashMapOf()
|
||||
private suspend inline fun updateValue(
|
||||
update: (ConcurrentHashMap<String, Data>) -> ConcurrentHashMap<String, Data>,
|
||||
) {
|
||||
val storedData = store.firstOrNull() ?: ConcurrentHashMap()
|
||||
val updatedData = update(storedData)
|
||||
|
||||
store.emit(updatedData)
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ internal class TokenListSortingOperations(
|
|||
private fun CryptoCurrencyStatus.getTotalBalance(): BigDecimal {
|
||||
val yieldBalance = value.yieldBalance as? YieldBalance.Data
|
||||
val totalYieldBalance = yieldBalance?.getTotalWithRewardsStakingBalance().orZero()
|
||||
val totalFiatYieldBalance = if (!BlockchainUtils.isIncludeStakingTotalBalance(currency.network.id.value)) {
|
||||
val totalFiatYieldBalance = if (BlockchainUtils.isIncludeStakingTotalBalance(currency.network.id.value)) {
|
||||
totalYieldBalance.multiply(value.fiatRate.orZero())
|
||||
} else {
|
||||
BigDecimal.ZERO
|
||||
|
|
|
|||
|
|
@ -23,12 +23,12 @@ import com.tangem.features.details.utils.SocialsBuilder
|
|||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.version.AppVersionProvider
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -52,42 +52,45 @@ internal class DetailsModel @Inject constructor(
|
|||
|
||||
private val params: DetailsComponent.Params = paramsContainer.require()
|
||||
|
||||
private val items: MutableStateFlow<ImmutableList<DetailsItemUM>> = MutableStateFlow(value = persistentListOf())
|
||||
private val items: MutableStateFlow<ImmutableList<DetailsItemUM>>
|
||||
|
||||
val state: MutableStateFlow<DetailsUM> = MutableStateFlow(
|
||||
value = DetailsUM(
|
||||
items = items.value,
|
||||
footer = DetailsFooterUM(
|
||||
socials = socialsBuilder.buildAll(),
|
||||
appVersion = getAppVersion(),
|
||||
),
|
||||
popBack = router::pop,
|
||||
),
|
||||
)
|
||||
val state: MutableStateFlow<DetailsUM>
|
||||
|
||||
init {
|
||||
// Use to save compatibility with screens that using Redux states
|
||||
bootstrapScreenState()
|
||||
|
||||
val isWalletConnectAvailable = runBlocking {
|
||||
// danger region, this works immediately, but will be refactored later with WC
|
||||
checkIsWalletConnectAvailableUseCase(params.userWalletId).getOrElse {
|
||||
Timber.w("Unable to check WalletConnect availability: $it")
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
items = MutableStateFlow(
|
||||
itemsBuilder.buildAll(
|
||||
isWalletConnectAvailable = isWalletConnectAvailable,
|
||||
onSupportClick = ::sendFeedback,
|
||||
onBuyClick = ::onBuyClick,
|
||||
),
|
||||
)
|
||||
|
||||
state = MutableStateFlow(
|
||||
value = DetailsUM(
|
||||
items = items.value,
|
||||
footer = DetailsFooterUM(
|
||||
socials = socialsBuilder.buildAll(),
|
||||
appVersion = getAppVersion(),
|
||||
),
|
||||
popBack = router::pop,
|
||||
),
|
||||
)
|
||||
|
||||
items
|
||||
.onEach(::updateState)
|
||||
.launchIn(modelScope)
|
||||
|
||||
checkWalletConnectAvailability()
|
||||
}
|
||||
|
||||
private fun checkWalletConnectAvailability() = modelScope.launch {
|
||||
val isWalletConnectAvailable = checkIsWalletConnectAvailableUseCase(params.userWalletId).getOrElse {
|
||||
Timber.w("Unable to check WalletConnect availability: $it")
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
items.value = itemsBuilder.buildAll(
|
||||
isWalletConnectAvailable = isWalletConnectAvailable,
|
||||
onSupportClick = ::sendFeedback,
|
||||
onBuyClick = ::onBuyClick,
|
||||
)
|
||||
}
|
||||
|
||||
private fun bootstrapScreenState() {
|
||||
|
|
|
|||
|
|
@ -48,9 +48,7 @@ internal class SetConfirmationStateInitTransformer(
|
|||
actionType = actionType,
|
||||
balanceState = balanceState,
|
||||
confirmationState = StakingStates.ConfirmationState.Data(
|
||||
isPrimaryButtonEnabled = with(cryptoCurrencyStatus.value) {
|
||||
sources.yieldBalanceSource.isActual() && sources.networkSource.isActual()
|
||||
},
|
||||
isPrimaryButtonEnabled = false,
|
||||
innerState = InnerConfirmationStakingState.ASSENT,
|
||||
feeState = FeeState.Loading,
|
||||
notifications = persistentListOf(),
|
||||
|
|
|
|||
|
|
@ -28,9 +28,9 @@ androidxWorkManager = "2.9.0"
|
|||
# endregion AndroidX
|
||||
|
||||
# region Compose
|
||||
compose-runtime = "1.7.8"
|
||||
compose-foundation = "1.7.8"
|
||||
compose-material = "1.7.8"
|
||||
compose-runtime = "1.7.4"
|
||||
compose-foundation = "1.7.4"
|
||||
compose-material = "1.7.4"
|
||||
compose-material3 = "1.3.1"
|
||||
compose-constraint = "1.0.1"
|
||||
compose-navigation = "2.7.7"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue