* [#1011] Rework buttons design system

* [#1011] Dark mode in Onboarding screen

* [#1011] Welcome animation dark mode

* [#1011] SecurityWarning screen dark mode

+ Proper coloring of the labeled checkbox across the app

* [#1011] NewWalletRecovery dark mode

+ Chip and ChipGrid coloring
+ Navigation button and Dialog coloring
+ NewWalletRecovery screen button copy update

* [#1011] RestoreView dark mode

+ Chip components coloring

* [#1011] RestoreView.Birthday dark mode

+ Fix Primary/Secondary colors

* [#1011] Settings screen dark mode

- Fix TopAppBar colors in dark mode

* [#1011] Support screen dark mode

* Fix static code analysis warnings

* [#1011] About screen dark mode

* [#1011] ChooseServer screen dark mode

+ LabeledRadioButton coloring
- Closes #1410

* [#1011] AppAlertDialog dark mode

* [#1011] Not Enough Free Space screen dark mode

- Screen redesigned to align with latest design specifications
- Added Go To System Settings and Go To App Settings buttons to the screen
- Closes #1337
- Few unused resources removed

* [#1011] App Update screen dark mode

* [#1011] Balances screen dark mode

+ dividers’ color review

* [#1011] Receive screen dark mode

* [#1011] Send.Form screen dark mode

* [#1011] Send.Confirmation screen dark mode

* [#1011] Send.MultipleTrxError screen dark mode

* [#1011] Scan screen dark mode

* [#1011] TransactionHistory screen dark mode

* Changelog update

* Address review comments
This commit is contained in:
Honza Rychnovský 2024-06-19 14:09:28 +02:00 committed by GitHub
parent 20348014be
commit 987595eaa2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
69 changed files with 1705 additions and 609 deletions

View File

@ -12,6 +12,10 @@ directly impact users rather than highlighting other key architectural updates.*
### Added ### Added
- New bubble message style for the Send and Transaction history item text components - New bubble message style for the Send and Transaction history item text components
- Display all messages within the transaction history record when it is expanded - Display all messages within the transaction history record when it is expanded
- The Dark mode is now officially supported by the entire app UI
### Changed
- The Not Enough Free Space screen UI has been slightly refactored to align with the latest design guidelines
## [1.1.1 (660)] - 2024-06-05 ## [1.1.1 (660)] - 2024-06-05

View File

@ -32,7 +32,7 @@ private const val COMPONENT_MIN_WIDTH = ARROW_WIDTH * 3
@Composable @Composable
private fun BubbleWithTextPreview() { private fun BubbleWithTextPreview() {
ZcashTheme { ZcashTheme {
BubbleMessage(backgroundColor = ZcashTheme.colors.dividerColor) { BubbleMessage(backgroundColor = ZcashTheme.colors.primaryDividerColor) {
Text( Text(
text = "TextTextTextText", text = "TextTextTextText",
fontSize = 16.sp, fontSize = 16.sp,

View File

@ -2,6 +2,7 @@ package co.electriccoin.zcash.ui.design.component
import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.border import androidx.compose.foundation.border
import androidx.compose.foundation.gestures.awaitFirstDown import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.waitForUpOrCancellation import androidx.compose.foundation.gestures.waitForUpOrCancellation
@ -11,13 +12,13 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.defaultMinSize
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.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults.buttonColors import androidx.compose.material3.ButtonDefaults.buttonColors
import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
@ -42,6 +43,7 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.constraintlayout.compose.ConstraintLayout import androidx.constraintlayout.compose.ConstraintLayout
import co.electriccoin.zcash.ui.design.theme.ZcashTheme import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.design.theme.internal.ButtonColors
@Preview @Preview
@Composable @Composable
@ -49,11 +51,59 @@ private fun ButtonComposablePreview() {
ZcashTheme(forceDarkMode = false) { ZcashTheme(forceDarkMode = false) {
BlankSurface { BlankSurface {
Column(Modifier.padding(ZcashTheme.dimens.spacingDefault)) { Column(Modifier.padding(ZcashTheme.dimens.spacingDefault)) {
PrimaryButton(onClick = { }, text = "Primary") Column(
PrimaryButton(onClick = { }, text = "Primary...", showProgressBar = true) modifier =
PrimaryButton(onClick = { }, text = "Primary Small", minHeight = ZcashTheme.dimens.buttonHeightSmall) Modifier
SecondaryButton(onClick = { }, text = "Secondary") .background(color = Color.Gray)
NavigationButton(onClick = { }, text = "Navigation") .padding(all = 24.dp)
) {
PrimaryButton(onClick = { }, text = "Primary Basic")
PrimaryButton(onClick = { }, text = "Primary Disabled", enabled = false)
SecondaryButton(onClick = { }, text = "Secondary Basic")
SecondaryButton(onClick = { }, text = "Secondary Disabled", enabled = false)
}
Spacer(modifier = Modifier.height(24.dp))
PrimaryButton(onClick = { }, text = "Primary loading", showProgressBar = true)
Spacer(modifier = Modifier.height(24.dp))
@Suppress("MagicNumber")
Row {
PrimaryButton(onClick = { }, text = "Button 1", modifier = Modifier.weight(0.5f))
Spacer(modifier = Modifier.width(24.dp))
PrimaryButton(onClick = { }, text = "Button 2", modifier = Modifier.weight(0.5f))
}
}
}
}
}
@Preview
@Composable
private fun ButtonComposableDarkPreview() {
ZcashTheme(forceDarkMode = true) {
BlankSurface {
Column(Modifier.padding(ZcashTheme.dimens.spacingDefault)) {
Column(
modifier =
Modifier
.background(color = Color.Gray)
.padding(all = 24.dp)
) {
PrimaryButton(onClick = { }, text = "Primary Basic")
PrimaryButton(onClick = { }, text = "Primary Disabled", enabled = false)
SecondaryButton(onClick = { }, text = "Secondary Basic")
SecondaryButton(onClick = { }, text = "Secondary Disabled", enabled = false)
}
Spacer(modifier = Modifier.height(24.dp))
PrimaryButton(onClick = { }, text = "Primary loading", showProgressBar = true)
Spacer(modifier = Modifier.height(24.dp))
@Suppress("MagicNumber") @Suppress("MagicNumber")
Row { Row {
PrimaryButton(onClick = { }, text = "Button 1", modifier = Modifier.weight(0.5f)) PrimaryButton(onClick = { }, text = "Button 1", modifier = Modifier.weight(0.5f))
@ -75,8 +125,7 @@ fun PrimaryButton(
minHeight: Dp = ZcashTheme.dimens.buttonHeight, minHeight: Dp = ZcashTheme.dimens.buttonHeight,
enabled: Boolean = true, enabled: Boolean = true,
showProgressBar: Boolean = false, showProgressBar: Boolean = false,
buttonColor: Color = MaterialTheme.colorScheme.primary, buttonColors: ButtonColors = ZcashTheme.colors.primaryButtonColors,
textColor: Color = MaterialTheme.colorScheme.onPrimary,
textStyle: TextStyle = ZcashTheme.extendedTypography.buttonText, textStyle: TextStyle = ZcashTheme.extendedTypography.buttonText,
outerPaddingValues: PaddingValues = outerPaddingValues: PaddingValues =
PaddingValues( PaddingValues(
@ -94,37 +143,66 @@ fun PrimaryButton(
Modifier Modifier
.padding(outerPaddingValues) .padding(outerPaddingValues)
.shadow( .shadow(
contentColor = textColor, contentColor =
strokeColor = buttonColor, if (enabled) {
buttonColors.shadowColor
} else {
buttonColors.disabledShadowColor
},
strokeColor =
if (enabled) {
buttonColors.shadowStrokeColor
} else {
buttonColors.shadowDisabledStrokeColor
},
strokeWidth = 1.dp, strokeWidth = 1.dp,
offsetX = ZcashTheme.dimens.buttonShadowOffsetX, offsetX = ZcashTheme.dimens.buttonShadowOffsetX,
offsetY = ZcashTheme.dimens.buttonShadowOffsetY, offsetY = ZcashTheme.dimens.buttonShadowOffsetY,
spread = ZcashTheme.dimens.buttonShadowSpread, spread = ZcashTheme.dimens.buttonShadowSpread,
) )
.translationClick( .then(
// + 6dp to exactly cover the bottom shadow if (enabled) {
translationX = ZcashTheme.dimens.buttonShadowOffsetX + 6.dp, Modifier.translationClick(
translationY = ZcashTheme.dimens.buttonShadowOffsetX + 6.dp // + 6dp to exactly cover the bottom shadow
translationX = ZcashTheme.dimens.buttonShadowOffsetX + 6.dp,
translationY = ZcashTheme.dimens.buttonShadowOffsetX + 6.dp
)
} else {
Modifier
}
) )
.defaultMinSize(minWidth, minHeight) .defaultMinSize(minWidth, minHeight)
.border(1.dp, Color.Black) .border(
width = 1.dp,
color =
if (enabled) {
buttonColors.strokeColor
} else {
buttonColors.disabledStrokeColor
}
)
), ),
colors = colors =
buttonColors( buttonColors(
containerColor = buttonColor, containerColor = buttonColors.containerColor,
disabledContainerColor = ZcashTheme.colors.disabledButtonColor, disabledContainerColor = buttonColors.disabledContainerColor,
disabledContentColor = ZcashTheme.colors.disabledButtonTextColor disabledContentColor = buttonColors.disabledContainerColor,
), ),
onClick = onClick, onClick = onClick,
) { ) {
ConstraintLayout { ConstraintLayout(modifier = Modifier.fillMaxWidth()) {
val (title, spacer, progress) = createRefs() val (title, spacer, progress) = createRefs()
Text( Text(
style = textStyle, style = textStyle,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
text = text.uppercase(), text = text.uppercase(),
color = textColor, color =
if (enabled) {
buttonColors.textColor
} else {
buttonColors.disabledTextColor
},
modifier = modifier =
Modifier.constrainAs(title) { Modifier.constrainAs(title) {
top.linkTo(parent.top) top.linkTo(parent.top)
@ -165,7 +243,7 @@ fun PrimaryButton(
} }
@Composable @Composable
@Suppress("LongParameterList") @Suppress("LongParameterList", "LongMethod")
fun SecondaryButton( fun SecondaryButton(
onClick: () -> Unit, onClick: () -> Unit,
text: String, text: String,
@ -173,8 +251,7 @@ fun SecondaryButton(
minWidth: Dp = ZcashTheme.dimens.buttonWidth, minWidth: Dp = ZcashTheme.dimens.buttonWidth,
minHeight: Dp = ZcashTheme.dimens.buttonHeight, minHeight: Dp = ZcashTheme.dimens.buttonHeight,
enabled: Boolean = true, enabled: Boolean = true,
buttonColor: Color = MaterialTheme.colorScheme.secondary, buttonColors: ButtonColors = ZcashTheme.colors.secondaryButtonColors,
textColor: Color = MaterialTheme.colorScheme.onSecondary,
outerPaddingValues: PaddingValues = outerPaddingValues: PaddingValues =
PaddingValues( PaddingValues(
horizontal = ZcashTheme.dimens.spacingNone, horizontal = ZcashTheme.dimens.spacingNone,
@ -191,27 +268,51 @@ fun SecondaryButton(
Modifier Modifier
.padding(outerPaddingValues) .padding(outerPaddingValues)
.shadow( .shadow(
contentColor = textColor, contentColor =
strokeColor = buttonColor, if (enabled) {
buttonColors.shadowColor
} else {
buttonColors.disabledShadowColor
},
strokeColor =
if (enabled) {
buttonColors.shadowStrokeColor
} else {
buttonColors.shadowDisabledStrokeColor
},
strokeWidth = 1.dp, strokeWidth = 1.dp,
offsetX = ZcashTheme.dimens.buttonShadowOffsetX, offsetX = ZcashTheme.dimens.buttonShadowOffsetX,
offsetY = ZcashTheme.dimens.buttonShadowOffsetY, offsetY = ZcashTheme.dimens.buttonShadowOffsetY,
spread = ZcashTheme.dimens.buttonShadowSpread, spread = ZcashTheme.dimens.buttonShadowSpread,
) )
.translationClick( .then(
// + 6dp to exactly cover the bottom shadow if (enabled) {
translationX = ZcashTheme.dimens.buttonShadowOffsetX + 6.dp, Modifier.translationClick(
translationY = ZcashTheme.dimens.buttonShadowOffsetX + 6.dp // + 6dp to exactly cover the bottom shadow
translationX = ZcashTheme.dimens.buttonShadowOffsetX + 6.dp,
translationY = ZcashTheme.dimens.buttonShadowOffsetX + 6.dp
)
} else {
Modifier
}
) )
.defaultMinSize(minWidth, minHeight) .defaultMinSize(minWidth, minHeight)
.fillMaxWidth() .fillMaxWidth()
.border(1.dp, Color.Black) .border(
width = 1.dp,
color =
if (enabled) {
buttonColors.strokeColor
} else {
buttonColors.disabledStrokeColor
}
)
), ),
colors = colors =
buttonColors( buttonColors(
containerColor = buttonColor, containerColor = buttonColors.containerColor,
disabledContainerColor = ZcashTheme.colors.disabledButtonColor, disabledContainerColor = buttonColors.disabledContainerColor,
disabledContentColor = ZcashTheme.colors.disabledButtonTextColor disabledContentColor = buttonColors.disabledContainerColor
), ),
onClick = onClick, onClick = onClick,
) { ) {
@ -219,37 +320,12 @@ fun SecondaryButton(
style = ZcashTheme.extendedTypography.buttonText, style = ZcashTheme.extendedTypography.buttonText,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
text = text.uppercase(), text = text.uppercase(),
color = textColor color =
) if (enabled) {
} buttonColors.textColor
} } else {
buttonColors.disabledTextColor
@Composable }
fun NavigationButton(
onClick: () -> Unit,
text: String,
modifier: Modifier = Modifier,
outerPaddingValues: PaddingValues =
PaddingValues(
horizontal = ZcashTheme.dimens.spacingNone,
vertical = ZcashTheme.dimens.spacingSmall
),
) {
Button(
shape = RectangleShape,
onClick = onClick,
modifier =
modifier.then(
Modifier
.padding(outerPaddingValues)
),
colors = buttonColors(containerColor = MaterialTheme.colorScheme.secondary)
) {
Text(
style = MaterialTheme.typography.labelLarge,
textAlign = TextAlign.Center,
text = text,
color = MaterialTheme.colorScheme.onSecondary
) )
} }
} }

View File

@ -1,15 +1,19 @@
package co.electriccoin.zcash.ui.design.component package co.electriccoin.zcash.ui.design.component
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.ClickableText import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Checkbox import androidx.compose.material3.Checkbox
import androidx.compose.material3.CheckboxDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
@ -17,60 +21,102 @@ import co.electriccoin.zcash.ui.design.theme.ZcashTheme
@Preview @Preview
@Composable @Composable
private fun ComposablePreview() { private fun LabeledCheckboxPreview() {
val checkBoxState = remember { mutableStateOf(false) }
ZcashTheme(forceDarkMode = false) { ZcashTheme(forceDarkMode = false) {
CheckBox( BlankSurface {
onCheckedChange = { checkBoxState.value = it }, Row {
text = "test", LabeledCheckBox(
checked = checkBoxState.value, onCheckedChange = {},
checkBoxTestTag = null text = "Checkbox",
) checked = false
)
LabeledCheckBox(
onCheckedChange = {},
text = "Checkbox",
checked = true
)
}
}
}
}
@Preview
@Composable
private fun LabeledCheckboxDarkPreview() {
ZcashTheme(forceDarkMode = true) {
BlankSurface {
Row {
LabeledCheckBox(
onCheckedChange = {},
text = "Checkbox",
checked = false
)
LabeledCheckBox(
onCheckedChange = {},
text = "Checkbox",
checked = true
)
}
}
} }
} }
@Composable @Composable
fun CheckBox( fun LabeledCheckBox(
onCheckedChange: (Boolean) -> Unit, onCheckedChange: (Boolean) -> Unit,
text: String, text: String,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
checked: Boolean = false, checked: Boolean = false,
checkBoxTestTag: String? = null checkBoxTestTag: String? = null
) { ) {
val (checkedState, setCheckedState) = rememberSaveable { mutableStateOf(checked) }
Row( Row(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
modifier = modifier modifier =
) { modifier.then(
val checkBoxModifier = Modifier
Modifier .wrapContentSize()
.padding( .clip(RoundedCornerShape(ZcashTheme.dimens.regularRippleEffectCorner))
top = ZcashTheme.dimens.spacingTiny, .clickable {
bottom = ZcashTheme.dimens.spacingTiny, setCheckedState(!checkedState)
end = ZcashTheme.dimens.spacingTiny onCheckedChange(!checkedState)
)
.then(
if (checkBoxTestTag != null) {
Modifier.testTag(checkBoxTestTag)
} else {
Modifier
} }
) // Setting just the end padding, the start one is taken from the checkbox
val (checkedState, setCheckedState) = rememberSaveable { mutableStateOf(checked) } .padding(end = ZcashTheme.dimens.spacingMid)
)
) {
Checkbox( Checkbox(
checked = checkedState, checked = checkedState,
colors =
CheckboxDefaults.colors(
checkedColor = ZcashTheme.colors.secondaryColor,
uncheckedColor = ZcashTheme.colors.secondaryColor,
checkmarkColor = ZcashTheme.colors.primaryColor,
),
onCheckedChange = { onCheckedChange = {
setCheckedState(it) setCheckedState(it)
onCheckedChange(it) onCheckedChange(it)
}, },
enabled = true, enabled = true,
modifier = checkBoxModifier modifier =
Modifier
.padding(
top = ZcashTheme.dimens.spacingTiny,
bottom = ZcashTheme.dimens.spacingTiny,
end = ZcashTheme.dimens.spacingTiny
)
.then(
if (checkBoxTestTag != null) {
Modifier.testTag(checkBoxTestTag)
} else {
Modifier
}
)
) )
ClickableText( Text(
onClick = {
setCheckedState(!checkedState)
onCheckedChange(!checkedState)
},
text = AnnotatedString(text), text = AnnotatedString(text),
color = ZcashTheme.colors.textPrimary,
style = ZcashTheme.extendedTypography.checkboxText style = ZcashTheme.extendedTypography.checkboxText
) )
} }

View File

@ -2,16 +2,19 @@ package co.electriccoin.zcash.ui.design.component
import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.border import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import co.electriccoin.zcash.spackle.model.Index import co.electriccoin.zcash.spackle.model.Index
import co.electriccoin.zcash.ui.design.theme.ZcashTheme import co.electriccoin.zcash.ui.design.theme.ZcashTheme
@ -19,7 +22,9 @@ import co.electriccoin.zcash.ui.design.theme.ZcashTheme
@Composable @Composable
private fun ComposableChipPreview() { private fun ComposableChipPreview() {
ZcashTheme(forceDarkMode = false) { ZcashTheme(forceDarkMode = false) {
Chip("route") Box(modifier = Modifier.padding(all = 12.dp)) {
Chip("route")
}
} }
} }
@ -27,7 +32,9 @@ private fun ComposableChipPreview() {
@Composable @Composable
private fun ComposableChipIndexedPreview() { private fun ComposableChipIndexedPreview() {
ZcashTheme(forceDarkMode = false) { ZcashTheme(forceDarkMode = false) {
ChipIndexed(Index(0), "edict") Box(modifier = Modifier.padding(all = 12.dp)) {
ChipIndexed(Index(0), "edict")
}
} }
} }
@ -35,7 +42,12 @@ private fun ComposableChipIndexedPreview() {
@Composable @Composable
private fun ComposableLongChipPreview() { private fun ComposableLongChipPreview() {
ZcashTheme(forceDarkMode = false) { ZcashTheme(forceDarkMode = false) {
ChipIndexed(Index(1), "a_very_long_seed_word_that_does_not_fit_into_the_chip_and_thus_needs_to_be_truncated") Box(modifier = Modifier.padding(all = 12.dp)) {
ChipIndexed(
Index(1),
"a_very_long_seed_word_that_does_not_fit_into_the_chip_and_thus_needs_to_be_truncated"
)
}
} }
} }
@ -43,7 +55,19 @@ private fun ComposableLongChipPreview() {
@Composable @Composable
private fun ComposableChipOnSurfacePreview() { private fun ComposableChipOnSurfacePreview() {
ZcashTheme(forceDarkMode = false) { ZcashTheme(forceDarkMode = false) {
ChipOnSurface("ribbon") Box(modifier = Modifier.padding(all = 12.dp)) {
ChipOnSurface({}, "ribbon")
}
}
}
@Preview
@Composable
private fun ComposableChipOnSurfaceDarkPreview() {
ZcashTheme(forceDarkMode = true) {
Box(modifier = Modifier.padding(all = 12.dp)) {
ChipOnSurface({}, "ribbon")
}
} }
} }
@ -55,7 +79,7 @@ fun Chip(
Text( Text(
text = text, text = text,
style = MaterialTheme.typography.bodyLarge, style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSecondary, color = ZcashTheme.colors.textPrimary,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
modifier = modifier.then(Modifier.testTag(CommonTag.CHIP)) modifier = modifier.then(Modifier.testTag(CommonTag.CHIP))
@ -71,7 +95,7 @@ fun ChipIndexed(
Text( Text(
text = "${index.value + 1}. $text", text = "${index.value + 1}. $text",
style = MaterialTheme.typography.bodyLarge, style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSecondary, color = ZcashTheme.colors.textPrimary,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
modifier = modifier.then(Modifier.testTag(CommonTag.CHIP)) modifier = modifier.then(Modifier.testTag(CommonTag.CHIP))
@ -80,11 +104,12 @@ fun ChipIndexed(
@Composable @Composable
fun ChipOnSurface( fun ChipOnSurface(
onClick: () -> Unit,
text: String, text: String,
modifier: Modifier = Modifier modifier: Modifier = Modifier,
) { ) {
Surface( Surface(
shape = RectangleShape, shape = RoundedCornerShape(size = ZcashTheme.dimens.regularRippleEffectCorner),
modifier = modifier =
modifier modifier
.padding(horizontal = ZcashTheme.dimens.spacingTiny) .padding(horizontal = ZcashTheme.dimens.spacingTiny)
@ -92,20 +117,22 @@ fun ChipOnSurface(
border = border =
BorderStroke( BorderStroke(
width = ZcashTheme.dimens.chipStroke, width = ZcashTheme.dimens.chipStroke,
color = ZcashTheme.colors.layoutStroke color = ZcashTheme.colors.layoutStrokeSecondary
) ),
), shape = RoundedCornerShape(size = ZcashTheme.dimens.regularRippleEffectCorner),
color = MaterialTheme.colorScheme.secondary, )
.clickable { onClick() },
color = ZcashTheme.colors.primaryColor,
shadowElevation = ZcashTheme.dimens.chipShadowElevation, shadowElevation = ZcashTheme.dimens.chipShadowElevation,
) { ) {
Text( Text(
text = text, text = text,
style = MaterialTheme.typography.bodyLarge, style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSecondary, color = ZcashTheme.colors.textPrimary,
modifier = modifier =
Modifier Modifier
.padding( .padding(
vertical = ZcashTheme.dimens.spacingSmall, vertical = ZcashTheme.dimens.spacingMid,
horizontal = ZcashTheme.dimens.spacingDefault horizontal = ZcashTheme.dimens.spacingDefault
) )
.testTag(CommonTag.CHIP) .testTag(CommonTag.CHIP)

View File

@ -26,12 +26,27 @@ const val CHIP_GRID_COLUMN_SIZE = 12
@Preview @Preview
@Composable @Composable
private fun ComposablePreview() { private fun ChipGridPreview() {
ZcashTheme(forceDarkMode = false) { ZcashTheme(forceDarkMode = false) {
ChipGrid( BlankSurface {
SeedPhrase.new(WalletFixture.Alice.seedPhrase).split.toPersistentList(), ChipGrid(
onGridClick = {} SeedPhrase.new(WalletFixture.Alice.seedPhrase).split.toPersistentList(),
) onGridClick = {}
)
}
}
}
@Preview
@Composable
private fun ChipGridDarkPreview() {
ZcashTheme(forceDarkMode = true) {
BlankSurface {
ChipGrid(
SeedPhrase.new(WalletFixture.Alice.seedPhrase).split.toPersistentList(),
onGridClick = {}
)
}
} }
} }

View File

@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.height
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
@ -27,6 +28,19 @@ private fun TopScreenLogoRegularComposablePreview() {
} }
} }
@Preview
@Composable
private fun TopScreenLogoRegularDarkComposablePreview() {
ZcashTheme(forceDarkMode = true) {
BlankSurface {
TopScreenLogoTitle(
title = "Test screen title",
logoContentDescription = "Test logo content description"
)
}
}
}
@Preview @Preview
@Composable @Composable
private fun TopScreenLogoLongComposablePreview() { private fun TopScreenLogoLongComposablePreview() {
@ -49,6 +63,7 @@ fun TopScreenLogoTitle(
Column(modifier = modifier) { Column(modifier = modifier) {
Image( Image(
painter = painterResource(id = R.drawable.zashi_logo_without_text), painter = painterResource(id = R.drawable.zashi_logo_without_text),
colorFilter = ColorFilter.tint(color = ZcashTheme.colors.secondaryColor),
contentDescription = logoContentDescription, contentDescription = logoContentDescription,
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) )
@ -57,6 +72,7 @@ fun TopScreenLogoTitle(
Text( Text(
text = title, text = title,
color = ZcashTheme.colors.textPrimary,
style = ZcashTheme.typography.secondary.headlineMedium, style = ZcashTheme.typography.secondary.headlineMedium,
maxLines = 2, maxLines = 2,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,

View File

@ -1,14 +1,19 @@
package co.electriccoin.zcash.ui.design.component package co.electriccoin.zcash.ui.design.component
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.CornerSize import androidx.compose.foundation.shape.CornerSize
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.AlertDialog import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults.buttonColors
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.DialogProperties
@ -30,6 +35,20 @@ private fun LightAlertDialogComposablePreview() {
} }
} }
@Preview
@Composable
private fun NoButtonAlertDialogComposablePreview() {
ZcashTheme(forceDarkMode = false) {
AppAlertDialog(
title = "Light popup",
text =
"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Temporibus autem quibusdam et aut " +
"officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et " +
"molestiae non recusandae. Duis condimentum augue id magna semper rutrum.",
)
}
}
@Preview @Preview
@Composable @Composable
private fun DarkAlertDialogComposablePreview() { private fun DarkAlertDialogComposablePreview() {
@ -40,6 +59,8 @@ private fun DarkAlertDialogComposablePreview() {
"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Temporibus autem quibusdam et aut " + "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Temporibus autem quibusdam et aut " +
"officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et " + "officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et " +
"molestiae non recusandae. Duis condimentum augue id magna semper rutrum.", "molestiae non recusandae. Duis condimentum augue id magna semper rutrum.",
confirmButtonText = "OK",
dismissButtonText = "Cancel"
) )
} }
} }
@ -86,6 +107,8 @@ fun AppAlertDialog(
text = text, text = text,
icon = icon?.let { { Icon(imageVector = icon, null) } }, icon = icon?.let { { Icon(imageVector = icon, null) } },
properties = properties, properties = properties,
titleContentColor = ZcashTheme.colors.textPrimary,
textContentColor = ZcashTheme.colors.textPrimary,
modifier = modifier, modifier = modifier,
) )
} }
@ -117,3 +140,50 @@ fun AppAlertDialog(
onDismissButtonClick = onDismissButtonClick onDismissButtonClick = onDismissButtonClick
) )
} }
@Preview
@Composable
private fun NavigationButtonPreview() {
ZcashTheme(forceDarkMode = false) {
NavigationButton(
onClick = {},
text = "Test button",
)
}
}
@Preview
@Composable
private fun NavigationButtonDarkPreview() {
ZcashTheme(forceDarkMode = true) {
NavigationButton(
onClick = {},
text = "Dark button",
)
}
}
@Composable
private fun NavigationButton(
onClick: () -> Unit,
text: String,
modifier: Modifier = Modifier,
outerPaddingValues: PaddingValues =
PaddingValues(
horizontal = ZcashTheme.dimens.spacingNone,
vertical = ZcashTheme.dimens.spacingSmall
),
) {
Button(
onClick = onClick,
modifier = modifier.padding(outerPaddingValues),
colors = buttonColors(containerColor = ZcashTheme.colors.primaryColor)
) {
Text(
style = MaterialTheme.typography.labelLarge,
textAlign = TextAlign.Center,
text = text,
color = ZcashTheme.colors.textPrimary
)
}
}

View File

@ -11,7 +11,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.pager.PagerState
import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Tab import androidx.compose.material3.Tab
import androidx.compose.material3.TabRow import androidx.compose.material3.TabRow
import androidx.compose.material3.Text import androidx.compose.material3.Text
@ -64,10 +63,7 @@ fun PagerTabs(
onTabSelected: (index: Int) -> Unit = {}, onTabSelected: (index: Int) -> Unit = {},
) { ) {
TabRow( TabRow(
modifier = modifier = modifier.border(ZcashTheme.dimens.spacingTiny, ZcashTheme.colors.layoutStroke),
modifier
.padding(horizontal = ZcashTheme.dimens.screenHorizontalSpacingBig)
.border(ZcashTheme.dimens.spacingTiny, ZcashTheme.colors.layoutStroke),
selectedTabIndex = pagerState.currentPage, selectedTabIndex = pagerState.currentPage,
divider = {}, divider = {},
indicator = {}, indicator = {},
@ -118,7 +114,7 @@ private fun PagerTab(
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = ZcashTheme.dimens.spacingXtiny), .padding(horizontal = ZcashTheme.dimens.spacingXtiny),
text = title, text = title,
color = if (selected) ZcashTheme.colors.textCommon else MaterialTheme.colorScheme.onPrimary, color = if (selected) ZcashTheme.colors.textPrimary else ZcashTheme.colors.textSecondary,
style = ZcashTheme.extendedTypography.restoringTopAppBarStyle, style = ZcashTheme.extendedTypography.restoringTopAppBarStyle,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
maxLines = 2, maxLines = 2,

View File

@ -19,14 +19,43 @@ import co.electriccoin.zcash.ui.design.theme.ZcashTheme
@Preview @Preview
@Composable @Composable
private fun ComposablePreview() { private fun RadioButtonPreview() {
ZcashTheme(forceDarkMode = false) { ZcashTheme(forceDarkMode = false) {
RadioButton( BlankBgColumn {
text = "test", RadioButton(
selected = true, text = "test",
onClick = {}, selected = false,
modifier = Modifier onClick = {},
) modifier = Modifier
)
RadioButton(
text = "test",
selected = true,
onClick = {},
modifier = Modifier
)
}
}
}
@Preview
@Composable
private fun RadioButtonDarkPreview() {
ZcashTheme(forceDarkMode = true) {
BlankBgColumn {
RadioButton(
text = "Dark test",
selected = false,
onClick = {},
modifier = Modifier
)
RadioButton(
text = "Dark test",
selected = true,
onClick = {},
modifier = Modifier
)
}
} }
} }
@ -59,14 +88,14 @@ fun RadioButton(
onClick = onClick, onClick = onClick,
colors = colors =
RadioButtonDefaults.colors( RadioButtonDefaults.colors(
selectedColor = ZcashTheme.colors.radioButtonColor, selectedColor = ZcashTheme.colors.secondaryColor,
unselectedColor = ZcashTheme.colors.radioButtonColor, unselectedColor = ZcashTheme.colors.secondaryColor,
) )
) )
Text( Text(
text = text, text = text,
style = ZcashTheme.extendedTypography.radioButton, style = ZcashTheme.extendedTypography.radioButton,
color = ZcashTheme.colors.radioButtonTextColor, color = ZcashTheme.colors.textPrimary,
modifier = modifier =
Modifier.padding( Modifier.padding(
top = 16.dp, top = 16.dp,

View File

@ -23,6 +23,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.buildAnnotatedString
@ -93,14 +94,14 @@ fun Header(
text: String, text: String,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
textAlign: TextAlign = TextAlign.Start, textAlign: TextAlign = TextAlign.Start,
color: Color = ZcashTheme.colors.onBackgroundHeader, color: Color = ZcashTheme.colors.textPrimary,
) { ) {
Text( Text(
text = text, text = text,
color = color, color = color,
textAlign = textAlign, textAlign = textAlign,
modifier = modifier, modifier = modifier,
style = ZcashTheme.typography.secondary.headlineLarge, style = ZcashTheme.typography.primary.headlineLarge,
) )
} }
@ -109,7 +110,7 @@ fun SubHeader(
text: String, text: String,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
textAlign: TextAlign = TextAlign.Start, textAlign: TextAlign = TextAlign.Start,
color: Color = ZcashTheme.colors.onBackgroundHeader, color: Color = ZcashTheme.colors.textPrimary,
) { ) {
Text( Text(
text = text, text = text,
@ -129,7 +130,7 @@ fun BodySmall(
overflow: TextOverflow = TextOverflow.Clip, overflow: TextOverflow = TextOverflow.Clip,
textAlign: TextAlign = TextAlign.Start, textAlign: TextAlign = TextAlign.Start,
textFontWeight: FontWeight = FontWeight.Normal, textFontWeight: FontWeight = FontWeight.Normal,
color: Color = MaterialTheme.colorScheme.onBackground, color: Color = ZcashTheme.colors.textPrimary,
) { ) {
Text( Text(
text = text, text = text,
@ -152,7 +153,7 @@ fun Body(
overflow: TextOverflow = TextOverflow.Clip, overflow: TextOverflow = TextOverflow.Clip,
textAlign: TextAlign = TextAlign.Start, textAlign: TextAlign = TextAlign.Start,
textFontWeight: FontWeight = FontWeight.Normal, textFontWeight: FontWeight = FontWeight.Normal,
color: Color = MaterialTheme.colorScheme.onBackground, color: Color = ZcashTheme.colors.textPrimary,
) { ) {
Text( Text(
text = text, text = text,
@ -174,7 +175,7 @@ fun TitleLarge(
maxLines: Int = Int.MAX_VALUE, maxLines: Int = Int.MAX_VALUE,
overflow: TextOverflow = TextOverflow.Clip, overflow: TextOverflow = TextOverflow.Clip,
textAlign: TextAlign = TextAlign.Start, textAlign: TextAlign = TextAlign.Start,
color: Color = MaterialTheme.colorScheme.onBackground, color: Color = ZcashTheme.colors.textPrimary,
) { ) {
Text( Text(
text = text, text = text,
@ -196,7 +197,7 @@ fun Small(
maxLines: Int = Int.MAX_VALUE, maxLines: Int = Int.MAX_VALUE,
overflow: TextOverflow = TextOverflow.Clip, overflow: TextOverflow = TextOverflow.Clip,
textAlign: TextAlign = TextAlign.Start, textAlign: TextAlign = TextAlign.Start,
color: Color = MaterialTheme.colorScheme.onBackground, color: Color = ZcashTheme.colors.textPrimary,
) { ) {
Text( Text(
text = text, text = text,
@ -218,7 +219,7 @@ fun Tiny(
maxLines: Int = Int.MAX_VALUE, maxLines: Int = Int.MAX_VALUE,
overflow: TextOverflow = TextOverflow.Clip, overflow: TextOverflow = TextOverflow.Clip,
textAlign: TextAlign = TextAlign.Start, textAlign: TextAlign = TextAlign.Start,
color: Color = MaterialTheme.colorScheme.onBackground, color: Color = ZcashTheme.colors.textPrimary,
) { ) {
Text( Text(
text = text, text = text,
@ -234,15 +235,16 @@ fun Tiny(
@Composable @Composable
@Suppress("LongParameterList") @Suppress("LongParameterList")
fun TextWithIcon( fun TextWithIcon(
text: String,
iconVector: ImageVector, iconVector: ImageVector,
text: String,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
iconContentDescription: String? = null, iconContentDescription: String? = null,
iconTintColor: Color? = null,
maxLines: Int = Int.MAX_VALUE, maxLines: Int = Int.MAX_VALUE,
overflow: TextOverflow = TextOverflow.Clip, overflow: TextOverflow = TextOverflow.Clip,
textAlign: TextAlign = TextAlign.Start, textAlign: TextAlign = TextAlign.Start,
style: TextStyle = LocalTextStyle.current, style: TextStyle = LocalTextStyle.current,
color: Color = MaterialTheme.colorScheme.onBackground, color: Color = ZcashTheme.colors.textPrimary,
) { ) {
Row( Row(
modifier = modifier =
@ -251,10 +253,18 @@ fun TextWithIcon(
.then(modifier), .then(modifier),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Image( if (iconTintColor != null) {
imageVector = iconVector, Image(
contentDescription = iconContentDescription imageVector = iconVector,
) colorFilter = ColorFilter.tint(color = iconTintColor),
contentDescription = iconContentDescription,
)
} else {
Image(
imageVector = iconVector,
contentDescription = iconContentDescription
)
}
Spacer(modifier = Modifier.padding(3.dp)) Spacer(modifier = Modifier.padding(3.dp))
@ -402,7 +412,7 @@ fun BodyWithFiatCurrencySymbol(
Text( Text(
text = amount, text = amount,
style = MaterialTheme.typography.bodyLarge, style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onBackground, color = ZcashTheme.colors.textPrimary,
modifier = modifier modifier = modifier
) )
} }
@ -443,7 +453,7 @@ fun NavigationTabText(
}, },
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Visible, overflow = TextOverflow.Visible,
color = ZcashTheme.colors.textCommon, color = ZcashTheme.colors.textPrimary,
modifier = modifier =
Modifier Modifier
.clip(RoundedCornerShape(ZcashTheme.dimens.regularRippleEffectCorner)) .clip(RoundedCornerShape(ZcashTheme.dimens.regularRippleEffectCorner))

View File

@ -50,9 +50,10 @@ fun FormTextField(
keyboardOptions: KeyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text), keyboardOptions: KeyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
colors: TextFieldColors = colors: TextFieldColors =
TextFieldDefaults.colors( TextFieldDefaults.colors(
focusedContainerColor = ZcashTheme.colors.backgroundColor, cursorColor = ZcashTheme.colors.textPrimary,
unfocusedContainerColor = ZcashTheme.colors.backgroundColor, focusedContainerColor = Color.Transparent,
disabledContainerColor = ZcashTheme.colors.textDisabled, unfocusedContainerColor = Color.Transparent,
disabledContainerColor = Color.Transparent,
errorContainerColor = Color.Transparent, errorContainerColor = Color.Transparent,
focusedIndicatorColor = Color.Transparent, focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent, unfocusedIndicatorColor = Color.Transparent,

View File

@ -56,6 +56,16 @@ private fun TopAppBarTextComposablePreview() {
} }
} }
@Preview
@Composable
private fun TopAppBarTextDarkComposablePreview() {
ZcashTheme(forceDarkMode = true) {
BlankSurface {
SmallTopAppBar(titleText = "Screen A", backText = "Back")
}
}
}
@Preview @Preview
@Composable @Composable
private fun TopAppBarTextRestoringComposablePreview() { private fun TopAppBarTextRestoringComposablePreview() {
@ -108,6 +118,20 @@ private fun TopAppBarLogoRestoringComposablePreview() {
} }
} }
@Preview
@Composable
private fun TopAppBarLogoRestoringDarkComposablePreview() {
ZcashTheme(forceDarkMode = true) {
BlankSurface {
SmallTopAppBar(
showTitleLogo = true,
backText = "Back",
subTitle = "[RESTORING YOUR WALLET…]"
)
}
}
}
@Preview @Preview
@Composable @Composable
private fun TopAppBarRegularMenuComposablePreview() { private fun TopAppBarRegularMenuComposablePreview() {

View File

@ -24,6 +24,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
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.ColorFilter
import androidx.compose.ui.graphics.painter.ColorPainter import androidx.compose.ui.graphics.painter.ColorPainter
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
@ -68,6 +69,7 @@ fun WelcomeAnimationAutostart(
private const val LOGO_RELATIVE_LOCATION = 0.2f private const val LOGO_RELATIVE_LOCATION = 0.2f
@Composable @Composable
@Suppress("LongMethod")
fun WelcomeAnimation( fun WelcomeAnimation(
animationState: Boolean, animationState: Boolean,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
@ -111,6 +113,7 @@ fun WelcomeAnimation(
Image( Image(
painter = painterResource(id = R.drawable.chart_line), painter = painterResource(id = R.drawable.chart_line),
contentScale = ContentScale.FillBounds, contentScale = ContentScale.FillBounds,
colorFilter = ColorFilter.tint(color = ZcashTheme.colors.welcomeAnimationColor),
contentDescription = null, contentDescription = null,
) )
} }

View File

@ -84,7 +84,7 @@ private val defaultDimens =
buttonHeightSmall = 38.dp, buttonHeightSmall = 38.dp,
gridCellSize = 14.dp, gridCellSize = 14.dp,
gridLineWidth = 1.dp, gridLineWidth = 1.dp,
chipShadowElevation = 4.dp, chipShadowElevation = 2.dp,
chipStroke = 0.5.dp, chipStroke = 0.5.dp,
circularScreenProgressWidth = 48.dp, circularScreenProgressWidth = 48.dp,
circularMidProgressWidth = 22.dp, circularMidProgressWidth = 22.dp,

View File

@ -2,19 +2,22 @@ package co.electriccoin.zcash.ui.design.theme
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import co.electriccoin.zcash.ui.design.theme.internal.ButtonColors
import co.electriccoin.zcash.ui.design.theme.internal.TopAppBarColors import co.electriccoin.zcash.ui.design.theme.internal.TopAppBarColors
@Immutable @Immutable
data class ExtendedColors( data class ExtendedColors(
val primaryColor: Color,
val secondaryColor: Color,
val backgroundColor: Color, val backgroundColor: Color,
val gridColor: Color, val gridColor: Color,
val onBackgroundHeader: Color,
val circularProgressBarSmall: Color, val circularProgressBarSmall: Color,
val circularProgressBarSmallDark: Color, val circularProgressBarSmallDark: Color,
val circularProgressBarScreen: Color, val circularProgressBarScreen: Color,
val linearProgressBarTrack: Color, val linearProgressBarTrack: Color,
val linearProgressBarBackground: Color, val linearProgressBarBackground: Color,
val textCommon: Color, val textPrimary: Color,
val textSecondary: Color,
val textDescription: Color, val textDescription: Color,
val textDisabled: Color, val textDisabled: Color,
val textFieldHint: Color, val textFieldHint: Color,
@ -22,22 +25,27 @@ data class ExtendedColors(
val textFieldFrame: Color, val textFieldFrame: Color,
val textDescriptionDark: Color, val textDescriptionDark: Color,
val layoutStroke: Color, val layoutStroke: Color,
val layoutStrokeSecondary: Color,
val overlay: Color, val overlay: Color,
val overlayProgressBar: Color,
val reference: Color, val reference: Color,
val disabledButtonColor: Color, val primaryButtonColors: ButtonColors,
val disabledButtonTextColor: Color, val secondaryButtonColors: ButtonColors,
val tertiaryButtonColors: ButtonColors,
val welcomeAnimationColor: Color, val welcomeAnimationColor: Color,
val complementaryColor: Color, val complementaryColor: Color,
val dividerColor: Color, val primaryDividerColor: Color,
val darkDividerColor: Color, val secondaryDividerColor: Color,
val tertiaryDividerColor: Color,
val panelBackgroundColor: Color, val panelBackgroundColor: Color,
val panelBackgroundColorActive: Color,
val cameraDisabledBackgroundColor: Color, val cameraDisabledBackgroundColor: Color,
val cameraDisabledFrameColor: Color, val cameraDisabledFrameColor: Color,
val radioButtonColor: Color,
val radioButtonTextColor: Color,
val historyBackgroundColor: Color, val historyBackgroundColor: Color,
val historyMessageBubbleColor: Color,
val historyMessageBubbleStrokeColor: Color,
val historyRedColor: Color, val historyRedColor: Color,
val historySyncingColor: Color, val historySyncingColor: Color,
val topAppBarColors: TopAppBarColors, val topAppBarColors: TopAppBarColors,
val transparentTopAppBarColors: TopAppBarColors val transparentTopAppBarColors: TopAppBarColors,
) )

View File

@ -0,0 +1,123 @@
@file:Suppress("MagicNumber")
package co.electriccoin.zcash.ui.design.theme.internal
import androidx.compose.runtime.Immutable
import androidx.compose.ui.graphics.Color
@Immutable
interface ButtonColors {
val containerColor: Color
val disabledContainerColor: Color
val shadowColor: Color
val disabledShadowColor: Color
val textColor: Color
val disabledTextColor: Color
val strokeColor: Color
val disabledStrokeColor: Color
val shadowStrokeColor: Color
val shadowDisabledStrokeColor: Color
}
@Immutable
internal data class DefaultButtonColors(
override val containerColor: Color = Color.Unspecified,
override val disabledContainerColor: Color = Color.Unspecified,
override val shadowColor: Color = Color.Unspecified,
override val disabledShadowColor: Color = Color.Unspecified,
override val textColor: Color = Color.Unspecified,
override val disabledTextColor: Color = Color.Unspecified,
override val strokeColor: Color = Color.Unspecified,
override val disabledStrokeColor: Color = Color.Unspecified,
override val shadowStrokeColor: Color = Color.Unspecified,
override val shadowDisabledStrokeColor: Color = Color.Unspecified,
) : ButtonColors
// LIGHT THEME BUTTONS:
@Immutable
internal data class LightPrimaryButtonColors(
override val containerColor: Color = Color(0xFF000000),
override val disabledContainerColor: Color = Color(0xFFB7B7B7),
override val shadowColor: Color = Color(0xFFFFFFFF),
override val disabledShadowColor: Color = Color(0xFFFFFFFF),
override val textColor: Color = Color(0xFFFFFFFF),
override val disabledTextColor: Color = Color(0xFFDDDDDD),
override val strokeColor: Color = Color(0xFF000000),
override val disabledStrokeColor: Color = Color(0xFF000000),
override val shadowStrokeColor: Color = Color(0xFF000000),
override val shadowDisabledStrokeColor: Color = Color(0xFF000000),
) : ButtonColors
@Immutable
internal data class LightSecondaryButtonColors(
override val containerColor: Color = Color(0xFFFFFFFF),
override val disabledContainerColor: Color = Color(0xFFFFFFFF),
override val shadowColor: Color = Color(0xFF000000),
override val disabledShadowColor: Color = Color(0xFFFFFFFF),
override val textColor: Color = Color(0xFF000000),
override val disabledTextColor: Color = Color(0xFFDDDDDD),
override val strokeColor: Color = Color(0xFF000000),
override val disabledStrokeColor: Color = Color(0xFF000000),
override val shadowStrokeColor: Color = Color(0xFFE6E7E8),
override val shadowDisabledStrokeColor: Color = Color(0xFF000000),
) : ButtonColors
// Currently the same as Light-Primary version
@Immutable
internal data class LightTertiaryButtonColors(
override val containerColor: Color = Color(0xFF000000),
override val disabledContainerColor: Color = Color(0xFFB7B7B7),
override val shadowColor: Color = Color(0xFFFFFFFF),
override val disabledShadowColor: Color = Color(0xFFFFFFFF),
override val textColor: Color = Color(0xFFFFFFFF),
override val disabledTextColor: Color = Color(0xFFDDDDDD),
override val strokeColor: Color = Color(0xFF000000),
override val disabledStrokeColor: Color = Color(0xFF000000),
override val shadowStrokeColor: Color = Color(0xFF000000),
override val shadowDisabledStrokeColor: Color = Color(0xFF000000),
) : ButtonColors
// DARK THEME BUTTONS:
@Immutable
internal data class DarkPrimaryButtonColors(
override val containerColor: Color = Color(0xFF181716),
override val disabledContainerColor: Color = Color(0xFF4D4D4D),
override val shadowColor: Color = Color(0xFF181716),
override val disabledShadowColor: Color = Color(0xFF181716),
override val textColor: Color = Color(0xFFFFFFFF),
override val disabledTextColor: Color = Color(0xFFFFFFFF),
override val strokeColor: Color = Color(0xFFFFFFFF),
override val disabledStrokeColor: Color = Color(0xFFFFFFFF),
override val shadowStrokeColor: Color = Color(0xFFFFFFFF),
override val shadowDisabledStrokeColor: Color = Color(0xFFFFFFFF),
) : ButtonColors
@Immutable
internal data class DarkSecondaryButtonColors(
override val containerColor: Color = Color(0xFF181716),
override val disabledContainerColor: Color = Color(0xFFFFFFFF),
override val shadowColor: Color = Color(0xFF4D4D4D),
override val disabledShadowColor: Color = Color(0xFFFFFFFF),
override val textColor: Color = Color(0xFFFFFFFF),
override val disabledTextColor: Color = Color(0xFFB7B7B7),
override val strokeColor: Color = Color(0xFFFFFFFF),
override val disabledStrokeColor: Color = Color(0xFF000000),
override val shadowStrokeColor: Color = Color(0xFFFFFFFF),
override val shadowDisabledStrokeColor: Color = Color(0xFF000000),
) : ButtonColors
@Immutable
internal data class DarkTertiaryButtonColors(
override val containerColor: Color = Color(0xFFFFFFFF),
override val disabledContainerColor: Color = Color(0xFFFFFFFF),
override val shadowColor: Color = Color(0xFF000000),
override val disabledShadowColor: Color = Color(0xFFFFFFFF),
override val textColor: Color = Color(0xFF000000),
override val disabledTextColor: Color = Color(0xFFDDDDDD),
override val strokeColor: Color = Color(0xFF000000),
override val disabledStrokeColor: Color = Color(0xFF000000),
override val shadowStrokeColor: Color = Color(0xFFE6E7E8),
override val shadowDisabledStrokeColor: Color = Color(0xFF000000),
) : ButtonColors

View File

@ -8,108 +8,111 @@ import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import co.electriccoin.zcash.ui.design.theme.ExtendedColors import co.electriccoin.zcash.ui.design.theme.ExtendedColors
// TODO [#998]: Check and enhance screen dark mode
// TODO [#998]: https://github.com/Electric-Coin-Company/zashi-android/issues/998
internal object Dark { internal object Dark {
val backgroundColor = Color(0xFF231F20) val primaryColor = Color(0xFF231F20)
val secondaryColor = Color(0xFFFFFFFF)
val backgroundColor = primaryColor
val gridColor = Color(0xFF272727) val gridColor = Color(0xFF272727)
val textHeaderOnBackground = Color(0xFFFFFFFF) val textPrimary = secondaryColor
val textBodyOnBackground = Color(0xFFFFFFFF) val textSecondary = primaryColor
val textPrimaryButton = Color(0xFF000000) val textDisabled = Color(0xFF4D4D4D)
val textSecondaryButton = Color(0xFF000000) val textFieldFrame = Color(0xFFFFFFFF)
val textCommon = Color(0xFFFFFFFF) val textFieldWarning = Color(0xFFFE5858)
val textDisabled = Color(0xFFB7B7B7)
val textFieldFrame = Color(0xFF231F20)
val textFieldWarning = Color(0xFFF40202)
val textFieldHint = Color(0xFFB7B7B7) val textFieldHint = Color(0xFFB7B7B7)
val textDescription = Color(0xFF777777) val textDescription = Color(0xFFC1C1C1)
val textDescriptionDark = Color(0xFF4D4D4D) val textDescriptionDark = Color(0xFFFFFFFF)
val reference = Color(0xFFFFFFFF)
val welcomeAnimationColor = Color(0xFF231F20) val welcomeAnimationColor = Color(0xFF181716)
val complementaryColor = Color(0xFFF4B728) val complementaryColor = Color(0xFFF4B728)
val dividerColor = Color(0xFFDDDDDD)
val darkDividerColor = Color(0xFF000000) val primaryDividerColor = Color(0xFF4D4D4D)
val secondaryDividerColor = Color(0xFFFFFFFF)
val tertiaryDividerColor = Color(0xFF4D4D4D)
val panelBackgroundColor = Color(0xFF262324)
val panelBackgroundColorActive = Color(0xFF000000)
val layoutStroke = Color(0xFFFFFFFF) val layoutStroke = Color(0xFFFFFFFF)
val panelBackgroundColor = Color(0xFFF6F6F6) val layoutStrokeSecondary = Color(0xFFDDDDDD)
val cameraDisabledBackgroundColor = Color(0xFF5E5C5C) val cameraDisabledBackgroundColor = Color(0xFF000000)
val cameraDisabledFrameColor = Color(0xFFFFFFFF) val cameraDisabledFrameColor = Color(0xFF5E5C5C)
val primaryButton = Color(0xFFFFFFFF) val primaryButtonColors = DarkPrimaryButtonColors()
val secondaryButton = Color(0xFFFFFFFF) val secondaryButtonColors = DarkSecondaryButtonColors()
val tertiaryButtonColors = DarkTertiaryButtonColors()
val radioButtonColor = Color(0xFF070707) val circularProgressBarSmall = Color(0xFFFFFFFF)
val radioButtonTextColor = Color(0xFF4E4E4E) val circularProgressBarSmallDark = Color(0xFFFFFFFF)
val circularProgressBarSmall = Color(0xFF8B8A8A)
val circularProgressBarSmallDark = textBodyOnBackground
val circularProgressBarScreen = Color(0xFFFFFFFF) val circularProgressBarScreen = Color(0xFFFFFFFF)
val linearProgressBarTrack = Color(0xFFD9D9D9) val linearProgressBarTrack = Color(0xFFDDDDDD)
val linearProgressBarBackground = complementaryColor val linearProgressBarBackground = complementaryColor
val overlay = Color(0x22000000) val overlay = Color(0x22000000)
val overlayProgressBar = Color(0xFFFFFFFF)
val reference = Color(0xFFFFFFFF) val historyBackgroundColor = Color(0xFF262324)
val disabledButtonColor = Color(0xFFB7B7B7)
val disabledButtonTextColor = Color(0xFFDDDDDD)
val historyBackgroundColor = Color(0xFFF6F6F6)
val historyRedColor = textFieldWarning val historyRedColor = textFieldWarning
val historySyncingColor = panelBackgroundColor val historySyncingColor = Color(0xFF181716)
val historyMessageBubbleColor = Color(0xFF000000)
val historyMessageBubbleStrokeColor = Color(0xFF000000)
val topAppBarColors = DarkTopAppBarColors() val topAppBarColors = DarkTopAppBarColors()
val transparentTopAppBarColors = TransparentTopAppBarColors() val transparentTopAppBarColors = TransparentTopAppBarColors()
} }
internal object Light { internal object Light {
val backgroundColor = Color(0xFFFFFFFF) val primaryColor = Color(0xFFFFFFFF)
val secondaryColor = Color(0xFF000000)
val backgroundColor = primaryColor
val gridColor = Color(0xFFFBFBFB) val gridColor = Color(0xFFFBFBFB)
val textHeaderOnBackground = Color(0xFF000000) val textPrimary = secondaryColor
val textBodyOnBackground = Color(0xFF000000) val textSecondary = primaryColor
val textPrimaryButton = Color(0xFFFFFFFF)
val textSecondaryButton = Color(0xFF000000)
val textCommon = Color(0xFF000000)
val textDisabled = Color(0xFFB7B7B7) val textDisabled = Color(0xFFB7B7B7)
val textFieldFrame = Color(0xFF231F20) val textFieldFrame = Color(0xFF000000)
val textFieldWarning = Color(0xFFF40202) val textFieldWarning = Color(0xFFF40202)
val textFieldHint = Color(0xFFB7B7B7) val textFieldHint = Color(0xFFB7B7B7)
val textDescription = Color(0xFF777777) val textDescription = Color(0xFF777777)
val textDescriptionDark = Color(0xFF4D4D4D) val textDescriptionDark = Color(0xFF4D4D4D)
val reference = Color(0xFF000000)
val welcomeAnimationColor = Color(0xFF231F20) val welcomeAnimationColor = Color(0xFF231F20)
val complementaryColor = Color(0xFFF4B728) val complementaryColor = Color(0xFFF4B728)
val dividerColor = Color(0xFFDDDDDD)
val darkDividerColor = Color(0xFF000000) val primaryDividerColor = Color(0xFFDDDDDD)
val layoutStroke = Color(0xFF000000) val secondaryDividerColor = Color(0xFF000000)
val tertiaryDividerColor = Color(0xFF000000)
val panelBackgroundColor = Color(0xFFEBEBEB) val panelBackgroundColor = Color(0xFFEBEBEB)
val panelBackgroundColorActive = Color(0xFFFFFFFF)
val layoutStroke = Color(0xFF000000)
val layoutStrokeSecondary = Color(0xFFDDDDDD)
val cameraDisabledBackgroundColor = Color(0xFF5E5C5C) val cameraDisabledBackgroundColor = Color(0xFF5E5C5C)
val cameraDisabledFrameColor = Color(0xFFFFFFFF) val cameraDisabledFrameColor = Color(0xFFFFFFFF)
val primaryButton = Color(0xFF000000) val primaryButtonColors = LightPrimaryButtonColors()
val secondaryButton = Color(0xFFFFFFFF) val secondaryButtonColors = LightSecondaryButtonColors()
val tertiaryButtonColors = LightTertiaryButtonColors()
val radioButtonColor = Color(0xFF070707)
val radioButtonTextColor = Color(0xFF4E4E4E)
val circularProgressBarSmall = Color(0xFF8B8A8A) val circularProgressBarSmall = Color(0xFF8B8A8A)
val circularProgressBarSmallDark = textPrimary
val circularProgressBarScreen = Color(0xFF000000) val circularProgressBarScreen = Color(0xFF000000)
val circularProgressBarSmallDark = textBodyOnBackground val linearProgressBarTrack = Color(0xFFDDDDDD)
val linearProgressBarTrack = Color(0xFFD9D9D9)
val linearProgressBarBackground = complementaryColor val linearProgressBarBackground = complementaryColor
val overlay = Color(0x22000000) val overlay = Color(0x22000000)
val overlayProgressBar = Color(0xFFFFFFFF)
val reference = Color(0xFF000000)
val disabledButtonColor = Color(0xFFB7B7B7)
val disabledButtonTextColor = Color(0xFFDDDDDD)
val historyBackgroundColor = Color(0xFFF6F6F6) val historyBackgroundColor = Color(0xFFF6F6F6)
val historyRedColor = textFieldWarning val historyRedColor = textFieldWarning
val historySyncingColor = panelBackgroundColor val historySyncingColor = Color(0xFFEBEBEB)
val historyMessageBubbleColor = Color(0xFFDDDDDD)
val historyMessageBubbleStrokeColor = Color(0xFF000000)
val topAppBarColors = LightTopAppBarColors() val topAppBarColors = LightTopAppBarColors()
val transparentTopAppBarColors = TransparentTopAppBarColors() val transparentTopAppBarColors = TransparentTopAppBarColors()
@ -117,39 +120,43 @@ internal object Light {
internal val DarkColorPalette = internal val DarkColorPalette =
darkColorScheme( darkColorScheme(
primary = Dark.primaryButton, // Our colors intentionally use a different naming than the ones from MaterialTheme
secondary = Dark.secondaryButton, primary = Dark.textPrimary,
onPrimary = Dark.textPrimaryButton, secondary = Dark.secondaryColor,
onSecondary = Dark.textSecondaryButton, onPrimary = Dark.textPrimary,
onSecondary = Dark.textSecondary,
surface = Dark.backgroundColor, surface = Dark.backgroundColor,
onSurface = Dark.textBodyOnBackground, onSurface = Dark.textPrimary,
background = Dark.backgroundColor, background = Dark.backgroundColor,
onBackground = Dark.textBodyOnBackground, onBackground = Dark.textPrimary,
) )
internal val LightColorPalette = internal val LightColorPalette =
lightColorScheme( lightColorScheme(
primary = Light.primaryButton, // Our colors intentionally use a different naming than the ones from MaterialTheme
secondary = Light.secondaryButton, primary = Light.textPrimary,
onPrimary = Light.textPrimaryButton, secondary = Light.secondaryColor,
onSecondary = Light.textSecondaryButton, onPrimary = Light.textPrimary,
onSecondary = Light.textSecondary,
surface = Light.backgroundColor, surface = Light.backgroundColor,
onSurface = Light.textBodyOnBackground, onSurface = Light.textPrimary,
background = Light.backgroundColor, background = Light.backgroundColor,
onBackground = Light.textBodyOnBackground, onBackground = Light.textPrimary,
) )
internal val DarkExtendedColorPalette = internal val DarkExtendedColorPalette =
ExtendedColors( ExtendedColors(
primaryColor = Dark.primaryColor,
secondaryColor = Dark.secondaryColor,
backgroundColor = Dark.backgroundColor, backgroundColor = Dark.backgroundColor,
gridColor = Dark.gridColor, gridColor = Dark.gridColor,
onBackgroundHeader = Dark.textHeaderOnBackground,
circularProgressBarSmall = Dark.circularProgressBarSmall, circularProgressBarSmall = Dark.circularProgressBarSmall,
circularProgressBarSmallDark = Dark.circularProgressBarSmallDark, circularProgressBarSmallDark = Dark.circularProgressBarSmallDark,
circularProgressBarScreen = Dark.circularProgressBarScreen, circularProgressBarScreen = Dark.circularProgressBarScreen,
linearProgressBarTrack = Dark.linearProgressBarTrack, linearProgressBarTrack = Dark.linearProgressBarTrack,
linearProgressBarBackground = Dark.linearProgressBarBackground, linearProgressBarBackground = Dark.linearProgressBarBackground,
textCommon = Dark.textCommon, textPrimary = Dark.textPrimary,
textSecondary = Dark.textSecondary,
textDisabled = Dark.textDisabled, textDisabled = Dark.textDisabled,
textFieldFrame = Dark.textFieldFrame, textFieldFrame = Dark.textFieldFrame,
textFieldWarning = Dark.textFieldWarning, textFieldWarning = Dark.textFieldWarning,
@ -157,37 +164,44 @@ internal val DarkExtendedColorPalette =
textDescription = Dark.textDescription, textDescription = Dark.textDescription,
textDescriptionDark = Dark.textDescriptionDark, textDescriptionDark = Dark.textDescriptionDark,
layoutStroke = Dark.layoutStroke, layoutStroke = Dark.layoutStroke,
layoutStrokeSecondary = Dark.layoutStrokeSecondary,
overlay = Dark.overlay, overlay = Dark.overlay,
disabledButtonTextColor = Dark.disabledButtonTextColor, overlayProgressBar = Dark.overlayProgressBar,
disabledButtonColor = Dark.disabledButtonColor,
reference = Dark.reference, reference = Dark.reference,
welcomeAnimationColor = Dark.welcomeAnimationColor, welcomeAnimationColor = Dark.welcomeAnimationColor,
complementaryColor = Dark.complementaryColor, complementaryColor = Dark.complementaryColor,
dividerColor = Dark.dividerColor, primaryDividerColor = Dark.primaryDividerColor,
darkDividerColor = Dark.darkDividerColor, secondaryDividerColor = Dark.secondaryDividerColor,
tertiaryDividerColor = Dark.tertiaryDividerColor,
panelBackgroundColor = Dark.panelBackgroundColor, panelBackgroundColor = Dark.panelBackgroundColor,
panelBackgroundColorActive = Dark.panelBackgroundColorActive,
cameraDisabledBackgroundColor = Dark.cameraDisabledBackgroundColor, cameraDisabledBackgroundColor = Dark.cameraDisabledBackgroundColor,
cameraDisabledFrameColor = Dark.cameraDisabledFrameColor, cameraDisabledFrameColor = Dark.cameraDisabledFrameColor,
radioButtonColor = Dark.radioButtonColor,
radioButtonTextColor = Dark.radioButtonTextColor,
historyBackgroundColor = Dark.historyBackgroundColor, historyBackgroundColor = Dark.historyBackgroundColor,
historyRedColor = Dark.historyRedColor, historyRedColor = Dark.historyRedColor,
historySyncingColor = Dark.historySyncingColor, historySyncingColor = Dark.historySyncingColor,
historyMessageBubbleColor = Dark.historyMessageBubbleColor,
historyMessageBubbleStrokeColor = Dark.historyMessageBubbleStrokeColor,
topAppBarColors = Dark.topAppBarColors, topAppBarColors = Dark.topAppBarColors,
transparentTopAppBarColors = Dark.transparentTopAppBarColors transparentTopAppBarColors = Dark.transparentTopAppBarColors,
primaryButtonColors = Dark.primaryButtonColors,
secondaryButtonColors = Dark.secondaryButtonColors,
tertiaryButtonColors = Dark.tertiaryButtonColors,
) )
internal val LightExtendedColorPalette = internal val LightExtendedColorPalette =
ExtendedColors( ExtendedColors(
primaryColor = Light.primaryColor,
secondaryColor = Light.secondaryColor,
backgroundColor = Light.backgroundColor, backgroundColor = Light.backgroundColor,
gridColor = Light.gridColor, gridColor = Light.gridColor,
onBackgroundHeader = Light.textHeaderOnBackground,
circularProgressBarScreen = Light.circularProgressBarScreen, circularProgressBarScreen = Light.circularProgressBarScreen,
circularProgressBarSmall = Light.circularProgressBarSmall, circularProgressBarSmall = Light.circularProgressBarSmall,
circularProgressBarSmallDark = Light.circularProgressBarSmallDark, circularProgressBarSmallDark = Light.circularProgressBarSmallDark,
linearProgressBarTrack = Light.linearProgressBarTrack, linearProgressBarTrack = Light.linearProgressBarTrack,
linearProgressBarBackground = Light.linearProgressBarBackground, linearProgressBarBackground = Light.linearProgressBarBackground,
textCommon = Light.textCommon, textPrimary = Light.textPrimary,
textSecondary = Light.textSecondary,
textDisabled = Light.textDisabled, textDisabled = Light.textDisabled,
textFieldFrame = Light.textFieldFrame, textFieldFrame = Light.textFieldFrame,
textFieldWarning = Light.textFieldWarning, textFieldWarning = Light.textFieldWarning,
@ -195,39 +209,46 @@ internal val LightExtendedColorPalette =
textDescription = Light.textDescription, textDescription = Light.textDescription,
textDescriptionDark = Light.textDescriptionDark, textDescriptionDark = Light.textDescriptionDark,
layoutStroke = Light.layoutStroke, layoutStroke = Light.layoutStroke,
layoutStrokeSecondary = Light.layoutStrokeSecondary,
overlay = Light.overlay, overlay = Light.overlay,
disabledButtonTextColor = Light.disabledButtonTextColor, overlayProgressBar = Light.overlayProgressBar,
disabledButtonColor = Light.disabledButtonColor,
reference = Light.reference, reference = Light.reference,
welcomeAnimationColor = Light.welcomeAnimationColor, welcomeAnimationColor = Light.welcomeAnimationColor,
complementaryColor = Light.complementaryColor, complementaryColor = Light.complementaryColor,
dividerColor = Light.dividerColor, primaryDividerColor = Light.primaryDividerColor,
darkDividerColor = Light.darkDividerColor, secondaryDividerColor = Light.secondaryDividerColor,
tertiaryDividerColor = Light.tertiaryDividerColor,
panelBackgroundColor = Light.panelBackgroundColor, panelBackgroundColor = Light.panelBackgroundColor,
panelBackgroundColorActive = Light.panelBackgroundColorActive,
cameraDisabledBackgroundColor = Light.cameraDisabledBackgroundColor, cameraDisabledBackgroundColor = Light.cameraDisabledBackgroundColor,
cameraDisabledFrameColor = Light.cameraDisabledFrameColor, cameraDisabledFrameColor = Light.cameraDisabledFrameColor,
radioButtonColor = Light.radioButtonColor,
radioButtonTextColor = Light.radioButtonTextColor,
historyBackgroundColor = Light.historyBackgroundColor, historyBackgroundColor = Light.historyBackgroundColor,
historyRedColor = Light.historyRedColor, historyRedColor = Light.historyRedColor,
historySyncingColor = Light.historySyncingColor, historySyncingColor = Light.historySyncingColor,
historyMessageBubbleColor = Light.historyMessageBubbleColor,
historyMessageBubbleStrokeColor = Light.historyMessageBubbleStrokeColor,
topAppBarColors = Light.topAppBarColors, topAppBarColors = Light.topAppBarColors,
transparentTopAppBarColors = Light.transparentTopAppBarColors transparentTopAppBarColors = Light.transparentTopAppBarColors,
primaryButtonColors = Light.primaryButtonColors,
secondaryButtonColors = Light.secondaryButtonColors,
tertiaryButtonColors = Light.tertiaryButtonColors,
) )
@Suppress("CompositionLocalAllowlist") @Suppress("CompositionLocalAllowlist")
internal val LocalExtendedColors = internal val LocalExtendedColors =
staticCompositionLocalOf { staticCompositionLocalOf {
ExtendedColors( ExtendedColors(
primaryColor = Color.Unspecified,
secondaryColor = Color.Unspecified,
backgroundColor = Color.Unspecified, backgroundColor = Color.Unspecified,
gridColor = Color.Unspecified, gridColor = Color.Unspecified,
onBackgroundHeader = Color.Unspecified,
circularProgressBarScreen = Color.Unspecified, circularProgressBarScreen = Color.Unspecified,
circularProgressBarSmall = Color.Unspecified, circularProgressBarSmall = Color.Unspecified,
circularProgressBarSmallDark = Color.Unspecified, circularProgressBarSmallDark = Color.Unspecified,
linearProgressBarTrack = Color.Unspecified, linearProgressBarTrack = Color.Unspecified,
linearProgressBarBackground = Color.Unspecified, linearProgressBarBackground = Color.Unspecified,
textCommon = Color.Unspecified, textPrimary = Color.Unspecified,
textSecondary = Color.Unspecified,
textDisabled = Color.Unspecified, textDisabled = Color.Unspecified,
textFieldHint = Color.Unspecified, textFieldHint = Color.Unspecified,
textFieldWarning = Color.Unspecified, textFieldWarning = Color.Unspecified,
@ -235,23 +256,28 @@ internal val LocalExtendedColors =
textDescription = Color.Unspecified, textDescription = Color.Unspecified,
textDescriptionDark = Color.Unspecified, textDescriptionDark = Color.Unspecified,
layoutStroke = Color.Unspecified, layoutStroke = Color.Unspecified,
layoutStrokeSecondary = Color.Unspecified,
overlay = Color.Unspecified, overlay = Color.Unspecified,
disabledButtonTextColor = Color.Unspecified, overlayProgressBar = Color.Unspecified,
disabledButtonColor = Color.Unspecified,
reference = Color.Unspecified, reference = Color.Unspecified,
welcomeAnimationColor = Color.Unspecified, welcomeAnimationColor = Color.Unspecified,
complementaryColor = Color.Unspecified, complementaryColor = Color.Unspecified,
dividerColor = Color.Unspecified, primaryDividerColor = Color.Unspecified,
darkDividerColor = Color.Unspecified, secondaryDividerColor = Color.Unspecified,
tertiaryDividerColor = Color.Unspecified,
panelBackgroundColor = Color.Unspecified, panelBackgroundColor = Color.Unspecified,
panelBackgroundColorActive = Color.Unspecified,
cameraDisabledBackgroundColor = Color.Unspecified, cameraDisabledBackgroundColor = Color.Unspecified,
cameraDisabledFrameColor = Color.Unspecified, cameraDisabledFrameColor = Color.Unspecified,
radioButtonColor = Color.Unspecified,
radioButtonTextColor = Color.Unspecified,
historyBackgroundColor = Color.Unspecified, historyBackgroundColor = Color.Unspecified,
historyRedColor = Color.Unspecified, historyRedColor = Color.Unspecified,
historySyncingColor = Color.Unspecified, historySyncingColor = Color.Unspecified,
historyMessageBubbleColor = Color.Unspecified,
historyMessageBubbleStrokeColor = Color.Unspecified,
topAppBarColors = DefaultTopAppBarColors(), topAppBarColors = DefaultTopAppBarColors(),
transparentTopAppBarColors = DefaultTopAppBarColors(), transparentTopAppBarColors = DefaultTopAppBarColors(),
primaryButtonColors = DefaultButtonColors(),
secondaryButtonColors = DefaultButtonColors(),
tertiaryButtonColors = DefaultButtonColors(),
) )
} }

View File

@ -81,10 +81,10 @@ internal data class LightTopAppBarColors(
@Immutable @Immutable
internal data class DarkTopAppBarColors( internal data class DarkTopAppBarColors(
override val containerColor: Color = Color(0xFF000000), override val containerColor: Color = Color(0xFF231F20),
override val navigationColor: Color = Color(0xFFFFFFFF), override val navigationColor: Color = Color(0xFFFFFFFF),
override val titleColor: Color = Color(0xFFFFFFFF), override val titleColor: Color = Color(0xFFFFFFFF),
override val subTitleColor: Color = Color(0xFF8A8888), override val subTitleColor: Color = Color(0xFFFFFFFF),
override val actionColor: Color = Color(0xFFFFFFFF), override val actionColor: Color = Color(0xFFFFFFFF),
) : TopAppBarColors { ) : TopAppBarColors {
override fun copyColors( override fun copyColors(

View File

@ -57,8 +57,8 @@ internal val PrimaryTypography =
headlineLarge = headlineLarge =
TextStyle( TextStyle(
fontFamily = InterFontFamily, fontFamily = InterFontFamily,
fontWeight = FontWeight.SemiBold, fontWeight = FontWeight.Bold,
fontSize = 30.sp fontSize = 22.sp
), ),
titleSmall = titleSmall =
TextStyle( TextStyle(
@ -194,7 +194,6 @@ data class ExtendedTypography(
val transactionItemStyles: TransactionItemTextStyles, val transactionItemStyles: TransactionItemTextStyles,
val restoringTopAppBarStyle: TextStyle, val restoringTopAppBarStyle: TextStyle,
val deleteWalletWarnStyle: TextStyle, val deleteWalletWarnStyle: TextStyle,
val updateTitleStyle: TextStyle,
) )
@Suppress("CompositionLocalAllowlist") @Suppress("CompositionLocalAllowlist")
@ -379,9 +378,5 @@ val LocalExtendedTypography =
PrimaryTypography.bodyLarge.copy( PrimaryTypography.bodyLarge.copy(
fontWeight = FontWeight.Bold fontWeight = FontWeight.Bold
), ),
updateTitleStyle =
PrimaryTypography.titleLarge.copy(
fontWeight = FontWeight.Bold
)
) )
} }

View File

@ -4,6 +4,7 @@ import android.content.Intent
import android.provider.Settings import android.provider.Settings
import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest
import co.electriccoin.zcash.ui.test.getAppContext import co.electriccoin.zcash.ui.test.getAppContext
import co.electriccoin.zcash.ui.util.SettingsUtil
import org.junit.Test import org.junit.Test
import kotlin.test.assertContains import kotlin.test.assertContains
import kotlin.test.assertEquals import kotlin.test.assertEquals

View File

@ -14,7 +14,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
@ -50,7 +49,6 @@ import co.electriccoin.zcash.ui.screen.onboarding.WrapOnboarding
import co.electriccoin.zcash.ui.screen.onboarding.persistExistingWalletWithSeedPhrase import co.electriccoin.zcash.ui.screen.onboarding.persistExistingWalletWithSeedPhrase
import co.electriccoin.zcash.ui.screen.securitywarning.WrapSecurityWarning import co.electriccoin.zcash.ui.screen.securitywarning.WrapSecurityWarning
import co.electriccoin.zcash.ui.screen.support.WrapSupport import co.electriccoin.zcash.ui.screen.support.WrapSupport
import co.electriccoin.zcash.ui.screen.warning.WrapNotEnoughSpace
import co.electriccoin.zcash.ui.screen.warning.viewmodel.StorageCheckViewModel import co.electriccoin.zcash.ui.screen.warning.viewmodel.StorageCheckViewModel
import co.electriccoin.zcash.work.WorkIds import co.electriccoin.zcash.work.WorkIds
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@ -68,7 +66,6 @@ class MainActivity : AppCompatActivity() {
val walletViewModel by viewModels<WalletViewModel>() val walletViewModel by viewModels<WalletViewModel>()
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
val storageCheckViewModel by viewModels<StorageCheckViewModel>() val storageCheckViewModel by viewModels<StorageCheckViewModel>()
internal val authenticationViewModel by viewModels<AuthenticationViewModel> { internal val authenticationViewModel by viewModels<AuthenticationViewModel> {
@ -138,13 +135,7 @@ class MainActivity : AppCompatActivity() {
.fillMaxHeight() .fillMaxHeight()
) { ) {
BindCompLocalProvider { BindCompLocalProvider {
val isEnoughSpace by storageCheckViewModel.isEnoughSpace.collectAsStateWithLifecycle() MainContent()
if (isEnoughSpace == false) {
WrapNotEnoughSpace()
} else {
MainContent()
}
AuthenticationForAppAccess() AuthenticationForAppAccess()
} }
} }

View File

@ -1,6 +1,7 @@
package co.electriccoin.zcash.ui package co.electriccoin.zcash.ui
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.lifecycle.LifecycleCoroutineScope import androidx.lifecycle.LifecycleCoroutineScope
@ -29,6 +30,7 @@ import co.electriccoin.zcash.ui.NavigationTargets.CHOOSE_SERVER
import co.electriccoin.zcash.ui.NavigationTargets.DELETE_WALLET import co.electriccoin.zcash.ui.NavigationTargets.DELETE_WALLET
import co.electriccoin.zcash.ui.NavigationTargets.EXPORT_PRIVATE_DATA import co.electriccoin.zcash.ui.NavigationTargets.EXPORT_PRIVATE_DATA
import co.electriccoin.zcash.ui.NavigationTargets.HOME import co.electriccoin.zcash.ui.NavigationTargets.HOME
import co.electriccoin.zcash.ui.NavigationTargets.NOT_ENOUGH_SPACE
import co.electriccoin.zcash.ui.NavigationTargets.SCAN import co.electriccoin.zcash.ui.NavigationTargets.SCAN
import co.electriccoin.zcash.ui.NavigationTargets.SEED_RECOVERY import co.electriccoin.zcash.ui.NavigationTargets.SEED_RECOVERY
import co.electriccoin.zcash.ui.NavigationTargets.SEND_CONFIRMATION import co.electriccoin.zcash.ui.NavigationTargets.SEND_CONFIRMATION
@ -60,6 +62,7 @@ import co.electriccoin.zcash.ui.screen.sendconfirmation.model.SendConfirmationSt
import co.electriccoin.zcash.ui.screen.settings.WrapSettings import co.electriccoin.zcash.ui.screen.settings.WrapSettings
import co.electriccoin.zcash.ui.screen.support.WrapSupport import co.electriccoin.zcash.ui.screen.support.WrapSupport
import co.electriccoin.zcash.ui.screen.update.WrapCheckForUpdate import co.electriccoin.zcash.ui.screen.update.WrapCheckForUpdate
import co.electriccoin.zcash.ui.screen.warning.WrapNotEnoughSpace
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -247,6 +250,12 @@ internal fun MainActivity.Navigation() {
) )
} }
} }
composable(NOT_ENOUGH_SPACE) {
WrapNotEnoughSpace(
goPrevious = { navController.popBackStackJustOnce(NOT_ENOUGH_SPACE) },
goSettings = { navController.navigateJustOnce(SETTINGS) }
)
}
} }
} }
@ -291,11 +300,15 @@ private fun MainActivity.NavigationHome(
}, },
) )
val isEnoughSpace by storageCheckViewModel.isEnoughSpace.collectAsStateWithLifecycle()
val sdkStatus = walletViewModel.walletSnapshot.collectAsStateWithLifecycle().value?.status val sdkStatus = walletViewModel.walletSnapshot.collectAsStateWithLifecycle().value?.status
if (Synchronizer.Status.DISCONNECTED == sdkStatus) { if (isEnoughSpace == false) {
Twig.info { "Not enough free space" }
navController.navigateJustOnce(NOT_ENOUGH_SPACE)
} else if (Synchronizer.Status.DISCONNECTED == sdkStatus) {
Twig.info { "Disconnected state received from Synchronizer" } Twig.info { "Disconnected state received from Synchronizer" }
WrapDisconnected( WrapDisconnected(
goChooseServer = { goChooseServer = {
navController.navigateJustOnce(CHOOSE_SERVER) navController.navigateJustOnce(CHOOSE_SERVER)
@ -305,6 +318,7 @@ private fun MainActivity.NavigationHome(
} }
) )
} else if (ConfigurationEntries.IS_APP_UPDATE_CHECK_ENABLED.getValue(RemoteConfig.current)) { } else if (ConfigurationEntries.IS_APP_UPDATE_CHECK_ENABLED.getValue(RemoteConfig.current)) {
Twig.info { "App update available" }
WrapCheckForUpdate() WrapCheckForUpdate()
} }
} }
@ -421,6 +435,7 @@ object NavigationTargets {
const val EXPORT_PRIVATE_DATA = "export_private_data" const val EXPORT_PRIVATE_DATA = "export_private_data"
const val HOME = "home" const val HOME = "home"
const val CHOOSE_SERVER = "choose_server" const val CHOOSE_SERVER = "choose_server"
const val NOT_ENOUGH_SPACE = "not_enough_space"
const val SCAN = "scan" const val SCAN = "scan"
const val SEED_RECOVERY = "seed_recovery" const val SEED_RECOVERY = "seed_recovery"
const val SEND_CONFIRMATION = "send_confirmation" const val SEND_CONFIRMATION = "send_confirmation"

View File

@ -113,7 +113,10 @@ fun StatusDialog(
Column( Column(
Modifier.verticalScroll(rememberScrollState()) Modifier.verticalScroll(rememberScrollState())
) { ) {
Text(text = statusAction.details) Text(
text = statusAction.details,
color = ZcashTheme.colors.textPrimary,
)
} }
}, },
confirmButtonText = stringResource(id = R.string.balances_status_dialog_button), confirmButtonText = stringResource(id = R.string.balances_status_dialog_button),

View File

@ -28,6 +28,7 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
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.ColorFilter
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
@ -183,14 +184,17 @@ fun AboutMainContent(
) { ) {
Image( Image(
painter = painterResource(id = co.electriccoin.zcash.ui.design.R.drawable.zashi_logo_without_text), painter = painterResource(id = co.electriccoin.zcash.ui.design.R.drawable.zashi_logo_without_text),
colorFilter = ColorFilter.tint(color = ZcashTheme.colors.secondaryColor),
contentDescription = null, contentDescription = null,
Modifier modifier =
.height(ZcashTheme.dimens.inScreenZcashLogoHeight) Modifier
.width(ZcashTheme.dimens.inScreenZcashLogoWidth) .height(ZcashTheme.dimens.inScreenZcashLogoHeight)
.width(ZcashTheme.dimens.inScreenZcashLogoWidth)
) )
Spacer(modifier = Modifier.width(ZcashTheme.dimens.spacingDefault)) Spacer(modifier = Modifier.width(ZcashTheme.dimens.spacingDefault))
Image( Image(
painter = painterResource(id = co.electriccoin.zcash.ui.design.R.drawable.zashi_text_logo), painter = painterResource(id = co.electriccoin.zcash.ui.design.R.drawable.zashi_text_logo),
colorFilter = ColorFilter.tint(color = ZcashTheme.colors.secondaryColor),
contentDescription = null, contentDescription = null,
modifier = Modifier.height(ZcashTheme.dimens.inScreenZcashTextLogoHeight) modifier = Modifier.height(ZcashTheme.dimens.inScreenZcashTextLogoHeight)
) )

View File

@ -188,7 +188,7 @@ private fun AccountMainContent(
.padding(horizontal = ZcashTheme.dimens.screenHorizontalSpacingRegular) .padding(horizontal = ZcashTheme.dimens.screenHorizontalSpacingRegular)
) )
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingUpLarge)) Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge))
HistoryContainer( HistoryContainer(
onStatusClick = onStatusClick, onStatusClick = onStatusClick,

View File

@ -3,6 +3,7 @@
package co.electriccoin.zcash.ui.screen.account.view package co.electriccoin.zcash.ui.screen.account.view
import androidx.compose.animation.animateContentSize import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
@ -27,6 +28,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.pluralStringResource
@ -197,7 +199,7 @@ private fun EmptyTransactionHistory() {
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
text = stringResource(id = R.string.account_history_empty), text = stringResource(id = R.string.account_history_empty),
style = ZcashTheme.extendedTypography.transactionItemStyles.titleRegular, style = ZcashTheme.extendedTypography.transactionItemStyles.titleRegular,
color = ZcashTheme.colors.textCommon, color = ZcashTheme.colors.textPrimary,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis overflow = TextOverflow.Ellipsis
) )
@ -220,7 +222,7 @@ private fun HistoryList(
) )
HorizontalDivider( HorizontalDivider(
color = ZcashTheme.colors.dividerColor, color = ZcashTheme.colors.primaryDividerColor,
thickness = DividerDefaults.Thickness, thickness = DividerDefaults.Thickness,
modifier = Modifier.padding(horizontal = ZcashTheme.dimens.spacingDefault) modifier = Modifier.padding(horizontal = ZcashTheme.dimens.spacingDefault)
) )
@ -359,7 +361,9 @@ private fun HistoryItem(
) { ) {
Image( Image(
imageVector = typeIcon, imageVector = typeIcon,
contentDescription = typeText colorFilter = ColorFilter.tint(color = ZcashTheme.colors.secondaryColor),
contentDescription = typeText,
modifier = Modifier.padding(top = ZcashTheme.dimens.spacingTiny)
) )
Spacer(modifier = Modifier.width(ZcashTheme.dimens.spacingDefault)) Spacer(modifier = Modifier.width(ZcashTheme.dimens.spacingDefault))
@ -449,7 +453,7 @@ private fun HistoryItemCollapsedMainPart(
if (transaction.overview.isSentTransaction) { if (transaction.overview.isSentTransaction) {
ZcashTheme.colors.historyRedColor ZcashTheme.colors.historyRedColor
} else { } else {
ZcashTheme.colors.textCommon ZcashTheme.colors.textPrimary
} }
} }
@ -546,7 +550,7 @@ private fun HistoryItemExpandedAddressPart(
Text( Text(
text = recipient.addressValue, text = recipient.addressValue,
style = ZcashTheme.extendedTypography.transactionItemStyles.content, style = ZcashTheme.extendedTypography.transactionItemStyles.content,
color = ZcashTheme.colors.textCommon, color = ZcashTheme.colors.textPrimary,
modifier = modifier =
Modifier Modifier
.fillMaxWidth(EXPANDED_ADDRESS_WIDTH_RATIO) .fillMaxWidth(EXPANDED_ADDRESS_WIDTH_RATIO)
@ -559,6 +563,7 @@ private fun HistoryItemExpandedAddressPart(
style = ZcashTheme.extendedTypography.transactionItemStyles.content, style = ZcashTheme.extendedTypography.transactionItemStyles.content,
color = ZcashTheme.colors.textDescription, color = ZcashTheme.colors.textDescription,
iconVector = ImageVector.vectorResource(R.drawable.ic_trx_copy), iconVector = ImageVector.vectorResource(R.drawable.ic_trx_copy),
iconTintColor = ZcashTheme.colors.secondaryColor,
modifier = modifier =
Modifier Modifier
.clip(RoundedCornerShape(ZcashTheme.dimens.regularRippleEffectCorner)) .clip(RoundedCornerShape(ZcashTheme.dimens.regularRippleEffectCorner))
@ -608,7 +613,7 @@ private fun HistoryItemExpandedPart(
count = transaction.messages!!.size count = transaction.messages!!.size
), ),
style = ZcashTheme.extendedTypography.transactionItemStyles.contentMedium, style = ZcashTheme.extendedTypography.transactionItemStyles.contentMedium,
color = ZcashTheme.colors.textCommon color = ZcashTheme.colors.textPrimary
) )
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall)) Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall))
@ -632,7 +637,7 @@ private fun HistoryItemExpandedPart(
Text( Text(
text = stringResource(id = R.string.account_history_item_no_message), text = stringResource(id = R.string.account_history_item_no_message),
style = ZcashTheme.extendedTypography.transactionItemStyles.contentItalic, style = ZcashTheme.extendedTypography.transactionItemStyles.contentItalic,
color = ZcashTheme.colors.textCommon, color = ZcashTheme.colors.textPrimary,
modifier = Modifier.fillMaxWidth(EXPANDED_TRANSACTION_WIDTH_RATIO) modifier = Modifier.fillMaxWidth(EXPANDED_TRANSACTION_WIDTH_RATIO)
) )
@ -708,7 +713,7 @@ private fun HistoryItemTransactionIdPart(
Text( Text(
text = txIdString, text = txIdString,
style = ZcashTheme.extendedTypography.transactionItemStyles.content, style = ZcashTheme.extendedTypography.transactionItemStyles.content,
color = ZcashTheme.colors.textCommon, color = ZcashTheme.colors.textPrimary,
modifier = modifier =
Modifier Modifier
.fillMaxWidth(EXPANDED_TRANSACTION_WIDTH_RATIO) .fillMaxWidth(EXPANDED_TRANSACTION_WIDTH_RATIO)
@ -722,6 +727,7 @@ private fun HistoryItemTransactionIdPart(
style = ZcashTheme.extendedTypography.transactionItemStyles.content, style = ZcashTheme.extendedTypography.transactionItemStyles.content,
color = ZcashTheme.colors.textDescription, color = ZcashTheme.colors.textDescription,
iconVector = ImageVector.vectorResource(R.drawable.ic_trx_copy), iconVector = ImageVector.vectorResource(R.drawable.ic_trx_copy),
iconTintColor = ZcashTheme.colors.secondaryColor,
modifier = modifier =
Modifier Modifier
.clip(RoundedCornerShape(ZcashTheme.dimens.regularRippleEffectCorner)) .clip(RoundedCornerShape(ZcashTheme.dimens.regularRippleEffectCorner))
@ -825,20 +831,27 @@ private fun HistoryItemMessagePart(
textColor = ZcashTheme.colors.historyRedColor textColor = ZcashTheme.colors.historyRedColor
} else { } else {
textStyle = ZcashTheme.extendedTypography.transactionItemStyles.content textStyle = ZcashTheme.extendedTypography.transactionItemStyles.content
textColor = ZcashTheme.colors.textCommon textColor = ZcashTheme.colors.textPrimary
} }
Column(modifier = modifier.then(Modifier.fillMaxWidth())) { Column(modifier = modifier.then(Modifier.fillMaxWidth())) {
val (messageBackground, arrowAlignment) = val bubbleBackgroundColor: Color
if (state.isSendType()) { val bubbleStroke: BorderStroke
Color.Transparent to BubbleArrowAlignment.BottomLeft val arrowAlignment: BubbleArrowAlignment
} else { if (state.isSendType()) {
ZcashTheme.colors.dividerColor to BubbleArrowAlignment.BottomRight bubbleBackgroundColor = Color.Transparent
} bubbleStroke = BorderStroke(1.dp, ZcashTheme.colors.textFieldFrame)
arrowAlignment = BubbleArrowAlignment.BottomLeft
} else {
bubbleBackgroundColor = ZcashTheme.colors.historyMessageBubbleColor
bubbleStroke = BorderStroke(1.dp, ZcashTheme.colors.historyMessageBubbleStrokeColor)
arrowAlignment = BubbleArrowAlignment.BottomRight
}
BubbleMessage( BubbleMessage(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
backgroundColor = messageBackground, backgroundColor = bubbleBackgroundColor,
borderStroke = bubbleStroke,
arrowAlignment = arrowAlignment arrowAlignment = arrowAlignment
) { ) {
Text( Text(
@ -856,6 +869,7 @@ private fun HistoryItemMessagePart(
style = ZcashTheme.extendedTypography.transactionItemStyles.content, style = ZcashTheme.extendedTypography.transactionItemStyles.content,
color = ZcashTheme.colors.textDescription, color = ZcashTheme.colors.textDescription,
iconVector = ImageVector.vectorResource(R.drawable.ic_trx_copy), iconVector = ImageVector.vectorResource(R.drawable.ic_trx_copy),
iconTintColor = ZcashTheme.colors.secondaryColor,
modifier = modifier =
Modifier Modifier
.clip(RoundedCornerShape(ZcashTheme.dimens.regularRippleEffectCorner)) .clip(RoundedCornerShape(ZcashTheme.dimens.regularRippleEffectCorner))

View File

@ -30,9 +30,9 @@ private fun PreviewAppAccessAuthentication() {
} }
} }
@Preview("Error Authentication") @Preview
@Composable @Composable
private fun PreviewErrorAuthentication() { private fun ErrorAuthenticationPreview() {
ZcashTheme(forceDarkMode = false) { ZcashTheme(forceDarkMode = false) {
BlankSurface { BlankSurface {
AuthenticationErrorDialog( AuthenticationErrorDialog(
@ -45,6 +45,21 @@ private fun PreviewErrorAuthentication() {
} }
} }
@Preview
@Composable
private fun ErrorAuthenticationDarkPreview() {
ZcashTheme(forceDarkMode = true) {
BlankSurface {
AuthenticationErrorDialog(
onDismiss = {},
onRetry = {},
onSupport = {},
reason = AuthenticationResult.Error(errorCode = -1, errorMessage = "Test Error Message")
)
}
}
}
@Composable @Composable
fun AppAccessAuthentication( fun AppAccessAuthentication(
welcomeAnimVisibility: Boolean, welcomeAnimVisibility: Boolean,
@ -69,7 +84,10 @@ fun AuthenticationErrorDialog(
Column( Column(
Modifier.verticalScroll(rememberScrollState()) Modifier.verticalScroll(rememberScrollState())
) { ) {
Text(text = stringResource(id = R.string.authentication_error_text)) Text(
text = stringResource(id = R.string.authentication_error_text),
color = ZcashTheme.colors.textPrimary,
)
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault)) Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault))
@ -80,7 +98,8 @@ fun AuthenticationErrorDialog(
reason.errorCode, reason.errorCode,
reason.errorMessage, reason.errorMessage,
), ),
fontStyle = FontStyle.Italic fontStyle = FontStyle.Italic,
color = ZcashTheme.colors.textPrimary,
) )
} }
}, },
@ -102,7 +121,10 @@ fun AuthenticationFailedDialog(
title = stringResource(id = R.string.authentication_failed_title), title = stringResource(id = R.string.authentication_failed_title),
text = { text = {
Column(Modifier.verticalScroll(rememberScrollState())) { Column(Modifier.verticalScroll(rememberScrollState())) {
Text(text = stringResource(id = R.string.authentication_failed_text)) Text(
text = stringResource(id = R.string.authentication_failed_text),
color = ZcashTheme.colors.textPrimary,
)
} }
}, },
confirmButtonText = stringResource(id = R.string.authentication_failed_button_retry), confirmButtonText = stringResource(id = R.string.authentication_failed_button_retry),

View File

@ -36,7 +36,6 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
@ -88,7 +87,7 @@ import co.electriccoin.zcash.ui.screen.balances.model.ShieldState
import co.electriccoin.zcash.ui.screen.balances.model.StatusAction import co.electriccoin.zcash.ui.screen.balances.model.StatusAction
import co.electriccoin.zcash.ui.screen.balances.model.WalletDisplayValues import co.electriccoin.zcash.ui.screen.balances.model.WalletDisplayValues
@Preview("Balances") @Preview
@Composable @Composable
private fun ComposableBalancesPreview() { private fun ComposableBalancesPreview() {
ZcashTheme(forceDarkMode = false) { ZcashTheme(forceDarkMode = false) {
@ -112,10 +111,10 @@ private fun ComposableBalancesPreview() {
} }
} }
@Preview("BalancesShieldFailure") @Preview
@Composable @Composable
private fun ComposableBalancesShieldFailurePreview() { private fun ComposableBalancesShieldDarkPreview() {
ZcashTheme(forceDarkMode = false) { ZcashTheme(forceDarkMode = true) {
Balances( Balances(
balanceState = BalanceStateFixture.new(), balanceState = BalanceStateFixture.new(),
isFiatConversionEnabled = false, isFiatConversionEnabled = false,
@ -234,14 +233,18 @@ fun ShieldingErrorDialog(
Column( Column(
Modifier.verticalScroll(rememberScrollState()) Modifier.verticalScroll(rememberScrollState())
) { ) {
Text(text = stringResource(id = R.string.balances_shielding_dialog_error_text)) Text(
text = stringResource(id = R.string.balances_shielding_dialog_error_text),
color = ZcashTheme.colors.textPrimary,
)
if (reason.isNotEmpty()) { if (reason.isNotEmpty()) {
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault)) Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault))
Text( Text(
text = reason, text = reason,
fontStyle = FontStyle.Italic fontStyle = FontStyle.Italic,
color = ZcashTheme.colors.textPrimary,
) )
} }
} }
@ -308,10 +311,10 @@ private fun BalancesMainContent(
onReferenceClick = {} onReferenceClick = {}
) )
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingUpLarge)) Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge))
HorizontalDivider( HorizontalDivider(
color = ZcashTheme.colors.darkDividerColor, color = ZcashTheme.colors.tertiaryDividerColor,
thickness = ZcashTheme.dimens.divider thickness = ZcashTheme.dimens.divider
) )
@ -490,7 +493,7 @@ fun TransparentBalanceHelpPanel(onHideHelpPanel: () -> Unit) {
modifier = modifier =
Modifier Modifier
.padding(all = ZcashTheme.dimens.spacingDefault) .padding(all = ZcashTheme.dimens.spacingDefault)
.background(color = Color.White) .background(color = ZcashTheme.colors.panelBackgroundColorActive)
.fillMaxSize(), .fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
) { ) {
@ -592,7 +595,7 @@ fun SpendableBalanceRow(walletSnapshot: WalletSnapshot) {
ZcashTheme.extendedTypography.balanceSingleStyles.first, ZcashTheme.extendedTypography.balanceSingleStyles.first,
ZcashTheme.extendedTypography.balanceSingleStyles.second ZcashTheme.extendedTypography.balanceSingleStyles.second
), ),
textColor = ZcashTheme.colors.textCommon textColor = ZcashTheme.colors.textPrimary
) )
Spacer(modifier = Modifier.width(12.dp)) Spacer(modifier = Modifier.width(12.dp))

View File

@ -107,7 +107,7 @@ fun ChooseServer(
options[CUSTOM_SERVER_OPTION_INDEX].run { options[CUSTOM_SERVER_OPTION_INDEX].run {
if (options[CUSTOM_SERVER_OPTION_INDEX].isValid()) { if (options[CUSTOM_SERVER_OPTION_INDEX].isValid()) {
stringResource( stringResource(
R.string.choose_server_textfield_value, R.string.choose_server_full_server_name,
options[CUSTOM_SERVER_OPTION_INDEX].host, options[CUSTOM_SERVER_OPTION_INDEX].host,
options[CUSTOM_SERVER_OPTION_INDEX].port options[CUSTOM_SERVER_OPTION_INDEX].port
) )
@ -194,7 +194,7 @@ fun ChooseServerBottomBar(
) { ) {
HorizontalDivider( HorizontalDivider(
thickness = DividerDefaults.Thickness, thickness = DividerDefaults.Thickness,
color = ZcashTheme.colors.dividerColor color = ZcashTheme.colors.primaryDividerColor
) )
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall)) Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall))
@ -239,6 +239,8 @@ private fun ChooseServerTopAppBar(
) )
} }
// When changing the following constants, be aware that they should not be the same
const val DEFAULT_SERVER_OPTION_INDEX = 0
const val CUSTOM_SERVER_OPTION_INDEX = 1 const val CUSTOM_SERVER_OPTION_INDEX = 1
@Composable @Composable
@ -269,7 +271,7 @@ private fun ChooseServerMainContent(
@OptIn(ExperimentalFoundationApi::class) @OptIn(ExperimentalFoundationApi::class)
@Composable @Composable
@Suppress("LongParameterList") @Suppress("LongParameterList", "LongMethod")
fun ServerList( fun ServerList(
options: ImmutableList<LightWalletEndpoint>, options: ImmutableList<LightWalletEndpoint>,
customServerValue: String, customServerValue: String,
@ -282,59 +284,84 @@ fun ServerList(
options.forEachIndexed { index, endpoint -> options.forEachIndexed { index, endpoint ->
val isSelected = index == selectedOption val isSelected = index == selectedOption
if (index == CUSTOM_SERVER_OPTION_INDEX) { when (index) {
Column( DEFAULT_SERVER_OPTION_INDEX -> {
modifier = Modifier.animateContentSize()
) {
LabeledRadioButton( LabeledRadioButton(
endpoint = endpoint, endpoint = endpoint,
changeClick = { setSelectedOption(index) }, changeClick = { setSelectedOption(index) },
name = stringResource(id = R.string.choose_server_custom), name =
stringResource(
id = R.string.choose_server_default_label,
stringResource(
id = R.string.choose_server_full_server_name,
endpoint.host,
endpoint.port
)
),
selected = isSelected, selected = isSelected,
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) )
}
if (isSelected) { CUSTOM_SERVER_OPTION_INDEX -> {
val focusManager = LocalFocusManager.current Column(
modifier = Modifier.animateContentSize()
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall)) ) {
LabeledRadioButton(
FormTextField( endpoint = endpoint,
value = customServerValue, changeClick = { setSelectedOption(index) },
onValueChange = { name = stringResource(id = R.string.choose_server_custom),
setCustomServerValue(it) selected = isSelected,
}, modifier = Modifier.fillMaxWidth()
placeholder = {
Text(text = stringResource(R.string.choose_server_textfield_hint))
},
keyboardActions =
KeyboardActions(
onDone = {
focusManager.clearFocus(true)
}
),
keyboardOptions =
KeyboardOptions(
keyboardType = KeyboardType.Uri,
imeAction = ImeAction.Done
),
modifier =
Modifier
.fillMaxWidth()
.padding(horizontal = ZcashTheme.dimens.spacingSmall)
) )
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall)) if (isSelected) {
val focusManager = LocalFocusManager.current
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall))
FormTextField(
value = customServerValue,
onValueChange = {
setCustomServerValue(it)
},
placeholder = {
Text(text = stringResource(R.string.choose_server_textfield_hint))
},
keyboardActions =
KeyboardActions(
onDone = {
focusManager.clearFocus(true)
}
),
keyboardOptions =
KeyboardOptions(
keyboardType = KeyboardType.Uri,
imeAction = ImeAction.Done
),
modifier =
Modifier
.fillMaxWidth()
.padding(horizontal = ZcashTheme.dimens.spacingSmall)
)
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall))
}
} }
} }
} else { else -> {
LabeledRadioButton( LabeledRadioButton(
endpoint = endpoint, endpoint = endpoint,
changeClick = { setSelectedOption(index) }, changeClick = { setSelectedOption(index) },
name = stringResource(id = R.string.choose_server_textfield_value, endpoint.host, endpoint.port), name =
selected = isSelected, stringResource(
modifier = Modifier.fillMaxWidth() id = R.string.choose_server_full_server_name,
) endpoint.host,
endpoint.port
),
selected = isSelected,
modifier = Modifier.fillMaxWidth()
)
}
} }
} }
} }
@ -357,7 +384,7 @@ fun LabeledRadioButton(
text = name, text = name,
selected = selected, selected = selected,
onClick = { changeClick(endpoint) }, onClick = { changeClick(endpoint) },
modifier = modifier modifier = modifier,
) )
} }

View File

@ -10,7 +10,6 @@ import co.electriccoin.zcash.ui.design.component.BlankSurface
import co.electriccoin.zcash.ui.design.component.Body import co.electriccoin.zcash.ui.design.component.Body
import co.electriccoin.zcash.ui.design.component.ChipIndexed import co.electriccoin.zcash.ui.design.component.ChipIndexed
import co.electriccoin.zcash.ui.design.component.Header import co.electriccoin.zcash.ui.design.component.Header
import co.electriccoin.zcash.ui.design.component.NavigationButton
import co.electriccoin.zcash.ui.design.component.PrimaryButton import co.electriccoin.zcash.ui.design.component.PrimaryButton
import co.electriccoin.zcash.ui.design.component.SecondaryButton import co.electriccoin.zcash.ui.design.component.SecondaryButton
import co.electriccoin.zcash.ui.design.theme.ZcashTheme import co.electriccoin.zcash.ui.design.theme.ZcashTheme
@ -31,8 +30,6 @@ fun DesignGuide() {
Column { Column {
Header(text = "H1") Header(text = "H1")
Body(text = "body") Body(text = "body")
NavigationButton(onClick = { }, text = "Back")
NavigationButton(onClick = { }, text = "Next")
PrimaryButton(onClick = { }, text = "Primary button", outerPaddingValues = PaddingValues(24.dp)) PrimaryButton(onClick = { }, text = "Primary button", outerPaddingValues = PaddingValues(24.dp))
SecondaryButton(onClick = { }, text = "Secondary button", outerPaddingValues = PaddingValues(24.dp)) SecondaryButton(onClick = { }, text = "Secondary button", outerPaddingValues = PaddingValues(24.dp))
ChipIndexed(Index(1), "edict") ChipIndexed(Index(1), "edict")

View File

@ -1,6 +1,7 @@
package co.electriccoin.zcash.ui.screen.deletewallet.view package co.electriccoin.zcash.ui.screen.deletewallet.view
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
@ -23,9 +24,9 @@ import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
import co.electriccoin.zcash.ui.design.component.Body import co.electriccoin.zcash.ui.design.component.Body
import co.electriccoin.zcash.ui.design.component.CheckBox
import co.electriccoin.zcash.ui.design.component.GridBgScaffold import co.electriccoin.zcash.ui.design.component.GridBgScaffold
import co.electriccoin.zcash.ui.design.component.GridBgSmallTopAppBar import co.electriccoin.zcash.ui.design.component.GridBgSmallTopAppBar
import co.electriccoin.zcash.ui.design.component.LabeledCheckBox
import co.electriccoin.zcash.ui.design.component.PrimaryButton import co.electriccoin.zcash.ui.design.component.PrimaryButton
import co.electriccoin.zcash.ui.design.component.TopScreenLogoTitle import co.electriccoin.zcash.ui.design.component.TopScreenLogoTitle
import co.electriccoin.zcash.ui.design.theme.ZcashTheme import co.electriccoin.zcash.ui.design.theme.ZcashTheme
@ -129,17 +130,15 @@ private fun DeleteWalletContent(
Spacer(Modifier.height(ZcashTheme.dimens.spacingDefault)) Spacer(Modifier.height(ZcashTheme.dimens.spacingDefault))
val checkedState = rememberSaveable { mutableStateOf(false) } val checkedState = rememberSaveable { mutableStateOf(false) }
CheckBox( Row(Modifier.fillMaxWidth()) {
modifier = LabeledCheckBox(
Modifier checked = checkedState.value,
.align(Alignment.Start) onCheckedChange = {
.fillMaxWidth(), checkedState.value = it
checked = checkedState.value, },
onCheckedChange = { text = stringResource(R.string.delete_wallet_acknowledge),
checkedState.value = it )
}, }
text = stringResource(R.string.delete_wallet_acknowledge),
)
Spacer( Spacer(
modifier = modifier =

View File

@ -48,7 +48,10 @@ fun ServerDisconnectedDialog(
Column( Column(
Modifier.verticalScroll(rememberScrollState()) Modifier.verticalScroll(rememberScrollState())
) { ) {
Text(text = stringResource(id = R.string.server_disconnected_dialog_message)) Text(
text = stringResource(id = R.string.server_disconnected_dialog_message),
color = ZcashTheme.colors.textPrimary,
)
} }
}, },
confirmButtonText = stringResource(id = R.string.server_disconnected_dialog_switch_btn), confirmButtonText = stringResource(id = R.string.server_disconnected_dialog_switch_btn),

View File

@ -1,6 +1,7 @@
package co.electriccoin.zcash.ui.screen.exportdata.view package co.electriccoin.zcash.ui.screen.exportdata.view
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
@ -25,9 +26,9 @@ import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
import co.electriccoin.zcash.ui.design.component.Body import co.electriccoin.zcash.ui.design.component.Body
import co.electriccoin.zcash.ui.design.component.CheckBox
import co.electriccoin.zcash.ui.design.component.GridBgScaffold import co.electriccoin.zcash.ui.design.component.GridBgScaffold
import co.electriccoin.zcash.ui.design.component.GridBgSmallTopAppBar import co.electriccoin.zcash.ui.design.component.GridBgSmallTopAppBar
import co.electriccoin.zcash.ui.design.component.LabeledCheckBox
import co.electriccoin.zcash.ui.design.component.PrimaryButton import co.electriccoin.zcash.ui.design.component.PrimaryButton
import co.electriccoin.zcash.ui.design.component.TopScreenLogoTitle import co.electriccoin.zcash.ui.design.component.TopScreenLogoTitle
import co.electriccoin.zcash.ui.design.theme.ZcashTheme import co.electriccoin.zcash.ui.design.theme.ZcashTheme
@ -46,9 +47,6 @@ private fun ExportPrivateDataPreview() {
} }
} }
// TODO [#998]: Check and enhance screen dark mode
// TODO [#998]: https://github.com/Electric-Coin-Company/zashi-android/issues/998
@Composable @Composable
fun ExportPrivateData( fun ExportPrivateData(
snackbarHostState: SnackbarHostState, snackbarHostState: SnackbarHostState,
@ -134,19 +132,17 @@ private fun ExportPrivateDataContent(
Spacer(Modifier.height(ZcashTheme.dimens.spacingDefault)) Spacer(Modifier.height(ZcashTheme.dimens.spacingDefault))
val checkedState = rememberSaveable { mutableStateOf(false) } val checkedState = rememberSaveable { mutableStateOf(false) }
CheckBox( Row(Modifier.fillMaxWidth()) {
modifier = LabeledCheckBox(
Modifier checked = checkedState.value,
.align(Alignment.Start) onCheckedChange = {
.fillMaxWidth(), checkedState.value = it
checked = checkedState.value, onAgree(it)
onCheckedChange = { },
checkedState.value = it text = stringResource(R.string.export_data_agree),
onAgree(it) checkBoxTestTag = ExportPrivateDataScreenTag.AGREE_CHECKBOX_TAG
}, )
text = stringResource(R.string.export_data_agree), }
checkBoxTestTag = ExportPrivateDataScreenTag.AGREE_CHECKBOX_TAG
)
Spacer( Spacer(
modifier = modifier =

View File

@ -173,7 +173,7 @@ fun HomeContent(
) { ) {
HorizontalDivider( HorizontalDivider(
thickness = DividerDefaults.Thickness, thickness = DividerDefaults.Thickness,
color = ZcashTheme.colors.dividerColor color = ZcashTheme.colors.primaryDividerColor
) )
TabRow( TabRow(
selectedTabIndex = pagerState.currentPage, selectedTabIndex = pagerState.currentPage,

View File

@ -52,9 +52,9 @@ import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toPersistentList
@Preview(name = "NewWalletRecovery") @Preview
@Composable @Composable
private fun ComposablePreview() { private fun NewWalletRecoveryPreview() {
ZcashTheme(forceDarkMode = false) { ZcashTheme(forceDarkMode = false) {
NewWalletRecovery( NewWalletRecovery(
PersistableWalletFixture.new(), PersistableWalletFixture.new(),
@ -66,8 +66,19 @@ private fun ComposablePreview() {
} }
} }
// TODO [#998]: Check and enhance screen dark mode @Preview
// TODO [#998]: https://github.com/Electric-Coin-Company/zashi-android/issues/998 @Composable
private fun NewWalletRecoveryDarkPreview() {
ZcashTheme(forceDarkMode = true) {
NewWalletRecovery(
PersistableWalletFixture.new(),
onSeedCopy = {},
onBirthdayCopy = {},
onComplete = {},
versionInfo = VersionInfoFixture.new(),
)
}
}
/** /**
* @param onComplete Callback when the user has confirmed viewing the seed phrase. * @param onComplete Callback when the user has confirmed viewing the seed phrase.

View File

@ -17,6 +17,7 @@ import androidx.compose.foundation.verticalScroll
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.ColorFilter
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.style.TextAlign import androidx.compose.ui.text.style.TextAlign
@ -43,8 +44,18 @@ private fun OnboardingComposablePreview() {
} }
} }
// TODO [#998]: Check and enhance screen dark mode @Preview("Onboarding")
// TODO [#998]: https://github.com/Electric-Coin-Company/zashi-android/issues/998 @Composable
private fun OnboardingComposableDarkPreview() {
ZcashTheme(forceDarkMode = true) {
Onboarding(
isDebugMenuEnabled = true,
onImportWallet = {},
onCreateWallet = {},
onFixtureWallet = {}
)
}
}
// TODO [#1001]: Screens in landscape mode // TODO [#1001]: Screens in landscape mode
// TODO [#1001]: https://github.com/Electric-Coin-Company/zashi-android/issues/1001 // TODO [#1001]: https://github.com/Electric-Coin-Company/zashi-android/issues/1001
@ -108,16 +119,18 @@ private fun OnboardingMainContent(
} }
Image( Image(
painterResource(id = co.electriccoin.zcash.ui.design.R.drawable.zashi_logo_without_text), painter = painterResource(id = co.electriccoin.zcash.ui.design.R.drawable.zashi_logo_without_text),
stringResource(R.string.zcash_logo_content_description), colorFilter = ColorFilter.tint(color = ZcashTheme.colors.secondaryColor),
contentDescription = stringResource(R.string.zcash_logo_content_description),
modifier = imageModifier modifier = imageModifier
) )
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault)) Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault))
Image( Image(
painterResource(id = co.electriccoin.zcash.ui.design.R.drawable.zashi_text_logo), painter = painterResource(id = co.electriccoin.zcash.ui.design.R.drawable.zashi_text_logo),
"" colorFilter = ColorFilter.tint(color = ZcashTheme.colors.secondaryColor),
contentDescription = null,
) )
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingUpLarge)) Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingUpLarge))

View File

@ -17,6 +17,8 @@ object AndroidQrCodeImageGenerator : QrCodeImageGenerator {
} }
} }
// TODO [#1473]: Dark mode QR codes for Receive screen
// TODO [#1473]: https://github.com/Electric-Coin-Company/zashi-android/issues/1473
private fun BooleanArray.toBlackAndWhiteColorArray() = private fun BooleanArray.toBlackAndWhiteColorArray() =
IntArray(size) { IntArray(size) {
if (this[it]) { if (this[it]) {

View File

@ -1,14 +1,24 @@
package co.electriccoin.zcash.ui.screen.receive.util package co.electriccoin.zcash.ui.screen.receive.util
import com.google.zxing.BarcodeFormat import com.google.zxing.BarcodeFormat
import com.google.zxing.EncodeHintType
import com.google.zxing.qrcode.QRCodeWriter import com.google.zxing.qrcode.QRCodeWriter
const val QR_CODE_IMAGE_MARGIN_IN_PIXELS = 2
object JvmQrCodeGenerator : QrCodeGenerator { object JvmQrCodeGenerator : QrCodeGenerator {
override fun generate( override fun generate(
data: String, data: String,
sizePixels: Int sizePixels: Int
): BooleanArray { ): BooleanArray {
val bitMatrix = QRCodeWriter().encode(data, BarcodeFormat.QR_CODE, sizePixels, sizePixels) val bitMatrix =
QRCodeWriter().encode(
data,
BarcodeFormat.QR_CODE,
sizePixels,
sizePixels,
mapOf(EncodeHintType.MARGIN to QR_CODE_IMAGE_MARGIN_IN_PIXELS)
)
return BooleanArray(sizePixels * sizePixels).apply { return BooleanArray(sizePixels * sizePixels).apply {
var booleanArrayPosition = 0 var booleanArrayPosition = 0

View File

@ -16,6 +16,7 @@ import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
@ -28,6 +29,8 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
@ -61,6 +64,40 @@ import kotlinx.collections.immutable.toPersistentList
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import kotlin.math.roundToInt import kotlin.math.roundToInt
@Preview
@Composable
private fun ReceivePreview() =
ZcashTheme(forceDarkMode = false) {
Receive(
screenBrightnessState = ScreenBrightnessState.NORMAL,
walletAddress = runBlocking { WalletAddressesFixture.new() },
snackbarHostState = SnackbarHostState(),
onSettings = {},
onAdjustBrightness = {},
onAddrCopyToClipboard = {},
onQrImageShare = {},
versionInfo = VersionInfoFixture.new(),
topAppBarSubTitleState = TopAppBarSubTitleState.None,
)
}
@Preview
@Composable
private fun ReceiveDarkPreview() =
ZcashTheme(forceDarkMode = true) {
Receive(
screenBrightnessState = ScreenBrightnessState.NORMAL,
walletAddress = runBlocking { WalletAddressesFixture.new() },
snackbarHostState = SnackbarHostState(),
onSettings = {},
onAdjustBrightness = {},
onAddrCopyToClipboard = {},
onQrImageShare = {},
versionInfo = VersionInfoFixture.new(),
topAppBarSubTitleState = TopAppBarSubTitleState.None,
)
}
@Suppress("LongParameterList") @Suppress("LongParameterList")
@Composable @Composable
fun Receive( fun Receive(
@ -139,7 +176,8 @@ private fun ReceiveTopAppBar(
) { ) {
Image( Image(
imageVector = ImageVector.vectorResource(id = R.drawable.ic_adjust_brightness), imageVector = ImageVector.vectorResource(id = R.drawable.ic_adjust_brightness),
contentDescription = stringResource(R.string.receive_brightness_content_description) colorFilter = ColorFilter.tint(color = ZcashTheme.colors.secondaryColor),
contentDescription = stringResource(R.string.receive_brightness_content_description),
) )
} }
} }
@ -180,7 +218,10 @@ private fun ReceiveContents(
Spacer(Modifier.height(ZcashTheme.dimens.spacingDefault)) Spacer(Modifier.height(ZcashTheme.dimens.spacingDefault))
PagerTabs( PagerTabs(
modifier = Modifier.fillMaxWidth(), modifier =
Modifier
.padding(horizontal = ZcashTheme.dimens.screenHorizontalSpacingRegular)
.fillMaxWidth(),
pagerState = pagerState, pagerState = pagerState,
tabs = tabs =
state.map { state.map {
@ -265,11 +306,11 @@ private fun ColumnScope.QrCode(
is WalletAddress.Transparent -> R.string.receive_transparent_content_description is WalletAddress.Transparent -> R.string.receive_transparent_content_description
} }
), ),
modifier = Modifier.align(Alignment.CenterHorizontally), modifier =
Modifier
.align(Alignment.CenterHorizontally),
) )
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingTiny))
Text( Text(
text = walletAddress.address, text = walletAddress.address,
style = ZcashTheme.extendedTypography.addressStyle, style = ZcashTheme.extendedTypography.addressStyle,
@ -278,13 +319,15 @@ private fun ColumnScope.QrCode(
modifier = modifier =
Modifier Modifier
.align(Alignment.CenterHorizontally) .align(Alignment.CenterHorizontally)
.clip(RoundedCornerShape(ZcashTheme.dimens.regularRippleEffectCorner))
.clickable { onAddressCopyToClipboard(walletAddress.address) } .clickable { onAddressCopyToClipboard(walletAddress.address) }
.padding(horizontal = ZcashTheme.dimens.spacingLarge) .padding(
horizontal = ZcashTheme.dimens.spacingLarge,
vertical = ZcashTheme.dimens.spacingSmall
)
.fillMaxWidth(), .fillMaxWidth(),
) )
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall))
Row( Row(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.Center horizontalArrangement = Arrangement.Center
@ -346,21 +389,4 @@ private fun QrCode(
) )
} }
@Preview
@Composable
private fun ComposablePreview() =
ZcashTheme(forceDarkMode = false) {
Receive(
screenBrightnessState = ScreenBrightnessState.NORMAL,
walletAddress = runBlocking { WalletAddressesFixture.new() },
snackbarHostState = SnackbarHostState(),
onSettings = {},
onAdjustBrightness = {},
onAddrCopyToClipboard = {},
onQrImageShare = {},
versionInfo = VersionInfoFixture.new(),
topAppBarSubTitleState = TopAppBarSubTitleState.None,
)
}
private val DEFAULT_QR_CODE_SIZE = 320.dp private val DEFAULT_QR_CODE_SIZE = 320.dp

View File

@ -6,7 +6,6 @@ import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.border import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
@ -21,10 +20,10 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextField import androidx.compose.material3.TextField
@ -45,7 +44,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.platform.LocalSoftwareKeyboardController
@ -86,9 +84,9 @@ import kotlinx.collections.immutable.ImmutableSet
import kotlinx.collections.immutable.persistentHashSetOf import kotlinx.collections.immutable.persistentHashSetOf
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@Preview("Restore Seed") @Preview
@Composable @Composable
private fun PreviewRestoreSeed() { private fun RestoreSeedPreview() {
ZcashTheme(forceDarkMode = false) { ZcashTheme(forceDarkMode = false) {
RestoreWallet( RestoreWallet(
ZcashNetwork.Mainnet, ZcashNetwork.Mainnet,
@ -116,9 +114,39 @@ private fun PreviewRestoreSeed() {
} }
} }
@Preview("Restore Seed Birthday") @Preview
@Composable @Composable
private fun PreviewRestoreBirthday() { private fun RestoreSeedDarkPreview() {
ZcashTheme(forceDarkMode = true) {
RestoreWallet(
ZcashNetwork.Mainnet,
restoreState = RestoreState(RestoreStage.Seed),
completeWordList =
persistentHashSetOf(
"abandon",
"ability",
"able",
"about",
"above",
"absent",
"absorb",
"abstract",
"rib",
"ribbon"
),
userWordList = WordList(listOf("abandon", "absorb")),
restoreHeight = null,
setRestoreHeight = {},
onBack = {},
paste = { "" },
onFinished = {}
)
}
}
@Preview
@Composable
private fun RestoreBirthdayPreview() {
ZcashTheme(forceDarkMode = false) { ZcashTheme(forceDarkMode = false) {
RestoreWallet( RestoreWallet(
ZcashNetwork.Mainnet, ZcashNetwork.Mainnet,
@ -146,6 +174,36 @@ private fun PreviewRestoreBirthday() {
} }
} }
@Preview
@Composable
private fun RestoreBirthdayDarkPreview() {
ZcashTheme(forceDarkMode = true) {
RestoreWallet(
ZcashNetwork.Mainnet,
restoreState = RestoreState(RestoreStage.Birthday),
completeWordList =
persistentHashSetOf(
"abandon",
"ability",
"able",
"about",
"above",
"absent",
"absorb",
"abstract",
"rib",
"ribbon"
),
userWordList = WordList(listOf("abandon", "absorb")),
restoreHeight = null,
setRestoreHeight = {},
onBack = {},
paste = { "" },
onFinished = {}
)
}
}
/** /**
* Note that the restore review doesn't allow the user to go back once the seed is entered correctly. * Note that the restore review doesn't allow the user to go back once the seed is entered correctly.
* *
@ -527,13 +585,14 @@ private fun SeedGridWithText(
isError = parseResult is ParseResult.Warn, isError = parseResult is ParseResult.Warn,
colors = colors =
TextFieldDefaults.colors( TextFieldDefaults.colors(
focusedContainerColor = Color.Transparent, cursorColor = ZcashTheme.colors.textPrimary,
unfocusedContainerColor = Color.Transparent,
disabledContainerColor = Color.Transparent, disabledContainerColor = Color.Transparent,
disabledIndicatorColor = Color.Transparent,
errorContainerColor = Color.Transparent, errorContainerColor = Color.Transparent,
focusedContainerColor = Color.Transparent,
focusedIndicatorColor = Color.Transparent, focusedIndicatorColor = Color.Transparent,
unfocusedContainerColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent, unfocusedIndicatorColor = Color.Transparent,
disabledIndicatorColor = Color.Transparent
) )
) )
} }
@ -619,10 +678,8 @@ private fun Autocomplete(
items(it) { items(it) {
ChipOnSurface( ChipOnSurface(
text = it, text = it,
modifier = onClick = { onSuggestionSelected(it) },
Modifier modifier = Modifier.testTag(RestoreTag.AUTOCOMPLETE_ITEM)
.testTag(RestoreTag.AUTOCOMPLETE_ITEM)
.clickable { onSuggestionSelected(it) }
) )
} }
} }
@ -636,21 +693,23 @@ private fun Warn(
) { ) {
if (parseResult is ParseResult.Warn) { if (parseResult is ParseResult.Warn) {
Surface( Surface(
shape = RoundedCornerShape(size = ZcashTheme.dimens.tinyRippleEffectCorner),
modifier = modifier =
modifier.then( modifier.then(
Modifier.border( Modifier.border(
border = border =
BorderStroke( BorderStroke(
width = ZcashTheme.dimens.chipStroke, width = ZcashTheme.dimens.chipStroke,
color = ZcashTheme.colors.layoutStroke color = ZcashTheme.colors.layoutStrokeSecondary
) ),
shape = RoundedCornerShape(size = ZcashTheme.dimens.tinyRippleEffectCorner),
) )
), ),
shape = RectangleShape, color = ZcashTheme.colors.primaryColor,
color = MaterialTheme.colorScheme.secondary,
shadowElevation = ZcashTheme.dimens.chipShadowElevation shadowElevation = ZcashTheme.dimens.chipShadowElevation
) { ) {
Text( Text(
color = ZcashTheme.colors.textPrimary,
modifier = modifier =
Modifier Modifier
.fillMaxWidth() .fillMaxWidth()
@ -709,11 +768,12 @@ private fun RestoreBirthdayMainContent(
}, },
colors = colors =
TextFieldDefaults.colors( TextFieldDefaults.colors(
cursorColor = ZcashTheme.colors.textPrimary,
focusedContainerColor = Color.Transparent, focusedContainerColor = Color.Transparent,
unfocusedContainerColor = Color.Transparent, unfocusedContainerColor = Color.Transparent,
disabledContainerColor = ZcashTheme.colors.textDisabled, disabledContainerColor = Color.Transparent,
errorContainerColor = Color.Transparent, errorContainerColor = Color.Transparent,
focusedIndicatorColor = ZcashTheme.colors.darkDividerColor, focusedIndicatorColor = ZcashTheme.colors.secondaryDividerColor,
unfocusedIndicatorColor = Color.Transparent, unfocusedIndicatorColor = Color.Transparent,
disabledIndicatorColor = Color.Transparent disabledIndicatorColor = Color.Transparent
), ),

View File

@ -18,8 +18,8 @@ import co.electriccoin.zcash.ui.common.model.SerializableAddress
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
import co.electriccoin.zcash.ui.screen.scan.util.SettingsUtil
import co.electriccoin.zcash.ui.screen.scan.view.Scan import co.electriccoin.zcash.ui.screen.scan.view.Scan
import co.electriccoin.zcash.ui.util.SettingsUtil
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@Composable @Composable
@ -80,7 +80,7 @@ fun WrapScan(
context.startActivity(SettingsUtil.newSettingsIntent(context.packageName)) context.startActivity(SettingsUtil.newSettingsIntent(context.packageName))
}.onFailure { }.onFailure {
// This case should not really happen, as the Settings app should be available on every // This case should not really happen, as the Settings app should be available on every
// Android device, but we need to handle it somehow. // Android device, but rather handle it.
scope.launch { scope.launch {
snackbarHostState.showSnackbar( snackbarHostState.showSnackbar(
message = context.getString(R.string.scan_settings_open_failed) message = context.getString(R.string.scan_settings_open_failed)

View File

@ -29,7 +29,7 @@ class QrCodeAnalyzer(
if (image.format in supportedImageFormats) { if (image.format in supportedImageFormats) {
val bytes = image.planes.first().buffer.toByteArray() val bytes = image.planes.first().buffer.toByteArray()
Twig.debug { Twig.verbose {
"Scan result: " + "Scan result: " +
"Frame: $framePosition, " + "Frame: $framePosition, " +
"Info: ${image.imageInfo}, " + "Info: ${image.imageInfo}, " +
@ -62,7 +62,7 @@ class QrCodeAnalyzer(
(binaryBmp.height * 0.4).toInt() (binaryBmp.height * 0.4).toInt()
) )
Twig.debug { Twig.verbose {
"Scan result cropped: " + "Scan result cropped: " +
"Image width: ${binaryBitmapCropped.width}, " + "Image width: ${binaryBitmapCropped.width}, " +
"Image height: ${binaryBitmapCropped.height}" "Image height: ${binaryBitmapCropped.height}"

View File

@ -80,9 +80,9 @@ import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.guava.await import kotlinx.coroutines.guava.await
import kotlin.math.roundToInt import kotlin.math.roundToInt
@Preview("Scan") @Preview
@Composable @Composable
private fun PreviewScan() { private fun ScanPreview() {
ZcashTheme(forceDarkMode = false) { ZcashTheme(forceDarkMode = false) {
BlankSurface { BlankSurface {
Scan( Scan(
@ -98,6 +98,24 @@ private fun PreviewScan() {
} }
} }
@Preview
@Composable
private fun ScanDarkPreview() {
ZcashTheme(forceDarkMode = true) {
BlankSurface {
Scan(
snackbarHostState = SnackbarHostState(),
onBack = {},
onScanned = {},
onOpenSettings = {},
onScanStateChanged = {},
topAppBarSubTitleState = TopAppBarSubTitleState.None,
addressValidationResult = AddressType.Transparent,
)
}
}
}
@OptIn(ExperimentalPermissionsApi::class) @OptIn(ExperimentalPermissionsApi::class)
@Composable @Composable
@Suppress("LongParameterList", "UnusedMaterial3ScaffoldPaddingParameter") @Suppress("LongParameterList", "UnusedMaterial3ScaffoldPaddingParameter")

View File

@ -1,6 +1,7 @@
package co.electriccoin.zcash.ui.screen.securitywarning.view package co.electriccoin.zcash.ui.screen.securitywarning.view
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
@ -24,15 +25,15 @@ import androidx.compose.ui.tooling.preview.Preview
import co.electriccoin.zcash.ui.R import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.model.VersionInfo import co.electriccoin.zcash.ui.common.model.VersionInfo
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
import co.electriccoin.zcash.ui.design.component.CheckBox
import co.electriccoin.zcash.ui.design.component.GridBgScaffold import co.electriccoin.zcash.ui.design.component.GridBgScaffold
import co.electriccoin.zcash.ui.design.component.GridBgSmallTopAppBar import co.electriccoin.zcash.ui.design.component.GridBgSmallTopAppBar
import co.electriccoin.zcash.ui.design.component.LabeledCheckBox
import co.electriccoin.zcash.ui.design.component.PrimaryButton import co.electriccoin.zcash.ui.design.component.PrimaryButton
import co.electriccoin.zcash.ui.design.component.TopScreenLogoTitle import co.electriccoin.zcash.ui.design.component.TopScreenLogoTitle
import co.electriccoin.zcash.ui.design.theme.ZcashTheme import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
@Preview("Security Warning") @Preview
@Composable @Composable
private fun SecurityWarningPreview() { private fun SecurityWarningPreview() {
ZcashTheme(forceDarkMode = false) { ZcashTheme(forceDarkMode = false) {
@ -45,11 +46,20 @@ private fun SecurityWarningPreview() {
} }
} }
// TODO [#998]: Check and enhance screen dark mode @Preview
// TODO [#998]: https://github.com/Electric-Coin-Company/zashi-android/issues/998 @Composable
private fun SecurityWarningDarkPreview() {
ZcashTheme(forceDarkMode = true) {
SecurityWarning(
versionInfo = VersionInfoFixture.new(),
onBack = {},
onAcknowledged = {},
onConfirm = {},
)
}
}
@Composable @Composable
@Suppress("LongParameterList")
fun SecurityWarning( fun SecurityWarning(
versionInfo: VersionInfo, versionInfo: VersionInfo,
onBack: () -> Unit, onBack: () -> Unit,
@ -111,19 +121,17 @@ private fun SecurityWarningContent(
Spacer(Modifier.height(ZcashTheme.dimens.spacingLarge)) Spacer(Modifier.height(ZcashTheme.dimens.spacingLarge))
val checkedState = rememberSaveable { mutableStateOf(false) } val checkedState = rememberSaveable { mutableStateOf(false) }
CheckBox( Row(Modifier.fillMaxWidth()) {
modifier = LabeledCheckBox(
Modifier checked = checkedState.value,
.align(Alignment.Start) onCheckedChange = {
.fillMaxWidth(), checkedState.value = it
checked = checkedState.value, onAcknowledged(it)
onCheckedChange = { },
checkedState.value = it text = stringResource(R.string.security_warning_acknowledge),
onAcknowledged(it) checkBoxTestTag = SecurityScreenTag.ACKNOWLEDGE_CHECKBOX_TAG
}, )
text = stringResource(R.string.security_warning_acknowledge), }
checkBoxTestTag = SecurityScreenTag.ACKNOWLEDGE_CHECKBOX_TAG
)
Spacer( Spacer(
modifier = modifier =
@ -148,6 +156,7 @@ fun SecurityWarningContentText(versionInfo: VersionInfo) {
Column { Column {
Text( Text(
text = stringResource(id = R.string.security_warning_text, versionInfo.versionName), text = stringResource(id = R.string.security_warning_text, versionInfo.versionName),
color = ZcashTheme.colors.textPrimary,
style = ZcashTheme.extendedTypography.securityWarningText style = ZcashTheme.extendedTypography.securityWarningText
) )
@ -164,6 +173,7 @@ fun SecurityWarningContentText(versionInfo: VersionInfo) {
} }
append(textPart2) append(textPart2)
}, },
color = ZcashTheme.colors.textPrimary,
style = ZcashTheme.extendedTypography.footnote, style = ZcashTheme.extendedTypography.footnote,
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) )

View File

@ -70,9 +70,6 @@ private fun ComposablePreview() {
} }
} }
// TODO [#998]: Check and enhance screen dark mode
// TODO [#998]: https://github.com/Electric-Coin-Company/zashi-android/issues/998
/** /**
* @param onDone Callback when the user has confirmed viewing the seed phrase. * @param onDone Callback when the user has confirmed viewing the seed phrase.
*/ */

View File

@ -326,7 +326,7 @@ private fun SendForm(
onReferenceClick = goBalances onReferenceClick = goBalances
) )
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingUpLarge)) Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge))
// TODO [#1256]: Consider Send.Form TextFields scrolling // TODO [#1256]: Consider Send.Form TextFields scrolling
// TODO [#1256]: https://github.com/Electric-Coin-Company/zashi-android/issues/1256 // TODO [#1256]: https://github.com/Electric-Coin-Company/zashi-android/issues/1256
@ -535,7 +535,8 @@ fun SendFormAddressTextField(
content = { content = {
Icon( Icon(
painter = painterResource(id = R.drawable.qr_code_icon), painter = painterResource(id = R.drawable.qr_code_icon),
contentDescription = stringResource(R.string.send_scan_content_description) contentDescription = stringResource(R.string.send_scan_content_description),
tint = ZcashTheme.colors.secondaryColor,
) )
} }
) )
@ -680,7 +681,7 @@ fun SendFormMemoTextField(
contentDescription = null, contentDescription = null,
tint = tint =
if (isMemoFieldAvailable) { if (isMemoFieldAvailable) {
ZcashTheme.colors.textCommon ZcashTheme.colors.textPrimary
} else { } else {
ZcashTheme.colors.textDisabled ZcashTheme.colors.textDisabled
} }
@ -692,7 +693,7 @@ fun SendFormMemoTextField(
text = stringResource(id = R.string.send_memo_label), text = stringResource(id = R.string.send_memo_label),
color = color =
if (isMemoFieldAvailable) { if (isMemoFieldAvailable) {
ZcashTheme.colors.textCommon ZcashTheme.colors.textPrimary
} else { } else {
ZcashTheme.colors.textDisabled ZcashTheme.colors.textDisabled
} }
@ -806,13 +807,17 @@ private fun SendFailure(
Column( Column(
Modifier.verticalScroll(rememberScrollState()) Modifier.verticalScroll(rememberScrollState())
) { ) {
Text(text = stringResource(id = R.string.send_dialog_error_text)) Text(
text = stringResource(id = R.string.send_dialog_error_text),
color = ZcashTheme.colors.textPrimary,
)
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault)) Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault))
Text( Text(
text = reason, text = reason,
fontStyle = FontStyle.Italic fontStyle = FontStyle.Italic,
color = ZcashTheme.colors.textPrimary,
) )
} }
}, },

View File

@ -4,7 +4,6 @@ package co.electriccoin.zcash.ui.screen.sendconfirmation.view
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column 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
@ -17,7 +16,6 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Icon
import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text import androidx.compose.material3.Text
@ -25,6 +23,7 @@ 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.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
@ -50,6 +49,7 @@ import co.electriccoin.zcash.ui.design.component.Body
import co.electriccoin.zcash.ui.design.component.BubbleArrowAlignment import co.electriccoin.zcash.ui.design.component.BubbleArrowAlignment
import co.electriccoin.zcash.ui.design.component.BubbleMessage import co.electriccoin.zcash.ui.design.component.BubbleMessage
import co.electriccoin.zcash.ui.design.component.PrimaryButton import co.electriccoin.zcash.ui.design.component.PrimaryButton
import co.electriccoin.zcash.ui.design.component.SecondaryButton
import co.electriccoin.zcash.ui.design.component.Small import co.electriccoin.zcash.ui.design.component.Small
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
import co.electriccoin.zcash.ui.design.component.StyledBalance import co.electriccoin.zcash.ui.design.component.StyledBalance
@ -59,8 +59,101 @@ import co.electriccoin.zcash.ui.screen.sendconfirmation.SendConfirmationTag
import co.electriccoin.zcash.ui.screen.sendconfirmation.model.SendConfirmationStage import co.electriccoin.zcash.ui.screen.sendconfirmation.model.SendConfirmationStage
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
@Preview
@Composable
private fun SendConfirmationPreview() {
ZcashTheme(forceDarkMode = false) {
SendConfirmation(
snackbarHostState = SnackbarHostState(),
zecSend =
ZecSend(
destination = runBlocking { WalletAddressFixture.sapling() },
amount = ZatoshiFixture.new(),
memo = MemoFixture.new(),
proposal = null,
),
onConfirmation = {},
onBack = {},
stage = SendConfirmationStage.Confirmation,
topAppBarSubTitleState = TopAppBarSubTitleState.None,
onContactSupport = {},
submissionResults = emptyList<TransactionSubmitResult>().toImmutableList()
)
}
}
@Preview
@Composable
private fun SendConfirmationDarkPreview() {
ZcashTheme(forceDarkMode = true) {
SendConfirmation(
snackbarHostState = SnackbarHostState(),
zecSend =
ZecSend(
destination = runBlocking { WalletAddressFixture.sapling() },
amount = ZatoshiFixture.new(),
memo = MemoFixture.new(),
proposal = null,
),
onConfirmation = {},
onBack = {},
stage = SendConfirmationStage.Confirmation,
topAppBarSubTitleState = TopAppBarSubTitleState.None,
onContactSupport = {},
submissionResults = emptyList<TransactionSubmitResult>().toImmutableList()
)
}
}
@Preview
@Composable
private fun SendMultipleErrorPreview() {
ZcashTheme(forceDarkMode = false) {
SendConfirmation(
snackbarHostState = SnackbarHostState(),
zecSend =
ZecSend(
destination = runBlocking { WalletAddressFixture.sapling() },
amount = ZatoshiFixture.new(),
memo = MemoFixture.new(),
proposal = null,
),
onConfirmation = {},
onBack = {},
stage = SendConfirmationStage.MultipleTrxFailure,
topAppBarSubTitleState = TopAppBarSubTitleState.None,
onContactSupport = {},
submissionResults = emptyList<TransactionSubmitResult>().toImmutableList()
)
}
}
@Preview
@Composable
private fun SendMultipleErrorDarkPreview() {
ZcashTheme(forceDarkMode = true) {
SendConfirmation(
snackbarHostState = SnackbarHostState(),
zecSend =
ZecSend(
destination = runBlocking { WalletAddressFixture.sapling() },
amount = ZatoshiFixture.new(),
memo = MemoFixture.new(),
proposal = null,
),
onConfirmation = {},
onBack = {},
stage = SendConfirmationStage.MultipleTrxFailure,
topAppBarSubTitleState = TopAppBarSubTitleState.None,
onContactSupport = {},
submissionResults = emptyList<TransactionSubmitResult>().toImmutableList()
)
}
}
@Composable @Composable
@Preview("SendConfirmation") @Preview("SendConfirmation")
private fun PreviewSendConfirmation() { private fun PreviewSendConfirmation() {
@ -80,9 +173,9 @@ private fun PreviewSendConfirmation() {
} }
} }
@Preview
@Composable @Composable
@Preview("SendMultipleTransactionFailure") private fun SendMultipleTransactionFailurePreview() {
private fun PreviewSendMultipleTransactionFailure() {
ZcashTheme(forceDarkMode = false) { ZcashTheme(forceDarkMode = false) {
@Suppress("MagicNumber") @Suppress("MagicNumber")
MultipleSubmissionFailure( MultipleSubmissionFailure(
@ -107,6 +200,33 @@ private fun PreviewSendMultipleTransactionFailure() {
} }
} }
@Preview
@Composable
private fun SendMultipleTransactionFailureDarkPreview() {
ZcashTheme(forceDarkMode = true) {
@Suppress("MagicNumber")
MultipleSubmissionFailure(
onContactSupport = {},
// Rework this into a test fixture
submissionResults =
persistentListOf(
TransactionSubmitResult.Failure(
FirstClassByteArray("test_transaction_id_1".toByteArray()),
true,
123,
"test transaction id failure"
),
TransactionSubmitResult.NotAttempted(
FirstClassByteArray("test_transaction_id_2".toByteArray())
),
TransactionSubmitResult.NotAttempted(
FirstClassByteArray("test_transaction_id_3".toByteArray())
)
)
)
}
}
// TODO [#1260]: Cover Send screens UI with tests // TODO [#1260]: Cover Send screens UI with tests
// TODO [#1260]: https://github.com/Electric-Coin-Company/zashi-android/issues/1260 // TODO [#1260]: https://github.com/Electric-Coin-Company/zashi-android/issues/1260
@ -337,6 +457,7 @@ fun SendConfirmationActionButtons(
enabled = !isSending, enabled = !isSending,
showProgressBar = isSending, showProgressBar = isSending,
minHeight = ZcashTheme.dimens.buttonHeightSmall, minHeight = ZcashTheme.dimens.buttonHeightSmall,
buttonColors = ZcashTheme.colors.tertiaryButtonColors,
modifier = modifier =
Modifier Modifier
.testTag(SendConfirmationTag.SEND_CONFIRMATION_SEND_BUTTON) .testTag(SendConfirmationTag.SEND_CONFIRMATION_SEND_BUTTON)
@ -345,7 +466,7 @@ fun SendConfirmationActionButtons(
Spacer(modifier = Modifier.width(ZcashTheme.dimens.spacingLarge)) Spacer(modifier = Modifier.width(ZcashTheme.dimens.spacingLarge))
PrimaryButton( SecondaryButton(
text = stringResource(R.string.send_confirmation_back_button), text = stringResource(R.string.send_confirmation_back_button),
onClick = onBack, onClick = onBack,
enabled = !isSending, enabled = !isSending,
@ -386,14 +507,18 @@ private fun SendFailure(
Column( Column(
Modifier.verticalScroll(rememberScrollState()) Modifier.verticalScroll(rememberScrollState())
) { ) {
Text(text = stringResource(id = R.string.send_confirmation_dialog_error_text)) Text(
text = stringResource(id = R.string.send_confirmation_dialog_error_text),
color = ZcashTheme.colors.textPrimary,
)
if (!reason.isNullOrEmpty()) { if (!reason.isNullOrEmpty()) {
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault)) Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault))
Text( Text(
text = reason, text = reason,
fontStyle = FontStyle.Italic fontStyle = FontStyle.Italic,
color = ZcashTheme.colors.textPrimary,
) )
} }
} }
@ -418,19 +543,11 @@ fun MultipleSubmissionFailure(
) { ) {
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall)) Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall))
Box( Image(
contentAlignment = Alignment.BottomEnd imageVector = ImageVector.vectorResource(R.drawable.ic_zashi_logo_sign_warn),
) { colorFilter = ColorFilter.tint(color = ZcashTheme.colors.secondaryColor),
Image( contentDescription = null,
imageVector = ImageVector.vectorResource(R.drawable.zashi_logo_sign), )
contentDescription = null,
)
Icon(
imageVector = ImageVector.vectorResource(R.drawable.ic_alert_circle_fill),
contentDescription = null,
modifier = Modifier.padding(bottom = ZcashTheme.dimens.spacingMid)
)
}
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingBig)) Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingBig))

View File

@ -22,6 +22,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource import androidx.compose.ui.res.vectorResource
@ -39,9 +40,9 @@ import co.electriccoin.zcash.ui.design.component.GridBgSmallTopAppBar
import co.electriccoin.zcash.ui.design.component.PrimaryButton import co.electriccoin.zcash.ui.design.component.PrimaryButton
import co.electriccoin.zcash.ui.design.theme.ZcashTheme import co.electriccoin.zcash.ui.design.theme.ZcashTheme
@Preview("Support") @Preview
@Composable @Composable
private fun PreviewSupport() { private fun SupportPreview() {
ZcashTheme(forceDarkMode = false) { ZcashTheme(forceDarkMode = false) {
BlankSurface { BlankSurface {
Support( Support(
@ -56,6 +57,23 @@ private fun PreviewSupport() {
} }
} }
@Preview
@Composable
private fun SupportDarkPreview() {
ZcashTheme(forceDarkMode = true) {
BlankSurface {
Support(
isShowingDialog = false,
setShowDialog = {},
onBack = {},
onSend = {},
snackbarHostState = SnackbarHostState(),
topAppBarSubTitleState = TopAppBarSubTitleState.None,
)
}
}
}
@Preview("Support-Popup") @Preview("Support-Popup")
@Composable @Composable
private fun PreviewSupportPopup() { private fun PreviewSupportPopup() {
@ -152,6 +170,7 @@ private fun SupportMainContent(
Image( Image(
imageVector = ImageVector.vectorResource(R.drawable.zashi_logo_sign), imageVector = ImageVector.vectorResource(R.drawable.zashi_logo_sign),
colorFilter = ColorFilter.tint(color = ZcashTheme.colors.secondaryColor),
contentDescription = null, contentDescription = null,
) )
@ -185,6 +204,8 @@ private fun SupportMainContent(
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge)) Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge))
// TODO [#1467]: Support screen - keep button above keyboard
// TODO [#1467]: https://github.com/Electric-Coin-Company/zashi-android/issues/1467
PrimaryButton( PrimaryButton(
onClick = { setShowDialog(true) }, onClick = { setShowDialog(true) },
text = stringResource(id = R.string.support_send), text = stringResource(id = R.string.support_send),

View File

@ -83,7 +83,7 @@ class AppUpdateCheckerMock private constructor() : AppUpdateChecker {
): Flow<Int> = ): Flow<Int> =
flow { flow {
// To simulate a real-world situation // To simulate a real-world situation
delay(2000.milliseconds) delay(4000.milliseconds)
emit(Activity.RESULT_OK) emit(Activity.RESULT_OK)
} }
} }

View File

@ -2,11 +2,14 @@ package co.electriccoin.zcash.ui.screen.update.view
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
@ -19,8 +22,10 @@ import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
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.ColorFilter
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
@ -32,6 +37,7 @@ import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.component.Body import co.electriccoin.zcash.ui.design.component.Body
import co.electriccoin.zcash.ui.design.component.GridBgScaffold import co.electriccoin.zcash.ui.design.component.GridBgScaffold
import co.electriccoin.zcash.ui.design.component.GridBgSmallTopAppBar import co.electriccoin.zcash.ui.design.component.GridBgSmallTopAppBar
import co.electriccoin.zcash.ui.design.component.Header
import co.electriccoin.zcash.ui.design.component.PrimaryButton import co.electriccoin.zcash.ui.design.component.PrimaryButton
import co.electriccoin.zcash.ui.design.component.Reference import co.electriccoin.zcash.ui.design.component.Reference
import co.electriccoin.zcash.ui.design.theme.ZcashTheme import co.electriccoin.zcash.ui.design.theme.ZcashTheme
@ -40,9 +46,9 @@ import co.electriccoin.zcash.ui.screen.update.UpdateTag
import co.electriccoin.zcash.ui.screen.update.model.UpdateInfo import co.electriccoin.zcash.ui.screen.update.model.UpdateInfo
import co.electriccoin.zcash.ui.screen.update.model.UpdateState import co.electriccoin.zcash.ui.screen.update.model.UpdateState
@Preview("Update") @Preview
@Composable @Composable
private fun PreviewUpdate() { private fun UpdatePreview() {
ZcashTheme(forceDarkMode = false) { ZcashTheme(forceDarkMode = false) {
Update( Update(
snackbarHostState = SnackbarHostState(), snackbarHostState = SnackbarHostState(),
@ -54,6 +60,48 @@ private fun PreviewUpdate() {
} }
} }
@Preview
@Composable
private fun UpdateRequiredPreview() {
ZcashTheme(forceDarkMode = false) {
Update(
snackbarHostState = SnackbarHostState(),
UpdateInfoFixture.new(force = true),
onDownload = {},
onLater = {},
onReference = {}
)
}
}
@Preview
@Composable
private fun UpdateAvailableDarkPreview() {
ZcashTheme(forceDarkMode = true) {
Update(
snackbarHostState = SnackbarHostState(),
UpdateInfoFixture.new(appUpdateInfo = null),
onDownload = {},
onLater = {},
onReference = {}
)
}
}
@Preview
@Composable
private fun UpdateRequiredDarkPreview() {
ZcashTheme(forceDarkMode = true) {
Update(
snackbarHostState = SnackbarHostState(),
UpdateInfoFixture.new(force = true),
onDownload = {},
onLater = {},
onReference = {}
)
}
}
@Composable @Composable
fun Update( fun Update(
snackbarHostState: SnackbarHostState, snackbarHostState: SnackbarHostState,
@ -101,14 +149,17 @@ fun UpdateOverlayRunning(updateInfo: UpdateInfo) {
if (updateInfo.state == UpdateState.Running) { if (updateInfo.state == UpdateState.Running) {
Column( Column(
Modifier Modifier
.background(ZcashTheme.colors.overlay.copy(0.5f)) .background(ZcashTheme.colors.overlay.copy(0.65f))
.fillMaxWidth() .fillMaxSize()
.fillMaxHeight() .clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null // Set indication to null to disable ripple effect
) {}
.testTag(UpdateTag.PROGRESSBAR_DOWNLOADING), .testTag(UpdateTag.PROGRESSBAR_DOWNLOADING),
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center verticalArrangement = Arrangement.Center
) { ) {
CircularProgressIndicator() CircularProgressIndicator(color = ZcashTheme.colors.overlayProgressBar)
} }
} }
} }
@ -143,7 +194,7 @@ private fun UpdateBottomAppBar(
) { ) {
HorizontalDivider( HorizontalDivider(
thickness = DividerDefaults.Thickness, thickness = DividerDefaults.Thickness,
color = ZcashTheme.colors.dividerColor color = ZcashTheme.colors.primaryDividerColor
) )
Column( Column(
@ -176,6 +227,7 @@ private fun UpdateBottomAppBar(
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
style = ZcashTheme.typography.primary.bodyLarge, style = ZcashTheme.typography.primary.bodyLarge,
fontWeight = FontWeight.SemiBold, fontWeight = FontWeight.SemiBold,
color = ZcashTheme.colors.textPrimary,
modifier = modifier =
Modifier Modifier
.padding(all = ZcashTheme.dimens.spacingDefault) .padding(all = ZcashTheme.dimens.spacingDefault)
@ -227,23 +279,23 @@ private fun UpdateContent(
Image( Image(
imageVector = imageVector =
if (updateInfo.isForce) { if (updateInfo.isForce) {
ImageVector.vectorResource(R.drawable.ic_zashi_logo_update_required) ImageVector.vectorResource(R.drawable.ic_zashi_logo_sign_warn)
} else { } else {
ImageVector.vectorResource(R.drawable.ic_zashi_logo_update_available) ImageVector.vectorResource(R.drawable.ic_zashi_logo_update_available)
}, },
colorFilter = ColorFilter.tint(color = ZcashTheme.colors.secondaryColor),
contentDescription = null contentDescription = null
) )
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingBig)) Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingBig))
Text( Header(
text = text =
if (updateInfo.isForce) { if (updateInfo.isForce) {
stringResource(id = R.string.update_title_required) stringResource(id = R.string.update_title_required)
} else { } else {
stringResource(id = R.string.update_title_available, appName) stringResource(id = R.string.update_title_available, appName)
}, },
style = ZcashTheme.extendedTypography.updateTitleStyle,
textAlign = TextAlign.Center textAlign = TextAlign.Center
) )

View File

@ -2,27 +2,85 @@
package co.electriccoin.zcash.ui.screen.warning package co.electriccoin.zcash.ui.screen.warning
import androidx.activity.ComponentActivity import androidx.activity.compose.BackHandler
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.platform.LocalContext
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import co.electriccoin.zcash.ui.MainActivity import co.electriccoin.zcash.ui.MainActivity
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.screen.warning.view.NotEnoughSpaceView import co.electriccoin.zcash.ui.screen.warning.view.NotEnoughSpaceView
import co.electriccoin.zcash.ui.screen.warning.viewmodel.StorageCheckViewModel import co.electriccoin.zcash.ui.screen.warning.viewmodel.StorageCheckViewModel
import co.electriccoin.zcash.ui.util.SettingsUtil
import kotlinx.coroutines.launch
@Composable @Composable
fun MainActivity.WrapNotEnoughSpace() { fun MainActivity.WrapNotEnoughSpace(
WrapNotEnoughSpace(this) goPrevious: () -> Unit,
} goSettings: () -> Unit
) {
val walletViewModel by viewModels<WalletViewModel>()
@Composable val storageCheckViewModel by viewModels<StorageCheckViewModel>()
private fun WrapNotEnoughSpace(activity: ComponentActivity) {
val storageCheckViewModel by activity.viewModels<StorageCheckViewModel>()
val spaceRequiredToContinue by storageCheckViewModel.spaceRequiredToContinueMegabytes.collectAsStateWithLifecycle()
NotEnoughSpaceView( val walletState = walletViewModel.walletStateInformation.collectAsStateWithLifecycle().value
storageSpaceRequiredGigabytes = storageCheckViewModel.requiredStorageSpaceGigabytes,
spaceRequiredToContinueMegabytes = spaceRequiredToContinue ?: 0 val isEnoughFreeSpace = storageCheckViewModel.isEnoughSpace.collectAsStateWithLifecycle().value
if (isEnoughFreeSpace == true) {
goPrevious()
}
val requiredStorageSpaceGigabytes = storageCheckViewModel.requiredStorageSpaceGigabytes
val spaceAvailableMegabytes = storageCheckViewModel.spaceAvailableMegabytes.collectAsStateWithLifecycle()
BackHandler {
finish()
}
WrapNotEnoughFreeSpace(
goSettings = goSettings,
spaceAvailableMegabytes = spaceAvailableMegabytes.value ?: 0,
requiredStorageSpaceGigabytes = requiredStorageSpaceGigabytes,
walletState = walletState,
)
}
@Composable
private fun WrapNotEnoughFreeSpace(
goSettings: () -> Unit,
requiredStorageSpaceGigabytes: Int,
spaceAvailableMegabytes: Int,
walletState: TopAppBarSubTitleState,
) {
val context = LocalContext.current
val scope = rememberCoroutineScope()
val snackbarHostState = remember { SnackbarHostState() }
NotEnoughSpaceView(
onSettings = goSettings,
onSystemSettings = {
runCatching {
context.startActivity(SettingsUtil.newStorageSettingsIntent())
}.onFailure {
// This case should not really happen, as the Settings app should be available on every
// Android device, but we rather handle it.
scope.launch {
snackbarHostState.showSnackbar(
message = context.getString(R.string.not_enough_space_settings_open_failed)
)
}
}
},
snackbarHostState = snackbarHostState,
storageSpaceRequiredGigabytes = requiredStorageSpaceGigabytes,
spaceAvailableMegabytes = spaceAvailableMegabytes,
topAppBarSubTitleState = walletState,
) )
} }

View File

@ -1,77 +1,193 @@
package co.electriccoin.zcash.ui.screen.warning.view package co.electriccoin.zcash.ui.screen.warning.view
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
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.ColorFilter
import androidx.compose.ui.platform.testTag
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.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import co.electriccoin.zcash.ui.R import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
import co.electriccoin.zcash.ui.common.test.CommonTag
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
import co.electriccoin.zcash.ui.design.component.Body import co.electriccoin.zcash.ui.design.component.Body
import co.electriccoin.zcash.ui.design.component.GridBgColumn import co.electriccoin.zcash.ui.design.component.GridBgScaffold
import co.electriccoin.zcash.ui.design.component.Header import co.electriccoin.zcash.ui.design.component.Header
import co.electriccoin.zcash.ui.design.component.Small import co.electriccoin.zcash.ui.design.component.PrimaryButton
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
import co.electriccoin.zcash.ui.design.theme.ZcashTheme import co.electriccoin.zcash.ui.design.theme.ZcashTheme
@Preview("NotEnoughSpace") @Preview
@Composable @Composable
private fun NotEnoughSpacePreview() { private fun NotEnoughSpacePreview() {
ZcashTheme(forceDarkMode = false) { ZcashTheme(forceDarkMode = false) {
NotEnoughSpaceView( NotEnoughSpaceView(
onSettings = {},
onSystemSettings = {},
snackbarHostState = SnackbarHostState(),
spaceAvailableMegabytes = 300,
storageSpaceRequiredGigabytes = 1, storageSpaceRequiredGigabytes = 1,
spaceRequiredToContinueMegabytes = 300 topAppBarSubTitleState = TopAppBarSubTitleState.None,
)
}
}
@Preview
@Composable
private fun NotEnoughSpaceDarkPreview() {
ZcashTheme(forceDarkMode = true) {
NotEnoughSpaceView(
onSettings = {},
onSystemSettings = {},
snackbarHostState = SnackbarHostState(),
spaceAvailableMegabytes = 300,
storageSpaceRequiredGigabytes = 1,
topAppBarSubTitleState = TopAppBarSubTitleState.None,
) )
} }
} }
@Composable @Composable
@Suppress("LongParameterList")
fun NotEnoughSpaceView( fun NotEnoughSpaceView(
onSettings: () -> Unit,
onSystemSettings: () -> Unit,
spaceAvailableMegabytes: Int,
storageSpaceRequiredGigabytes: Int, storageSpaceRequiredGigabytes: Int,
spaceRequiredToContinueMegabytes: Int topAppBarSubTitleState: TopAppBarSubTitleState,
snackbarHostState: SnackbarHostState,
) { ) {
GridBgColumn( GridBgScaffold(
Modifier topBar = {
.fillMaxSize() NotEnoughSpaceTopAppBar(
.padding(ZcashTheme.dimens.screenHorizontalSpacingRegular) onSettings = onSettings,
.verticalScroll( subTitleState = topAppBarSubTitleState,
rememberScrollState() )
), },
verticalArrangement = Arrangement.Center, snackbarHost = { SnackbarHost(snackbarHostState) },
horizontalAlignment = Alignment.CenterHorizontally ) { paddingValues ->
) { NotEnoughSpaceMainContent(
Image( onSystemSettings = onSystemSettings,
painter = painterResource(id = R.drawable.not_enough_space), spaceRequiredToContinueMegabytes = spaceAvailableMegabytes,
contentDescription = null, storageSpaceRequiredGigabytes = storageSpaceRequiredGigabytes,
modifier = Modifier.fillMaxWidth() modifier =
) Modifier
.padding(
Spacer(Modifier.height(ZcashTheme.dimens.spacingUpLarge)) top = paddingValues.calculateTopPadding(),
bottom = paddingValues.calculateBottomPadding(),
Header(text = stringResource(id = R.string.not_enough_space_title)) start = ZcashTheme.dimens.screenHorizontalSpacingBig,
end = ZcashTheme.dimens.screenHorizontalSpacingBig
Spacer(Modifier.height(ZcashTheme.dimens.spacingUpLarge)) )
Body(
text = stringResource(id = R.string.not_enough_space_description, storageSpaceRequiredGigabytes),
textAlign = TextAlign.Center
)
Spacer(Modifier.height(ZcashTheme.dimens.spacingHuge))
Small(
text = stringResource(id = R.string.space_required_to_continue, spaceRequiredToContinueMegabytes),
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth()
) )
} }
} }
@Composable
private fun NotEnoughSpaceTopAppBar(
onSettings: () -> Unit,
subTitleState: TopAppBarSubTitleState
) {
SmallTopAppBar(
subTitle =
when (subTitleState) {
TopAppBarSubTitleState.Disconnected -> stringResource(id = R.string.disconnected_label)
TopAppBarSubTitleState.Restoring -> stringResource(id = R.string.restoring_wallet_label)
TopAppBarSubTitleState.None -> null
},
titleText = stringResource(id = R.string.not_enough_space_title).uppercase(),
hamburgerMenuActions = {
IconButton(
onClick = onSettings,
modifier = Modifier.testTag(CommonTag.SETTINGS_TOP_BAR_BUTTON)
) {
Icon(
painter = painterResource(id = co.electriccoin.zcash.ui.design.R.drawable.hamburger_menu_icon),
contentDescription = stringResource(id = R.string.settings_menu_content_description)
)
}
}
)
}
@Composable
private fun NotEnoughSpaceMainContent(
onSystemSettings: () -> Unit,
spaceRequiredToContinueMegabytes: Int,
storageSpaceRequiredGigabytes: Int,
modifier: Modifier = Modifier
) {
Column(
modifier =
modifier.then(
Modifier
.fillMaxHeight()
.verticalScroll(
rememberScrollState()
)
),
horizontalAlignment = Alignment.CenterHorizontally
) {
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingBig))
Image(
painter = painterResource(id = R.drawable.ic_zashi_logo_sign_warn),
colorFilter = ColorFilter.tint(color = ZcashTheme.colors.secondaryColor),
contentDescription = null,
)
Spacer(Modifier.height(ZcashTheme.dimens.spacingBig))
Header(
text =
stringResource(
id = R.string.not_enough_space_description_1,
stringResource(id = R.string.app_name),
storageSpaceRequiredGigabytes,
spaceRequiredToContinueMegabytes
),
textAlign = TextAlign.Center
)
Spacer(Modifier.height(ZcashTheme.dimens.spacingLarge))
Body(
text =
stringResource(
id = R.string.not_enough_space_description_2,
stringResource(id = R.string.app_name)
),
textAlign = TextAlign.Center
)
Spacer(
modifier =
Modifier
.fillMaxHeight()
.weight(MINIMAL_WEIGHT)
)
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault))
PrimaryButton(
onClick = onSystemSettings,
text = stringResource(R.string.not_enough_space_system_settings_btn),
)
Spacer(Modifier.height(ZcashTheme.dimens.spacingHuge))
}
}

View File

@ -29,4 +29,12 @@ class StorageCheckViewModel : ViewModel() {
SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT), SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT),
null null
) )
val spaceAvailableMegabytes =
flow { emit(StorageChecker.checkAvailableStorageMegabytes()) }
.stateIn(
viewModelScope,
SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT),
null
)
} }

View File

@ -1,4 +1,4 @@
package co.electriccoin.zcash.ui.screen.scan.util package co.electriccoin.zcash.ui.util
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
@ -26,4 +26,15 @@ object SettingsUtil {
flags = FLAGS flags = FLAGS
} }
} }
/**
* Returns an intent to the system Storage Settings page.
*
* @return Intent for launching the system Settings app
*/
internal fun newStorageSettingsIntent(): Intent {
return Intent(Settings.ACTION_INTERNAL_STORAGE_SETTINGS).apply {
flags = FLAGS
}
}
} }

View File

@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="12dp"
android:height="11dp"
android:viewportWidth="12"
android:viewportHeight="11">
<path
android:pathData="M1,0.625h10v10h-10z"
android:strokeWidth="0.25"
android:fillColor="#00000000"
android:strokeColor="#C1C1C1"/>
<path
android:pathData="M6,4.084L8.02,6.105L7.313,6.812L6,5.499L4.687,6.812L3.98,6.105L6,4.084Z"
android:fillColor="#F4B728"
android:fillType="evenOdd"/>
</vector>

View File

@ -0,0 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="11dp"
android:height="12dp"
android:viewportWidth="11"
android:viewportHeight="12">
<path
android:strokeWidth="1"
android:pathData="M5.5,5.5m-5,0a5,5 0,1 1,10 0a5,5 0,1 1,-10 0"
android:fillColor="#ffffff"
android:strokeColor="#ffffff"/>
<path
android:pathData="M4.795,6.682V6.545C4.795,6.233 4.82,5.984 4.869,5.798C4.919,5.613 4.991,5.464 5.088,5.352C5.185,5.239 5.303,5.136 5.443,5.045C5.564,4.966 5.672,4.889 5.767,4.815C5.864,4.741 5.939,4.663 5.994,4.58C6.051,4.496 6.08,4.402 6.08,4.295C6.08,4.201 6.057,4.117 6.011,4.045C5.966,3.973 5.904,3.918 5.827,3.878C5.749,3.838 5.663,3.818 5.568,3.818C5.466,3.818 5.371,3.842 5.284,3.889C5.199,3.937 5.13,4.002 5.077,4.085C5.026,4.169 5,4.265 5,4.375H3.545C3.549,3.958 3.644,3.62 3.83,3.361C4.015,3.099 4.261,2.908 4.568,2.787C4.875,2.664 5.212,2.602 5.58,2.602C5.985,2.602 6.347,2.662 6.665,2.781C6.983,2.899 7.234,3.077 7.418,3.315C7.601,3.552 7.693,3.848 7.693,4.205C7.693,4.434 7.653,4.635 7.574,4.81C7.496,4.982 7.387,5.134 7.247,5.267C7.109,5.398 6.947,5.517 6.761,5.625C6.625,5.705 6.51,5.787 6.418,5.872C6.325,5.955 6.255,6.051 6.207,6.159C6.16,6.265 6.136,6.394 6.136,6.545V6.682H4.795ZM5.489,8.591C5.269,8.591 5.08,8.514 4.923,8.361C4.768,8.205 4.691,8.017 4.693,7.795C4.691,7.58 4.768,7.395 4.923,7.241C5.08,7.088 5.269,7.011 5.489,7.011C5.697,7.011 5.881,7.088 6.04,7.241C6.201,7.395 6.282,7.58 6.284,7.795C6.282,7.943 6.243,8.078 6.168,8.199C6.094,8.318 5.997,8.414 5.878,8.486C5.759,8.556 5.629,8.591 5.489,8.591Z"
android:fillColor="#181716"/>
</vector>

View File

@ -3,10 +3,13 @@
<string name="choose_server_back_content_description">Back</string> <string name="choose_server_back_content_description">Back</string>
<string name="choose_server_title">Server</string> <string name="choose_server_title">Server</string>
<string name="choose_server_default_label">default: <xliff:g id="server" example="example.com:123">%1$s</xliff:g></string>
<string name="choose_server_custom">custom</string> <string name="choose_server_custom">custom</string>
<string name="choose_server_custom_delimiter">:</string> <string name="choose_server_custom_delimiter">:</string>
<string name="choose_server_textfield_value"><xliff:g id="hostname" example="example.com">%1$s</xliff:g>:<xliff:g <string name="choose_server_full_server_name">
id="port" example="508">%2$d</xliff:g></string> <xliff:g id="hostname" example="example.com">%1$s</xliff:g>:
<xliff:g id="port" example="508">%2$d</xliff:g>
</string>
<string name="choose_server_textfield_hint">&lt;hostname&gt;:&lt;port&gt;</string> <string name="choose_server_textfield_hint">&lt;hostname&gt;:&lt;port&gt;</string>
<string name="choose_server_save">Save</string> <string name="choose_server_save">Save</string>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 708 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -5,7 +5,7 @@
place you trust and never share it with anyone!</string> place you trust and never share it with anyone!</string>
<string name="new_wallet_recovery_birthday_height" formatted="true">Wallet birthday height: <xliff:g example="419200" <string name="new_wallet_recovery_birthday_height" formatted="true">Wallet birthday height: <xliff:g example="419200"
id="birthday_height">%1$d</xliff:g></string> id="birthday_height">%1$d</xliff:g></string>
<string name="new_wallet_recovery_button_finished">I got it!</string> <string name="new_wallet_recovery_button_finished">I\'ve saved it</string>
<string name="new_wallet_recovery_copy">Tap to Copy</string> <string name="new_wallet_recovery_copy">Tap to Copy</string>
<string name="new_wallet_recovery_seed_clipboard_tag">Zcash Seed Phrase</string> <string name="new_wallet_recovery_seed_clipboard_tag">Zcash Seed Phrase</string>
<string name="new_wallet_recovery_birthday_clipboard_tag">Zcash Wallet Birthday</string> <string name="new_wallet_recovery_birthday_clipboard_tag">Zcash Wallet Birthday</string>

View File

@ -1,5 +1,5 @@
<resources> <resources>
<string name="app_name">zcash-ui</string> <string name="app_name">zashi-ui</string>
<string name="onboarding_header">A no-frills wallet for sending and receiving Zcash (ZEC)</string> <string name="onboarding_header">A no-frills wallet for sending and receiving Zcash (ZEC)</string>

View File

@ -20,7 +20,7 @@
android:fillColor="#000000"/> android:fillColor="#000000"/>
<path <path
android:pathData="M10,13.404C11.88,13.404 13.403,11.88 13.403,10C13.403,8.121 11.88,6.597 10,6.597V13.404Z" android:pathData="M10,13.404C11.88,13.404 13.403,11.88 13.403,10C13.403,8.121 11.88,6.597 10,6.597V13.404Z"
android:fillColor="#ffffff"/> android:fillColor="#000000"/>
<path <path
android:pathData="M3.095,10.49H0.49C0.219,10.49 0,10.27 0,10C0,9.73 0.219,9.51 0.49,9.51H3.095C3.365,9.51 3.585,9.73 3.585,10C3.585,10.27 3.365,10.49 3.095,10.49Z" android:pathData="M3.095,10.49H0.49C0.219,10.49 0,10.27 0,10C0,9.73 0.219,9.51 0.49,9.51H3.095C3.365,9.51 3.585,9.73 3.585,10C3.585,10.27 3.365,10.49 3.095,10.49Z"
android:fillColor="#000000"/> android:fillColor="#000000"/>

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="25dp"
android:height="25dp"
android:viewportWidth="25"
android:viewportHeight="25">
<path
android:pathData="M12.359,22.587C6.836,22.587 2.359,18.11 2.359,12.587C2.359,7.065 6.836,2.587 12.359,2.587C17.882,2.587 22.359,7.065 22.359,12.587C22.359,18.11 17.882,22.587 12.359,22.587ZM12.359,7.587C12.094,7.587 11.839,7.692 11.652,7.88C11.464,8.067 11.359,8.322 11.359,8.587V13.587C11.359,13.852 11.464,14.106 11.652,14.294C11.839,14.481 12.094,14.587 12.359,14.587C12.624,14.587 12.878,14.481 13.066,14.294C13.253,14.106 13.359,13.852 13.359,13.587V8.587C13.359,8.322 13.253,8.067 13.066,7.88C12.878,7.692 12.624,7.587 12.359,7.587ZM12.359,17.587C12.624,17.587 12.878,17.481 13.066,17.294C13.253,17.106 13.359,16.852 13.359,16.587C13.359,16.322 13.253,16.067 13.066,15.88C12.878,15.692 12.624,15.587 12.359,15.587C12.094,15.587 11.839,15.692 11.652,15.88C11.464,16.067 11.359,16.322 11.359,16.587C11.359,16.852 11.464,17.106 11.652,17.294C11.839,17.481 12.094,17.587 12.359,17.587Z"
android:fillColor="#21272A"/>
</vector>

View File

@ -2,14 +2,14 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="update_header">Update available</string> <string name="update_header">Update available</string>
<string name="update_critical_header">Update required</string> <string name="update_critical_header">Update required</string>
<string name="update_title_available"><xliff:g id="app_name" example="Zcash">%1$s</xliff:g> here.</string> <string name="update_title_available"><xliff:g id="app_name" example="Zashi">%1$s</xliff:g> here.</string>
<string name="update_title_required">It\'s not you, it\'s me.</string> <string name="update_title_required">It\'s not you, it\'s me.</string>
<string name="update_description_required"> <string name="update_description_required">
There is a required update for <xliff:g id="app_name" example="Zcash">%1$s</xliff:g> that makes major There is a required update for <xliff:g id="app_name" example="Zashi">%1$s</xliff:g> that makes major
improvements to performance and/or security. improvements to performance and/or security.
</string> </string>
<string name="update_description_available"> <string name="update_description_available">
There is a new version of <xliff:g id="app_name" example="Zcash">%1$s</xliff:g> that makes minor updates to There is a new version of <xliff:g id="app_name" example="Zashi">%1$s</xliff:g> that makes minor updates to
improve performance and/or security.\n\nPlease take a moment to update to the latest version. improve performance and/or security.\n\nPlease take a moment to update to the latest version.
</string> </string>
<string name="update_link_text">Learn more about this update here.</string> <string name="update_link_text">Learn more about this update here.</string>

View File

@ -1,12 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="123dp"
android:height="151dp"
android:viewportWidth="123"
android:viewportHeight="151">
<path
android:pathData="M61.5,151l-30.75,-16.25a47.25,47.25 0,0 1,-12.8 -10.14,65.56 65.56,0 0,1 -9.68,-14.14 76.37,76.37 0,0 1,-6.13 -16.25,67.59 67.59,0 0,1 -2.14,-16.48v-0.82h33.17L58.88,104l25.71,-27.06h38.41v0.82a67.59,67.59 0,0 1,-2.14 16.48,76.33 76.33,0 0,1 -6.13,16.25 65.52,65.52 0,0 1,-9.68 14.14,47.25 47.25,0 0,1 -12.8,10.14L61.5,151Z"
android:fillColor="#891c2f"/>
<path
android:pathData="M32.22,75.94h0l-32.22,0L0,24.36L61.5,0l61.5,24.36L123,75.94h-37.46L99,61.78 84.95,47l-26.07,27.44 -12.84,-13.51L32,75.71l0.22,0.23Z"
android:fillColor="#ff0000"/>
</vector>

View File

@ -1,9 +1,15 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="not_enough_space_title">Not enough space!</string> <string name="not_enough_space_title">Not enough free space</string>
<string name="not_enough_space_description">You need approximately <xliff:g example="1" id="required_gigabytes"> <string name="not_enough_space_description_1">
%1$d</xliff:g> Gbyte of space while synchronizing the Zcash blockchain, but only 300 Mbyte once done. Syncing <xliff:g id="app_name" example="Zashi">%1$s</xliff:g> requires at least
will stay paused until more space is available.</string> <xliff:g example="1" id="required_gigabytes">%2$d</xliff:g> GB of space to operate but there is only
<string name="space_required_to_continue"><xliff:g example="300" id="required_megabytes">~%1$d</xliff:g> Mbyte <xliff:g example="300" id="available_megabytes">%3$d</xliff:g> MB available.
required to continue </string> </string>
<string name="not_enough_space_description_2">
Go to your device settings and make more space available if you wish to use the
<xliff:g id="app_name" example="Zashi">%1$s</xliff:g> app.
</string>
<string name="not_enough_space_system_settings_btn">System settings</string>
<string name="not_enough_space_settings_open_failed">Unable to launch Settings app.</string>
</resources> </resources>