Updated on 2026-08-14

This commit is contained in:
Tangem 2024-06-24 10:50:03 +01:00
commit bc84d8f5f8
579 changed files with 13604 additions and 3422 deletions

View file

@ -14,7 +14,8 @@ import androidx.lifecycle.Lifecycle
import androidx.transition.TransitionInflater
import com.google.android.material.snackbar.Snackbar
import com.tangem.common.extensions.VoidCallback
import com.tangem.core.navigation.NavigationAction
import com.tangem.common.routing.AppRouter
import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.store
import com.tangem.wallet.R
@ -36,7 +37,7 @@ abstract class BaseFragment(layoutId: Int) : Fragment(layoutId), FragmentOnBackP
}
override fun handleOnBackPressed() {
store.dispatch(NavigationAction.PopBackTo())
store.dispatchNavigationAction(AppRouter::pop)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

View file

@ -1,12 +1,12 @@
package com.tangem.tap.features.customtoken.impl.presentation
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.hilt.navigation.compose.hiltViewModel
import com.tangem.core.ui.UiDependencies
import com.tangem.core.ui.components.SystemBarsEffect
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.screen.ComposeFragment
import com.tangem.tap.features.customtoken.impl.presentation.ui.AddCustomTokenScreen
@ -30,12 +30,10 @@ internal class AddCustomTokenFragment : ComposeFragment() {
val viewModel = hiltViewModel<AddCustomTokenViewModel>().apply {
LocalLifecycleOwner.current.lifecycle.addObserver(this)
}
val statusBarColor = TangemTheme.colors.background.secondary
SystemBarsEffect {
setSystemBarsColor(color = statusBarColor)
}
AddCustomTokenScreen(
modifier = Modifier.systemBarsPadding(),
modifier = Modifier
.background(TangemTheme.colors.background.primary)
.systemBarsPadding(),
stateHolder = viewModel.uiState,
)
}

View file

@ -1,9 +1,11 @@
package com.tangem.tap.features.customtoken.impl.presentation.routers
import com.tangem.blockchain.common.Blockchain
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.AppRouter
import com.tangem.common.routing.utils.popTo
import com.tangem.tap.common.extensions.dispatchDialogShow
import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.common.redux.AppDialog
import com.tangem.tap.store
import com.tangem.wallet.R
@ -12,11 +14,11 @@ import com.tangem.wallet.R
internal class DefaultCustomTokenRouter : CustomTokenRouter {
override fun popBackStack() {
store.dispatch(NavigationAction.PopBackTo())
store.dispatchNavigationAction(AppRouter::pop)
}
override fun openWalletScreen() {
store.dispatch(NavigationAction.PopBackTo(screen = AppScreen.Wallet))
store.dispatchNavigationAction { popTo<AppRoute.Wallet>() }
}
override fun openUnsupportedNetworkAlert(blockchain: Blockchain) {
@ -32,7 +34,7 @@ internal class DefaultCustomTokenRouter : CustomTokenRouter {
val alert = AppDialog.SimpleOkDialogRes(
headerId = R.string.common_error,
messageId = R.string.common_unknown_error,
onOk = { store.dispatch(NavigationAction.PopBackTo()) },
onOk = { store.dispatchNavigationAction(AppRouter::pop) },
)
store.dispatchDialogShow(alert)
}

View file

@ -97,6 +97,8 @@ sealed class DetailsAction : Action {
data class ChangeAppCurrency(
val currency: AppCurrency,
) : AppSettings()
data class Prepare(val state: AppSettingsState) : AppSettings()
}
data class ChangeAppCurrency(val currency: AppCurrency) : DetailsAction()

View file

@ -5,9 +5,11 @@ import com.tangem.common.*
import com.tangem.common.core.TangemError
import com.tangem.common.core.TangemSdkError
import com.tangem.common.core.UserCodeRequestPolicy
import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.AppRouter
import com.tangem.common.routing.utils.popTo
import com.tangem.core.analytics.Analytics
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
@ -20,6 +22,7 @@ import com.tangem.domain.wallets.builder.UserWalletIdBuilder
import com.tangem.domain.wallets.legacy.UserWalletsListError
import com.tangem.domain.wallets.legacy.asLockable
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.tap.*
import com.tangem.tap.common.analytics.events.AnalyticsParam
import com.tangem.tap.common.analytics.events.Settings
import com.tangem.tap.common.extensions.*
@ -30,9 +33,6 @@ 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.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 com.tangem.wallet.R
@ -72,7 +72,8 @@ class DetailsMiddleware {
is DetailsAction.AppSettings -> appSettingsMiddleware.handle(state, action)
is DetailsAction.ReCreateTwinsWallet -> {
store.dispatch(TwinCardsAction.SetMode(CreateTwinWalletMode.RecreateWallet))
store.dispatch(NavigationAction.NavigateTo(AppScreen.OnboardingTwins))
store.dispatchNavigationAction { push(AppRoute.OnboardingTwins) }
}
is DetailsAction.AccessCodeRecovery -> accessCodeRecoveryMiddleware.handle(state, action)
is DetailsAction.ScanCard -> scanCard(state)
@ -92,7 +93,7 @@ class DetailsMiddleware {
store.dispatch(DetailsAction.ReCreateTwinsWallet)
return
} else {
store.dispatch(NavigationAction.NavigateTo(AppScreen.ResetToFactory))
store.dispatchNavigationAction { push(AppRoute.ResetToFactory) }
}
}
is DetailsAction.ResetToFactory.Proceed -> {
@ -133,15 +134,15 @@ class DetailsMiddleware {
val selectedUserWallet = userWalletsListManager.selectedUserWalletSync
if (selectedUserWallet != null) {
store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Wallet))
store.dispatchNavigationAction { popTo<AppRoute.Wallet>() }
store.onUserWalletSelected(selectedUserWallet)
} else {
val isLocked = runCatching { userWalletsListManager.asLockable()?.isLockedSync }
.fold(onSuccess = { true }, onFailure = { false })
if (isLocked && userWalletsListManager.hasUserWallets) {
store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Welcome))
store.dispatchNavigationAction { replaceAll(AppRoute.Welcome()) }
} else {
store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Home))
store.dispatchNavigationAction { replaceAll(AppRoute.Home) }
}
}
}
@ -165,7 +166,7 @@ class DetailsMiddleware {
fun handle(action: DetailsAction.ManageSecurity, detailsState: DetailsState) {
when (action) {
is DetailsAction.ManageSecurity.OpenSecurity -> {
store.dispatch(NavigationAction.NavigateTo(AppScreen.DetailsSecurity))
store.dispatchNavigationAction { push(AppRoute.DetailsSecurity) }
}
is DetailsAction.ManageSecurity.SaveChanges -> {
val cardSettingsState = detailsState.cardSettingsState
@ -184,7 +185,7 @@ class DetailsMiddleware {
is CompletionResult.Success -> {
Analytics.send(Settings.CardSettings.SecurityModeChanged(paramValue))
store.dispatch(GlobalAction.UpdateSecurityOptions(selectedOption))
store.dispatch(NavigationAction.PopBackTo())
store.dispatchNavigationAction(AppRouter::pop)
store.dispatch(DetailsAction.ManageSecurity.SaveChanges.Success)
}
is CompletionResult.Failure -> {
@ -244,6 +245,7 @@ class DetailsMiddleware {
is DetailsAction.AppSettings.SwitchPrivacySetting.Success,
is DetailsAction.AppSettings.SwitchPrivacySetting.Failure,
is DetailsAction.AppSettings.BiometricsStatusChanged,
is DetailsAction.AppSettings.Prepare,
-> Unit
}
}
@ -273,7 +275,7 @@ class DetailsMiddleware {
private fun enrollBiometrics() {
Analytics.send(Settings.AppSettings.ButtonEnableBiometricAuthentication)
store.dispatchOnMain(NavigationAction.OpenBiometricsSettings)
activityResultCaller.openSystemBiometrySettings()
}
private fun changeAppThemeMode(appThemeMode: AppThemeMode) {
@ -394,7 +396,7 @@ class DetailsMiddleware {
deleteSavedAccessCodes()
store.inject(DaggerGraphState::walletsRepository).saveShouldSaveUserWallets(item = false)
store.dispatchWithMain(NavigationAction.PopBackTo(AppScreen.Home))
store.dispatchNavigationAction { popTo<AppRoute.Home>() }
return CompletionResult.Success(Unit)
}
@ -433,7 +435,7 @@ class DetailsMiddleware {
when (action) {
is DetailsAction.AccessCodeRecovery.Open -> {
Analytics.send(Settings.CardSettings.AccessCodeRecoveryButton())
store.dispatch(NavigationAction.NavigateTo(AppScreen.AccessCodeRecovery))
store.dispatchNavigationAction { push(AppRoute.AccessCodeRecovery) }
}
is DetailsAction.AccessCodeRecovery.SaveChanges -> {
scope.launch {
@ -445,7 +447,7 @@ class DetailsMiddleware {
AnalyticsParam.AccessCodeRecoveryStatus.from(action.enabled),
),
)
store.dispatchOnMain(NavigationAction.PopBackTo())
store.dispatchNavigationAction(AppRouter::pop)
store.dispatchOnMain(
DetailsAction.AccessCodeRecovery.SaveChanges.Success(action.enabled),
)
@ -504,7 +506,7 @@ class DetailsMiddleware {
store.dispatchWithMain(DetailsAction.ScanAndSaveUserWallet.Success)
},
disclaimerWillShow = {
store.dispatchOnMain(NavigationAction.PopBackTo())
store.dispatchNavigationAction(AppRouter::pop)
},
onSuccess = { scanResponse ->
createUserWallet(scanResponse)
@ -548,7 +550,7 @@ class DetailsMiddleware {
store.onUserWalletSelected(userWallet)
store.dispatchWithMain(DetailsAction.ScanAndSaveUserWallet.Success)
store.dispatchWithMain(NavigationAction.PopBackTo(AppScreen.Wallet))
store.dispatchNavigationAction { popTo<AppRoute.Wallet>() }
}
.doOnFailure { error ->
if (error is UserWalletsListError.WalletAlreadySaved) {
@ -556,7 +558,7 @@ class DetailsMiddleware {
store.onUserWalletSelected(userWallet)
store.dispatchWithMain(DetailsAction.ScanAndSaveUserWallet.Success)
store.dispatchWithMain(NavigationAction.PopBackTo(AppScreen.Wallet))
store.dispatchNavigationAction { popTo<AppRoute.Wallet>() }
} else {
Timber.e(error, "Unable to create user wallet")
handleError(error, prevUseBiometricsForAccessCode)

View file

@ -1,6 +1,6 @@
package com.tangem.tap.features.details.redux
import com.tangem.core.navigation.AppScreen
import com.tangem.common.routing.AppRoute
import com.tangem.domain.apptheme.model.AppThemeMode
import com.tangem.domain.common.CardTypesResolver
import com.tangem.domain.common.util.cardTypesResolver
@ -69,10 +69,12 @@ private fun internalReduce(action: Action, state: AppState): DetailsState {
}
private fun handlePrepareScreen(action: DetailsAction.PrepareScreen, state: AppState): DetailsState {
val router = store.inject(DaggerGraphState::appRouter)
return DetailsState(
scanResponse = action.scanResponse,
// If the current screen is ResetToFactory, we must save the ResetToFactory's state
cardSettingsState = if (store.state.navigationState.backStack.lastOrNull() == AppScreen.ResetToFactory) {
cardSettingsState = if (router.stack.lastOrNull() is AppRoute.ResetToFactory) {
state.detailsState.cardSettingsState
} else {
null
@ -281,6 +283,9 @@ private fun handlePrivacyAction(action: DetailsAction.AppSettings, state: Detail
isHidingEnabled = action.hideBalance,
),
)
is DetailsAction.AppSettings.Prepare -> state.copy(
appSettingsState = action.state,
)
is DetailsAction.AppSettings.EnrollBiometrics,
is DetailsAction.AppSettings.CheckBiometricsStatus,
-> state

View file

@ -1,19 +1,17 @@
package com.tangem.tap.features.details.redux.walletconnect
import androidx.core.os.bundleOf
import com.tangem.blockchain.common.WalletManager
import com.tangem.blockchainsdk.utils.toNetworkId
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.common.routing.AppRoute
import com.tangem.domain.qrscanning.models.SourceType
import com.tangem.feature.qrscanning.QrScanningRouter
import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.extensions.inject
import com.tangem.tap.common.redux.AppDialog
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.domain.walletconnect2.domain.WalletConnectInteractor
import com.tangem.tap.domain.walletconnect2.domain.LegacyWalletConnectRepository
import com.tangem.tap.domain.walletconnect2.domain.WalletConnectInteractor
import com.tangem.tap.domain.walletconnect2.domain.WcPreparedRequest
import com.tangem.tap.domain.walletconnect2.domain.models.Account
import com.tangem.tap.domain.walletconnect2.domain.models.WalletConnectError
@ -62,14 +60,7 @@ class WalletConnectMiddleware {
// TODO check
store.dispatchOnMain(WalletConnectAction.ShowClipboardOrScanQrDialog(uri))
} else {
store.dispatchOnMain(
NavigationAction.NavigateTo(
screen = AppScreen.QrScanning,
bundle = bundleOf(
QrScanningRouter.SOURCE_KEY to SourceType.WALLET_CONNECT,
),
),
)
store.dispatchNavigationAction { push(AppRoute.QrScanning(SourceType.WALLET_CONNECT)) }
}
}
is WalletConnectAction.ShowClipboardOrScanQrDialog -> {

View file

@ -5,9 +5,9 @@ import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.TransactionData
import com.tangem.blockchain.common.WalletManager
import com.tangem.blockchain.common.derivation.DerivationStyle
import com.tangem.core.navigation.StateDialog
import com.tangem.crypto.hdWallet.DerivationPath
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.redux.StateDialog
import com.tangem.tap.domain.walletconnect2.domain.WcPreparedRequest
import com.tangem.tap.domain.walletconnect2.domain.WcSignMessage
import com.tangem.tap.domain.walletconnect2.domain.models.WalletConnectEvents

View file

@ -6,8 +6,7 @@ import androidx.compose.ui.Modifier
import androidx.fragment.app.viewModels
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tangem.core.ui.UiDependencies
import com.tangem.core.ui.components.SystemBarsEffect
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.components.NavigationBar3ButtonsScrim
import com.tangem.core.ui.screen.ComposeFragment
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@ -22,12 +21,8 @@ internal class AppCurrencySelectorFragment : ComposeFragment() {
@Composable
override fun ScreenContent(modifier: Modifier) {
val systemBarsColor = TangemTheme.colors.background.secondary
SystemBarsEffect {
setSystemBarsColor(systemBarsColor)
}
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
NavigationBar3ButtonsScrim()
AppCurrencySelectorScreen(
modifier = modifier,
state = uiState,

View file

@ -16,6 +16,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
@ -40,7 +41,9 @@ internal fun AppCurrencySelectorScreen(state: AppCurrencySelectorState, modifier
val listState = rememberLazyListState()
Scaffold(
modifier = modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
modifier = modifier
.imePadding()
.nestedScroll(scrollBehavior.nestedScrollConnection),
containerColor = TangemTheme.colors.background.secondary,
topBar = {
TopBar(
@ -49,6 +52,7 @@ internal fun AppCurrencySelectorScreen(state: AppCurrencySelectorState, modifier
state = state,
)
},
contentWindowInsets = ScaffoldDefaults.contentWindowInsets.exclude(WindowInsets.navigationBars),
content = { paddingValues ->
val contentModifier = Modifier
.padding(paddingValues)
@ -62,7 +66,7 @@ internal fun AppCurrencySelectorScreen(state: AppCurrencySelectorState, modifier
modifier = contentModifier,
listState = listState,
currencies = state.items,
selectedId = state.selectedId.orEmpty(),
selectedId = state.selectedId,
onCurrencyClick = state.onCurrencyClick,
)
}
@ -175,6 +179,7 @@ private fun SearchBar(onInputChange: (String) -> Unit, modifier: Modifier = Modi
@Composable
private fun LoadingList(modifier: Modifier = Modifier) {
val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() }
Column(modifier = modifier) {
repeat(times = 10) {
Row(
@ -199,6 +204,7 @@ private fun LoadingList(modifier: Modifier = Modifier) {
)
}
}
Spacer(Modifier.height(bottomBarHeight))
}
}
@ -210,9 +216,11 @@ private fun CurrenciesList(
onCurrencyClick: (Currency) -> Unit,
modifier: Modifier = Modifier,
) {
val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() }
LazyColumn(
modifier = modifier,
state = listState,
contentPadding = PaddingValues(bottom = bottomBarHeight),
) {
items(
items = currencies,

View file

@ -2,8 +2,9 @@ package com.tangem.tap.features.details.ui.appcurrency
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.tangem.common.routing.AppRouter
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.navigation.ReduxNavController
import com.tangem.domain.appcurrency.GetAvailableCurrenciesUseCase
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.appcurrency.SelectAppCurrencyUseCase
@ -20,7 +21,7 @@ internal class AppCurrencySelectorViewModel @Inject constructor(
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
private val getAvailableCurrenciesUseCase: GetAvailableCurrenciesUseCase,
private val selectAppCurrencyUseCase: SelectAppCurrencyUseCase,
private val reduxNavController: ReduxNavController,
private val router: AppRouter,
private val dispatchers: CoroutineDispatcherProvider,
private val analyticsEventHandler: AnalyticsEventHandler,
) : ViewModel(), AppCurrencySelectorIntents {
@ -34,7 +35,7 @@ internal class AppCurrencySelectorViewModel @Inject constructor(
val uiState: StateFlow<AppCurrencySelectorState> = stateController.stateFlow
override fun onBackClick() {
reduxNavController.popBackStack()
router.pop()
}
override fun onSearchClick() {
@ -52,7 +53,7 @@ internal class AppCurrencySelectorViewModel @Inject constructor(
analyticsEventHandler.send(
event = Settings.AppSettings.MainCurrencyChanged(currencyType = currency.name),
)
reduxNavController.popBackStack()
router.pop()
}
}
}

View file

@ -6,10 +6,12 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tangem.core.navigation.NavigationAction
import com.tangem.common.routing.AppRouter
import com.tangem.core.ui.UiDependencies
import com.tangem.core.ui.screen.ComposeFragment
import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.features.details.redux.DetailsAction
import com.tangem.tap.store
import dagger.hilt.android.AndroidEntryPoint
@ -36,7 +38,7 @@ internal class AppSettingsFragment : ComposeFragment() {
state = state,
onBackClick = {
store.dispatch(DetailsAction.ResetCardSettingsData)
store.dispatch(NavigationAction.PopBackTo())
store.dispatchNavigationAction(AppRouter::pop)
},
)
}

View file

@ -1,13 +1,17 @@
package com.tangem.tap.features.details.ui.appsettings
import android.content.res.Configuration
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
@ -32,6 +36,7 @@ internal fun AppSettingsScreen(state: AppSettingsScreenState, onBackClick: () ->
},
titleRes = R.string.app_settings_title,
onBackClick = onBackClick,
addBottomInsets = false,
)
}
@ -44,7 +49,11 @@ private fun AppSettings(state: AppSettingsScreenState.Content) {
null -> Unit
}
LazyColumn {
val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() }
LazyColumn(
contentPadding = PaddingValues(bottom = bottomBarHeight),
) {
items(
items = state.items,
key = Item::id,

View file

@ -1,16 +1,20 @@
package com.tangem.tap.features.details.ui.appsettings
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ViewModel
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.*
import com.tangem.common.routing.AppRoute
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
import com.tangem.domain.apptheme.model.AppThemeMode
import com.tangem.domain.apptheme.repository.AppThemeModeRepository
import com.tangem.domain.balancehiding.repositories.BalanceHidingRepository
import com.tangem.domain.settings.CanUseBiometryUseCase
import com.tangem.domain.settings.repositories.SettingsRepository
import com.tangem.domain.wallets.repository.WalletsRepository
import com.tangem.features.details.DetailsFeatureToggles
import com.tangem.tap.common.analytics.events.AnalyticsParam
import com.tangem.tap.common.analytics.events.Settings
import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.extensions.dispatchWithMain
import com.tangem.tap.features.details.redux.AppSetting
@ -26,14 +30,22 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import org.rekotlin.StoreSubscriber
import javax.inject.Inject
@Suppress("LongParameterList")
@HiltViewModel
internal class AppSettingsViewModel @Inject constructor(
private val appCurrencyRepository: AppCurrencyRepository,
private val walletsRepository: WalletsRepository,
private val canUseBiometryUseCase: CanUseBiometryUseCase,
private val balanceHidingRepository: BalanceHidingRepository,
private val analyticsEventHandler: AnalyticsEventHandler,
private val appThemeModeRepository: AppThemeModeRepository,
private val settingsRepository: SettingsRepository,
private val appSettingsItemsAnalyticsSender: AppSettingsItemsAnalyticsSender,
private val detailsFeatureToggles: DetailsFeatureToggles,
) : ViewModel(),
StoreSubscriber<DetailsState>,
DefaultLifecycleObserver {
@ -50,6 +62,9 @@ internal class AppSettingsViewModel @Inject constructor(
init {
bootstrapAppCurrencyUpdates()
if (detailsFeatureToggles.isRedesignEnabled) {
bootstrapBiometricsUpdates()
}
subscribeToStoreChanges()
sendItemsAnalytics()
@ -128,7 +143,7 @@ internal class AppSettingsViewModel @Inject constructor(
}
private fun showAppCurrencySelector() {
store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.AppCurrencySelector))
store.dispatchNavigationAction { push(AppRoute.AppCurrencySelector) }
}
private fun showThemeModeSelector(selectedMode: AppThemeMode) {
@ -214,6 +229,19 @@ internal class AppSettingsViewModel @Inject constructor(
.saveIn(appCurrencyUpdatesJobHolder)
}
private fun bootstrapBiometricsUpdates() = viewModelScope.launch {
val state = AppSettingsState(
saveWallets = walletsRepository.shouldSaveUserWalletsSync(),
saveAccessCodes = settingsRepository.shouldSaveAccessCodes(),
isBiometricsAvailable = canUseBiometryUseCase(),
isHidingEnabled = balanceHidingRepository.getBalanceHidingSettings().isHidingEnabledInSettings,
selectedAppCurrency = appCurrencyRepository.getSelectedAppCurrency().firstOrNull() ?: AppCurrency.Default,
selectedThemeMode = appThemeModeRepository.getAppThemeMode().firstOrNull() ?: AppThemeMode.DEFAULT,
)
store.dispatchWithMain(DetailsAction.AppSettings.Prepare(state))
}
private fun subscribeToStoreChanges() {
store.subscribe(subscriber = this) { state ->
state.skipRepeats { oldState, newState ->

View file

@ -4,9 +4,11 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.fragment.app.viewModels
import com.tangem.core.navigation.NavigationAction
import com.tangem.common.routing.AppRouter
import com.tangem.core.ui.UiDependencies
import com.tangem.core.ui.screen.ComposeFragment
import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.features.details.redux.DetailsAction
import com.tangem.tap.store
import dagger.hilt.android.AndroidEntryPoint
@ -29,7 +31,7 @@ internal class CardSettingsFragment : ComposeFragment() {
state = viewModel.screenState.value,
onBackClick = {
store.dispatch(DetailsAction.ResetCardSettingsData)
store.dispatch(NavigationAction.PopBackTo())
store.dispatchNavigationAction(AppRouter::pop)
},
)
}

View file

@ -4,9 +4,10 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Modifier
import com.tangem.core.navigation.NavigationAction
import com.tangem.common.routing.AppRouter
import com.tangem.core.ui.UiDependencies
import com.tangem.core.ui.screen.ComposeFragment
import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.features.details.redux.DetailsState
import com.tangem.tap.store
import dagger.hilt.android.AndroidEntryPoint
@ -28,7 +29,7 @@ class AccessCodeRecoveryFragment : ComposeFragment(), StoreSubscriber<DetailsSta
override fun ScreenContent(modifier: Modifier) {
AccessCodeRecoveryScreen(
state = screenState.value,
onBackClick = { store.dispatch(NavigationAction.PopBackTo()) },
onBackClick = { store.dispatchNavigationAction(AppRouter::pop) },
)
}

View file

@ -13,8 +13,8 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.components.PrimaryButtonIconEnd
import com.tangem.core.ui.components.SystemBarsEffect
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.utils.WindowInsetsZero
import com.tangem.wallet.R
@Composable
@ -24,31 +24,42 @@ internal fun SettingsScreensScaffold(
modifier: Modifier = Modifier,
@StringRes titleRes: Int? = null,
snackbarHostState: SnackbarHostState = remember { SnackbarHostState() },
addBottomInsets: Boolean = true,
fab: @Composable () -> Unit = {},
) {
val state = rememberScaffoldState(snackbarHostState = snackbarHostState)
val backgroundColor = TangemTheme.colors.background.secondary
BackHandler(onBack = onBackClick)
SystemBarsEffect {
setSystemBarsColor(backgroundColor)
}
Scaffold(
scaffoldState = state,
topBar = {
EmptyTopBarWithNavigation(
modifier = Modifier.statusBarsPadding(),
onBackClick = onBackClick,
backgroundColor = backgroundColor,
)
},
modifier = modifier.systemBarsPadding(),
modifier = modifier,
contentWindowInsets = WindowInsetsZero,
backgroundColor = backgroundColor,
floatingActionButton = fab,
content = { paddings ->
floatingActionButton = {
Box(modifier = Modifier.navigationBarsPadding()) {
fab()
}
},
content = { paddingValues ->
Column(
modifier = Modifier
.padding(paddings)
.run {
if (addBottomInsets) {
navigationBarsPadding()
} else {
this
}
}
.padding(paddingValues)
.fillMaxSize(),
) {
if (titleRes != null) {
@ -81,9 +92,11 @@ internal fun ScreenTitle(titleRes: Int, modifier: Modifier = Modifier) {
@Composable
internal fun EmptyTopBarWithNavigation(
onBackClick: () -> Unit,
modifier: Modifier = Modifier,
backgroundColor: Color = TangemTheme.colors.background.primary,
) {
TopAppBar(
modifier = modifier,
title = { },
navigationIcon =
{

View file

@ -3,13 +3,14 @@ package com.tangem.tap.features.details.ui.details
import android.os.Bundle
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.tangem.common.routing.AppRouter
import com.tangem.core.analytics.Analytics
import com.tangem.core.navigation.NavigationAction
import com.tangem.core.ui.UiDependencies
import com.tangem.core.ui.screen.ComposeFragment
import com.tangem.domain.wallets.legacy.UserWalletsListManager
import com.tangem.domain.wallets.repository.WalletsRepository
import com.tangem.tap.common.analytics.events.Settings
import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.features.details.redux.DetailsState
import com.tangem.tap.store
import dagger.hilt.android.AndroidEntryPoint
@ -45,7 +46,7 @@ internal class DetailsFragment : ComposeFragment(), StoreSubscriber<DetailsState
DetailsScreen(
modifier = modifier,
state = detailsViewModel.detailsScreenState.value,
onBackClick = { store.dispatch(NavigationAction.PopBackTo()) },
onBackClick = { store.dispatchNavigationAction(AppRouter::pop) },
)
}

View file

@ -3,11 +3,11 @@ package com.tangem.tap.features.details.ui.details
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import com.tangem.common.extensions.guard
import com.tangem.common.routing.AppRoute
import com.tangem.core.analytics.Analytics
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.Basic
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.core.ui.event.StateEvent
import com.tangem.core.ui.event.consumedEvent
import com.tangem.core.ui.event.triggeredEvent
@ -16,15 +16,14 @@ import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.wallets.legacy.UserWalletsListManager
import com.tangem.domain.wallets.repository.WalletsRepository
import com.tangem.tap.common.analytics.events.Settings
import com.tangem.tap.common.extensions.addContext
import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.extensions.dispatchWithMain
import com.tangem.tap.common.extensions.*
import com.tangem.tap.common.feedback.FeedbackEmail
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.features.details.redux.DetailsAction
import com.tangem.tap.features.details.redux.DetailsState
import com.tangem.tap.features.disclaimer.redux.DisclaimerAction
import com.tangem.tap.features.disclaimer.redux.DisclaimerSource
import com.tangem.tap.features.home.LocaleRegionProvider
import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE
import com.tangem.tap.scope
@ -128,15 +127,17 @@ internal class DetailsViewModel(
}
private fun navigateToTesterMenu() {
store.state.daggerGraphState.testerRouter?.startTesterScreen()
store.dispatchNavigationAction {
push(AppRoute.TesterMenu)
}
}
private fun navigateToToS() {
store.dispatchOnMain(DisclaimerAction.Show(AppScreen.Details))
store.dispatchOnMain(DisclaimerAction.Show(DisclaimerSource.Details))
}
private fun navigateToReferralProgram() {
store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.ReferralProgram))
store.dispatchNavigationAction { push(AppRoute.ReferralProgram) }
}
private fun sendFeedback() {
@ -146,12 +147,12 @@ internal class DetailsViewModel(
private fun navigateToAppSettings() {
Analytics.send(Settings.ButtonAppSettings())
store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.AppSettings))
store.dispatchNavigationAction { push(AppRoute.AppSettings) }
}
private fun navigateToCardSettings() {
Analytics.send(Settings.ButtonCardSettings())
store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.CardSettings))
store.dispatchNavigationAction { push(AppRoute.CardSettings) }
}
private fun linkMoreCards() {
@ -164,7 +165,7 @@ internal class DetailsViewModel(
val scanResponse = selectedUserWallet.scanResponse
Analytics.addContext(scanResponse)
store.dispatch(GlobalAction.Onboarding.Start(scanResponse, canSkipBackup = false))
store.dispatch(NavigationAction.NavigateTo(AppScreen.OnboardingWallet))
store.dispatchNavigationAction { push(AppRoute.OnboardingWallet()) }
}
private fun scanAndSaveUserWallet() {
@ -174,12 +175,12 @@ internal class DetailsViewModel(
private fun navigateToWalletConnect() {
Analytics.send(Settings.ButtonWalletConnect())
store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.WalletConnectSessions))
store.dispatchNavigationAction { push(AppRoute.WalletConnectSessions) }
}
private fun handleSocialNetworkClick(link: SocialNetworkLink) {
Analytics.send(Settings.ButtonSocialNetwork(link.network))
store.dispatchOnMain(NavigationAction.OpenUrl(link.url))
store.dispatchOpenUrl(link.url)
}
private fun getSocialLinks(): ImmutableList<SocialNetworkLink> {

View file

@ -4,9 +4,10 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.fragment.app.viewModels
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tangem.core.navigation.NavigationAction
import com.tangem.common.routing.AppRouter
import com.tangem.core.ui.UiDependencies
import com.tangem.core.ui.screen.ComposeFragment
import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.features.details.redux.DetailsState
import com.tangem.tap.store
import dagger.hilt.android.AndroidEntryPoint
@ -30,7 +31,7 @@ internal class ResetCardFragment : ComposeFragment(), StoreSubscriber<DetailsSta
ResetCardScreen(
state = state,
onBackClick = { store.dispatch(NavigationAction.PopBackTo()) },
onBackClick = { store.dispatchNavigationAction(AppRouter::pop) },
modifier = modifier,
)
}

View file

@ -2,13 +2,15 @@ package com.tangem.tap.features.details.ui.resetcard
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.utils.popTo
import com.tangem.domain.card.DeleteSavedAccessCodesUseCase
import com.tangem.domain.card.ResetCardUseCase
import com.tangem.domain.wallets.usecase.DeleteWalletUseCase
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
import com.tangem.feature.wallet.presentation.wallet.domain.getCardsCount
import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.common.extensions.onUserWalletSelected
import com.tangem.tap.features.details.redux.CardSettingsState
import com.tangem.tap.features.details.redux.DetailsAction.ResetToFactory
@ -165,9 +167,9 @@ internal class ResetCardViewModel @Inject constructor(
val newSelectedWallet = getSelectedWalletSyncUseCase().getOrNull()
if (newSelectedWallet != null) {
store.dispatch(NavigationAction.PopBackTo(AppScreen.Wallet))
store.dispatchNavigationAction { popTo<AppRoute.Wallet>() }
} else {
store.dispatch(NavigationAction.PopBackTo(AppScreen.Home))
store.dispatchNavigationAction { popTo<AppRoute.Home>() }
}
}

View file

@ -4,9 +4,10 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Modifier
import com.tangem.core.navigation.NavigationAction
import com.tangem.common.routing.AppRouter
import com.tangem.core.ui.UiDependencies
import com.tangem.core.ui.screen.ComposeFragment
import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.features.details.redux.DetailsState
import com.tangem.tap.store
import dagger.hilt.android.AndroidEntryPoint
@ -29,7 +30,7 @@ internal class SecurityModeFragment : ComposeFragment(), StoreSubscriber<Details
SecurityModeScreen(
modifier = modifier,
state = screenState.value,
onBackClick = { store.dispatch(NavigationAction.PopBackTo()) },
onBackClick = { store.dispatchNavigationAction(AppRouter::pop) },
)
}

View file

@ -6,11 +6,12 @@ import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Modifier
import androidx.fragment.app.viewModels
import com.tangem.common.routing.AppRouter
import com.tangem.core.analytics.Analytics
import com.tangem.core.navigation.NavigationAction
import com.tangem.core.ui.UiDependencies
import com.tangem.core.ui.screen.ComposeFragment
import com.tangem.tap.common.analytics.events.WalletConnect
import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectState
import com.tangem.tap.store
import dagger.hilt.android.AndroidEntryPoint
@ -41,7 +42,7 @@ internal class WalletConnectFragment : ComposeFragment(), StoreSubscriber<Wallet
modifier = modifier,
state = state,
onBackClick = {
store.dispatch(NavigationAction.PopBackTo())
store.dispatchNavigationAction(AppRouter::pop)
},
)
}

View file

@ -2,12 +2,10 @@ package com.tangem.tap.features.details.ui.walletconnect.dialogs
import android.content.Context
import androidx.appcompat.app.AlertDialog
import androidx.core.os.bundleOf
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.feature.qrscanning.QrScanningRouter
import com.tangem.common.routing.AppRoute
import com.tangem.domain.qrscanning.models.SourceType
import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction
import com.tangem.tap.store
@ -22,14 +20,9 @@ object ClipboardOrScanQrDialog {
store.dispatch(WalletConnectAction.OpenSession(wcUri))
}
setNegativeButton(context.getText(R.string.wallet_connect_scan_new_code)) { _, _ ->
store.dispatch(
NavigationAction.NavigateTo(
screen = AppScreen.QrScanning,
bundle = bundleOf(
QrScanningRouter.SOURCE_KEY to SourceType.WALLET_CONNECT,
),
),
)
store.dispatchNavigationAction {
push(AppRoute.QrScanning(source = SourceType.WALLET_CONNECT))
}
}
setOnDismissListener {
store.dispatch(GlobalAction.HideDialog)

View file

@ -1,6 +1,5 @@
package com.tangem.tap.features.disclaimer.redux
import com.tangem.core.navigation.AppScreen
import com.tangem.tap.common.entities.ProgressState
import com.tangem.tap.features.disclaimer.Disclaimer
import org.rekotlin.Action
@ -10,7 +9,7 @@ sealed class DisclaimerAction : Action {
data class SetDisclaimer(val disclaimer: Disclaimer) : DisclaimerAction()
data class Show(
val fromScreen: AppScreen,
val from: DisclaimerSource,
val callback: DisclaimerCallback? = null,
) : DisclaimerAction()

View file

@ -1,7 +1,8 @@
package com.tangem.tap.features.disclaimer.redux
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.AppRouter
import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.mainScope
import com.tangem.tap.store
@ -25,17 +26,19 @@ private fun handleDisclaimerMiddleware(action: Action, appState: AppState) {
when (action) {
is DisclaimerAction.Show -> {
store.dispatch(NavigationAction.NavigateTo(AppScreen.Disclaimer))
store.dispatchNavigationAction {
push(AppRoute.Disclaimer(isTosAccepted = action.from == DisclaimerSource.Details))
}
}
is DisclaimerAction.AcceptDisclaimer -> {
mainScope.launch {
state.disclaimer.accept()
store.dispatch(NavigationAction.PopBackTo())
store.dispatchNavigationAction(AppRouter::pop)
state.callback?.onAccept?.invoke()
}
}
is DisclaimerAction.OnBackPressed -> {
store.dispatch(NavigationAction.PopBackTo())
store.dispatchNavigationAction(AppRouter::pop)
state.callback?.onDismiss?.invoke()
}
}

View file

@ -17,7 +17,7 @@ private fun internalReduce(action: Action, state: AppState): DisclaimerState {
disclaimer = action.disclaimer,
)
is DisclaimerAction.Show -> disclaimerState.copy(
showedFromScreen = action.fromScreen,
showedFrom = action.from,
callback = action.callback,
)
is DisclaimerAction.AcceptDisclaimer, is DisclaimerAction.OnBackPressed -> disclaimerState.copy(

View file

@ -0,0 +1,5 @@
package com.tangem.tap.features.disclaimer.redux
enum class DisclaimerSource {
Home, Details
}

View file

@ -1,7 +1,7 @@
package com.tangem.tap.features.disclaimer.redux
import com.tangem.common.extensions.VoidCallback
import com.tangem.core.navigation.AppScreen
import com.tangem.tap.common.entities.ProgressState
import com.tangem.tap.features.disclaimer.Disclaimer
import com.tangem.tap.features.disclaimer.DummyDisclaimer
@ -9,7 +9,7 @@ import org.rekotlin.StateType
data class DisclaimerState(
val disclaimer: Disclaimer = DummyDisclaimer(),
val showedFromScreen: AppScreen = AppScreen.Home,
val showedFrom: DisclaimerSource = DisclaimerSource.Home,
val callback: DisclaimerCallback? = null,
val progressState: ProgressState? = null,
) : StateType

View file

@ -7,7 +7,7 @@ import android.webkit.WebView
import androidx.lifecycle.lifecycleScope
import androidx.transition.TransitionInflater
import by.kirich1409.viewbindingdelegate.viewBinding
import com.tangem.core.navigation.AppScreen
import com.tangem.core.ui.extensions.setStatusBarColor
import com.tangem.tap.common.entities.ProgressState
import com.tangem.tap.common.extensions.beginDelayedTransition
@ -18,6 +18,7 @@ import com.tangem.tap.features.BaseFragment
import com.tangem.tap.features.addBackPressHandler
import com.tangem.tap.features.disclaimer.Disclaimer
import com.tangem.tap.features.disclaimer.redux.DisclaimerAction
import com.tangem.tap.features.disclaimer.redux.DisclaimerSource
import com.tangem.tap.features.disclaimer.redux.DisclaimerState
import com.tangem.tap.store
import com.tangem.wallet.R
@ -76,17 +77,14 @@ class DisclaimerFragment : BaseFragment(R.layout.fragment_disclaimer), StoreSubs
override fun configureTransitions() {
val inflater = TransitionInflater.from(requireContext())
when (store.state.disclaimerState.showedFromScreen) {
AppScreen.Home -> {
when (store.state.disclaimerState.showedFrom) {
DisclaimerSource.Home -> {
enterTransition = inflater.inflateTransition(android.R.transition.slide_bottom)
exitTransition = inflater.inflateTransition(android.R.transition.slide_top)
}
AppScreen.Details -> {
DisclaimerSource.Details -> {
super.configureTransitions()
}
else -> {
/* no-op */
}
}
}

View file

@ -6,17 +6,16 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.core.view.WindowCompat
import androidx.lifecycle.lifecycleScope
import com.tangem.common.routing.AppRoute
import com.tangem.core.analytics.Analytics
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.core.ui.UiDependencies
import com.tangem.core.ui.components.SystemBarsEffect
import com.tangem.core.ui.components.SystemBarsIconsDisposable
import com.tangem.core.ui.screen.ComposeFragment
import com.tangem.domain.tokens.TokensAction
import com.tangem.tap.common.analytics.events.IntroductionProcess
import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.features.home.compose.StoriesScreen
import com.tangem.tap.features.home.redux.HomeAction
@ -43,15 +42,12 @@ class HomeFragment : ComposeFragment(), StoreSubscriber<HomeState> {
@Composable
override fun ScreenContent(modifier: Modifier) {
BackHandler(onBack = requireActivity()::finish)
SystemBarsEffect {
setSystemBarsColor(color = Color.Transparent, darkIcons = false)
}
SystemBarsIconsDisposable(darkIcons = false)
ScreenContent()
}
override fun onStart() {
super.onStart()
activity?.window?.let { WindowCompat.setDecorFitsSystemWindows(it, false) }
store.subscribe(subscriber = this) { state ->
state
@ -86,7 +82,7 @@ class HomeFragment : ComposeFragment(), StoreSubscriber<HomeState> {
},
onSearchTokensClick = {
Analytics.send(IntroductionProcess.ButtonTokensList())
store.dispatch(NavigationAction.NavigateTo(AppScreen.ManageTokens))
store.dispatchNavigationAction { push(AppRoute.ManageTokens) }
store.dispatch(TokensAction.SetArgs.ReadAccess)
},
)

View file

@ -4,11 +4,10 @@ import com.tangem.common.doOnFailure
import com.tangem.common.doOnResult
import com.tangem.common.doOnSuccess
import com.tangem.common.extensions.guard
import com.tangem.common.routing.AppRoute
import com.tangem.core.analytics.Analytics
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.Basic
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.wallets.builder.UserWalletBuilder
@ -119,7 +118,7 @@ private fun proceedWithScanResponse(scanResponse: ScanResponse) = scope.launch {
scope.launch { store.onUserWalletSelected(userWallet = userWallet) }
}
.doOnResult {
navigateTo(AppScreen.Wallet)
navigateTo(AppRoute.Wallet)
}
}
@ -143,8 +142,8 @@ private fun sendSignedInCardAnalyticsEvent(scanResponse: ScanResponse) {
}
}
private suspend fun navigateTo(appScreen: AppScreen) {
store.dispatchOnMain(NavigationAction.NavigateTo(appScreen))
private suspend fun navigateTo(route: AppRoute) {
store.dispatchNavigationAction { push(route) }
delay(HIDE_PROGRESS_DELAY)
store.dispatch(HomeAction.ScanInProgress(scanInProgress = false))
}

View file

@ -3,11 +3,11 @@ package com.tangem.tap.features.main
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.tangem.blockchainsdk.BlockchainSDKFactory
import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.AppRouter
import com.tangem.core.analytics.Analytics
import com.tangem.core.analytics.models.Basic
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.core.navigation.ReduxNavController
import com.tangem.domain.appcurrency.FetchAppCurrenciesUseCase
import com.tangem.domain.balancehiding.BalanceHidingSettings
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
@ -16,9 +16,11 @@ import com.tangem.domain.balancehiding.UpdateBalanceHidingSettingsUseCase
import com.tangem.domain.feedback.FeedbackManagerFeatureToggles
import com.tangem.domain.settings.DeleteDeprecatedLogsUseCase
import com.tangem.domain.settings.IncrementAppLaunchCounterUseCase
import com.tangem.domain.staking.FetchStakingTokensUseCase
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.wallets.legacy.UserWalletsListManager
import com.tangem.features.send.api.featuretoggles.SendFeatureToggles
import com.tangem.features.staking.api.featuretoggles.StakingFeatureToggles
import com.tangem.tap.common.extensions.setContext
import com.tangem.tap.features.main.model.MainScreenState
import com.tangem.tap.store
@ -34,7 +36,7 @@ import javax.inject.Inject
internal class MainViewModel @Inject constructor(
private val updateBalanceHidingSettingsUseCase: UpdateBalanceHidingSettingsUseCase,
private val listenToFlipsUseCase: ListenToFlipsUseCase,
private val reduxNavController: ReduxNavController,
private val router: AppRouter,
private val fetchAppCurrenciesUseCase: FetchAppCurrenciesUseCase,
private val deleteDeprecatedLogsUseCase: DeleteDeprecatedLogsUseCase,
private val incrementAppLaunchCounterUseCase: IncrementAppLaunchCounterUseCase,
@ -44,6 +46,8 @@ internal class MainViewModel @Inject constructor(
private val sendFeatureToggles: SendFeatureToggles,
private val feedbackManagerFeatureToggles: FeedbackManagerFeatureToggles,
private val dispatchers: CoroutineDispatcherProvider,
private val stakingFeatureToggles: StakingFeatureToggles,
private val fetchStakingTokensUseCase: FetchStakingTokensUseCase,
getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
) : ViewModel(), MainIntents {
@ -70,6 +74,10 @@ internal class MainViewModel @Inject constructor(
displayBalancesHidingStatusToast()
displayHiddenBalancesModalNotification()
if (stakingFeatureToggles.isStakingEnabled) {
fetchStakingTokens()
}
viewModelScope.launch(dispatchers.main) {
deleteDeprecatedLogsUseCase()
}
@ -115,6 +123,14 @@ internal class MainViewModel @Inject constructor(
}
}
private fun fetchStakingTokens() {
viewModelScope.launch(dispatchers.main) {
fetchStakingTokensUseCase()
.onLeft { Timber.e(it, "Unable to fetch the staking tokens list") }
.onRight { Timber.d("Staking token list was fetched successfully") }
}
}
private fun updateSendFeatureToggle() {
viewModelScope.launch(dispatchers.main) {
sendFeatureToggles.fetchNewSendEnabled()
@ -136,7 +152,7 @@ internal class MainViewModel @Inject constructor(
if (state.value.modalNotification?.isShow != true && !it.isUpdateFromToast) {
listenToFlipsUseCase.changeUpdateEnabled(false)
stateHolder.updateWithHiddenBalancesNotification()
reduxNavController.navigate(NavigationAction.NavigateTo(AppScreen.ModalNotification))
router.push(AppRoute.ModalNotification)
}
}
.launchIn(viewModelScope)

View file

@ -1,7 +1,7 @@
package com.tangem.tap.features.onboarding
import com.tangem.common.extensions.VoidCallback
import com.tangem.core.navigation.StateDialog
import com.tangem.domain.redux.StateDialog
/**
[REDACTED_AUTHOR]

View file

@ -3,10 +3,10 @@ package com.tangem.tap.features.onboarding
import com.tangem.common.doOnFailure
import com.tangem.common.doOnSuccess
import com.tangem.common.extensions.guard
import com.tangem.common.routing.AppRoute
import com.tangem.core.analytics.Analytics
import com.tangem.core.analytics.models.Basic
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.common.util.twinsIsTwinned
import com.tangem.domain.models.scan.CardDTO
@ -56,18 +56,18 @@ object OnboardingHelper {
}
}
fun whereToNavigate(scanResponse: ScanResponse): AppScreen {
fun whereToNavigate(scanResponse: ScanResponse): AppRoute {
return when (val type = scanResponse.productType) {
ProductType.Note -> AppScreen.OnboardingNote
ProductType.Note -> AppRoute.OnboardingNote
ProductType.Wallet,
ProductType.Wallet2,
ProductType.Ring,
-> if (scanResponse.card.settings.isBackupAllowed) {
AppScreen.OnboardingWallet
AppRoute.OnboardingWallet()
} else {
AppScreen.OnboardingOther
AppRoute.OnboardingOther
}
ProductType.Twins -> AppScreen.OnboardingTwins
ProductType.Twins -> AppRoute.OnboardingTwins
ProductType.Start2Coin,
ProductType.Visa,
-> throw UnsupportedOperationException("Onboarding for ${type.name} cards is not supported")
@ -111,14 +111,14 @@ object OnboardingHelper {
backupCardsIds = backupCardsIds?.toSet(),
),
)
store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.Wallet))
store.dispatchNavigationAction { push(AppRoute.Wallet) }
delay(timeMillis = 1_800)
store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.SaveWallet))
store.dispatchNavigationAction { push(AppRoute.SaveWallet) }
}
// If device has no biometry and save wallet screen has been shown, then go through old scenario
else -> {
proceedWithScanResponse(scanResponse, backupCardsIds, hasBackupError)
store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.Wallet))
store.dispatchNavigationAction { push(AppRoute.Wallet) }
}
}
}

View file

@ -2,8 +2,9 @@ package com.tangem.tap.features.onboarding.products.note.redux
import com.tangem.common.CompletionResult
import com.tangem.common.extensions.guard
import com.tangem.common.routing.AppRouter
import com.tangem.core.analytics.Analytics
import com.tangem.core.navigation.NavigationAction
import com.tangem.data.tokens.utils.CryptoCurrencyFactory
import com.tangem.domain.common.extensions.makePrimaryWalletManager
import com.tangem.domain.common.extensions.withMainContext
@ -204,7 +205,7 @@ private fun handleNoteAction(appState: () -> AppState?, action: Action, dispatch
OnboardingDialog.InterruptOnboarding(
onOk = {
OnboardingHelper.onInterrupted()
store.dispatch(NavigationAction.PopBackTo())
store.dispatchNavigationAction(AppRouter::pop)
},
),
)

View file

@ -3,9 +3,10 @@ package com.tangem.tap.features.onboarding.products.twins.redux
import com.tangem.blockchain.extensions.Result
import com.tangem.common.CompletionResult
import com.tangem.common.extensions.guard
import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.utils.popTo
import com.tangem.core.analytics.Analytics
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.data.tokens.utils.CryptoCurrencyFactory
import com.tangem.domain.common.extensions.makePrimaryWalletManager
import com.tangem.domain.common.extensions.withMainContext
@ -39,6 +40,7 @@ import kotlinx.coroutines.runBlocking
import org.rekotlin.Action
import org.rekotlin.DispatchFunction
import org.rekotlin.Middleware
import kotlin.reflect.KClass
object TwinCardsMiddleware {
val handler = twinsWalletMiddleware
@ -328,7 +330,7 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
if (walletsRepository.shouldSaveUserWalletsSync()) {
OnboardingHelper.trySaveWalletAndNavigateToWalletScreen(scanResponse)
} else {
store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Home))
store.dispatchNavigationAction { popTo<AppRoute.Home>() }
}
}
}
@ -352,7 +354,7 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
store.dispatch(TwinCardsAction.CardsManager.Release)
action.shouldResetTwinCardsWidget(shouldReturnCardBack) {
store.dispatchOnMain(NavigationAction.PopBackTo(getPopBackScreen()))
store.dispatchNavigationAction { popTo(routeClass = getPopBackScreen()) }
}
}
store.dispatchDialogShow(OnboardingDialog.InterruptOnboarding(onOkCallback))
@ -362,18 +364,19 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
}
}
private fun getPopBackScreen(): AppScreen {
private fun getPopBackScreen(): KClass<out AppRoute> {
val userWalletsListManager = store.inject(DaggerGraphState::generalUserWalletsListManager)
return if (userWalletsListManager.hasUserWallets) {
val isLocked = runCatching { userWalletsListManager.asLockable()?.isLockedSync }
.fold(onSuccess = { true }, onFailure = { false })
if (isLocked) {
AppScreen.Welcome
AppRoute.Welcome::class
} else {
AppScreen.Wallet
AppRoute.Wallet::class
}
} else {
AppScreen.Home
AppRoute.Home::class
}
}

View file

@ -7,16 +7,16 @@ import com.tangem.common.core.TangemSdkError
import com.tangem.common.extensions.guard
import com.tangem.common.extensions.ifNotNull
import com.tangem.common.extensions.toHexString
import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.AppRouter
import com.tangem.common.services.Result
import com.tangem.core.analytics.Analytics
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.domain.common.extensions.withMainContext
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.wallets.models.Artwork
import com.tangem.domain.wallets.builder.UserWalletBuilder
import com.tangem.domain.wallets.models.Artwork
import com.tangem.feature.onboarding.data.model.CreateWalletResponse
import com.tangem.feature.onboarding.presentation.wallet2.analytics.SeedPhraseSource
import com.tangem.feature.wallet.presentation.wallet.domain.BackupValidator
@ -25,10 +25,7 @@ import com.tangem.operations.backup.BackupService
import com.tangem.tap.*
import com.tangem.tap.common.analytics.events.AnalyticsParam
import com.tangem.tap.common.analytics.events.Onboarding
import com.tangem.tap.common.extensions.dispatchDialogShow
import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.extensions.dispatchWithMain
import com.tangem.tap.common.extensions.inject
import com.tangem.tap.common.extensions.*
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
@ -164,7 +161,7 @@ private fun handleWalletAction(action: Action) {
store.dispatch(GlobalAction.Onboarding.Stop)
if (scanResponse == null) {
store.dispatch(NavigationAction.PopBackTo())
store.dispatchNavigationAction(AppRouter::pop)
store.dispatch(HomeAction.ReadCard(scope = action.scope))
} else {
val backupState = store.state.onboardingWalletState.backupState
@ -529,7 +526,8 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
addedBackupCardsCount = backupService.addedBackupCardsCount,
),
)
store.dispatch(NavigationAction.NavigateTo(AppScreen.OnboardingWallet))
store.dispatchNavigationAction { push(AppRoute.OnboardingWallet()) }
}
is BackupAction.SkipBackup -> {
Analytics.send(Onboarding.Backup.Skipped())
@ -614,7 +612,7 @@ private fun handleOnBackPressed(state: OnboardingWalletState) {
}
BackupStep.Finished -> {
OnboardingHelper.onInterrupted()
store.dispatch(NavigationAction.PopBackTo())
store.dispatchNavigationAction(AppRouter::pop)
}
}
}
@ -625,7 +623,7 @@ private fun showInterruptOnboardingDialog() {
onOk = {
OnboardingHelper.onInterrupted()
store.dispatch(BackupAction.DiscardBackup)
store.dispatch(NavigationAction.PopBackTo())
store.dispatchNavigationAction(AppRouter::pop)
},
),
)

View file

@ -2,7 +2,7 @@ package com.tangem.tap.features.onboarding.products.wallet.redux
import android.graphics.Bitmap
import android.net.Uri
import com.tangem.core.navigation.StateDialog
import com.tangem.domain.redux.StateDialog
import org.rekotlin.StateType
/**

View file

@ -1,6 +1,10 @@
package com.tangem.tap.features.onboarding.products.wallet.ui
import android.app.Activity
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.runtime.collectAsState
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.windowsize.rememberWindowSize
import com.tangem.feature.onboarding.api.OnboardingSeedPhraseScreen
import com.tangem.feature.onboarding.api.OnboardingSeedPhraseApi
import com.tangem.feature.onboarding.presentation.wallet2.viewmodel.SeedPhraseScreen
@ -16,6 +20,7 @@ import com.tangem.wallet.R
*/
internal class OnboardingSeedPhraseStateHandler(
private val onboardingSeedPhraseApi: OnboardingSeedPhraseApi = OnboardingSeedPhraseScreen(),
private val activity: Activity,
) {
fun newState(
@ -49,11 +54,16 @@ internal class OnboardingSeedPhraseStateHandler(
val subScreen = viewModel.currentScreen.collectAsState().value
setMainScreenToolbarTitle(walletFragment, subScreen)
onboardingSeedPhraseApi.ScreenContent(
uiState = viewModel.uiState,
subScreen = subScreen,
progress = viewModel.progress.collectAsState(0).value.toFloat() / onboardingWalletMaxProgress,
)
TangemTheme(
isDark = isSystemInDarkTheme(),
windowSize = rememberWindowSize(activity = activity),
) {
onboardingSeedPhraseApi.ScreenContent(
uiState = viewModel.uiState,
subScreen = subScreen,
progress = viewModel.progress.collectAsState(0).value.toFloat() / onboardingWalletMaxProgress,
)
}
}
}

View file

@ -21,13 +21,13 @@ import com.google.android.material.tabs.TabLayoutMediator
import com.tangem.common.CardIdFormatter
import com.tangem.common.CompletionResult
import com.tangem.common.core.CardIdDisplayFormat
import com.tangem.common.routing.AppRoute
import com.tangem.core.analytics.Analytics
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.Basic
import com.tangem.core.ui.extensions.setStatusBarColor
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.feature.onboarding.data.model.CreateWalletResponse
import com.tangem.feature.onboarding.navigation.OnboardingRouter
import com.tangem.feature.onboarding.presentation.wallet2.analytics.SeedPhraseSource
import com.tangem.feature.onboarding.presentation.wallet2.viewmodel.SeedPhraseMediator
import com.tangem.feature.onboarding.presentation.wallet2.viewmodel.SeedPhraseRouter
@ -66,9 +66,10 @@ class OnboardingWalletFragment :
internal val bindingSeedPhrase: LayoutOnboardingSeedPhraseBinding by lazy { binding.onboardingSeedPhraseContainer }
private val canSkipBackup by lazy { arguments?.getBoolean(OnboardingRouter.CAN_SKIP_BACKUP) ?: true }
private val canSkipBackup by lazy { arguments?.getBoolean(AppRoute.OnboardingWallet.CAN_SKIP_BACKUP_KEY) ?: true }
private lateinit var seedPhraseStateHandler: OnboardingSeedPhraseStateHandler
private val seedPhraseStateHandler: OnboardingSeedPhraseStateHandler = OnboardingSeedPhraseStateHandler()
private val seedPhraseViewModel by viewModels<SeedPhraseViewModel>()
private lateinit var cardsWidget: WalletCardsWidget
@ -79,6 +80,7 @@ class OnboardingWalletFragment :
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
seedPhraseStateHandler = OnboardingSeedPhraseStateHandler(activity = requireActivity())
val newSeedPhraseRouter = makeSeedPhraseRouter()
seedPhraseRouter = newSeedPhraseRouter

View file

@ -3,29 +3,22 @@ package com.tangem.tap.features.saveWallet.redux
import com.tangem.common.*
import com.tangem.common.core.TangemSdkError
import com.tangem.common.extensions.guard
import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.utils.popTo
import com.tangem.core.analytics.Analytics
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.domain.wallets.builder.UserWalletBuilder
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.tap.*
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.dispatchWithMain
import com.tangem.tap.common.extensions.inject
import com.tangem.tap.common.extensions.onUserWalletSelected
import com.tangem.tap.common.extensions.*
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.mainScope
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.launch
import org.rekotlin.Middleware
import org.rekotlin.Store
import timber.log.Timber
internal class SaveWalletMiddleware {
@ -83,12 +76,12 @@ internal class SaveWalletMiddleware {
Timber.e(error, "Unable to save user wallet")
}
.doOnSuccess { mainScope.launch { store.onUserWalletSelected(userWallet) } }
.doOnResult { store.navigateToWallet() }
.doOnResult { navigateToWallet() }
}
}
private fun enrollBiometrics() {
store.dispatchOnMain(NavigationAction.OpenBiometricsSettings)
activityResultCaller.openSystemBiometrySettings()
}
private fun allowToUseBiometrics(state: SaveWalletState) {
@ -133,7 +126,7 @@ internal class SaveWalletMiddleware {
)
store.dispatchWithMain(SaveWalletAction.AllowToUseBiometrics.Success)
store.dispatchWithMain(NavigationAction.PopBackTo(AppScreen.Wallet))
store.dispatchNavigationAction { popTo<AppRoute.Wallet>() }
}
private fun dismiss(state: SaveWalletState) {
@ -162,13 +155,9 @@ internal class SaveWalletMiddleware {
}
}
private suspend fun Store<AppState>.navigateToWallet() {
dispatchWithMain(
if (store.state.navigationState.backStack.contains(AppScreen.Wallet)) {
NavigationAction.PopBackTo(AppScreen.Wallet)
} else {
NavigationAction.NavigateTo(AppScreen.Wallet)
},
)
private fun navigateToWallet() {
store.dispatchNavigationAction {
replaceAll(AppRoute.Wallet)
}
}
}

View file

@ -7,7 +7,7 @@ import com.tangem.blockchain.common.FeePaidCurrency
import com.tangem.blockchain.common.WalletManager
import com.tangem.blockchain.common.transaction.TransactionFee
import com.tangem.common.core.TangemSdkError
import com.tangem.core.navigation.StateDialog
import com.tangem.domain.redux.StateDialog
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.tap.common.analytics.events.Token.Send.AddressEntered
import com.tangem.tap.common.redux.ToastNotificationAction

View file

@ -14,10 +14,10 @@ import com.tangem.blockchain.common.transaction.Fee
import com.tangem.blockchain.extensions.Result
import com.tangem.blockchainsdk.utils.minimalAmount
import com.tangem.common.core.TangemSdkError
import com.tangem.common.routing.AppRouter
import com.tangem.core.analytics.Analytics
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.Basic
import com.tangem.core.navigation.NavigationAction
import com.tangem.domain.common.TapWorkarounds.isStart2Coin
import com.tangem.domain.common.extensions.withMainContext
import com.tangem.domain.demo.DemoTransactionSender
@ -270,7 +270,7 @@ private fun sendTransaction(
),
)
Analytics.sendSelectedCurrencyEvent(mainCurrencyType)
dispatch(NavigationAction.PopBackTo())
store.dispatchNavigationAction(AppRouter::pop)
}
}
is Result.Failure -> {
@ -326,7 +326,7 @@ private fun sendTransaction(
AppDialog.SimpleOkDialogRes(
headerId = R.string.common_done,
messageId = R.string.alert_demo_feature_disabled,
onOk = { dispatch(NavigationAction.PopBackTo()) },
onOk = { store.dispatchNavigationAction(AppRouter::pop) },
),
)
}

View file

@ -1,6 +1,5 @@
package com.tangem.tap.features.send.redux.reducers
import com.tangem.common.Strings.STARS
import com.tangem.common.extensions.isZero
import com.tangem.tap.common.extensions.stripZeroPlainString
import com.tangem.tap.features.send.redux.AmountAction
@ -11,6 +10,7 @@ import com.tangem.tap.features.send.redux.states.AmountState
import com.tangem.tap.features.send.redux.states.InputViewValue
import com.tangem.tap.features.send.redux.states.MainCurrencyType
import com.tangem.tap.features.send.redux.states.SendState
import com.tangem.utils.Strings.STARS
import java.math.BigDecimal
/**

View file

@ -4,8 +4,8 @@ import com.tangem.blockchain.common.Amount
import com.tangem.blockchain.common.AmountType
import com.tangem.blockchain.common.WalletManager
import com.tangem.common.extensions.isZero
import com.tangem.core.navigation.StateDialog
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.redux.StateDialog
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.tap.common.CurrencyConverter
import com.tangem.tap.common.entities.IndeterminateProgressButton

View file

@ -8,7 +8,6 @@ import android.text.method.DigitsKeyListener
import android.view.View
import android.view.inputmethod.EditorInfo
import android.widget.EditText
import androidx.core.os.bundleOf
import androidx.core.view.postDelayed
import androidx.core.widget.addTextChangedListener
import androidx.fragment.app.viewModels
@ -20,19 +19,18 @@ import androidx.recyclerview.widget.RecyclerView
import by.kirich1409.viewbindingdelegate.viewBinding
import com.google.android.material.textfield.TextInputEditText
import com.tangem.Message
import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.AppRouter
import com.tangem.core.analytics.Analytics
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.qrscanning.models.SourceType
import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase
import com.tangem.domain.qrscanning.usecases.ParseQrCodeUseCase
import com.tangem.domain.tokens.legacy.TradeCryptoAction
import com.tangem.feature.qrscanning.QrScanningRouter
import com.tangem.sdk.extensions.hideSoftKeyboard
import com.tangem.tap.common.KeyboardObserver
import com.tangem.tap.common.analytics.events.Token
import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.common.extensions.getFromClipboard
import com.tangem.tap.common.extensions.setOnImeActionListener
import com.tangem.tap.common.recyclerView.SpaceItemDecoration
@ -162,14 +160,9 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
imvQrCode.setOnClickListener {
Analytics.send(Token.Send.ButtonQRCode())
store.dispatchOnMain(
NavigationAction.NavigateTo(
screen = AppScreen.QrScanning,
bundle = bundleOf(
QrScanningRouter.SOURCE_KEY to SourceType.SEND,
),
),
)
store.dispatchNavigationAction {
push(AppRoute.QrScanning(source = SourceType.SEND))
}
}
}
@ -370,7 +363,7 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
override fun handleOnBackPressed() {
val externalTransactionData = store.state.sendState.externalTransactionData
if (externalTransactionData == null) {
store.dispatch(NavigationAction.PopBackTo())
store.dispatchNavigationAction(AppRouter::pop)
} else {
store.dispatch(TradeCryptoAction.FinishSelling(externalTransactionData.transactionId))
}

View file

@ -2,6 +2,7 @@ package com.tangem.tap.features.send.ui
import androidx.lifecycle.*
import arrow.core.getOrElse
import com.tangem.common.routing.AppRoute
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
import com.tangem.domain.qrscanning.models.SourceType
import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase
@ -12,7 +13,6 @@ import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
import com.tangem.features.send.api.navigation.SendRouter
import com.tangem.tap.common.analytics.events.Token
import com.tangem.tap.di.DelayedWork
import com.tangem.tap.features.send.redux.AddressActionUi
@ -52,7 +52,7 @@ internal class SendViewModel @Inject constructor(
.launchIn(viewModelScope)
}
private val cryptoCurrency: CryptoCurrency? = savedStateHandle[SendRouter.CRYPTO_CURRENCY_KEY]
private val cryptoCurrency: CryptoCurrency? = savedStateHandle[AppRoute.Send.CRYPTO_CURRENCY_KEY]
override fun onCreate(owner: LifecycleOwner) {
getBalanceHidingSettingsUseCase()

View file

@ -1,13 +1,10 @@
package com.tangem.tap.features.tokens.impl.presentation
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.hilt.navigation.compose.hiltViewModel
import com.tangem.core.ui.UiDependencies
import com.tangem.core.ui.components.SystemBarsEffect
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.screen.ComposeFragment
import com.tangem.tap.features.tokens.impl.presentation.ui.TokensListScreen
import com.tangem.tap.features.tokens.impl.presentation.viewmodels.TokensListViewModel
@ -30,12 +27,7 @@ internal class TokensListFragment : ComposeFragment() {
val viewModel = hiltViewModel<TokensListViewModel>().apply {
LocalLifecycleOwner.current.lifecycle.addObserver(this)
}
val statusBarColor = TangemTheme.colors.background.secondary
SystemBarsEffect {
setSystemBarsColor(color = statusBarColor)
}
TokensListScreen(
modifier = Modifier.systemBarsPadding(),
stateHolder = viewModel.uiState,
)
}

View file

@ -1,9 +1,11 @@
package com.tangem.tap.features.tokens.impl.presentation.router
import com.tangem.blockchain.common.Blockchain
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.AppRouter
import com.tangem.tap.common.extensions.dispatchDialogShow
import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.common.extensions.dispatchNotification
import com.tangem.tap.common.redux.AppDialog
import com.tangem.tap.store
@ -18,11 +20,11 @@ import com.tangem.wallet.R
internal class DefaultTokensListRouter : TokensListRouter {
override fun popBackStack() {
store.dispatch(NavigationAction.PopBackTo())
store.dispatchNavigationAction(AppRouter::pop)
}
override fun openAddCustomTokenScreen() {
store.dispatch(NavigationAction.NavigateTo(AppScreen.AddCustomToken))
store.dispatchNavigationAction { push(AppRoute.AddCustomToken) }
}
override fun showAddressCopiedNotification() {
@ -54,7 +56,7 @@ internal class DefaultTokensListRouter : TokensListRouter {
val alert = AppDialog.SimpleOkDialogRes(
headerId = R.string.common_error,
messageId = R.string.common_unknown_error,
onOk = { store.dispatch(NavigationAction.PopBackTo()) },
onOk = { store.dispatchNavigationAction(AppRouter::pop) },
)
store.dispatchDialogShow(alert)
}

View file

@ -15,7 +15,6 @@ import androidx.compose.material.Scaffold
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity
@ -34,6 +33,8 @@ import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.collectAsLazyPagingItems
import androidx.paging.compose.itemContentType
import androidx.paging.compose.itemKey
import com.tangem.core.ui.components.BottomFade
import com.tangem.core.ui.components.NavigationBar3ButtonsScrim
import com.tangem.core.ui.components.PrimaryButton
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.res.TangemTheme
@ -61,32 +62,45 @@ internal fun TokensListScreen(stateHolder: TokensListStateHolder, modifier: Modi
Scaffold(
modifier = modifier,
topBar = { TokensListToolbar(state = stateHolder.toolbarState) },
topBar = {
TokensListToolbar(state = stateHolder.toolbarState)
},
floatingActionButton = {
if (stateHolder is TokensListStateHolder.ManageContent) {
val density = LocalDensity.current
val verticalPadding = TangemTheme.dimens.spacing32
SaveChangesButton(
modifier = Modifier.onSizeChanged {
with(density) { floatingButtonHeight = it.height.toDp() + verticalPadding }
},
modifier = Modifier
.navigationBarsPadding()
.onSizeChanged {
with(density) { floatingButtonHeight = it.height.toDp() + verticalPadding }
},
showProgress = stateHolder.isSavingInProgress,
onClick = stateHolder.onSaveButtonClick,
)
}
},
floatingActionButtonPosition = FabPosition.Center,
backgroundColor = TangemTheme.colors.background.primary,
) { scaffoldPadding ->
backgroundColor = TangemTheme.colors.background.secondary,
) { _ ->
val tokens = stateHolder.tokens.collectAsLazyPagingItems()
TokensListContent(
isDifferentAddressesBlockVisible = stateHolder.isDifferentAddressesBlockVisible,
tokens = tokens,
scaffoldPadding = scaffoldPadding,
bottomMarginDp = floatingButtonHeight,
)
if (stateHolder !is TokensListStateHolder.ManageContent) {
NavigationBar3ButtonsScrim()
}
Box {
TokensListContent(
isDifferentAddressesBlockVisible = stateHolder.isDifferentAddressesBlockVisible,
tokens = tokens,
bottomMarginDp = floatingButtonHeight,
)
if (stateHolder is TokensListStateHolder.ManageContent) {
BottomFade(Modifier.align(Alignment.BottomCenter))
}
}
Crossfade(targetState = stateHolder.isLoading, label = "Update progress bar visibility") {
if (it) {
@ -112,23 +126,24 @@ private fun LoadingContent() {
}
}
@OptIn(ExperimentalComposeUiApi::class)
@Composable
private fun TokensListContent(
isDifferentAddressesBlockVisible: Boolean,
tokens: LazyPagingItems<TokenItemState>,
scaffoldPadding: PaddingValues,
bottomMarginDp: Dp,
) {
val state = rememberLazyListState()
val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() }
LazyColumn(
modifier = Modifier
.background(color = TangemTheme.colors.background.primary)
.imePadding()
.fillMaxSize()
.padding(scaffoldPadding),
.fillMaxSize(),
state = state,
contentPadding = PaddingValues(bottom = bottomMarginDp),
contentPadding = PaddingValues(
bottom = bottomMarginDp + bottomBarHeight,
),
) {
item(
key = "DifferentAddressesWarning$isDifferentAddressesBlockVisible",

View file

@ -1,10 +1,7 @@
package com.tangem.tap.features.tokens.impl.presentation.ui
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
@ -16,6 +13,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
@ -42,8 +40,15 @@ internal fun TokensListToolbar(state: TokensListToolbarState) {
} else {
AppBarDefaults.TopAppBarElevation
}
val statusBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getTop(this).toDp() }
TopAppBar(
backgroundColor = TangemTheme.colors.background.secondary,
contentPadding = PaddingValues(
start = TangemTheme.dimens.spacing4,
end = TangemTheme.dimens.spacing4,
top = statusBarHeight,
),
elevation = toolbarElevation,
) {
IconButton(onClick = state.onBackButtonClick) {

View file

@ -3,8 +3,8 @@ package com.tangem.tap.features.tokens.impl.presentation.viewmodels
import arrow.core.Either
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.Token
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.utils.popTo
import com.tangem.data.tokens.utils.CryptoCurrencyFactory
import com.tangem.domain.card.DerivePublicKeysUseCase
import com.tangem.domain.common.util.derivationStyleProvider
@ -16,7 +16,7 @@ import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
import com.tangem.tap.common.extensions.dispatchWithMain
import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.common.extensions.inject
import com.tangem.tap.proxy.redux.DaggerGraphState
import com.tangem.tap.store
@ -126,7 +126,7 @@ internal class TokensListMigration(
val isNothingToDoWithBlockchain = blockchainsToAdd.isEmpty() && blockchainsToRemove.isEmpty()
if (isNothingToDoWithTokens && isNothingToDoWithBlockchain) {
store.dispatchDebugErrorNotification(message = "Nothing to save")
store.dispatchWithMain(NavigationAction.PopBackTo(screen = AppScreen.Wallet))
store.dispatchNavigationAction { popTo<AppRoute.Wallet>() }
return
}

View file

@ -11,9 +11,9 @@ import androidx.lifecycle.viewModelScope
import androidx.paging.*
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchainsdk.utils.fromNetworkId
import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.utils.popTo
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.core.ui.extensions.getActiveIconRes
import com.tangem.core.ui.extensions.getGreyedOutIconRes
import com.tangem.domain.card.DerivePublicKeysUseCase
@ -26,7 +26,7 @@ import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase
import com.tangem.domain.tokens.GetCryptoCurrenciesUseCase
import com.tangem.domain.tokens.TokenWithBlockchain
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
import com.tangem.tap.common.extensions.dispatchWithMain
import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.common.extensions.fullNameWithoutTestnet
import com.tangem.tap.common.extensions.getNetworkName
import com.tangem.tap.features.customtoken.impl.presentation.models.SupportBlockchainType
@ -326,7 +326,7 @@ internal class TokensListViewModel @Inject constructor(
)
uiState = state.copy(isSavingInProgress = false)
store.dispatchWithMain(NavigationAction.PopBackTo(screen = AppScreen.Wallet))
store.dispatchNavigationAction { popTo<AppRoute.Wallet>() }
}
}

View file

@ -1,18 +1,16 @@
package com.tangem.tap.features.wallet.redux.middlewares
import androidx.core.os.bundleOf
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager
import com.tangem.blockchain.common.AmountType
import com.tangem.blockchain.common.Blockchain
import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.AppRouter
import com.tangem.core.analytics.Analytics
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.domain.tokens.legacy.TradeCryptoAction
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.NetworkAddress
import com.tangem.feature.swap.presentation.SwapFragment
import com.tangem.features.send.api.navigation.SendRouter
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.tap.common.analytics.events.Token
import com.tangem.tap.common.apptheme.MutableAppThemeModeHolder
import com.tangem.tap.common.extensions.*
@ -150,7 +148,7 @@ object TradeCryptoMiddleware {
}
private fun openReceiptUrl(transactionId: String) {
store.dispatchOnMain(NavigationAction.PopBackTo())
store.dispatchNavigationAction(AppRouter::pop)
store.state.globalState.exchangeManager.getSellCryptoReceiptUrl(
action = CurrencyExchangeManager.Action.Sell,
transactionId = transactionId,
@ -158,11 +156,7 @@ object TradeCryptoMiddleware {
}
private fun openSwap(currency: CryptoCurrency) {
val bundle = bundleOf(
SwapFragment.CURRENCY_BUNDLE_KEY to currency,
)
store.dispatchOnMain(NavigationAction.NavigateTo(screen = AppScreen.Swap, bundle = bundle))
store.dispatchNavigationAction { push(AppRoute.Swap(currency = currency)) }
}
private fun handleSendToken(action: TradeCryptoAction.SendToken) {
@ -214,11 +208,12 @@ object TradeCryptoMiddleware {
)
}
val bundle = bundleOf(
SendRouter.CRYPTO_CURRENCY_KEY to currency,
SendRouter.USER_WALLET_ID_KEY to action.userWallet.walletId.stringValue,
val route = AppRoute.Send(
currency = currency,
userWalletId = action.userWallet.walletId,
)
store.dispatchOnMain(NavigationAction.NavigateTo(screen = AppScreen.Send, bundle = bundle))
store.dispatchNavigationAction { push(route) }
}
}
@ -285,17 +280,17 @@ object TradeCryptoMiddleware {
)
}
val bundle = bundleOf(
SendRouter.CRYPTO_CURRENCY_KEY to currency,
SendRouter.USER_WALLET_ID_KEY to action.userWallet.walletId.stringValue,
val route = AppRoute.Send(
currency = currency,
userWalletId = action.userWallet.walletId,
)
store.dispatchOnMain(NavigationAction.NavigateTo(screen = AppScreen.Send, bundle = bundle))
store.dispatchNavigationAction { push(route) }
}
}
private fun handleNewSendToken(action: TradeCryptoAction.SendToken) {
handleNewSend(
userWalletId = action.userWallet.walletId.stringValue,
userWalletId = action.userWallet.walletId,
txInfo = action.transactionInfo,
currency = action.tokenCurrency,
)
@ -303,25 +298,26 @@ object TradeCryptoMiddleware {
private fun handleNewSendCoin(action: TradeCryptoAction.SendCoin) {
handleNewSend(
userWalletId = action.userWallet.walletId.stringValue,
userWalletId = action.userWallet.walletId,
txInfo = action.transactionInfo,
currency = action.coinStatus.currency,
)
}
private fun handleNewSend(
userWalletId: String,
userWalletId: UserWalletId,
txInfo: TradeCryptoAction.TransactionInfo?,
currency: CryptoCurrency,
) {
val bundle = bundleOf(
SendRouter.CRYPTO_CURRENCY_KEY to currency,
SendRouter.USER_WALLET_ID_KEY to userWalletId,
SendRouter.TRANSACTION_ID_KEY to txInfo?.transactionId,
SendRouter.DESTINATION_ADDRESS_KEY to txInfo?.destinationAddress,
SendRouter.AMOUNT_KEY to txInfo?.amount,
SendRouter.TAG_KEY to txInfo?.tag,
val route = AppRoute.Send(
currency = currency,
userWalletId = userWalletId,
transactionId = txInfo?.transactionId,
destinationAddress = txInfo?.destinationAddress,
amount = txInfo?.amount,
tag = txInfo?.tag,
)
store.dispatchOnMain(NavigationAction.NavigateTo(screen = AppScreen.Send, bundle = bundle))
store.dispatchNavigationAction { push(route) }
}
}

View file

@ -6,11 +6,12 @@ import com.tangem.common.doOnFailure
import com.tangem.common.doOnResult
import com.tangem.common.doOnSuccess
import com.tangem.common.flatMap
import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.utils.popTo
import com.tangem.core.analytics.Analytics
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.Basic
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.wallets.builder.UserWalletBuilder
@ -98,7 +99,7 @@ internal class WelcomeMiddleware {
signInType = Basic.SignedIn.SignInType.Biometric,
)
store.dispatchWithMain(NavigationAction.NavigateTo(AppScreen.Wallet))
store.dispatchNavigationAction { push(AppRoute.Wallet) }
store.dispatchWithMain(WelcomeAction.ProceedWithBiometrics.Success)
store.onUserWalletSelected(userWallet = selectedUserWallet)
@ -130,7 +131,7 @@ internal class WelcomeMiddleware {
.doOnSuccess {
sendSignedInAnalyticsEvent(scanResponse = scanResponse, signInType = Basic.SignedIn.SignInType.Card)
store.dispatchWithMain(NavigationAction.NavigateTo(AppScreen.Wallet))
store.dispatchNavigationAction { push(AppRoute.Wallet) }
store.dispatchWithMain(WelcomeAction.ProceedWithCard.Success)
store.onUserWalletSelected(userWallet = userWallet)
@ -170,7 +171,7 @@ internal class WelcomeMiddleware {
}
.doOnResult {
store.dispatchWithMain(WelcomeAction.CloseError)
store.dispatchWithMain(NavigationAction.PopBackTo(AppScreen.Home))
store.dispatchNavigationAction { popTo<AppRoute.Home>() }
}
}

View file

@ -16,7 +16,6 @@ import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tangem.core.analytics.Analytics
import com.tangem.core.ui.UiDependencies
import com.tangem.core.ui.components.SystemBarsEffect
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.screen.ComposeFragment
import com.tangem.tap.common.analytics.events.SignIn
@ -49,19 +48,14 @@ internal class WelcomeFragment : ComposeFragment() {
val errorMessage by rememberUpdatedState(newValue = state.error?.resolveReference())
val warning by rememberUpdatedState(newValue = state.warning)
val backgroundColor = TangemTheme.colors.background.primary
SystemBarsEffect {
setSystemBarsColor(backgroundColor)
}
BackHandler {
requireActivity().finish()
}
Box(
modifier = modifier
.systemBarsPadding()
.background(backgroundColor),
.background(TangemTheme.colors.background.primary)
.systemBarsPadding(),
) {
WelcomeScreenContent(
showUnlockProgress = state.showUnlockWithBiometricsProgress,
@ -88,8 +82,4 @@ internal class WelcomeFragment : ComposeFragment() {
}
}
}
internal companion object {
const val INITIAL_INTENT_KEY = "intent"
}
}

View file

@ -1,8 +1,11 @@
package com.tangem.tap.features.welcome.ui
import android.content.Intent
import android.os.Bundle
import androidx.lifecycle.*
import com.tangem.common.core.TangemError
import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.bundle.unbundle
import com.tangem.common.routing.entity.SerializableIntent
import com.tangem.core.analytics.Analytics
import com.tangem.domain.wallets.legacy.UserWalletsListError
import com.tangem.tap.common.analytics.events.SignIn
@ -26,7 +29,8 @@ internal class WelcomeViewModel @Inject constructor(
StoreSubscriber<WelcomeState>,
DefaultLifecycleObserver {
private val initialIntent: Intent? = savedStateHandle[WelcomeFragment.INITIAL_INTENT_KEY]
private val initialIntent: SerializableIntent? = savedStateHandle.get<Bundle>(AppRoute.Welcome.INITIAL_INTENT_KEY)
?.let { it.unbundle(SerializableIntent.serializer()) }
private val stateInternal = MutableStateFlow(WelcomeScreenState())
val state: StateFlow<WelcomeScreenState> = stateInternal
@ -38,7 +42,7 @@ internal class WelcomeViewModel @Inject constructor(
initGlobalState()
val welcomeAction = if (initialIntent != null) {
WelcomeAction.ProceedWithIntent(initialIntent)
WelcomeAction.ProceedWithIntent(initialIntent.toIntent())
} else {
WelcomeAction.ProceedWithBiometrics()
}