From 000f5d018761eb8bd37dd89e1f183843bc2a343f Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 26 Dec 2024 15:05:22 +0400 Subject: [PATCH] Updated on 2026-08-14 --- .../java/com/tangem/tap/DecomposeFragment.kt | 6 --- .../main/java/com/tangem/tap/MainActivity.kt | 48 +++++++++++++++++-- .../wallet/ui/OnboardingWalletFragment.kt | 5 -- app/src/main/res/layout/activity_main.xml | 6 +++ .../components/snackbar/TangemSnackbarHost.kt | 17 +++++-- .../features/details/ui/DetailsScreen.kt | 8 ---- .../managetokens/ui/ManageTokensScreen.kt | 8 ---- .../ui/OnboardingManageTokensContent.kt | 10 ---- .../impl/DefaultMarketsEntryComponent.kt | 20 ++++---- .../tokendetails/ui/TokenDetailsScreen.kt | 11 ----- .../walletsettings/ui/WalletSettingsScreen.kt | 8 ---- 11 files changed, 72 insertions(+), 75 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/DecomposeFragment.kt b/app/src/main/java/com/tangem/tap/DecomposeFragment.kt index 296704a5e1..ad37670303 100644 --- a/app/src/main/java/com/tangem/tap/DecomposeFragment.kt +++ b/app/src/main/java/com/tangem/tap/DecomposeFragment.kt @@ -8,7 +8,6 @@ import com.tangem.core.decompose.context.AppComponentContext import com.tangem.core.decompose.factory.ComponentFactory import com.tangem.core.ui.UiDependencies import com.tangem.core.ui.decompose.ComposableContentComponent -import com.tangem.core.ui.message.EventMessageEffect import com.tangem.core.ui.screen.ComposeFragment import com.tangem.utils.Provider import dagger.hilt.android.AndroidEntryPoint @@ -33,11 +32,6 @@ internal class DecomposeFragment : ComposeFragment() { @Composable override fun ScreenContent(modifier: Modifier) { component.Content(modifier) - - EventMessageEffect( - messageHandler = uiDependencies.eventMessageHandler, - snackbarHostState = uiDependencies.globalSnackbarHostState, - ) } private class ComponentBuilder>( diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index 94cc27578a..b5cd3eab19 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -7,7 +7,6 @@ import android.content.res.Configuration import android.os.Build import android.os.Bundle import android.view.MotionEvent -import android.view.View import android.view.WindowManager import androidx.activity.SystemBarStyle import androidx.activity.compose.setContent @@ -21,6 +20,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.platform.ViewCompositionStrategy import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.lifecycle.Lifecycle @@ -39,10 +39,14 @@ import com.tangem.core.decompose.context.AppComponentContext import com.tangem.core.decompose.di.RootAppComponentContext import com.tangem.core.deeplink.DeepLinksRegistry import com.tangem.core.navigation.email.EmailSender +import com.tangem.core.ui.UiDependencies import com.tangem.core.ui.event.StateEvent import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.resolveReference +import com.tangem.core.ui.message.EventMessageEffect +import com.tangem.core.ui.message.SnackbarMessage import com.tangem.core.ui.res.TangemColorPalette +import com.tangem.core.ui.res.TangemTheme import com.tangem.data.card.sdk.CardSdkOwner import com.tangem.domain.apptheme.model.AppThemeMode import com.tangem.domain.card.ScanCardUseCase @@ -216,6 +220,9 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac @Inject internal lateinit var routingFeatureToggles: RoutingFeatureToggles + @Inject + internal lateinit var uiDependencies: UiDependencies + internal val viewModel: MainViewModel by viewModels() private lateinit var appThemeModeFlow: SharedFlow @@ -267,6 +274,7 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac } else { setContentView(R.layout.activity_main) installRouting() + installEventMessageEffect() } initContent() @@ -283,6 +291,33 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac lifecycle.addObserver(WindowObscurationObserver) } + private fun installEventMessageEffect() { + binding.composeView.setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) + binding.composeView.setContent { + TangemTheme( + activity = this, + uiDependencies = uiDependencies, + overrideSystemBarColors = false, + ) { + EventMessageEffect( + onShowSnackbar = { message, _ -> + showSnackbar( + text = message.message.resolveReference(resources), + length = when (message.duration) { + SnackbarMessage.Duration.Short -> Snackbar.LENGTH_SHORT + SnackbarMessage.Duration.Long -> Snackbar.LENGTH_LONG + SnackbarMessage.Duration.Indefinite -> Snackbar.LENGTH_INDEFINITE + }, + buttonTitle = message.actionLabel?.resolveReference(resources), + action = message.action, + onDismiss = message.onDismissRequest, + ) + }, + ) + } + } + } + private fun setRootContent() { val routingComponent = routingComponentFactory.create( context = rootComponentContext, @@ -557,7 +592,13 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac return if (result) super.dispatchTouchEvent(event) else false } - private fun showSnackbar(text: String, length: Int, buttonTitle: String?, action: View.OnClickListener?) { + private fun showSnackbar( + text: String, + length: Int, + buttonTitle: String?, + action: (() -> Unit)? = null, + onDismiss: () -> Unit = {}, + ) { if (snackbar != null) return snackbar = Snackbar.make(binding.fragmentContainer, text, length).apply { @@ -568,12 +609,13 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac setTextColor(textColor) if (buttonTitle != null && action != null) { - setAction(buttonTitle, action) + setAction(buttonTitle, { action() }) } addCallback( object : BaseTransientBottomBar.BaseCallback() { override fun onDismissed(transientBottomBar: Snackbar?, event: Int) { + onDismiss() snackbar = null removeCallback(this) } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt index 7f20094f7b..60ecd8a44e 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt @@ -37,7 +37,6 @@ import com.tangem.core.decompose.context.childByContext import com.tangem.core.decompose.di.RootAppComponentContext import com.tangem.core.ui.UiDependencies import com.tangem.core.ui.extensions.setStatusBarColor -import com.tangem.core.ui.message.EventMessageEffect import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.windowsize.rememberWindowSize import com.tangem.datasource.utils.isNullOrEmpty @@ -301,10 +300,6 @@ class OnboardingWalletFragment : windowSize = rememberWindowSize(activity = requireActivity()), ) { onboardingManageTokensComponent?.Content(modifier = Modifier.fillMaxSize()) - EventMessageEffect( - messageHandler = uiDependencies.eventMessageHandler, - snackbarHostState = uiDependencies.globalSnackbarHostState, - ) } } } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index aa962825e1..dac7964d66 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -6,4 +6,10 @@ android:background="@color/background_primary" android:filterTouchesWhenObscured="true"> + + \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/snackbar/TangemSnackbarHost.kt b/core/ui/src/main/java/com/tangem/core/ui/components/snackbar/TangemSnackbarHost.kt index d1cd229f6d..9f9fdabff9 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/snackbar/TangemSnackbarHost.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/snackbar/TangemSnackbarHost.kt @@ -9,15 +9,18 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter +import com.tangem.core.ui.res.LocalSnackbarHostState import com.tangem.core.ui.res.TangemThemePreview /** * Tangem snackbar host. - * Based on Material3 component. It's best way to show [TangemSnackbar]. + * Based on Material3 component. It's the best way to show [TangemSnackbar]. * - * @param hostState snackbar host state - * @param modifier modifier - * @param actionOnNewLine flag that indicates if the action should be displayed on a new line (default: false) + * @param modifier Modifier to be applied to the layout. + * @param hostState SnackbarHostState that will be used to show snackbar. + * Optional parameter. By default, it uses [LocalSnackbarHostState.current]. + * @param actionOnNewLine Flag that indicates if the action should be displayed on a new line. + * Optional parameter, `false` by default. * * @see Figma @@ -25,7 +28,11 @@ import com.tangem.core.ui.res.TangemThemePreview [REDACTED_AUTHOR] */ @Composable -fun TangemSnackbarHost(hostState: SnackbarHostState, modifier: Modifier = Modifier, actionOnNewLine: Boolean = false) { +fun TangemSnackbarHost( + modifier: Modifier = Modifier, + hostState: SnackbarHostState = LocalSnackbarHostState.current, + actionOnNewLine: Boolean = false, +) { SnackbarHost(hostState = hostState, modifier = modifier) { data -> TangemSnackbar(data = data, actionOnNewLine = actionOnNewLine) } diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/ui/DetailsScreen.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/ui/DetailsScreen.kt index 8054977653..0c2faf9735 100644 --- a/features/details/impl/src/main/kotlin/com/tangem/features/details/ui/DetailsScreen.kt +++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/ui/DetailsScreen.kt @@ -22,10 +22,8 @@ import androidx.compose.ui.tooling.preview.Preview import com.tangem.core.ui.components.appbar.TangemTopAppBar import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM import com.tangem.core.ui.components.block.BlockItem -import com.tangem.core.ui.components.snackbar.TangemSnackbarHost import com.tangem.core.ui.decompose.ComposableContentComponent import com.tangem.core.ui.extensions.stringResourceSafe -import com.tangem.core.ui.res.LocalSnackbarHostState import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview import com.tangem.core.ui.test.TestTags @@ -48,12 +46,6 @@ internal fun DetailsScreen( Scaffold( modifier = modifier, containerColor = backgroundColor, - snackbarHost = { - TangemSnackbarHost( - modifier = Modifier.padding(all = TangemTheme.dimens.spacing16), - hostState = LocalSnackbarHostState.current, - ) - }, topBar = { TangemTopAppBar( modifier = Modifier.statusBarsPadding(), diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/ui/ManageTokensScreen.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/ui/ManageTokensScreen.kt index fa7699bc52..e35c8871c7 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/ui/ManageTokensScreen.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/ui/ManageTokensScreen.kt @@ -50,14 +50,12 @@ import com.tangem.core.ui.components.rows.ChainRow import com.tangem.core.ui.components.rows.ChainRowContainer import com.tangem.core.ui.components.rows.model.BlockchainRowUM import com.tangem.core.ui.components.rows.model.ChainRowUM -import com.tangem.core.ui.components.snackbar.TangemSnackbarHost import com.tangem.core.ui.event.EventEffect import com.tangem.core.ui.extensions.resolveReference import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.stringResourceSafe import com.tangem.core.ui.haptic.TangemHapticEffect import com.tangem.core.ui.res.LocalHapticManager -import com.tangem.core.ui.res.LocalSnackbarHostState import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview import com.tangem.core.ui.utils.WindowInsetsZero @@ -100,12 +98,6 @@ internal fun ManageTokensScreen(state: ManageTokensUM, modifier: Modifier = Modi state = state, ) }, - snackbarHost = { - TangemSnackbarHost( - modifier = Modifier.padding(all = TangemTheme.dimens.spacing16), - hostState = LocalSnackbarHostState.current, - ) - }, floatingActionButtonPosition = FabPosition.Center, floatingActionButton = { if (state is ManageTokensUM.ManageContent) { diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/ui/OnboardingManageTokensContent.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/ui/OnboardingManageTokensContent.kt index e9752d8611..1d764d21a2 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/ui/OnboardingManageTokensContent.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/ui/OnboardingManageTokensContent.kt @@ -17,10 +17,8 @@ import com.tangem.core.ui.components.PrimaryButton import com.tangem.core.ui.components.PrimaryButtonIconEnd import com.tangem.core.ui.components.SecondaryButton import com.tangem.core.ui.components.fields.SearchBar -import com.tangem.core.ui.components.snackbar.TangemSnackbarHost import com.tangem.core.ui.event.EventEffect import com.tangem.core.ui.extensions.stringResourceSafe -import com.tangem.core.ui.res.LocalSnackbarHostState import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview import com.tangem.core.ui.utils.WindowInsetsZero @@ -53,14 +51,6 @@ internal fun OnboardingManageTokensContent(state: OnboardingManageTokensUM, modi state = state, ) }, - snackbarHost = { - TangemSnackbarHost( - modifier = Modifier - .padding(all = TangemTheme.dimens.spacing16) - .navigationBarsPadding(), - hostState = LocalSnackbarHostState.current, - ) - }, floatingActionButtonPosition = FabPosition.Center, floatingActionButton = { FloatingActionButton( diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/entry/impl/DefaultMarketsEntryComponent.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/entry/impl/DefaultMarketsEntryComponent.kt index 79865f0661..ae0a8b3e09 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/entry/impl/DefaultMarketsEntryComponent.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/entry/impl/DefaultMarketsEntryComponent.kt @@ -1,23 +1,26 @@ package com.tangem.features.markets.entry.impl -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Stable +import androidx.compose.runtime.State import androidx.compose.ui.Modifier import androidx.compose.ui.unit.Dp import com.arkivanov.decompose.ExperimentalDecomposeApi import com.arkivanov.decompose.extensions.compose.jetpack.subscribeAsState -import com.arkivanov.decompose.router.stack.* +import com.arkivanov.decompose.router.stack.ChildStack +import com.arkivanov.decompose.router.stack.StackNavigation +import com.arkivanov.decompose.router.stack.childStack +import com.arkivanov.decompose.router.stack.pushNew import com.arkivanov.decompose.value.Value import com.tangem.core.decompose.context.AppComponentContext import com.tangem.core.decompose.context.childByContext import com.tangem.core.decompose.navigation.Router -import com.tangem.core.ui.UiDependencies -import com.tangem.core.ui.message.EventMessageEffect import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.markets.TokenMarket +import com.tangem.domain.markets.toSerializableParam +import com.tangem.features.markets.details.MarketsTokenDetailsComponent import com.tangem.features.markets.entry.BottomSheetState import com.tangem.features.markets.entry.MarketsEntryComponent -import com.tangem.features.markets.details.MarketsTokenDetailsComponent -import com.tangem.domain.markets.toSerializableParam import com.tangem.features.markets.entry.impl.MarketsEntryChildFactory.Child import com.tangem.features.markets.entry.impl.ui.EntryBottomSheetContent import dagger.assisted.Assisted @@ -28,7 +31,6 @@ import dagger.assisted.AssistedInject internal class DefaultMarketsEntryComponent @AssistedInject constructor( @Assisted context: AppComponentContext, private val marketsEntryChildFactory: MarketsEntryChildFactory, - private val uiDependencies: UiDependencies, ) : MarketsEntryComponent, AppComponentContext by context { private val stackNavigation = StackNavigation() @@ -64,10 +66,6 @@ internal class DefaultMarketsEntryComponent @AssistedInject constructor( stackState = stack.subscribeAsState(), modifier = modifier, ) - EventMessageEffect( - messageHandler = uiDependencies.eventMessageHandler, - snackbarHostState = uiDependencies.globalSnackbarHostState, - ) } @OptIn(ExperimentalDecomposeApi::class) diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/TokenDetailsScreen.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/TokenDetailsScreen.kt index 87ec82270c..097f21a1b0 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/TokenDetailsScreen.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/TokenDetailsScreen.kt @@ -32,7 +32,6 @@ import com.tangem.core.ui.components.marketprice.MarketPriceBlock import com.tangem.core.ui.components.marketprice.MarketPriceBlockState import com.tangem.core.ui.components.notifications.Notification import com.tangem.core.ui.components.notifications.OkxPromoNotification -import com.tangem.core.ui.components.snackbar.TangemSnackbarHost import com.tangem.core.ui.components.transactions.state.TxHistoryState import com.tangem.core.ui.components.transactions.txHistoryItems import com.tangem.core.ui.event.EventEffect @@ -65,16 +64,6 @@ internal fun TokenDetailsScreen(state: TokenDetailsState, tokenMarketBlockCompon val snackbarHostState = remember { SnackbarHostState() } Scaffold( topBar = { TokenDetailsTopAppBar(config = state.topAppBarConfig) }, - snackbarHost = { - TangemSnackbarHost( - modifier = Modifier.padding( - start = TangemTheme.dimens.spacing16, - end = TangemTheme.dimens.spacing16, - bottom = bottomBarHeight + TangemTheme.dimens.spacing16, - ), - hostState = snackbarHostState, - ) - }, contentWindowInsets = ScaffoldDefaults.contentWindowInsets.exclude(WindowInsets.navigationBars), containerColor = TangemTheme.colors.background.secondary, ) { scaffoldPaddings -> diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/ui/WalletSettingsScreen.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/ui/WalletSettingsScreen.kt index 15a43446e9..b2c0270b20 100644 --- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/ui/WalletSettingsScreen.kt +++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/ui/WalletSettingsScreen.kt @@ -18,10 +18,8 @@ import com.tangem.core.ui.components.appbar.TangemTopAppBar import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM import com.tangem.core.ui.components.block.BlockCard import com.tangem.core.ui.components.block.BlockItem -import com.tangem.core.ui.components.snackbar.TangemSnackbarHost import com.tangem.core.ui.extensions.resolveReference import com.tangem.core.ui.extensions.stringResourceSafe -import com.tangem.core.ui.res.LocalSnackbarHostState import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview import com.tangem.core.ui.test.TestTags @@ -43,12 +41,6 @@ internal fun WalletSettingsScreen( Scaffold( modifier = modifier, containerColor = backgroundColor, - snackbarHost = { - TangemSnackbarHost( - modifier = Modifier.padding(all = TangemTheme.dimens.spacing16), - hostState = LocalSnackbarHostState.current, - ) - }, topBar = { TangemTopAppBar( modifier = Modifier.statusBarsPadding(),