Home messages and dialogs UI

This commit is contained in:
Milan Cerovsky 2025-04-04 12:15:12 +02:00
parent 6ce230cba0
commit 2f12bea435
82 changed files with 2475 additions and 320 deletions

View File

@ -1,56 +1,77 @@
package co.electriccoin.zcash.ui.design.component
import androidx.annotation.DrawableRes
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.ripple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import co.electriccoin.zcash.ui.design.R
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
import co.electriccoin.zcash.ui.design.util.StringResource
import co.electriccoin.zcash.ui.design.util.getValue
import co.electriccoin.zcash.ui.design.util.orDark
import co.electriccoin.zcash.ui.design.util.stringRes
@Suppress("MagicNumber")
@Composable
fun ZashiBigIconButton(
state: BigIconButtonState,
modifier: Modifier = Modifier,
) {
val darkBgGradient =
Brush.verticalGradient(
0f to ZashiColors.Surfaces.strokeSecondary,
.66f to ZashiColors.Surfaces.strokeSecondary.copy(alpha = 0.5f),
1f to ZashiColors.Surfaces.strokeSecondary.copy(alpha = 0.25f),
)
val darkBorderGradient =
Brush.verticalGradient(
0f to ZashiColors.Surfaces.strokePrimary,
1f to ZashiColors.Surfaces.strokePrimary.copy(alpha = 0f),
)
val backgroundModifier =
Modifier.background(ZashiColors.Surfaces.bgPrimary) orDark
Modifier.background(darkBgGradient)
Surface(
modifier =
modifier,
shape = RoundedCornerShape(16.dp),
color = ZashiColors.Surfaces.bgSecondary
modifier = modifier,
onClick = state.onClick,
color = ZashiColors.Surfaces.bgPrimary,
shape = RoundedCornerShape(22.dp),
border =
BorderStroke(.5.dp, ZashiColors.Utility.Gray.utilityGray100) orDark
BorderStroke(.5.dp, darkBorderGradient),
shadowElevation = 2.dp orDark 4.dp
) {
Column(
modifier =
Modifier
.clickable(
indication = ripple(),
interactionSource = remember { MutableInteractionSource() },
onClick = state.onClick,
role = Role.Button,
).padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally
modifier = backgroundModifier.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Icon(
Image(
painter = painterResource(state.icon),
contentDescription = state.text.getValue(),
tint = ZashiColors.Text.textPrimary
colorFilter = ColorFilter.tint(ZashiColors.Text.textPrimary)
)
Spacer(Modifier.height(4.dp))
Text(
@ -68,3 +89,17 @@ data class BigIconButtonState(
@DrawableRes val icon: Int,
val onClick: () -> Unit,
)
@PreviewScreens
@Composable
private fun Preview() =
ZcashTheme {
ZashiBigIconButton(
state =
BigIconButtonState(
text = stringRes("Text"),
icon = R.drawable.ic_reveal,
onClick = {}
)
)
}

View File

@ -0,0 +1,54 @@
package co.electriccoin.zcash.ui.design.component
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.ParagraphStyle
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.text.style.TextIndent
import androidx.compose.ui.text.withStyle
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
@Composable
fun ZashiBulletText(
vararg bulletText: String,
modifier: Modifier = Modifier,
style: TextStyle = ZashiTypography.textSm,
fontWeight: FontWeight = FontWeight.Normal,
color: Color = ZashiColors.Text.textPrimary,
) {
val normalizedStyle = style.copy(fontWeight = fontWeight)
val bulletString = remember { "\u2022 " }
val bulletTextMeasurer = rememberTextMeasurer()
val bulletStringWidth =
remember(normalizedStyle, bulletTextMeasurer) {
bulletTextMeasurer.measure(text = bulletString, style = normalizedStyle).size.width
}
val bulletRestLine = with(LocalDensity.current) { bulletStringWidth.toSp() }
val bulletParagraphStyle = ParagraphStyle(textIndent = TextIndent(restLine = bulletRestLine))
Text(
modifier = modifier,
text =
buildAnnotatedString {
withStyle(style = bulletParagraphStyle) {
bulletText.forEachIndexed { index, string ->
if (index != 0) {
appendLine()
}
append(bulletString)
append(string)
}
}
},
style = style,
fontWeight = fontWeight,
color = color,
)
}

View File

@ -18,6 +18,7 @@ import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
@ -31,6 +32,7 @@ import co.electriccoin.zcash.ui.design.R
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColorsInternal
import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
import co.electriccoin.zcash.ui.design.util.StringResource
import co.electriccoin.zcash.ui.design.util.getValue
@ -42,7 +44,7 @@ fun ZashiButton(
style: TextStyle = ZashiButtonDefaults.style,
shape: Shape = ZashiButtonDefaults.shape,
contentPadding: PaddingValues = ZashiButtonDefaults.contentPadding,
colors: ZashiButtonColors = ZashiButtonDefaults.primaryColors(),
colors: ZashiButtonColors = LocalZashiButtonColors.current ?: ZashiButtonDefaults.primaryColors(),
content: @Composable RowScope.(ZashiButtonScope) -> Unit = ZashiButtonDefaults.content
) {
ZashiButton(
@ -74,7 +76,7 @@ fun ZashiButton(
style: TextStyle = ZashiButtonDefaults.style,
shape: Shape = ZashiButtonDefaults.shape,
contentPadding: PaddingValues = ZashiButtonDefaults.contentPadding,
colors: ZashiButtonColors = ZashiButtonDefaults.primaryColors(),
colors: ZashiButtonColors = LocalZashiButtonColors.current ?: ZashiButtonDefaults.primaryColors(),
content: @Composable RowScope.(ZashiButtonScope) -> Unit = ZashiButtonDefaults.content
) {
val scope =
@ -180,10 +182,11 @@ object ZashiButtonDefaults {
@Composable
fun primaryColors(
containerColor: Color = ZashiColors.Btns.Primary.btnPrimaryBg,
contentColor: Color = ZashiColors.Btns.Primary.btnPrimaryFg,
disabledContainerColor: Color = ZashiColors.Btns.Primary.btnPrimaryBgDisabled,
disabledContentColor: Color = ZashiColors.Btns.Primary.btnBoldFgDisabled,
source: ZashiColorsInternal = ZashiColors,
containerColor: Color = source.Btns.Primary.btnPrimaryBg,
contentColor: Color = source.Btns.Primary.btnPrimaryFg,
disabledContainerColor: Color = source.Btns.Primary.btnPrimaryBgDisabled,
disabledContentColor: Color = source.Btns.Primary.btnBoldFgDisabled,
) = ZashiButtonColors(
containerColor = containerColor,
contentColor = contentColor,
@ -195,11 +198,12 @@ object ZashiButtonDefaults {
@Composable
fun secondaryColors(
containerColor: Color = ZashiColors.Btns.Secondary.btnSecondaryBg,
contentColor: Color = ZashiColors.Btns.Secondary.btnSecondaryFg,
source: ZashiColorsInternal = ZashiColors,
containerColor: Color = source.Btns.Secondary.btnSecondaryBg,
contentColor: Color = source.Btns.Secondary.btnSecondaryFg,
borderColor: Color = Color.Unspecified,
disabledContainerColor: Color = ZashiColors.Btns.Secondary.btnSecondaryBgDisabled,
disabledContentColor: Color = ZashiColors.Btns.Secondary.btnSecondaryFg,
disabledContainerColor: Color = source.Btns.Secondary.btnSecondaryBgDisabled,
disabledContentColor: Color = source.Btns.Secondary.btnSecondaryFg,
) = ZashiButtonColors(
containerColor = containerColor,
contentColor = contentColor,
@ -211,10 +215,11 @@ object ZashiButtonDefaults {
@Composable
fun tertiaryColors(
containerColor: Color = ZashiColors.Btns.Tertiary.btnTertiaryBg,
contentColor: Color = ZashiColors.Btns.Tertiary.btnTertiaryFg,
disabledContainerColor: Color = ZashiColors.Btns.Tertiary.btnTertiaryBgDisabled,
disabledContentColor: Color = ZashiColors.Btns.Tertiary.btnTertiaryFgDisabled,
source: ZashiColorsInternal = ZashiColors,
containerColor: Color = source.Btns.Tertiary.btnTertiaryBg,
contentColor: Color = source.Btns.Tertiary.btnTertiaryFg,
disabledContainerColor: Color = source.Btns.Tertiary.btnTertiaryBgDisabled,
disabledContentColor: Color = source.Btns.Tertiary.btnTertiaryFgDisabled,
) = ZashiButtonColors(
containerColor = containerColor,
contentColor = contentColor,
@ -226,11 +231,12 @@ object ZashiButtonDefaults {
@Composable
fun destructive1Colors(
containerColor: Color = ZashiColors.Btns.Destructive1.btnDestroy1Bg,
contentColor: Color = ZashiColors.Btns.Destructive1.btnDestroy1Fg,
borderColor: Color = ZashiColors.Btns.Destructive1.btnDestroy1Border,
disabledContainerColor: Color = ZashiColors.Btns.Destructive1.btnDestroy1BgDisabled,
disabledContentColor: Color = ZashiColors.Btns.Destructive1.btnDestroy1FgDisabled,
source: ZashiColorsInternal = ZashiColors,
containerColor: Color = source.Btns.Destructive1.btnDestroy1Bg,
contentColor: Color = source.Btns.Destructive1.btnDestroy1Fg,
borderColor: Color = source.Btns.Destructive1.btnDestroy1Border,
disabledContainerColor: Color = source.Btns.Destructive1.btnDestroy1BgDisabled,
disabledContentColor: Color = source.Btns.Destructive1.btnDestroy1FgDisabled,
) = ZashiButtonColors(
containerColor = containerColor,
contentColor = contentColor,
@ -242,11 +248,12 @@ object ZashiButtonDefaults {
@Composable
fun destructive2Colors(
containerColor: Color = ZashiColors.Btns.Destructive2.btnDestroy2Bg,
contentColor: Color = ZashiColors.Btns.Destructive2.btnDestroy2Fg,
source: ZashiColorsInternal = ZashiColors,
containerColor: Color = source.Btns.Destructive2.btnDestroy2Bg,
contentColor: Color = source.Btns.Destructive2.btnDestroy2Fg,
borderColor: Color = Color.Unspecified,
disabledContainerColor: Color = ZashiColors.Btns.Destructive2.btnDestroy2BgDisabled,
disabledContentColor: Color = ZashiColors.Btns.Destructive2.btnDestroy2FgDisabled,
disabledContainerColor: Color = source.Btns.Destructive2.btnDestroy2BgDisabled,
disabledContentColor: Color = source.Btns.Destructive2.btnDestroy2FgDisabled,
) = ZashiButtonColors(
containerColor = containerColor,
contentColor = contentColor,
@ -286,6 +293,12 @@ private fun ZashiButtonColors.toButtonColors() =
disabledContentColor = disabledContentColor,
)
@Suppress("CompositionLocalAllowlist")
val LocalZashiButtonColors =
compositionLocalOf<ZashiButtonColors?> {
null
}
@PreviewScreens
@Composable
private fun PrimaryPreview() =

View File

@ -1,18 +1,24 @@
package co.electriccoin.zcash.ui.design.component
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.isSpecified
import androidx.compose.ui.unit.dp
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
@Composable
fun ZashiCard(
modifier: Modifier = Modifier,
borderColor: Color = Color.Unspecified,
contentPadding: PaddingValues = PaddingValues(24.dp),
content: @Composable ColumnScope.() -> Unit,
) {
Card(
@ -22,9 +28,15 @@ fun ZashiCard(
containerColor = ZashiColors.Surfaces.bgSecondary,
contentColor = ZashiColors.Text.textTertiary
),
border =
if (borderColor.isSpecified) {
BorderStroke(1.dp, borderColor)
} else {
null
}
) {
Column(
Modifier.padding(24.dp)
Modifier.padding(contentPadding)
) {
content()
}

View File

@ -0,0 +1,71 @@
package co.electriccoin.zcash.ui.design.component
import androidx.annotation.IntRange
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ProgressIndicatorDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
@Composable
fun ZashiCircularProgressIndicator(
progress: Float,
modifier: Modifier = Modifier,
colors: ZashiCircularProgressIndicatorColors =
LocalZashiCircularProgressIndicatorColors.current
?: ZashiCircularProgressIndicatorDefaults.colors()
) {
val animatedProgress by animateFloatAsState(
progress,
animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec
)
CircularProgressIndicator(
modifier = modifier,
color = colors.progressColor,
trackColor = colors.trackColor,
progress = { animatedProgress },
gapSize = 0.dp,
strokeWidth = 3.dp
)
}
@Composable
fun ZashiCircularProgressIndicator(
@IntRange(from = 0, to = 100) progressPercent: Int,
modifier: Modifier = Modifier,
colors: ZashiCircularProgressIndicatorColors =
LocalZashiCircularProgressIndicatorColors.current
?: ZashiCircularProgressIndicatorDefaults.colors()
) {
ZashiCircularProgressIndicator(
progress = progressPercent / 100f,
modifier = modifier,
colors = colors
)
}
@Immutable
data class ZashiCircularProgressIndicatorColors(
val progressColor: Color,
val trackColor: Color
)
@Suppress("CompositionLocalAllowlist")
val LocalZashiCircularProgressIndicatorColors = compositionLocalOf<ZashiCircularProgressIndicatorColors?> { null }
object ZashiCircularProgressIndicatorDefaults {
@Composable
fun colors(
progressColor: Color = ZashiColors.Utility.Purple.utilityPurple400,
trackColor: Color = ZashiColors.Utility.Purple.utilityPurple50
) = ZashiCircularProgressIndicatorColors(
progressColor = progressColor,
trackColor = trackColor
)
}

View File

@ -0,0 +1,46 @@
package co.electriccoin.zcash.ui.design.component
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Row
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import co.electriccoin.zcash.ui.design.R
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
@Composable
fun ZashiInfoText(
text: String,
modifier: Modifier = Modifier,
color: Color = ZashiColors.Text.textTertiary,
style: TextStyle = ZashiTypography.textXs,
textAlign: TextAlign = TextAlign.Start,
) {
Row(
modifier = modifier,
) {
Image(
modifier = Modifier,
painter = painterResource(R.drawable.ic_info),
contentDescription = null,
colorFilter = ColorFilter.tint(color)
)
HorizontalSpacer(8.dp)
Text(
modifier =
Modifier
.weight(1f),
text = text,
textAlign = textAlign,
style = style,
color = color
)
}
}

View File

@ -1,13 +1,25 @@
package co.electriccoin.zcash.ui.design.component
import android.view.WindowManager
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.windowInsetsBottomHeight
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.SheetState
import androidx.compose.material3.SheetValue
import androidx.compose.material3.SheetValue.Expanded
import androidx.compose.material3.SheetValue.Hidden
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.DialogWindowProvider
import co.electriccoin.zcash.ui.design.LocalSheetStateManager
@OptIn(ExperimentalMaterial3Api::class)
@ -15,29 +27,64 @@ import co.electriccoin.zcash.ui.design.LocalSheetStateManager
fun <T : ModalBottomSheetState> ZashiScreenModalBottomSheet(
state: T?,
sheetState: SheetState = rememberScreenModalBottomSheetState(),
content: @Composable (state: T) -> Unit = {},
) {
val parent = LocalView.current.parent
SideEffect {
(parent as? DialogWindowProvider)?.window?.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
(parent as? DialogWindowProvider)?.window?.setDimAmount(0f)
}
state?.let {
ZashiModalBottomSheet(
sheetState = sheetState,
content = {
BackHandler {
it.onBack()
}
content(it)
Spacer(24.dp)
androidx.compose.foundation.layout.Spacer(
modifier = Modifier.windowInsetsBottomHeight(WindowInsets.systemBars),
)
LaunchedEffect(Unit) {
sheetState.show()
}
},
onDismissRequest = it.onBack
)
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ZashiScreenModalBottomSheet(
onDismissRequest: () -> Unit,
sheetState: SheetState = rememberScreenModalBottomSheetState(),
content: @Composable () -> Unit = {},
) {
ZashiModalBottomSheet(
ZashiScreenModalBottomSheet(
state =
remember(onDismissRequest) {
object : ModalBottomSheetState {
override val onBack: () -> Unit = {
onDismissRequest()
}
}
},
sheetState = sheetState,
content = {
BackHandler(state != null) {
state?.onBack?.invoke()
}
content()
},
onDismissRequest = { state?.onBack?.invoke() }
)
LaunchedEffect(Unit) {
sheetState.show()
}
}
@Composable
@ExperimentalMaterial3Api
fun rememberScreenModalBottomSheetState(
initialValue: SheetValue = Hidden,
skipHiddenState: Boolean = false,
initialValue: SheetValue = if (LocalInspectionMode.current) Expanded else Hidden,
skipHiddenState: Boolean = LocalInspectionMode.current,
skipPartiallyExpanded: Boolean = true,
confirmValueChange: (SheetValue) -> Boolean = { true },
): SheetState {

View File

@ -10,21 +10,31 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Dp
@Composable
fun VerticalSpacer(height: Dp) {
fun ColumnScope.Spacer(height: Dp) {
Spacer(Modifier.height(height))
}
@Composable
fun ColumnScope.VerticalSpacer(weight: Float) {
fun ColumnScope.Spacer(weight: Float) {
Spacer(Modifier.weight(weight))
}
@Composable
fun RowScope.VerticalSpacer(weight: Float) {
fun RowScope.Spacer(weight: Float) {
Spacer(Modifier.weight(weight))
}
@Composable
fun RowScope.Spacer(width: Dp) {
Spacer(Modifier.width(width))
}
@Composable
fun HorizontalSpacer(width: Dp) {
Spacer(Modifier.width(width))
}
@Composable
fun VerticalSpacer(height: Dp) {
Spacer(Modifier.height(height))
}

View File

@ -28,7 +28,8 @@ val DarkZashiColorsInternal =
textError = ErrorRed.`300`,
textLink = HyperBlue.`300`,
textLight = Shark.`50`,
textLightSupport = Shark.`200`
textLightSupport = Shark.`200`,
textOpposite = Base.Bone
),
Btns =
Btns(
@ -543,7 +544,8 @@ val DarkZashiColorsInternal =
utilityPurple50 = Purple.`950`,
utilityPurple100 = Purple.`900`,
utilityPurple400 = Purple.`600`,
utilityPurple300 = Purple.`700`
utilityPurple300 = Purple.`700`,
utilityPurple900 = Purple.`50`
),
Espresso =
UtilityEspresso(
@ -555,8 +557,9 @@ val DarkZashiColorsInternal =
utilityEspresso100 = Espresso.`900`,
utilityEspresso400 = Espresso.`500`,
utilityEspresso300 = Espresso.`600`,
utilityEspresso800 = Espresso.`100`,
utilityEspresso900 = Espresso.`50`,
utilityEspresso800 = Espresso.`100`
utilityEspresso950 = Espresso.`25`
)
),
Transparent =

View File

@ -28,7 +28,8 @@ val LightZashiColorsInternal =
textError = ErrorRed.`500`,
textLink = HyperBlue.`500`,
textLight = Gray.`25`,
textLightSupport = Gray.`200`
textLightSupport = Gray.`200`,
textOpposite = Base.Bone
),
Btns =
Btns(
@ -543,7 +544,8 @@ val LightZashiColorsInternal =
utilityPurple50 = Purple.`50`,
utilityPurple100 = Purple.`100`,
utilityPurple400 = Purple.`400`,
utilityPurple300 = Purple.`300`
utilityPurple300 = Purple.`300`,
utilityPurple900 = Purple.`900`
),
Espresso =
UtilityEspresso(
@ -556,7 +558,8 @@ val LightZashiColorsInternal =
utilityEspresso400 = Espresso.`400`,
utilityEspresso300 = Espresso.`300`,
utilityEspresso900 = Espresso.`900`,
utilityEspresso800 = Espresso.`800`
utilityEspresso800 = Espresso.`800`,
utilityEspresso950 = Espresso.`950`
)
),
Transparent =

View File

@ -145,7 +145,7 @@ internal object Indigo {
val `950` = Color(0xFF1F235B)
}
internal object Purple {
object Purple {
val `25` = Color(0xFFFAFAFF)
val `50` = Color(0xFFF4F3FF)
val `100` = Color(0xFFEBE9FE)

View File

@ -8,5 +8,17 @@ import androidx.compose.runtime.staticCompositionLocalOf
val ZashiColors: ZashiColorsInternal
@Composable get() = LocalZashiColors.current
val ZashiLightColors: ZashiColorsInternal
@Composable get() = LocalLightZashiColors.current
val ZashiDarkColors: ZashiColorsInternal
@Composable get() = LocalDarkZashiColors.current
@Suppress("CompositionLocalAllowlist")
internal val LocalZashiColors = staticCompositionLocalOf<ZashiColorsInternal> { error("no colors specified") }
@Suppress("CompositionLocalAllowlist")
internal val LocalLightZashiColors = staticCompositionLocalOf { LightZashiColorsInternal }
@Suppress("CompositionLocalAllowlist")
internal val LocalDarkZashiColors = staticCompositionLocalOf { DarkZashiColorsInternal }

View File

@ -56,7 +56,8 @@ data class Text(
val textError: Color,
val textLink: Color,
val textLight: Color,
val textLightSupport: Color
val textLightSupport: Color,
val textOpposite: Color
)
@Immutable
@ -647,7 +648,8 @@ data class UtilityPurple(
val utilityPurple50: Color,
val utilityPurple100: Color,
val utilityPurple400: Color,
val utilityPurple300: Color
val utilityPurple300: Color,
val utilityPurple900: Color
)
@Immutable
@ -661,6 +663,7 @@ data class UtilityEspresso(
val utilityEspresso400: Color,
val utilityEspresso300: Color,
val utilityEspresso900: Color,
val utilityEspresso950: Color,
val utilityEspresso800: Color
)

View File

@ -15,6 +15,7 @@ import co.electriccoin.zcash.ui.screen.contact.viewmodel.UpdateContactViewModel
import co.electriccoin.zcash.ui.screen.feedback.viewmodel.FeedbackViewModel
import co.electriccoin.zcash.ui.screen.flexa.FlexaViewModel
import co.electriccoin.zcash.ui.screen.home.HomeViewModel
import co.electriccoin.zcash.ui.screen.home.balance.TransparentBalanceInfoViewModel
import co.electriccoin.zcash.ui.screen.integrations.IntegrationsViewModel
import co.electriccoin.zcash.ui.screen.qrcode.viewmodel.QrCodeViewModel
import co.electriccoin.zcash.ui.screen.receive.viewmodel.ReceiveViewModel
@ -142,4 +143,5 @@ val viewModelModule =
viewModelOf(::RestoreBDHeightViewModel)
viewModelOf(::RestoreBDDateViewModel)
viewModelOf(::RestoreBDEstimationViewModel)
viewModelOf(::TransparentBalanceInfoViewModel)
}

View File

@ -26,13 +26,11 @@ import co.electriccoin.zcash.ui.NavigationTargets.ABOUT
import co.electriccoin.zcash.ui.NavigationTargets.ADVANCED_SETTINGS
import co.electriccoin.zcash.ui.NavigationTargets.CHOOSE_SERVER
import co.electriccoin.zcash.ui.NavigationTargets.DELETE_WALLET
import co.electriccoin.zcash.ui.NavigationTargets.EXCHANGE_RATE_OPT_IN
import co.electriccoin.zcash.ui.NavigationTargets.EXPORT_PRIVATE_DATA
import co.electriccoin.zcash.ui.NavigationTargets.NOT_ENOUGH_SPACE
import co.electriccoin.zcash.ui.NavigationTargets.QR_CODE
import co.electriccoin.zcash.ui.NavigationTargets.REQUEST
import co.electriccoin.zcash.ui.NavigationTargets.SETTINGS
import co.electriccoin.zcash.ui.NavigationTargets.SETTINGS_EXCHANGE_RATE_OPT_IN
import co.electriccoin.zcash.ui.NavigationTargets.SUPPORT
import co.electriccoin.zcash.ui.NavigationTargets.WHATS_NEW
import co.electriccoin.zcash.ui.common.compose.LocalNavController
@ -62,12 +60,26 @@ import co.electriccoin.zcash.ui.screen.contact.WrapUpdateContact
import co.electriccoin.zcash.ui.screen.deletewallet.WrapDeleteWallet
import co.electriccoin.zcash.ui.screen.disconnected.WrapDisconnected
import co.electriccoin.zcash.ui.screen.exchangerate.optin.AndroidExchangeRateOptIn
import co.electriccoin.zcash.ui.screen.exchangerate.settings.AndroidSettingsExchangeRateOptIn
import co.electriccoin.zcash.ui.screen.exchangerate.optin.ExchangeRateOptIn
import co.electriccoin.zcash.ui.screen.exchangerate.settings.AndroidExchangeRateSettings
import co.electriccoin.zcash.ui.screen.exchangerate.settings.ExchangeRateSettings
import co.electriccoin.zcash.ui.screen.exportdata.WrapExportPrivateData
import co.electriccoin.zcash.ui.screen.feedback.WrapFeedback
import co.electriccoin.zcash.ui.screen.flexa.FlexaViewModel
import co.electriccoin.zcash.ui.screen.home.AndroidHome
import co.electriccoin.zcash.ui.screen.home.AndroidSeedBackupInfo
import co.electriccoin.zcash.ui.screen.home.AndroidWalletDisconnectedInfo
import co.electriccoin.zcash.ui.screen.home.AndroidWalletRestoringInfo
import co.electriccoin.zcash.ui.screen.home.AndroidWalletSyncingInfo
import co.electriccoin.zcash.ui.screen.home.AndroidWalletUpdatingInfo
import co.electriccoin.zcash.ui.screen.home.Home
import co.electriccoin.zcash.ui.screen.home.SeedBackupInfo
import co.electriccoin.zcash.ui.screen.home.WalletDisconnectedInfo
import co.electriccoin.zcash.ui.screen.home.WalletRestoringInfo
import co.electriccoin.zcash.ui.screen.home.WalletSyncingInfo
import co.electriccoin.zcash.ui.screen.home.WalletUpdatingInfo
import co.electriccoin.zcash.ui.screen.home.balance.AndroidTransparentBalanceInfo
import co.electriccoin.zcash.ui.screen.home.balance.TransparentBalanceInfo
import co.electriccoin.zcash.ui.screen.integrations.AndroidDialogIntegrations
import co.electriccoin.zcash.ui.screen.integrations.AndroidIntegrations
import co.electriccoin.zcash.ui.screen.integrations.DialogIntegrations
@ -248,11 +260,11 @@ internal fun MainActivity.Navigation() {
dialog<DialogIntegrations> {
AndroidDialogIntegrations()
}
composable(EXCHANGE_RATE_OPT_IN) {
composable<ExchangeRateOptIn> {
AndroidExchangeRateOptIn()
}
composable(SETTINGS_EXCHANGE_RATE_OPT_IN) {
AndroidSettingsExchangeRateOptIn()
composable<ExchangeRateSettings> {
AndroidExchangeRateSettings()
}
composable<ScanKeystoneSignInRequest> {
WrapScanKeystoneSignInRequest()
@ -399,7 +411,61 @@ internal fun MainActivity.Navigation() {
AndroidSeedInfo()
}
composable<SeedBackup> {
AndroidSeedBackup()
AndroidSeedBackup(it.toRoute())
}
dialog<SeedBackupInfo>(
dialogProperties =
DialogProperties(
dismissOnBackPress = false,
dismissOnClickOutside = false
)
) {
AndroidSeedBackupInfo()
}
dialog<TransparentBalanceInfo>(
dialogProperties =
DialogProperties(
dismissOnBackPress = false,
dismissOnClickOutside = false
)
) {
AndroidTransparentBalanceInfo()
}
dialog<WalletDisconnectedInfo>(
dialogProperties =
DialogProperties(
dismissOnBackPress = false,
dismissOnClickOutside = false
)
) {
AndroidWalletDisconnectedInfo()
}
dialog<WalletRestoringInfo>(
dialogProperties =
DialogProperties(
dismissOnBackPress = false,
dismissOnClickOutside = false
)
) {
AndroidWalletRestoringInfo()
}
dialog<WalletSyncingInfo>(
dialogProperties =
DialogProperties(
dismissOnBackPress = false,
dismissOnClickOutside = false
)
) {
AndroidWalletSyncingInfo()
}
dialog<WalletUpdatingInfo>(
dialogProperties =
DialogProperties(
dismissOnBackPress = false,
dismissOnClickOutside = false
)
) {
AndroidWalletUpdatingInfo()
}
}
}
@ -524,14 +590,12 @@ object NavigationTargets {
const val ABOUT = "about"
const val ADVANCED_SETTINGS = "advanced_settings"
const val DELETE_WALLET = "delete_wallet"
const val EXCHANGE_RATE_OPT_IN = "exchange_rate_opt_in"
const val EXPORT_PRIVATE_DATA = "export_private_data"
const val CHOOSE_SERVER = "choose_server"
const val NOT_ENOUGH_SPACE = "not_enough_space"
const val QR_CODE = "qr_code"
const val REQUEST = "request"
const val SETTINGS = "settings"
const val SETTINGS_EXCHANGE_RATE_OPT_IN = "settings_exchange_rate_opt_in"
const val SUPPORT = "support"
const val WHATS_NEW = "whats_new"
}

View File

@ -6,12 +6,12 @@ import co.electriccoin.zcash.preference.StandardPreferenceProvider
import co.electriccoin.zcash.preference.model.entry.NullableBooleanPreferenceDefault
import co.electriccoin.zcash.spackle.Twig
import co.electriccoin.zcash.ui.NavigationRouter
import co.electriccoin.zcash.ui.NavigationTargets.EXCHANGE_RATE_OPT_IN
import co.electriccoin.zcash.ui.common.provider.SynchronizerProvider
import co.electriccoin.zcash.ui.common.wallet.ExchangeRateState
import co.electriccoin.zcash.ui.common.wallet.RefreshLock
import co.electriccoin.zcash.ui.common.wallet.StaleLock
import co.electriccoin.zcash.ui.preference.StandardPreferenceKeys
import co.electriccoin.zcash.ui.screen.exchangerate.optin.ExchangeRateOptIn
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
@ -204,7 +204,7 @@ class ExchangeRateRepositoryImpl(
setNullableBooleanPreference(StandardPreferenceKeys.EXCHANGE_RATE_OPTED_IN, false)
}
private fun showOptInExchangeRateUsd() = navigationRouter.forward(EXCHANGE_RATE_OPT_IN)
private fun showOptInExchangeRateUsd() = navigationRouter.forward(ExchangeRateOptIn)
private fun nullableBooleanStateFlow(default: NullableBooleanPreferenceDefault): StateFlow<Boolean?> =
flow {

View File

@ -13,6 +13,7 @@ import cash.z.ecc.android.sdk.model.ZcashNetwork
import cash.z.ecc.sdk.type.fromResources
import co.electriccoin.zcash.preference.StandardPreferenceProvider
import co.electriccoin.zcash.spackle.Twig
import co.electriccoin.zcash.ui.NavigationRouter
import co.electriccoin.zcash.ui.common.model.OnboardingState
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
@ -50,6 +51,7 @@ class WalletViewModel(
private val resetSharedPrefsData: ResetSharedPrefsDataUseCase,
private val isFlexaAvailable: IsFlexaAvailableUseCase,
private val getSynchronizer: GetSynchronizerUseCase,
private val navigationRouter: NavigationRouter,
) : AndroidViewModel(application) {
val synchronizer = walletRepository.synchronizer
@ -68,7 +70,11 @@ class WalletViewModel(
}
fun dismissOptInExchangeRateUsd() {
exchangeRateRepository.dismissOptInExchangeRateUsd()
navigationRouter.back()
}
fun onSkipClick() {
navigationRouter.back()
}
fun persistNewWalletAndRestoringState(state: WalletRestoringState) {

View File

@ -1,12 +1,8 @@
package co.electriccoin.zcash.ui.screen.accountlist
import android.view.WindowManager
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.window.DialogWindowProvider
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import co.electriccoin.zcash.ui.screen.accountlist.view.AccountListView
import co.electriccoin.zcash.ui.screen.accountlist.viewmodel.AccountListViewModel
@ -17,12 +13,5 @@ import org.koin.androidx.compose.koinViewModel
fun AndroidAccountList() {
val viewModel = koinViewModel<AccountListViewModel>()
val state by viewModel.state.collectAsStateWithLifecycle()
val parent = LocalView.current.parent
SideEffect {
(parent as? DialogWindowProvider)?.window?.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
(parent as? DialogWindowProvider)?.window?.setDimAmount(0f)
}
state?.let {
AccountListView(it)
}
AccountListView(state)
}

View File

@ -7,12 +7,9 @@ import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.windowInsetsBottomHeight
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.ExperimentalMaterial3Api
@ -55,14 +52,14 @@ import kotlinx.collections.immutable.persistentListOf
@Composable
@OptIn(ExperimentalMaterial3Api::class)
internal fun AccountListView(
state: AccountListState,
state: AccountListState?,
sheetState: SheetState = rememberScreenModalBottomSheetState(),
) {
ZashiScreenModalBottomSheet(
state = state,
sheetState = sheetState,
content = {
BottomSheetContent(state)
BottomSheetContent(it)
},
)
}
@ -121,8 +118,6 @@ private fun BottomSheetContent(state: AccountListState) {
)
)
}
Spacer(modifier = Modifier.height(24.dp))
Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.systemBars))
}
}

View File

@ -13,6 +13,7 @@ import co.electriccoin.zcash.ui.common.usecase.NavigateToTaxExportUseCase
import co.electriccoin.zcash.ui.design.component.ButtonState
import co.electriccoin.zcash.ui.design.component.listitem.ZashiListItemState
import co.electriccoin.zcash.ui.design.util.stringRes
import co.electriccoin.zcash.ui.screen.exchangerate.optin.ExchangeRateOptIn
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@ -88,7 +89,7 @@ class AdvancedSettingsViewModel(
private fun onChooseServerClick() = navigationRouter.forward(NavigationTargets.CHOOSE_SERVER)
private fun onCurrencyConversionClick() = navigationRouter.forward(NavigationTargets.SETTINGS_EXCHANGE_RATE_OPT_IN)
private fun onCurrencyConversionClick() = navigationRouter.forward(ExchangeRateOptIn)
private fun onTaxExportClick() =
viewModelScope.launch {

View File

@ -5,6 +5,7 @@ import androidx.activity.viewModels
import androidx.compose.runtime.Composable
import co.electriccoin.zcash.ui.common.compose.LocalActivity
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
import kotlinx.serialization.Serializable
@Composable
fun AndroidExchangeRateOptIn() {
@ -16,7 +17,11 @@ fun AndroidExchangeRateOptIn() {
}
ExchangeRateOptIn(
onEnabledClick = { walletViewModel.optInExchangeRateUsd(true) },
onDismiss = { walletViewModel.dismissOptInExchangeRateUsd() }
onEnableClick = { walletViewModel.optInExchangeRateUsd(true) },
onDismiss = { walletViewModel.dismissOptInExchangeRateUsd() },
onSkipClick = { walletViewModel.onSkipClick() }
)
}
@Serializable
object ExchangeRateOptIn

View File

@ -30,7 +30,8 @@ import co.electriccoin.zcash.ui.screen.exchangerate.BaseExchangeRateOptIn
@Composable
fun ExchangeRateOptIn(
onEnabledClick: () -> Unit,
onEnableClick: () -> Unit,
onSkipClick: () -> Unit,
onDismiss: () -> Unit,
) {
BaseExchangeRateOptIn(
@ -58,15 +59,9 @@ fun ExchangeRateOptIn(
)
},
footer = {
ZashiButton(
modifier = Modifier.fillMaxWidth(),
text = stringResource(R.string.exchange_rate_opt_in_enable),
onClick = onEnabledClick,
colors = ZashiButtonDefaults.primaryColors()
)
ZashiTextButton(
modifier = Modifier.fillMaxWidth(),
onClick = onDismiss,
onClick = onSkipClick,
) {
Text(
text = stringResource(R.string.exchange_rate_opt_in_skip),
@ -74,6 +69,12 @@ fun ExchangeRateOptIn(
fontWeight = FontWeight.SemiBold
)
}
ZashiButton(
modifier = Modifier.fillMaxWidth(),
text = stringResource(R.string.exchange_rate_opt_in_enable),
onClick = onEnableClick,
colors = ZashiButtonDefaults.primaryColors()
)
}
)
}
@ -117,6 +118,6 @@ private fun InfoItem(
private fun CurrencyConversionOptInPreview() =
ZcashTheme {
BlankSurface {
ExchangeRateOptIn(onEnabledClick = {}, onDismiss = {})
ExchangeRateOptIn(onEnableClick = {}, onDismiss = {}, onSkipClick = {})
}
}

View File

@ -7,9 +7,10 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import co.electriccoin.zcash.ui.common.compose.LocalActivity
import co.electriccoin.zcash.ui.common.compose.LocalNavController
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
import kotlinx.serialization.Serializable
@Composable
fun AndroidSettingsExchangeRateOptIn() {
fun AndroidExchangeRateSettings() {
val activity = LocalActivity.current
val navController = LocalNavController.current
val walletViewModel by activity.viewModels<WalletViewModel>()
@ -19,9 +20,12 @@ fun AndroidSettingsExchangeRateOptIn() {
navController.popBackStack()
}
SettingsExchangeRateOptIn(
ExchangeRateSettings(
isOptedIn = isOptedIn,
onSaveClick = { walletViewModel.optInExchangeRateUsd(it) },
onDismiss = { navController.popBackStack() }
)
}
@Serializable
object ExchangeRateSettings

View File

@ -37,7 +37,7 @@ import co.electriccoin.zcash.ui.screen.exchangerate.BaseExchangeRateOptIn
import co.electriccoin.zcash.ui.screen.exchangerate.SecondaryCard
@Composable
fun SettingsExchangeRateOptIn(
fun ExchangeRateSettings(
isOptedIn: Boolean,
onDismiss: () -> Unit,
onSaveClick: (Boolean) -> Unit
@ -187,6 +187,6 @@ private val Unchecked: Int
private fun SettingsExchangeRateOptInPreview() =
ZcashTheme {
BlankSurface {
SettingsExchangeRateOptIn(isOptedIn = true, onDismiss = {}, onSaveClick = {})
ExchangeRateSettings(isOptedIn = true, onDismiss = {}, onSaveClick = {})
}
}

View File

@ -0,0 +1,136 @@
package co.electriccoin.zcash.ui.screen.home
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.SheetState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import co.electriccoin.zcash.ui.NavigationRouter
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.component.ButtonState
import co.electriccoin.zcash.ui.design.component.Spacer
import co.electriccoin.zcash.ui.design.component.ZashiBulletText
import co.electriccoin.zcash.ui.design.component.ZashiButton
import co.electriccoin.zcash.ui.design.component.ZashiButtonDefaults
import co.electriccoin.zcash.ui.design.component.ZashiScreenModalBottomSheet
import co.electriccoin.zcash.ui.design.component.rememberScreenModalBottomSheetState
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
import co.electriccoin.zcash.ui.design.util.stringRes
import co.electriccoin.zcash.ui.screen.seed.backup.SeedBackup
import kotlinx.serialization.Serializable
import org.koin.compose.koinInject
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AndroidSeedBackupInfo() {
val navigationRouter = koinInject<NavigationRouter>()
Content(
onBack = { navigationRouter.back() },
onPositiveClick = { navigationRouter.replace(SeedBackup(true)) }
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun Content(
onBack: () -> Unit,
onPositiveClick: () -> Unit,
sheetState: SheetState = rememberScreenModalBottomSheetState(),
) {
ZashiScreenModalBottomSheet(
sheetState = sheetState,
onDismissRequest = onBack
) {
Column(
modifier =
Modifier
.padding(horizontal = 24.dp)
) {
Image(
painter = painterResource(R.drawable.ic_info_backup),
contentDescription = null
)
Spacer(12.dp)
Text(
stringResource(R.string.home_info_backup_title),
color = ZashiColors.Text.textPrimary,
style = ZashiTypography.textXl,
fontWeight = FontWeight.SemiBold
)
Spacer(12.dp)
Text(
stringResource(R.string.home_info_backup_subtitle_1),
color = ZashiColors.Text.textTertiary,
style = ZashiTypography.textMd
)
Spacer(12.dp)
Text(
stringResource(R.string.home_info_backup_subtitle_2),
color = ZashiColors.Text.textTertiary,
style = ZashiTypography.textMd
)
Spacer(12.dp)
ZashiBulletText(
stringResource(R.string.home_info_backup_bullet_1),
stringResource(R.string.home_info_backup_bullet_2),
color = ZashiColors.Text.textTertiary
)
Spacer(12.dp)
Text(
stringResource(R.string.home_info_backup_message_1),
color = ZashiColors.Text.textTertiary,
style = ZashiTypography.textMd
)
Spacer(24.dp)
Text(
stringResource(R.string.home_info_backup_message_2),
color = ZashiColors.Text.textTertiary,
style = ZashiTypography.textMd
)
Spacer(32.dp)
ZashiButton(
modifier = Modifier.fillMaxWidth(),
state =
ButtonState(
text = stringRes(R.string.general_remind_me_later),
onClick = onBack
),
colors = ZashiButtonDefaults.secondaryColors()
)
Spacer(4.dp)
ZashiButton(
modifier = Modifier.fillMaxWidth(),
state =
ButtonState(
text = stringRes(R.string.general_ok),
onClick = onPositiveClick
)
)
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@PreviewScreens
@Composable
private fun Preview() =
ZcashTheme {
Content(
onBack = {},
onPositiveClick = {}
)
}
@Serializable
object SeedBackupInfo

View File

@ -0,0 +1,96 @@
package co.electriccoin.zcash.ui.screen.home
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.SheetState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import co.electriccoin.zcash.ui.NavigationRouter
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.component.ButtonState
import co.electriccoin.zcash.ui.design.component.Spacer
import co.electriccoin.zcash.ui.design.component.ZashiButton
import co.electriccoin.zcash.ui.design.component.ZashiScreenModalBottomSheet
import co.electriccoin.zcash.ui.design.component.rememberScreenModalBottomSheetState
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
import co.electriccoin.zcash.ui.design.util.stringRes
import kotlinx.serialization.Serializable
import org.koin.compose.koinInject
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AndroidWalletDisconnectedInfo() {
val navigationRouter = koinInject<NavigationRouter>()
Content(
onBack = { navigationRouter.back() }
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun Content(
onBack: () -> Unit,
sheetState: SheetState = rememberScreenModalBottomSheetState(),
) {
ZashiScreenModalBottomSheet(
sheetState = sheetState,
onDismissRequest = onBack
) {
Column(
modifier =
Modifier
.padding(horizontal = 24.dp)
) {
Image(
painter = painterResource(R.drawable.ic_info_wallet_disconnected),
contentDescription = null
)
Spacer(12.dp)
Text(
stringResource(R.string.home_info_disconnected_title),
color = ZashiColors.Text.textPrimary,
style = ZashiTypography.textXl,
fontWeight = FontWeight.SemiBold
)
Spacer(12.dp)
Text(
stringResource(R.string.home_info_disconnected_subtitle),
color = ZashiColors.Text.textTertiary,
style = ZashiTypography.textMd
)
Spacer(32.dp)
ZashiButton(
modifier = Modifier.fillMaxWidth(),
state =
ButtonState(
text = stringRes(R.string.general_ok),
onClick = onBack
)
)
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@PreviewScreens
@Composable
private fun Preview() =
ZcashTheme {
Content(
onBack = {},
)
}
@Serializable
object WalletDisconnectedInfo

View File

@ -0,0 +1,101 @@
package co.electriccoin.zcash.ui.screen.home
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.SheetState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import co.electriccoin.zcash.ui.NavigationRouter
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.component.ButtonState
import co.electriccoin.zcash.ui.design.component.Spacer
import co.electriccoin.zcash.ui.design.component.ZashiBulletText
import co.electriccoin.zcash.ui.design.component.ZashiButton
import co.electriccoin.zcash.ui.design.component.ZashiInfoText
import co.electriccoin.zcash.ui.design.component.ZashiScreenModalBottomSheet
import co.electriccoin.zcash.ui.design.component.rememberScreenModalBottomSheetState
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
import co.electriccoin.zcash.ui.design.util.stringRes
import kotlinx.serialization.Serializable
import org.koin.compose.koinInject
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AndroidWalletRestoringInfo() {
val navigationRouter = koinInject<NavigationRouter>()
Content(
onBack = { navigationRouter.back() }
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun Content(
onBack: () -> Unit,
sheetState: SheetState = rememberScreenModalBottomSheetState(),
) {
ZashiScreenModalBottomSheet(
sheetState = sheetState,
onDismissRequest = onBack
) {
Column(
modifier =
Modifier
.padding(horizontal = 24.dp)
) {
Text(
stringResource(R.string.home_info_restoring_title),
color = ZashiColors.Text.textPrimary,
style = ZashiTypography.textXl,
fontWeight = FontWeight.SemiBold
)
Spacer(12.dp)
Text(
stringResource(R.string.home_info_restoring_message),
color = ZashiColors.Text.textTertiary,
style = ZashiTypography.textMd
)
Spacer(12.dp)
ZashiBulletText(
stringResource(R.string.home_info_restoring_bullet_1),
stringResource(R.string.home_info_restoring_bullet_2),
color = ZashiColors.Text.textTertiary
)
Spacer(32.dp)
ZashiInfoText(
stringResource(R.string.home_info_restoring_note),
)
Spacer(24.dp)
ZashiButton(
modifier = Modifier.fillMaxWidth(),
state =
ButtonState(
text = stringRes(R.string.general_ok),
onClick = onBack
)
)
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@PreviewScreens
@Composable
private fun Preview() =
ZcashTheme {
Content(
onBack = {},
)
}
@Serializable
object WalletRestoringInfo

View File

@ -0,0 +1,89 @@
package co.electriccoin.zcash.ui.screen.home
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.SheetState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import co.electriccoin.zcash.ui.NavigationRouter
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.component.ButtonState
import co.electriccoin.zcash.ui.design.component.Spacer
import co.electriccoin.zcash.ui.design.component.ZashiButton
import co.electriccoin.zcash.ui.design.component.ZashiScreenModalBottomSheet
import co.electriccoin.zcash.ui.design.component.rememberScreenModalBottomSheetState
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
import co.electriccoin.zcash.ui.design.util.stringRes
import kotlinx.serialization.Serializable
import org.koin.compose.koinInject
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AndroidWalletSyncingInfo() {
val navigationRouter = koinInject<NavigationRouter>()
Content(
onBack = { navigationRouter.back() }
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun Content(
onBack: () -> Unit,
sheetState: SheetState = rememberScreenModalBottomSheetState(),
) {
ZashiScreenModalBottomSheet(
sheetState = sheetState,
onDismissRequest = onBack
) {
Column(
modifier =
Modifier
.padding(horizontal = 24.dp)
) {
Text(
stringResource(R.string.home_info_syncing_title),
color = ZashiColors.Text.textPrimary,
style = ZashiTypography.textXl,
fontWeight = FontWeight.SemiBold
)
Spacer(12.dp)
Text(
stringResource(R.string.home_info_syncing_message),
color = ZashiColors.Text.textTertiary,
style = ZashiTypography.textMd
)
Spacer(32.dp)
ZashiButton(
modifier = Modifier.fillMaxWidth(),
state =
ButtonState(
text = stringRes(R.string.general_ok),
onClick = onBack
)
)
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@PreviewScreens
@Composable
private fun Preview() =
ZcashTheme {
Content(
onBack = {},
)
}
@Serializable
object WalletSyncingInfo

View File

@ -0,0 +1,89 @@
package co.electriccoin.zcash.ui.screen.home
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.SheetState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import co.electriccoin.zcash.ui.NavigationRouter
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.component.ButtonState
import co.electriccoin.zcash.ui.design.component.Spacer
import co.electriccoin.zcash.ui.design.component.ZashiButton
import co.electriccoin.zcash.ui.design.component.ZashiScreenModalBottomSheet
import co.electriccoin.zcash.ui.design.component.rememberScreenModalBottomSheetState
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
import co.electriccoin.zcash.ui.design.util.stringRes
import kotlinx.serialization.Serializable
import org.koin.compose.koinInject
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AndroidWalletUpdatingInfo() {
val navigationRouter = koinInject<NavigationRouter>()
Content(
onBack = { navigationRouter.back() }
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun Content(
onBack: () -> Unit,
sheetState: SheetState = rememberScreenModalBottomSheetState(),
) {
ZashiScreenModalBottomSheet(
sheetState = sheetState,
onDismissRequest = onBack
) {
Column(
modifier =
Modifier
.padding(horizontal = 24.dp)
) {
Text(
stringResource(R.string.home_info_updating_title),
color = ZashiColors.Text.textPrimary,
style = ZashiTypography.textXl,
fontWeight = FontWeight.SemiBold
)
Spacer(12.dp)
Text(
stringResource(R.string.home_info_updating_message),
color = ZashiColors.Text.textTertiary,
style = ZashiTypography.textMd
)
Spacer(32.dp)
ZashiButton(
modifier = Modifier.fillMaxWidth(),
state =
ButtonState(
text = stringRes(R.string.general_ok),
onClick = onBack
)
)
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@PreviewScreens
@Composable
private fun Preview() =
ZcashTheme {
Content(
onBack = {},
)
}
@Serializable
object WalletUpdatingInfo

View File

@ -6,8 +6,10 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.runtime.Composable
@ -15,6 +17,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.appbar.ZashiMainTopAppBarState
import co.electriccoin.zcash.ui.common.appbar.ZashiTopAppBarWithAccountSelection
@ -30,6 +33,7 @@ import co.electriccoin.zcash.ui.fixture.ZashiMainTopAppBarStateFixture
import co.electriccoin.zcash.ui.screen.balances.BalanceState
import co.electriccoin.zcash.ui.screen.balances.BalanceWidget
import co.electriccoin.zcash.ui.screen.home.messages.HomeMessage
import co.electriccoin.zcash.ui.screen.home.messages.WalletErrorMessageState
import co.electriccoin.zcash.ui.screen.transactionhistory.widget.TransactionHistoryWidgetState
import co.electriccoin.zcash.ui.screen.transactionhistory.widget.TransactionHistoryWidgetStateFixture
import co.electriccoin.zcash.ui.screen.transactionhistory.widget.createTransactionHistoryWidgets
@ -78,10 +82,21 @@ private fun Content(
),
balanceState = balanceState,
)
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge))
NavButtons(paddingValues, state)
Spacer(Modifier.height(16.dp))
HomeMessage(state.message)
NavButtons(
modifier =
Modifier
.zIndex(1f)
.offset(y = 8.dp),
paddingValues = paddingValues,
state = state
)
Spacer(Modifier.height(2.dp))
HomeMessage(
modifier =
Modifier
.zIndex(0f),
state = state.message
)
LazyColumn(
modifier =
Modifier
@ -96,19 +111,22 @@ private fun Content(
}
}
@Suppress("MagicNumber")
@Composable
private fun NavButtons(
paddingValues: PaddingValues,
state: HomeState
state: HomeState,
modifier: Modifier = Modifier
) {
Row(
modifier = Modifier.scaffoldPadding(paddingValues, top = 0.dp, bottom = 0.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp)
modifier = modifier.scaffoldPadding(paddingValues, top = 0.dp, bottom = 0.dp),
horizontalArrangement = Arrangement.spacedBy(9.dp)
) {
ZashiBigIconButton(
modifier =
Modifier
.weight(1f)
.aspectRatio(1.06f)
.testTag(HomeTags.RECEIVE),
state = state.firstButton,
)
@ -116,15 +134,22 @@ private fun NavButtons(
modifier =
Modifier
.weight(1f)
.aspectRatio(1.06f)
.testTag(HomeTags.SEND),
state = state.secondButton,
)
ZashiBigIconButton(
modifier = Modifier.weight(1f),
modifier =
Modifier
.aspectRatio(1.06f)
.weight(1f),
state = state.thirdButton,
)
ZashiBigIconButton(
modifier = Modifier.weight(1f),
modifier =
Modifier
.aspectRatio(1.06f)
.weight(1f),
state = state.fourthButton,
)
}
@ -164,7 +189,7 @@ private fun Preview() {
icon = R.drawable.ic_warning,
onClick = {}
),
message = null
message = WalletErrorMessageState(onClick = {})
)
)
}

View File

@ -2,6 +2,7 @@ package co.electriccoin.zcash.ui.screen.home
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.sdk.ANDROID_STATE_FLOW_TIMEOUT
import co.electriccoin.zcash.ui.NavigationRouter
import co.electriccoin.zcash.ui.NavigationTargets
@ -15,7 +16,17 @@ import co.electriccoin.zcash.ui.common.usecase.IsRestoreSuccessDialogVisibleUseC
import co.electriccoin.zcash.ui.common.usecase.NavigateToCoinbaseUseCase
import co.electriccoin.zcash.ui.design.component.BigIconButtonState
import co.electriccoin.zcash.ui.design.util.stringRes
import co.electriccoin.zcash.ui.screen.exchangerate.optin.ExchangeRateOptIn
import co.electriccoin.zcash.ui.screen.home.balance.TransparentBalanceInfo
import co.electriccoin.zcash.ui.screen.home.messages.EnableCurrencyConversionMessageState
import co.electriccoin.zcash.ui.screen.home.messages.HomeMessageState
import co.electriccoin.zcash.ui.screen.home.messages.TransparentBalanceDetectedMessageState
import co.electriccoin.zcash.ui.screen.home.messages.WalletBackupMessageState
import co.electriccoin.zcash.ui.screen.home.messages.WalletDisconnectedMessageState
import co.electriccoin.zcash.ui.screen.home.messages.WalletErrorMessageState
import co.electriccoin.zcash.ui.screen.home.messages.WalletRestoringMessageState
import co.electriccoin.zcash.ui.screen.home.messages.WalletSyncingMessageState
import co.electriccoin.zcash.ui.screen.home.messages.WalletUpdatingMessageState
import co.electriccoin.zcash.ui.screen.integrations.DialogIntegrations
import co.electriccoin.zcash.ui.screen.receive.Receive
import co.electriccoin.zcash.ui.screen.receive.model.ReceiveAddressType
@ -23,15 +34,17 @@ import co.electriccoin.zcash.ui.screen.scan.Scan
import co.electriccoin.zcash.ui.screen.scan.ScanFlow
import co.electriccoin.zcash.ui.screen.seed.backup.SeedBackup
import co.electriccoin.zcash.ui.screen.send.Send
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.WhileSubscribed
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import kotlin.time.Duration.Companion.seconds
class HomeViewModel(
getVersionInfoProvider: GetVersionInfoProvider,
@ -40,7 +53,73 @@ class HomeViewModel(
private val isRestoreSuccessDialogVisible: IsRestoreSuccessDialogVisibleUseCase,
private val navigateToCoinbase: NavigateToCoinbaseUseCase
) : ViewModel() {
private val isMessageVisible = MutableStateFlow(true)
@Suppress("MagicNumber")
private val messageState =
flow {
val states =
listOf(
WalletErrorMessageState(
onClick = {}
),
WalletDisconnectedMessageState(onClick = {
navigationRouter.forward(WalletDisconnectedInfo)
}),
WalletRestoringMessageState(progress = 0, onClick = {
navigationRouter.forward(WalletRestoringInfo)
}),
WalletRestoringMessageState(progress = 100, onClick = {
navigationRouter.forward(WalletRestoringInfo)
}),
WalletSyncingMessageState(progress = 0, onClick = {
navigationRouter.forward(WalletSyncingInfo)
}),
WalletSyncingMessageState(progress = 100, onClick = {
navigationRouter.forward(WalletSyncingInfo)
}),
WalletUpdatingMessageState(onClick = {
navigationRouter.forward(WalletUpdatingInfo)
}),
WalletBackupMessageState(
onClick = {
navigationRouter.forward(SeedBackupInfo)
},
onButtonClick = {
navigationRouter.forward(SeedBackup(false))
}
),
TransparentBalanceDetectedMessageState(
subtitle = stringRes(zatoshi = Zatoshi(1000)),
onClick = {
navigationRouter.forward(TransparentBalanceInfo)
},
onButtonClick = {
// navigationRouter.forward(TransparentBalanceInfo)
},
),
EnableCurrencyConversionMessageState(
onClick = {
navigationRouter.forward(ExchangeRateOptIn)
},
onButtonClick = {
navigationRouter.forward(ExchangeRateOptIn)
},
)
)
var index = 0
while (true) {
emit(states[index])
delay(3.seconds)
if (index == states.lastIndex) {
emit(null)
delay(10.seconds)
index = 0
} else {
index += 1
}
}
}
private val isRestoreDialogVisible: Flow<Boolean?> =
isRestoreSuccessDialogVisible
@ -64,8 +143,11 @@ class HomeViewModel(
)
val state: StateFlow<HomeState?> =
combine(getSelectedWalletAccountUseCase.observe(), isMessageVisible) { selectedAccount, isMessageVisible ->
createState(getVersionInfoProvider, selectedAccount, isMessageVisible)
combine(
getSelectedWalletAccountUseCase.observe(),
messageState
) { selectedAccount, messageState ->
createState(getVersionInfoProvider, selectedAccount, messageState)
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT),
@ -75,7 +157,7 @@ class HomeViewModel(
private fun createState(
getVersionInfoProvider: GetVersionInfoProvider,
selectedAccount: WalletAccount?,
isMessageVisible: Boolean
messageState: HomeMessageState?
) = HomeState(
firstButton =
BigIconButtonState(
@ -118,16 +200,9 @@ class HomeViewModel(
onClick = ::onMoreButtonClick,
)
},
message = createWalletBackupMessageState().takeIf { isMessageVisible }
message = messageState
)
private fun createWalletBackupMessageState(): WalletBackupMessageState =
WalletBackupMessageState(
onClick = {
navigationRouter.forward(SeedBackup)
}
)
private fun onRestoreDialogSeenClick() =
viewModelScope.launch {
isRestoreSuccessDialogVisible.setSeen()

View File

@ -0,0 +1,19 @@
package co.electriccoin.zcash.ui.screen.home.balance
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import kotlinx.serialization.Serializable
import org.koin.androidx.compose.koinViewModel
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AndroidTransparentBalanceInfo() {
val vm = koinViewModel<TransparentBalanceInfoViewModel>()
val state by vm.state.collectAsStateWithLifecycle()
state?.let { TransparentBalanceInfoView(it) }
}
@Serializable
object TransparentBalanceInfo

View File

@ -0,0 +1,12 @@
package co.electriccoin.zcash.ui.screen.home.balance
import cash.z.ecc.android.sdk.model.Zatoshi
import co.electriccoin.zcash.ui.design.component.ButtonState
import co.electriccoin.zcash.ui.design.component.ModalBottomSheetState
data class TransparentBalanceInfoState(
val transparentAmount: Zatoshi,
override val onBack: () -> Unit,
val primaryButton: ButtonState,
val secondaryButton: ButtonState
) : ModalBottomSheetState

View File

@ -0,0 +1,152 @@
package co.electriccoin.zcash.ui.screen.home.balance
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.SheetState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import cash.z.ecc.android.sdk.model.Zatoshi
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.component.ButtonState
import co.electriccoin.zcash.ui.design.component.Spacer
import co.electriccoin.zcash.ui.design.component.ZashiButton
import co.electriccoin.zcash.ui.design.component.ZashiButtonDefaults
import co.electriccoin.zcash.ui.design.component.ZashiCard
import co.electriccoin.zcash.ui.design.component.ZashiScreenModalBottomSheet
import co.electriccoin.zcash.ui.design.component.rememberScreenModalBottomSheetState
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
import co.electriccoin.zcash.ui.design.util.getValue
import co.electriccoin.zcash.ui.design.util.stringRes
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TransparentBalanceInfoView(
state: TransparentBalanceInfoState?,
sheetState: SheetState = rememberScreenModalBottomSheetState(),
) {
ZashiScreenModalBottomSheet(
sheetState = sheetState,
state = state,
) {
Content(it)
}
}
@Composable
private fun Content(state: TransparentBalanceInfoState) {
Column(
modifier =
Modifier
.padding(horizontal = 24.dp)
) {
Image(
painter = painterResource(R.drawable.ic_info_shield),
contentDescription = null
)
Spacer(12.dp)
Text(
stringResource(R.string.home_info_transparent_title),
color = ZashiColors.Text.textPrimary,
style = ZashiTypography.textXl,
fontWeight = FontWeight.SemiBold
)
Spacer(12.dp)
Text(
stringResource(R.string.home_info_transparent_subtitle),
color = ZashiColors.Text.textTertiary,
style = ZashiTypography.textMd
)
Spacer(24.dp)
Text(
stringResource(R.string.home_info_transparent_message),
color = ZashiColors.Text.textTertiary,
style = ZashiTypography.textMd
)
Spacer(32.dp)
ZashiCard(
modifier = Modifier.fillMaxWidth(),
contentPadding =
PaddingValues(
horizontal = 20.dp,
vertical = 12.dp
),
borderColor = ZashiColors.Surfaces.strokeSecondary
) {
Row(
verticalAlignment = Alignment.CenterVertically
) {
Text(
stringResource(R.string.home_info_transparent_subheader),
color = ZashiColors.Text.textPrimary,
style = ZashiTypography.textMd,
fontWeight = FontWeight.Medium
)
Spacer(4.dp)
Image(
painter = painterResource(R.drawable.ic_transparent_small),
contentDescription = null
)
}
Spacer(4.dp)
Text(
text =
stringResource(
R.string.home_message_transparent_balance_subtitle,
stringRes(state.transparentAmount).getValue()
),
color = ZashiColors.Text.textPrimary,
style = ZashiTypography.textXl,
fontWeight = FontWeight.SemiBold
)
}
Spacer(24.dp)
ZashiButton(
modifier = Modifier.fillMaxWidth(),
state = state.secondaryButton,
colors = ZashiButtonDefaults.secondaryColors()
)
Spacer(4.dp)
ZashiButton(
modifier = Modifier.fillMaxWidth(),
state = state.primaryButton
)
}
}
@OptIn(ExperimentalMaterial3Api::class)
@PreviewScreens
@Composable
private fun Preview() =
ZcashTheme {
TransparentBalanceInfoView(
state =
TransparentBalanceInfoState(
onBack = {},
primaryButton =
ButtonState(
text = stringRes("Remind me later"),
onClick = {}
),
secondaryButton =
ButtonState(
text = stringRes("Shield"),
onClick = {}
),
transparentAmount = Zatoshi(0)
)
)
}

View File

@ -0,0 +1,45 @@
package co.electriccoin.zcash.ui.screen.home.balance
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.sdk.ANDROID_STATE_FLOW_TIMEOUT
import co.electriccoin.zcash.ui.NavigationRouter
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.usecase.GetSelectedWalletAccountUseCase
import co.electriccoin.zcash.ui.design.component.ButtonState
import co.electriccoin.zcash.ui.design.util.stringRes
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.WhileSubscribed
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
class TransparentBalanceInfoViewModel(
getSelectedWalletAccount: GetSelectedWalletAccountUseCase,
private val navigationRouter: NavigationRouter
) : ViewModel() {
val state: StateFlow<TransparentBalanceInfoState?> =
getSelectedWalletAccount
.observe()
.map {
TransparentBalanceInfoState(
onBack = { navigationRouter.back() },
primaryButton =
ButtonState(
onClick = { navigationRouter.back() },
text = stringRes(R.string.home_info_transparent_balance_shield)
),
secondaryButton =
ButtonState(
onClick = { navigationRouter.back() },
text = stringRes(R.string.general_remind_me_later)
),
transparentAmount = it?.transparent?.balance ?: Zatoshi(0)
)
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT),
initialValue = null
)
}

View File

@ -0,0 +1,84 @@
package co.electriccoin.zcash.ui.screen.home.messages
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.height
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.component.BlankSurface
import co.electriccoin.zcash.ui.design.component.ButtonState
import co.electriccoin.zcash.ui.design.component.ZashiButton
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.design.util.stringRes
@Suppress("ModifierNaming")
@Composable
fun EnableCurrencyConversionMessage(
contentPadding: PaddingValues,
state: EnableCurrencyConversionMessageState,
innerModifier: Modifier = Modifier,
) {
HomeMessageWrapper(
innerModifier = innerModifier,
contentPadding = contentPadding,
onClick = state.onClick,
start = {
Image(
modifier = Modifier.align(Alignment.Top),
painter = painterResource(R.drawable.ic_message_currency_conversion),
contentDescription = null,
colorFilter = ColorFilter.tint(LocalContentColor.current)
)
},
title = {
Text(
stringResource(R.string.home_message_currency_conversion_title)
)
},
subtitle = {
Text(
text = stringResource(R.string.home_message_currency_conversion_subtitle),
)
},
end = {
ZashiButton(
modifier = Modifier.height(36.dp),
state =
ButtonState(
onClick = state.onButtonClick,
text = stringRes(stringResource(R.string.home_message_currency_conversion_button))
)
)
}
)
}
class EnableCurrencyConversionMessageState(
val onClick: () -> Unit,
val onButtonClick: () -> Unit,
) : HomeMessageState
@PreviewScreens
@Composable
private fun Preview() =
ZcashTheme {
BlankSurface {
EnableCurrencyConversionMessage(
state =
EnableCurrencyConversionMessageState(
onClick = {},
onButtonClick = {}
),
contentPadding = PaddingValues()
)
}
}

View File

@ -1,6 +1,8 @@
package co.electriccoin.zcash.ui.screen.home.messages
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.CubicBezierEasing
import androidx.compose.animation.core.TweenSpec
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.tween
import androidx.compose.animation.expandIn
@ -34,53 +36,122 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
import kotlinx.coroutines.delay
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
@Suppress("MagicNumber")
@Suppress("MagicNumber", "CyclomaticComplexMethod")
@Composable
fun HomeMessage(state: HomeMessageState?) {
val cutoutHeight = 16.dp
fun HomeMessage(
state: HomeMessageState?,
modifier: Modifier = Modifier
) {
var normalizedState: HomeMessageState? by remember { mutableStateOf(state) }
var isVisible by remember { mutableStateOf(state != null) }
val bottomCornerSize by animateDpAsState(
if (isVisible) cutoutHeight else 0.dp,
animationSpec = tween(350)
targetValue = if (isVisible) BOTTOM_CUTOUT_HEIGHT_DP.dp else 0.dp,
animationSpec = animationSpec()
)
val bottomHeight by animateDpAsState(
targetValue = if (isVisible) BOTTOM_CUTOUT_HEIGHT_DP.dp else TOP_CUTOUT_HEIGHT_DP.dp,
animationSpec =
animationSpec(
delay = if (isVisible) null else 250.milliseconds
)
)
Box(
modifier =
Modifier
.background(Color.Gray)
modifier = modifier
) {
Box(
modifier =
Modifier
.fillMaxWidth()
.height(cutoutHeight)
.height(TOP_CUTOUT_HEIGHT_DP.dp)
.zIndex(2f)
.bottomOnlyShadow(
elevation = 2.dp,
shape = RoundedCornerShape(bottomStart = 32.dp, bottomEnd = 32.dp),
shape =
RoundedCornerShape(
bottomStart = TOP_CUTOUT_HEIGHT_DP.dp,
bottomEnd = TOP_CUTOUT_HEIGHT_DP.dp
),
backgroundColor = ZashiColors.Surfaces.bgPrimary
),
)
AnimatedVisibility(
modifier =
Modifier
.fillMaxWidth()
.zIndex(0f),
visible = isVisible,
enter = expandIn(animationSpec = tween(350)),
exit = shrinkOut(animationSpec = tween(350))
enter =
expandIn(
animationSpec = animationSpec(),
expandFrom = Alignment.TopEnd
),
exit =
shrinkOut(
animationSpec = animationSpec(),
shrinkTowards = Alignment.TopEnd
)
) {
val contentPadding = PaddingValues(top = TOP_CUTOUT_HEIGHT_DP.dp, bottom = BOTTOM_CUTOUT_HEIGHT_DP.dp)
val innerModifier = Modifier
when (normalizedState) {
is WalletBackupMessageState ->
WalletBackupMessage(
innerModifier = innerModifier,
state = normalizedState as WalletBackupMessageState,
contentPadding =
PaddingValues(
vertical = cutoutHeight
)
contentPadding = contentPadding
)
is EnableCurrencyConversionMessageState ->
EnableCurrencyConversionMessage(
innerModifier = innerModifier,
state = normalizedState as EnableCurrencyConversionMessageState,
contentPadding = contentPadding
)
is TransparentBalanceDetectedMessageState ->
TransparentBalanceDetectedMessage(
innerModifier = innerModifier,
state = normalizedState as TransparentBalanceDetectedMessageState,
contentPadding = contentPadding
)
is WalletDisconnectedMessageState ->
WalletDisconnectedMessage(
innerModifier = innerModifier,
state = normalizedState as WalletDisconnectedMessageState,
contentPadding = contentPadding
)
is WalletRestoringMessageState ->
WalletRestoringMessage(
innerModifier = innerModifier,
state = normalizedState as WalletRestoringMessageState,
contentPadding = contentPadding
)
is WalletSyncingMessageState ->
WalletSyncingMessage(
innerModifier = innerModifier,
state = normalizedState as WalletSyncingMessageState,
contentPadding = contentPadding
)
is WalletUpdatingMessageState ->
WalletUpdatingMessage(
innerModifier = innerModifier,
state = normalizedState as WalletUpdatingMessageState,
contentPadding = contentPadding
)
is WalletErrorMessageState ->
WalletErrorMessage(
innerModifier = innerModifier,
state = normalizedState as WalletErrorMessageState,
contentPadding = contentPadding
)
null -> {
@ -93,7 +164,7 @@ fun HomeMessage(state: HomeMessageState?) {
modifier =
Modifier
.fillMaxWidth()
.height(cutoutHeight)
.height(bottomHeight)
.zIndex(1f)
.align(Alignment.BottomCenter)
.topOnlyShadow(
@ -105,17 +176,51 @@ fun HomeMessage(state: HomeMessageState?) {
}
LaunchedEffect(state) {
if (state != null) {
normalizedState = state
isVisible = true
} else {
isVisible = false
delay(350)
normalizedState = null
when {
normalizedState == null -> {
normalizedState = state
isVisible = state != null
}
state == null -> {
isVisible = false
delay(ANIMATION_DURATION_MS.milliseconds)
normalizedState = null
}
normalizedState!!::class == state::class -> {
normalizedState = state
isVisible = true
}
else -> {
isVisible = false
delay(ANIMATION_DURATION_BETWEEN_MESSAGES_MS.milliseconds)
normalizedState = state
isVisible = true
}
}
}
}
sealed interface HomeMessageState
@Suppress("MagicNumber")
@Composable
private fun <T> animationSpec(delay: Duration? = null): TweenSpec<T> {
val delayMs = delay?.inWholeMilliseconds?.toInt() ?: 0
return tween(
durationMillis = ANIMATION_DURATION_MS - delayMs,
easing = CubicBezierEasing(0.6f, 0.1f, 0.3f, 0.9f),
delayMillis = delayMs
)
}
private const val ANIMATION_DURATION_MS = 850
private const val ANIMATION_DURATION_BETWEEN_MESSAGES_MS = 1000
private const val TOP_CUTOUT_HEIGHT_DP = 32
private const val BOTTOM_CUTOUT_HEIGHT_DP = 24
private fun Modifier.bottomOnlyShadow(
elevation: Dp,
shape: Shape,

View File

@ -1,3 +0,0 @@
package co.electriccoin.zcash.ui.screen.home.messages
sealed interface HomeMessageState

View File

@ -1,38 +1,125 @@
package co.electriccoin.zcash.ui.screen.home.messages
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Surface
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.LocalTextStyle
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import co.electriccoin.zcash.ui.design.component.HorizontalSpacer
import co.electriccoin.zcash.ui.design.component.LocalZashiButtonColors
import co.electriccoin.zcash.ui.design.component.LocalZashiCircularProgressIndicatorColors
import co.electriccoin.zcash.ui.design.component.VerticalSpacer
import co.electriccoin.zcash.ui.design.component.ZashiButtonDefaults
import co.electriccoin.zcash.ui.design.component.ZashiCircularProgressIndicatorDefaults
import co.electriccoin.zcash.ui.design.theme.colors.Purple
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
import co.electriccoin.zcash.ui.design.theme.colors.ZashiDarkColors
import co.electriccoin.zcash.ui.design.theme.colors.ZashiLightColors
import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
@Suppress("ModifierNaming", "ModifierWithoutDefault")
@Composable
fun HomeMessageWrapper(
color: Color,
innerModifier: Modifier,
contentPadding: PaddingValues,
content: @Composable RowScope.() -> Unit,
onClick: () -> Unit,
start: @Composable RowScope.() -> Unit,
title: @Composable () -> Unit,
subtitle: @Composable () -> Unit,
end: (@Composable () -> Unit)?,
) {
Surface(
color = color,
Container(
contentPadding = contentPadding,
onClick = onClick,
innerModifier = innerModifier,
) {
Box(
modifier = Modifier.padding(contentPadding)
CompositionLocalProvider(
LocalContentColor provides ZashiColors.Text.textOpposite,
LocalZashiCircularProgressIndicatorColors provides
ZashiCircularProgressIndicatorDefaults.colors(
progressColor = ZashiColors.Text.textOpposite,
trackColor = Purple.`400`
)
) {
Row(
modifier =
Modifier.padding(
horizontal = 16.dp,
vertical = 14.dp
start()
}
HorizontalSpacer(16.dp)
Column(
modifier = Modifier.weight(1f)
) {
CompositionLocalProvider(
LocalTextStyle provides
ZashiTypography.textSm.copy(
color = ZashiColors.Text.textOpposite,
fontWeight = FontWeight.Medium
),
verticalAlignment = Alignment.CenterVertically,
content = content
)
) {
title()
}
VerticalSpacer(2.dp)
CompositionLocalProvider(
LocalTextStyle provides
ZashiTypography.textXs.copy(
color = Purple.`200`,
fontWeight = FontWeight.Medium
),
) {
subtitle()
}
}
if (end != null) {
CompositionLocalProvider(
LocalZashiButtonColors provides
ZashiButtonDefaults.primaryColors(
if (isSystemInDarkTheme()) ZashiLightColors else ZashiDarkColors
)
) {
end()
}
}
}
}
@Suppress("ModifierNaming", "ModifierWithoutDefault")
@Composable
private fun Container(
innerModifier: Modifier,
contentPadding: PaddingValues,
onClick: () -> Unit,
content: @Composable (RowScope.() -> Unit),
) {
Box(
modifier =
Modifier
.background(
Brush.verticalGradient(
0f to Purple.`500`,
1f to Purple.`900`,
)
).clickable(onClick = onClick)
.padding(contentPadding),
) {
Row(
modifier =
innerModifier.padding(
horizontal = 16.dp,
vertical = 18.dp
),
verticalAlignment = Alignment.CenterVertically,
content = content
)
}
}

View File

@ -0,0 +1,93 @@
package co.electriccoin.zcash.ui.screen.home.messages
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.height
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import cash.z.ecc.android.sdk.model.Zatoshi
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.component.BlankSurface
import co.electriccoin.zcash.ui.design.component.ButtonState
import co.electriccoin.zcash.ui.design.component.ZashiButton
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.design.util.StringResource
import co.electriccoin.zcash.ui.design.util.getValue
import co.electriccoin.zcash.ui.design.util.stringRes
@Suppress("ModifierNaming")
@Composable
fun TransparentBalanceDetectedMessage(
contentPadding: PaddingValues,
state: TransparentBalanceDetectedMessageState,
innerModifier: Modifier = Modifier,
) {
HomeMessageWrapper(
innerModifier = innerModifier,
contentPadding = contentPadding,
onClick = state.onClick,
start = {
Image(
modifier = Modifier.align(Alignment.Top),
painter = painterResource(R.drawable.ic_message_transparent_balance),
contentDescription = null,
colorFilter = ColorFilter.tint(LocalContentColor.current)
)
},
title = {
Text(
stringResource(R.string.home_message_transparent_balance_title),
)
},
subtitle = {
Text(
text = state.subtitle.getValue(),
)
},
end = {
ZashiButton(
modifier = Modifier.height(36.dp),
state =
ButtonState(
onClick = state.onButtonClick,
text = stringRes(stringResource(R.string.home_message_transparent_balance_button))
)
)
}
)
}
class TransparentBalanceDetectedMessageState(
val subtitle: StringResource,
val onClick: () -> Unit,
val onButtonClick: () -> Unit,
) : HomeMessageState
@PreviewScreens
@Composable
private fun Preview() =
ZcashTheme {
BlankSurface {
TransparentBalanceDetectedMessage(
state =
TransparentBalanceDetectedMessageState(
subtitle =
stringRes(
R.string.home_message_transparent_balance_subtitle,
stringRes(Zatoshi(10000))
),
onClick = {},
onButtonClick = {}
),
contentPadding = PaddingValues()
)
}
}

View File

@ -1,74 +1,72 @@
package co.electriccoin.zcash.ui.screen.home.messages
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.height
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.component.BlankSurface
import co.electriccoin.zcash.ui.design.component.ButtonState
import co.electriccoin.zcash.ui.design.component.HorizontalSpacer
import co.electriccoin.zcash.ui.design.component.VerticalSpacer
import co.electriccoin.zcash.ui.design.component.ZashiButton
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
import co.electriccoin.zcash.ui.design.util.stringRes
@Suppress("ModifierNaming")
@Composable
fun WalletBackupMessage(
state: WalletBackupMessageState,
contentPadding: PaddingValues
contentPadding: PaddingValues,
innerModifier: Modifier = Modifier,
) {
HomeMessageWrapper(
color = ZashiColors.Utility.Espresso.utilityEspresso100,
innerModifier = innerModifier,
contentPadding = contentPadding,
) {
Image(
painter = painterResource(R.drawable.ic_warning_triangle),
contentDescription = null
)
HorizontalSpacer(16.dp)
Column(
modifier = Modifier.weight(1f)
) {
onClick = state.onClick,
start = {
Image(
modifier = Modifier.align(Alignment.Top),
painter = painterResource(R.drawable.ic_warning_triangle),
contentDescription = null,
colorFilter = ColorFilter.tint(LocalContentColor.current)
)
},
title = {
Text(
stringResource(R.string.home_message_backup_required_title),
style = ZashiTypography.textSm,
fontWeight = FontWeight.Medium,
color = ZashiColors.Utility.Espresso.utilityEspresso900
)
VerticalSpacer(2.dp)
},
subtitle = {
Text(
text = stringResource(R.string.home_message_backup_required_subtitle),
style = ZashiTypography.textXs,
fontWeight = FontWeight.Medium,
color = ZashiColors.Utility.Espresso.utilityEspresso700
)
},
end = {
ZashiButton(
modifier = Modifier.height(36.dp),
state =
ButtonState(
onClick = state.onButtonClick,
text = stringRes(R.string.home_message_backup_required_button)
)
)
}
ZashiButton(
modifier = Modifier.height(36.dp),
state =
ButtonState(
onClick = state.onClick,
text = stringRes("Start")
)
)
}
)
}
@Immutable
data class WalletBackupMessageState(
val onClick: () -> Unit,
val onButtonClick: () -> Unit,
) : HomeMessageState
@PreviewScreens
@ -79,7 +77,8 @@ private fun Preview() =
WalletBackupMessage(
state =
WalletBackupMessageState(
onClick = {}
onClick = {},
onButtonClick = {}
),
contentPadding = PaddingValues()
)

View File

@ -0,0 +1,69 @@
package co.electriccoin.zcash.ui.screen.home.messages
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.component.BlankSurface
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
@Suppress("ModifierNaming")
@Composable
fun WalletDisconnectedMessage(
contentPadding: PaddingValues,
state: WalletDisconnectedMessageState,
innerModifier: Modifier = Modifier,
) {
HomeMessageWrapper(
innerModifier = innerModifier,
contentPadding = contentPadding,
onClick = state.onClick,
start = {
Image(
modifier = Modifier.align(Alignment.Top),
painter = painterResource(R.drawable.ic_message_disconnected),
contentDescription = null,
colorFilter = ColorFilter.tint(LocalContentColor.current)
)
},
title = {
Text(
stringResource(R.string.home_message_wallet_disconnected_title),
)
},
subtitle = {
Text(
text = stringResource(R.string.home_message_wallet_disconnected_subtitle),
)
},
end = null
)
}
class WalletDisconnectedMessageState(
val onClick: () -> Unit
) : HomeMessageState
@PreviewScreens
@Composable
private fun Preview() =
ZcashTheme {
BlankSurface {
WalletDisconnectedMessage(
contentPadding = PaddingValues(16.dp),
state =
WalletDisconnectedMessageState(
onClick = {}
)
)
}
}

View File

@ -0,0 +1,69 @@
package co.electriccoin.zcash.ui.screen.home.messages
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.component.BlankSurface
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
@Suppress("ModifierNaming")
@Composable
fun WalletErrorMessage(
contentPadding: PaddingValues,
state: WalletErrorMessageState,
innerModifier: Modifier = Modifier,
) {
HomeMessageWrapper(
innerModifier = innerModifier,
contentPadding = contentPadding,
onClick = state.onClick,
start = {
Image(
modifier = Modifier.align(Alignment.Top),
painter = painterResource(R.drawable.ic_warning_triangle),
contentDescription = null,
colorFilter = ColorFilter.tint(LocalContentColor.current)
)
},
title = {
Text(
stringResource(R.string.home_message_error_title),
)
},
subtitle = {
Text(
text = stringResource(R.string.home_message_error_subtitle),
)
},
end = null
)
}
class WalletErrorMessageState(
val onClick: () -> Unit
) : HomeMessageState
@PreviewScreens
@Composable
private fun Preview() =
ZcashTheme {
BlankSurface {
WalletErrorMessage(
contentPadding = PaddingValues(16.dp),
state =
WalletErrorMessageState(
onClick = {}
)
)
}
}

View File

@ -0,0 +1,72 @@
package co.electriccoin.zcash.ui.screen.home.messages
import androidx.annotation.IntRange
import androidx.compose.animation.core.animateIntAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.component.BlankSurface
import co.electriccoin.zcash.ui.design.component.ZashiCircularProgressIndicator
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
@Suppress("ModifierNaming")
@Composable
fun WalletRestoringMessage(
contentPadding: PaddingValues,
state: WalletRestoringMessageState,
innerModifier: Modifier = Modifier,
) {
HomeMessageWrapper(
innerModifier = innerModifier,
contentPadding = contentPadding,
onClick = state.onClick,
start = {
ZashiCircularProgressIndicator(
modifier = Modifier.size(20.dp),
progressPercent = state.progress,
)
},
title = {
Text(
text = stringResource(R.string.home_message_restoring_title, state.progress),
)
},
subtitle = {
Text(
text = stringResource(R.string.home_message_restoring_subtitle),
)
},
end = null
)
}
class WalletRestoringMessageState(
@IntRange(from = 0, to = 100) val progress: Int,
val onClick: () -> Unit
) : HomeMessageState
@PreviewScreens
@Composable
private fun Preview() =
ZcashTheme {
val progress by animateIntAsState(50, label = "progress", animationSpec = tween(10000))
BlankSurface {
WalletRestoringMessage(
contentPadding = PaddingValues(16.dp),
state =
WalletRestoringMessageState(
progress = progress,
onClick = {}
)
)
}
}

View File

@ -0,0 +1,72 @@
package co.electriccoin.zcash.ui.screen.home.messages
import androidx.annotation.IntRange
import androidx.compose.animation.core.animateIntAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.component.BlankSurface
import co.electriccoin.zcash.ui.design.component.ZashiCircularProgressIndicator
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
@Suppress("ModifierNaming")
@Composable
fun WalletSyncingMessage(
contentPadding: PaddingValues,
state: WalletSyncingMessageState,
innerModifier: Modifier = Modifier,
) {
HomeMessageWrapper(
innerModifier = innerModifier,
contentPadding = contentPadding,
onClick = state.onClick,
start = {
ZashiCircularProgressIndicator(
modifier = Modifier.size(20.dp),
progressPercent = state.progress,
)
},
title = {
Text(
text = stringResource(R.string.home_message_syncing_title, state.progress),
)
},
subtitle = {
Text(
text = stringResource(R.string.home_message_syncing_subtitle),
)
},
end = null
)
}
class WalletSyncingMessageState(
@IntRange(from = 0, to = 100) val progress: Int,
val onClick: () -> Unit
) : HomeMessageState
@PreviewScreens
@Composable
private fun Preview() =
ZcashTheme {
val progress by animateIntAsState(50, label = "progress", animationSpec = tween(10000))
BlankSurface {
WalletSyncingMessage(
contentPadding = PaddingValues(16.dp),
state =
WalletSyncingMessageState(
progress = progress,
onClick = {}
)
)
}
}

View File

@ -0,0 +1,69 @@
package co.electriccoin.zcash.ui.screen.home.messages
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.component.BlankSurface
import co.electriccoin.zcash.ui.design.component.LottieProgress
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
@Suppress("ModifierNaming")
@Composable
fun WalletUpdatingMessage(
contentPadding: PaddingValues,
state: WalletUpdatingMessageState,
innerModifier: Modifier = Modifier,
) {
HomeMessageWrapper(
innerModifier = innerModifier,
contentPadding = contentPadding,
onClick = state.onClick,
start = {
LottieProgress(
modifier =
Modifier
.size(20.dp)
.align(Alignment.Top),
size = 20.dp,
loadingRes = co.electriccoin.zcash.ui.design.R.raw.lottie_loading_white
)
},
title = {
Text(
stringResource(R.string.home_message_wallet_updating_title),
)
},
subtitle = {
Text(
text = stringResource(R.string.home_message_wallet_updating_subtitle),
)
},
end = null
)
}
class WalletUpdatingMessageState(
val onClick: () -> Unit
) : HomeMessageState
@PreviewScreens
@Composable
private fun Preview() =
ZcashTheme {
BlankSurface {
WalletUpdatingMessage(
contentPadding = PaddingValues(16.dp),
state =
WalletUpdatingMessageState(
onClick = {}
)
)
}
}

View File

@ -1,12 +1,8 @@
package co.electriccoin.zcash.ui.screen.integrations
import android.view.WindowManager
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.window.DialogWindowProvider
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import kotlinx.serialization.Serializable
import org.koin.androidx.compose.koinViewModel
@ -15,20 +11,9 @@ import org.koin.core.parameter.parametersOf
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AndroidDialogIntegrations() {
val parent = LocalView.current.parent
val viewModel = koinViewModel<IntegrationsViewModel> { parametersOf(true) }
val state by viewModel.state.collectAsStateWithLifecycle()
SideEffect {
(parent as? DialogWindowProvider)?.window?.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
(parent as? DialogWindowProvider)?.window?.setDimAmount(0f)
}
state?.let {
IntegrationsDialogView(
state = it,
)
}
IntegrationsDialogView(state)
}
@Serializable

View File

@ -5,12 +5,9 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.windowInsetsBottomHeight
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.SheetState
import androidx.compose.material3.SheetValue
@ -39,14 +36,14 @@ import kotlinx.collections.immutable.persistentListOf
@Composable
@OptIn(ExperimentalMaterial3Api::class)
internal fun IntegrationsDialogView(
state: IntegrationsState,
state: IntegrationsState?,
sheetState: SheetState = rememberScreenModalBottomSheetState(),
) {
ZashiScreenModalBottomSheet(
state = state,
sheetState = sheetState,
content = {
BottomSheetContent(state)
BottomSheetContent(it)
},
)
}
@ -73,7 +70,7 @@ fun BottomSheetContent(state: IntegrationsState) {
) {
Image(
modifier = Modifier,
painter = painterResource(R.drawable.ic_info),
painter = painterResource(co.electriccoin.zcash.ui.design.R.drawable.ic_info),
contentDescription = null,
colorFilter = ColorFilter.tint(ZashiColors.Text.textTertiary)
)
@ -86,10 +83,6 @@ fun BottomSheetContent(state: IntegrationsState) {
color = ZashiColors.Text.textTertiary
)
}
Spacer(modifier = Modifier.height(16.dp))
Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.systemBars))
}
}

View File

@ -97,7 +97,7 @@ private fun Content(
horizontalArrangement = Arrangement.Center
) {
Image(
painterResource(R.drawable.ic_info),
painterResource(co.electriccoin.zcash.ui.design.R.drawable.ic_info),
contentDescription = "",
colorFilter = ColorFilter.tint(color = ZashiColors.Utility.Indigo.utilityIndigo700)
)

View File

@ -20,7 +20,11 @@ class RestoreBDDateViewModel(
private fun createState() =
RestoreBDDateState(
next = ButtonState(stringRes(R.string.restore_bd_height_btn), onClick = ::onEstimateClick),
dialogButton = IconButtonState(icon = R.drawable.ic_info, onClick = ::onInfoButtonClick),
dialogButton =
IconButtonState(
icon = co.electriccoin.zcash.ui.design.R.drawable.ic_info,
onClick = ::onInfoButtonClick,
),
onBack = ::onBack,
)

View File

@ -25,6 +25,7 @@ import co.electriccoin.zcash.ui.common.appbar.ZashiTopAppBarTags
import co.electriccoin.zcash.ui.design.component.BlankBgScaffold
import co.electriccoin.zcash.ui.design.component.ButtonState
import co.electriccoin.zcash.ui.design.component.IconButtonState
import co.electriccoin.zcash.ui.design.component.Spacer
import co.electriccoin.zcash.ui.design.component.VerticalSpacer
import co.electriccoin.zcash.ui.design.component.ZashiButton
import co.electriccoin.zcash.ui.design.component.ZashiButtonDefaults
@ -94,7 +95,7 @@ private fun Content(
colors = ZashiButtonDefaults.tertiaryColors()
)
VerticalSpacer(24.dp)
VerticalSpacer(1f)
Spacer(1f)
ZashiButton(
state = state.restore,
modifier = Modifier.fillMaxWidth(),

View File

@ -18,7 +18,11 @@ class RestoreBDEstimationViewModel(
private fun createState() =
RestoreBDEstimationState(
dialogButton = IconButtonState(icon = R.drawable.ic_info, onClick = ::onInfoButtonClick),
dialogButton =
IconButtonState(
icon = co.electriccoin.zcash.ui.design.R.drawable.ic_info,
onClick = ::onInfoButtonClick,
),
onBack = ::onBack,
text = stringRes("123456"),
copy = ButtonState(stringRes(R.string.restore_bd_estimation_copy), icon = R.drawable.ic_copy) {},

View File

@ -52,7 +52,11 @@ class RestoreBDHeightViewModel(
return RestoreBDHeightState(
onBack = ::onBack,
dialogButton = IconButtonState(icon = R.drawable.ic_info, onClick = ::onInfoButtonClick),
dialogButton =
IconButtonState(
icon = co.electriccoin.zcash.ui.design.R.drawable.ic_info,
onClick = ::onInfoButtonClick,
),
restore =
ButtonState(
stringRes(R.string.restore_bd_restore_btn),

View File

@ -1,12 +1,8 @@
package co.electriccoin.zcash.ui.screen.restore.info
import android.view.WindowManager
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.window.DialogWindowProvider
import co.electriccoin.zcash.ui.NavigationRouter
import kotlinx.serialization.Serializable
import org.koin.compose.koinInject
@ -14,14 +10,7 @@ import org.koin.compose.koinInject
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AndroidSeedInfo() {
val parent = LocalView.current.parent
val navigationRouter = koinInject<NavigationRouter>()
SideEffect {
(parent as? DialogWindowProvider)?.window?.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
(parent as? DialogWindowProvider)?.window?.setDimAmount(0f)
}
SeedInfoView(
state = remember { SeedInfoState(onBack = { navigationRouter.back() }) },
)

View File

@ -4,13 +4,10 @@ import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.windowInsetsBottomHeight
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.SheetState
import androidx.compose.material3.SheetValue
@ -38,14 +35,14 @@ import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
@Composable
@OptIn(ExperimentalMaterial3Api::class)
internal fun SeedInfoView(
state: SeedInfoState,
state: SeedInfoState?,
sheetState: SheetState = rememberScreenModalBottomSheetState(),
) {
ZashiScreenModalBottomSheet(
state = state,
sheetState = sheetState,
content = {
Content(state)
Content(it)
},
)
}
@ -92,9 +89,6 @@ private fun Content(state: SeedInfoState) {
text = stringResource(R.string.restore_dialog_button),
onClick = state.onBack
)
Spacer(modifier = Modifier.height(24.dp))
Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.systemBars))
}
}
@ -102,7 +96,7 @@ private fun Content(state: SeedInfoState) {
private fun Info(text: AnnotatedString) {
Row {
Image(
painterResource(R.drawable.ic_info),
painterResource(co.electriccoin.zcash.ui.design.R.drawable.ic_info),
contentDescription = ""
)
Spacer(Modifier.width(8.dp))

View File

@ -128,7 +128,11 @@ class RestoreSeedViewModel(
}
),
onBack = ::onBack,
dialogButton = IconButtonState(icon = R.drawable.ic_info, onClick = ::onInfoButtonClick),
dialogButton =
IconButtonState(
icon = co.electriccoin.zcash.ui.design.R.drawable.ic_info,
onClick = ::onInfoButtonClick
),
nextButton =
ButtonState(
text = stringRes(R.string.restore_button),

View File

@ -43,6 +43,7 @@ import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
import co.electriccoin.zcash.ui.design.component.ButtonState
import co.electriccoin.zcash.ui.design.component.IconButtonState
import co.electriccoin.zcash.ui.design.component.SeedTextState
import co.electriccoin.zcash.ui.design.component.Spacer
import co.electriccoin.zcash.ui.design.component.VerticalSpacer
import co.electriccoin.zcash.ui.design.component.ZashiButton
import co.electriccoin.zcash.ui.design.component.ZashiIconButton
@ -145,7 +146,7 @@ private fun SeedRecoveryMainContent(
BDSecret(modifier = Modifier.fillMaxWidth(), state = state.birthday)
VerticalSpacer(1f)
Spacer(1f)
ZashiButton(
state = state.button,
@ -301,7 +302,7 @@ private fun RevealedPreview() =
info =
IconButtonState(
onClick = {},
icon = R.drawable.ic_info
icon = co.electriccoin.zcash.ui.design.R.drawable.ic_info
),
onBack = {}
)
@ -337,7 +338,7 @@ private fun HiddenPreview() =
info =
IconButtonState(
onClick = {},
icon = R.drawable.ic_info
icon = co.electriccoin.zcash.ui.design.R.drawable.ic_info
),
onBack = {}
)

View File

@ -8,20 +8,27 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import co.electriccoin.zcash.di.koinActivityViewModel
import co.electriccoin.zcash.ui.NavigationRouter
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.screen.home.SeedBackupInfo
import co.electriccoin.zcash.ui.screen.restore.info.SeedInfo
import co.electriccoin.zcash.ui.screen.seed.SeedRecovery
import kotlinx.serialization.Serializable
import org.koin.compose.koinInject
@Composable
fun AndroidSeedBackup() {
fun AndroidSeedBackup(args: SeedBackup) {
val viewModel = koinActivityViewModel<WalletViewModel>()
val appBarState by viewModel.walletStateInformation.collectAsStateWithLifecycle()
val navigationRouter = koinInject<NavigationRouter>()
val state =
remember {
SeedBackupState(
onBack = { navigationRouter.back() },
onBack = {
if (args.isOpenedFromSeedBackupInfo) {
navigationRouter.replace(SeedBackupInfo)
} else {
navigationRouter.back()
}
},
onNextClick = { navigationRouter.replace(SeedRecovery) },
onInfoClick = { navigationRouter.forward(SeedInfo) }
)
@ -38,4 +45,6 @@ fun AndroidSeedBackup() {
}
@Serializable
object SeedBackup
data class SeedBackup(
val isOpenedFromSeedBackupInfo: Boolean
)

View File

@ -24,6 +24,7 @@ import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
import co.electriccoin.zcash.ui.design.component.ButtonState
import co.electriccoin.zcash.ui.design.component.HorizontalSpacer
import co.electriccoin.zcash.ui.design.component.IconButtonState
import co.electriccoin.zcash.ui.design.component.Spacer
import co.electriccoin.zcash.ui.design.component.VerticalSpacer
import co.electriccoin.zcash.ui.design.component.ZashiButton
import co.electriccoin.zcash.ui.design.component.ZashiIconButton
@ -136,12 +137,12 @@ private fun Content(
VerticalSpacer(20.dp)
VerticalSpacer(1f)
Spacer(1f)
Row {
HorizontalSpacer(20.dp)
Image(
painter = painterResource(R.drawable.ic_info),
painter = painterResource(co.electriccoin.zcash.ui.design.R.drawable.ic_info),
contentDescription = null,
colorFilter = ColorFilter.tint(ZashiColors.Utility.WarningYellow.utilityOrange700)
)

View File

@ -1,12 +1,8 @@
package co.electriccoin.zcash.ui.screen.transactionfilters
import android.view.WindowManager
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.window.DialogWindowProvider
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import co.electriccoin.zcash.ui.screen.transactionfilters.view.TransactionFiltersView
import co.electriccoin.zcash.ui.screen.transactionfilters.viewmodel.TransactionFiltersViewModel
@ -17,13 +13,6 @@ import org.koin.androidx.compose.koinViewModel
fun AndroidTransactionFiltersList() {
val viewModel = koinViewModel<TransactionFiltersViewModel>()
val state by viewModel.state.collectAsStateWithLifecycle()
val parent = LocalView.current.parent
SideEffect {
(parent as? DialogWindowProvider)?.window?.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
(parent as? DialogWindowProvider)?.window?.setDimAmount(0f)
}
TransactionFiltersView(
state = state,
)

View File

@ -10,12 +10,9 @@ import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.windowInsetsBottomHeight
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.verticalScroll
@ -153,11 +150,7 @@ private fun BottomSheetContent(state: TransactionFiltersState?) {
colors = ZashiButtonDefaults.primaryColors()
)
}
Spacer(modifier = Modifier.height(24.dp))
}
Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.systemBars))
}
}

View File

@ -1,12 +1,8 @@
package co.electriccoin.zcash.ui.screen.transactionnote
import android.view.WindowManager
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.window.DialogWindowProvider
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import co.electriccoin.zcash.ui.screen.transactionnote.view.TransactionNoteView
import co.electriccoin.zcash.ui.screen.transactionnote.viewmodel.TransactionNoteViewModel
@ -18,12 +14,5 @@ import org.koin.core.parameter.parametersOf
fun AndroidTransactionNote(transactionNote: TransactionNote) {
val viewModel = koinViewModel<TransactionNoteViewModel> { parametersOf(transactionNote) }
val state by viewModel.state.collectAsStateWithLifecycle()
val parent = LocalView.current.parent
SideEffect {
(parent as? DialogWindowProvider)?.window?.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
(parent as? DialogWindowProvider)?.window?.setDimAmount(0f)
}
TransactionNoteView(state = state)
}

View File

@ -4,12 +4,9 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.windowInsetsBottomHeight
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.SheetState
import androidx.compose.material3.SheetValue
@ -39,14 +36,14 @@ import co.electriccoin.zcash.ui.screen.transactionnote.model.TransactionNoteStat
@Composable
@OptIn(ExperimentalMaterial3Api::class)
internal fun TransactionNoteView(
state: TransactionNoteState,
state: TransactionNoteState?,
sheetState: SheetState = rememberScreenModalBottomSheetState(),
) {
ZashiScreenModalBottomSheet(
state = state,
sheetState = sheetState,
content = {
BottomSheetContent(state)
BottomSheetContent(it)
},
)
}
@ -121,10 +118,6 @@ private fun BottomSheetContent(state: TransactionNoteState) {
)
}
}
Spacer(modifier = Modifier.height(24.dp))
Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.systemBars))
}
}

View File

@ -26,4 +26,7 @@
<string name="server_disconnected_dialog_ignore_btn">Ignorar</string>
<string name="general_etc"></string>
<string name="general_ok">OK</string>
<string name="general_remind_me_later">Remind me later</string>
</resources>

View File

@ -27,4 +27,7 @@
<string name="server_disconnected_dialog_ignore_btn">Ignore</string>
<string name="general_etc"></string>
<string name="general_ok">OK</string>
<string name="general_remind_me_later">Remind me later</string>
</resources>

View File

@ -13,7 +13,7 @@
<string name="exchange_rate_opt_in_enable">Habilitar</string>
<string name="exchange_rate_opt_in_save">Guardar cambios</string>
<string name="exchange_rate_opt_in_skip">Omitir por ahora</string>
<string name="exchange_rate_opt_in_skip">Skip</string>
<string name="exchange_rate_opt_in_note">Nota para los más conscientes de la privacidad: Debido a que obtenemos la tasa de conversión de los intercambios, un intercambio podría ver que la tasa de cambio fue consultada antes de que ocurriera una transacción.</string>
<string name="exchange_rate_opt_in_option_title">Habilitar</string>

View File

@ -15,7 +15,7 @@
<string name="exchange_rate_opt_in_enable">Enable</string>
<string name="exchange_rate_opt_in_save">Save changes</string>
<string name="exchange_rate_opt_in_skip">Skip for now</string>
<string name="exchange_rate_opt_in_skip">Skip</string>
<string name="exchange_rate_opt_in_note">Note for the super privacy-conscious: Because we pull the conversion rate
from exchanges, an exchange might be able to see that the exchange rate was queried before a transaction occurred.</string>

View File

@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:pathData="M0,20C0,8.954 8.954,0 20,0C31.046,0 40,8.954 40,20C40,31.046 31.046,40 20,40C8.954,40 0,31.046 0,20Z"
android:fillColor="#454243"/>
<path
android:pathData="M20,17.5V20.833M20,24.167H20.008M18.846,13.243L11.992,25.082C11.611,25.739 11.421,26.067 11.45,26.337C11.474,26.572 11.597,26.785 11.788,26.924C12.007,27.083 12.387,27.083 13.146,27.083H26.854C27.612,27.083 27.992,27.083 28.211,26.924C28.402,26.785 28.525,26.572 28.55,26.337C28.578,26.067 28.388,25.739 28.008,25.082L21.153,13.243C20.775,12.589 20.585,12.262 20.338,12.152C20.123,12.056 19.877,12.056 19.661,12.152C19.414,12.262 19.225,12.589 18.846,13.243Z"
android:strokeLineJoin="round"
android:strokeWidth="1.66667"
android:fillColor="#00000000"
android:strokeColor="#E8E8E8"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:pathData="M0,20C0,8.954 8.954,0 20,0C31.046,0 40,8.954 40,20C40,31.046 31.046,40 20,40C8.954,40 0,31.046 0,20Z"
android:fillColor="#454243"/>
<path
android:pathData="M17.5,19.584L19.167,21.25L22.917,17.5M26.667,20C26.667,24.091 22.205,27.066 20.582,28.013C20.397,28.12 20.305,28.174 20.175,28.202C20.074,28.224 19.927,28.224 19.825,28.202C19.695,28.174 19.603,28.12 19.419,28.013C17.795,27.066 13.333,24.091 13.333,20V16.015C13.333,15.349 13.333,15.016 13.443,14.729C13.539,14.476 13.695,14.25 13.898,14.072C14.128,13.869 14.44,13.752 15.064,13.518L19.532,11.842C19.705,11.778 19.792,11.745 19.881,11.732C19.96,11.721 20.04,11.721 20.119,11.732C20.208,11.745 20.295,11.778 20.468,11.842L24.937,13.518C25.56,13.752 25.872,13.869 26.102,14.072C26.305,14.25 26.462,14.476 26.558,14.729C26.667,15.016 26.667,15.349 26.667,16.015V20Z"
android:strokeLineJoin="round"
android:strokeWidth="1.66667"
android:fillColor="#00000000"
android:strokeColor="#EBE9E9"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:pathData="M0,20C0,8.954 8.954,0 20,0C31.046,0 40,8.954 40,20C40,31.046 31.046,40 20,40C8.954,40 0,31.046 0,20Z"
android:fillColor="#454243"/>
<path
android:pathData="M22.76,18.333C23.9,18.689 24.969,19.266 25.9,20.042M28.816,17.083C26.381,14.937 23.246,13.752 20,13.752C19.496,13.752 18.994,13.781 18.498,13.837M17.108,23.008C17.954,22.407 18.966,22.084 20.004,22.084C21.042,22.084 22.054,22.407 22.9,23.008M20,26.25H20.008M10.994,17.251C12.106,16.232 13.39,15.4 14.799,14.802M13.943,20.202C15.108,19.177 16.535,18.442 18.111,18.112M23.082,23.146C22.233,22.48 21.163,22.083 20,22.083C18.819,22.083 17.735,22.492 16.879,23.176M12.5,12.5L27.5,27.5"
android:strokeLineJoin="round"
android:strokeWidth="1.66667"
android:fillColor="#00000000"
android:strokeColor="#E8E8E8"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M5.872,2.131L7.625,1.474C7.764,1.422 7.833,1.396 7.905,1.386C7.968,1.377 8.032,1.377 8.095,1.386C8.167,1.396 8.236,1.422 8.375,1.474L11.949,2.814C12.448,3.002 12.698,3.095 12.882,3.257C13.044,3.4 13.169,3.581 13.246,3.783C13.333,4.012 13.333,4.279 13.333,4.812V8C13.333,8.48 13.257,8.941 13.121,9.381M11.748,11.751C10.624,13.058 9.192,13.986 8.466,14.41C8.318,14.496 8.244,14.539 8.14,14.562C8.059,14.579 7.941,14.579 7.86,14.562C7.756,14.539 7.682,14.496 7.535,14.41C6.236,13.653 2.667,11.273 2.667,8V3.851C2.667,3.54 2.86,3.261 3.151,3.152M2,2L14,14"
android:strokeLineJoin="round"
android:strokeWidth="1.33333"
android:fillColor="#00000000"
android:strokeColor="#E8E8E8"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:pathData="M0,20C0,8.954 8.954,0 20,0C31.046,0 40,8.954 40,20C40,31.046 31.046,40 20,40C8.954,40 0,31.046 0,20Z"
android:fillColor="#EBEBE6"/>
<path
android:pathData="M20,17.5V20.833M20,24.167H20.008M18.846,13.243L11.992,25.082C11.612,25.739 11.422,26.067 11.45,26.337C11.474,26.572 11.597,26.785 11.788,26.924C12.007,27.083 12.387,27.083 13.146,27.083H26.854C27.613,27.083 27.992,27.083 28.211,26.924C28.402,26.785 28.525,26.572 28.55,26.337C28.578,26.067 28.388,25.739 28.008,25.082L21.154,13.243C20.775,12.589 20.585,12.262 20.338,12.152C20.123,12.056 19.877,12.056 19.661,12.152C19.414,12.262 19.225,12.589 18.846,13.243Z"
android:strokeLineJoin="round"
android:strokeWidth="1.66667"
android:fillColor="#00000000"
android:strokeColor="#282622"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:pathData="M0,20C0,8.954 8.954,0 20,0C31.046,0 40,8.954 40,20C40,31.046 31.046,40 20,40C8.954,40 0,31.046 0,20Z"
android:fillColor="#EBEBE6"/>
<path
android:pathData="M17.5,19.584L19.167,21.25L22.917,17.5M26.667,20C26.667,24.091 22.205,27.066 20.582,28.013C20.397,28.12 20.305,28.174 20.175,28.202C20.074,28.224 19.926,28.224 19.825,28.202C19.695,28.174 19.603,28.12 19.418,28.013C17.795,27.066 13.333,24.091 13.333,20V16.015C13.333,15.349 13.333,15.016 13.442,14.729C13.539,14.476 13.695,14.25 13.898,14.072C14.128,13.869 14.44,13.752 15.064,13.518L19.532,11.842C19.705,11.778 19.792,11.745 19.881,11.732C19.96,11.721 20.04,11.721 20.119,11.732C20.208,11.745 20.295,11.778 20.468,11.842L24.936,13.518C25.56,13.752 25.872,13.869 26.102,14.072C26.305,14.25 26.462,14.476 26.558,14.729C26.667,15.016 26.667,15.349 26.667,16.015V20Z"
android:strokeLineJoin="round"
android:strokeWidth="1.66667"
android:fillColor="#00000000"
android:strokeColor="#332424"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:pathData="M0,20C0,8.954 8.954,0 20,0C31.046,0 40,8.954 40,20C40,31.046 31.046,40 20,40C8.954,40 0,31.046 0,20Z"
android:fillColor="#EBEBE6"/>
<path
android:pathData="M22.76,18.333C23.9,18.689 24.969,19.266 25.9,20.042M28.817,17.083C26.381,14.937 23.246,13.752 20,13.752C19.496,13.752 18.994,13.781 18.498,13.837M17.108,23.008C17.954,22.407 18.966,22.084 20.004,22.084C21.042,22.084 22.054,22.407 22.9,23.008M20,26.25H20.008M10.995,17.251C12.106,16.232 13.39,15.4 14.799,14.802M13.943,20.202C15.108,19.177 16.535,18.442 18.111,18.112M23.082,23.146C22.233,22.48 21.163,22.083 20,22.083C18.82,22.083 17.735,22.492 16.879,23.176M12.5,12.5L27.5,27.5"
android:strokeLineJoin="round"
android:strokeWidth="1.66667"
android:fillColor="#00000000"
android:strokeColor="#231F20"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,17 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<group>
<clip-path
android:pathData="M0,0h20v20h-20z"/>
<path
android:pathData="M5,5L6.667,3.334M6.667,3.334L5,1.667M6.667,3.334H5C3.159,3.334 1.667,4.826 1.667,6.667M15,15L13.333,16.667M13.333,16.667L15,18.334M13.333,16.667H15C16.841,16.667 18.333,15.175 18.333,13.334M8.491,5.417C9.046,3.26 11.004,1.667 13.333,1.667C16.095,1.667 18.333,3.906 18.333,6.667C18.333,8.997 16.74,10.954 14.583,11.509M11.667,13.334C11.667,16.095 9.428,18.334 6.667,18.334C3.905,18.334 1.667,16.095 1.667,13.334C1.667,10.572 3.905,8.334 6.667,8.334C9.428,8.334 11.667,10.572 11.667,13.334Z"
android:strokeLineJoin="round"
android:strokeWidth="1.66667"
android:fillColor="#00000000"
android:strokeColor="#332424"
android:strokeLineCap="round"/>
</group>
</vector>

View File

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:pathData="M12.76,8.333C13.9,8.689 14.969,9.266 15.9,10.042M18.817,7.083C16.381,4.937 13.246,3.752 10,3.752C9.496,3.752 8.994,3.781 8.498,3.837M7.108,13.008C7.954,12.407 8.966,12.084 10.004,12.084C11.042,12.084 12.054,12.407 12.9,13.008M10,16.25H10.008M0.994,7.251C2.106,6.232 3.39,5.4 4.799,4.803M3.943,10.203C5.108,9.177 6.535,8.442 8.111,8.112M13.082,13.146C12.233,12.48 11.163,12.083 10,12.083C8.82,12.083 7.735,12.492 6.879,13.176M2.5,2.5L17.5,17.5"
android:strokeLineJoin="round"
android:strokeWidth="1.66667"
android:fillColor="#00000000"
android:strokeColor="#231F20"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:pathData="M7.341,2.664L9.532,1.843C9.705,1.778 9.792,1.745 9.881,1.732C9.96,1.721 10.04,1.721 10.119,1.732C10.208,1.745 10.295,1.778 10.468,1.843L14.936,3.518C15.56,3.752 15.872,3.869 16.102,4.072C16.305,4.251 16.461,4.476 16.558,4.729C16.667,5.016 16.667,5.349 16.667,6.015V10C16.667,10.601 16.571,11.177 16.402,11.726M14.685,14.688C13.28,16.322 11.49,17.483 10.583,18.012C10.398,18.12 10.305,18.174 10.175,18.202C10.074,18.224 9.926,18.224 9.825,18.202C9.695,18.174 9.603,18.12 9.418,18.013C7.795,17.066 3.333,14.091 3.333,10V4.814C3.333,4.425 3.575,4.076 3.939,3.94M2.5,2.5L17.5,17.5"
android:strokeLineJoin="round"
android:strokeWidth="1.66667"
android:fillColor="#00000000"
android:strokeColor="#332424"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M5.872,2.131L7.625,1.474C7.764,1.422 7.833,1.396 7.905,1.386C7.968,1.377 8.032,1.377 8.095,1.386C8.167,1.396 8.236,1.422 8.375,1.474L11.949,2.814C12.448,3.002 12.698,3.095 12.882,3.257C13.044,3.4 13.169,3.581 13.246,3.783C13.333,4.012 13.333,4.279 13.333,4.812V8C13.333,8.48 13.257,8.941 13.121,9.381M11.748,11.751C10.624,13.058 9.192,13.986 8.466,14.41C8.318,14.496 8.244,14.539 8.14,14.562C8.059,14.579 7.941,14.579 7.86,14.562C7.756,14.539 7.682,14.496 7.535,14.41C6.236,13.653 2.667,11.273 2.667,8V3.851C2.667,3.54 2.86,3.261 3.151,3.152M2,2L14,14"
android:strokeLineJoin="round"
android:strokeWidth="1.33333"
android:fillColor="#00000000"
android:strokeColor="#231F20"
android:strokeLineCap="round"/>
</vector>

View File

@ -1,11 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="home_message_backup_required_title">Wallet Backup Required</string>
<string name="home_message_backup_required_subtitle">Prevent potential loss of funds</string>
<string name="home_button_receive">Receive</string>
<string name="home_button_send">Send</string>
<string name="home_button_scan">Scan</string>
<string name="home_button_request">Request</string>
<string name="home_button_buy">Buy</string>
<string name="home_button_more">More</string>
<string name="home_message_backup_required_title">Wallet Backup Required</string>
<string name="home_message_backup_required_subtitle">Prevent potential loss of funds</string>
<string name="home_message_backup_required_button">Start</string>
<string name="home_message_wallet_disconnected_title">Wallet Disconnected</string>
<string name="home_message_wallet_disconnected_subtitle">Check your connection and reload Zashi</string>
<string name="home_message_transparent_balance_subtitle">%s ZEC</string>
<string name="home_message_transparent_balance_title">Transparent Balance Detected</string>
<string name="home_message_transparent_balance_button">Shield</string>
<string name="home_message_currency_conversion_title">Currency Conversion</string>
<string name="home_message_currency_conversion_subtitle">Enable to display USD values</string>
<string name="home_message_currency_conversion_button">Start</string>
<string name="home_message_wallet_updating_title">Updating Balance…</string>
<string name="home_message_wallet_updating_subtitle">Waiting for last transaction to process</string>
<string name="home_message_restoring_title">Restoring Wallet • %d%% Complete</string>
<string name="home_message_restoring_subtitle">Keep Zashi open on active phone screen</string>
<string name="home_message_syncing_title">Syncing • %d%% Complete</string>
<string name="home_message_syncing_subtitle">Your wallet is getting updated</string>
<string name="home_message_error_title">Error encountered while syncing</string>
<string name="home_message_error_subtitle">Attempting to resolve</string>
<string name="home_info_backup_title">Backup Required</string>
<string name="home_info_backup_subtitle_1">Prevent potential loss of funds by securely backing up your wallet.</string>
<string name="home_info_backup_subtitle_2">Back up access to your funds by backing up:</string>
<string name="home_info_backup_bullet_1">Secret Recovery Phrase (a unique set of 24 words in a precise
order)</string>
<string name="home_info_backup_bullet_2">Wallet Birthday Height (block height at which your wallet was
created)</string>
<string name="home_info_backup_message_1">In case you lose access to the app or to your device, knowing the Secret
Recovery Phrase is the only way to recover your funds. We cannot see it and cannot help you recover it.</string>
<string name="home_info_backup_message_2">Anyone with access to your Secret Recovery Phrase will have full control
of your wallet, so keep it secure and never show it to anyone.</string>
<string name="home_info_transparent_balance_shield">Shield</string>
<string name="home_info_transparent_title">Always Shield Transparent Funds</string>
<string name="home_info_transparent_subtitle">To protect user privacy, Zashi doesn\'t support spending transparent
ZEC. Tap the \"Shield\" button below to make your transparent funds spendable and your total Zashi balance private. </string>
<string name="home_info_transparent_message">This will create a shielding in-wallet transaction, consolidating your
transparent and shielded funds. (Typical fee: .001 ZEC)</string>
<string name="home_info_transparent_subheader">Transparent</string>
<string name="home_info_disconnected_title">Wallet Disconnected</string>
<string name="home_info_disconnected_subtitle">You appear to be offline. Please restore your internet connection
to use Zashi wallet.</string>
<string name="home_info_restoring_title">Wallet Restore in Progress</string>
<string name="home_info_restoring_message">Zashi is scanning the blockchain to retrieve your transactions. Older
wallets can take hours to restore. Follow these steps to prevent interruption:</string>
<string name="home_info_restoring_bullet_1">Keep the Zashi app open on an active phone screen.</string>
<string name="home_info_restoring_bullet_2">To prevent your phone screen from going dark, turn off power-saving
mode and keep your phone plugged in.</string>
<string name="home_info_restoring_note">Funds cannot be spent until your wallet is restored.</string>
<string name="home_info_syncing_title">Wallet Sync in Progress</string>
<string name="home_info_syncing_message">Zashi is scanning the blockchain for your latest transactions to make sure
your balances are displayed correctly. Keep the Zashi app open on an active phone screen to avoid interruptions.</string>
<string name="home_info_updating_title">Updating Balance</string>
<string name="home_info_updating_message">Your last transaction is getting mined and confirmed.</string>
</resources>

View File

@ -1,11 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="home_message_backup_required_title">Wallet Backup Required</string>
<string name="home_message_backup_required_subtitle">Prevent potential loss of funds</string>
<string name="home_button_receive">Receive</string>
<string name="home_button_send">Send</string>
<string name="home_button_scan">Scan</string>
<string name="home_button_request">Request</string>
<string name="home_button_buy">Buy</string>
<string name="home_button_more">More</string>
<string name="home_message_backup_required_title">Wallet Backup Required</string>
<string name="home_message_backup_required_subtitle">Prevent potential loss of funds</string>
<string name="home_message_backup_required_button">Start</string>
<string name="home_message_wallet_disconnected_title">Wallet Disconnected</string>
<string name="home_message_wallet_disconnected_subtitle">Check your connection and reload Zashi</string>
<string name="home_message_transparent_balance_subtitle">%s ZEC</string>
<string name="home_message_transparent_balance_title">Transparent Balance Detected</string>
<string name="home_message_transparent_balance_button">Shield</string>
<string name="home_message_currency_conversion_title">Currency Conversion</string>
<string name="home_message_currency_conversion_subtitle">Enable to display USD values</string>
<string name="home_message_currency_conversion_button">Start</string>
<string name="home_message_wallet_updating_title">Updating Balance…</string>
<string name="home_message_wallet_updating_subtitle">Waiting for last transaction to process</string>
<string name="home_message_restoring_title">Restoring Wallet • %d%% Complete</string>
<string name="home_message_restoring_subtitle">Keep Zashi open on active phone screen</string>
<string name="home_message_syncing_title">Syncing • %d%% Complete</string>
<string name="home_message_syncing_subtitle">Your wallet is getting updated</string>
<string name="home_message_error_title">Error encountered while syncing</string>
<string name="home_message_error_subtitle">Attempting to resolve</string>
<string name="home_info_backup_title">Backup Required</string>
<string name="home_info_backup_subtitle_1">Prevent potential loss of funds by securely backing up your wallet.</string>
<string name="home_info_backup_subtitle_2">Back up access to your funds by backing up:</string>
<string name="home_info_backup_bullet_1">Secret Recovery Phrase (a unique set of 24 words in a precise
order)</string>
<string name="home_info_backup_bullet_2">Wallet Birthday Height (block height at which your wallet was
created)</string>
<string name="home_info_backup_message_1">In case you lose access to the app or to your device, knowing the Secret
Recovery Phrase is the only way to recover your funds. We cannot see it and cannot help you recover it.</string>
<string name="home_info_backup_message_2">Anyone with access to your Secret Recovery Phrase will have full control
of your wallet, so keep it secure and never show it to anyone.</string>
<string name="home_info_transparent_balance_shield">Shield</string>
<string name="home_info_transparent_title">Always Shield Transparent Funds</string>
<string name="home_info_transparent_subtitle">To protect user privacy, Zashi doesn\'t support spending transparent
ZEC. Tap the \"Shield\" button below to make your transparent funds spendable and your total Zashi balance private. </string>
<string name="home_info_transparent_message">This will create a shielding in-wallet transaction, consolidating your
transparent and shielded funds. (Typical fee: .001 ZEC)</string>
<string name="home_info_transparent_subheader">Transparent</string>
<string name="home_info_disconnected_title">Wallet Disconnected</string>
<string name="home_info_disconnected_subtitle">You appear to be offline. Please restore your internet connection
to use Zashi wallet.</string>
<string name="home_info_restoring_title">Wallet Restore in Progress</string>
<string name="home_info_restoring_message">Zashi is scanning the blockchain to retrieve your transactions. Older
wallets can take hours to restore. Follow these steps to prevent interruption:</string>
<string name="home_info_restoring_bullet_1">Keep the Zashi app open on an active phone screen.</string>
<string name="home_info_restoring_bullet_2">To prevent your phone screen from going dark, turn off power-saving
mode and keep your phone plugged in.</string>
<string name="home_info_restoring_note">Funds cannot be spent until your wallet is restored.</string>
<string name="home_info_syncing_title">Wallet Sync in Progress</string>
<string name="home_info_syncing_message">Zashi is scanning the blockchain for your latest transactions to make sure
your balances are displayed correctly. Keep the Zashi app open on an active phone screen to avoid interruptions.</string>
<string name="home_info_updating_title">Updating Balance</string>
<string name="home_info_updating_message">Your last transaction is getting mined and confirmed.</string>
</resources>