Updated on 2026-08-14

This commit is contained in:
Tangem 2024-07-15 15:53:44 +04:00
commit 5dea3089f3
34 changed files with 905 additions and 758 deletions

View file

@ -1,4 +1,4 @@
package com.tangem.common.ui.bottomsheets
package com.tangem.common.ui.bottomsheet.permission
import android.content.res.Configuration
import androidx.compose.foundation.background
@ -25,10 +25,9 @@ import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.window.PopupProperties
import com.tangem.common.ui.R
import com.tangem.common.ui.bottomsheets.state.*
import com.tangem.common.ui.bottomsheet.permission.state.*
import com.tangem.core.ui.components.*
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.TopAppBarButtonUM
import com.tangem.core.ui.components.atoms.text.EllipsisText
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
@ -42,17 +41,33 @@ import kotlinx.collections.immutable.ImmutableList
@Composable
fun GiveTxPermissionBottomSheet(config: TangemBottomSheetConfig) {
var isPermissionAlertShow by remember { mutableStateOf(false) }
TangemBottomSheet(
config = config,
containerColor = TangemTheme.colors.background.secondary,
) { content: GiveTxPermissionBottomSheetConfig ->
GiveTxPermissionBottomSheetContent(content = content)
}
titleText = resourceReference(R.string.give_permission_title),
titleAction = TopAppBarButtonUM(
iconRes = R.drawable.ic_information_24,
onIconClicked = { isPermissionAlertShow = true },
),
content = { content: GiveTxPermissionBottomSheetConfig ->
GiveTxPermissionBottomSheetContent(content = content)
if (isPermissionAlertShow) {
BasicDialog(
message = content.data.dialogText.resolveReference(),
title = stringResource(id = R.string.common_approve),
confirmButton = DialogButton { isPermissionAlertShow = false },
onDismissDialog = {},
)
}
},
)
}
@Composable
private fun GiveTxPermissionBottomSheetContent(content: GiveTxPermissionBottomSheetConfig) {
var isPermissionAlertShow by remember { mutableStateOf(false) }
val data = content.data
Column(
modifier = Modifier
@ -60,14 +75,6 @@ private fun GiveTxPermissionBottomSheetContent(content: GiveTxPermissionBottomSh
.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
AppBarWithAdditionalButtons(
text = resourceReference(id = R.string.give_permission_title),
iconColor = TangemTheme.colors.text.tertiary,
endButton = AdditionalButton(
iconRes = R.drawable.ic_information_24,
onIconClicked = { isPermissionAlertShow = true },
),
)
Text(
text = content.data.subtitle.resolveReference(),
color = TangemTheme.colors.text.secondary,
@ -102,16 +109,6 @@ private fun GiveTxPermissionBottomSheetContent(content: GiveTxPermissionBottomSh
)
SpacerH16()
// region dialog
if (isPermissionAlertShow) {
BasicDialog(
message = content.data.dialogText.resolveReference(),
title = stringResource(id = R.string.common_approve),
confirmButton = DialogButton { isPermissionAlertShow = false },
onDismissDialog = {},
)
}
}
}
@ -303,12 +300,18 @@ private fun DropdownSelector(
}
// region preview
@Preview(showBackground = true, widthDp = 360)
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun Preview_AgreementBottomSheet() {
@Preview(showBackground = true)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
private fun Preview_GiveTxPermissionBottomSheet() {
TangemThemePreview {
GiveTxPermissionBottomSheetContent(content = previewData)
GiveTxPermissionBottomSheet(
config = TangemBottomSheetConfig(
isShow = true,
onDismissRequest = {},
content = previewData,
),
)
}
}

View file

@ -1,4 +1,4 @@
package com.tangem.common.ui.bottomsheets.state
package com.tangem.common.ui.bottomsheet.permission.state
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent

View file

@ -1,4 +1,4 @@
package com.tangem.common.ui.bottomsheets.state
package com.tangem.common.ui.bottomsheet.permission.state
import com.tangem.core.ui.extensions.TextReference
import kotlinx.collections.immutable.ImmutableList

View file

@ -1,55 +0,0 @@
package com.tangem.core.ui.components.appbar
import android.content.res.Configuration
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
/**
* App bar without buttons
*
* @param text title
* @param modifier modifier
*
* @see <a href = "https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?node-id=123%3A287&t=WdN5XpixzZLlQAZO-4"
* >Figma component</a>
*/
@Composable
fun AppBar(text: TextReference, modifier: Modifier = Modifier) {
Box(modifier = modifier.fillMaxWidth()) {
Text(
text = text.resolveReference(),
color = TangemTheme.colors.text.primary1,
maxLines = 1,
style = TangemTheme.typography.subtitle1,
modifier = Modifier
.align(Alignment.Center)
.padding(vertical = TangemTheme.dimens.spacing10),
)
}
}
// region Preview
@Preview(showBackground = true, widthDp = 360)
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun AppBar_Preview() {
TangemThemePreview {
AppBar(
text = stringReference("Tangem"),
modifier = Modifier.background(TangemTheme.colors.background.primary),
)
}
}
// endregion

View file

@ -1,179 +0,0 @@
package com.tangem.core.ui.components.appbar
import android.content.res.Configuration
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.R
import com.tangem.core.ui.components.appbar.models.AdditionalButton
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
/**
* App bar with title and two additional buttons
*
* @param startButton button information attached to the left edge
* @param endButton button information attached to the right edge
*
* @see <a href = "https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?node-id=50%3A403&t=tRQ4KlzkjV7TCLZl-4">
* Figma Component</a>
*/
@Composable
fun AppBarWithAdditionalButtons(
text: TextReference,
modifier: Modifier = Modifier,
startButton: AdditionalButton? = null,
endButton: AdditionalButton? = null,
textColor: Color = TangemTheme.colors.text.primary1,
iconColor: Color = TangemTheme.colors.icon.primary1,
) {
AppBarWithAdditionalButtons(
text = text.resolveReference(),
startButton = startButton,
endButton = endButton,
modifier = modifier,
textColor = textColor,
iconColor = iconColor,
)
}
/**
* App bar with title and two additional buttons
*
* @param startButton button information attached to the left edge
* @param endButton button information attached to the right edge
*
* @see <a href = "https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?node-id=50%3A403&t=tRQ4KlzkjV7TCLZl-4">
* Figma Component</a>
*/
@Composable
fun AppBarWithAdditionalButtons(
text: String,
modifier: Modifier = Modifier,
startButton: AdditionalButton? = null,
endButton: AdditionalButton? = null,
textColor: Color = TangemTheme.colors.text.primary1,
iconColor: Color = TangemTheme.colors.icon.primary1,
) {
Box(
modifier = modifier
.fillMaxWidth()
.padding(all = TangemTheme.dimens.spacing16),
) {
if (startButton != null) {
Icon(
painter = painterResource(id = startButton.iconRes),
contentDescription = null,
tint = iconColor,
modifier = Modifier
.size(TangemTheme.dimens.size24)
.align(Alignment.CenterStart)
.clickable(
onClick = startButton.onIconClicked,
role = Role.Button,
interactionSource = remember { MutableInteractionSource() },
indication = androidx.compose.material.ripple.rememberRipple(
bounded = false,
radius = TangemTheme.dimens.size24 / 2,
),
),
)
}
Text(
text = text,
modifier = Modifier.align(Alignment.Center),
color = textColor,
maxLines = 1,
style = TangemTheme.typography.subtitle1,
)
if (endButton != null) {
Icon(
painter = painterResource(id = endButton.iconRes),
contentDescription = null,
tint = iconColor,
modifier = Modifier
.size(TangemTheme.dimens.size24)
.align(Alignment.CenterEnd)
.clickable(
onClick = endButton.onIconClicked,
role = Role.Button,
interactionSource = remember { MutableInteractionSource() },
indication = androidx.compose.material.ripple.rememberRipple(
bounded = false,
radius = TangemTheme.dimens.size24 / 2,
),
),
)
}
}
}
@Preview(widthDp = 360, heightDp = 56, showBackground = true)
@Preview(widthDp = 360, heightDp = 56, showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun Preview_AppBarWithAdditionalButtons() {
TangemThemePreview {
AppBarWithAdditionalButtons(
text = "Tangem",
startButton = AdditionalButton(
iconRes = R.drawable.ic_scan_24,
onIconClicked = {},
),
endButton = AdditionalButton(
iconRes = R.drawable.ic_more_vertical_24,
onIconClicked = {},
),
modifier = Modifier.background(TangemTheme.colors.background.secondary),
)
}
}
@Preview(widthDp = 360, heightDp = 56, showBackground = true)
@Preview(widthDp = 360, heightDp = 56, showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun Preview_AppBarWithOnlyStartButtons() {
TangemThemePreview {
AppBarWithAdditionalButtons(
text = "Tangem",
startButton = AdditionalButton(
iconRes = R.drawable.ic_scan_24,
onIconClicked = {},
),
modifier = Modifier.background(TangemTheme.colors.background.secondary),
)
}
}
@Preview(widthDp = 360, heightDp = 56, showBackground = true)
@Preview(widthDp = 360, heightDp = 56, showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun Preview_AppBarWithOnlyEndButtons() {
TangemThemePreview {
AppBarWithAdditionalButtons(
text = "Tangem",
endButton = AdditionalButton(
iconRes = R.drawable.ic_more_vertical_24,
onIconClicked = {},
),
modifier = Modifier.background(TangemTheme.colors.background.secondary),
)
}
}

View file

@ -2,22 +2,12 @@ package com.tangem.core.ui.components.appbar
import android.content.res.Configuration
import androidx.annotation.DrawableRes
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.material.Icon
import androidx.compose.material.Text
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.R
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.res.TangemTheme
/**
* App bar with back button and optional title
@ -37,37 +27,17 @@ fun AppBarWithBackButton(
text: String? = null,
@DrawableRes iconRes: Int? = null,
) {
Row(
modifier = modifier
.background(color = TangemTheme.colors.background.secondary)
.fillMaxWidth()
.padding(all = TangemTheme.dimens.spacing16),
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing16),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
painter = painterResource(iconRes ?: R.drawable.ic_back_24),
contentDescription = null,
modifier = Modifier
.size(size = TangemTheme.dimens.size24)
.clickable(
indication = rememberRipple(bounded = false),
interactionSource = remember { MutableInteractionSource() },
onClick = onBackClick,
),
tint = TangemTheme.colors.icon.primary1,
)
if (!text.isNullOrBlank()) {
Text(
text = text,
color = TangemTheme.colors.text.primary1,
maxLines = 1,
style = TangemTheme.typography.subtitle1,
)
}
}
TangemTopAppBar(
modifier = modifier,
title = text,
startButton = TopAppBarButtonUM(
iconRes = iconRes ?: R.drawable.ic_back_24,
onIconClicked = onBackClick,
),
)
}
// region Preview
@Preview(widthDp = 360, heightDp = 56, showBackground = true)
@Preview(widthDp = 360, heightDp = 56, showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
@ -75,4 +45,5 @@ private fun PreviewAppBarWithBackButton() {
TangemThemePreview {
AppBarWithBackButton(text = "Title", onBackClick = {})
}
}
}
// endregion

View file

@ -2,18 +2,14 @@ package com.tangem.core.ui.components.appbar
import android.content.res.Configuration
import androidx.annotation.DrawableRes
import androidx.compose.animation.*
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.size
import androidx.compose.material.Icon
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.R
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
@Composable
fun AppBarWithBackButtonAndIcon(
@ -26,30 +22,22 @@ fun AppBarWithBackButtonAndIcon(
onIconClick: (() -> Unit)? = null,
backgroundColor: Color = TangemTheme.colors.background.secondary,
) {
AppBarWithBackButtonAndIconContent(
onBackClick = onBackClick,
TangemTopAppBar(
modifier = modifier,
text = text,
title = text,
subtitle = subtitle,
backIconRes = backIconRes,
backgroundColor = backgroundColor,
iconContent = {
AnimatedContent(
targetState = iconRes,
transitionSpec = { (fadeIn() + scaleIn()).togetherWith(fadeOut() + scaleOut()) },
label = "Toolbar icon change",
) {
if (onIconClick != null && it != null) {
Icon(
painter = painterResource(it),
contentDescription = null,
modifier = Modifier
.size(size = TangemTheme.dimens.size24)
.clickable { onIconClick() },
tint = TangemTheme.colors.icon.primary1,
)
}
}
containerColor = backgroundColor,
startButton = TopAppBarButtonUM(
iconRes = backIconRes ?: R.drawable.ic_back_24,
onIconClicked = onBackClick,
),
endButton = if (iconRes != null && onIconClick != null) {
TopAppBarButtonUM(
iconRes = iconRes,
onIconClicked = onIconClick,
)
} else {
null
},
)
}

View file

@ -1,127 +0,0 @@
package com.tangem.core.ui.components.appbar
import android.content.res.Configuration
import androidx.annotation.DrawableRes
import androidx.compose.animation.*
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.material.Icon
import androidx.compose.material.Text
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.R
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.res.TangemTheme
/**
* App bar with back button and icon content for any possible number/style of icons
*
* @param onBackClick callback for back button
* @param modifier modifier
* @param text appbar title
* @param backIconRes icon for back button
* @param backgroundColor background color
* @param iconContent icon content
*/
@Composable
fun AppBarWithBackButtonAndIconContent(
onBackClick: () -> Unit,
modifier: Modifier = Modifier,
text: String? = null,
subtitle: String? = null,
@DrawableRes backIconRes: Int? = null,
backIconTint: Color = TangemTheme.colors.icon.primary1,
backgroundColor: Color = TangemTheme.colors.background.secondary,
iconContent: @Composable () -> Unit,
) {
Row(
modifier = modifier
.height(TangemTheme.dimens.size56)
.background(color = backgroundColor)
.fillMaxWidth()
.padding(horizontal = TangemTheme.dimens.spacing16),
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing16),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
painter = painterResource(backIconRes ?: R.drawable.ic_back_24),
contentDescription = null,
modifier = Modifier
.padding(vertical = TangemTheme.dimens.spacing16)
.size(size = TangemTheme.dimens.size24)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(bounded = false),
) { onBackClick() },
tint = backIconTint,
)
Column(
verticalArrangement = Arrangement.Center,
modifier = Modifier.weight(1f)
.animateContentSize(),
) {
AnimatedVisibility(
visible = !text.isNullOrBlank(),
enter = fadeIn(),
exit = fadeOut(),
label = "Toolbar title change",
) {
Text(
text = text.orEmpty(),
color = TangemTheme.colors.text.primary1,
maxLines = 1,
style = TangemTheme.typography.subtitle1,
)
}
AnimatedVisibility(
visible = !subtitle.isNullOrBlank(),
enter = fadeIn().plus(expandVertically()),
exit = fadeOut().plus(shrinkVertically()),
label = "Toolbar subtitle change",
) {
Text(
text = subtitle.orEmpty(),
color = TangemTheme.colors.text.secondary,
maxLines = 1,
style = TangemTheme.typography.caption2,
)
}
}
iconContent()
}
}
@Preview(widthDp = 360, heightDp = 56, showBackground = true)
@Preview(widthDp = 360, heightDp = 56, showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun PreviewAppBarWithBackButtonAndIcon() {
TangemThemePreview {
AppBarWithBackButtonAndIconContent(
text = "Title",
subtitle = "Subtitle",
onBackClick = {},
iconContent = {
Row {
Icon(
painter = painterResource(id = R.drawable.ic_qrcode_scan_24),
tint = TangemTheme.colors.icon.primary1,
contentDescription = null,
)
Icon(
painter = painterResource(id = R.drawable.ic_flash_on_24),
tint = TangemTheme.colors.icon.primary1,
contentDescription = null,
)
}
},
)
}
}

View file

@ -0,0 +1,336 @@
package com.tangem.core.ui.components.appbar
import android.content.res.Configuration
import androidx.compose.animation.*
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import com.tangem.core.ui.R
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
/**
* [TangemTopAppBar] height options.
* */
enum class TangemTopAppBarHeight {
BOTTOM_SHEET, DEFAULT,
}
/**
* Top app bar with two optional buttons: [startButton] and [endButton].
*
* @see <a href = "https://www.figma.com/design/14ISV23YB1yVW1uNVwqrKv/Android?node-id=122-47&m=dev">
* Figma Component</a>
*/
@Composable
fun TangemTopAppBar(
modifier: Modifier = Modifier,
startButton: TopAppBarButtonUM? = null,
endButton: TopAppBarButtonUM? = null,
textColor: Color = TangemTheme.colors.text.primary1,
iconTint: Color = TangemTheme.colors.icon.primary1,
containerColor: Color = Color.Transparent,
height: TangemTopAppBarHeight = TangemTopAppBarHeight.DEFAULT,
) {
TangemTopAppBar(
modifier = modifier,
title = null,
startButton = startButton,
endButton = endButton,
textColor = textColor,
iconTint = iconTint,
containerColor = containerColor,
height = height,
)
}
/**
* Top app bar with [title], optional [subtitle] and two optional buttons: [startButton] and [endButton].
*
* Where [title] and [subtitle] are [TextReference].
*
* @see <a href = "https://www.figma.com/design/14ISV23YB1yVW1uNVwqrKv/Android?node-id=122-47&m=dev">
* Figma Component</a>
*/
@Composable
fun TangemTopAppBar(
title: TextReference,
modifier: Modifier = Modifier,
subtitle: TextReference? = null,
startButton: TopAppBarButtonUM? = null,
endButton: TopAppBarButtonUM? = null,
textColor: Color = TangemTheme.colors.text.primary1,
iconTint: Color = TangemTheme.colors.icon.primary1,
titleAlignment: Alignment.Horizontal = Alignment.Start,
containerColor: Color = Color.Transparent,
height: TangemTopAppBarHeight = TangemTopAppBarHeight.DEFAULT,
) {
TangemTopAppBar(
modifier = modifier,
title = title.resolveReference(),
subtitle = subtitle?.resolveReference(),
startButton = startButton,
endButton = endButton,
textColor = textColor,
iconTint = iconTint,
titleAlignment = titleAlignment,
containerColor = containerColor,
height = height,
)
}
/**
* Top app bar with [title], optional [subtitle] and two optional buttons: [startButton] and [endButton].
*
* Where [title] and [subtitle] are [String].
*
* @see <a href = "https://www.figma.com/design/14ISV23YB1yVW1uNVwqrKv/Android?node-id=122-47&m=dev">
* Figma Component</a>
*/
@Composable
fun TangemTopAppBar(
title: String?,
modifier: Modifier = Modifier,
subtitle: String? = null,
startButton: TopAppBarButtonUM? = null,
endButton: TopAppBarButtonUM? = null,
textColor: Color = TangemTheme.colors.text.primary1,
iconTint: Color = TangemTheme.colors.icon.primary1,
titleAlignment: Alignment.Horizontal = Alignment.Start,
containerColor: Color = Color.Transparent,
height: TangemTopAppBarHeight = TangemTopAppBarHeight.DEFAULT,
) {
TangemTopAppBar(
title = title,
modifier = modifier,
subtitle = subtitle,
startButton = startButton,
textColor = textColor,
iconTint = iconTint,
titleAlignment = titleAlignment,
containerColor = containerColor,
height = height,
endContent = {
if (endButton != null) {
TopAppBarButton(
button = endButton,
tint = iconTint,
)
}
},
)
}
/**
* Top app bar with [title], optional [subtitle], optional [startButton] and [endContent].
*
* Where [title] and [subtitle] are [String] and [endContent] is a lambda that provides a [RowScope] to build
* the end content.
*
* @see <a href = "https://www.figma.com/design/14ISV23YB1yVW1uNVwqrKv/Android?node-id=122-47&m=dev">
* Figma Component</a>
*/
@Composable
fun TangemTopAppBar(
title: String?,
modifier: Modifier = Modifier,
subtitle: String? = null,
startButton: TopAppBarButtonUM? = null,
textColor: Color = TangemTheme.colors.text.primary1,
iconTint: Color = TangemTheme.colors.icon.primary1,
titleAlignment: Alignment.Horizontal = Alignment.Start,
containerColor: Color = Color.Transparent,
height: TangemTopAppBarHeight = TangemTopAppBarHeight.DEFAULT,
endContent: @Composable RowScope.() -> Unit,
) {
Row(
modifier = modifier
.background(color = containerColor)
.fillMaxWidth()
.heightIn(min = height.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Box(
modifier = Modifier
.padding(horizontal = TangemTheme.dimens.spacing12)
.size(TangemTheme.dimens.size32),
contentAlignment = Alignment.Center,
) {
if (startButton != null) {
TopAppBarButton(
button = startButton,
tint = iconTint,
)
}
}
TopAppBarTitle(
modifier = Modifier.weight(1f),
title = title,
subtitle = subtitle,
textColor = textColor,
titleAlignment = titleAlignment,
)
Row(
modifier = Modifier
.padding(horizontal = TangemTheme.dimens.spacing12)
.widthIn(min = TangemTheme.dimens.size32)
.height(TangemTheme.dimens.size32),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12, Alignment.End),
content = endContent,
)
}
}
@Composable
private fun TopAppBarTitle(
title: String?,
subtitle: String?,
textColor: Color,
titleAlignment: Alignment.Horizontal,
modifier: Modifier = Modifier,
) {
Box(modifier = modifier) {
AnimatedVisibility(
modifier = Modifier.fillMaxWidth(),
visible = !title.isNullOrBlank(),
enter = fadeIn() + expandVertically(),
exit = fadeOut() + shrinkVertically(),
) {
Column(
modifier = Modifier.fillMaxWidth(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = titleAlignment,
) {
Text(
text = title.orEmpty(),
style = TangemTheme.typography.subtitle1,
color = textColor,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
AnimatedVisibility(
visible = !subtitle.isNullOrBlank(),
enter = fadeIn() + expandVertically(),
exit = fadeOut() + shrinkVertically(),
label = "Toolbar subtitle visibility",
) {
Text(
text = subtitle.orEmpty(),
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.secondary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
}
}
}
}
private val TangemTopAppBarHeight.dp
@Composable
@ReadOnlyComposable
get() = when (this) {
TangemTopAppBarHeight.BOTTOM_SHEET -> TangemTheme.dimens.size44
TangemTopAppBarHeight.DEFAULT -> TangemTheme.dimens.size56
}
// region Preview
@Composable
@Preview(showBackground = true, widthDp = 360)
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
private fun Preview_BasicTopAppBar(
@PreviewParameter(BasicTopAppBarPMPreviewProvider::class) params: BasicTopAppBarPM,
) {
TangemThemePreview {
TangemTopAppBar(
title = params.title,
subtitle = params.subtitle,
startButton = params.startButton,
endButton = params.endButton,
titleAlignment = params.titleAlignment,
containerColor = TangemTheme.colors.background.secondary,
height = params.height,
)
}
}
private data class BasicTopAppBarPM(
val title: String? = "Tangem",
val subtitle: String? = null,
val startButton: TopAppBarButtonUM? = null,
val endButton: TopAppBarButtonUM? = null,
val titleAlignment: Alignment.Horizontal = Alignment.CenterHorizontally,
val height: TangemTopAppBarHeight = TangemTopAppBarHeight.DEFAULT,
)
private class BasicTopAppBarPMPreviewProvider : PreviewParameterProvider<BasicTopAppBarPM> {
override val values: Sequence<BasicTopAppBarPM>
get() = sequenceOf(
BasicTopAppBarPM(
subtitle = "Subtitle",
titleAlignment = Alignment.Start,
startButton = TopAppBarButtonUM.Back { },
),
BasicTopAppBarPM(
title = null,
startButton = TopAppBarButtonUM.Back { },
),
BasicTopAppBarPM(
height = TangemTopAppBarHeight.BOTTOM_SHEET,
),
BasicTopAppBarPM(
startButton = TopAppBarButtonUM(
iconRes = R.drawable.ic_scan_24,
onIconClicked = {},
),
endButton = TopAppBarButtonUM(
iconRes = R.drawable.ic_more_vertical_24,
onIconClicked = {},
),
),
BasicTopAppBarPM(
startButton = TopAppBarButtonUM(
iconRes = R.drawable.ic_scan_24,
onIconClicked = {},
),
),
BasicTopAppBarPM(
endButton = TopAppBarButtonUM(
iconRes = R.drawable.ic_more_vertical_24,
onIconClicked = {},
),
height = TangemTopAppBarHeight.BOTTOM_SHEET,
),
BasicTopAppBarPM(
title = "1234567891011121314151617181920",
subtitle = "12345678910111213141516171819202122232425",
titleAlignment = Alignment.Start,
startButton = TopAppBarButtonUM(
iconRes = R.drawable.ic_scan_24,
onIconClicked = {},
),
endButton = TopAppBarButtonUM(
iconRes = R.drawable.ic_more_vertical_24,
onIconClicked = {},
),
),
)
}
// endregion Preview

View file

@ -0,0 +1,26 @@
package com.tangem.core.ui.components.appbar
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
import com.tangem.core.ui.res.TangemTheme
@Composable
fun TopAppBarButton(button: TopAppBarButtonUM, tint: Color, modifier: Modifier = Modifier) {
IconButton(
modifier = modifier.size(TangemTheme.dimens.size32),
onClick = button.onIconClicked,
) {
Icon(
modifier = Modifier.size(TangemTheme.dimens.size24),
painter = painterResource(id = button.iconRes),
tint = tint,
contentDescription = null,
)
}
}

View file

@ -1,8 +0,0 @@
package com.tangem.core.ui.components.appbar.models
import androidx.annotation.DrawableRes
data class AdditionalButton(
@DrawableRes val iconRes: Int,
val onIconClicked: () -> Unit,
)

View file

@ -0,0 +1,19 @@
package com.tangem.core.ui.components.appbar.models
import androidx.annotation.DrawableRes
import com.tangem.core.ui.R
data class TopAppBarButtonUM(
@DrawableRes val iconRes: Int,
val onIconClicked: () -> Unit,
) {
@Suppress("FunctionName")
companion object {
fun Back(onBackClicked: () -> Unit) = TopAppBarButtonUM(
iconRes = R.drawable.ic_back_24,
onIconClicked = onBackClicked,
)
}
}

View file

@ -1,75 +0,0 @@
package com.tangem.core.ui.components.appbar.models
import androidx.compose.foundation.layout.size
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import com.tangem.core.ui.R
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
private const val COLLAPSED_APP_BAR_THRESHOLD = 0.4f
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TopAppBarMedium(
title: TextReference,
scrollBehavior: TopAppBarScrollBehavior,
onBackClick: () -> Unit,
modifier: Modifier = Modifier,
navigationIconResId: Int = R.drawable.ic_back_24,
colors: TopAppBarColors = TangemTopAppBarColors,
) {
MediumTopAppBar(
modifier = modifier,
scrollBehavior = scrollBehavior,
colors = colors,
title = {
val collapsedStyle = TangemTheme.typography.subtitle1
val expandedStyle = TangemTheme.typography.h1
val style by remember(scrollBehavior.state.collapsedFraction) {
derivedStateOf {
if (scrollBehavior.state.collapsedFraction >= COLLAPSED_APP_BAR_THRESHOLD) {
collapsedStyle
} else {
expandedStyle
}
}
}
Text(
text = title.resolveReference(),
style = style,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
},
navigationIcon = {
IconButton(
modifier = Modifier.size(TangemTheme.dimens.size32),
onClick = onBackClick,
) {
Icon(
modifier = Modifier.size(TangemTheme.dimens.size24),
painter = painterResource(id = navigationIconResId),
contentDescription = null,
)
}
},
)
}
@OptIn(ExperimentalMaterial3Api::class)
internal val TangemTopAppBarColors: TopAppBarColors
@Composable
@ReadOnlyComposable
get() = TopAppBarColors(
containerColor = TangemTheme.colors.background.secondary,
scrolledContainerColor = TangemTheme.colors.background.secondary,
navigationIconContentColor = TangemTheme.colors.icon.primary1,
titleContentColor = TangemTheme.colors.text.primary1,
actionIconContentColor = TangemTheme.colors.icon.primary1,
)

View file

@ -1,11 +1,18 @@
package com.tangem.core.ui.components.bottomsheets
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.SheetState
import androidx.compose.material3.SheetValue.Expanded
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalDensity
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.res.LocalBottomSheetAlwaysVisible
import com.tangem.core.ui.res.LocalWindowSize
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.utils.WindowInsetsZero
@ -13,45 +20,79 @@ import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
/**
* Tangem bottom sheet with custom draggable header and config
*
* @param config data model containing logic and ui models
* @param
* @param content custom bottom sheet content
* Bottom sheet with [content], [titleText] and optional [titleAction].
* */
@Composable
inline fun <reified T : TangemBottomSheetConfigContent> TangemBottomSheet(
config: TangemBottomSheetConfig,
titleText: TextReference,
titleAction: TopAppBarButtonUM? = null,
containerColor: Color = TangemTheme.colors.background.primary,
addBottomInsets: Boolean = true,
crossinline content: @Composable ColumnScope.(T) -> Unit,
) {
TangemBottomSheet(
config = config,
containerColor = containerColor,
addBottomInsets = addBottomInsets,
title = { TangemBottomSheetTitle(title = titleText, endButton = titleAction) },
content = content,
)
}
/**
* Bottom sheet with [content] and optional [title].
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
inline fun <reified T : TangemBottomSheetConfigContent> TangemBottomSheet(
config: TangemBottomSheetConfig,
containerColor: Color = TangemTheme.colors.background.primary,
addBottomInsets: Boolean = true,
crossinline title: @Composable BoxScope.(T) -> Unit = {},
crossinline content: @Composable ColumnScope.(T) -> Unit,
) {
val isAlwaysVisible = LocalBottomSheetAlwaysVisible.current
if (isAlwaysVisible) {
PreviewBottomSheet<T>(
config = config,
containerColor = containerColor,
addBottomInsets = addBottomInsets,
title = title,
content = content,
)
} else {
DefaultBottomSheet<T>(
config = config,
containerColor = containerColor,
addBottomInsets = addBottomInsets,
title = title,
content = content,
)
}
}
@Composable
@OptIn(ExperimentalMaterial3Api::class)
inline fun <reified T : TangemBottomSheetConfigContent> DefaultBottomSheet(
config: TangemBottomSheetConfig,
containerColor: Color,
addBottomInsets: Boolean,
crossinline title: @Composable (BoxScope.(T) -> Unit),
crossinline content: @Composable (ColumnScope.(T) -> Unit),
) {
var isVisible by remember { mutableStateOf(value = config.isShow) }
val statusBarHeight = with(LocalDensity.current) { WindowInsets.statusBars.getTop(this).toDp() }
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
if (isVisible && config.content is T) {
ModalBottomSheet(
// FIXME temporary solution to fix height of the bottom sheet
modifier = Modifier.sizeIn(maxHeight = LocalWindowSize.current.height - statusBarHeight),
onDismissRequest = config.onDismissRequest,
BasicBottomSheet<T>(
config = config,
sheetState = sheetState,
containerColor = containerColor,
shape = TangemTheme.shapes.bottomSheetLarge,
windowInsets = WindowInsetsZero,
dragHandle = { TangemBottomSheetDraggableHeader(color = containerColor) },
) {
if (addBottomInsets) {
Column(
// FIXME temporary solution to fix height of the bottom sheet
modifier = Modifier.navigationBarsPadding(),
) {
content(config.content)
}
} else {
content(config.content)
}
}
addBottomInsets = addBottomInsets,
title = title,
content = content,
)
}
LaunchedEffect(key1 = config.isShow) {
@ -63,6 +104,74 @@ inline fun <reified T : TangemBottomSheetConfigContent> TangemBottomSheet(
}
}
@Composable
@OptIn(ExperimentalMaterial3Api::class)
inline fun <reified T : TangemBottomSheetConfigContent> PreviewBottomSheet(
config: TangemBottomSheetConfig,
containerColor: Color,
addBottomInsets: Boolean,
crossinline title: @Composable (BoxScope.(T) -> Unit),
crossinline content: @Composable (ColumnScope.(T) -> Unit),
) {
BasicBottomSheet<T>(
config = config,
sheetState = SheetState(
skipPartiallyExpanded = true,
initialValue = Expanded,
density = LocalDensity.current,
),
containerColor = containerColor,
addBottomInsets = addBottomInsets,
title = title,
content = content,
)
}
@Suppress("LongParameterList")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
inline fun <reified T : TangemBottomSheetConfigContent> BasicBottomSheet(
config: TangemBottomSheetConfig,
sheetState: SheetState,
containerColor: Color,
addBottomInsets: Boolean,
crossinline title: @Composable (BoxScope.(T) -> Unit),
crossinline content: @Composable (ColumnScope.(T) -> Unit),
) {
val model = config.content as? T ?: return
val statusBarHeight = with(LocalDensity.current) { WindowInsets.statusBars.getTop(this).toDp() }
ModalBottomSheet(
// FIXME temporary solution to fix height of the bottom sheet
modifier = Modifier.sizeIn(maxHeight = LocalWindowSize.current.height - statusBarHeight),
onDismissRequest = config.onDismissRequest,
sheetState = sheetState,
containerColor = containerColor,
shape = TangemTheme.shapes.bottomSheetLarge,
windowInsets = WindowInsetsZero,
dragHandle = { TangemBottomSheetDraggableHeader(color = containerColor) },
) {
Column(
modifier = Modifier.let {
if (addBottomInsets) {
it.navigationBarsPadding()
} else {
it
}
},
) {
Box(
modifier = Modifier.fillMaxWidth(),
) {
title(model)
}
content(model)
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
suspend fun SheetState.collapse(onCollapsed: () -> Unit) {
coroutineScope {

View file

@ -5,7 +5,7 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material.Surface
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
@ -14,8 +14,7 @@ import com.tangem.core.ui.res.TangemTheme
@Composable
fun TangemBottomSheetDraggableHeader(color: Color = TangemTheme.colors.background.primary) {
Surface(
modifier = Modifier
.height(TangemTheme.dimens.size20),
modifier = Modifier.height(TangemTheme.dimens.size20),
color = color,
) {
Box(

View file

@ -0,0 +1,68 @@
package com.tangem.core.ui.components.bottomsheets
import android.content.res.Configuration
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.R
import com.tangem.core.ui.components.appbar.TangemTopAppBar
import com.tangem.core.ui.components.appbar.TangemTopAppBarHeight
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
@Composable
fun TangemBottomSheetTitle(
title: TextReference?,
modifier: Modifier = Modifier,
endButton: TopAppBarButtonUM? = null,
containerColor: Color = Color.Transparent,
) {
TangemBottomSheetTitle(
modifier = modifier,
title = title?.resolveReference(),
endButton = endButton,
containerColor = containerColor,
)
}
@Composable
fun TangemBottomSheetTitle(
title: String?,
modifier: Modifier = Modifier,
endButton: TopAppBarButtonUM? = null,
containerColor: Color = Color.Transparent,
) {
TangemTopAppBar(
modifier = modifier,
title = title,
endButton = endButton,
textColor = TangemTheme.colors.text.primary1,
iconTint = TangemTheme.colors.icon.informative,
titleAlignment = Alignment.CenterHorizontally,
containerColor = containerColor,
height = TangemTopAppBarHeight.BOTTOM_SHEET,
)
}
// region Preview
@Composable
@Preview(showBackground = true, widthDp = 360)
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
private fun Preview_TangemBottomSheetTitle() {
TangemThemePreview {
TangemBottomSheetTitle(
title = "Title",
endButton = TopAppBarButtonUM(
iconRes = R.drawable.ic_information_24,
onIconClicked = {},
),
containerColor = TangemTheme.colors.background.secondary,
)
}
}
// endregion Preview

View file

@ -3,6 +3,9 @@ package com.tangem.core.ui.res
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.ProvidableCompositionLocal
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.ui.platform.LocalHapticFeedback
import com.tangem.core.ui.haptic.MockHapticManager
import com.tangem.core.ui.windowsize.rememberWindowSizePreview
@ -12,18 +15,30 @@ fun TangemThemePreview(
isDark: Boolean? = null,
typography: TangemTypography = TangemTheme.typography,
dimens: TangemDimens = TangemTheme.dimens,
alwaysShowBottomSheets: Boolean = true,
content: @Composable () -> Unit,
) {
val isDarkTheme = isDark ?: isSystemInDarkTheme()
BoxWithConstraints {
TangemTheme(
isDark = isDarkTheme,
typography = typography,
dimens = dimens,
windowSize = rememberWindowSizePreview(maxWidth, maxHeight),
hapticManager = MockHapticManager(LocalHapticFeedback.current),
content = content,
)
CompositionLocalProvider(
LocalBottomSheetAlwaysVisible provides alwaysShowBottomSheets,
) {
BoxWithConstraints {
TangemTheme(
isDark = isDarkTheme,
typography = typography,
dimens = dimens,
windowSize = rememberWindowSizePreview(maxWidth, maxHeight),
hapticManager = MockHapticManager(LocalHapticFeedback.current),
content = content,
)
}
}
}
/**
* This is used to make the bottom sheet always visible in the Preview and should be `true` only in the Preview.
* */
val LocalBottomSheetAlwaysVisible: ProvidableCompositionLocal<Boolean> = compositionLocalOf {
false
}

View file

@ -9,18 +9,21 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState
import androidx.compose.material3.*
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.components.appbar.models.TopAppBarMedium
import com.tangem.core.ui.components.appbar.TangemTopAppBar
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
import com.tangem.core.ui.components.block.BlockItem
import com.tangem.core.ui.components.snackbar.TangemSnackbarHost
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.res.LocalSnackbarHostState
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
@ -30,7 +33,6 @@ import com.tangem.features.details.entity.DetailsItemUM
import com.tangem.features.details.entity.DetailsUM
import com.tangem.features.details.impl.R
@OptIn(ExperimentalMaterial3Api::class)
@Composable
internal fun DetailsScreen(
state: DetailsUM,
@ -38,12 +40,11 @@ internal fun DetailsScreen(
modifier: Modifier = Modifier,
) {
val backgroundColor = TangemTheme.colors.background.secondary
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
BackHandler(onBack = state.popBack)
Scaffold(
modifier = modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
modifier = modifier,
containerColor = backgroundColor,
snackbarHost = {
TangemSnackbarHost(
@ -52,10 +53,9 @@ internal fun DetailsScreen(
)
},
topBar = {
TopAppBarMedium(
title = resourceReference(R.string.details_title),
scrollBehavior = scrollBehavior,
onBackClick = state.popBack,
TangemTopAppBar(
modifier = Modifier.statusBarsPadding(),
startButton = TopAppBarButtonUM.Back(state.popBack),
)
},
) { paddingValues ->
@ -77,10 +77,18 @@ private fun Content(
modifier = modifier,
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing16),
contentPadding = PaddingValues(
top = TangemTheme.dimens.spacing16,
top = TangemTheme.dimens.spacing12,
bottom = TangemTheme.dimens.spacing16,
),
) {
item {
Text(
modifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing16),
text = stringResource(R.string.details_title),
style = TangemTheme.typography.h1,
color = TangemTheme.colors.text.primary1,
)
}
items(
items = state.items,
key = DetailsItemUM::id,

View file

@ -25,8 +25,8 @@ 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
import com.tangem.core.ui.components.appbar.TangemTopAppBar
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
import com.tangem.core.ui.components.buttons.common.TangemButtonColors
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.res.TangemColorPalette
@ -57,14 +57,14 @@ internal fun DisclaimerScreen(state: DisclaimerUM) {
.statusBarsPadding(),
) {
Column(modifier = Modifier.padding(bottom = bottomPadding)) {
AppBarWithAdditionalButtons(
text = resourceReference(R.string.disclaimer_title),
startButton = AdditionalButton(
TangemTopAppBar(
title = resourceReference(R.string.disclaimer_title),
startButton = TopAppBarButtonUM(
iconRes = R.drawable.ic_back_24,
onIconClicked = state.popBack,
).takeIf { state.isTosAccepted },
textColor = textColor,
iconColor = iconColor,
iconTint = iconColor,
)
DisclaimerContent(state.url, state.isTosAccepted)
}

View file

@ -1,25 +1,35 @@
package com.tangem.feature.qrscanning.presentation
import android.content.Intent
import android.content.res.Configuration
import android.net.Uri
import android.provider.Settings
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.core.content.ContextCompat
import com.tangem.core.ui.components.SimpleSettingsRow
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.feature.qrscanning.impl.R
@Composable
fun CameraDeniedBottomSheet(config: TangemBottomSheetConfig) {
TangemBottomSheet(config) { content: CameraDeniedBottomSheetConfig ->
TangemBottomSheet(
config = config,
title = {
CameraDeniedBottomSheetHeader()
},
) { content: CameraDeniedBottomSheetConfig ->
CameraDeniedBottomSheet(content = content)
}
}
@ -28,7 +38,6 @@ fun CameraDeniedBottomSheet(config: TangemBottomSheetConfig) {
private fun CameraDeniedBottomSheet(content: CameraDeniedBottomSheetConfig) {
val context = LocalContext.current
Column {
CameraDeniedBottomSheetHeader()
SimpleSettingsRow(
title = stringResource(id = R.string.qr_scanner_camera_denied_settings_button),
icon = R.drawable.ic_settings_24,
@ -55,28 +64,45 @@ private fun CameraDeniedBottomSheet(content: CameraDeniedBottomSheetConfig) {
}
@Composable
private fun CameraDeniedBottomSheetHeader() {
Text(
text = stringResource(id = R.string.qr_scanner_camera_denied_title),
style = TangemTheme.typography.subtitle1,
color = TangemTheme.colors.text.primary1,
modifier = Modifier
private fun CameraDeniedBottomSheetHeader(modifier: Modifier = Modifier) {
Column(
modifier = modifier
.padding(
start = TangemTheme.dimens.spacing20,
end = TangemTheme.dimens.spacing20,
top = TangemTheme.dimens.spacing16,
vertical = TangemTheme.dimens.spacing16,
horizontal = TangemTheme.dimens.spacing20,
),
)
Text(
text = stringResource(id = R.string.qr_scanner_camera_denied_text),
style = TangemTheme.typography.body2,
color = TangemTheme.colors.text.secondary,
modifier = Modifier
.padding(
start = TangemTheme.dimens.spacing20,
end = TangemTheme.dimens.spacing20,
top = TangemTheme.dimens.spacing3,
bottom = TangemTheme.dimens.spacing16,
horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing4),
) {
Text(
text = stringResource(id = R.string.qr_scanner_camera_denied_title),
style = TangemTheme.typography.subtitle1,
color = TangemTheme.colors.text.primary1,
)
Text(
text = stringResource(id = R.string.qr_scanner_camera_denied_text),
style = TangemTheme.typography.body2,
color = TangemTheme.colors.text.secondary,
)
}
}
// region Preview
@Composable
@Preview(showBackground = true)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
private fun Preview_CameraDeniedBottomSheet() {
TangemThemePreview {
CameraDeniedBottomSheet(
config = TangemBottomSheetConfig(
isShow = true,
onDismissRequest = {},
content = CameraDeniedBottomSheetConfig(
onCancelClick = {},
onGalleryClick = {},
),
),
)
}
)
}
}
// endregion Preview

View file

@ -6,11 +6,9 @@ import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.material3.Icon
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
@ -20,12 +18,13 @@ import androidx.compose.ui.graphics.PathEffect
import androidx.compose.ui.graphics.StrokeJoin
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.drawText
import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.Constraints
import com.tangem.core.ui.components.appbar.AppBarWithBackButtonAndIconContent
import com.tangem.core.ui.components.appbar.TangemTopAppBar
import com.tangem.core.ui.components.appbar.TopAppBarButton
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemColorPalette
@ -59,46 +58,37 @@ internal fun QrScanningContent(
Overlay(
message = uiState.message,
)
AppBarWithBackButtonAndIconContent(
onBackClick = uiState.onBackClick,
TangemTopAppBar(
modifier = Modifier.statusBarsPadding(),
backgroundColor = Color.Transparent,
backIconTint = TangemColorPalette.White,
iconContent = {
Row {
AnimatedContent(
targetState = isFlash,
transitionSpec = { fadeIn().togetherWith(fadeOut()) },
label = "Flash Change",
) {
val flashIconRes = if (it) R.drawable.ic_flash_on_24 else R.drawable.ic_flash_off_24
Icon(
painter = painterResource(flashIconRes),
contentDescription = null,
modifier = Modifier
.padding(end = TangemTheme.dimens.spacing20)
.size(size = TangemTheme.dimens.size24)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(bounded = false),
onClick = { isFlash = !isFlash },
),
tint = TangemColorPalette.White,
)
}
Icon(
painter = painterResource(R.drawable.ic_gallery_24),
contentDescription = null,
modifier = Modifier
.size(size = TangemTheme.dimens.size24)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(bounded = false),
onClick = uiState.onGalleryClick,
),
title = null,
startButton = TopAppBarButtonUM.Back(uiState.onBackClick),
iconTint = TangemColorPalette.White,
containerColor = Color.Transparent,
endContent = {
AnimatedContent(
targetState = isFlash,
transitionSpec = { fadeIn().togetherWith(fadeOut()) },
label = "Flash Change",
) {
TopAppBarButton(
button = TopAppBarButtonUM(
iconRes = if (it) R.drawable.ic_flash_on_24 else R.drawable.ic_flash_off_24,
onIconClicked = {
isFlash = !isFlash
},
),
tint = TangemColorPalette.White,
)
}
TopAppBarButton(
button = TopAppBarButtonUM(
iconRes = R.drawable.ic_gallery_24,
onIconClicked = uiState.onGalleryClick,
),
tint = TangemColorPalette.White,
)
},
)
if (uiState.bottomSheetConfig != null) {

View file

@ -13,7 +13,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
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.components.appbar.TangemTopAppBar
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.feature.referral.presentation.R
@ -32,7 +32,7 @@ internal fun AgreementBottomSheetContent(url: String) {
.fillMaxSize()
.verticalScroll(rememberScrollState()),
) {
AppBarWithAdditionalButtons(text = stringResource(id = R.string.details_referral_title))
TangemTopAppBar(title = stringResource(id = R.string.details_referral_title))
AgreementHtmlView(url = url)
Spacer(modifier = Modifier.height(bottomBarHeight))
}

View file

@ -1,5 +1,6 @@
package com.tangem.features.staking.impl.presentation.ui.bottomsheet
import android.content.res.Configuration
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
@ -7,23 +8,29 @@ import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.tangem.core.ui.components.appbar.AppBar
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetTitle
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.staking.impl.presentation.state.bottomsheet.StakingInfoBottomSheetConfig
@Composable
fun StakingInfoBottomSheet(config: TangemBottomSheetConfig) {
val scrollState = rememberScrollState()
TangemBottomSheet(
TangemBottomSheet<StakingInfoBottomSheetConfig>(
config = config,
) { content: StakingInfoBottomSheetConfig ->
title = { content ->
TangemBottomSheetTitle(title = content.title)
},
) { content ->
Column(
modifier = Modifier.verticalScroll(scrollState),
) {
AppBar(text = content.title)
Text(
text = content.text.resolveReference(),
color = TangemTheme.colors.text.secondary,
@ -35,4 +42,33 @@ fun StakingInfoBottomSheet(config: TangemBottomSheetConfig) {
)
}
}
}
}
// region Preview
@Composable
@Preview(showBackground = true)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
private fun Preview_StakingInfoBottomSheet() {
TangemThemePreview {
StakingInfoBottomSheet(
config = TangemBottomSheetConfig(
isShow = true,
onDismissRequest = {},
content = StakingInfoBottomSheetConfig(
title = stringReference("Title"),
text = stringReference(
"""
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce varius neque vel ligula
tincidunt, nec faucibus nulla ultricies. Maecenas euismod arcu in nunc volutpat,
at bibendum eros lacinia. Proin hendrerit massa non velit congue,
in volutpat nisi consequat. Sed vitae justo nec orci tincidunt malesuada.
Nullam feugiat purus vel lectus efficitur, vel fringilla urna volutpat.
Donec sagittis enim in metus lacinia, vel tempor nunc bibendum.
""".trimIndent(),
),
),
),
)
}
}
// endregion Preview

View file

@ -1,6 +1,6 @@
package com.tangem.feature.swap.analytics
import com.tangem.common.ui.bottomsheets.state.ApproveType
import com.tangem.common.ui.bottomsheet.permission.state.ApproveType
import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.feature.swap.domain.models.domain.SwapProvider
import com.tangem.feature.swap.domain.models.ui.FeeType

View file

@ -3,7 +3,7 @@ package com.tangem.feature.swap.models
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.compose.ui.text.input.TextFieldValue
import com.tangem.common.ui.bottomsheets.state.GiveTxPermissionState
import com.tangem.common.ui.bottomsheet.permission.state.GiveTxPermissionState
import com.tangem.core.ui.R
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.components.notifications.NotificationConfig

View file

@ -1,6 +1,6 @@
package com.tangem.feature.swap.models
import com.tangem.common.ui.bottomsheets.state.ApproveType
import com.tangem.common.ui.bottomsheet.permission.state.ApproveType
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.feature.swap.domain.models.SwapAmount
import com.tangem.feature.swap.domain.models.ui.TxFee

View file

@ -1,12 +1,11 @@
package com.tangem.feature.swap.ui
import android.content.res.Configuration
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.ClickableText
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.stringResource
@ -15,12 +14,12 @@ import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.components.SpacerH24
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.components.rows.SelectorRowItem
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
@ -35,6 +34,7 @@ fun ChooseFeeBottomSheet(config: TangemBottomSheetConfig) {
TangemBottomSheet(
config = config,
containerColor = TangemTheme.colors.background.tertiary,
titleText = resourceReference(R.string.common_fee_selector_title),
) { content: ChooseFeeBottomSheetConfig ->
ChooseFeeBottomSheetContent(content = content)
}
@ -47,14 +47,6 @@ private fun ChooseFeeBottomSheetContent(content: ChooseFeeBottomSheetConfig) {
.background(TangemTheme.colors.background.tertiary)
.padding(bottom = TangemTheme.dimens.spacing8),
) {
Text(
text = stringResource(R.string.common_fee_selector_title),
style = TangemTheme.typography.subtitle1,
color = TangemTheme.colors.text.primary1,
modifier = Modifier
.padding(top = TangemTheme.dimens.spacing10)
.align(Alignment.CenterHorizontally),
)
Column(
modifier = Modifier
.padding(TangemTheme.dimens.spacing16)
@ -145,9 +137,11 @@ private fun FeeItemsBlock(content: ChooseFeeBottomSheetConfig) {
}
}
@Preview
// region Preview
@Composable
private fun ChooseFeeBottomSheetContent_Preview() {
@Preview(showBackground = true)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
private fun Preview_ChooseFeeBottomSheet() {
val feeItems = listOf(
FeeItemState.Content(
feeType = FeeType.NORMAL,
@ -168,33 +162,23 @@ private fun ChooseFeeBottomSheetContent_Preview() {
onClick = {},
),
).toImmutableList()
Column {
TangemThemePreview(isDark = true) {
ChooseFeeBottomSheetContent(
ChooseFeeBottomSheetConfig(
selectedFee = FeeType.NORMAL,
onSelectFeeType = {},
feeItems = feeItems,
readMore = stringReference("Read more"),
readMoreUrl = "",
onReadMoreClick = {},
),
)
}
val content = ChooseFeeBottomSheetConfig(
selectedFee = FeeType.NORMAL,
onSelectFeeType = {},
feeItems = feeItems,
readMore = stringReference("Read more"),
readMoreUrl = "",
onReadMoreClick = {},
)
SpacerH24()
TangemThemePreview(isDark = false) {
ChooseFeeBottomSheetContent(
ChooseFeeBottomSheetConfig(
selectedFee = FeeType.NORMAL,
onSelectFeeType = {},
feeItems = feeItems,
readMore = stringReference("Read more"),
readMoreUrl = "",
onReadMoreClick = {},
),
)
}
TangemThemePreview {
ChooseFeeBottomSheet(
config = TangemBottomSheetConfig(
isShow = true,
onDismissRequest = {},
content = content,
),
)
}
}
}
// endregion Preview

View file

@ -1,5 +1,6 @@
package com.tangem.feature.swap.ui
import android.content.res.Configuration
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
@ -16,6 +17,7 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
@ -23,13 +25,14 @@ import com.tangem.feature.swap.models.states.ChooseProviderBottomSheetConfig
import com.tangem.feature.swap.models.states.PercentDifference
import com.tangem.feature.swap.models.states.ProviderState
import com.tangem.feature.swap.presentation.R
import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.persistentListOf
@Composable
fun ChooseProviderBottomSheet(config: TangemBottomSheetConfig) {
TangemBottomSheet(
config = config,
containerColor = TangemTheme.colors.background.tertiary,
titleText = resourceReference(R.string.express_choose_providers_title),
) { content: ChooseProviderBottomSheetConfig ->
ChooseProviderBottomSheetContent(content = content)
}
@ -39,13 +42,6 @@ fun ChooseProviderBottomSheet(config: TangemBottomSheetConfig) {
@Composable
private fun ChooseProviderBottomSheetContent(content: ChooseProviderBottomSheetConfig) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(
text = stringResource(R.string.express_choose_providers_title),
style = TangemTheme.typography.subtitle1,
color = TangemTheme.colors.text.primary1,
modifier = Modifier
.padding(top = TangemTheme.dimens.spacing10),
)
Text(
text = stringResource(R.string.express_choose_providers_subtitle),
style = TangemTheme.typography.caption2,
@ -104,10 +100,12 @@ private fun ChooseProviderBottomSheetContent(content: ChooseProviderBottomSheetC
}
}
@Preview
// region Preview
@Composable
private fun ChooseProviderBottomSheet_Preview() {
val providers = listOf(
@Preview(showBackground = true)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
private fun Preview_ChooseProviderBottomSheet() {
val providers = persistentListOf(
ProviderState.Content(
id = "1",
name = "1inch",
@ -129,12 +127,18 @@ private fun ChooseProviderBottomSheet_Preview() {
alertText = stringReference("Unavailable"),
),
)
TangemThemePreview(isDark = false) {
ChooseProviderBottomSheetContent(
ChooseProviderBottomSheetConfig(
selectedProviderId = "1",
providers = providers.toImmutableList(),
val content = ChooseProviderBottomSheetConfig(
selectedProviderId = "1",
providers = providers,
)
TangemThemePreview {
ChooseProviderBottomSheet(
TangemBottomSheetConfig(
isShow = true,
onDismissRequest = {},
content = content,
),
)
}
}
}
// endregion Preview

View file

@ -2,7 +2,7 @@ package com.tangem.feature.swap.ui
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.input.TextFieldValue
import com.tangem.common.ui.bottomsheets.state.*
import com.tangem.common.ui.bottomsheet.permission.state.*
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
import com.tangem.core.ui.components.notifications.NotificationConfig

View file

@ -1,13 +1,14 @@
package com.tangem.feature.swap.ui
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import com.tangem.common.ui.bottomsheets.GiveTxPermissionBottomSheet
import com.tangem.common.ui.bottomsheets.state.GiveTxPermissionBottomSheetConfig
import com.tangem.common.ui.bottomsheet.permission.GiveTxPermissionBottomSheet
import com.tangem.common.ui.bottomsheet.permission.state.GiveTxPermissionBottomSheetConfig
import com.tangem.core.ui.components.appbar.AppBarWithBackButton
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.utils.WindowInsetsZero

View file

@ -23,7 +23,7 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.constraintlayout.compose.ConstraintLayout
import com.tangem.common.ui.bottomsheets.state.GiveTxPermissionState
import com.tangem.common.ui.bottomsheet.permission.state.GiveTxPermissionState
import com.tangem.core.ui.components.*
import com.tangem.core.ui.components.notifications.Notification
import com.tangem.core.ui.components.notifications.NotificationConfig

View file

@ -1,6 +1,6 @@
package com.tangem.feature.swap.viewmodels
import com.tangem.common.ui.bottomsheets.state.ApproveType
import com.tangem.common.ui.bottomsheet.permission.state.ApproveType
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.feature.swap.domain.models.domain.SwapDataModel
import com.tangem.feature.swap.domain.models.domain.SwapProvider

View file

@ -9,7 +9,7 @@ import arrow.core.Either
import arrow.core.getOrElse
import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.bundle.unbundle
import com.tangem.common.ui.bottomsheets.state.ApproveType
import com.tangem.common.ui.bottomsheet.permission.state.ApproveType
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.Basic

View file

@ -6,22 +6,20 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
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.components.appbar.models.TopAppBarMedium
import com.tangem.core.ui.components.appbar.TangemTopAppBar
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
import com.tangem.core.ui.components.block.BlockCard
import com.tangem.core.ui.components.block.BlockItem
import com.tangem.core.ui.components.snackbar.TangemSnackbarHost
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.res.LocalSnackbarHostState
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
@ -30,7 +28,6 @@ import com.tangem.feature.walletsettings.entity.WalletSettingsItemUM
import com.tangem.feature.walletsettings.entity.WalletSettingsUM
import com.tangem.feature.walletsettings.impl.R
@OptIn(ExperimentalMaterial3Api::class)
@Composable
internal fun WalletSettingsScreen(
state: WalletSettingsUM,
@ -38,12 +35,11 @@ internal fun WalletSettingsScreen(
modifier: Modifier = Modifier,
) {
val backgroundColor = TangemTheme.colors.background.secondary
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
BackHandler(onBack = state.popBack)
Scaffold(
modifier = modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
modifier = modifier,
containerColor = backgroundColor,
snackbarHost = {
TangemSnackbarHost(
@ -52,10 +48,9 @@ internal fun WalletSettingsScreen(
)
},
topBar = {
TopAppBarMedium(
title = resourceReference(R.string.wallet_settings_title),
scrollBehavior = scrollBehavior,
onBackClick = state.popBack,
TangemTopAppBar(
modifier = Modifier.statusBarsPadding(),
startButton = TopAppBarButtonUM.Back(state.popBack),
)
},
content = { paddingValues ->
@ -79,11 +74,21 @@ private fun Content(state: WalletSettingsUM, modifier: Modifier = Modifier) {
bottom = TangemTheme.dimens.spacing16,
),
) {
item {
Text(
modifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing16),
text = stringResource(id = R.string.wallet_settings_title),
style = TangemTheme.typography.h1,
color = TangemTheme.colors.text.primary1,
)
}
items(
items = state.items,
key = WalletSettingsItemUM::id,
) { item ->
val itemModifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing16)
val itemModifier = Modifier
.padding(horizontal = TangemTheme.dimens.spacing16)
.fillMaxWidth()
when (item) {
is WalletSettingsItemUM.WithItems -> ItemsBlock(
@ -117,7 +122,10 @@ private fun ItemsBlock(model: WalletSettingsItemUM.WithItems, modifier: Modifier
verticalArrangement = Arrangement.Top,
) {
model.blocks.forEach { block ->
BlockItem(model = block)
BlockItem(
modifier = Modifier.fillMaxWidth(),
model = block,
)
}
}