diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index e55b98f204..cf81714141 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -12,15 +12,18 @@ import android.nfc.NfcAdapter import android.os.Build import android.os.Bundle import android.view.View +import androidx.activity.SystemBarStyle +import androidx.activity.enableEdgeToEdge import androidx.activity.viewModels import androidx.annotation.StringRes import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate.setDefaultNightMode +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.toArgb import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen -import androidx.core.view.WindowCompat import androidx.lifecycle.Lifecycle import androidx.lifecycle.flowWithLifecycle import androidx.lifecycle.lifecycleScope @@ -195,6 +198,13 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac installAppTheme() // We need to call it before onCreate to prevent unnecessary activity recreation + enableEdgeToEdge( + navigationBarStyle = SystemBarStyle.auto( + Color.Transparent.toArgb(), + Color.Transparent.toArgb(), + ), + ) + super.onCreate(savedInstanceState) splashScreen.setKeepOnScreenCondition { viewModel.isSplashScreenShown } @@ -307,8 +317,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac @SuppressLint("SourceLockedOrientationActivity") private fun initContent() { - WindowCompat.setDecorFitsSystemWindows(window, false) - supportFragmentManager.registerFragmentLifecycleCallbacks( NavBarInsetsFragmentLifecycleCallback(), true, diff --git a/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/AddCustomTokenFragment.kt b/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/AddCustomTokenFragment.kt index da295c57c5..3bae12b5a1 100644 --- a/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/AddCustomTokenFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/AddCustomTokenFragment.kt @@ -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().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, ) } diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/AppCurrencySelectorFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/AppCurrencySelectorFragment.kt index d48050ec85..e4170e8003 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/AppCurrencySelectorFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/AppCurrencySelectorFragment.kt @@ -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, diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/AppCurrencySelectorScreen.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/AppCurrencySelectorScreen.kt index b29b503a39..168fccb7e7 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/AppCurrencySelectorScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/AppCurrencySelectorScreen.kt @@ -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, diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsScreen.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsScreen.kt index c60f34ecce..f3d0b721c9 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsScreen.kt @@ -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, diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/common/DetailsComposeElements.kt b/app/src/main/java/com/tangem/tap/features/details/ui/common/DetailsComposeElements.kt index 35b36c0f00..8cdc6777a9 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/common/DetailsComposeElements.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/common/DetailsComposeElements.kt @@ -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 = { diff --git a/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt b/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt index e27f58f4a3..f3fae68135 100644 --- a/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt @@ -6,14 +6,12 @@ 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.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 @@ -44,15 +42,12 @@ class HomeFragment : ComposeFragment(), StoreSubscriber { @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 diff --git a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/TokensListFragment.kt b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/TokensListFragment.kt index 272c773c95..ed260691fe 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/TokensListFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/TokensListFragment.kt @@ -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().apply { LocalLifecycleOwner.current.lifecycle.addObserver(this) } - val statusBarColor = TangemTheme.colors.background.secondary - SystemBarsEffect { - setSystemBarsColor(color = statusBarColor) - } TokensListScreen( - modifier = Modifier.systemBarsPadding(), stateHolder = viewModel.uiState, ) } diff --git a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/ui/TokensListScreen.kt b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/ui/TokensListScreen.kt index 56366dfb51..d045437bb8 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/ui/TokensListScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/ui/TokensListScreen.kt @@ -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, - 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", diff --git a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/ui/TokensListToolbar.kt b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/ui/TokensListToolbar.kt index 5e0aafc999..0a4dd9c309 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/ui/TokensListToolbar.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/ui/TokensListToolbar.kt @@ -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) { diff --git a/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeFragment.kt b/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeFragment.kt index 41ef679b6a..c34497d9f0 100644 --- a/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeFragment.kt @@ -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, diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/BottomFade.kt b/core/ui/src/main/java/com/tangem/core/ui/components/BottomFade.kt new file mode 100644 index 0000000000..fbb4ae896b --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/components/BottomFade.kt @@ -0,0 +1,33 @@ +package com.tangem.core.ui.components + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalDensity +import com.tangem.core.ui.res.TangemTheme + +/** + * A composable that draws a fade effect at the bottom of the screen. Used on screens with a list of repeating + * elements and floating button at the bottom of the screen. + */ +@Composable +fun BottomFade(modifier: Modifier = Modifier, backgroundColor: Color = TangemTheme.colors.background.secondary) { + val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() } + + Box( + modifier = modifier + .fillMaxWidth() + .height(TangemTheme.dimens.size100 + bottomBarHeight) + .background( + brush = Brush.verticalGradient( + colors = listOf( + Color.Transparent, + backgroundColor, + ), + ), + ), + ) +} \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/SystemBarsEffect.kt b/core/ui/src/main/java/com/tangem/core/ui/components/SystemBarsEffect.kt deleted file mode 100644 index ea843b7a7a..0000000000 --- a/core/ui/src/main/java/com/tangem/core/ui/components/SystemBarsEffect.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.tangem.core.ui.components - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.SideEffect -import com.google.accompanist.systemuicontroller.SystemUiController -import com.google.accompanist.systemuicontroller.rememberSystemUiController - -@Composable -fun SystemBarsEffect(block: SystemUiController.() -> Unit) { - val systemUiController = rememberSystemUiController() - SideEffect { block(systemUiController) } -} \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/SystemBarsUtils.kt b/core/ui/src/main/java/com/tangem/core/ui/components/SystemBarsUtils.kt new file mode 100644 index 0000000000..0e40554581 --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/components/SystemBarsUtils.kt @@ -0,0 +1,61 @@ +package com.tangem.core.ui.components + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.SideEffect +import com.google.accompanist.systemuicontroller.rememberSystemUiController +import com.tangem.core.ui.res.LocalIsInDarkTheme + +/** + * Provides the ability to set a scrim for 3-button navigation + * + * Automatically makes navigation bar transparent when the composable is disposed. + * + * Usage example: [com.tangem.feature.tokendetails.presentation.TokenDetailsFragment] + */ +@Composable +fun NavigationBar3ButtonsScrim() { + val systemUiController = rememberSystemUiController() + val isDarkTheme = LocalIsInDarkTheme.current + SideEffect { + systemUiController.isNavigationBarContrastEnforced = true + } + LaunchedEffect(systemUiController.isNavigationBarContrastEnforced) { + if (systemUiController.isNavigationBarContrastEnforced.not()) { + systemUiController.isNavigationBarContrastEnforced = true + } + } + DisposableEffect(isDarkTheme) { + onDispose { + systemUiController.isNavigationBarContrastEnforced = false + } + } +} + +/** + * Provides the ability to set dark/light icons in cases where the darkness of the screen differs from that + * provided in [TangemTheme]. + * + * Automatically returns the icon colors to their original state when the composable is disposed. + * + * Usage example: [com.tangem.feature.qrscanning.QrScanningFragment] + */ +@Composable +fun SystemBarsIconsDisposable(darkIcons: Boolean, isNavigationBarContrastEnforced: Boolean = false) { + val systemUiController = rememberSystemUiController() + + SideEffect { + systemUiController.systemBarsDarkContentEnabled = darkIcons + systemUiController.isNavigationBarContrastEnforced = isNavigationBarContrastEnforced + } + + val isDarkTheme = LocalIsInDarkTheme.current + + DisposableEffect(isDarkTheme) { + onDispose { + systemUiController.systemBarsDarkContentEnabled = !isDarkTheme + systemUiController.isNavigationBarContrastEnforced = false + } + } +} \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/TangemBottomSheet.kt b/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/TangemBottomSheet.kt index 3f934a0f9b..ec10ddfa0a 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/TangemBottomSheet.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/TangemBottomSheet.kt @@ -1,13 +1,14 @@ package com.tangem.core.ui.components.bottomsheets -import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.ModalBottomSheet -import androidx.compose.material3.SheetState -import androidx.compose.material3.rememberModalBottomSheetState +import androidx.compose.foundation.layout.* +import androidx.compose.material3.* import androidx.compose.runtime.* +import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalDensity +import com.tangem.core.ui.res.LocalWindowSize import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.utils.WindowInsetsZero import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.launch @@ -15,6 +16,7 @@ import kotlinx.coroutines.launch * Tangem bottom sheet with custom draggable header and config * * @param config data model containing logic and ui models + * @param * @param content custom bottom sheet content */ @OptIn(ExperimentalMaterial3Api::class) @@ -22,20 +24,33 @@ import kotlinx.coroutines.launch inline fun TangemBottomSheet( config: TangemBottomSheetConfig, containerColor: Color = TangemTheme.colors.background.primary, + addBottomInsets: Boolean = true, crossinline content: @Composable ColumnScope.(T) -> Unit, ) { var isVisible by remember { mutableStateOf(value = config.isShow) } - + val statusBarHeight = with(LocalDensity.current) { WindowInsets.statusBars.getTop(this).toDp() } val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) if (isVisible && config.content is T) { ModalBottomSheet( + // FIXME temporary solution to fix height of the bottom sheet + modifier = Modifier.sizeIn(maxHeight = LocalWindowSize.current.height - statusBarHeight), onDismissRequest = config.onDismissRequest, sheetState = sheetState, containerColor = containerColor, shape = TangemTheme.shapes.bottomSheetLarge, + windowInsets = WindowInsetsZero, dragHandle = { TangemBottomSheetDraggableHeader(color = containerColor) }, ) { - content(config.content) + if (addBottomInsets) { + Column( + // FIXME temporary solution to fix height of the bottom sheet + modifier = Modifier.navigationBarsPadding(), + ) { + content(config.content) + } + } else { + content(config.content) + } } } diff --git a/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt b/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt index 863f3e59cc..a2649901ad 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt @@ -81,6 +81,7 @@ data class TangemDimens internal constructor( val size90: Dp = 90.dp, val size93: Dp = 93.dp, val size96: Dp = 96.dp, + val size100: Dp = 100.dp, val size102: Dp = 102.dp, val size108: Dp = 108.dp, val size110: Dp = 110.dp, 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 968b635c5d..58552b1353 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 @@ -5,9 +5,10 @@ import androidx.compose.material.MaterialTheme import androidx.compose.material.ProvideTextStyle import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.* +import androidx.compose.ui.graphics.Color +import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.tangem.core.ui.haptic.HapticManager import com.tangem.core.ui.haptic.MockHapticManager - import com.tangem.core.ui.windowsize.WindowSize @Composable @@ -25,6 +26,16 @@ fun TangemTheme( .also { it.update(themeColors) } val shapes = remember { TangemShapes(dimens) } + val systemUiController = rememberSystemUiController() + + SideEffect { + systemUiController.setSystemBarsColor( + color = Color.Transparent, + darkIcons = !isDark, + isNavigationBarContrastEnforced = false, + ) + } + MaterialTheme( colors = materialThemeColors(colors = themeColors, isDark = isDark), ) { diff --git a/core/ui/src/main/java/com/tangem/core/ui/utils/WindowInsetsZero.kt b/core/ui/src/main/java/com/tangem/core/ui/utils/WindowInsetsZero.kt new file mode 100644 index 0000000000..a17ac5f1ef --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/utils/WindowInsetsZero.kt @@ -0,0 +1,12 @@ +package com.tangem.core.ui.utils + +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.ui.unit.Density +import androidx.compose.ui.unit.LayoutDirection + +object WindowInsetsZero : WindowInsets { + override fun getBottom(density: Density): Int = 0 + override fun getLeft(density: Density, layoutDirection: LayoutDirection): Int = 0 + override fun getRight(density: Density, layoutDirection: LayoutDirection): Int = 0 + override fun getTop(density: Density): Int = 0 +} \ No newline at end of file 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 af683ca7a8..02c43a0396 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 @@ -19,7 +19,6 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import com.tangem.core.ui.ComposableContentComponent -import com.tangem.core.ui.components.SystemBarsEffect import com.tangem.core.ui.components.snackbar.TangemSnackbarHost import com.tangem.core.ui.res.LocalSnackbarHostState import com.tangem.core.ui.res.TangemTheme @@ -42,10 +41,6 @@ internal fun DetailsScreen( val backgroundColor = TangemTheme.colors.background.secondary val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior() - SystemBarsEffect { - setSystemBarsColor(backgroundColor) - } - BackHandler(onBack = state.popBack) Scaffold( diff --git a/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/DisclaimerFragment.kt b/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/DisclaimerFragment.kt index fb87182dd5..e17e88299f 100644 --- a/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/DisclaimerFragment.kt +++ b/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/DisclaimerFragment.kt @@ -7,8 +7,6 @@ import androidx.compose.ui.Modifier import androidx.fragment.app.viewModels import com.tangem.common.routing.AppRouter 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.features.disclaimer.api.DisclaimerRouter import com.tangem.features.disclaimer.impl.presentation.ui.DisclaimerScreen @@ -37,7 +35,6 @@ internal class DisclaimerFragment : ComposeFragment() { @Composable override fun ScreenContent(modifier: Modifier) { - val systemBarsColor = TangemTheme.colors.background.primary BackHandler { if (isTosAccepted) { appRouter.pop() @@ -45,9 +42,6 @@ internal class DisclaimerFragment : ComposeFragment() { requireActivity().finish() } } - SystemBarsEffect { - setSystemBarsColor(systemBarsColor) - } DisclaimerScreen(viewModel.state, appRouter::pop) } diff --git a/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/presentation/ui/DisclaimerScreen.kt b/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/presentation/ui/DisclaimerScreen.kt index f99bd7bc4e..e9a40a7a03 100644 --- a/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/presentation/ui/DisclaimerScreen.kt +++ b/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/presentation/ui/DisclaimerScreen.kt @@ -15,17 +15,16 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.isGranted import com.google.accompanist.permissions.rememberPermissionState +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.components.appbar.AppBarWithAdditionalButtons import com.tangem.core.ui.components.appbar.models.AdditionalButton @@ -39,17 +38,14 @@ import com.tangem.features.disclaimer.impl.presentation.state.DummyDisclaimer @Composable internal fun DisclaimerScreen(state: DisclaimerState, onBackClick: () -> Unit) { - val bottomPadding = if (state.isTosAccepted) TangemTheme.dimens.spacing16 else TangemTheme.dimens.size64 + val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() } + Box( modifier = Modifier - .statusBarsPadding() - .background(TangemColorPalette.Dark6), + .background(TangemColorPalette.Dark6) + .statusBarsPadding(), ) { - Column( - modifier = Modifier - .navigationBarsPadding() - .padding(bottom = bottomPadding), - ) { + Column { AppBarWithAdditionalButtons( text = resourceReference(R.string.disclaimer_title), startButton = AdditionalButton( @@ -58,23 +54,34 @@ internal fun DisclaimerScreen(state: DisclaimerState, onBackClick: () -> Unit) { ).takeIf { state.isTosAccepted }, ) DisclaimerContent(state.url) + Spacer( + modifier = Modifier + .background(TangemColorPalette.Dark6) + .height( + height = if (!state.isTosAccepted) { + bottomBarHeight + } else { + bottomBarHeight + TangemTheme.dimens.size64 + }, + ), + ) } + if (!state.isTosAccepted) { + BottomFade(Modifier.align(Alignment.BottomCenter), backgroundColor = TangemColorPalette.Dark6) DisclaimerButton(state.onAccept) + } else { + NavigationBar3ButtonsScrim() } } } @Composable private fun ColumnScope.DisclaimerContent(url: String) { - val transparent = Color.Transparent - val progressState = remember { mutableStateOf(ProgressState.Loading) } val webClient = remember { DisclaimerWebViewClient(progressState) } Box( - modifier = Modifier - .fillMaxWidth() - .weight(1f), + modifier = Modifier, ) { AndroidView( factory = { @@ -83,9 +90,10 @@ private fun ColumnScope.DisclaimerContent(url: String) { ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, ) - setBackgroundColor(transparent.toArgb()) + setBackgroundColor(TangemColorPalette.Dark6.toArgb()) settings.allowFileAccess = false settings.javaScriptEnabled = false + overScrollMode = View.OVER_SCROLL_NEVER webViewClient = webClient loadUrl(url) @@ -94,28 +102,34 @@ private fun ColumnScope.DisclaimerContent(url: String) { ) when (progressState.value) { - ProgressState.Loading -> CircularProgressIndicator( - color = TangemTheme.colors.icon.informative, - modifier = Modifier - .align(Alignment.Center) - .padding(TangemTheme.dimens.spacing8), - ) - ProgressState.Error -> Column( - verticalArrangement = Arrangement.Center, - modifier = Modifier - .fillMaxWidth() - .padding(TangemTheme.dimens.spacing16) - .align(Alignment.Center), - ) { - Text( - text = stringResource(id = R.string.disclaimer_error_loading), - style = TangemTheme.typography.body1, - color = TangemTheme.colors.text.constantWhite, - ) - PrimaryButton( - text = stringResource(R.string.common_retry), - onClick = { webClient.reset() }, - ) + ProgressState.Loading -> { + Box(modifier = Modifier.fillMaxSize()) { + CircularProgressIndicator( + color = TangemTheme.colors.icon.informative, + modifier = Modifier + .align(Alignment.Center) + .padding(TangemTheme.dimens.spacing8), + ) + } + } + ProgressState.Error -> Box(modifier = Modifier.fillMaxSize()) { + Column( + verticalArrangement = Arrangement.Center, + modifier = Modifier + .fillMaxWidth() + .padding(TangemTheme.dimens.spacing16) + .align(Alignment.Center), + ) { + Text( + text = stringResource(id = R.string.disclaimer_error_loading), + style = TangemTheme.typography.body1, + color = TangemTheme.colors.text.constantWhite, + ) + PrimaryButton( + text = stringResource(R.string.common_retry), + onClick = { webClient.reset() }, + ) + } } else -> Unit } @@ -130,23 +144,6 @@ private fun BoxScope.DisclaimerButton(onAccept: (Boolean) -> Unit) { } else { true } - val bottomInsetsPx = WindowInsets.navigationBars.getBottom(LocalDensity.current) - Box( - modifier = Modifier - .align(Alignment.BottomCenter) - .fillMaxWidth() - .height(TangemTheme.dimens.size110 + bottomInsetsPx.dp) - .background( - Brush.verticalGradient( - colors = listOf( - TangemTheme.colors.background.primary.copy(alpha = 0f), - TangemTheme.colors.background.primary.copy(alpha = 0.75f), - TangemTheme.colors.background.primary.copy(alpha = 0.95f), - TangemTheme.colors.background.primary, - ), - ), - ), - ) PrimaryButton( text = stringResource(id = R.string.common_accept), onClick = { onAccept(shouldAskPushPermission) }, diff --git a/features/manage-tokens/impl/src/main/java/com/tangem/managetokens/presentation/addcustomtoken/ui/AddCustomTokenBottomSheet.kt b/features/manage-tokens/impl/src/main/java/com/tangem/managetokens/presentation/addcustomtoken/ui/AddCustomTokenBottomSheet.kt index 69fe567327..95dfd58871 100644 --- a/features/manage-tokens/impl/src/main/java/com/tangem/managetokens/presentation/addcustomtoken/ui/AddCustomTokenBottomSheet.kt +++ b/features/manage-tokens/impl/src/main/java/com/tangem/managetokens/presentation/addcustomtoken/ui/AddCustomTokenBottomSheet.kt @@ -4,12 +4,7 @@ import android.annotation.SuppressLint import androidx.activity.compose.BackHandler import androidx.activity.compose.LocalOnBackPressedDispatcherOwner import androidx.compose.foundation.focusable -import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.WindowInsetsSides -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.only -import androidx.compose.foundation.layout.systemBars +import androidx.compose.foundation.layout.* import androidx.compose.material3.BottomSheetDefaults import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ModalBottomSheet @@ -36,6 +31,7 @@ import androidx.compose.ui.input.key.KeyEventType import androidx.compose.ui.input.key.key import androidx.compose.ui.input.key.onPreviewKeyEvent import androidx.compose.ui.input.key.type +import androidx.compose.ui.platform.LocalDensity import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable @@ -43,7 +39,9 @@ import androidx.navigation.compose.rememberNavController import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetDraggableHeader import com.tangem.core.ui.components.bottomsheets.collapse +import com.tangem.core.ui.res.LocalWindowSize import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.utils.WindowInsetsZero import com.tangem.managetokens.presentation.addcustomtoken.router.AddCustomTokenRoute import com.tangem.managetokens.presentation.addcustomtoken.router.AddCustomTokenRouter import com.tangem.managetokens.presentation.addcustomtoken.viewmodels.AddCustomTokenViewModel @@ -57,6 +55,7 @@ fun AddCustomTokenBottomSheet(config: TangemBottomSheetConfig) { var isVisible by remember { mutableStateOf(value = config.isShow) } val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) + val statusBarHeight = with(LocalDensity.current) { WindowInsets.statusBars.getTop(this).toDp() } if (isVisible) { // ViewModel cannot be scoped to ModalBottomSheet's lifecycle, @@ -67,11 +66,13 @@ fun AddCustomTokenBottomSheet(config: TangemBottomSheetConfig) { } ModalBottomSheetWithBackHandling( + modifier = Modifier + .sizeIn(maxHeight = LocalWindowSize.current.height - statusBarHeight), onDismissRequest = config.onDismissRequest, sheetState = sheetState, containerColor = TangemTheme.colors.background.tertiary, shape = TangemTheme.shapes.bottomSheetLarge, - windowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top), + windowInsets = WindowInsetsZero, dragHandle = { TangemBottomSheetDraggableHeader(color = TangemTheme.colors.background.tertiary) }, properties = ModalBottomSheetDefaults.properties(shouldDismissOnBackPress = false), ) { diff --git a/features/manage-tokens/impl/src/main/java/com/tangem/managetokens/presentation/managetokens/ui/ManageTokensScreen.kt b/features/manage-tokens/impl/src/main/java/com/tangem/managetokens/presentation/managetokens/ui/ManageTokensScreen.kt index 15197a8e4a..6b91d83e18 100644 --- a/features/manage-tokens/impl/src/main/java/com/tangem/managetokens/presentation/managetokens/ui/ManageTokensScreen.kt +++ b/features/manage-tokens/impl/src/main/java/com/tangem/managetokens/presentation/managetokens/ui/ManageTokensScreen.kt @@ -65,7 +65,6 @@ private fun Content(state: ManageTokensState, onHeaderSizeChange: (Dp) -> Unit) Box( modifier = Modifier .fillMaxSize() - .navigationBarsPadding() .imePadding() .background(color = TangemTheme.colors.background.primary), ) { diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/QrScanningFragment.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/QrScanningFragment.kt index 72d725c460..5118630639 100644 --- a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/QrScanningFragment.kt +++ b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/QrScanningFragment.kt @@ -7,21 +7,16 @@ import android.os.Bundle import android.view.View import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.core.content.ContextCompat import androidx.fragment.app.viewModels import androidx.lifecycle.Lifecycle -import androidx.lifecycle.LifecycleEventObserver import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle -import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.google.mlkit.vision.common.InputImage import com.tangem.core.ui.UiDependencies -import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.components.SystemBarsIconsDisposable import com.tangem.core.ui.screen.ComposeFragment import com.tangem.feature.qrscanning.inner.MLKitBarcodeAnalyzer import com.tangem.feature.qrscanning.navigation.QrScanningInnerRouter @@ -105,7 +100,8 @@ internal class QrScanningFragment : ComposeFragment() { @Composable override fun ScreenContent(modifier: Modifier) { - StatusBarTransparencyDisposable() + SystemBarsIconsDisposable(darkIcons = false) + QrScanningContent( executor = { cameraExecutor }, analyzer = { cameraAnalyzer }, @@ -145,29 +141,4 @@ internal class QrScanningFragment : ComposeFragment() { fun create() = QrScanningFragment() } -} - -@Composable -private fun StatusBarTransparencyDisposable() { - val systemUiController = rememberSystemUiController() - val systemBarsColor = TangemTheme.colors.background.secondary - val lifecycleOwner = LocalLifecycleOwner.current - DisposableEffect(Unit) { - val observer = LifecycleEventObserver { _, event -> - if (event == Lifecycle.Event.ON_START) { - systemUiController.setSystemBarsColor( - color = Color.Transparent, - darkIcons = false, - ) - } - if (event == Lifecycle.Event.ON_STOP) { - systemUiController.setSystemBarsColor(systemBarsColor) - } - } - lifecycleOwner.lifecycle.addObserver(observer) - - onDispose { - lifecycleOwner.lifecycle.removeObserver(observer) - } - } } \ No newline at end of file diff --git a/features/referral/presentation/src/main/java/com/tangem/feature/referral/ReferralFragment.kt b/features/referral/presentation/src/main/java/com/tangem/feature/referral/ReferralFragment.kt index 3d157aa005..cec296cc80 100644 --- a/features/referral/presentation/src/main/java/com/tangem/feature/referral/ReferralFragment.kt +++ b/features/referral/presentation/src/main/java/com/tangem/feature/referral/ReferralFragment.kt @@ -1,14 +1,11 @@ package com.tangem.feature.referral import android.os.Bundle -import androidx.compose.foundation.layout.systemBarsPadding import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.fragment.app.viewModels import com.tangem.common.routing.AppRouter 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.feature.referral.router.ReferralRouter import com.tangem.feature.referral.ui.ReferralScreen @@ -35,12 +32,6 @@ class ReferralFragment : ComposeFragment() { @Composable override fun ScreenContent(modifier: Modifier) { - val backgroundColor = TangemTheme.colors.background.secondary - SystemBarsEffect { setSystemBarsColor(backgroundColor) } - - ReferralScreen( - modifier = Modifier.systemBarsPadding(), - stateHolder = viewModel.uiState, - ) + ReferralScreen(stateHolder = viewModel.uiState) } } \ No newline at end of file diff --git a/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/AgreementBottomSheetContent.kt b/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/AgreementBottomSheetContent.kt index e44e192d0d..8d8b5aadfa 100644 --- a/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/AgreementBottomSheetContent.kt +++ b/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/AgreementBottomSheetContent.kt @@ -2,23 +2,20 @@ package com.tangem.feature.referral.ui import android.content.res.Configuration import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.* import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp import com.google.accompanist.web.WebView import com.google.accompanist.web.rememberWebViewState import com.tangem.core.ui.components.appbar.AppBarWithAdditionalButtons -import com.tangem.core.ui.res.TangemThemePreview import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview import com.tangem.feature.referral.presentation.R /** @@ -28,15 +25,16 @@ import com.tangem.feature.referral.presentation.R */ @Composable internal fun AgreementBottomSheetContent(url: String) { + val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() } + Column( modifier = Modifier - .fillMaxWidth() - .height(LocalConfiguration.current.screenHeightDp.dp - TangemTheme.dimens.spacing16), + .fillMaxSize() + .verticalScroll(rememberScrollState()), ) { - Column(modifier = Modifier.verticalScroll(rememberScrollState())) { - AppBarWithAdditionalButtons(text = stringResource(id = R.string.details_referral_title)) - AgreementHtmlView(url = url) - } + AppBarWithAdditionalButtons(text = stringResource(id = R.string.details_referral_title)) + AgreementHtmlView(url = url) + Spacer(modifier = Modifier.height(bottomBarHeight)) } } @@ -46,7 +44,7 @@ private fun AgreementHtmlView(url: String) { val isInPreviewMode = LocalInspectionMode.current WebView( state = state, - modifier = Modifier.background(TangemTheme.colors.background.secondary), + modifier = Modifier.background(TangemTheme.colors.background.primary), captureBackPresses = false, onCreated = { if (!isInPreviewMode) { diff --git a/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/ReferralBottomSheet.kt b/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/ReferralBottomSheet.kt index 2d70513c8a..d91a122117 100644 --- a/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/ReferralBottomSheet.kt +++ b/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/ReferralBottomSheet.kt @@ -1,11 +1,18 @@ package com.tangem.feature.referral.ui +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.SheetState import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalDensity +import com.tangem.core.ui.res.LocalWindowSize import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.utils.WindowInsetsZero import com.tangem.feature.referral.models.ReferralStateHolder @OptIn(ExperimentalMaterial3Api::class) @@ -16,14 +23,18 @@ internal fun ReferralBottomSheet( onDismissRequest: () -> Unit, config: ReferralStateHolder.ReferralInfoState, ) { + val statusBarHeight = with(LocalDensity.current) { WindowInsets.statusBars.getTop(this).toDp() } + if (isVisible) { ModalBottomSheet( + modifier = Modifier.height(LocalWindowSize.current.height - statusBarHeight), onDismissRequest = onDismissRequest, sheetState = sheetState, shape = RoundedCornerShape( topStart = TangemTheme.dimens.radius16, topEnd = TangemTheme.dimens.radius16, ), + windowInsets = WindowInsetsZero, containerColor = TangemTheme.colors.background.primary, ) { AgreementBottomSheetContent( diff --git a/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/ReferralScreen.kt b/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/ReferralScreen.kt index 39b216fb16..7d6614a7aa 100644 --- a/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/ReferralScreen.kt +++ b/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/ReferralScreen.kt @@ -46,16 +46,16 @@ import kotlinx.coroutines.launch */ @OptIn(ExperimentalMaterial3Api::class) @Composable -internal fun ReferralScreen(stateHolder: ReferralStateHolder, modifier: Modifier = Modifier) { +internal fun ReferralScreen(stateHolder: ReferralStateHolder) { var isBottomSheetVisible by remember { mutableStateOf(value = false) } val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) val snackbarHostState = remember(::SnackbarHostState) Scaffold( - modifier = modifier, topBar = { AppBarWithBackButton( + modifier = Modifier.statusBarsPadding(), text = stringResource(R.string.details_referral_title), onBackClick = stateHolder.headerState.onBackClicked, ) diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/SendFragment.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/SendFragment.kt index 0a3b32c382..231c029e8f 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/SendFragment.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/SendFragment.kt @@ -9,8 +9,6 @@ import com.tangem.common.routing.AppRoute import com.tangem.common.routing.AppRouter import com.tangem.core.analytics.api.AnalyticsEventHandler 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.features.send.api.navigation.SendRouter import com.tangem.features.send.impl.navigation.InnerSendRouter @@ -61,10 +59,6 @@ internal class SendFragment : ComposeFragment() { @Composable override fun ScreenContent(modifier: Modifier) { - val systemBarsColor = TangemTheme.colors.background.tertiary - SystemBarsEffect { - setSystemBarsColor(systemBarsColor) - } val currentState = viewModel.stateRouter.currentState.collectAsStateWithLifecycle() SendScreen(viewModel.uiState, currentState.value) } diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendScreen.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendScreen.kt index cdef0b59c6..b05b60afe0 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendScreen.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendScreen.kt @@ -46,10 +46,10 @@ internal fun SendScreen(uiState: SendUiState, currentState: SendUiCurrentScreen) BackHandler(onBack = onBackClick) Column( modifier = Modifier + .background(color = TangemTheme.colors.background.tertiary) .fillMaxSize() .imePadding() - .systemBarsPadding() - .background(color = TangemTheme.colors.background.tertiary), + .systemBarsPadding(), horizontalAlignment = Alignment.CenterHorizontally, ) { SendAppBar( diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/StakingFragment.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/StakingFragment.kt index 9648e0164d..64b167ead5 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/StakingFragment.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/StakingFragment.kt @@ -7,8 +7,6 @@ import androidx.fragment.app.viewModels import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.tangem.core.analytics.api.AnalyticsEventHandler 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.features.staking.api.navigation.StakingRouter import com.tangem.features.staking.impl.navigation.InnerStakingRouter @@ -59,10 +57,6 @@ internal class StakingFragment : ComposeFragment() { @Composable override fun ScreenContent(modifier: Modifier) { - val systemBarsColor = TangemTheme.colors.background.tertiary - SystemBarsEffect { - setSystemBarsColor(systemBarsColor) - } val currentState = viewModel.uiState.collectAsStateWithLifecycle() StakingScreen(currentState.value) } diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingScreen.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingScreen.kt index ec18cf17e0..51be837ffe 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingScreen.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingScreen.kt @@ -28,10 +28,10 @@ internal fun StakingScreen(uiState: StakingUiState) { BackHandler(onBack = uiState.clickIntents::onBackClick) Column( modifier = Modifier + .background(color = TangemTheme.colors.background.tertiary) .fillMaxSize() .imePadding() - .systemBarsPadding() - .background(color = TangemTheme.colors.background.tertiary), + .systemBarsPadding(), horizontalAlignment = Alignment.CenterHorizontally, ) { SendAppBar( diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/presentation/SwapFragment.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/presentation/SwapFragment.kt index 51ac5b23a2..60df4a856b 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/presentation/SwapFragment.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/presentation/SwapFragment.kt @@ -2,13 +2,13 @@ package com.tangem.feature.swap.presentation import android.os.Bundle import androidx.compose.animation.Crossfade +import androidx.compose.foundation.background import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.fragment.app.viewModels import com.tangem.common.routing.AppRouter 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.feature.swap.router.CustomTabsManager @@ -47,17 +47,17 @@ class SwapFragment : ComposeFragment() { @Composable override fun ScreenContent(modifier: Modifier) { viewModel.onScreenOpened() - - val backgroundColor = TangemTheme.colors.background.secondary - SystemBarsEffect { setSystemBarsColor(backgroundColor) } - ScreenContent(viewModel = viewModel) } @Suppress("TopLevelComposableFunctions") @Composable private fun ScreenContent(viewModel: SwapViewModel) { - Crossfade(targetState = viewModel.currentScreen, label = "") { screen -> + Crossfade( + modifier = Modifier.background(TangemTheme.colors.background.secondary), + targetState = viewModel.currentScreen, + label = "", + ) { screen -> when (screen) { SwapNavScreen.Main -> SwapScreen(stateHolder = viewModel.uiState) SwapNavScreen.Success -> { diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreen.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreen.kt index 04a53a581c..ff34b02557 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreen.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreen.kt @@ -8,6 +8,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import com.tangem.core.ui.components.appbar.AppBarWithBackButton import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.utils.WindowInsetsZero import com.tangem.feature.swap.models.SwapStateHolder import com.tangem.feature.swap.models.states.ChooseFeeBottomSheetConfig import com.tangem.feature.swap.models.states.ChooseProviderBottomSheetConfig @@ -28,7 +29,7 @@ internal fun SwapScreen(stateHolder: SwapStateHolder) { iconRes = R.drawable.ic_close_24, ) }, - contentWindowInsets = WindowInsets(left = 0, top = 0, right = 0, bottom = 0), + contentWindowInsets = WindowInsetsZero, containerColor = TangemTheme.colors.background.secondary, ) { scaffoldPaddings -> diff --git a/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/TesterActivity.kt b/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/TesterActivity.kt index c94208933f..62206ea5e5 100644 --- a/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/TesterActivity.kt +++ b/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/TesterActivity.kt @@ -6,9 +6,9 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController +import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.tangem.core.navigation.finisher.AppFinisher 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.ComposeActivity import com.tangem.feature.tester.presentation.actions.TesterActionsScreen @@ -45,9 +45,8 @@ internal class TesterActivity : ComposeActivity() { @Composable override fun ScreenContent(modifier: Modifier) { val systemBarsColor = TangemTheme.colors.background.secondary - SystemBarsEffect { - setSystemBarsColor(systemBarsColor) - } + val systemUiController = rememberSystemUiController() + systemUiController.setSystemBarsColor(systemBarsColor) TesterNavHost() } diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/TokenDetailsFragment.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/TokenDetailsFragment.kt index 94200fbd59..bbbe520ddf 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/TokenDetailsFragment.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/TokenDetailsFragment.kt @@ -5,8 +5,7 @@ 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.components.NavigationBar3ButtonsScrim import com.tangem.core.ui.screen.ComposeFragment import com.tangem.feature.tokendetails.presentation.router.InnerTokenDetailsRouter import com.tangem.feature.tokendetails.presentation.tokendetails.ui.TokenDetailsScreen @@ -33,14 +32,8 @@ internal class TokenDetailsFragment : ComposeFragment() { override fun ScreenContent(modifier: Modifier) { val viewModel = hiltViewModel() viewModel.router = this@TokenDetailsFragment.internalTokenDetailsRouter - LocalLifecycleOwner.current.lifecycle.addObserver(viewModel) - - val systemBarsColor = TangemTheme.colors.background.secondary - SystemBarsEffect { - setSystemBarsColor(systemBarsColor) - } - + NavigationBar3ButtonsScrim() TokenDetailsScreen(state = viewModel.uiState) } } \ No newline at end of file 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 ddcb006eae..e4574897ac 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 @@ -3,10 +3,7 @@ package com.tangem.feature.tokendetails.presentation.tokendetails.ui import android.content.res.Configuration import androidx.activity.compose.BackHandler import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material.ExperimentalMaterialApi @@ -14,6 +11,7 @@ import androidx.compose.material.pullrefresh.PullRefreshIndicator import androidx.compose.material.pullrefresh.pullRefresh import androidx.compose.material.pullrefresh.rememberPullRefreshState import androidx.compose.material3.Scaffold +import androidx.compose.material3.ScaffoldDefaults import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable @@ -21,6 +19,7 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +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 @@ -60,11 +59,13 @@ import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.e @Composable internal fun TokenDetailsScreen(state: TokenDetailsState) { BackHandler(onBack = state.topAppBarConfig.onBackClick) + val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() } val snackbarHostState = remember { SnackbarHostState() } Scaffold( topBar = { TokenDetailsTopAppBar(config = state.topAppBarConfig) }, snackbarHost = { SnackbarHost(hostState = snackbarHostState) }, + contentWindowInsets = ScaffoldDefaults.contentWindowInsets.exclude(WindowInsets.navigationBars), containerColor = TangemTheme.colors.background.secondary, ) { scaffoldPaddings -> val pullRefreshState = rememberPullRefreshState( @@ -90,7 +91,9 @@ internal fun TokenDetailsScreen(state: TokenDetailsState) { ) { LazyColumn( modifier = Modifier.fillMaxSize(), - contentPadding = PaddingValues(bottom = TangemTheme.dimens.spacing16), + contentPadding = PaddingValues( + bottom = TangemTheme.dimens.spacing16 + bottomBarHeight, + ), ) { item { TokenInfoBlock( diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/WalletFragment.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/WalletFragment.kt index 5a2c923015..6535806903 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/WalletFragment.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/WalletFragment.kt @@ -3,8 +3,6 @@ package com.tangem.feature.wallet.presentation import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier 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.feature.wallet.presentation.router.InnerWalletRouter import com.tangem.features.managetokens.navigation.ManageTokensUi @@ -37,11 +35,6 @@ internal class WalletFragment : ComposeFragment() { @Composable override fun ScreenContent(modifier: Modifier) { - val systemBarsColor = TangemTheme.colors.background.secondary - SystemBarsEffect { - setSystemBarsColor(systemBarsColor) - } - _walletRouter.Initialize( onFinish = requireActivity()::finish, manageTokensUi = manageTokensUi, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensScreen.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensScreen.kt index 4efcf827cb..6c3aea984f 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensScreen.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensScreen.kt @@ -16,11 +16,10 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.composed import androidx.compose.ui.draw.shadow -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.graphics.Shape import androidx.compose.ui.hapticfeedback.HapticFeedbackType +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview @@ -28,6 +27,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +import com.tangem.core.ui.components.BottomFade import com.tangem.core.ui.components.PrimaryButton import com.tangem.core.ui.components.SecondaryButton import com.tangem.core.ui.components.buttons.actions.ActionButtonConfig @@ -36,6 +36,7 @@ import com.tangem.core.ui.event.EventEffect import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.core.ui.utils.WindowInsetsZero import com.tangem.feature.wallet.impl.R import com.tangem.feature.wallet.presentation.common.WalletPreviewData import com.tangem.feature.wallet.presentation.common.component.DraggableNetworkGroupItem @@ -57,8 +58,12 @@ internal fun OrganizeTokensScreen(state: OrganizeTokensState, modifier: Modifier Scaffold( modifier = modifier, topBar = { - TopBar(state.header, tokensListState) + TopBar( + config = state.header, + tokensListState = tokensListState, + ) }, + contentWindowInsets = WindowInsetsZero, content = { paddingValues -> TokenList( modifier = Modifier @@ -72,7 +77,9 @@ internal fun OrganizeTokensScreen(state: OrganizeTokensState, modifier: Modifier }, floatingActionButtonPosition = FabPosition.Center, floatingActionButton = { - Actions(state.actions) + Box(modifier = Modifier.navigationBarsPadding()) { + Actions(state.actions) + } }, containerColor = TangemTheme.colors.background.secondary, ) @@ -104,9 +111,11 @@ private fun TokenList( onDragEnd = onDragEnd, ) + val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() } + val listContentPadding = PaddingValues( top = TangemTheme.dimens.spacing4, - bottom = TangemTheme.dimens.spacing92, + bottom = TangemTheme.dimens.spacing92 + bottomBarHeight, start = TangemTheme.dimens.spacing16, end = TangemTheme.dimens.spacing16, ) @@ -140,7 +149,7 @@ private fun TokenList( } } - BottomGradient(modifier = Modifier.align(Alignment.BottomCenter)) + BottomFade(modifier = Modifier.align(Alignment.BottomCenter)) } } @@ -191,23 +200,6 @@ private fun LazyItemScope.DraggableItem( } } -@Composable -private fun BottomGradient(modifier: Modifier = Modifier) { - Box( - modifier = modifier - .fillMaxWidth() - .height(TangemTheme.dimens.size116) - .background( - brush = Brush.verticalGradient( - colors = listOf( - Color.Transparent, - TangemTheme.colors.background.secondary, - ), - ), - ), - ) -} - @Composable private fun TopBar( config: OrganizeTokensState.HeaderConfig, @@ -228,6 +220,7 @@ private fun TopBar( modifier = modifier .shadow(elevation) .background(TangemTheme.colors.background.secondary) + .statusBarsPadding() .padding(horizontal = TangemTheme.dimens.spacing16) .fillMaxWidth(), ) { diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt index 69906449ee..292cea1bde 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt @@ -1,9 +1,7 @@ package com.tangem.feature.wallet.presentation.router import android.annotation.SuppressLint -import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.runtime.* -import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.unit.dp import androidx.fragment.app.Fragment @@ -86,7 +84,6 @@ internal class DefaultWalletRouter( val uiState by viewModel.uiState.collectAsStateWithLifecycle() OrganizeTokensScreen( - modifier = Modifier.statusBarsPadding(), state = uiState, ) } 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 eccfc5ea55..3dde33fa2b 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 @@ -20,6 +20,7 @@ import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.luminance import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalSoftwareKeyboardController @@ -33,16 +34,13 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.paging.compose.collectAsLazyPagingItems import com.google.accompanist.systemuicontroller.rememberSystemUiController -import com.tangem.core.ui.components.Keyboard -import com.tangem.core.ui.components.PrimaryButton -import com.tangem.core.ui.components.SystemBarsEffect +import com.tangem.core.ui.components.* import com.tangem.core.ui.components.atoms.Hand import com.tangem.core.ui.components.atoms.handComposableComponentHeight import com.tangem.core.ui.components.bottomsheets.chooseaddress.ChooseAddressBottomSheet import com.tangem.core.ui.components.bottomsheets.chooseaddress.ChooseAddressBottomSheetConfig import com.tangem.core.ui.components.bottomsheets.tokenreceive.TokenReceiveBottomSheet import com.tangem.core.ui.components.bottomsheets.tokenreceive.TokenReceiveBottomSheetConfig -import com.tangem.core.ui.components.keyboardAsState import com.tangem.core.ui.components.snackbar.CopiedTextSnackbar import com.tangem.core.ui.components.snackbar.TangemSnackbar import com.tangem.core.ui.components.transactions.state.TxHistoryState @@ -50,6 +48,7 @@ import com.tangem.core.ui.event.StateEvent import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview import com.tangem.core.ui.test.TestTags +import com.tangem.core.ui.utils.WindowInsetsZero import com.tangem.feature.wallet.impl.R import com.tangem.feature.wallet.presentation.common.preview.WalletScreenPreviewData.walletScreenState import com.tangem.feature.wallet.presentation.wallet.state.model.* @@ -112,7 +111,7 @@ internal fun WalletScreen( ) } -@Suppress("LongMethod", "LongParameterList") +@Suppress("LongMethod", "LongParameterList", "CyclomaticComplexMethod") @Composable private fun WalletContent( state: WalletScreenState, @@ -144,12 +143,14 @@ private fun WalletContent( .padding(top = betweenItemsPadding) .padding(horizontal = horizontalPadding) + val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() } + LazyColumn( modifier = Modifier .fillMaxSize() .testTag(TestTags.WALLET_SCREEN), contentPadding = PaddingValues( - bottom = TangemTheme.dimens.spacing92, + bottom = TangemTheme.dimens.spacing92 + bottomBarHeight, ), horizontalAlignment = Alignment.CenterHorizontally, ) { @@ -330,7 +331,7 @@ private fun BaseScaffoldManageTokenRedesign( coroutineScope.launch { bottomSheetState.partialExpand() } } }, - content = { paddingValues -> + content = { _ -> val pullRefreshState = rememberPullRefreshState( refreshing = selectedWallet.pullToRefreshConfig.isRefreshing, onRefresh = { @@ -338,9 +339,7 @@ private fun BaseScaffoldManageTokenRedesign( }, ) - Column( - modifier = Modifier.padding(paddingValues), - ) { + Column { WalletTopBar(config = state.topBarConfig) Box( modifier = Modifier.pullRefresh(pullRefreshState), @@ -392,7 +391,7 @@ private fun BottomSheetScrim(color: Color, visible: Boolean, onDismissRequest: ( } @OptIn(ExperimentalMaterial3Api::class) -@Suppress("CyclomaticComplexMethod") +@Suppress("CyclomaticComplexMethod", "MagicNumber") @Composable private fun BottomSheetStateEffects( bottomSheetState: SheetState, @@ -425,19 +424,29 @@ private fun BottomSheetStateEffects( val systemUiController = rememberSystemUiController() val navigationBarColor = TangemTheme.colors.background.primary - val navigationBarColorWithout = TangemTheme.colors.background.secondary - SystemBarsEffect { - if (showManageTokensBottomSheet) { - setNavigationBarColor(navigationBarColor) + LaunchedEffect(key1 = bottomSheetState.targetValue, navigationBarColor) { + when (bottomSheetState.targetValue) { + SheetValue.Hidden, + SheetValue.Expanded, + -> systemUiController.setNavigationBarColor( + color = Color.Transparent, + darkIcons = navigationBarColor.luminance() > 0.5f, + navigationBarContrastEnforced = true, + ) + SheetValue.PartiallyExpanded, + -> systemUiController.setNavigationBarColor(navigationBarColor) } } - DisposableEffect( - showManageTokensBottomSheet, - ) { + + DisposableEffect(showManageTokensBottomSheet) { onDispose { if (showManageTokensBottomSheet) { - systemUiController.setNavigationBarColor(navigationBarColorWithout) + systemUiController.setNavigationBarColor( + color = Color.Transparent, + darkIcons = navigationBarColor.luminance() > 0.5f, + navigationBarContrastEnforced = false, + ) } } } @@ -506,6 +515,7 @@ private fun BaseScaffold( ) { Scaffold( topBar = { WalletTopBar(config = state.topBarConfig) }, + contentWindowInsets = WindowInsetsZero, snackbarHost = { WalletSnackbarHost( snackbarHostState = snackbarHostState, @@ -520,7 +530,12 @@ private fun BaseScaffold( ) } - manageTokensButtonConfig?.let { ManageTokensButton(onClick = it.onClick) } + manageTokensButtonConfig?.let { + ManageTokensButton( + modifier = Modifier.navigationBarsPadding(), + onClick = it.onClick, + ) + } }, floatingActionButtonPosition = FabPosition.Center, containerColor = TangemTheme.colors.background.secondary, @@ -544,6 +559,8 @@ private fun BaseScaffold( state = pullRefreshState, modifier = Modifier.align(Alignment.TopCenter), ) + + BottomFade(Modifier.align(Alignment.BottomCenter)) } }, ) @@ -565,11 +582,11 @@ private fun WalletSnackbarHost( } @Composable -private fun ManageTokensButton(onClick: () -> Unit) { +private fun ManageTokensButton(onClick: () -> Unit, modifier: Modifier = Modifier) { PrimaryButton( text = stringResource(id = R.string.main_manage_tokens), onClick = onClick, - modifier = Modifier + modifier = modifier .fillMaxWidth() .padding(horizontal = TangemTheme.dimens.spacing16), )