Updated on 2026-08-14
This commit is contained in:
commit
4ded391291
7 changed files with 62 additions and 27 deletions
|
|
@ -8,6 +8,7 @@ import androidx.compose.runtime.Immutable
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import coil.compose.SubcomposeAsyncImage
|
||||
import coil.request.ImageRequest
|
||||
|
|
@ -74,7 +75,7 @@ fun TangemIcon(tangemIconUM: TangemIconUM, modifier: Modifier = Modifier) {
|
|||
tint = tangemIconUM.tintReference(),
|
||||
)
|
||||
is TangemIconUM.Image -> Image(
|
||||
imageVector = ImageVector.vectorResource(tangemIconUM.imageRes),
|
||||
painter = painterResource(tangemIconUM.imageRes),
|
||||
contentDescription = null,
|
||||
modifier = modifier,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ fun TangemMessage(
|
|||
Alignment.Top
|
||||
},
|
||||
)
|
||||
.size(TangemTheme.dimens2.x7),
|
||||
.size(messageUM.iconSize),
|
||||
)
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -6,10 +6,7 @@ import androidx.compose.foundation.background
|
|||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableFloatStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.draw.drawWithContent
|
||||
|
|
@ -25,6 +22,7 @@ import androidx.compose.ui.unit.dp
|
|||
import com.tangem.core.ui.components.haze.hazeForegroundEffectTangem
|
||||
import com.tangem.core.ui.extensions.conditionalCompose
|
||||
import com.tangem.core.ui.res.LocalIsInDarkTheme
|
||||
import com.tangem.core.ui.res.LocalMessageEffectAnimation
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||
import com.tangem.core.ui.utils.toPx
|
||||
|
|
@ -33,6 +31,10 @@ import dev.chrisbanes.haze.HazeTint
|
|||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
data class MessageEffectAnimation(
|
||||
val offsetState: State<Float>,
|
||||
)
|
||||
|
||||
/**
|
||||
* Different visual effects for [Tangem message component].
|
||||
*/
|
||||
|
|
@ -222,7 +224,6 @@ enum class TangemMessageEffect(val isAnimatable: Boolean) {
|
|||
}
|
||||
}
|
||||
|
||||
// todo redesign replace with proper color when design is ready
|
||||
@Suppress("MagicNumber")
|
||||
fun fallbackColor(isInDarkTheme: Boolean): Color {
|
||||
return when (this) {
|
||||
|
|
@ -242,12 +243,16 @@ internal fun Modifier.messageEffectBackground(
|
|||
contentColor: Color,
|
||||
): Modifier {
|
||||
val isInDarkTheme = LocalIsInDarkTheme.current
|
||||
val borderGradientColors = remember { messageEffect.getBorderGradient(isInDarkTheme) }
|
||||
val gradientColors = remember { messageEffect.getColorGradient(isInDarkTheme) }
|
||||
val gradientTint = remember { messageEffect.getGradientTint(isInDarkTheme) }
|
||||
val borderGradientColors = remember(messageEffect, isInDarkTheme) { messageEffect.getBorderGradient(isInDarkTheme) }
|
||||
val gradientColors = remember(messageEffect, isInDarkTheme) { messageEffect.getColorGradient(isInDarkTheme) }
|
||||
val gradientTint = remember(messageEffect, isInDarkTheme) { messageEffect.getGradientTint(isInDarkTheme) }
|
||||
|
||||
val angle by rememberAnimationAngle(messageEffect.isAnimatable)
|
||||
val brush = remember { Brush.sweepGradient(messageEffect.getColorGradient(isInDarkTheme)) }
|
||||
val angle by if (messageEffect.isAnimatable) {
|
||||
LocalMessageEffectAnimation.current.offsetState
|
||||
} else {
|
||||
remember { mutableFloatStateOf(0f) }
|
||||
}
|
||||
val brush = remember(gradientColors) { Brush.sweepGradient(gradientColors) }
|
||||
val padding = 1.dp.toPx()
|
||||
|
||||
return this
|
||||
|
|
@ -278,12 +283,14 @@ internal fun Modifier.messageEffectBackground(
|
|||
}
|
||||
.conditionalCompose(gradientColors.isNotEmpty()) {
|
||||
drawWithContent {
|
||||
rotate(angle) {
|
||||
drawCircle(
|
||||
brush = brush,
|
||||
radius = size.width,
|
||||
blendMode = BlendMode.SrcIn,
|
||||
)
|
||||
if (messageEffect.isAnimatable) {
|
||||
rotate(angle) {
|
||||
drawCircle(
|
||||
brush = brush,
|
||||
radius = size.width,
|
||||
blendMode = BlendMode.SrcIn,
|
||||
)
|
||||
}
|
||||
}
|
||||
drawRect(
|
||||
color = contentColor,
|
||||
|
|
@ -296,9 +303,9 @@ internal fun Modifier.messageEffectBackground(
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun rememberAnimationAngle(isAnimatable: Boolean) = if (isAnimatable) {
|
||||
internal fun rememberMessageEffectAnimationAngle(): MessageEffectAnimation {
|
||||
val infiniteTransition = rememberInfiniteTransition()
|
||||
infiniteTransition.animateFloat(
|
||||
val offsetState = infiniteTransition.animateFloat(
|
||||
initialValue = 0f,
|
||||
targetValue = 360f,
|
||||
animationSpec = infiniteRepeatable(
|
||||
|
|
@ -306,8 +313,10 @@ private fun rememberAnimationAngle(isAnimatable: Boolean) = if (isAnimatable) {
|
|||
repeatMode = RepeatMode.Restart,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
remember { mutableFloatStateOf(0f) }
|
||||
|
||||
return remember(offsetState) {
|
||||
MessageEffectAnimation(offsetState)
|
||||
}
|
||||
}
|
||||
|
||||
// region Preview
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package com.tangem.core.ui.ds.message
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.ds.button.*
|
||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
|
|
@ -10,12 +12,16 @@ import kotlinx.collections.immutable.persistentListOf
|
|||
/**
|
||||
* Data model representing the properties of a Tangem message.
|
||||
*
|
||||
* @param id Unique identifier for the message.
|
||||
* @param title TextReference for the message title.
|
||||
* @param subtitle TextReference for the message subtitle.
|
||||
* @param messageEffect TangemMessageEffect defining the visual effect of the message.
|
||||
* @param iconUM Optional TangemIconUM representing the icon to be displayed in the message.
|
||||
* @param iconSize Dp value defining the size of the icon (default is 28.dp).
|
||||
* @param isCentered Boolean indicating whether the icon is centered.
|
||||
* @param buttonsUM ImmutableList of TangemMessageButtonUM representing the buttons in the message.
|
||||
* @param onCloseClick Lambda to be invoked when the close button is clicked (optional
|
||||
* @param onClick Lambda to be invoked when the message is clicked (optional).
|
||||
* @param onCloseClick Lambda to be invoked when the close button is clicked (optional).
|
||||
*/
|
||||
data class TangemMessageUM(
|
||||
val id: String,
|
||||
|
|
@ -23,6 +29,7 @@ data class TangemMessageUM(
|
|||
val subtitle: TextReference,
|
||||
val messageEffect: TangemMessageEffect = TangemMessageEffect.None,
|
||||
val iconUM: TangemIconUM? = null,
|
||||
val iconSize: Dp = 28.dp,
|
||||
val isCentered: Boolean = false,
|
||||
val buttonsUM: ImmutableList<TangemMessageButtonUM> = persistentListOf(),
|
||||
val onClick: (() -> Unit)? = null,
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ import com.tangem.core.ui.components.powersaving.rememberPowerSavingState
|
|||
import com.tangem.core.ui.components.snackbar.TangemTopSnackbarHostState
|
||||
import com.tangem.core.ui.components.text.BladeAnimation
|
||||
import com.tangem.core.ui.components.text.rememberBladeAnimation
|
||||
import com.tangem.core.ui.ds.message.MessageEffectAnimation
|
||||
import com.tangem.core.ui.ds.message.rememberMessageEffectAnimationAngle
|
||||
import com.tangem.core.ui.haptic.DefaultHapticManager
|
||||
import com.tangem.core.ui.haptic.HapticManager
|
||||
import com.tangem.core.ui.haptic.VibratorHapticManager
|
||||
|
|
@ -128,6 +130,7 @@ fun TangemTheme(
|
|||
LocalBladeAnimation provides rememberBladeAnimation(),
|
||||
LocalSystemBarsIconsController provides systemBarsIconsController,
|
||||
LocalPowerSavingState provides rememberPowerSavingState(),
|
||||
LocalMessageEffectAnimation provides rememberMessageEffectAnimationAngle(),
|
||||
) {
|
||||
CompositionLocalProvider(
|
||||
LocalTangemShimmer provides TangemShimmer,
|
||||
|
|
@ -433,6 +436,10 @@ val LocalPowerSavingState = compositionLocalOf<PowerSavingState> {
|
|||
error("No PowerSavingState provided")
|
||||
}
|
||||
|
||||
val LocalMessageEffectAnimation = compositionLocalOf<MessageEffectAnimation> {
|
||||
error("No MessageEffectAnimation provided")
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the dark theme should be used based on the given [AppThemeMode].
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
|
||||
package com.tangem.feature.tester.presentation.storybook.page.message
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
|
|
@ -16,7 +17,10 @@ import androidx.compose.ui.unit.dp
|
|||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.ds.button.TangemButtonType
|
||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.ds.message.*
|
||||
import com.tangem.core.ui.ds.message.TangemMessage
|
||||
import com.tangem.core.ui.ds.message.TangemMessageButtonUM
|
||||
import com.tangem.core.ui.ds.message.TangemMessageEffect
|
||||
import com.tangem.core.ui.ds.message.TangemMessageUM
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemMessageStory
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.model
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.ds.button.TangemButtonType
|
||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.ds.message.TangemMessageButtonUM
|
||||
|
|
@ -196,7 +197,6 @@ internal sealed class WalletNotificationUM(val messageUM: TangemMessageUM, val t
|
|||
onClick = onConfirmClick,
|
||||
),
|
||||
),
|
||||
|
||||
),
|
||||
type = WalletNotificationType.Critical,
|
||||
)
|
||||
|
|
@ -379,8 +379,14 @@ internal sealed class WalletNotificationUM(val messageUM: TangemMessageUM, val t
|
|||
title = resourceReference(R.string.notification_one_plus_one_title),
|
||||
subtitle = resourceReference(R.string.notification_one_plus_one_text),
|
||||
messageEffect = TangemMessageEffect.Magic,
|
||||
onCloseClick = onCloseClick,
|
||||
iconUM = TangemIconUM.Image(R.drawable.img_one_plus_one_promo),
|
||||
iconSize = 54.dp,
|
||||
buttonsUM = persistentListOf(
|
||||
TangemMessageButtonUM(
|
||||
text = resourceReference(R.string.common_later),
|
||||
type = TangemButtonType.PrimaryInverse,
|
||||
onClick = onCloseClick,
|
||||
),
|
||||
TangemMessageButtonUM(
|
||||
text = resourceReference(R.string.notification_one_plus_one_button),
|
||||
type = TangemButtonType.Primary,
|
||||
|
|
@ -452,7 +458,8 @@ internal sealed class WalletNotificationUM(val messageUM: TangemMessageUM, val t
|
|||
id = "PushNotificationsNotification",
|
||||
title = resourceReference(R.string.user_push_notification_banner_title),
|
||||
subtitle = resourceReference(R.string.user_push_notification_banner_subtitle),
|
||||
onCloseClick = onCloseClick,
|
||||
iconUM = TangemIconUM.Image(R.drawable.img_push_reminder),
|
||||
iconSize = 54.dp,
|
||||
messageEffect = TangemMessageEffect.Magic,
|
||||
buttonsUM = persistentListOf(
|
||||
TangemMessageButtonUM(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue