Updated on 2026-08-14
This commit is contained in:
commit
f047db3304
7 changed files with 267 additions and 11 deletions
|
|
@ -114,6 +114,32 @@ fun PrimaryButtonIconEnd(
|
|||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* [Show in Figma](https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?type=design&node-id=68%3A20&mode=design&t=YXX8vqJcB9jn0wPp-1)
|
||||
* */
|
||||
@Composable
|
||||
fun PrimaryButtonIconEndTwoLines(
|
||||
text: String,
|
||||
@DrawableRes iconResId: Int,
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
showProgress: Boolean = false,
|
||||
enabled: Boolean = true,
|
||||
additionalText: String? = null,
|
||||
) {
|
||||
TangemButton(
|
||||
modifier = modifier,
|
||||
text = text,
|
||||
icon = TangemButtonIconPosition.End(iconResId),
|
||||
onClick = onClick,
|
||||
colors = TangemButtonsDefaults.primaryButtonColors,
|
||||
enabled = enabled,
|
||||
showProgress = showProgress,
|
||||
additionalText = additionalText,
|
||||
size = TangemButtonSize.TwoLines,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* [Show in Figma](https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?node-id=233%3A258&t=TmfD6UBHPg9uYfev-4)
|
||||
* */
|
||||
|
|
@ -261,6 +287,13 @@ private fun PrimaryButtonSample() {
|
|||
enabled = false,
|
||||
onClick = { },
|
||||
)
|
||||
PrimaryButtonIconEndTwoLines(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
text = "Manage tokens",
|
||||
iconResId = R.drawable.ic_tangem_24,
|
||||
onClick = { },
|
||||
additionalText = "Manage these tokens",
|
||||
)
|
||||
PrimaryButtonIconStart(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
text = "Manage tokens",
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ fun TangemButton(
|
|||
showProgress: Boolean,
|
||||
enabled: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
additionalText: String? = null,
|
||||
size: TangemButtonSize = TangemButtonSize.Default,
|
||||
elevation: ButtonElevation = TangemButtonsDefaults.elevation,
|
||||
textStyle: TextStyle = TangemTheme.typography.button,
|
||||
|
|
@ -73,6 +74,20 @@ fun TangemButton(
|
|||
contentDescription = null,
|
||||
)
|
||||
},
|
||||
additionalText = {
|
||||
if (additionalText != null) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
text = additionalText,
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.disabled,
|
||||
textAlign = TextAlign.Center,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -86,18 +101,27 @@ private inline fun RowScope.ButtonContentContainer(
|
|||
progressIndicator: @Composable RowScope.() -> Unit,
|
||||
text: @Composable RowScope.() -> Unit,
|
||||
icon: @Composable RowScope.(Int) -> Unit,
|
||||
additionalText: @Composable () -> Unit,
|
||||
) {
|
||||
if (showProgress) {
|
||||
progressIndicator()
|
||||
} else {
|
||||
if (buttonIcon is TangemButtonIconPosition.Start) {
|
||||
icon(buttonIcon.iconResId)
|
||||
Spacer(modifier = Modifier.requiredWidth(iconPadding))
|
||||
}
|
||||
text()
|
||||
if (buttonIcon is TangemButtonIconPosition.End) {
|
||||
Spacer(modifier = Modifier.requiredWidth(iconPadding))
|
||||
icon(buttonIcon.iconResId)
|
||||
Column {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
) {
|
||||
if (buttonIcon is TangemButtonIconPosition.Start) {
|
||||
icon(buttonIcon.iconResId)
|
||||
Spacer(modifier = Modifier.requiredWidth(iconPadding))
|
||||
}
|
||||
text()
|
||||
if (buttonIcon is TangemButtonIconPosition.End) {
|
||||
Spacer(modifier = Modifier.requiredWidth(iconPadding))
|
||||
icon(buttonIcon.iconResId)
|
||||
}
|
||||
}
|
||||
additionalText()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,12 +14,13 @@ enum class TangemButtonSize {
|
|||
Selector,
|
||||
Action,
|
||||
RoundedAction,
|
||||
TwoLines,
|
||||
}
|
||||
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
internal fun TangemButtonSize.toHeightDp(): Dp = when (this) {
|
||||
TangemButtonSize.Default -> TangemTheme.dimens.size48
|
||||
TangemButtonSize.Default, TangemButtonSize.TwoLines -> TangemTheme.dimens.size48
|
||||
TangemButtonSize.Text -> TangemTheme.dimens.size40
|
||||
TangemButtonSize.Selector -> TangemTheme.dimens.size24
|
||||
TangemButtonSize.Action,
|
||||
|
|
@ -34,13 +35,14 @@ internal fun TangemButtonSize.toShape(): Shape = when (this) {
|
|||
TangemButtonSize.Text -> TangemTheme.shapes.roundedCornersSmall
|
||||
TangemButtonSize.Selector -> TangemTheme.shapes.roundedCornersSmall
|
||||
TangemButtonSize.Action -> TangemTheme.shapes.roundedCornersMedium
|
||||
TangemButtonSize.TwoLines -> TangemTheme.shapes.roundedCornersXMedium
|
||||
TangemButtonSize.RoundedAction -> TangemTheme.shapes.roundedCornersLarge
|
||||
}
|
||||
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
internal fun TangemButtonSize.toIconPadding(): Dp = when (this) {
|
||||
TangemButtonSize.Default -> TangemTheme.dimens.spacing4
|
||||
TangemButtonSize.Default, TangemButtonSize.TwoLines -> TangemTheme.dimens.spacing4
|
||||
TangemButtonSize.Text -> TangemTheme.dimens.spacing8
|
||||
TangemButtonSize.Selector -> 0.dp
|
||||
TangemButtonSize.Action,
|
||||
|
|
@ -80,6 +82,12 @@ internal fun TangemButtonSize.toContentPadding(icon: TangemButtonIconPosition):
|
|||
start = horizontalPadding.first,
|
||||
end = horizontalPadding.second,
|
||||
)
|
||||
TangemButtonSize.TwoLines -> PaddingValues(
|
||||
top = TangemTheme.dimens.spacing6,
|
||||
bottom = TangemTheme.dimens.spacing6,
|
||||
start = horizontalPadding.first,
|
||||
end = horizontalPadding.second,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -87,7 +95,8 @@ internal fun TangemButtonSize.toContentPadding(icon: TangemButtonIconPosition):
|
|||
@ReadOnlyComposable
|
||||
internal fun TangemButtonSize.toHorizontalContentPadding(icon: TangemButtonIconPosition): Pair<Dp, Dp> {
|
||||
return when (this) {
|
||||
TangemButtonSize.Default -> TangemTheme.dimens.spacing32 to TangemTheme.dimens.spacing32
|
||||
TangemButtonSize.Default, TangemButtonSize.TwoLines ->
|
||||
TangemTheme.dimens.spacing32 to TangemTheme.dimens.spacing32
|
||||
TangemButtonSize.Text -> when (icon) {
|
||||
is TangemButtonIconPosition.None -> TangemTheme.dimens.spacing16 to TangemTheme.dimens.spacing16
|
||||
is TangemButtonIconPosition.Start -> TangemTheme.dimens.spacing14 to TangemTheme.dimens.spacing16
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ data class NotificationConfig(
|
|||
|
||||
data class PrimaryButtonConfig(
|
||||
val text: TextReference,
|
||||
val additionalText: TextReference? = null,
|
||||
@DrawableRes val iconResId: Int? = null,
|
||||
val onClick: () -> Unit,
|
||||
) : ButtonsState()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
package com.tangem.managetokens.presentation.managetokens.state
|
||||
|
||||
import com.tangem.core.ui.components.notifications.NotificationConfig
|
||||
import com.tangem.core.ui.extensions.pluralReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.features.managetokens.impl.R
|
||||
|
||||
data class DerivationNotificationState(
|
||||
val totalNeeded: Int,
|
||||
val missingAddressesCount: Int,
|
||||
val onGenerateClick: () -> Unit,
|
||||
) {
|
||||
val config = NotificationConfig(
|
||||
title = resourceReference(id = R.string.warning_missing_derivation_title),
|
||||
subtitle = pluralReference(
|
||||
id = R.plurals.warning_missing_derivation_message,
|
||||
count = totalNeeded,
|
||||
formatArgs = wrappedList(totalNeeded),
|
||||
),
|
||||
iconResId = R.drawable.ic_alert_circle_24,
|
||||
buttonsState = NotificationConfig.ButtonsState.PrimaryButtonConfig(
|
||||
text = resourceReference(id = R.string.common_generate_addresses),
|
||||
iconResId = R.drawable.ic_tangem_24,
|
||||
onClick = onGenerateClick,
|
||||
// TODO: enable when we find how to use this type of strings with plurals on Localise
|
||||
// Task: [REDACTED_JIRA]
|
||||
// additionalText = pluralReference(
|
||||
// id = R.plurals.manage_tokens_number_of_wallets,
|
||||
// count = totalNeeded,
|
||||
// formatArgs = wrappedList(missingAddressesCount, totalNeeded)
|
||||
// )
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package com.tangem.managetokens.presentation.managetokens.state.previewdata
|
||||
|
||||
import com.tangem.managetokens.presentation.managetokens.state.DerivationNotificationState
|
||||
|
||||
object DerivationNotificationStatePreviewData {
|
||||
val state = DerivationNotificationState(
|
||||
totalNeeded = 3,
|
||||
missingAddressesCount = 2,
|
||||
onGenerateClick = {},
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
package com.tangem.managetokens.presentation.managetokens.ui.components
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material3.Text
|
||||
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.res.painterResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.core.ui.components.PrimaryButtonIconEndTwoLines
|
||||
import com.tangem.core.ui.components.SpacerW
|
||||
import com.tangem.core.ui.components.notifications.NotificationConfig
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.managetokens.impl.R
|
||||
import com.tangem.managetokens.presentation.managetokens.state.previewdata.DerivationNotificationStatePreviewData
|
||||
|
||||
@Composable
|
||||
internal fun DerivationNotification(config: NotificationConfig, modifier: Modifier = Modifier) {
|
||||
BaseContainer(
|
||||
modifier = modifier,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(all = TangemTheme.dimens.spacing16),
|
||||
verticalArrangement = Arrangement.spacedBy(space = TangemTheme.dimens.spacing16),
|
||||
) {
|
||||
MainContent(
|
||||
iconResId = config.iconResId,
|
||||
iconTint = TangemTheme.colors.icon.accent,
|
||||
title = config.title,
|
||||
subtitle = config.subtitle,
|
||||
)
|
||||
val buttonConfig = config.buttonsState
|
||||
if (buttonConfig is NotificationConfig.ButtonsState.PrimaryButtonConfig) {
|
||||
PrimaryButtonIconEndTwoLines(
|
||||
text = buttonConfig.text.resolveReference(),
|
||||
iconResId = buttonConfig.iconResId ?: R.drawable.ic_tangem_24,
|
||||
onClick = buttonConfig.onClick,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
additionalText = buttonConfig.additionalText?.resolveReference(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BaseContainer(modifier: Modifier = Modifier, content: @Composable BoxScope.() -> Unit) {
|
||||
Card(
|
||||
modifier = modifier
|
||||
.defaultMinSize(minHeight = TangemTheme.dimens.size62)
|
||||
.fillMaxWidth(),
|
||||
shape = RoundedCornerShape(
|
||||
topStart = TangemTheme.dimens.radius16,
|
||||
topEnd = TangemTheme.dimens.radius16,
|
||||
),
|
||||
elevation = TangemTheme.dimens.elevation12,
|
||||
backgroundColor = TangemTheme.colors.background.action,
|
||||
) {
|
||||
Box(content = content)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MainContent(iconResId: Int, iconTint: Color, title: TextReference, subtitle: TextReference) {
|
||||
Row {
|
||||
NotificationIcon(iconResId = iconResId, iconTint = iconTint)
|
||||
SpacerW(width = TangemTheme.dimens.spacing10)
|
||||
TextsBlock(title = title, subtitle = subtitle)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RowScope.NotificationIcon(iconResId: Int, iconTint: Color) {
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier
|
||||
.align(alignment = Alignment.CenterVertically),
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(TangemTheme.dimens.size36)
|
||||
.background(
|
||||
color = iconTint.copy(alpha = 0.12f),
|
||||
shape = CircleShape,
|
||||
),
|
||||
)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(TangemTheme.dimens.size16)
|
||||
.background(
|
||||
color = TangemTheme.colors.background.action,
|
||||
shape = CircleShape,
|
||||
),
|
||||
)
|
||||
Icon(
|
||||
painter = painterResource(id = iconResId),
|
||||
contentDescription = null,
|
||||
tint = iconTint,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TextsBlock(title: TextReference, subtitle: TextReference) {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(space = TangemTheme.dimens.spacing2)) {
|
||||
Text(
|
||||
text = title.resolveReference(),
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.button,
|
||||
)
|
||||
|
||||
Text(
|
||||
text = subtitle.resolveReference(),
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
style = TangemTheme.typography.caption2,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun Preview_ManageTokensScreen_LightTheme() {
|
||||
TangemTheme(isDark = false) {
|
||||
DerivationNotification(DerivationNotificationStatePreviewData.state.config)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun Preview_ManageTokensScreen_DarkTheme() {
|
||||
TangemTheme(isDark = true) {
|
||||
DerivationNotification(DerivationNotificationStatePreviewData.state.config)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue