301 lines
9.9 KiB
Kotlin
301 lines
9.9 KiB
Kotlin
@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.Box
|
|
import androidx.compose.foundation.layout.Column
|
|
import androidx.compose.foundation.layout.PaddingValues
|
|
import androidx.compose.foundation.layout.fillMaxWidth
|
|
import androidx.compose.foundation.layout.padding
|
|
import androidx.compose.foundation.rememberScrollState
|
|
import androidx.compose.foundation.verticalScroll
|
|
import androidx.compose.material.icons.Icons
|
|
import androidx.compose.material.icons.filled.ArrowBack
|
|
import androidx.compose.material.icons.filled.MoreVert
|
|
import androidx.compose.material3.DropdownMenu
|
|
import androidx.compose.material3.DropdownMenuItem
|
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
import androidx.compose.material3.Icon
|
|
import androidx.compose.material3.IconButton
|
|
import androidx.compose.material3.MaterialTheme
|
|
import androidx.compose.material3.Scaffold
|
|
import androidx.compose.material3.Text
|
|
import androidx.compose.material3.TopAppBar
|
|
import androidx.compose.runtime.Composable
|
|
import androidx.compose.runtime.getValue
|
|
import androidx.compose.runtime.mutableStateOf
|
|
import androidx.compose.runtime.saveable.rememberSaveable
|
|
import androidx.compose.runtime.setValue
|
|
import androidx.compose.ui.Modifier
|
|
import androidx.compose.ui.draw.scale
|
|
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 androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|
import co.electriccoin.zcash.ui.R
|
|
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) {
|
|
GradientSurface {
|
|
LongOnboarding(
|
|
OnboardingState(OnboardingStage.Wallet),
|
|
isDebugMenuEnabled = false,
|
|
onImportWallet = {},
|
|
onCreateWallet = {},
|
|
onFixtureWallet = {}
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @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
|
|
@OptIn(ExperimentalMaterial3Api::class)
|
|
@Suppress("LongParameterList")
|
|
fun LongOnboarding(
|
|
onboardingState: OnboardingState,
|
|
isDebugMenuEnabled: Boolean,
|
|
onImportWallet: () -> Unit,
|
|
onCreateWallet: () -> Unit,
|
|
onFixtureWallet: () -> Unit
|
|
) {
|
|
val currentStage = onboardingState.current.collectAsStateWithLifecycle().value
|
|
Scaffold(
|
|
topBar = {
|
|
OnboardingTopAppBar(onboardingState, isDebugMenuEnabled, onFixtureWallet)
|
|
},
|
|
bottomBar = {
|
|
BottomNav(currentStage, onboardingState::goNext, onCreateWallet, onImportWallet)
|
|
}
|
|
) { paddingValues ->
|
|
OnboardingMainContent(
|
|
paddingValues,
|
|
onboardingState
|
|
)
|
|
}
|
|
}
|
|
|
|
@Composable
|
|
@OptIn(ExperimentalMaterial3Api::class)
|
|
private fun OnboardingTopAppBar(
|
|
onboardingState: OnboardingState,
|
|
isDebugMenuEnabled: Boolean,
|
|
onFixtureWallet: () -> Unit
|
|
) {
|
|
val currentStage = onboardingState.current.collectAsStateWithLifecycle().value
|
|
|
|
TopAppBar(
|
|
title = { Text(text = stringResource(id = R.string.app_name)) },
|
|
navigationIcon = {
|
|
if (currentStage.hasPrevious()) {
|
|
IconButton(onboardingState::goPrevious) {
|
|
Icon(
|
|
imageVector = Icons.Filled.ArrowBack,
|
|
contentDescription = stringResource(R.string.onboarding_back)
|
|
)
|
|
}
|
|
}
|
|
},
|
|
actions = {
|
|
if (currentStage.hasNext()) {
|
|
NavigationButton(onboardingState::goToEnd, stringResource(R.string.onboarding_skip))
|
|
}
|
|
|
|
if (isDebugMenuEnabled) {
|
|
DebugMenu(onFixtureWallet)
|
|
}
|
|
}
|
|
)
|
|
}
|
|
|
|
@Composable
|
|
private fun DebugMenu(onFixtureWallet: () -> Unit) {
|
|
Column {
|
|
var expanded by rememberSaveable { mutableStateOf(false) }
|
|
IconButton(onClick = { expanded = true }) {
|
|
Icon(Icons.Default.MoreVert, contentDescription = null)
|
|
}
|
|
|
|
DropdownMenu(
|
|
expanded = expanded,
|
|
onDismissRequest = { expanded = false }
|
|
) {
|
|
DropdownMenuItem(
|
|
text = { Text("Import wallet with fixture seed phrase") },
|
|
onClick = onFixtureWallet
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
@Composable
|
|
fun OnboardingMainContent(
|
|
paddingValues: PaddingValues,
|
|
onboardingState: OnboardingState
|
|
) {
|
|
Column(
|
|
Modifier.padding(top = paddingValues.calculateTopPadding())
|
|
) {
|
|
val onboardingStage = onboardingState.current.collectAsStateWithLifecycle().value
|
|
|
|
when (onboardingStage) {
|
|
OnboardingStage.ShieldedByDefault -> ShieldedByDefault(paddingValues)
|
|
OnboardingStage.UnifiedAddresses -> UnifiedAddresses(paddingValues)
|
|
OnboardingStage.More -> More(paddingValues)
|
|
OnboardingStage.Wallet -> Wallet(paddingValues)
|
|
}
|
|
}
|
|
}
|
|
|
|
@Composable
|
|
private fun BottomNav(
|
|
currentStage: OnboardingStage,
|
|
onNext: () -> Unit,
|
|
onCreateWallet: () -> Unit,
|
|
onImportWallet: () -> Unit
|
|
) {
|
|
Column(Modifier.background(MaterialTheme.colorScheme.surface)) {
|
|
if (currentStage == OnboardingStage.Wallet) {
|
|
WalletStageBottomNav(onCreateWallet = onCreateWallet, onImportWallet)
|
|
} else {
|
|
OnboardingBottomNav(currentStage = currentStage, onNext = onNext)
|
|
}
|
|
}
|
|
}
|
|
|
|
@Composable
|
|
private fun WalletStageBottomNav(
|
|
onCreateWallet: () -> Unit,
|
|
onImportWallet: () -> Unit
|
|
) {
|
|
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 OnboardingBottomNav(
|
|
currentStage: OnboardingStage,
|
|
onNext: () -> Unit
|
|
) {
|
|
SecondaryButton(onNext, stringResource(R.string.onboarding_next), Modifier.fillMaxWidth())
|
|
// Converts from index to human numbering
|
|
Body((currentStage.getProgress().current.value + 1).toString())
|
|
PinkProgress(currentStage.getProgress(), Modifier.fillMaxWidth())
|
|
}
|
|
|
|
@Composable
|
|
private fun ShieldedByDefault(paddingValues: PaddingValues) {
|
|
Content(
|
|
paddingValues = paddingValues,
|
|
image = painterResource(id = R.drawable.onboarding_1),
|
|
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(paddingValues: PaddingValues) {
|
|
Content(
|
|
paddingValues = paddingValues,
|
|
image = painterResource(id = R.drawable.onboarding_2),
|
|
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(paddingValues: PaddingValues) {
|
|
Content(
|
|
paddingValues = paddingValues,
|
|
image = painterResource(id = R.drawable.onboarding_3),
|
|
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(paddingValues: PaddingValues) {
|
|
Column(
|
|
Modifier
|
|
.padding(
|
|
start = ZcashTheme.paddings.padding,
|
|
end = ZcashTheme.paddings.padding,
|
|
bottom = paddingValues.calculateBottomPadding()
|
|
)
|
|
.fillMaxWidth()
|
|
) {
|
|
Header(
|
|
modifier = Modifier.padding(
|
|
top = ZcashTheme.paddings.padding,
|
|
bottom = ZcashTheme.paddings.paddingHalf
|
|
),
|
|
text = stringResource(R.string.onboarding_4_header)
|
|
)
|
|
Body(stringResource(R.string.onboarding_4_body))
|
|
}
|
|
}
|
|
|
|
@Suppress("LongParameterList")
|
|
@Composable
|
|
private fun Content(
|
|
image: Painter,
|
|
imageContentDescription: String?,
|
|
headline: String,
|
|
body: String,
|
|
paddingValues: PaddingValues,
|
|
imageScale: Float = 0.8f
|
|
) {
|
|
val scrollState = rememberScrollState()
|
|
Column(
|
|
Modifier
|
|
.fillMaxWidth()
|
|
.verticalScroll(scrollState)
|
|
) {
|
|
Column(
|
|
Modifier.padding(
|
|
start = ZcashTheme.paddings.padding,
|
|
end = ZcashTheme.paddings.padding,
|
|
bottom = paddingValues.calculateBottomPadding()
|
|
)
|
|
) {
|
|
Image(modifier = Modifier.scale(imageScale), painter = image, contentDescription = imageContentDescription)
|
|
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)
|
|
}
|
|
}
|