diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index 60676fa1f7..6186775651 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -489,7 +489,9 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac * `android:configChanges="uiMode"` is set in the manifest. * */ - updateAppBackground() + if (routingFeatureToggles.isNavigationRefactoringEnabled.not()) { + updateAppBackground() + } } private fun updateAppBackground() { diff --git a/app/src/main/java/com/tangem/tap/routing/RootContent.kt b/app/src/main/java/com/tangem/tap/routing/RootContent.kt index 669e7f44a3..f320d18a1c 100644 --- a/app/src/main/java/com/tangem/tap/routing/RootContent.kt +++ b/app/src/main/java/com/tangem/tap/routing/RootContent.kt @@ -2,28 +2,36 @@ package com.tangem.tap.routing import android.app.Activity import android.os.Bundle +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp import androidx.core.content.ContextCompat.startActivity +import com.arkivanov.decompose.ExperimentalDecomposeApi import com.arkivanov.decompose.extensions.compose.stack.Children +import com.arkivanov.decompose.extensions.compose.stack.animation.* import com.arkivanov.decompose.router.stack.ChildStack +import com.arkivanov.decompose.value.Value import com.tangem.common.routing.AppRoute import com.tangem.core.ui.UiDependencies import com.tangem.core.ui.components.snackbar.TangemSnackbarHost import com.tangem.core.ui.message.EventMessageEffect +import com.tangem.core.ui.res.LocalIsNavigationRefactoringEnabled import com.tangem.core.ui.res.LocalSnackbarHostState import com.tangem.core.ui.res.TangemTheme -import com.tangem.core.ui.utils.WindowInsetsZero import com.tangem.tap.routing.component.RoutingComponent +@OptIn(ExperimentalDecomposeApi::class) @Composable internal fun RootContent( - stack: ChildStack, + stack: Value>, uiDependencies: UiDependencies, modifier: Modifier = Modifier, ) { @@ -33,21 +41,15 @@ internal fun RootContent( activity = context as Activity, uiDependencies = uiDependencies, ) { - val snackbarHostState = LocalSnackbarHostState.current + CompositionLocalProvider( + LocalIsNavigationRefactoringEnabled provides true, + ) { + val snackbarHostState = LocalSnackbarHostState.current - Scaffold( - modifier = modifier, - containerColor = TangemTheme.colors.background.primary, - snackbarHost = { - TangemSnackbarHost( - modifier = Modifier.padding(all = 16.dp), - hostState = snackbarHostState, - ) - }, - contentWindowInsets = WindowInsetsZero, - content = { paddingValues -> + Box(Modifier.background(TangemTheme.colors.background.primary)) { Children( - modifier = Modifier.padding(paddingValues), + modifier = modifier, + animation = stackAnimation(fade()), stack = stack, ) { child -> when (val instance = child.instance) { @@ -63,8 +65,16 @@ internal fun RootContent( -> error("Unsupported child: $instance") } } - }, - ) + + TangemSnackbarHost( + modifier = Modifier + .align(Alignment.BottomCenter) + .navigationBarsPadding() + .padding(all = 16.dp), + hostState = snackbarHostState, + ) + } + } EventMessageEffect() } diff --git a/app/src/main/java/com/tangem/tap/routing/component/impl/DefaultRoutingComponent.kt b/app/src/main/java/com/tangem/tap/routing/component/impl/DefaultRoutingComponent.kt index cafffe14d3..759951e25e 100644 --- a/app/src/main/java/com/tangem/tap/routing/component/impl/DefaultRoutingComponent.kt +++ b/app/src/main/java/com/tangem/tap/routing/component/impl/DefaultRoutingComponent.kt @@ -4,12 +4,10 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import com.arkivanov.decompose.ComponentContext -import com.arkivanov.decompose.extensions.compose.subscribeAsState import com.arkivanov.decompose.router.stack.ChildStack import com.arkivanov.decompose.router.stack.childStack import com.arkivanov.decompose.value.Value import com.arkivanov.decompose.value.subscribe -import com.arkivanov.essenty.backhandler.BackCallback import com.arkivanov.essenty.lifecycle.doOnDestroy import com.google.android.material.snackbar.Snackbar import com.tangem.common.routing.AppRoute @@ -43,19 +41,15 @@ internal class DefaultRoutingComponent @AssistedInject constructor( AppComponentContext by context, SnackbarHandler { - private val backCallback = BackCallback(priority = Int.MIN_VALUE, onBack = router::pop) - override val stack: Value> = childStack( source = navigationProvider.getOrCreateTyped(), initialStack = { getInitialStackOrInit() }, serializer = null, // AppRoute.serializer(), // Disabled until Nav refactoring completes - handleBackButton = false, + handleBackButton = routingFeatureToggles.isNavigationRefactoringEnabled, childFactory = ::child, ) init { - backHandler.register(backCallback) - lifecycle.doOnDestroy { childFactory.doOnDestroy() } @@ -77,8 +71,6 @@ internal class DefaultRoutingComponent @AssistedInject constructor( @Composable override fun Content(modifier: Modifier) { - val stack by this.stack.subscribeAsState() - RootContent( modifier = modifier, stack = stack, diff --git a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt index 732fe9d4d0..6fbc0a8a83 100644 --- a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt +++ b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt @@ -87,31 +87,28 @@ internal class ChildFactory @Inject constructor( fun createChild(route: AppRoute, contextFactory: (route: AppRoute) -> AppComponentContext): Child { return if (routingFeatureToggles.isNavigationRefactoringEnabled) { - createChildNew(route, contextFactory) + createChildNew(route, contextFactory(route)) } else { createChildLegacy(route, contextFactory) } } @Suppress("LongMethod", "CyclomaticComplexMethod") - private fun createChildNew(route: AppRoute, contextFactory: (route: AppRoute) -> AppComponentContext): Child { - componentContexts[route] = contextFactory(route) - - // region Child creation + private fun createChildNew(route: AppRoute, context: AppComponentContext): Child { return when (route) { is AppRoute.Initial -> { Child.Initial } is AppRoute.Details -> { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = DetailsComponent.Params(route.userWalletId), componentFactory = detailsComponentFactory, ) } is AppRoute.Disclaimer -> { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = DisclaimerComponent.Params(route.isTosAccepted), componentFactory = disclaimerComponentFactory, ) @@ -124,14 +121,14 @@ internal class ChildFactory @Inject constructor( } createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = ManageTokensComponent.Params(route.userWalletId, source), componentFactory = manageTokensComponentFactory, ) } is AppRoute.Welcome -> { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = WelcomeComponent.Params( intent = route.intent, ), @@ -143,14 +140,14 @@ internal class ChildFactory @Inject constructor( } is AppRoute.WalletSettings -> { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = WalletSettingsComponent.Params(route.userWalletId), componentFactory = walletSettingsComponentFactory, ) } is AppRoute.MarketsTokenDetails -> { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = MarketsTokenDetailsComponent.Params( token = route.token, appCurrency = route.appCurrency, @@ -167,7 +164,7 @@ internal class ChildFactory @Inject constructor( } is AppRoute.Onramp -> { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = OnrampComponent.Params( userWalletId = route.userWalletId, cryptoCurrency = route.currency, @@ -178,35 +175,35 @@ internal class ChildFactory @Inject constructor( } is AppRoute.OnrampSuccess -> { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = OnrampSuccessComponent.Params(route.externalTxId), componentFactory = onrampSuccessComponentFactory, ) } is AppRoute.BuyCrypto -> { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = BuyCryptoComponent.Params(userWalletId = route.userWalletId), componentFactory = buyCryptoComponentFactory, ) } is AppRoute.SellCrypto -> { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = SellCryptoComponent.Params(userWalletId = route.userWalletId), componentFactory = sellCryptoComponentFactory, ) } is AppRoute.SwapCrypto -> { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = SwapSelectTokensComponent.Params(userWalletId = route.userWalletId), componentFactory = swapSelectTokensComponentFactory, ) } is AppRoute.Onboarding -> { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = OnboardingEntryComponent.Params( scanResponse = route.scanResponse, mode = when (route.mode) { @@ -222,7 +219,7 @@ internal class ChildFactory @Inject constructor( } is AppRoute.Stories -> { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = StoriesComponent.Params( storyId = route.storyId, nextScreen = route.nextScreen, @@ -233,7 +230,7 @@ internal class ChildFactory @Inject constructor( } is AppRoute.CurrencyDetails -> { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = TokenDetailsComponent.Params( userWalletId = route.userWalletId, currency = route.currency, @@ -243,7 +240,7 @@ internal class ChildFactory @Inject constructor( } is AppRoute.Staking -> { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = StakingComponent.Params( userWalletId = route.userWalletId, cryptoCurrencyId = route.cryptoCurrencyId, @@ -254,7 +251,7 @@ internal class ChildFactory @Inject constructor( } is AppRoute.Swap -> { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = SwapComponent.Params( currencyFrom = route.currencyFrom, currencyTo = route.currencyTo, @@ -268,7 +265,7 @@ internal class ChildFactory @Inject constructor( is AppRoute.Send -> { if (sendFeatureToggles.isSendV2Enabled) { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = com.tangem.features.send.v2.api.SendComponent.Params( userWalletId = route.userWalletId, currency = route.currency, @@ -281,7 +278,7 @@ internal class ChildFactory @Inject constructor( ) } else { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = SendComponent.Params( userWalletId = route.userWalletId, currency = route.currency, @@ -296,7 +293,7 @@ internal class ChildFactory @Inject constructor( } is AppRoute.Home -> { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = Unit, componentFactory = homeComponentFactory, ) @@ -304,13 +301,13 @@ internal class ChildFactory @Inject constructor( is AppRoute.WalletConnectSessions -> { if (walletConnectFeatureToggles.isRedesignedWalletConnectEnabled) { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = Unit, componentFactory = redesignedWalletConnectComponentFactory, ) } else { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = Unit, componentFactory = walletConnectComponentFactory, ) @@ -322,7 +319,7 @@ internal class ChildFactory @Inject constructor( is AppRoute.QrScanning.Source.WalletConnect -> SourceType.WALLET_CONNECT } createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = QrScanningComponent.Params( source = source, networkName = (route.source as? AppRoute.QrScanning.Source.Send)?.networkName, @@ -332,35 +329,35 @@ internal class ChildFactory @Inject constructor( } is AppRoute.AccessCodeRecovery -> { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = Unit, componentFactory = accessCodeRecoveryComponentFactory, ) } is AppRoute.CardSettings -> { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = CardSettingsComponent.Params(userWalletId = route.userWalletId), componentFactory = cardSettingsComponentFactory, ) } is AppRoute.AppCurrencySelector -> { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = Unit, componentFactory = appCurrencySelectorComponentFactory, ) } is AppRoute.AppSettings -> { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = Unit, componentFactory = appSettingsComponentFactory, ) } is AppRoute.DetailsSecurity -> { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = SecurityModeComponent.Params( userWalletId = route.userWalletId, ), @@ -369,7 +366,7 @@ internal class ChildFactory @Inject constructor( } is AppRoute.ResetToFactory -> { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = ResetCardComponent.Params( userWalletId = route.userWalletId, cardId = route.cardId, @@ -381,21 +378,21 @@ internal class ChildFactory @Inject constructor( } is AppRoute.ReferralProgram -> { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = ReferralComponent.Params(route.userWalletId), componentFactory = referralComponentFactory, ) } is AppRoute.PushNotification -> { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = Unit, componentFactory = pushNotificationsComponentFactory, ) } is AppRoute.Wallet -> { createComponentChild( - contextProvider = contextProvider(route, contextFactory), + context = context, params = Unit, componentFactory = walletComponentFactory, ) diff --git a/app/src/main/java/com/tangem/tap/routing/utils/RouteMappers.kt b/app/src/main/java/com/tangem/tap/routing/utils/RouteMappers.kt index e7aa49f4d9..f20d2b096b 100644 --- a/app/src/main/java/com/tangem/tap/routing/utils/RouteMappers.kt +++ b/app/src/main/java/com/tangem/tap/routing/utils/RouteMappers.kt @@ -40,11 +40,9 @@ internal fun > createComponentChild( - contextProvider: Provider, + context: AppComponentContext, params: P, componentFactory: F, ): Child { - val context = contextProvider() - return Child.ComposableComponent(componentFactory.create(context, params)) } \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/res/TangemTheme.kt b/core/ui/src/main/java/com/tangem/core/ui/res/TangemTheme.kt index de31c28cc4..fd2a88637f 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/res/TangemTheme.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/res/TangemTheme.kt @@ -312,6 +312,11 @@ val LocalBladeAnimation = staticCompositionLocalOf { error("No MainBottomSheetColor provided") } +// TODO remove this after migration to new navigation +val LocalIsNavigationRefactoringEnabled = staticCompositionLocalOf { + false +} + /** * Determines whether the dark theme should be used based on the given [AppThemeMode]. * diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt index ff7362b3c2..28aa1a4a5e 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt @@ -59,6 +59,7 @@ import com.tangem.core.ui.components.snackbar.TangemSnackbar import com.tangem.core.ui.components.transactions.state.TxHistoryState import com.tangem.core.ui.event.StateEvent import com.tangem.core.ui.extensions.stringResourceSafe +import com.tangem.core.ui.res.LocalIsNavigationRefactoringEnabled import com.tangem.core.ui.res.LocalMainBottomSheetColor import com.tangem.core.ui.res.LocalWindowSize import com.tangem.core.ui.res.TangemTheme @@ -427,7 +428,11 @@ private inline fun BaseScaffoldWithMarkets( .padding(bottom = 24.dp) .fillMaxWidth(fraction = 0.7f), isVisible = state.showMarketsOnboarding, - availableHeight = maxHeight - statusBarHeight - bottomBarHeight, + availableHeight = if (LocalIsNavigationRefactoringEnabled.current) { + maxHeight + } else { + maxHeight - statusBarHeight - bottomBarHeight + }, bottomSheetState = bottomSheetState, ) }