Updated on 2026-08-14
This commit is contained in:
parent
1d75f13d4e
commit
b2f12e90aa
22 changed files with 386 additions and 5 deletions
|
|
@ -62,6 +62,7 @@ import com.tangem.tap.domain.walletStores.repository.di.provideDefaultImplementa
|
|||
import com.tangem.tap.domain.walletconnect.WalletConnectRepository
|
||||
import com.tangem.tap.domain.walletconnect2.domain.WalletConnectSessionsRepository
|
||||
import com.tangem.tap.features.customtoken.api.featuretoggles.CustomTokenFeatureToggles
|
||||
import com.tangem.tap.features.details.featuretoggles.DetailsFeatureToggles
|
||||
import com.tangem.tap.proxy.AppStateHolder
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.wallet.BuildConfig
|
||||
|
|
@ -176,6 +177,9 @@ class TapApplication : Application(), ImageLoaderFactory {
|
|||
@Inject
|
||||
lateinit var appThemeModeRepository: AppThemeModeRepository
|
||||
|
||||
@Inject
|
||||
lateinit var detailsFeatureToggles: DetailsFeatureToggles
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
|
|
@ -199,6 +203,7 @@ class TapApplication : Application(), ImageLoaderFactory {
|
|||
appStateHolder = appStateHolder,
|
||||
currenciesRepository = currenciesRepository,
|
||||
appThemeModeRepository = appThemeModeRepository,
|
||||
detailsFeatureToggles = detailsFeatureToggles,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import com.tangem.core.navigation.FragmentShareTransition
|
|||
import com.tangem.feature.referral.ReferralFragment
|
||||
import com.tangem.feature.swap.presentation.SwapFragment
|
||||
import com.tangem.tap.features.customtoken.impl.presentation.AddCustomTokenFragment
|
||||
import com.tangem.tap.features.details.ui.appcurrency.AppCurrencySelectorFragment
|
||||
import com.tangem.tap.features.details.ui.appsettings.AppSettingsFragment
|
||||
import com.tangem.tap.features.details.ui.cardsettings.CardSettingsFragment
|
||||
import com.tangem.tap.features.details.ui.cardsettings.coderecovery.AccessCodeRecoveryFragment
|
||||
|
|
@ -174,5 +175,6 @@ private fun fragmentFactory(screen: AppScreen): Fragment {
|
|||
AppScreen.Welcome -> WelcomeFragment()
|
||||
AppScreen.SaveWallet -> SaveWalletBottomSheetFragment()
|
||||
AppScreen.WalletSelector -> WalletSelectorBottomSheetFragment()
|
||||
AppScreen.AppCurrencySelector -> AppCurrencySelectorFragment()
|
||||
}
|
||||
}
|
||||
|
|
@ -66,7 +66,13 @@ private fun handleAction(action: Action, appState: () -> AppState?, dispatch: Di
|
|||
}
|
||||
}
|
||||
is GlobalAction.RestoreAppCurrency -> {
|
||||
if (store.state.daggerGraphState.get(DaggerGraphState::walletFeatureToggles).isRedesignedScreenEnabled) {
|
||||
val daggerGraphState = store.state.daggerGraphState
|
||||
val walletFeatureToggles = daggerGraphState.get(DaggerGraphState::walletFeatureToggles)
|
||||
val detailsFeatureToggles = daggerGraphState.get(DaggerGraphState::detailsFeatureToggles)
|
||||
|
||||
if (walletFeatureToggles.isRedesignedScreenEnabled ||
|
||||
detailsFeatureToggles.isRedesignedAppCurrencySelectorEnabled
|
||||
) {
|
||||
restoreAppCurrencyNew()
|
||||
} else {
|
||||
restoreAppCurrencyLegacy()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
package com.tangem.tap.features.details.featuretoggles
|
||||
|
||||
import com.tangem.core.featuretoggle.manager.FeatureTogglesManager
|
||||
|
||||
internal class DefaultDetailsFeatureToggles(
|
||||
private val featureTogglesManager: FeatureTogglesManager,
|
||||
) : DetailsFeatureToggles {
|
||||
|
||||
override val isRedesignedAppCurrencySelectorEnabled: Boolean
|
||||
get() = featureTogglesManager.isFeatureEnabled(name = "REDESIGNED_APP_CURRENCY_SELECTOR_ENABLED")
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package com.tangem.tap.features.details.featuretoggles
|
||||
|
||||
interface DetailsFeatureToggles {
|
||||
|
||||
val isRedesignedAppCurrencySelectorEnabled: Boolean
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package com.tangem.tap.features.details.featuretoggles
|
||||
|
||||
import com.tangem.core.featuretoggle.manager.FeatureTogglesManager
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal object DetailsFeatureTogglesModule {
|
||||
|
||||
@Provides
|
||||
fun provideDetailsFeatureToggles(featureTogglesManager: FeatureTogglesManager): DetailsFeatureToggles {
|
||||
return DefaultDetailsFeatureToggles(featureTogglesManager)
|
||||
}
|
||||
}
|
||||
|
|
@ -84,6 +84,10 @@ sealed class DetailsAction : Action {
|
|||
data class ChangeAppThemeMode(
|
||||
val appThemeMode: AppThemeMode,
|
||||
) : AppSettings()
|
||||
|
||||
data class ChangeAppCurrency(
|
||||
val fiatCurrency: FiatCurrency,
|
||||
) : AppSettings()
|
||||
}
|
||||
|
||||
data class ChangeAppCurrency(val fiatCurrency: FiatCurrency) : DetailsAction()
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import com.tangem.tap.features.demo.DemoHelper
|
|||
import com.tangem.tap.features.onboarding.products.twins.redux.CreateTwinWalletMode
|
||||
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.features.walletSelector.redux.WalletSelectorAction
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.tap.tangemSdkManager
|
||||
import com.tangem.wallet.R
|
||||
|
|
@ -206,6 +207,11 @@ class DetailsMiddleware {
|
|||
is DetailsAction.AppSettings.ChangeAppThemeMode -> {
|
||||
changeAppThemeMode(action.appThemeMode)
|
||||
}
|
||||
is DetailsAction.AppSettings.ChangeAppCurrency -> {
|
||||
store.dispatch(GlobalAction.ChangeAppCurrency(action.fiatCurrency))
|
||||
store.dispatch(DetailsAction.ChangeAppCurrency(action.fiatCurrency))
|
||||
store.dispatch(WalletSelectorAction.ChangeAppCurrency(action.fiatCurrency))
|
||||
}
|
||||
is DetailsAction.AppSettings.SwitchPrivacySetting.Success,
|
||||
is DetailsAction.AppSettings.SwitchPrivacySetting.Failure,
|
||||
is DetailsAction.AppSettings.BiometricsStatusChanged,
|
||||
|
|
|
|||
|
|
@ -216,6 +216,11 @@ private fun handlePrivacyAction(action: DetailsAction.AppSettings, state: Detail
|
|||
selectedThemeMode = action.appThemeMode,
|
||||
),
|
||||
)
|
||||
is DetailsAction.AppSettings.ChangeAppCurrency -> state.copy(
|
||||
appSettingsState = state.appSettingsState.copy(
|
||||
selectedFiatCurrency = action.fiatCurrency,
|
||||
),
|
||||
)
|
||||
is DetailsAction.AppSettings.EnrollBiometrics,
|
||||
is DetailsAction.AppSettings.CheckBiometricsStatus,
|
||||
-> state
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
package com.tangem.tap.features.details.ui.appcurrency
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.core.ui.components.SystemBarsEffect
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.screen.ComposeFragment
|
||||
|
|
@ -15,6 +18,8 @@ internal class AppCurrencySelectorFragment : ComposeFragment() {
|
|||
@Inject
|
||||
override lateinit var appThemeModeHolder: AppThemeModeHolder
|
||||
|
||||
private val viewModel: AppCurrencySelectorViewModel by viewModels()
|
||||
|
||||
@Composable
|
||||
override fun ScreenContent(modifier: Modifier) {
|
||||
val systemBarsColor = TangemTheme.colors.background.secondary
|
||||
|
|
@ -22,9 +27,10 @@ internal class AppCurrencySelectorFragment : ComposeFragment() {
|
|||
setSystemBarsColor(systemBarsColor)
|
||||
}
|
||||
|
||||
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
|
||||
AppCurrencySelectorScreen(
|
||||
modifier = modifier,
|
||||
state = AppCurrencySelectorState.Loading({}), // TODO: Will be updated in next MR
|
||||
state = uiState,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package com.tangem.tap.features.details.ui.appcurrency
|
||||
|
||||
internal interface AppCurrencySelectorIntents {
|
||||
|
||||
fun onBackClick()
|
||||
|
||||
fun onSearchClick()
|
||||
|
||||
fun onSearchInputChange(input: String)
|
||||
|
||||
fun onCurrencyClick(currency: AppCurrencySelectorState.Currency)
|
||||
|
||||
fun onDismissSearchClick()
|
||||
}
|
||||
|
|
@ -20,6 +20,29 @@ internal sealed class AppCurrencySelectorState {
|
|||
abstract val items: PersistentList<Currency>
|
||||
abstract val onCurrencyClick: (Currency) -> Unit
|
||||
abstract val onTopBarActionClick: () -> Unit
|
||||
|
||||
fun copySealed(
|
||||
selectedId: String? = this.selectedId,
|
||||
items: PersistentList<Currency> = this.items,
|
||||
scrollToSelected: StateEvent<Int> = this.scrollToSelected,
|
||||
onCurrencyClick: (Currency) -> Unit = this.onCurrencyClick,
|
||||
onTopBarActionClick: () -> Unit = this.onTopBarActionClick,
|
||||
): AppCurrencySelectorState = when (this) {
|
||||
is Default -> this.copy(
|
||||
selectedId = selectedId.orEmpty(),
|
||||
items = items,
|
||||
scrollToSelected = scrollToSelected,
|
||||
onCurrencyClick = onCurrencyClick,
|
||||
onTopBarActionClick = onTopBarActionClick,
|
||||
)
|
||||
is Search -> this.copy(
|
||||
selectedId = selectedId.orEmpty(),
|
||||
items = items,
|
||||
scrollToSelected = scrollToSelected,
|
||||
onCurrencyClick = onCurrencyClick,
|
||||
onTopBarActionClick = onTopBarActionClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
data class Default(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,125 @@
|
|||
package com.tangem.tap.features.details.ui.appcurrency
|
||||
|
||||
import com.tangem.core.ui.event.consumedEvent
|
||||
import com.tangem.core.ui.event.triggeredEvent
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.tap.features.details.ui.appcurrency.converter.CurrencyConverter
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.mutate
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
||||
internal class AppCurrencySelectorStateHolder(
|
||||
private val intents: AppCurrencySelectorIntents,
|
||||
private val onSubscription: () -> Unit,
|
||||
stateFlowScope: CoroutineScope,
|
||||
) {
|
||||
|
||||
private var availableCurrencies: PersistentList<AppCurrencySelectorState.Currency> = persistentListOf()
|
||||
|
||||
private val stateFlowInternal: MutableStateFlow<AppCurrencySelectorState> = MutableStateFlow(getInitialState())
|
||||
|
||||
private val currencyConverter by lazy(mode = LazyThreadSafetyMode.NONE) { CurrencyConverter() }
|
||||
|
||||
val stateFlow: StateFlow<AppCurrencySelectorState> = stateFlowInternal
|
||||
.onSubscription { onSubscription() }
|
||||
.stateIn(
|
||||
scope = stateFlowScope,
|
||||
started = SharingStarted.WhileSubscribed(),
|
||||
initialValue = getInitialState(),
|
||||
)
|
||||
|
||||
fun updateStateWithAvailableCurrencies(currencies: List<AppCurrency>) {
|
||||
availableCurrencies = currencyConverter.convertList(currencies).toPersistentList()
|
||||
|
||||
updateState {
|
||||
when (this) {
|
||||
is AppCurrencySelectorState.Loading -> getContentState(availableCurrencies)
|
||||
is AppCurrencySelectorState.Content -> copySealed(items = availableCurrencies)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun updateStateWithSelectedCurrency(selectedCurrency: AppCurrency, selectedCurrencyIndex: Int) {
|
||||
val selectedCurrencyId = selectedCurrency.code
|
||||
|
||||
updateState {
|
||||
when (this) {
|
||||
is AppCurrencySelectorState.Loading -> this
|
||||
is AppCurrencySelectorState.Content -> copySealed(
|
||||
selectedId = selectedCurrencyId,
|
||||
scrollToSelected = triggeredEvent(selectedCurrencyIndex, ::consumeScrollToSelectedEvent),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun updateStateWithSearch(input: String = "") {
|
||||
val filteredItems = availableCurrencies.mutate { list ->
|
||||
list.removeAll { input.lowercase() !in it.name.lowercase() }
|
||||
}
|
||||
|
||||
updateState {
|
||||
when (this) {
|
||||
is AppCurrencySelectorState.Loading -> this
|
||||
is AppCurrencySelectorState.Search -> copy(items = filteredItems)
|
||||
is AppCurrencySelectorState.Default -> getSearchState(filteredItems, selectedId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun updateStateWithoutSearch() {
|
||||
updateState {
|
||||
when (this) {
|
||||
is AppCurrencySelectorState.Search -> getContentState(availableCurrencies, selectedId)
|
||||
is AppCurrencySelectorState.Default,
|
||||
is AppCurrencySelectorState.Loading,
|
||||
-> this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getInitialState() = AppCurrencySelectorState.Loading(
|
||||
onBackClick = intents::onBackClick,
|
||||
)
|
||||
|
||||
private fun getContentState(
|
||||
items: PersistentList<AppCurrencySelectorState.Currency>,
|
||||
selectedCurrencyId: String = "",
|
||||
) = AppCurrencySelectorState.Default(
|
||||
selectedId = selectedCurrencyId,
|
||||
items = items,
|
||||
onBackClick = intents::onBackClick,
|
||||
onCurrencyClick = intents::onCurrencyClick,
|
||||
onTopBarActionClick = intents::onSearchClick,
|
||||
scrollToSelected = consumedEvent(),
|
||||
)
|
||||
|
||||
private fun getSearchState(
|
||||
filteredItems: PersistentList<AppCurrencySelectorState.Currency>,
|
||||
selectedCurrencyId: String,
|
||||
) = AppCurrencySelectorState.Search(
|
||||
selectedId = selectedCurrencyId,
|
||||
items = filteredItems,
|
||||
scrollToSelected = consumedEvent(),
|
||||
onBackClick = intents::onBackClick,
|
||||
onCurrencyClick = intents::onCurrencyClick,
|
||||
onSearchInputChange = intents::onSearchInputChange,
|
||||
onTopBarActionClick = intents::onDismissSearchClick,
|
||||
)
|
||||
|
||||
private inline fun updateState(block: AppCurrencySelectorState.() -> AppCurrencySelectorState) {
|
||||
stateFlowInternal.update(block)
|
||||
}
|
||||
|
||||
private fun consumeScrollToSelectedEvent() {
|
||||
updateState {
|
||||
when (this) {
|
||||
is AppCurrencySelectorState.Loading -> this
|
||||
is AppCurrencySelectorState.Content -> copySealed(scrollToSelected = consumedEvent())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
package com.tangem.tap.features.details.ui.appcurrency
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.tangem.core.navigation.ReduxNavController
|
||||
import com.tangem.domain.appcurrency.GetAvailableCurrenciesUseCase
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.appcurrency.SelectAppCurrencyUseCase
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
internal class AppCurrencySelectorViewModel @Inject constructor(
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val getAvailableCurrenciesUseCase: GetAvailableCurrenciesUseCase,
|
||||
private val selectAppCurrencyUseCase: SelectAppCurrencyUseCase,
|
||||
private val reduxNavController: ReduxNavController,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : ViewModel(), AppCurrencySelectorIntents {
|
||||
|
||||
private val stateController = AppCurrencySelectorStateHolder(
|
||||
intents = this,
|
||||
onSubscription = { fetchCurrencies() },
|
||||
stateFlowScope = viewModelScope,
|
||||
)
|
||||
|
||||
val uiState: StateFlow<AppCurrencySelectorState> = stateController.stateFlow
|
||||
|
||||
override fun onBackClick() {
|
||||
reduxNavController.popBackStack()
|
||||
}
|
||||
|
||||
override fun onSearchClick() {
|
||||
stateController.updateStateWithSearch()
|
||||
}
|
||||
|
||||
override fun onSearchInputChange(input: String) {
|
||||
stateController.updateStateWithSearch(input)
|
||||
}
|
||||
|
||||
override fun onCurrencyClick(currency: AppCurrencySelectorState.Currency) {
|
||||
viewModelScope.launch(dispatchers.io) {
|
||||
selectAppCurrencyUseCase(currency.id)
|
||||
.onRight { reduxNavController.popBackStack() }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDismissSearchClick() {
|
||||
stateController.updateStateWithoutSearch()
|
||||
}
|
||||
|
||||
private fun fetchCurrencies() {
|
||||
viewModelScope.launch(dispatchers.io) {
|
||||
val availableCurrencies = getAvailableCurrenciesUseCase()
|
||||
.onRight(stateController::updateStateWithAvailableCurrencies)
|
||||
.getOrNull()
|
||||
|
||||
getSelectedAppCurrencyUseCase().collectLatest { maybeSelectedCurrency ->
|
||||
maybeSelectedCurrency
|
||||
.onRight { selectedCurrency ->
|
||||
val selectedCurrencyIndex = availableCurrencies?.indexOfFirst { it == selectedCurrency }
|
||||
|
||||
if (selectedCurrencyIndex != null && selectedCurrencyIndex != -1) {
|
||||
stateController.updateStateWithSelectedCurrency(selectedCurrency, selectedCurrencyIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package com.tangem.tap.features.details.ui.appcurrency.converter
|
||||
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.tap.features.details.ui.appcurrency.AppCurrencySelectorState
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
internal class CurrencyConverter : Converter<AppCurrency, AppCurrencySelectorState.Currency> {
|
||||
|
||||
override fun convert(value: AppCurrency): AppCurrencySelectorState.Currency {
|
||||
val fullCurrencyName = with(value) { "$name ($code) - $symbol" }
|
||||
|
||||
return AppCurrencySelectorState.Currency(value.code, fullCurrencyName)
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,8 @@ import androidx.transition.TransitionInflater
|
|||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.core.ui.screen.ComposeFragment
|
||||
import com.tangem.core.ui.theme.AppThemeModeHolder
|
||||
import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
|
||||
import com.tangem.tap.features.details.featuretoggles.DetailsFeatureToggles
|
||||
import com.tangem.tap.features.details.redux.DetailsAction
|
||||
import com.tangem.tap.features.details.redux.DetailsState
|
||||
import com.tangem.tap.store
|
||||
|
|
@ -22,7 +24,15 @@ internal class AppSettingsFragment : ComposeFragment(), StoreSubscriber<DetailsS
|
|||
@Inject
|
||||
override lateinit var appThemeModeHolder: AppThemeModeHolder
|
||||
|
||||
private val viewModel = AppSettingsViewModel(store)
|
||||
@Inject
|
||||
lateinit var detailsFeatureToggles: DetailsFeatureToggles
|
||||
|
||||
@Inject
|
||||
lateinit var appCurrencyRepository: AppCurrencyRepository
|
||||
|
||||
private val viewModel by lazy(mode = LazyThreadSafetyMode.NONE) {
|
||||
AppSettingsViewModel(store, detailsFeatureToggles, appCurrencyRepository)
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun ScreenContent(modifier: Modifier) {
|
||||
|
|
|
|||
|
|
@ -4,26 +4,49 @@ import androidx.compose.runtime.getValue
|
|||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.LifecycleCoroutineScope
|
||||
import com.tangem.core.navigation.AppScreen
|
||||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
|
||||
import com.tangem.domain.apptheme.model.AppThemeMode
|
||||
import com.tangem.tap.common.entities.FiatCurrency
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.dispatchWithMain
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.features.details.featuretoggles.DetailsFeatureToggles
|
||||
import com.tangem.tap.features.details.redux.AppSetting
|
||||
import com.tangem.tap.features.details.redux.AppSettingsState
|
||||
import com.tangem.tap.features.details.redux.DetailsAction
|
||||
import com.tangem.tap.features.details.redux.DetailsState
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.scope
|
||||
import com.tangem.utils.coroutines.JobHolder
|
||||
import com.tangem.utils.coroutines.saveIn
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import org.rekotlin.Store
|
||||
|
||||
internal class AppSettingsViewModel(private val store: Store<AppState>) {
|
||||
internal class AppSettingsViewModel(
|
||||
private val store: Store<AppState>,
|
||||
private val detailsFeatureToggles: DetailsFeatureToggles,
|
||||
private val appCurrencyRepository: AppCurrencyRepository,
|
||||
) {
|
||||
|
||||
private val itemsFactory = AppSettingsItemsFactory()
|
||||
private val dialogsFactory = AppSettingsDialogsFactory()
|
||||
|
||||
private val appCurrencyUpdatesJobHolder = JobHolder()
|
||||
|
||||
var uiState: AppSettingsScreenState by mutableStateOf(AppSettingsScreenState.Loading)
|
||||
private set
|
||||
|
||||
init {
|
||||
if (detailsFeatureToggles.isRedesignedAppCurrencySelectorEnabled) {
|
||||
bootstrapAppCurrencyUpdates()
|
||||
}
|
||||
}
|
||||
|
||||
fun updateState(state: DetailsState) {
|
||||
uiState = AppSettingsScreenState.Content(
|
||||
items = buildItems(state.appSettingsState),
|
||||
|
|
@ -89,7 +112,13 @@ internal class AppSettingsViewModel(private val store: Store<AppState>) {
|
|||
}
|
||||
|
||||
private fun showAppCurrencySelector() {
|
||||
store.dispatchOnMain(WalletAction.AppCurrencyAction.ChooseAppCurrency)
|
||||
val action = if (detailsFeatureToggles.isRedesignedAppCurrencySelectorEnabled) {
|
||||
NavigationAction.NavigateTo(AppScreen.AppCurrencySelector)
|
||||
} else {
|
||||
WalletAction.AppCurrencyAction.ChooseAppCurrency
|
||||
}
|
||||
|
||||
store.dispatchOnMain(action)
|
||||
}
|
||||
|
||||
private fun showThemeModeSelector(selectedMode: AppThemeMode) {
|
||||
|
|
@ -151,6 +180,17 @@ internal class AppSettingsViewModel(private val store: Store<AppState>) {
|
|||
updateContentState { copy(dialog = null) }
|
||||
}
|
||||
|
||||
private fun bootstrapAppCurrencyUpdates() {
|
||||
appCurrencyRepository
|
||||
.getSelectedAppCurrency()
|
||||
.onEach {
|
||||
val fiatCurrency = with(it) { FiatCurrency(code, name, symbol) }
|
||||
store.dispatchWithMain(DetailsAction.AppSettings.ChangeAppCurrency(fiatCurrency))
|
||||
}
|
||||
.launchIn(scope)
|
||||
.saveIn(appCurrencyUpdatesJobHolder)
|
||||
}
|
||||
|
||||
private fun updateContentState(block: AppSettingsScreenState.Content.() -> AppSettingsScreenState.Content) {
|
||||
uiState = when (val state = uiState) {
|
||||
is AppSettingsScreenState.Content -> block(state)
|
||||
|
|
|
|||
|
|
@ -58,6 +58,10 @@ class AppStateHolder @Inject constructor() : WalletsStateHolder, ReduxNavControl
|
|||
|
||||
override fun getBackStack(): List<AppScreen> = mainStore?.state?.navigationState?.backStack.orEmpty()
|
||||
|
||||
override fun popBackStack(screen: AppScreen?) {
|
||||
mainStore?.dispatch(NavigationAction.PopBackTo(screen))
|
||||
}
|
||||
|
||||
override fun dispatch(action: Action) {
|
||||
mainStore?.dispatch(action)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import com.tangem.tap.domain.walletconnect2.domain.WalletConnectInteractor
|
|||
import com.tangem.tap.domain.walletconnect2.domain.WalletConnectRepository
|
||||
import com.tangem.tap.domain.walletconnect2.domain.WalletConnectSessionsRepository
|
||||
import com.tangem.tap.features.customtoken.api.featuretoggles.CustomTokenFeatureToggles
|
||||
import com.tangem.tap.features.details.featuretoggles.DetailsFeatureToggles
|
||||
import com.tangem.tap.proxy.AppStateHolder
|
||||
import org.rekotlin.StateType
|
||||
|
||||
|
|
@ -40,6 +41,7 @@ data class DaggerGraphState(
|
|||
val walletManagersFacade: WalletManagersFacade? = null,
|
||||
val appStateHolder: AppStateHolder? = null,
|
||||
val appThemeModeRepository: AppThemeModeRepository? = null,
|
||||
val detailsFeatureToggles: DetailsFeatureToggles? = null,
|
||||
|
||||
// FIXME: It is used only for TokensList screen. Remove after refactoring of TokensList
|
||||
val currenciesRepository: CurrenciesRepository? = null,
|
||||
|
|
|
|||
|
|
@ -22,5 +22,9 @@
|
|||
{
|
||||
"name": "SHOPIFY_DYNAMIC_ENABLED",
|
||||
"version": "undefined"
|
||||
},
|
||||
{
|
||||
"name": "REDESIGNED_APP_CURRENCY_SELECTOR_ENABLED",
|
||||
"version": "undefined"
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -35,4 +35,5 @@ enum class AppScreen(val isDialogFragment: Boolean = false) {
|
|||
Welcome,
|
||||
SaveWallet(isDialogFragment = true),
|
||||
WalletSelector(isDialogFragment = true),
|
||||
AppCurrencySelector,
|
||||
}
|
||||
|
|
@ -10,5 +10,7 @@ interface ReduxNavController {
|
|||
/** Navigate by [action] */
|
||||
fun navigate(action: NavigationAction)
|
||||
|
||||
fun popBackStack(screen: AppScreen? = null)
|
||||
|
||||
fun getBackStack(): List<AppScreen>
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue