secant-android-wallet/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/onboarding/view/OnboardingView.kt

249 lines
8.4 KiB
Kotlin
Raw Normal View History

@file:Suppress("TooManyFunctions")
package co.electriccoin.zcash.ui.screen.onboarding.view
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
2021-12-09 12:18:18 -08:00
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
2022-02-21 06:33:40 -08:00
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.SmallTopAppBar
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import co.electriccoin.zcash.spackle.model.Progress
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
import co.electriccoin.zcash.ui.design.component.Body
import co.electriccoin.zcash.ui.design.component.GradientSurface
import co.electriccoin.zcash.ui.design.component.Header
import co.electriccoin.zcash.ui.design.component.NavigationButton
import co.electriccoin.zcash.ui.design.component.PinkProgress
import co.electriccoin.zcash.ui.design.component.PrimaryButton
import co.electriccoin.zcash.ui.design.component.SecondaryButton
import co.electriccoin.zcash.ui.design.component.TertiaryButton
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.screen.onboarding.model.OnboardingStage
import co.electriccoin.zcash.ui.screen.onboarding.state.OnboardingState
@Preview
@Composable
fun ComposablePreview() {
ZcashTheme(darkTheme = true) {
2021-12-09 12:18:18 -08:00
GradientSurface {
Onboarding(
OnboardingState(OnboardingStage.UnifiedAddresses),
onImportWallet = {},
onCreateWallet = {}
)
}
}
}
// Pending internal discussion on where the navigation should live.
// This toggles between the app bar or custom buttons below the app bar
private const val IS_NAVIGATION_IN_APP_BAR = false
/**
* @param onImportWallet Callback when the user decides to import an existing wallet.
* @param onCreateWallet Callback when the user decides to create a new wallet.
*/
@Composable
fun Onboarding(
onboardingState: OnboardingState,
onImportWallet: () -> Unit,
onCreateWallet: () -> Unit
) {
2021-12-09 12:18:18 -08:00
Column {
OnboardingTopAppBar(onboardingState)
OnboardingMainContent(onboardingState, onImportWallet = onImportWallet, onCreateWallet = onCreateWallet)
}
}
@Composable
private fun OnboardingTopAppBar(onboardingState: OnboardingState) {
val currentStage = onboardingState.current.collectAsState().value
2022-02-21 06:33:40 -08:00
SmallTopAppBar(
title = { Text(text = stringResource(id = R.string.app_name)) },
navigationIcon =
if (IS_NAVIGATION_IN_APP_BAR && currentStage.hasPrevious()) {
{
IconButton(onboardingState::goPrevious) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = stringResource(R.string.onboarding_back)
)
}
}
} else {
2022-02-21 06:33:40 -08:00
{ Unit }
},
actions = {
if (IS_NAVIGATION_IN_APP_BAR && currentStage.hasNext()) {
NavigationButton(onboardingState::goToEnd, stringResource(R.string.onboarding_skip))
}
}
)
}
/**
* @param onImportWallet Callback when the user decides to import an existing wallet.
* @param onCreateWallet Callback when the user decides to create a new wallet.
*/
@Composable
fun OnboardingMainContent(
onboardingState: OnboardingState,
onImportWallet: () -> Unit,
onCreateWallet: () -> Unit
) {
Column {
if (!IS_NAVIGATION_IN_APP_BAR) {
TopNavButtons(onboardingState)
}
2021-12-09 12:18:18 -08:00
val onboardingStage = onboardingState.current.collectAsState().value
2021-12-09 12:18:18 -08:00
when (onboardingStage) {
OnboardingStage.ShieldedByDefault -> ShieldedByDefault()
OnboardingStage.UnifiedAddresses -> UnifiedAddresses()
OnboardingStage.More -> More()
OnboardingStage.Wallet -> Wallet(
onCreateWallet = onCreateWallet,
onImportWallet = onImportWallet
)
}
2021-12-09 12:18:18 -08:00
BottomNav(onboardingStage.getProgress(), onboardingState::goNext)
}
}
@Composable
private fun TopNavButtons(onboardingState: OnboardingState) {
Row {
val currentStage = onboardingState.current.collectAsState().value
if (currentStage.hasPrevious()) {
NavigationButton(onboardingState::goPrevious, stringResource(R.string.onboarding_back))
}
Spacer(
Modifier
.fillMaxWidth()
.weight(MINIMAL_WEIGHT, true)
)
if (currentStage.hasNext()) {
NavigationButton(onboardingState::goToEnd, stringResource(R.string.onboarding_skip))
}
}
}
@Composable
private fun BottomNav(progress: Progress, onNext: () -> Unit) {
if (progress.current != progress.last) {
Column {
Spacer(
modifier = Modifier
.fillMaxHeight()
.weight(MINIMAL_WEIGHT, true)
)
2021-12-09 12:18:18 -08:00
SecondaryButton(onNext, stringResource(R.string.onboarding_next), Modifier.fillMaxWidth())
// Converts from index to human numbering
Body((progress.current.value + 1).toString())
PinkProgress(progress, Modifier.fillMaxWidth())
}
}
}
@Composable
private fun ShieldedByDefault() {
Column {
Content(
image = painterResource(id = R.drawable.onboarding_1_shielded),
imageContentDescription = stringResource(R.string.onboarding_1_image_content_description),
headline = stringResource(R.string.onboarding_1_header),
body = stringResource(R.string.onboarding_1_body)
)
}
}
@Composable
private fun UnifiedAddresses() {
Column {
Content(
image = painterResource(id = R.drawable.onboarding_2_unified),
imageContentDescription = stringResource(R.string.onboarding_2_image_content_description),
headline = stringResource(R.string.onboarding_2_header),
body = stringResource(R.string.onboarding_2_body)
)
}
}
@Composable
private fun More() {
Column {
Content(
image = painterResource(id = R.drawable.onboarding_3_more),
imageContentDescription = stringResource(R.string.onboarding_3_image_content_description),
headline = stringResource(R.string.onboarding_3_header),
body = stringResource(R.string.onboarding_3_body)
)
}
}
@Composable
private fun Wallet(onCreateWallet: () -> Unit, onImportWallet: () -> Unit) {
Column {
Header(stringResource(R.string.onboarding_4_header))
Body(stringResource(R.string.onboarding_4_body))
PrimaryButton(onCreateWallet, stringResource(R.string.onboarding_4_create_new_wallet), Modifier.fillMaxWidth())
TertiaryButton(
onImportWallet, stringResource(R.string.onboarding_4_import_existing_wallet),
Modifier.fillMaxWidth()
)
}
}
@Composable
private fun Content(
image: Painter,
imageContentDescription: String?,
headline: String,
body: String
) {
Column(Modifier.fillMaxWidth()) {
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) {
// TODO [#17]: This suppression and magic number will get replaced once we have real assets
@Suppress("MagicNumber")
Image(image, imageContentDescription, Modifier.fillMaxSize(0.50f))
}
Header(headline)
Body(body)
}
}
@Composable
fun Callout(imageVector: ImageVector, contentDescription: String) {
Box(modifier = Modifier.background(ZcashTheme.colors.callout)) {
Icon(imageVector, contentDescription, tint = ZcashTheme.colors.onCallout)
}
}