Restoration connected to sdk
This commit is contained in:
parent
a07d7fcc8e
commit
aa72d1f92f
|
@ -211,7 +211,7 @@ ZIP_321_VERSION = 0.0.6
|
||||||
# WARNING: Ensure a non-snapshot version is used before releasing to production
|
# WARNING: Ensure a non-snapshot version is used before releasing to production
|
||||||
ZCASH_BIP39_VERSION=1.0.9
|
ZCASH_BIP39_VERSION=1.0.9
|
||||||
# WARNING: Ensure a non-snapshot version is used before releasing to production
|
# WARNING: Ensure a non-snapshot version is used before releasing to production
|
||||||
ZCASH_SDK_VERSION=2.2.11
|
ZCASH_SDK_VERSION=2.2.11-SNAPSHOT
|
||||||
|
|
||||||
# Toolchain is the Java version used to build the application, which is separate from the
|
# Toolchain is the Java version used to build the application, which is separate from the
|
||||||
# Java version used to run the application.
|
# Java version used to run the application.
|
||||||
|
|
|
@ -13,6 +13,7 @@ import androidx.compose.foundation.lazy.LazyListState
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
@ -39,40 +40,34 @@ import java.text.DateFormatSymbols
|
||||||
import java.time.Month
|
import java.time.Month
|
||||||
import java.time.Year
|
import java.time.Year
|
||||||
import java.time.YearMonth
|
import java.time.YearMonth
|
||||||
|
import kotlin.math.absoluteValue
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
|
|
||||||
@Suppress("MagicNumber")
|
@Suppress("MagicNumber")
|
||||||
@Composable
|
@Composable
|
||||||
fun ZashiYearMonthWheelDatePicker(
|
fun ZashiYearMonthWheelDatePicker(
|
||||||
|
selection: YearMonth,
|
||||||
onSelectionChange: (YearMonth) -> Unit,
|
onSelectionChange: (YearMonth) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
verticallyVisibleItems: Int = 3,
|
verticallyVisibleItems: Int = 3,
|
||||||
startYear: Year = Year.of(2016),
|
startInclusive: YearMonth = YearMonth.of(2018, 10),
|
||||||
endYear: Year = Year.now(),
|
endInclusive: YearMonth = YearMonth.now(),
|
||||||
selectionYear: YearMonth = YearMonth.now(),
|
|
||||||
) {
|
) {
|
||||||
val latestOnSelectionChanged by rememberUpdatedState(onSelectionChange)
|
val latestOnSelectionChanged by rememberUpdatedState(onSelectionChange)
|
||||||
var selectedDate by remember { mutableStateOf(selectionYear) }
|
|
||||||
val months =
|
|
||||||
listOf(
|
|
||||||
Month.JANUARY,
|
|
||||||
Month.FEBRUARY,
|
|
||||||
Month.MARCH,
|
|
||||||
Month.APRIL,
|
|
||||||
Month.MAY,
|
|
||||||
Month.JUNE,
|
|
||||||
Month.JULY,
|
|
||||||
Month.AUGUST,
|
|
||||||
Month.SEPTEMBER,
|
|
||||||
Month.OCTOBER,
|
|
||||||
Month.NOVEMBER,
|
|
||||||
Month.DECEMBER
|
|
||||||
)
|
|
||||||
val years = (startYear.value..endYear.value).toList()
|
|
||||||
|
|
||||||
LaunchedEffect(selectedDate) {
|
var state by remember {
|
||||||
Twig.debug { "Selection changed: $selectedDate" }
|
mutableStateOf(
|
||||||
latestOnSelectionChanged(selectedDate)
|
InternalState(
|
||||||
|
selectedDate = selection,
|
||||||
|
months = getMonthsForYear(Year.of(selection.year), startInclusive, endInclusive),
|
||||||
|
years = (startInclusive.year..endInclusive.year).map { Year.of(it) }.toList()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(state.selectedDate) {
|
||||||
|
Twig.debug { "Selection changed: ${state.selectedDate}" }
|
||||||
|
latestOnSelectionChanged(state.selectedDate)
|
||||||
}
|
}
|
||||||
|
|
||||||
Box(modifier = modifier) {
|
Box(modifier = modifier) {
|
||||||
|
@ -92,14 +87,18 @@ fun ZashiYearMonthWheelDatePicker(
|
||||||
Spacer(Modifier.weight(.5f))
|
Spacer(Modifier.weight(.5f))
|
||||||
WheelLazyList(
|
WheelLazyList(
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
selection = maxOf(months.indexOf(selectedDate.month), 0),
|
selection = state.selectedMonthIndex,
|
||||||
itemCount = months.size,
|
itemCount = state.months.size,
|
||||||
itemVerticalOffset = verticallyVisibleItems,
|
itemVerticalOffset = verticallyVisibleItems,
|
||||||
isInfiniteScroll = true,
|
isInfiniteScroll = false,
|
||||||
onFocusItem = { selectedDate = selectedDate.withMonth(months[it].value) },
|
onFocusItem = {
|
||||||
|
state = state.copy(
|
||||||
|
selectedDate = state.selectedDate.withMonth(state.months[it].value)
|
||||||
|
)
|
||||||
|
},
|
||||||
itemContent = {
|
itemContent = {
|
||||||
Text(
|
Text(
|
||||||
text = DateFormatSymbols().months[months[it].value - 1],
|
text = DateFormatSymbols().months[state.months[it].value - 1],
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
modifier = Modifier.fillParentMaxWidth(),
|
modifier = Modifier.fillParentMaxWidth(),
|
||||||
style = ZashiTypography.header6,
|
style = ZashiTypography.header6,
|
||||||
|
@ -110,14 +109,28 @@ fun ZashiYearMonthWheelDatePicker(
|
||||||
)
|
)
|
||||||
WheelLazyList(
|
WheelLazyList(
|
||||||
modifier = Modifier.weight(.75f),
|
modifier = Modifier.weight(.75f),
|
||||||
selection = years.indexOf(selectedDate.year),
|
selection = state.selectedYearIndex,
|
||||||
itemCount = years.size,
|
itemCount = state.years.size,
|
||||||
itemVerticalOffset = verticallyVisibleItems,
|
itemVerticalOffset = verticallyVisibleItems,
|
||||||
isInfiniteScroll = false,
|
isInfiniteScroll = false,
|
||||||
onFocusItem = { selectedDate = selectedDate.withYear(years[it]) },
|
onFocusItem = {
|
||||||
|
val year = state.years[it]
|
||||||
|
val normalizedSelectedMonth = getSelectedMonthForYear(
|
||||||
|
year = year,
|
||||||
|
selectedMonth = state.selectedDate.month,
|
||||||
|
startYearMonth = startInclusive,
|
||||||
|
endYearMonth = endInclusive
|
||||||
|
)
|
||||||
|
val months = getMonthsForYear(year, startInclusive, endInclusive)
|
||||||
|
val selectedDate = state.selectedDate.withYear(year.value).withMonth(normalizedSelectedMonth.value)
|
||||||
|
state = state.copy(
|
||||||
|
selectedDate = selectedDate,
|
||||||
|
months = months
|
||||||
|
)
|
||||||
|
},
|
||||||
itemContent = {
|
itemContent = {
|
||||||
Text(
|
Text(
|
||||||
text = years[it].toString(),
|
text = state.years[it].toString(),
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
modifier = Modifier.fillParentMaxWidth(),
|
modifier = Modifier.fillParentMaxWidth(),
|
||||||
style = ZashiTypography.header6,
|
style = ZashiTypography.header6,
|
||||||
|
@ -131,6 +144,79 @@ fun ZashiYearMonthWheelDatePicker(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getMonthsForYear(year: Year, startYearMonth: YearMonth, endYearMonth: YearMonth): List<Month> {
|
||||||
|
return when (year.value) {
|
||||||
|
startYearMonth.year -> {
|
||||||
|
(startYearMonth.month.value..Month.DECEMBER.value).map { index ->
|
||||||
|
Month.entries.first { it.value == index }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
endYearMonth.year -> {
|
||||||
|
(Month.JANUARY.value..endYearMonth.month.value).map { index ->
|
||||||
|
Month.entries.first { it.value == index }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
listOf(
|
||||||
|
Month.JANUARY,
|
||||||
|
Month.FEBRUARY,
|
||||||
|
Month.MARCH,
|
||||||
|
Month.APRIL,
|
||||||
|
Month.MAY,
|
||||||
|
Month.JUNE,
|
||||||
|
Month.JULY,
|
||||||
|
Month.AUGUST,
|
||||||
|
Month.SEPTEMBER,
|
||||||
|
Month.OCTOBER,
|
||||||
|
Month.NOVEMBER,
|
||||||
|
Month.DECEMBER
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getSelectedMonthForYear(
|
||||||
|
year: Year,
|
||||||
|
selectedMonth: Month,
|
||||||
|
startYearMonth: YearMonth,
|
||||||
|
endYearMonth: YearMonth
|
||||||
|
): Month {
|
||||||
|
return when (year.value) {
|
||||||
|
startYearMonth.year -> {
|
||||||
|
val months = (startYearMonth.month.value..Month.DECEMBER.value).map { index ->
|
||||||
|
Month.entries.first { it.value == index }
|
||||||
|
}
|
||||||
|
if (selectedMonth in months) selectedMonth else months.findClosest(selectedMonth)
|
||||||
|
}
|
||||||
|
|
||||||
|
endYearMonth.year -> {
|
||||||
|
val months = (Month.JANUARY.value..endYearMonth.month.value).map { index ->
|
||||||
|
Month.entries.first { it.value == index }
|
||||||
|
}
|
||||||
|
if (selectedMonth in months) selectedMonth else months.findClosest(selectedMonth)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> selectedMonth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun List<Month>.findClosest(target: Month): Month {
|
||||||
|
var closestNumber = this[0] // Initialize with the first element
|
||||||
|
var minDifference = (this[0].value - target.value).absoluteValue
|
||||||
|
|
||||||
|
for (number in this) {
|
||||||
|
val difference = (number.value - target.value).absoluteValue
|
||||||
|
if (difference < minDifference) {
|
||||||
|
minDifference = difference
|
||||||
|
closestNumber = number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return closestNumber
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("MagicNumber", "ContentSlotReused")
|
@Suppress("MagicNumber", "ContentSlotReused")
|
||||||
@Composable
|
@Composable
|
||||||
private fun WheelLazyList(
|
private fun WheelLazyList(
|
||||||
|
@ -155,10 +241,8 @@ private fun WheelLazyList(
|
||||||
val isScrollInProgress = state.isScrollInProgress
|
val isScrollInProgress = state.isScrollInProgress
|
||||||
|
|
||||||
LaunchedEffect(itemCount) {
|
LaunchedEffect(itemCount) {
|
||||||
coroutineScope.launch {
|
|
||||||
state.scrollToItem(startIndex)
|
state.scrollToItem(startIndex)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
LaunchedEffect(key1 = isScrollInProgress) {
|
LaunchedEffect(key1 = isScrollInProgress) {
|
||||||
if (!isScrollInProgress) {
|
if (!isScrollInProgress) {
|
||||||
|
@ -286,3 +370,13 @@ private fun calculateIndexToFocus(
|
||||||
}
|
}
|
||||||
return index
|
return index
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
private data class InternalState(
|
||||||
|
val selectedDate: YearMonth,
|
||||||
|
val months: List<Month>,
|
||||||
|
val years: List<Year>
|
||||||
|
) {
|
||||||
|
val selectedYearIndex = years.map { it.value }.indexOf(selectedDate.year)
|
||||||
|
val selectedMonthIndex = maxOf(months.indexOf(selectedDate.month), 0)
|
||||||
|
}
|
||||||
|
|
|
@ -134,10 +134,10 @@ fun MainActivity.OnboardingNavigation() {
|
||||||
AndroidRestoreBDHeight(it.toRoute())
|
AndroidRestoreBDHeight(it.toRoute())
|
||||||
}
|
}
|
||||||
composable<RestoreBDDate> {
|
composable<RestoreBDDate> {
|
||||||
AndroidRestoreBDDate()
|
AndroidRestoreBDDate(it.toRoute())
|
||||||
}
|
}
|
||||||
composable<RestoreBDEstimation> {
|
composable<RestoreBDEstimation> {
|
||||||
AndroidRestoreBDEstimation()
|
AndroidRestoreBDEstimation(it.toRoute())
|
||||||
}
|
}
|
||||||
dialog<SeedInfo>(
|
dialog<SeedInfo>(
|
||||||
dialogProperties =
|
dialogProperties =
|
||||||
|
|
|
@ -6,14 +6,15 @@ import androidx.compose.runtime.getValue
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
|
import org.koin.core.parameter.parametersOf
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AndroidRestoreBDDate() {
|
fun AndroidRestoreBDDate(args: RestoreBDDate) {
|
||||||
val vm = koinViewModel<RestoreBDDateViewModel>()
|
val vm = koinViewModel<RestoreBDDateViewModel> { parametersOf(args) }
|
||||||
val state by vm.state.collectAsStateWithLifecycle()
|
val state by vm.state.collectAsStateWithLifecycle()
|
||||||
RestoreBDDateView(state)
|
BackHandler(enabled = state != null) { state?.onBack?.invoke() }
|
||||||
BackHandler { state.onBack() }
|
state?.let { RestoreBDDateView(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data object RestoreBDDate
|
data class RestoreBDDate(val seed: String)
|
||||||
|
|
|
@ -2,9 +2,12 @@ package co.electriccoin.zcash.ui.screen.restore.date
|
||||||
|
|
||||||
import co.electriccoin.zcash.ui.design.component.ButtonState
|
import co.electriccoin.zcash.ui.design.component.ButtonState
|
||||||
import co.electriccoin.zcash.ui.design.component.IconButtonState
|
import co.electriccoin.zcash.ui.design.component.IconButtonState
|
||||||
|
import java.time.YearMonth
|
||||||
|
|
||||||
data class RestoreBDDateState(
|
data class RestoreBDDateState(
|
||||||
|
val selection: YearMonth,
|
||||||
val next: ButtonState,
|
val next: ButtonState,
|
||||||
val dialogButton: IconButtonState,
|
val dialogButton: IconButtonState,
|
||||||
val onBack: () -> Unit
|
val onBack: () -> Unit,
|
||||||
|
val onYearMonthChange: (YearMonth) -> Unit,
|
||||||
)
|
)
|
||||||
|
|
|
@ -42,6 +42,7 @@ import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
|
||||||
import co.electriccoin.zcash.ui.design.util.orDark
|
import co.electriccoin.zcash.ui.design.util.orDark
|
||||||
import co.electriccoin.zcash.ui.design.util.scaffoldPadding
|
import co.electriccoin.zcash.ui.design.util.scaffoldPadding
|
||||||
import co.electriccoin.zcash.ui.design.util.stringRes
|
import co.electriccoin.zcash.ui.design.util.stringRes
|
||||||
|
import java.time.YearMonth
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RestoreBDDateView(state: RestoreBDDateState) {
|
fun RestoreBDDateView(state: RestoreBDDateState) {
|
||||||
|
@ -84,7 +85,8 @@ private fun Content(
|
||||||
Spacer(Modifier.height(24.dp))
|
Spacer(Modifier.height(24.dp))
|
||||||
|
|
||||||
ZashiYearMonthWheelDatePicker(
|
ZashiYearMonthWheelDatePicker(
|
||||||
onSelectionChange = {},
|
selection = state.selection,
|
||||||
|
onSelectionChange = state.onYearMonthChange,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -150,8 +152,10 @@ private fun Preview() =
|
||||||
state =
|
state =
|
||||||
RestoreBDDateState(
|
RestoreBDDateState(
|
||||||
next = ButtonState(stringRes("Estimate")) {},
|
next = ButtonState(stringRes("Estimate")) {},
|
||||||
dialogButton = IconButtonState(R.drawable.ic_restore_dialog) {},
|
dialogButton = IconButtonState(R.drawable.ic_help) {},
|
||||||
onBack = {}
|
onBack = {},
|
||||||
|
onYearMonthChange = {},
|
||||||
|
selection = YearMonth.now()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
package co.electriccoin.zcash.ui.screen.restore.date
|
package co.electriccoin.zcash.ui.screen.restore.date
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import cash.z.ecc.android.sdk.SdkSynchronizer
|
||||||
|
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||||
|
import cash.z.ecc.sdk.ANDROID_STATE_FLOW_TIMEOUT
|
||||||
|
import cash.z.ecc.sdk.type.fromResources
|
||||||
import co.electriccoin.zcash.ui.NavigationRouter
|
import co.electriccoin.zcash.ui.NavigationRouter
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
import co.electriccoin.zcash.ui.design.component.ButtonState
|
import co.electriccoin.zcash.ui.design.component.ButtonState
|
||||||
|
@ -9,27 +15,64 @@ import co.electriccoin.zcash.ui.design.util.stringRes
|
||||||
import co.electriccoin.zcash.ui.screen.restore.estimation.RestoreBDEstimation
|
import co.electriccoin.zcash.ui.screen.restore.estimation.RestoreBDEstimation
|
||||||
import co.electriccoin.zcash.ui.screen.restore.info.SeedInfo
|
import co.electriccoin.zcash.ui.screen.restore.info.SeedInfo
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.WhileSubscribed
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.flow.stateIn
|
||||||
|
import kotlinx.coroutines.flow.update
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.datetime.Clock
|
||||||
|
import kotlinx.datetime.toKotlinInstant
|
||||||
|
import java.time.YearMonth
|
||||||
|
import java.time.ZoneId
|
||||||
|
|
||||||
class RestoreBDDateViewModel(
|
class RestoreBDDateViewModel(
|
||||||
private val navigationRouter: NavigationRouter
|
private val args: RestoreBDDate,
|
||||||
|
private val navigationRouter: NavigationRouter,
|
||||||
|
private val context: Context,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
val state: StateFlow<RestoreBDDateState> = MutableStateFlow(createState()).asStateFlow()
|
|
||||||
|
|
||||||
private fun createState() =
|
private val selection = MutableStateFlow<YearMonth>(YearMonth.now())
|
||||||
|
|
||||||
|
val state: StateFlow<RestoreBDDateState?> = selection
|
||||||
|
.map {
|
||||||
|
createState(it)
|
||||||
|
}
|
||||||
|
.stateIn(
|
||||||
|
scope = viewModelScope,
|
||||||
|
started = SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT),
|
||||||
|
initialValue = null
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun createState(selection: YearMonth) =
|
||||||
RestoreBDDateState(
|
RestoreBDDateState(
|
||||||
next = ButtonState(stringRes(R.string.restore_bd_height_btn), onClick = ::onEstimateClick),
|
next = ButtonState(stringRes(R.string.restore_bd_height_btn), onClick = ::onEstimateClick),
|
||||||
dialogButton =
|
dialogButton =
|
||||||
IconButtonState(
|
IconButtonState(
|
||||||
icon = co.electriccoin.zcash.ui.design.R.drawable.ic_info,
|
icon = R.drawable.ic_help,
|
||||||
onClick = ::onInfoButtonClick,
|
onClick = ::onInfoButtonClick,
|
||||||
),
|
),
|
||||||
onBack = ::onBack,
|
onBack = ::onBack,
|
||||||
|
onYearMonthChange = ::onYearMonthChange,
|
||||||
|
selection = selection
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun onEstimateClick() {
|
private fun onEstimateClick() {
|
||||||
navigationRouter.forward(RestoreBDEstimation)
|
viewModelScope.launch {
|
||||||
|
val instant = selection.value.atDay(1)
|
||||||
|
.atStartOfDay()
|
||||||
|
.atZone(ZoneId.systemDefault())
|
||||||
|
.toInstant()
|
||||||
|
.toKotlinInstant()
|
||||||
|
val bday = SdkSynchronizer.estimateBirthdayHeight(
|
||||||
|
context = context,
|
||||||
|
date = instant,
|
||||||
|
network = ZcashNetwork.fromResources(context)
|
||||||
|
)
|
||||||
|
navigationRouter.forward(RestoreBDEstimation(seed = args.seed, blockHeight = bday.value))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onBack() {
|
private fun onBack() {
|
||||||
|
@ -39,4 +82,8 @@ class RestoreBDDateViewModel(
|
||||||
private fun onInfoButtonClick() {
|
private fun onInfoButtonClick() {
|
||||||
navigationRouter.forward(SeedInfo)
|
navigationRouter.forward(SeedInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun onYearMonthChange(yearMonth: YearMonth) {
|
||||||
|
selection.update { yearMonth }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,14 +6,18 @@ import androidx.compose.runtime.getValue
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
|
import org.koin.core.parameter.parametersOf
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AndroidRestoreBDEstimation() {
|
fun AndroidRestoreBDEstimation(args: RestoreBDEstimation) {
|
||||||
val vm = koinViewModel<RestoreBDEstimationViewModel>()
|
val vm = koinViewModel<RestoreBDEstimationViewModel> { parametersOf(args) }
|
||||||
val state by vm.state.collectAsStateWithLifecycle()
|
val state by vm.state.collectAsStateWithLifecycle()
|
||||||
RestoreBDEstimationView(state)
|
RestoreBDEstimationView(state)
|
||||||
BackHandler { state.onBack() }
|
BackHandler { state.onBack() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data object RestoreBDEstimation
|
data class RestoreBDEstimation(
|
||||||
|
val seed: String,
|
||||||
|
val blockHeight: Long
|
||||||
|
)
|
||||||
|
|
|
@ -133,7 +133,7 @@ private fun Preview() =
|
||||||
state =
|
state =
|
||||||
RestoreBDEstimationState(
|
RestoreBDEstimationState(
|
||||||
restore = ButtonState(stringRes("Estimate")) {},
|
restore = ButtonState(stringRes("Estimate")) {},
|
||||||
dialogButton = IconButtonState(R.drawable.ic_restore_dialog) {},
|
dialogButton = IconButtonState(R.drawable.ic_help) {},
|
||||||
onBack = {},
|
onBack = {},
|
||||||
text = stringRes("123456"),
|
text = stringRes("123456"),
|
||||||
copy = ButtonState(stringRes("Copy"), icon = R.drawable.ic_copy) {}
|
copy = ButtonState(stringRes("Copy"), icon = R.drawable.ic_copy) {}
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
package co.electriccoin.zcash.ui.screen.restore.estimation
|
package co.electriccoin.zcash.ui.screen.restore.estimation
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||||
|
import cash.z.ecc.android.sdk.model.SeedPhrase
|
||||||
import co.electriccoin.zcash.ui.NavigationRouter
|
import co.electriccoin.zcash.ui.NavigationRouter
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
|
import co.electriccoin.zcash.ui.common.usecase.RestoreWalletUseCase
|
||||||
import co.electriccoin.zcash.ui.design.component.ButtonState
|
import co.electriccoin.zcash.ui.design.component.ButtonState
|
||||||
import co.electriccoin.zcash.ui.design.component.IconButtonState
|
import co.electriccoin.zcash.ui.design.component.IconButtonState
|
||||||
import co.electriccoin.zcash.ui.design.util.stringRes
|
import co.electriccoin.zcash.ui.design.util.stringRes
|
||||||
|
@ -12,7 +15,9 @@ import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
|
||||||
class RestoreBDEstimationViewModel(
|
class RestoreBDEstimationViewModel(
|
||||||
private val navigationRouter: NavigationRouter
|
private val args: RestoreBDEstimation,
|
||||||
|
private val navigationRouter: NavigationRouter,
|
||||||
|
private val restoreWallet: RestoreWalletUseCase
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
val state: StateFlow<RestoreBDEstimationState> = MutableStateFlow(createState()).asStateFlow()
|
val state: StateFlow<RestoreBDEstimationState> = MutableStateFlow(createState()).asStateFlow()
|
||||||
|
|
||||||
|
@ -20,17 +25,20 @@ class RestoreBDEstimationViewModel(
|
||||||
RestoreBDEstimationState(
|
RestoreBDEstimationState(
|
||||||
dialogButton =
|
dialogButton =
|
||||||
IconButtonState(
|
IconButtonState(
|
||||||
icon = co.electriccoin.zcash.ui.design.R.drawable.ic_info,
|
icon = R.drawable.ic_help,
|
||||||
onClick = ::onInfoButtonClick,
|
onClick = ::onInfoButtonClick,
|
||||||
),
|
),
|
||||||
onBack = ::onBack,
|
onBack = ::onBack,
|
||||||
text = stringRes("123456"),
|
text = stringRes(args.blockHeight.toString()),
|
||||||
copy = ButtonState(stringRes(R.string.restore_bd_estimation_copy), icon = R.drawable.ic_copy) {},
|
copy = ButtonState(stringRes(R.string.restore_bd_estimation_copy), icon = R.drawable.ic_copy) {},
|
||||||
restore = ButtonState(stringRes(R.string.restore_bd_estimation_restore), onClick = ::onRestoreClick),
|
restore = ButtonState(stringRes(R.string.restore_bd_estimation_restore), onClick = ::onRestoreClick),
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun onRestoreClick() {
|
private fun onRestoreClick() {
|
||||||
// do nothing
|
restoreWallet(
|
||||||
|
seedPhrase = SeedPhrase.new(args.seed),
|
||||||
|
birthday = BlockHeight.new(args.blockHeight)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onBack() {
|
private fun onBack() {
|
||||||
|
|
|
@ -205,7 +205,7 @@ private fun Preview() =
|
||||||
state =
|
state =
|
||||||
RestoreBDHeightState(
|
RestoreBDHeightState(
|
||||||
onBack = {},
|
onBack = {},
|
||||||
dialogButton = IconButtonState(R.drawable.ic_restore_dialog) {},
|
dialogButton = IconButtonState(R.drawable.ic_help) {},
|
||||||
blockHeight = TextFieldState(stringRes("")) {},
|
blockHeight = TextFieldState(stringRes("")) {},
|
||||||
estimate = ButtonState(stringRes("Estimate")) {},
|
estimate = ButtonState(stringRes("Estimate")) {},
|
||||||
restore = ButtonState(stringRes("Restore")) {}
|
restore = ButtonState(stringRes("Restore")) {}
|
||||||
|
|
|
@ -54,7 +54,7 @@ class RestoreBDHeightViewModel(
|
||||||
onBack = ::onBack,
|
onBack = ::onBack,
|
||||||
dialogButton =
|
dialogButton =
|
||||||
IconButtonState(
|
IconButtonState(
|
||||||
icon = co.electriccoin.zcash.ui.design.R.drawable.ic_info,
|
icon = R.drawable.ic_help,
|
||||||
onClick = ::onInfoButtonClick,
|
onClick = ::onInfoButtonClick,
|
||||||
),
|
),
|
||||||
restore =
|
restore =
|
||||||
|
@ -74,7 +74,7 @@ class RestoreBDHeightViewModel(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onEstimateClick() {
|
private fun onEstimateClick() {
|
||||||
navigationRouter.forward(RestoreBDDate)
|
navigationRouter.forward(RestoreBDDate(seed = restoreBDHeight.seed))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onRestoreClick() {
|
private fun onRestoreClick() {
|
||||||
|
|
|
@ -297,7 +297,7 @@ private fun Preview() =
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
onBack = {},
|
onBack = {},
|
||||||
dialogButton = IconButtonState(R.drawable.ic_restore_dialog) {},
|
dialogButton = IconButtonState(R.drawable.ic_help) {},
|
||||||
nextButton =
|
nextButton =
|
||||||
ButtonState(
|
ButtonState(
|
||||||
text = stringRes("Next"),
|
text = stringRes("Next"),
|
||||||
|
|
|
@ -130,7 +130,7 @@ class RestoreSeedViewModel(
|
||||||
onBack = ::onBack,
|
onBack = ::onBack,
|
||||||
dialogButton =
|
dialogButton =
|
||||||
IconButtonState(
|
IconButtonState(
|
||||||
icon = co.electriccoin.zcash.ui.design.R.drawable.ic_info,
|
icon = R.drawable.ic_help,
|
||||||
onClick = ::onInfoButtonClick
|
onClick = ::onInfoButtonClick
|
||||||
),
|
),
|
||||||
nextButton =
|
nextButton =
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<path
|
|
||||||
android:pathData="M9.09,9C9.325,8.332 9.789,7.768 10.4,7.409C11.011,7.05 11.729,6.919 12.427,7.039C13.125,7.158 13.759,7.522 14.215,8.064C14.671,8.606 14.921,9.292 14.92,10C14.92,12 11.92,13 11.92,13M12,17H12.01M22,12C22,17.523 17.523,22 12,22C6.477,22 2,17.523 2,12C2,6.477 6.477,2 12,2C17.523,2 22,6.477 22,12Z"
|
|
||||||
android:strokeLineJoin="round"
|
|
||||||
android:strokeWidth="2"
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:strokeColor="#231F20"
|
|
||||||
android:strokeLineCap="round"/>
|
|
||||||
</vector>
|
|
Loading…
Reference in New Issue