Balances UI implementation
This commit is contained in:
parent
8f526602ce
commit
720c2f82ca
|
@ -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(
|
||||
|
|
|
@ -285,7 +285,7 @@ data class ButtonState(
|
|||
)
|
||||
|
||||
@Composable
|
||||
private fun ZashiButtonColors.toButtonColors() =
|
||||
fun ZashiButtonColors.toButtonColors() =
|
||||
ButtonDefaults.buttonColors(
|
||||
containerColor = containerColor,
|
||||
contentColor = contentColor,
|
||||
|
|
|
@ -103,6 +103,10 @@ private fun ContactItemLeading(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
ImageResource.Loading -> {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -66,6 +66,10 @@ fun ZashiCheckboxListItem(
|
|||
textAlign = TextAlign.Center,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
)
|
||||
|
||||
ImageResource.Loading -> {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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 = {}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
|
@ -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,
|
||||
)
|
|
@ -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 = {}
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
|
@ -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 = {}
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
|
@ -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),
|
||||
|
|
|
@ -79,7 +79,7 @@ private fun Content(
|
|||
start = ZcashTheme.dimens.screenHorizontalSpacingRegular,
|
||||
end = ZcashTheme.dimens.screenHorizontalSpacingRegular,
|
||||
),
|
||||
balanceState = balanceState,
|
||||
state = balanceState,
|
||||
)
|
||||
NavButtons(
|
||||
modifier =
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue