Balances UI implementation

This commit is contained in:
Milan Cerovsky 2025-04-14 15:35:51 +02:00
parent 8f526602ce
commit 720c2f82ca
25 changed files with 539 additions and 103 deletions

View File

@ -1,6 +1,5 @@
package co.electriccoin.zcash.ui.design.component
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Text
@ -100,7 +99,6 @@ fun StyledBalance(
val resultModifier =
Modifier
.basicMarquee()
.animateContentSize()
.then(modifier)
Text(

View File

@ -285,7 +285,7 @@ data class ButtonState(
)
@Composable
private fun ZashiButtonColors.toButtonColors() =
fun ZashiButtonColors.toButtonColors() =
ButtonDefaults.buttonColors(
containerColor = containerColor,
contentColor = contentColor,

View File

@ -103,6 +103,10 @@ private fun ContactItemLeading(
)
}
}
ImageResource.Loading -> {
// do nothing
}
}
}

View File

@ -66,6 +66,10 @@ fun ZashiCheckboxListItem(
textAlign = TextAlign.Center,
fontWeight = FontWeight.SemiBold,
)
ImageResource.Loading -> {
// do nothing
}
}
}
},

View File

@ -8,15 +8,14 @@ import androidx.compose.runtime.Stable
sealed interface ImageResource {
@Immutable
@JvmInline
value class ByDrawable(
@DrawableRes val resource: Int
) : ImageResource
value class ByDrawable(@DrawableRes val resource: Int) : ImageResource
@JvmInline
@Immutable
value class DisplayString(
val value: String
) : ImageResource
value class DisplayString(val value: String) : ImageResource
@Immutable
data object Loading: ImageResource
}
@Stable
@ -26,3 +25,6 @@ fun imageRes(
@Stable
fun imageRes(value: String): ImageResource = ImageResource.DisplayString(value)
@Stable
fun loadingImageRes(): ImageResource = ImageResource.Loading

View File

@ -9,6 +9,7 @@ import co.electriccoin.zcash.ui.screen.addressbook.viewmodel.AddressBookViewMode
import co.electriccoin.zcash.ui.screen.addressbook.viewmodel.SelectRecipientViewModel
import co.electriccoin.zcash.ui.screen.advancedsettings.AdvancedSettingsViewModel
import co.electriccoin.zcash.ui.screen.balances.BalanceViewModel
import co.electriccoin.zcash.ui.screen.balances.action.BalanceActionViewModel
import co.electriccoin.zcash.ui.screen.chooseserver.ChooseServerViewModel
import co.electriccoin.zcash.ui.screen.contact.viewmodel.AddContactViewModel
import co.electriccoin.zcash.ui.screen.contact.viewmodel.UpdateContactViewModel
@ -152,4 +153,5 @@ val viewModelModule =
viewModelOf(::ExchangeRateSettingsViewModel)
viewModelOf(::WalletBackupDetailViewModel)
viewModelOf(::ErrorViewModel)
viewModelOf(::BalanceActionViewModel)
}

View File

@ -51,6 +51,8 @@ import co.electriccoin.zcash.ui.screen.addressbook.WrapAddressBook
import co.electriccoin.zcash.ui.screen.advancedsettings.WrapAdvancedSettings
import co.electriccoin.zcash.ui.screen.authentication.AuthenticationUseCase
import co.electriccoin.zcash.ui.screen.authentication.WrapAuthentication
import co.electriccoin.zcash.ui.screen.balances.action.AndroidBalanceAction
import co.electriccoin.zcash.ui.screen.balances.action.BalanceAction
import co.electriccoin.zcash.ui.screen.chooseserver.WrapChooseServer
import co.electriccoin.zcash.ui.screen.connectkeystone.AndroidConnectKeystone
import co.electriccoin.zcash.ui.screen.connectkeystone.ConnectKeystone
@ -493,6 +495,15 @@ internal fun MainActivity.Navigation() {
) {
AndroidErrorBottomSheet()
}
dialog<BalanceAction>(
dialogProperties =
DialogProperties(
dismissOnBackPress = false,
dismissOnClickOutside = false
)
) {
AndroidBalanceAction()
}
}
}

View File

@ -8,15 +8,13 @@ object BalanceStateFixture {
private const val BALANCE_VALUE = 0L
val TOTAL_BALANCE = Zatoshi(BALANCE_VALUE)
val SPENDABLE_BALANCE = Zatoshi(BALANCE_VALUE)
fun new(
totalBalance: Zatoshi = TOTAL_BALANCE,
spendableBalance: Zatoshi = SPENDABLE_BALANCE,
exchangeRate: ExchangeRateState = ObserveFiatCurrencyResultFixture.new()
) = BalanceState.Available(
) = BalanceState(
totalBalance = totalBalance,
spendableBalance = spendableBalance,
exchangeRate = exchangeRate,
button = null
)
}

View File

@ -0,0 +1,114 @@
package co.electriccoin.zcash.ui.screen.balances
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
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.graphics.ColorFilter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import cash.z.ecc.android.sdk.model.Zatoshi
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.component.BlankSurface
import co.electriccoin.zcash.ui.design.component.LottieProgress
import co.electriccoin.zcash.ui.design.component.Spacer
import co.electriccoin.zcash.ui.design.component.ZashiButtonDefaults
import co.electriccoin.zcash.ui.design.component.toButtonColors
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
import co.electriccoin.zcash.ui.design.theme.dimensions.ZashiDimensions
import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
import co.electriccoin.zcash.ui.design.util.getValue
import co.electriccoin.zcash.ui.design.util.stringRes
@Suppress("LongParameterList")
@Composable
fun BalanceButton(
state: BalanceButtonState,
modifier: Modifier = Modifier,
) {
val colors = ZashiButtonDefaults.secondaryColors(
containerColor = ZashiColors.Surfaces.bgPrimary,
borderColor = ZashiColors.Utility.Gray.utilityGray100
)
val borderColor = colors.borderColor
Button(
onClick = state.onClick,
modifier = modifier,
shape = RoundedCornerShape(ZashiDimensions.Radius.radiusIg),
contentPadding = PaddingValues(horizontal = 12.dp, vertical = 10.dp),
colors = colors.toButtonColors(),
elevation = ButtonDefaults.buttonElevation(
defaultElevation = 2.dp,
pressedElevation = 0.dp
),
border = borderColor.takeIf { it != Color.Unspecified }?.let { BorderStroke(1.dp, it) },
content = {
Row(
verticalAlignment = Alignment.CenterVertically
) {
Image(
painter = painterResource(state.icon),
contentDescription = null,
colorFilter = ColorFilter.tint(ZashiColors.Text.textTertiary)
)
Spacer(4.dp)
Text(
text = state.text.getValue(),
color = ZashiColors.Btns.Tertiary.btnTertiaryFg,
style = ZashiTypography.textSm,
fontWeight = FontWeight.SemiBold
)
if (state.amount != null) {
Spacer(6.dp)
Image(
modifier = Modifier.padding(top = 1.dp),
painter = painterResource(R.drawable.ic_balance_zec_small),
contentDescription = null,
colorFilter = ColorFilter.tint(ZashiColors.Text.textTertiary)
)
Spacer(3.dp)
Text(
text = stringRes(state.amount).getValue(),
color = ZashiColors.Btns.Tertiary.btnTertiaryFg,
style = ZashiTypography.textSm,
fontWeight = FontWeight.SemiBold
)
} else {
Spacer(6.dp)
LottieProgress(
modifier = Modifier.size(20.dp),
)
}
}
}
)
}
@PreviewScreens
@Composable
private fun Preview() = ZcashTheme {
BlankSurface {
BalanceButton(
state = BalanceButtonState(
icon = R.drawable.ic_help,
text = stringRes("text"),
amount = Zatoshi(1000),
onClick = {}
)
)
}
}

View File

