Updated on 2026-08-14

This commit is contained in:
Tangem 2024-06-17 16:42:57 +03:00
parent 7a5933253b
commit 2f5ed09224
41 changed files with 414 additions and 320 deletions

View file

@ -12,15 +12,18 @@ import android.nfc.NfcAdapter
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.activity.SystemBarStyle
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import androidx.appcompat.app.AppCompatDelegate.setDefaultNightMode 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.app.ActivityCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.view.WindowCompat
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.flowWithLifecycle import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope 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 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) super.onCreate(savedInstanceState)
splashScreen.setKeepOnScreenCondition { viewModel.isSplashScreenShown } splashScreen.setKeepOnScreenCondition { viewModel.isSplashScreenShown }
@ -307,8 +317,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
@SuppressLint("SourceLockedOrientationActivity") @SuppressLint("SourceLockedOrientationActivity")
private fun initContent() { private fun initContent() {
WindowCompat.setDecorFitsSystemWindows(window, false)
supportFragmentManager.registerFragmentLifecycleCallbacks( supportFragmentManager.registerFragmentLifecycleCallbacks(
NavBarInsetsFragmentLifecycleCallback(), NavBarInsetsFragmentLifecycleCallback(),
true, true,

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -6,14 +6,12 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.core.view.WindowCompat
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.tangem.common.routing.AppRoute import com.tangem.common.routing.AppRoute
import com.tangem.core.analytics.Analytics import com.tangem.core.analytics.Analytics
import com.tangem.core.ui.UiDependencies 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.core.ui.screen.ComposeFragment
import com.tangem.domain.tokens.TokensAction import com.tangem.domain.tokens.TokensAction
import com.tangem.tap.common.analytics.events.IntroductionProcess import com.tangem.tap.common.analytics.events.IntroductionProcess
@ -44,15 +42,12 @@ class HomeFragment : ComposeFragment(), StoreSubscriber<HomeState> {
@Composable @Composable
override fun ScreenContent(modifier: Modifier) { override fun ScreenContent(modifier: Modifier) {
BackHandler(onBack = requireActivity()::finish) BackHandler(onBack = requireActivity()::finish)
SystemBarsEffect { SystemBarsIconsDisposable(darkIcons = false)
setSystemBarsColor(color = Color.Transparent, darkIcons = false)
}
ScreenContent() ScreenContent()
} }
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
activity?.window?.let { WindowCompat.setDecorFitsSystemWindows(it, false) }
store.subscribe(subscriber = this) { state -> store.subscribe(subscriber = this) { state ->
state state

View file

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

View file

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

View file

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

View file

@ -16,7 +16,6 @@ import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tangem.core.analytics.Analytics import com.tangem.core.analytics.Analytics
import com.tangem.core.ui.UiDependencies 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.res.TangemTheme
import com.tangem.core.ui.screen.ComposeFragment import com.tangem.core.ui.screen.ComposeFragment
import com.tangem.tap.common.analytics.events.SignIn 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 errorMessage by rememberUpdatedState(newValue = state.error?.resolveReference())
val warning by rememberUpdatedState(newValue = state.warning) val warning by rememberUpdatedState(newValue = state.warning)
val backgroundColor = TangemTheme.colors.background.primary
SystemBarsEffect {
setSystemBarsColor(backgroundColor)
}
BackHandler { BackHandler {
requireActivity().finish() requireActivity().finish()
} }
Box( Box(
modifier = modifier modifier = modifier
.systemBarsPadding() .background(TangemTheme.colors.background.primary)
.background(backgroundColor), .systemBarsPadding(),
) { ) {
WelcomeScreenContent( WelcomeScreenContent(
showUnlockProgress = state.showUnlockWithBiometricsProgress, showUnlockProgress = state.showUnlockWithBiometricsProgress,

View file

@ -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,
),
),
),
)
}

View file

@ -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) }
}

View file

@ -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
}
}
}

View file

@ -1,13 +1,14 @@
package com.tangem.core.ui.components.bottomsheets package com.tangem.core.ui.components.bottomsheets
import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.*
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.*
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.SheetState
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color 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.res.TangemTheme
import com.tangem.core.ui.utils.WindowInsetsZero
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -15,6 +16,7 @@ import kotlinx.coroutines.launch
* Tangem bottom sheet with custom draggable header and config * Tangem bottom sheet with custom draggable header and config
* *
* @param config data model containing logic and ui models * @param config data model containing logic and ui models
* @param
* @param content custom bottom sheet content * @param content custom bottom sheet content
*/ */
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@ -22,20 +24,33 @@ import kotlinx.coroutines.launch
inline fun <reified T : TangemBottomSheetConfigContent> TangemBottomSheet( inline fun <reified T : TangemBottomSheetConfigContent> TangemBottomSheet(
config: TangemBottomSheetConfig, config: TangemBottomSheetConfig,
containerColor: Color = TangemTheme.colors.background.primary, containerColor: Color = TangemTheme.colors.background.primary,
addBottomInsets: Boolean = true,
crossinline content: @Composable ColumnScope.(T) -> Unit, crossinline content: @Composable ColumnScope.(T) -> Unit,
) { ) {
var isVisible by remember { mutableStateOf(value = config.isShow) } var isVisible by remember { mutableStateOf(value = config.isShow) }
val statusBarHeight = with(LocalDensity.current) { WindowInsets.statusBars.getTop(this).toDp() }
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
if (isVisible && config.content is T) { if (isVisible && config.content is T) {
ModalBottomSheet( ModalBottomSheet(
// FIXME temporary solution to fix height of the bottom sheet
modifier = Modifier.sizeIn(maxHeight = LocalWindowSize.current.height - statusBarHeight),
onDismissRequest = config.onDismissRequest, onDismissRequest = config.onDismissRequest,
sheetState = sheetState, sheetState = sheetState,
containerColor = containerColor, containerColor = containerColor,
shape = TangemTheme.shapes.bottomSheetLarge, shape = TangemTheme.shapes.bottomSheetLarge,
windowInsets = WindowInsetsZero,
dragHandle = { TangemBottomSheetDraggableHeader(color = containerColor) }, 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)
}
} }
} }

View file

@ -81,6 +81,7 @@ data class TangemDimens internal constructor(
val size90: Dp = 90.dp, val size90: Dp = 90.dp,
val size93: Dp = 93.dp, val size93: Dp = 93.dp,
val size96: Dp = 96.dp, val size96: Dp = 96.dp,
val size100: Dp = 100.dp,
val size102: Dp = 102.dp, val size102: Dp = 102.dp,
val size108: Dp = 108.dp, val size108: Dp = 108.dp,
val size110: Dp = 110.dp, val size110: Dp = 110.dp,

View file

@ -5,9 +5,10 @@ import androidx.compose.material.MaterialTheme
import androidx.compose.material.ProvideTextStyle import androidx.compose.material.ProvideTextStyle
import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.* 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.HapticManager
import com.tangem.core.ui.haptic.MockHapticManager import com.tangem.core.ui.haptic.MockHapticManager
import com.tangem.core.ui.windowsize.WindowSize import com.tangem.core.ui.windowsize.WindowSize
@Composable @Composable
@ -25,6 +26,16 @@ fun TangemTheme(
.also { it.update(themeColors) } .also { it.update(themeColors) }
val shapes = remember { TangemShapes(dimens) } val shapes = remember { TangemShapes(dimens) }
val systemUiController = rememberSystemUiController()
SideEffect {
systemUiController.setSystemBarsColor(
color = Color.Transparent,
darkIcons = !isDark,
isNavigationBarContrastEnforced = false,
)
}
MaterialTheme( MaterialTheme(
colors = materialThemeColors(colors = themeColors, isDark = isDark), colors = materialThemeColors(colors = themeColors, isDark = isDark),
) { ) {

View file

@ -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
}

View file

@ -19,7 +19,6 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.ComposableContentComponent 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.components.snackbar.TangemSnackbarHost
import com.tangem.core.ui.res.LocalSnackbarHostState import com.tangem.core.ui.res.LocalSnackbarHostState
import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemTheme
@ -42,10 +41,6 @@ internal fun DetailsScreen(
val backgroundColor = TangemTheme.colors.background.secondary val backgroundColor = TangemTheme.colors.background.secondary
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior() val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
SystemBarsEffect {
setSystemBarsColor(backgroundColor)
}
BackHandler(onBack = state.popBack) BackHandler(onBack = state.popBack)
Scaffold( Scaffold(

View file

@ -7,8 +7,6 @@ import androidx.compose.ui.Modifier
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import com.tangem.common.routing.AppRouter import com.tangem.common.routing.AppRouter
import com.tangem.core.ui.UiDependencies 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.core.ui.screen.ComposeFragment
import com.tangem.features.disclaimer.api.DisclaimerRouter import com.tangem.features.disclaimer.api.DisclaimerRouter
import com.tangem.features.disclaimer.impl.presentation.ui.DisclaimerScreen import com.tangem.features.disclaimer.impl.presentation.ui.DisclaimerScreen
@ -37,7 +35,6 @@ internal class DisclaimerFragment : ComposeFragment() {
@Composable @Composable
override fun ScreenContent(modifier: Modifier) { override fun ScreenContent(modifier: Modifier) {
val systemBarsColor = TangemTheme.colors.background.primary
BackHandler { BackHandler {
if (isTosAccepted) { if (isTosAccepted) {
appRouter.pop() appRouter.pop()
@ -45,9 +42,6 @@ internal class DisclaimerFragment : ComposeFragment() {
requireActivity().finish() requireActivity().finish()
} }
} }
SystemBarsEffect {
setSystemBarsColor(systemBarsColor)
}
DisclaimerScreen(viewModel.state, appRouter::pop) DisclaimerScreen(viewModel.state, appRouter::pop)
} }

View file

@ -15,17 +15,16 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier 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.graphics.toArgb
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView import androidx.compose.ui.viewinterop.AndroidView
import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.isGranted import com.google.accompanist.permissions.isGranted
import com.google.accompanist.permissions.rememberPermissionState 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.PrimaryButton
import com.tangem.core.ui.components.appbar.AppBarWithAdditionalButtons import com.tangem.core.ui.components.appbar.AppBarWithAdditionalButtons
import com.tangem.core.ui.components.appbar.models.AdditionalButton import com.tangem.core.ui.components.appbar.models.AdditionalButton
@ -39,17 +38,14 @@ import com.tangem.features.disclaimer.impl.presentation.state.DummyDisclaimer
@Composable @Composable
internal fun DisclaimerScreen(state: DisclaimerState, onBackClick: () -> Unit) { 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( Box(
modifier = Modifier modifier = Modifier
.statusBarsPadding() .background(TangemColorPalette.Dark6)
.background(TangemColorPalette.Dark6), .statusBarsPadding(),
) { ) {
Column( Column {
modifier = Modifier
.navigationBarsPadding()
.padding(bottom = bottomPadding),
) {
AppBarWithAdditionalButtons( AppBarWithAdditionalButtons(
text = resourceReference(R.string.disclaimer_title), text = resourceReference(R.string.disclaimer_title),
startButton = AdditionalButton( startButton = AdditionalButton(
@ -58,23 +54,34 @@ internal fun DisclaimerScreen(state: DisclaimerState, onBackClick: () -> Unit) {
).takeIf { state.isTosAccepted }, ).takeIf { state.isTosAccepted },
) )
DisclaimerContent(state.url) DisclaimerContent(state.url)
Spacer(
modifier = Modifier
.background(TangemColorPalette.Dark6)
.height(
height = if (!state.isTosAccepted) {
bottomBarHeight
} else {
bottomBarHeight + TangemTheme.dimens.size64
},
),
)
} }
if (!state.isTosAccepted) { if (!state.isTosAccepted) {
BottomFade(Modifier.align(Alignment.BottomCenter), backgroundColor = TangemColorPalette.Dark6)
DisclaimerButton(state.onAccept) DisclaimerButton(state.onAccept)
} else {
NavigationBar3ButtonsScrim()
} }
} }
} }
@Composable @Composable
private fun ColumnScope.DisclaimerContent(url: String) { private fun ColumnScope.DisclaimerContent(url: String) {
val transparent = Color.Transparent
val progressState = remember { mutableStateOf(ProgressState.Loading) } val progressState = remember { mutableStateOf(ProgressState.Loading) }
val webClient = remember { DisclaimerWebViewClient(progressState) } val webClient = remember { DisclaimerWebViewClient(progressState) }
Box( Box(
modifier = Modifier modifier = Modifier,
.fillMaxWidth()
.weight(1f),
) { ) {
AndroidView( AndroidView(
factory = { factory = {
@ -83,9 +90,10 @@ private fun ColumnScope.DisclaimerContent(url: String) {
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
) )
setBackgroundColor(transparent.toArgb()) setBackgroundColor(TangemColorPalette.Dark6.toArgb())
settings.allowFileAccess = false settings.allowFileAccess = false
settings.javaScriptEnabled = false settings.javaScriptEnabled = false
overScrollMode = View.OVER_SCROLL_NEVER overScrollMode = View.OVER_SCROLL_NEVER
webViewClient = webClient webViewClient = webClient
loadUrl(url) loadUrl(url)
@ -94,28 +102,34 @@ private fun ColumnScope.DisclaimerContent(url: String) {
) )
when (progressState.value) { when (progressState.value) {
ProgressState.Loading -> CircularProgressIndicator( ProgressState.Loading -> {
color = TangemTheme.colors.icon.informative, Box(modifier = Modifier.fillMaxSize()) {
modifier = Modifier CircularProgressIndicator(
.align(Alignment.Center) color = TangemTheme.colors.icon.informative,
.padding(TangemTheme.dimens.spacing8), modifier = Modifier
) .align(Alignment.Center)
ProgressState.Error -> Column( .padding(TangemTheme.dimens.spacing8),
verticalArrangement = Arrangement.Center, )
modifier = Modifier }
.fillMaxWidth() }
.padding(TangemTheme.dimens.spacing16) ProgressState.Error -> Box(modifier = Modifier.fillMaxSize()) {
.align(Alignment.Center), Column(
) { verticalArrangement = Arrangement.Center,
Text( modifier = Modifier
text = stringResource(id = R.string.disclaimer_error_loading), .fillMaxWidth()
style = TangemTheme.typography.body1, .padding(TangemTheme.dimens.spacing16)
color = TangemTheme.colors.text.constantWhite, .align(Alignment.Center),
) ) {
PrimaryButton( Text(
text = stringResource(R.string.common_retry), text = stringResource(id = R.string.disclaimer_error_loading),
onClick = { webClient.reset() }, style = TangemTheme.typography.body1,
) color = TangemTheme.colors.text.constantWhite,
)
PrimaryButton(
text = stringResource(R.string.common_retry),
onClick = { webClient.reset() },
)
}
} }
else -> Unit else -> Unit
} }
@ -130,23 +144,6 @@ private fun BoxScope.DisclaimerButton(onAccept: (Boolean) -> Unit) {
} else { } else {
true 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( PrimaryButton(
text = stringResource(id = R.string.common_accept), text = stringResource(id = R.string.common_accept),
onClick = { onAccept(shouldAskPushPermission) }, onClick = { onAccept(shouldAskPushPermission) },

View file

@ -4,12 +4,7 @@ import android.annotation.SuppressLint
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
import androidx.activity.compose.LocalOnBackPressedDispatcherOwner import androidx.activity.compose.LocalOnBackPressedDispatcherOwner
import androidx.compose.foundation.focusable import androidx.compose.foundation.focusable
import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.*
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.material3.BottomSheetDefaults import androidx.compose.material3.BottomSheetDefaults
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ModalBottomSheet 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.key
import androidx.compose.ui.input.key.onPreviewKeyEvent import androidx.compose.ui.input.key.onPreviewKeyEvent
import androidx.compose.ui.input.key.type import androidx.compose.ui.input.key.type
import androidx.compose.ui.platform.LocalDensity
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable 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.TangemBottomSheetConfig
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetDraggableHeader import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetDraggableHeader
import com.tangem.core.ui.components.bottomsheets.collapse 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.res.TangemTheme
import com.tangem.core.ui.utils.WindowInsetsZero
import com.tangem.managetokens.presentation.addcustomtoken.router.AddCustomTokenRoute import com.tangem.managetokens.presentation.addcustomtoken.router.AddCustomTokenRoute
import com.tangem.managetokens.presentation.addcustomtoken.router.AddCustomTokenRouter import com.tangem.managetokens.presentation.addcustomtoken.router.AddCustomTokenRouter
import com.tangem.managetokens.presentation.addcustomtoken.viewmodels.AddCustomTokenViewModel import com.tangem.managetokens.presentation.addcustomtoken.viewmodels.AddCustomTokenViewModel
@ -57,6 +55,7 @@ fun AddCustomTokenBottomSheet(config: TangemBottomSheetConfig) {
var isVisible by remember { mutableStateOf(value = config.isShow) } var isVisible by remember { mutableStateOf(value = config.isShow) }
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
val statusBarHeight = with(LocalDensity.current) { WindowInsets.statusBars.getTop(this).toDp() }
if (isVisible) { if (isVisible) {
// ViewModel cannot be scoped to ModalBottomSheet's lifecycle, // ViewModel cannot be scoped to ModalBottomSheet's lifecycle,
@ -67,11 +66,13 @@ fun AddCustomTokenBottomSheet(config: TangemBottomSheetConfig) {
} }
ModalBottomSheetWithBackHandling( ModalBottomSheetWithBackHandling(
modifier = Modifier
.sizeIn(maxHeight = LocalWindowSize.current.height - statusBarHeight),
onDismissRequest = config.onDismissRequest, onDismissRequest = config.onDismissRequest,
sheetState = sheetState, sheetState = sheetState,
containerColor = TangemTheme.colors.background.tertiary, containerColor = TangemTheme.colors.background.tertiary,
shape = TangemTheme.shapes.bottomSheetLarge, shape = TangemTheme.shapes.bottomSheetLarge,
windowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top), windowInsets = WindowInsetsZero,
dragHandle = { TangemBottomSheetDraggableHeader(color = TangemTheme.colors.background.tertiary) }, dragHandle = { TangemBottomSheetDraggableHeader(color = TangemTheme.colors.background.tertiary) },
properties = ModalBottomSheetDefaults.properties(shouldDismissOnBackPress = false), properties = ModalBottomSheetDefaults.properties(shouldDismissOnBackPress = false),
) { ) {

View file

@ -65,7 +65,6 @@ private fun Content(state: ManageTokensState, onHeaderSizeChange: (Dp) -> Unit)
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.navigationBarsPadding()
.imePadding() .imePadding()
.background(color = TangemTheme.colors.background.primary), .background(color = TangemTheme.colors.background.primary),
) { ) {

View file

@ -7,21 +7,16 @@ import android.os.Bundle
import android.view.View import android.view.View
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.repeatOnLifecycle
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.google.mlkit.vision.common.InputImage import com.google.mlkit.vision.common.InputImage
import com.tangem.core.ui.UiDependencies 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.core.ui.screen.ComposeFragment
import com.tangem.feature.qrscanning.inner.MLKitBarcodeAnalyzer import com.tangem.feature.qrscanning.inner.MLKitBarcodeAnalyzer
import com.tangem.feature.qrscanning.navigation.QrScanningInnerRouter import com.tangem.feature.qrscanning.navigation.QrScanningInnerRouter
@ -105,7 +100,8 @@ internal class QrScanningFragment : ComposeFragment() {
@Composable @Composable
override fun ScreenContent(modifier: Modifier) { override fun ScreenContent(modifier: Modifier) {
StatusBarTransparencyDisposable() SystemBarsIconsDisposable(darkIcons = false)
QrScanningContent( QrScanningContent(
executor = { cameraExecutor }, executor = { cameraExecutor },
analyzer = { cameraAnalyzer }, analyzer = { cameraAnalyzer },
@ -145,29 +141,4 @@ internal class QrScanningFragment : ComposeFragment() {
fun create() = QrScanningFragment() 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)
}
}
} }

View file

@ -1,14 +1,11 @@
package com.tangem.feature.referral package com.tangem.feature.referral
import android.os.Bundle import android.os.Bundle
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import com.tangem.common.routing.AppRouter import com.tangem.common.routing.AppRouter
import com.tangem.core.ui.UiDependencies 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.core.ui.screen.ComposeFragment
import com.tangem.feature.referral.router.ReferralRouter import com.tangem.feature.referral.router.ReferralRouter
import com.tangem.feature.referral.ui.ReferralScreen import com.tangem.feature.referral.ui.ReferralScreen
@ -35,12 +32,6 @@ class ReferralFragment : ComposeFragment() {
@Composable @Composable
override fun ScreenContent(modifier: Modifier) { override fun ScreenContent(modifier: Modifier) {
val backgroundColor = TangemTheme.colors.background.secondary ReferralScreen(stateHolder = viewModel.uiState)
SystemBarsEffect { setSystemBarsColor(backgroundColor) }
ReferralScreen(
modifier = Modifier.systemBarsPadding(),
stateHolder = viewModel.uiState,
)
} }
} }

View file

@ -2,23 +2,20 @@ package com.tangem.feature.referral.ui
import android.content.res.Configuration import android.content.res.Configuration
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier 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.platform.LocalInspectionMode
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.google.accompanist.web.WebView import com.google.accompanist.web.WebView
import com.google.accompanist.web.rememberWebViewState import com.google.accompanist.web.rememberWebViewState
import com.tangem.core.ui.components.appbar.AppBarWithAdditionalButtons 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.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.feature.referral.presentation.R import com.tangem.feature.referral.presentation.R
/** /**
@ -28,15 +25,16 @@ import com.tangem.feature.referral.presentation.R
*/ */
@Composable @Composable
internal fun AgreementBottomSheetContent(url: String) { internal fun AgreementBottomSheetContent(url: String) {
val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() }
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxSize()
.height(LocalConfiguration.current.screenHeightDp.dp - TangemTheme.dimens.spacing16), .verticalScroll(rememberScrollState()),
) { ) {
Column(modifier = Modifier.verticalScroll(rememberScrollState())) { AppBarWithAdditionalButtons(text = stringResource(id = R.string.details_referral_title))
AppBarWithAdditionalButtons(text = stringResource(id = R.string.details_referral_title)) AgreementHtmlView(url = url)
AgreementHtmlView(url = url) Spacer(modifier = Modifier.height(bottomBarHeight))
}
} }
} }
@ -46,7 +44,7 @@ private fun AgreementHtmlView(url: String) {
val isInPreviewMode = LocalInspectionMode.current val isInPreviewMode = LocalInspectionMode.current
WebView( WebView(
state = state, state = state,
modifier = Modifier.background(TangemTheme.colors.background.secondary), modifier = Modifier.background(TangemTheme.colors.background.primary),
captureBackPresses = false, captureBackPresses = false,
onCreated = { onCreated = {
if (!isInPreviewMode) { if (!isInPreviewMode) {

View file

@ -1,11 +1,18 @@
package com.tangem.feature.referral.ui 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.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.SheetState import androidx.compose.material3.SheetState
import androidx.compose.runtime.Composable 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.res.TangemTheme
import com.tangem.core.ui.utils.WindowInsetsZero
import com.tangem.feature.referral.models.ReferralStateHolder import com.tangem.feature.referral.models.ReferralStateHolder
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@ -16,14 +23,18 @@ internal fun ReferralBottomSheet(
onDismissRequest: () -> Unit, onDismissRequest: () -> Unit,
config: ReferralStateHolder.ReferralInfoState, config: ReferralStateHolder.ReferralInfoState,
) { ) {
val statusBarHeight = with(LocalDensity.current) { WindowInsets.statusBars.getTop(this).toDp() }
if (isVisible) { if (isVisible) {
ModalBottomSheet( ModalBottomSheet(
modifier = Modifier.height(LocalWindowSize.current.height - statusBarHeight),
onDismissRequest = onDismissRequest, onDismissRequest = onDismissRequest,
sheetState = sheetState, sheetState = sheetState,
shape = RoundedCornerShape( shape = RoundedCornerShape(
topStart = TangemTheme.dimens.radius16, topStart = TangemTheme.dimens.radius16,
topEnd = TangemTheme.dimens.radius16, topEnd = TangemTheme.dimens.radius16,
), ),
windowInsets = WindowInsetsZero,
containerColor = TangemTheme.colors.background.primary, containerColor = TangemTheme.colors.background.primary,
) { ) {
AgreementBottomSheetContent( AgreementBottomSheetContent(

View file

@ -46,16 +46,16 @@ import kotlinx.coroutines.launch
*/ */
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
internal fun ReferralScreen(stateHolder: ReferralStateHolder, modifier: Modifier = Modifier) { internal fun ReferralScreen(stateHolder: ReferralStateHolder) {
var isBottomSheetVisible by remember { mutableStateOf(value = false) } var isBottomSheetVisible by remember { mutableStateOf(value = false) }
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
val snackbarHostState = remember(::SnackbarHostState) val snackbarHostState = remember(::SnackbarHostState)
Scaffold( Scaffold(
modifier = modifier,
topBar = { topBar = {
AppBarWithBackButton( AppBarWithBackButton(
modifier = Modifier.statusBarsPadding(),
text = stringResource(R.string.details_referral_title), text = stringResource(R.string.details_referral_title),
onBackClick = stateHolder.headerState.onBackClicked, onBackClick = stateHolder.headerState.onBackClicked,
) )

View file

@ -9,8 +9,6 @@ import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.AppRouter import com.tangem.common.routing.AppRouter
import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.ui.UiDependencies 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.core.ui.screen.ComposeFragment
import com.tangem.features.send.api.navigation.SendRouter import com.tangem.features.send.api.navigation.SendRouter
import com.tangem.features.send.impl.navigation.InnerSendRouter import com.tangem.features.send.impl.navigation.InnerSendRouter
@ -61,10 +59,6 @@ internal class SendFragment : ComposeFragment() {
@Composable @Composable
override fun ScreenContent(modifier: Modifier) { override fun ScreenContent(modifier: Modifier) {
val systemBarsColor = TangemTheme.colors.background.tertiary
SystemBarsEffect {
setSystemBarsColor(systemBarsColor)
}
val currentState = viewModel.stateRouter.currentState.collectAsStateWithLifecycle() val currentState = viewModel.stateRouter.currentState.collectAsStateWithLifecycle()
SendScreen(viewModel.uiState, currentState.value) SendScreen(viewModel.uiState, currentState.value)
} }

View file

@ -46,10 +46,10 @@ internal fun SendScreen(uiState: SendUiState, currentState: SendUiCurrentScreen)
BackHandler(onBack = onBackClick) BackHandler(onBack = onBackClick)
Column( Column(
modifier = Modifier modifier = Modifier
.background(color = TangemTheme.colors.background.tertiary)
.fillMaxSize() .fillMaxSize()
.imePadding() .imePadding()
.systemBarsPadding() .systemBarsPadding(),
.background(color = TangemTheme.colors.background.tertiary),
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
) { ) {
SendAppBar( SendAppBar(

View file

@ -7,8 +7,6 @@ import androidx.fragment.app.viewModels
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.ui.UiDependencies 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.core.ui.screen.ComposeFragment
import com.tangem.features.staking.api.navigation.StakingRouter import com.tangem.features.staking.api.navigation.StakingRouter
import com.tangem.features.staking.impl.navigation.InnerStakingRouter import com.tangem.features.staking.impl.navigation.InnerStakingRouter
@ -59,10 +57,6 @@ internal class StakingFragment : ComposeFragment() {
@Composable @Composable
override fun ScreenContent(modifier: Modifier) { override fun ScreenContent(modifier: Modifier) {
val systemBarsColor = TangemTheme.colors.background.tertiary
SystemBarsEffect {
setSystemBarsColor(systemBarsColor)
}
val currentState = viewModel.uiState.collectAsStateWithLifecycle() val currentState = viewModel.uiState.collectAsStateWithLifecycle()
StakingScreen(currentState.value) StakingScreen(currentState.value)
} }

View file

@ -28,10 +28,10 @@ internal fun StakingScreen(uiState: StakingUiState) {
BackHandler(onBack = uiState.clickIntents::onBackClick) BackHandler(onBack = uiState.clickIntents::onBackClick)
Column( Column(
modifier = Modifier modifier = Modifier
.background(color = TangemTheme.colors.background.tertiary)
.fillMaxSize() .fillMaxSize()
.imePadding() .imePadding()
.systemBarsPadding() .systemBarsPadding(),
.background(color = TangemTheme.colors.background.tertiary),
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
) { ) {
SendAppBar( SendAppBar(

View file

@ -2,13 +2,13 @@ package com.tangem.feature.swap.presentation
import android.os.Bundle import android.os.Bundle
import androidx.compose.animation.Crossfade import androidx.compose.animation.Crossfade
import androidx.compose.foundation.background
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import com.tangem.common.routing.AppRouter import com.tangem.common.routing.AppRouter
import com.tangem.core.ui.UiDependencies 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.res.TangemTheme
import com.tangem.core.ui.screen.ComposeFragment import com.tangem.core.ui.screen.ComposeFragment
import com.tangem.feature.swap.router.CustomTabsManager import com.tangem.feature.swap.router.CustomTabsManager
@ -47,17 +47,17 @@ class SwapFragment : ComposeFragment() {
@Composable @Composable
override fun ScreenContent(modifier: Modifier) { override fun ScreenContent(modifier: Modifier) {
viewModel.onScreenOpened() viewModel.onScreenOpened()
val backgroundColor = TangemTheme.colors.background.secondary
SystemBarsEffect { setSystemBarsColor(backgroundColor) }
ScreenContent(viewModel = viewModel) ScreenContent(viewModel = viewModel)
} }
@Suppress("TopLevelComposableFunctions") @Suppress("TopLevelComposableFunctions")
@Composable @Composable
private fun ScreenContent(viewModel: SwapViewModel) { 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) { when (screen) {
SwapNavScreen.Main -> SwapScreen(stateHolder = viewModel.uiState) SwapNavScreen.Main -> SwapScreen(stateHolder = viewModel.uiState)
SwapNavScreen.Success -> { SwapNavScreen.Success -> {

View file

@ -8,6 +8,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import com.tangem.core.ui.components.appbar.AppBarWithBackButton import com.tangem.core.ui.components.appbar.AppBarWithBackButton
import com.tangem.core.ui.res.TangemTheme 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.SwapStateHolder
import com.tangem.feature.swap.models.states.ChooseFeeBottomSheetConfig import com.tangem.feature.swap.models.states.ChooseFeeBottomSheetConfig
import com.tangem.feature.swap.models.states.ChooseProviderBottomSheetConfig import com.tangem.feature.swap.models.states.ChooseProviderBottomSheetConfig
@ -28,7 +29,7 @@ internal fun SwapScreen(stateHolder: SwapStateHolder) {
iconRes = R.drawable.ic_close_24, iconRes = R.drawable.ic_close_24,
) )
}, },
contentWindowInsets = WindowInsets(left = 0, top = 0, right = 0, bottom = 0), contentWindowInsets = WindowInsetsZero,
containerColor = TangemTheme.colors.background.secondary, containerColor = TangemTheme.colors.background.secondary,
) { scaffoldPaddings -> ) { scaffoldPaddings ->

View file

@ -6,9 +6,9 @@ import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.tangem.core.navigation.finisher.AppFinisher import com.tangem.core.navigation.finisher.AppFinisher
import com.tangem.core.ui.UiDependencies 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.res.TangemTheme
import com.tangem.core.ui.screen.ComposeActivity import com.tangem.core.ui.screen.ComposeActivity
import com.tangem.feature.tester.presentation.actions.TesterActionsScreen import com.tangem.feature.tester.presentation.actions.TesterActionsScreen
@ -45,9 +45,8 @@ internal class TesterActivity : ComposeActivity() {
@Composable @Composable
override fun ScreenContent(modifier: Modifier) { override fun ScreenContent(modifier: Modifier) {
val systemBarsColor = TangemTheme.colors.background.secondary val systemBarsColor = TangemTheme.colors.background.secondary
SystemBarsEffect { val systemUiController = rememberSystemUiController()
setSystemBarsColor(systemBarsColor) systemUiController.setSystemBarsColor(systemBarsColor)
}
TesterNavHost() TesterNavHost()
} }

View file

@ -5,8 +5,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import com.tangem.core.ui.UiDependencies import com.tangem.core.ui.UiDependencies
import com.tangem.core.ui.components.SystemBarsEffect import com.tangem.core.ui.components.NavigationBar3ButtonsScrim
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.screen.ComposeFragment import com.tangem.core.ui.screen.ComposeFragment
import com.tangem.feature.tokendetails.presentation.router.InnerTokenDetailsRouter import com.tangem.feature.tokendetails.presentation.router.InnerTokenDetailsRouter
import com.tangem.feature.tokendetails.presentation.tokendetails.ui.TokenDetailsScreen import com.tangem.feature.tokendetails.presentation.tokendetails.ui.TokenDetailsScreen
@ -33,14 +32,8 @@ internal class TokenDetailsFragment : ComposeFragment() {
override fun ScreenContent(modifier: Modifier) { override fun ScreenContent(modifier: Modifier) {
val viewModel = hiltViewModel<TokenDetailsViewModel>() val viewModel = hiltViewModel<TokenDetailsViewModel>()
viewModel.router = this@TokenDetailsFragment.internalTokenDetailsRouter viewModel.router = this@TokenDetailsFragment.internalTokenDetailsRouter
LocalLifecycleOwner.current.lifecycle.addObserver(viewModel) LocalLifecycleOwner.current.lifecycle.addObserver(viewModel)
NavigationBar3ButtonsScrim()
val systemBarsColor = TangemTheme.colors.background.secondary
SystemBarsEffect {
setSystemBarsColor(systemBarsColor)
}
TokenDetailsScreen(state = viewModel.uiState) TokenDetailsScreen(state = viewModel.uiState)
} }
} }

View file

@ -3,10 +3,7 @@ package com.tangem.feature.tokendetails.presentation.tokendetails.ui
import android.content.res.Configuration import android.content.res.Configuration
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.material.ExperimentalMaterialApi 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.pullRefresh
import androidx.compose.material.pullrefresh.rememberPullRefreshState import androidx.compose.material.pullrefresh.rememberPullRefreshState
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.ScaffoldDefaults
import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -21,6 +19,7 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext 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.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
@ -60,11 +59,13 @@ import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.e
@Composable @Composable
internal fun TokenDetailsScreen(state: TokenDetailsState) { internal fun TokenDetailsScreen(state: TokenDetailsState) {
BackHandler(onBack = state.topAppBarConfig.onBackClick) BackHandler(onBack = state.topAppBarConfig.onBackClick)
val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() }
val snackbarHostState = remember { SnackbarHostState() } val snackbarHostState = remember { SnackbarHostState() }
Scaffold( Scaffold(
topBar = { TokenDetailsTopAppBar(config = state.topAppBarConfig) }, topBar = { TokenDetailsTopAppBar(config = state.topAppBarConfig) },
snackbarHost = { SnackbarHost(hostState = snackbarHostState) }, snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
contentWindowInsets = ScaffoldDefaults.contentWindowInsets.exclude(WindowInsets.navigationBars),
containerColor = TangemTheme.colors.background.secondary, containerColor = TangemTheme.colors.background.secondary,
) { scaffoldPaddings -> ) { scaffoldPaddings ->
val pullRefreshState = rememberPullRefreshState( val pullRefreshState = rememberPullRefreshState(
@ -90,7 +91,9 @@ internal fun TokenDetailsScreen(state: TokenDetailsState) {
) { ) {
LazyColumn( LazyColumn(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
contentPadding = PaddingValues(bottom = TangemTheme.dimens.spacing16), contentPadding = PaddingValues(
bottom = TangemTheme.dimens.spacing16 + bottomBarHeight,
),
) { ) {
item { item {
TokenInfoBlock( TokenInfoBlock(

View file

@ -3,8 +3,6 @@ package com.tangem.feature.wallet.presentation
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import com.tangem.core.ui.UiDependencies 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.core.ui.screen.ComposeFragment
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
import com.tangem.features.managetokens.navigation.ManageTokensUi import com.tangem.features.managetokens.navigation.ManageTokensUi
@ -37,11 +35,6 @@ internal class WalletFragment : ComposeFragment() {
@Composable @Composable
override fun ScreenContent(modifier: Modifier) { override fun ScreenContent(modifier: Modifier) {
val systemBarsColor = TangemTheme.colors.background.secondary
SystemBarsEffect {
setSystemBarsColor(systemBarsColor)
}
_walletRouter.Initialize( _walletRouter.Initialize(
onFinish = requireActivity()::finish, onFinish = requireActivity()::finish,
manageTokensUi = manageTokensUi, manageTokensUi = manageTokensUi,

View file

@ -16,11 +16,10 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.composed import androidx.compose.ui.composed
import androidx.compose.ui.draw.shadow 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.RectangleShape
import androidx.compose.ui.graphics.Shape import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview 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.tooling.preview.datasource.CollectionPreviewParameterProvider
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
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.PrimaryButton
import com.tangem.core.ui.components.SecondaryButton import com.tangem.core.ui.components.SecondaryButton
import com.tangem.core.ui.components.buttons.actions.ActionButtonConfig 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.extensions.TextReference
import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview 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.impl.R
import com.tangem.feature.wallet.presentation.common.WalletPreviewData import com.tangem.feature.wallet.presentation.common.WalletPreviewData
import com.tangem.feature.wallet.presentation.common.component.DraggableNetworkGroupItem import com.tangem.feature.wallet.presentation.common.component.DraggableNetworkGroupItem
@ -57,8 +58,12 @@ internal fun OrganizeTokensScreen(state: OrganizeTokensState, modifier: Modifier
Scaffold( Scaffold(
modifier = modifier, modifier = modifier,
topBar = { topBar = {
TopBar(state.header, tokensListState) TopBar(
config = state.header,
tokensListState = tokensListState,
)
}, },
contentWindowInsets = WindowInsetsZero,
content = { paddingValues -> content = { paddingValues ->
TokenList( TokenList(
modifier = Modifier modifier = Modifier
@ -72,7 +77,9 @@ internal fun OrganizeTokensScreen(state: OrganizeTokensState, modifier: Modifier
}, },
floatingActionButtonPosition = FabPosition.Center, floatingActionButtonPosition = FabPosition.Center,
floatingActionButton = { floatingActionButton = {
Actions(state.actions) Box(modifier = Modifier.navigationBarsPadding()) {
Actions(state.actions)
}
}, },
containerColor = TangemTheme.colors.background.secondary, containerColor = TangemTheme.colors.background.secondary,
) )
@ -104,9 +111,11 @@ private fun TokenList(
onDragEnd = onDragEnd, onDragEnd = onDragEnd,
) )
val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() }
val listContentPadding = PaddingValues( val listContentPadding = PaddingValues(
top = TangemTheme.dimens.spacing4, top = TangemTheme.dimens.spacing4,
bottom = TangemTheme.dimens.spacing92, bottom = TangemTheme.dimens.spacing92 + bottomBarHeight,
start = TangemTheme.dimens.spacing16, start = TangemTheme.dimens.spacing16,
end = 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 @Composable
private fun TopBar( private fun TopBar(
config: OrganizeTokensState.HeaderConfig, config: OrganizeTokensState.HeaderConfig,
@ -228,6 +220,7 @@ private fun TopBar(
modifier = modifier modifier = modifier
.shadow(elevation) .shadow(elevation)
.background(TangemTheme.colors.background.secondary) .background(TangemTheme.colors.background.secondary)
.statusBarsPadding()
.padding(horizontal = TangemTheme.dimens.spacing16) .padding(horizontal = TangemTheme.dimens.spacing16)
.fillMaxWidth(), .fillMaxWidth(),
) { ) {

View file

@ -1,9 +1,7 @@
package com.tangem.feature.wallet.presentation.router package com.tangem.feature.wallet.presentation.router
import android.annotation.SuppressLint import android.annotation.SuppressLint
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
@ -86,7 +84,6 @@ internal class DefaultWalletRouter(
val uiState by viewModel.uiState.collectAsStateWithLifecycle() val uiState by viewModel.uiState.collectAsStateWithLifecycle()
OrganizeTokensScreen( OrganizeTokensScreen(
modifier = Modifier.statusBarsPadding(),
state = uiState, state = uiState,
) )
} }

View file

@ -20,6 +20,7 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.luminance
import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.platform.LocalSoftwareKeyboardController
@ -33,16 +34,13 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.paging.compose.collectAsLazyPagingItems import androidx.paging.compose.collectAsLazyPagingItems
import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.tangem.core.ui.components.Keyboard import com.tangem.core.ui.components.*
import com.tangem.core.ui.components.PrimaryButton
import com.tangem.core.ui.components.SystemBarsEffect
import com.tangem.core.ui.components.atoms.Hand import com.tangem.core.ui.components.atoms.Hand
import com.tangem.core.ui.components.atoms.handComposableComponentHeight 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.ChooseAddressBottomSheet
import com.tangem.core.ui.components.bottomsheets.chooseaddress.ChooseAddressBottomSheetConfig 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.TokenReceiveBottomSheet
import com.tangem.core.ui.components.bottomsheets.tokenreceive.TokenReceiveBottomSheetConfig 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.CopiedTextSnackbar
import com.tangem.core.ui.components.snackbar.TangemSnackbar import com.tangem.core.ui.components.snackbar.TangemSnackbar
import com.tangem.core.ui.components.transactions.state.TxHistoryState 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.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.test.TestTags 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.impl.R
import com.tangem.feature.wallet.presentation.common.preview.WalletScreenPreviewData.walletScreenState import com.tangem.feature.wallet.presentation.common.preview.WalletScreenPreviewData.walletScreenState
import com.tangem.feature.wallet.presentation.wallet.state.model.* import com.tangem.feature.wallet.presentation.wallet.state.model.*
@ -112,7 +111,7 @@ internal fun WalletScreen(
) )
} }
@Suppress("LongMethod", "LongParameterList") @Suppress("LongMethod", "LongParameterList", "CyclomaticComplexMethod")
@Composable @Composable
private fun WalletContent( private fun WalletContent(
state: WalletScreenState, state: WalletScreenState,
@ -144,12 +143,14 @@ private fun WalletContent(
.padding(top = betweenItemsPadding) .padding(top = betweenItemsPadding)
.padding(horizontal = horizontalPadding) .padding(horizontal = horizontalPadding)
val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() }
LazyColumn( LazyColumn(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.testTag(TestTags.WALLET_SCREEN), .testTag(TestTags.WALLET_SCREEN),
contentPadding = PaddingValues( contentPadding = PaddingValues(
bottom = TangemTheme.dimens.spacing92, bottom = TangemTheme.dimens.spacing92 + bottomBarHeight,
), ),
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
) { ) {
@ -330,7 +331,7 @@ private fun BaseScaffoldManageTokenRedesign(
coroutineScope.launch { bottomSheetState.partialExpand() } coroutineScope.launch { bottomSheetState.partialExpand() }
} }
}, },
content = { paddingValues -> content = { _ ->
val pullRefreshState = rememberPullRefreshState( val pullRefreshState = rememberPullRefreshState(
refreshing = selectedWallet.pullToRefreshConfig.isRefreshing, refreshing = selectedWallet.pullToRefreshConfig.isRefreshing,
onRefresh = { onRefresh = {
@ -338,9 +339,7 @@ private fun BaseScaffoldManageTokenRedesign(
}, },
) )
Column( Column {
modifier = Modifier.padding(paddingValues),
) {
WalletTopBar(config = state.topBarConfig) WalletTopBar(config = state.topBarConfig)
Box( Box(
modifier = Modifier.pullRefresh(pullRefreshState), modifier = Modifier.pullRefresh(pullRefreshState),
@ -392,7 +391,7 @@ private fun BottomSheetScrim(color: Color, visible: Boolean, onDismissRequest: (
} }
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Suppress("CyclomaticComplexMethod") @Suppress("CyclomaticComplexMethod", "MagicNumber")
@Composable @Composable
private fun BottomSheetStateEffects( private fun BottomSheetStateEffects(
bottomSheetState: SheetState, bottomSheetState: SheetState,
@ -425,19 +424,29 @@ private fun BottomSheetStateEffects(
val systemUiController = rememberSystemUiController() val systemUiController = rememberSystemUiController()
val navigationBarColor = TangemTheme.colors.background.primary val navigationBarColor = TangemTheme.colors.background.primary
val navigationBarColorWithout = TangemTheme.colors.background.secondary
SystemBarsEffect { LaunchedEffect(key1 = bottomSheetState.targetValue, navigationBarColor) {
if (showManageTokensBottomSheet) { when (bottomSheetState.targetValue) {
setNavigationBarColor(navigationBarColor) 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 { onDispose {
if (showManageTokensBottomSheet) { 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( Scaffold(
topBar = { WalletTopBar(config = state.topBarConfig) }, topBar = { WalletTopBar(config = state.topBarConfig) },
contentWindowInsets = WindowInsetsZero,
snackbarHost = { snackbarHost = {
WalletSnackbarHost( WalletSnackbarHost(
snackbarHostState = snackbarHostState, 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, floatingActionButtonPosition = FabPosition.Center,
containerColor = TangemTheme.colors.background.secondary, containerColor = TangemTheme.colors.background.secondary,
@ -544,6 +559,8 @@ private fun BaseScaffold(
state = pullRefreshState, state = pullRefreshState,
modifier = Modifier.align(Alignment.TopCenter), modifier = Modifier.align(Alignment.TopCenter),
) )
BottomFade(Modifier.align(Alignment.BottomCenter))
} }
}, },
) )
@ -565,11 +582,11 @@ private fun WalletSnackbarHost(
} }
@Composable @Composable
private fun ManageTokensButton(onClick: () -> Unit) { private fun ManageTokensButton(onClick: () -> Unit, modifier: Modifier = Modifier) {
PrimaryButton( PrimaryButton(
text = stringResource(id = R.string.main_manage_tokens), text = stringResource(id = R.string.main_manage_tokens),
onClick = onClick, onClick = onClick,
modifier = Modifier modifier = modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = TangemTheme.dimens.spacing16), .padding(horizontal = TangemTheme.dimens.spacing16),
) )