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

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

View file

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

View file

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

View file

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

View file

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

View file

@ -7,21 +7,16 @@ import android.os.Bundle
import android.view.View
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.core.content.ContextCompat
import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.google.mlkit.vision.common.InputImage
import com.tangem.core.ui.UiDependencies
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.components.SystemBarsIconsDisposable
import com.tangem.core.ui.screen.ComposeFragment
import com.tangem.feature.qrscanning.inner.MLKitBarcodeAnalyzer
import com.tangem.feature.qrscanning.navigation.QrScanningInnerRouter
@ -105,7 +100,8 @@ internal class QrScanningFragment : ComposeFragment() {
@Composable
override fun ScreenContent(modifier: Modifier) {
StatusBarTransparencyDisposable()
SystemBarsIconsDisposable(darkIcons = false)
QrScanningContent(
executor = { cameraExecutor },
analyzer = { cameraAnalyzer },
@ -145,29 +141,4 @@ internal class QrScanningFragment : ComposeFragment() {
fun create() = QrScanningFragment()
}
}
@Composable
private fun StatusBarTransparencyDisposable() {
val systemUiController = rememberSystemUiController()
val systemBarsColor = TangemTheme.colors.background.secondary
val lifecycleOwner = LocalLifecycleOwner.current
DisposableEffect(Unit) {
val observer = LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_START) {
systemUiController.setSystemBarsColor(
color = Color.Transparent,
darkIcons = false,
)
}
if (event == Lifecycle.Event.ON_STOP) {
systemUiController.setSystemBarsColor(systemBarsColor)
}
}
lifecycleOwner.lifecycle.addObserver(observer)
onDispose {
lifecycleOwner.lifecycle.removeObserver(observer)
}
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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