@ -1,29 +1,22 @@
package co.electriccoin.zcash.ui.screen.balances
import androidx.annotation.DrawableRes
import androidx.compose.runtime.Immutable
import cash.z.ecc.android.sdk.model.Zatoshi
import co.electriccoin.zcash.ui.common.wallet.ExchangeRateState
import co.electriccoin.zcash.ui.design.util.StringResource
sealed interface BalanceState {
val totalBalance: Zatoshi
val spendableBalance: Zatoshi
val exchangeRate: ExchangeRateState
@Immutable
data class BalanceState(
val totalBalance: Zatoshi,
val button: BalanceButtonState?,
val exchangeRate: ExchangeRateState?,
)
data class None(
override val exchangeRate: ExchangeRateState
) : BalanceState {
override val totalBalance: Zatoshi = Zatoshi(0L)
override val spendableBalance: Zatoshi = Zatoshi(0L)
}
data class Loading(
override val totalBalance: Zatoshi,
override val spendableBalance: Zatoshi,
override val exchangeRate: ExchangeRateState,
) : BalanceState
data class Available(
override val totalBalance: Zatoshi,
override val spendableBalance: Zatoshi,
override val exchangeRate: ExchangeRateState,
) : BalanceState
}
@Immutable
data class BalanceButtonState(
@DrawableRes val icon: Int,
val text: StringResource,
val amount: Zatoshi?,
val onClick: () -> Unit
)

View File

@ -34,30 +34,11 @@ class BalanceViewModel(
)
)
private fun createState(
account: WalletAccount?,
exchangeRateUsd: ExchangeRateState
): BalanceState =
when {
(
account != null &&
account.spendableBalance.value == 0L &&
account.totalBalance.value > 0L &&
(account.hasChangePending || account.hasValuePending)
) -> {
BalanceState.Loading(
totalBalance = account.totalBalance,
spendableBalance = account.spendableBalance,
exchangeRate = exchangeRateUsd,
)
}
else -> {
BalanceState.Available(
totalBalance = account?.totalBalance ?: Zatoshi(0),
spendableBalance = account?.spendableBalance ?: Zatoshi(0),
exchangeRate = exchangeRateUsd,
)
}
}
private fun createState(account: WalletAccount?, exchangeRateUsd: ExchangeRateState): BalanceState {
return BalanceState(
totalBalance = account?.totalBalance ?: Zatoshi(0),
exchangeRate = exchangeRateUsd,
button = null
)
}
}

View File

