Exchange rate design implementation

This commit is contained in:
Milan Cerovsky 2024-08-07 12:13:17 +02:00
parent 72d2e5b478
commit 0cf64ae202
6 changed files with 115 additions and 27 deletions

View File

@ -0,0 +1,34 @@
@file:Suppress("MagicNumber")
package co.electriccoin.zcash.ui.design.theme
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.graphics.Color
@Immutable
data class ExchangeRateColors(
val btnSecondaryBg: Color,
val btnSecondaryBorder: Color,
val btnSecondaryFg: Color,
val btnSpinnerDisabled: Color
)
internal val LightExchangeRateColorPalette =
ExchangeRateColors(
btnSecondaryBg = Color(0xFFFFFFFF),
btnSecondaryBorder = Color(0xFFD9D8CF),
btnSecondaryFg = Color(0xFF4D4941),
btnSpinnerDisabled = Color(0x97989980)
)
internal val DarkExchangeRateColorPalette =
ExchangeRateColors(
btnSecondaryBg = Color(0xFF4B4144),
btnSecondaryBorder = Color(0xFF4B4144),
btnSecondaryFg = Color(0xFFFFFFFF),
btnSpinnerDisabled = Color(0xFF3D3A3B)
)
@Suppress("CompositionLocalAllowlist")
internal val LocalExchangeRateColors = staticCompositionLocalOf<ExchangeRateColors> { error("no colors specified") }

View File

@ -0,0 +1,31 @@
@file:Suppress("MagicNumber")
package co.electriccoin.zcash.ui.design.theme
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.graphics.Color
@Immutable
data class ZashiColors(
val textLight: Color,
val textLightSupport: Color,
val surfacePrimary: Color,
)
internal val LightZashiColorPalette =
ZashiColors(
textLight = Color(0xFFFFFFFF),
textLightSupport = Color(0xFFD9D8CF),
surfacePrimary = Color(0xFF282622),
)
internal val DarkZashiColorPalette =
ZashiColors(
textLight = Color(0xFFE8E8E8),
textLightSupport = Color(0xFFBDBBBC),
surfacePrimary = Color(0xFF454243),
)
@Suppress("CompositionLocalAllowlist")
internal val LocalZashiColors = staticCompositionLocalOf<ZashiColors> { error("no colors specified") }

View File

@ -27,22 +27,16 @@ fun ZcashTheme(
content: @Composable () -> Unit content: @Composable () -> Unit
) { ) {
val useDarkMode = forceDarkMode || isSystemInDarkTheme() val useDarkMode = forceDarkMode || isSystemInDarkTheme()
val baseColors = if (useDarkMode) DarkColorPalette else LightColorPalette
val extendedColors = if (useDarkMode) DarkExtendedColorPalette else LightExtendedColorPalette
val zashiColors = if (useDarkMode) DarkZashiColorPalette else LightZashiColorPalette
val exchangeRateColors = if (useDarkMode) DarkExchangeRateColorPalette else LightExchangeRateColorPalette
val baseColors = CompositionLocalProvider(
if (useDarkMode) { LocalExtendedColors provides extendedColors,
DarkColorPalette LocalZashiColors provides zashiColors,
} else { LocalExchangeRateColors provides exchangeRateColors,
LightColorPalette ) {
}
val extendedColors =
if (useDarkMode) {
DarkExtendedColorPalette
} else {
LightExtendedColorPalette
}
CompositionLocalProvider(LocalExtendedColors provides extendedColors) {
ProvideDimens { ProvideDimens {
MaterialTheme( MaterialTheme(
colorScheme = baseColors, colorScheme = baseColors,
@ -72,4 +66,12 @@ object ZcashTheme {
val dimens: Dimens val dimens: Dimens
@Composable @Composable
get() = localDimens.current get() = localDimens.current
val zashiColors: ZashiColors
@Composable
get() = LocalZashiColors.current
val exchangeRateColors: ExchangeRateColors
@Composable
get() = LocalExchangeRateColors.current
} }

View File

@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
@ -63,7 +64,7 @@ fun StyledExchangeBalance(
isHideBalances: Boolean = false, isHideBalances: Boolean = false,
hiddenBalancePlaceholder: StringResource = hiddenBalancePlaceholder: StringResource =
stringRes(co.electriccoin.zcash.ui.design.R.string.hide_balance_placeholder), stringRes(co.electriccoin.zcash.ui.design.R.string.hide_balance_placeholder),
textColor: Color = ZcashTheme.colors.textPrimary, textColor: Color = ZcashTheme.exchangeRateColors.btnSecondaryFg,
style: TextStyle = ZcashTheme.typography.primary.titleSmall.copy(fontWeight = FontWeight.SemiBold) style: TextStyle = ZcashTheme.typography.primary.titleSmall.copy(fontWeight = FontWeight.SemiBold)
) { ) {
if ((state.isStale && !state.isLoading) || if ((state.isStale && !state.isLoading) ||
@ -168,7 +169,7 @@ private fun ExchangeAvailableRateButton(
if (state.isRefreshEnabled) { if (state.isRefreshEnabled) {
textColor textColor
} else { } else {
ZcashTheme.colors.textDisabled ZcashTheme.exchangeRateColors.btnSpinnerDisabled
} }
) )
) )
@ -241,10 +242,11 @@ private fun ExchangeRateButton(
ElevatedButton( ElevatedButton(
modifier = modifier =
modifier modifier
.height(36.dp)
.animateContentSize(), .animateContentSize(),
onClick = onClick, onClick = onClick,
enabled = isEnabled, enabled = isEnabled,
shape = RoundedCornerShape(6.dp), shape = RoundedCornerShape(8.dp),
elevation = elevation =
ButtonDefaults.elevatedButtonElevation( ButtonDefaults.elevatedButtonElevation(
defaultElevation = 0.dp, defaultElevation = 0.dp,
@ -252,12 +254,23 @@ private fun ExchangeRateButton(
), ),
colors = colors =
ButtonDefaults.elevatedButtonColors( ButtonDefaults.elevatedButtonColors(
containerColor =
if (isEnabled && enableBorder) {
ZcashTheme.exchangeRateColors.btnSecondaryBg
} else {
Color.Unspecified
},
disabledContainerColor = Color.Transparent, disabledContainerColor = Color.Transparent,
disabledContentColor = textColor, disabledContentColor = textColor,
contentColor = textColor contentColor = textColor
), ),
border = if (isEnabled && enableBorder) BorderStroke(1.dp, Color.Gray) else null, border =
contentPadding = PaddingValues(horizontal = 14.dp, vertical = 2.dp), if (isEnabled && enableBorder) {
BorderStroke(1.dp, ZcashTheme.exchangeRateColors.btnSecondaryBorder)
} else {
BorderStroke(1.dp, Color.Transparent)
},
contentPadding = PaddingValues(horizontal = 16.dp, vertical = 0.dp),
content = content content = content
) )
} }

View File

@ -27,18 +27,18 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Popup import androidx.compose.ui.window.Popup
import co.electriccoin.zcash.ui.design.theme.ZcashTheme import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.util.PreviewScreens import co.electriccoin.zcash.ui.util.PreviewScreens
@Composable @Composable
fun UnavailableExchangeRatePopup( internal fun UnavailableExchangeRatePopup(
offset: IntOffset, offset: IntOffset,
transitionState: MutableTransitionState<Boolean>, transitionState: MutableTransitionState<Boolean>,
onDismissRequest: () -> Unit, onDismissRequest: () -> Unit,
@ -76,12 +76,12 @@ private fun PopupContent(onDismissRequest: () -> Unit) {
Modifier Modifier
.width(16.dp) .width(16.dp)
.height(8.dp) .height(8.dp)
.background(Color(0xFF4B4144), TriangleShape) .background(ZcashTheme.zashiColors.surfacePrimary, TriangleShape)
) )
Box( Box(
Modifier Modifier
.fillMaxWidth() .fillMaxWidth()
.background(Color(0xFF4B4144), RoundedCornerShape(8.dp)) .background(ZcashTheme.zashiColors.surfacePrimary, RoundedCornerShape(8.dp))
.padding(start = 12.dp, bottom = 12.dp), .padding(start = 12.dp, bottom = 12.dp),
) { ) {
Row { Row {
@ -90,17 +90,19 @@ private fun PopupContent(onDismissRequest: () -> Unit) {
) { ) {
Text( Text(
modifier = Modifier.padding(top = 12.dp), modifier = Modifier.padding(top = 12.dp),
color = Color.White, color = ZcashTheme.zashiColors.textLight,
fontSize = 16.sp,
style = ZcashTheme.extendedTypography.restoringTopAppBarStyle, style = ZcashTheme.extendedTypography.restoringTopAppBarStyle,
text = stringResource(R.string.balances_exchange_rate_unavailable) text = stringResource(R.string.balances_exchange_rate_unavailable)
) )
Spacer(modifier = Modifier.height(6.dp)) Spacer(modifier = Modifier.height(6.dp))
Text( Text(
color = Color(0xFFDED9DA), color = ZcashTheme.zashiColors.textLightSupport,
style = style =
ZcashTheme.extendedTypography.restoringTopAppBarStyle.copy( ZcashTheme.extendedTypography.restoringTopAppBarStyle.copy(
fontWeight = FontWeight.Medium fontWeight = FontWeight.Medium
), ),
fontSize = 14.sp,
text = stringResource(id = R.string.balances_exchange_rate_unavailable_subtitle) text = stringResource(id = R.string.balances_exchange_rate_unavailable_subtitle)
) )
} }
@ -108,7 +110,7 @@ private fun PopupContent(onDismissRequest: () -> Unit) {
Icon( Icon(
painter = painterResource(R.drawable.ic_unavailable_exchange_rate_dialog_close), painter = painterResource(R.drawable.ic_unavailable_exchange_rate_dialog_close),
contentDescription = "", contentDescription = "",
tint = Color.White tint = ZcashTheme.zashiColors.textLightSupport
) )
} }
} }

View File

@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.layout.wrapContentSize
@ -17,6 +18,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Devices import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import cash.z.ecc.android.sdk.model.Zatoshi import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.sdk.extension.toZecStringFull import cash.z.ecc.sdk.extension.toZecStringFull
import cash.z.ecc.sdk.type.ZcashCurrency import cash.z.ecc.sdk.type.ZcashCurrency
@ -149,12 +151,16 @@ fun BalanceWidget(
parts = balanceState.totalBalance.toZecStringFull().asZecAmountTriple() parts = balanceState.totalBalance.toZecStringFull().asZecAmountTriple()
) )
Spacer(modifier = Modifier.height(16.dp))
StyledExchangeBalance( StyledExchangeBalance(
zatoshi = balanceState.totalBalance, zatoshi = balanceState.totalBalance,
state = balanceState.exchangeRate, state = balanceState.exchangeRate,
isHideBalances = isHideBalances isHideBalances = isHideBalances
) )
Spacer(modifier = Modifier.height(12.dp))
Row(verticalAlignment = Alignment.CenterVertically) { Row(verticalAlignment = Alignment.CenterVertically) {
if (isReferenceToBalances) { if (isReferenceToBalances) {
Reference( Reference(