Updated on 2026-08-14

This commit is contained in:
Tangem 2023-09-20 21:51:44 +08:00
parent 4c903fc654
commit 1485cebb6b
14 changed files with 420 additions and 397 deletions

View file

@ -1,9 +1,7 @@
package com.tangem.core.ui.components.notifications
import androidx.annotation.DrawableRes
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.LocalIndication
import androidx.compose.foundation.clickable
@ -25,9 +23,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
import com.tangem.core.ui.R
import com.tangem.core.ui.components.PrimaryButton
import com.tangem.core.ui.components.PrimaryButtonIconEnd
import com.tangem.core.ui.components.SecondaryButton
import com.tangem.core.ui.components.*
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
@ -46,7 +42,7 @@ import com.tangem.core.ui.components.notifications.NotificationConfig.ButtonsSta
*/
@Composable
fun Notification(config: NotificationConfig, modifier: Modifier = Modifier, iconTint: Color? = null) {
BaseContainer(buttonsState = config.buttonsState, modifier = modifier) {
BaseContainer(buttonsState = config.buttonsState, onClick = config.onClick, modifier = modifier) {
Column(
modifier = Modifier.padding(all = TangemTheme.dimens.spacing12),
verticalArrangement = Arrangement.spacedBy(space = TangemTheme.dimens.spacing12),
@ -56,6 +52,7 @@ fun Notification(config: NotificationConfig, modifier: Modifier = Modifier, icon
iconTint = iconTint,
title = config.title,
subtitle = config.subtitle,
isClickableComponent = config.onClick != null,
)
Buttons(state = config.buttonsState)
@ -71,11 +68,12 @@ fun Notification(config: NotificationConfig, modifier: Modifier = Modifier, icon
@Composable
private fun BaseContainer(
buttonsState: NotificationConfig.ButtonsState?,
onClick: (() -> Unit)?,
modifier: Modifier = Modifier,
content: @Composable BoxScope.() -> Unit,
) {
val containerColor by rememberUpdatedState(
newValue = if (buttonsState != null) {
newValue = if (buttonsState != null || onClick != null) {
TangemTheme.colors.background.primary
} else {
TangemTheme.colors.button.disabled
@ -83,9 +81,11 @@ private fun BaseContainer(
)
Surface(
onClick = onClick ?: {},
modifier = modifier
.defaultMinSize(minHeight = TangemTheme.dimens.size62)
.fillMaxWidth(),
enabled = onClick != null,
shape = TangemTheme.shapes.roundedCornersXMedium,
color = containerColor,
) {
@ -94,15 +94,36 @@ private fun BaseContainer(
}
@Composable
private fun MainContent(iconResId: Int, iconTint: Color?, title: TextReference, subtitle: TextReference) {
Row(horizontalArrangement = Arrangement.spacedBy(space = TangemTheme.dimens.spacing10)) {
private fun MainContent(
iconResId: Int,
iconTint: Color?,
title: TextReference,
subtitle: TextReference,
isClickableComponent: Boolean,
) {
Row {
Icon(
iconResId = iconResId,
tint = iconTint,
modifier = Modifier.align(alignment = Alignment.CenterVertically),
)
SpacerW(width = TangemTheme.dimens.spacing10)
TextsBlock(title = title, subtitle = subtitle)
if (isClickableComponent) {
SpacerWMax()
Icon(
painter = painterResource(id = R.drawable.ic_chevron_right_24),
contentDescription = null,
modifier = Modifier
.size(size = TangemTheme.dimens.size20)
.align(alignment = Alignment.CenterVertically),
tint = TangemTheme.colors.icon.informative,
)
}
}
}
@ -130,7 +151,7 @@ private fun TextsBlock(title: TextReference, subtitle: TextReference) {
Text(
text = title.resolveReference(),
color = TangemTheme.colors.text.primary1,
style = TangemTheme.typography.body2,
style = TangemTheme.typography.button,
)
Text(
@ -141,16 +162,13 @@ private fun TextsBlock(title: TextReference, subtitle: TextReference) {
}
}
@OptIn(ExperimentalAnimationApi::class)
@Composable
private fun Buttons(state: NotificationButtonsState?) {
AnimatedContent(targetState = state, label = "Update the buttons content") { animatedState ->
when (animatedState) {
is NotificationButtonsState.SecondaryButtonConfig -> SingleSecondaryButton(config = animatedState)
is NotificationButtonsState.PrimaryButtonConfig -> SinglePrimaryButton(config = animatedState)
is NotificationButtonsState.PairButtonsConfig -> PairButtons(config = animatedState)
null -> Unit
}
when (state) {
is NotificationButtonsState.SecondaryButtonConfig -> SingleSecondaryButton(config = state)
is NotificationButtonsState.PrimaryButtonConfig -> SinglePrimaryButton(config = state)
is NotificationButtonsState.PairButtonsConfig -> PairButtons(config = state)
null -> Unit
}
}
@ -266,6 +284,12 @@ private class NotificationConfigProvider : CollectionPreviewParameterProvider<No
subtitle = TextReference.Str(value = "Check your network connection"),
iconResId = R.drawable.img_attention_20,
),
NotificationConfig(
title = TextReference.Str(value = "Used card"),
subtitle = TextReference.Str(value = "The card signed transactions in the past"),
iconResId = R.drawable.ic_alert_circle_24,
onClick = {},
),
NotificationConfig(
title = TextReference.Str(value = "Your wallet hasnt been backed up"),
subtitle = TextReference.Str(value = "To protect your assets, we advise you to carry out this procedure"),

View file

@ -10,6 +10,7 @@ import com.tangem.core.ui.extensions.TextReference
* @property subtitle subtitle
* @property iconResId icon resource id
* @property buttonsState buttons state
* @property onClick lambda be invoked when notification is clicked
* @property onCloseClick lambda be invoked when close button is clicked
*
[REDACTED_AUTHOR]
@ -19,6 +20,7 @@ data class NotificationConfig(
val subtitle: TextReference,
@DrawableRes val iconResId: Int,
val buttonsState: ButtonsState? = null,
val onClick: (() -> Unit)? = null,
val onCloseClick: (() -> Unit)? = null,
) {

View file

@ -109,7 +109,13 @@ fun combinedReference(refs: WrappedList<TextReference>): TextReference {
@ReadOnlyComposable
fun TextReference.resolveReference(): String {
return when (this) {
is TextReference.Res -> stringResource(id, *formatArgs.toTypedArray())
is TextReference.Res -> {
val args = formatArgs
.map { if (it is TextReference) it.resolveReference() else it }
.toTypedArray()
stringResource(id = id, *args)
}
is TextReference.PluralRes -> pluralStringResource(id, count, *formatArgs.toTypedArray())
is TextReference.Str -> value
is TextReference.Combined -> {
@ -125,7 +131,13 @@ fun TextReference.resolveReference(): String {
/** Resolve [TextReference] as [String] using [resources] (non-composable context) */
fun TextReference.resolveReference(resources: Resources): String {
return when (this) {
is TextReference.Res -> resources.getString(id, *formatArgs.toTypedArray())
is TextReference.Res -> {
val args = formatArgs
.map { if (it is TextReference) it.resolveReference(resources) else it }
.toTypedArray()
resources.getString(id, *args)
}
is TextReference.PluralRes -> resources.getQuantityString(id, count, *formatArgs.toTypedArray())
is TextReference.Str -> value
is TextReference.Combined -> {