@ -3,40 +3,38 @@ package co.electriccoin.zcash.ui.screen.balances
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.sdk.extension.toZecStringFull
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.extension.asZecAmountTriple
import co.electriccoin.zcash.ui.common.wallet.ExchangeRateState
import co.electriccoin.zcash.ui.design.R
import co.electriccoin.zcash.ui.design.component.BlankSurface
import co.electriccoin.zcash.ui.design.component.Spacer
import co.electriccoin.zcash.ui.design.component.StyledBalance
import co.electriccoin.zcash.ui.design.component.StyledBalanceDefaults
import co.electriccoin.zcash.ui.design.component.ZecAmountTriple
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.design.theme.balances.LocalBalancesAvailable
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
import co.electriccoin.zcash.ui.design.util.stringRes
import co.electriccoin.zcash.ui.fixture.ObserveFiatCurrencyResultFixture
import co.electriccoin.zcash.ui.screen.balances.BalanceTag.BALANCE_VIEWS
import co.electriccoin.zcash.ui.screen.exchangerate.widget.StyledExchangeBalance
@Composable
fun BalanceWidget(
balanceState: BalanceState,
modifier: Modifier = Modifier
) {
fun BalanceWidget(state: BalanceState, modifier: Modifier = Modifier) {
Column(
modifier =
Modifier
@ -46,20 +44,22 @@ fun BalanceWidget(
horizontalAlignment = Alignment.CenterHorizontally
) {
BalanceWidgetHeader(
parts = balanceState.totalBalance.toZecStringFull().asZecAmountTriple()
parts = state.totalBalance.toZecStringFull().asZecAmountTriple()
)
if (balanceState.exchangeRate is ExchangeRateState.Data) {
Spacer(modifier = Modifier.height(12.dp))
state.button?.let {
Spacer(12.dp)
BalanceButton(it)
}
StyledExchangeBalance(
zatoshi = balanceState.totalBalance,
state = balanceState.exchangeRate,
)
if (balanceState.exchangeRate is ExchangeRateState.Data) {
Spacer(modifier = Modifier.height(8.dp))
state.exchangeRate?.let {
if (state.exchangeRate is ExchangeRateState.Data) {
Spacer(12.dp)
}
StyledExchangeBalance(state = it, zatoshi = state.totalBalance)
if (state.exchangeRate is ExchangeRateState.Data) {
Spacer(12.dp)
}
}
}
}
@ -74,6 +74,12 @@ fun BalanceWidgetHeader(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically
) {
Image(
painter = painterResource(R.drawable.ic_balance_zec),
contentDescription = null,
colorFilter = ColorFilter.tint(ZashiColors.Text.textPrimary)
)
Spacer(6.dp)
StyledBalance(
balanceParts = parts,
isHideBalances = isHideBalances,
@ -83,13 +89,6 @@ fun BalanceWidgetHeader(
leastSignificantPart = ZashiTypography.textXs.copy(fontWeight = FontWeight.SemiBold),
)
)
Spacer(modifier = Modifier.width(4.dp))
Image(
painter = painterResource(id = R.drawable.ic_zcash_zec_icon),
contentDescription = null,
)
}
}
@ -101,10 +100,15 @@ private fun BalanceWidgetPreview() {
modifier = Modifier.fillMaxWidth()
) {
BalanceWidget(
balanceState =
BalanceState.Available(
state =
BalanceState(
totalBalance = Zatoshi(1234567891234567L),
spendableBalance = Zatoshi(1234567891234567L),
button = BalanceButtonState(
icon = R.drawable.ic_help,
text = stringRes("text"),
amount = Zatoshi(1000),
onClick = {}
),
exchangeRate = ObserveFiatCurrencyResultFixture.new()
),
modifier = Modifier,

View File

@ -0,0 +1,19 @@
package co.electriccoin.zcash.ui.screen.balances.action
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import kotlinx.serialization.Serializable
import org.koin.androidx.compose.koinViewModel
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AndroidBalanceAction() {
val vm = koinViewModel<BalanceActionViewModel>()
val state by vm.state.collectAsStateWithLifecycle()
BalanceActionView(state)
}
@Serializable
data object BalanceAction

View File

@ -0,0 +1,31 @@
package co.electriccoin.zcash.ui.screen.balances.action
import androidx.compose.runtime.Immutable
import cash.z.ecc.android.sdk.model.Zatoshi
import co.electriccoin.zcash.ui.design.component.ButtonState
import co.electriccoin.zcash.ui.design.component.ModalBottomSheetState
import co.electriccoin.zcash.ui.design.util.ImageResource
import co.electriccoin.zcash.ui.design.util.StringResource
@Immutable
data class BalanceActionState(
val title: StringResource,
val message: StringResource,
val rows: List<BalanceActionRowState>,
val shieldButton: BalanceShieldButtonState?,
val positive: ButtonState,
override val onBack: () -> Unit,
): ModalBottomSheetState
@Immutable
data class BalanceActionRowState(
val title: StringResource,
val icon: ImageResource,
val value: StringResource
)
@Immutable
data class BalanceShieldButtonState(
val amount: Zatoshi,
val onShieldClick: () -> Unit,
)

View File

@ -0,0 +1,211 @@
package co.electriccoin.zcash.ui.screen.balances.action
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.SheetState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import cash.z.ecc.android.sdk.model.Zatoshi
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.component.ButtonState
import co.electriccoin.zcash.ui.design.component.LottieProgress
import co.electriccoin.zcash.ui.design.component.Spacer
import co.electriccoin.zcash.ui.design.component.ZashiButton
import co.electriccoin.zcash.ui.design.component.ZashiCard
import co.electriccoin.zcash.ui.design.component.ZashiScreenModalBottomSheet
import co.electriccoin.zcash.ui.design.component.rememberScreenModalBottomSheetState
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
import co.electriccoin.zcash.ui.design.util.ImageResource
import co.electriccoin.zcash.ui.design.util.getValue
import co.electriccoin.zcash.ui.design.util.imageRes
import co.electriccoin.zcash.ui.design.util.loadingImageRes
import co.electriccoin.zcash.ui.design.util.stringRes
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BalanceActionView(
state: BalanceActionState?,
sheetState: SheetState = rememberScreenModalBottomSheetState(),
) {
ZashiScreenModalBottomSheet(
state = state,
sheetState = sheetState,
content = {
BottomSheetContent(it, modifier = Modifier.weight(1f, false))
},
)
}
@Composable
fun BottomSheetContent(state: BalanceActionState, modifier: Modifier = Modifier) {
Column(
modifier =
modifier
.verticalScroll(rememberScrollState())
.padding(horizontal = 24.dp)
) {
Text(
text = state.title.getValue(),
color = ZashiColors.Text.textPrimary,
style = ZashiTypography.textXl,
fontWeight = FontWeight.SemiBold
)
Spacer(12.dp)
Text(
text = state.message.getValue(),
color = ZashiColors.Text.textTertiary,
style = ZashiTypography.textMd
)
Spacer(32.dp)
state.rows.forEachIndexed { index, state ->
if (index != 0) {
Spacer(12.dp)
}
BalanceActionRow(state)
}
Spacer(32.dp)
state.shieldButton?.let {
BalanceShieldButton(it)
}
Spacer(32.dp)
ZashiButton(
modifier = Modifier.fillMaxWidth(),
state = state.positive
)
}
}
@Composable
private fun BalanceActionRow(state: BalanceActionRowState) {
Row(
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = state.title.getValue(),
color = ZashiColors.Text.textTertiary,
style = ZashiTypography.textSm,
)
Spacer(1f)
when (state.icon) {
is ImageResource.ByDrawable -> Image(
modifier = Modifier.size(20.dp),
painter = painterResource(state.icon.resource),
contentDescription = null
)
ImageResource.Loading -> LottieProgress(modifier = Modifier.size(20.dp))
is ImageResource.DisplayString -> {
// do nothing
}
}
Spacer(8.dp)
Text(
text = state.value.getValue(),
color = if (state.icon is ImageResource.Loading) {
ZashiColors.Text.textTertiary
} else {
ZashiColors.Text.textPrimary
},
style = ZashiTypography.textSm,
fontWeight = FontWeight.Medium
)
}
}
@Composable
private fun BalanceShieldButton(state: BalanceShieldButtonState) {
ZashiCard(
modifier = Modifier.fillMaxWidth(),
contentPadding =
PaddingValues(
horizontal = 20.dp,
vertical = 12.dp
),
borderColor = ZashiColors.Surfaces.strokeSecondary
) {
Row {
Column {
Row(
verticalAlignment = Alignment.CenterVertically
) {
Text(
stringResource(R.string.balance_action_shield_button_header),
color = ZashiColors.Text.textPrimary,
style = ZashiTypography.textMd,
fontWeight = FontWeight.Medium
)
Spacer(4.dp)
Image(
painter = painterResource(R.drawable.ic_transparent_small),
contentDescription = null
)
}
Spacer(4.dp)
Text(
text =
stringResource(
R.string.home_message_transparent_balance_subtitle,
stringRes(state.amount).getValue()
),
color = ZashiColors.Text.textPrimary,
style = ZashiTypography.textXl,
fontWeight = FontWeight.SemiBold
)
}
Spacer(1f)
ZashiButton(
state = ButtonState(
text = stringRes(R.string.balance_action_shield),
onClick = state.onShieldClick)
)
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@PreviewScreens
@Composable
private fun Preview() = ZcashTheme {
BalanceActionView(
state = BalanceActionState(
title = stringRes("Title"),
message = stringRes("Subtitle"),
positive = ButtonState(
text = stringRes("Positive")
),
onBack = {},
rows = listOf(
BalanceActionRowState(
title = stringRes("Row"),
icon = loadingImageRes(),
value = stringRes("Value")
),
BalanceActionRowState(
title = stringRes("Row"),
icon = imageRes(R.drawable.ic_home_buy),
value = stringRes("Value")
)
),
shieldButton = BalanceShieldButtonState(
amount = Zatoshi(10000),
onShieldClick = {}
)
)
)
}

View File

@ -0,0 +1,39 @@
package co.electriccoin.zcash.ui.screen.balances.action
import androidx.lifecycle.ViewModel
import cash.z.ecc.android.sdk.model.Zatoshi
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.component.ButtonState
import co.electriccoin.zcash.ui.design.util.imageRes
import co.electriccoin.zcash.ui.design.util.loadingImageRes
import co.electriccoin.zcash.ui.design.util.stringRes
import kotlinx.coroutines.flow.MutableStateFlow
class BalanceActionViewModel : ViewModel() {
val state = MutableStateFlow(
BalanceActionState(
title = stringRes("Error"),
message = stringRes("Something went wrong"),
positive = ButtonState(
text = stringRes("Positive")
),
onBack = {},
rows = listOf(
BalanceActionRowState(
title = stringRes("Row"),
icon = loadingImageRes(),
value = stringRes("Value")
),
BalanceActionRowState(
title = stringRes("Row"),
icon = imageRes(R.drawable.ic_home_buy),
value = stringRes("Value")
)
),
shieldButton = BalanceShieldButtonState(
amount = Zatoshi(10000),
onShieldClick = {}
)
)
)
}

View File

@ -2,11 +2,9 @@
package co.electriccoin.zcash.ui.screen.exchangerate.widget
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.MutableTransitionState
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.RowScope
@ -105,10 +103,7 @@ private fun ExchangeAvailableRateLabelInternal(
val isEnabled = !state.isLoading && state.isRefreshEnabled
ExchangeRateButton(
modifier =
modifier
.basicMarquee()
.animateContentSize(),
modifier = modifier,
onClick = state.onRefresh,
isEnabled = isEnabled,
textColor = textColor,
@ -233,10 +228,7 @@ private fun ExchangeRateButton(
content: @Composable RowScope.() -> Unit
) {
ElevatedButton(
modifier =
modifier
.height(36.dp)
.animateContentSize(),
modifier = modifier.height(36.dp),
onClick = onClick,
enabled = isEnabled,
shape = RoundedCornerShape(8.dp),

View File

@ -79,7 +79,7 @@ private fun Content(
start = ZcashTheme.dimens.screenHorizontalSpacingRegular,
end = ZcashTheme.dimens.screenHorizontalSpacingRegular,
),
balanceState = balanceState,
state = balanceState,
)
NavButtons(
modifier =

View File

@ -298,7 +298,7 @@ private fun SendForm(
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall))
BalanceWidget(
balanceState = balanceState
state = balanceState
)
Spacer(modifier = Modifier.height(24.dp))

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="19dp"
android:height="32dp"
android:viewportWidth="19"
android:viewportHeight="32">
<path
android:pathData="M18.537,8.104V4.249H11.624V0H7.376V4.249H0.463V9.363H11.175L0.463,23.907V27.763H7.376V32H11.624V27.763H18.537V22.649H7.814L18.537,8.104Z"
android:fillColor="#282622"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="6dp"
android:height="10dp"
android:viewportWidth="6"
android:viewportHeight="10">
<path
android:pathData="M5.824,2.533V1.328H3.664V0H2.336V1.328H0.176V2.926H3.523L0.176,7.471V8.676H2.336V10H3.664V8.676H5.824V7.078H2.473L5.824,2.533Z"
android:fillColor="#716C5D"/>
</vector>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="balance_action_shield">Shield</string>
<string name="balance_action_shield_button_header">Transparent</string>
</resources>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="balance_action_shield">Shield</string>
<string name="balance_action_shield_button_header">Transparent</string>
</resources>

View File

@ -29,4 +29,9 @@
<string name="general_ok">OK</string>
<string name="general_remind_me_later">Remind me later</string>
<string name="general_remind_me_in">Remind me in %s</string>
<string name="general_report">Report</string>
<string name="general_remind_me_in_two_days">two days</string>
<string name="general_remind_me_in_two_weeks">two weeks</string>
<string name="general_remind_me_in_two_months">two months</string>
</resources>

View File

@ -29,9 +29,9 @@
<string name="general_etc"></string>
<string name="general_ok">OK</string>
<string name="general_report">Report</string>
<string name="general_remind_me_later">Remind me later</string>
<string name="general_remind_me_in">Remind me in %s</string>
<string name="general_report">Report</string>
<string name="general_remind_me_in_two_days">two days</string>
<string name="general_remind_me_in_two_weeks">two weeks</string>
<string name="general_remind_me_in_two_months">two months</string>