[#1164] Restoring UI state in TopAppBar
- Closes #1164 - This incorporates the new wallet restoring label into the custom TopAppBar UI component, so it’s accessible from all screens - This also fixes the adjust brightness feature that previously stayed turned on when the user left to a surrounding tab screen (Send or Balances) - Changelog update Move DisableScreenTimeout into the parent HomeView Persist restoring state Fix infinite loading trx history UI state Add New wallet syncing state This also adds the wallet restoring state into the transaction history state calculation
This commit is contained in:
parent
84c7618037
commit
8c027003cc
|
@ -19,6 +19,8 @@ directly impact users rather than highlighting other key architectural updates.*
|
||||||
- Transitions between screens are now animated with a simple slide animation
|
- Transitions between screens are now animated with a simple slide animation
|
||||||
- Proposal API from the Zcash SDK has been integrated together with handling error states for multi-transaction
|
- Proposal API from the Zcash SDK has been integrated together with handling error states for multi-transaction
|
||||||
submission
|
submission
|
||||||
|
- New Restoring Your Wallet label has been added to all post-onboarding screens to notify users about the current
|
||||||
|
state of the wallet-restoring process.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- The Transaction History UI has been incorporated into the Account screen and completely reworked according to the
|
- The Transaction History UI has been incorporated into the Account screen and completely reworked according to the
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
@file:Suppress("TooManyFunctions")
|
||||||
|
|
||||||
package co.electriccoin.zcash.ui.design.component
|
package co.electriccoin.zcash.ui.design.component
|
||||||
|
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
|
@ -7,6 +9,7 @@ import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.RowScope
|
import androidx.compose.foundation.layout.RowScope
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
|
@ -34,7 +37,10 @@ import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.platform.testTag
|
import androidx.compose.ui.platform.testTag
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.Dp
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
import co.electriccoin.zcash.ui.design.R
|
import co.electriccoin.zcash.ui.design.R
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
import co.electriccoin.zcash.ui.design.theme.internal.SecondaryTypography
|
import co.electriccoin.zcash.ui.design.theme.internal.SecondaryTypography
|
||||||
|
@ -49,6 +55,34 @@ private fun TopAppBarTextComposablePreview() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
private fun TopAppBarTextRestoringComposablePreview() {
|
||||||
|
ZcashTheme(forceDarkMode = false) {
|
||||||
|
GradientSurface {
|
||||||
|
SmallTopAppBar(
|
||||||
|
titleText = "Screen A",
|
||||||
|
backText = "Back",
|
||||||
|
restoringLabel = "[RESTORING YOUR WALLET…]"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
private fun TopAppBarTextRestoringLongComposablePreview() {
|
||||||
|
ZcashTheme(forceDarkMode = false) {
|
||||||
|
GradientSurface {
|
||||||
|
SmallTopAppBar(
|
||||||
|
titleText = "Screen A",
|
||||||
|
backText = "Back",
|
||||||
|
restoringLabel = "[RESTORING YOUR WALLET LONG TEXT…]"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
private fun TopAppBarLogoComposablePreview() {
|
private fun TopAppBarLogoComposablePreview() {
|
||||||
|
@ -59,6 +93,20 @@ private fun TopAppBarLogoComposablePreview() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
private fun TopAppBarLogoRestoringComposablePreview() {
|
||||||
|
ZcashTheme(forceDarkMode = false) {
|
||||||
|
GradientSurface {
|
||||||
|
SmallTopAppBar(
|
||||||
|
showTitleLogo = true,
|
||||||
|
backText = "Back",
|
||||||
|
restoringLabel = "[RESTORING YOUR WALLET…]"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
private fun TopAppBarRegularMenuComposablePreview() {
|
private fun TopAppBarRegularMenuComposablePreview() {
|
||||||
|
@ -213,10 +261,11 @@ private fun TopBarOneVisibleActionMenuExample(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList", "LongMethod")
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
fun SmallTopAppBar(
|
fun SmallTopAppBar(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
restoringLabel: String? = null,
|
||||||
titleText: String? = null,
|
titleText: String? = null,
|
||||||
showTitleLogo: Boolean = false,
|
showTitleLogo: Boolean = false,
|
||||||
backText: String? = null,
|
backText: String? = null,
|
||||||
|
@ -227,17 +276,40 @@ fun SmallTopAppBar(
|
||||||
) {
|
) {
|
||||||
CenterAlignedTopAppBar(
|
CenterAlignedTopAppBar(
|
||||||
title = {
|
title = {
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
var restoringSpacerHeight: Dp = 0.dp
|
||||||
|
|
||||||
if (titleText != null) {
|
if (titleText != null) {
|
||||||
Text(
|
Text(
|
||||||
text = titleText.uppercase(),
|
text = titleText.uppercase(),
|
||||||
style = SecondaryTypography.headlineSmall
|
style = SecondaryTypography.headlineSmall
|
||||||
)
|
)
|
||||||
|
restoringSpacerHeight = ZcashTheme.dimens.spacingTiny
|
||||||
} else if (showTitleLogo) {
|
} else if (showTitleLogo) {
|
||||||
Icon(
|
Icon(
|
||||||
painter = painterResource(id = R.drawable.zashi_text_logo),
|
painter = painterResource(id = R.drawable.zashi_text_logo),
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
modifier = Modifier.height(ZcashTheme.dimens.topAppBarZcashLogoHeight)
|
modifier = Modifier.height(ZcashTheme.dimens.topAppBarZcashLogoHeight)
|
||||||
)
|
)
|
||||||
|
restoringSpacerHeight = ZcashTheme.dimens.spacingSmall
|
||||||
|
}
|
||||||
|
|
||||||
|
if (restoringLabel != null) {
|
||||||
|
Spacer(modifier = Modifier.height(restoringSpacerHeight))
|
||||||
|
|
||||||
|
@Suppress("MagicNumber")
|
||||||
|
Text(
|
||||||
|
text = restoringLabel.uppercase(),
|
||||||
|
style = ZcashTheme.extendedTypography.restoringTopAppBarStyle,
|
||||||
|
color = ZcashTheme.colors.restoringTopAppBarColor,
|
||||||
|
modifier = Modifier.fillMaxWidth(0.75f),
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
|
|
|
@ -18,6 +18,7 @@ data class ExtendedColors(
|
||||||
val circularProgressBarScreen: Color,
|
val circularProgressBarScreen: Color,
|
||||||
val linearProgressBarTrack: Color,
|
val linearProgressBarTrack: Color,
|
||||||
val linearProgressBarBackground: Color,
|
val linearProgressBarBackground: Color,
|
||||||
|
val restoringTopAppBarColor: Color,
|
||||||
val chipIndex: Color,
|
val chipIndex: Color,
|
||||||
val textCommon: Color,
|
val textCommon: Color,
|
||||||
val textMedium: Color,
|
val textMedium: Color,
|
||||||
|
|
|
@ -54,6 +54,7 @@ internal object Dark {
|
||||||
val circularProgressBarScreen = Color(0xFFFFFFFF)
|
val circularProgressBarScreen = Color(0xFFFFFFFF)
|
||||||
val linearProgressBarTrack = Color(0xFFD9D9D9)
|
val linearProgressBarTrack = Color(0xFFD9D9D9)
|
||||||
val linearProgressBarBackground = Light.complementaryColor
|
val linearProgressBarBackground = Light.complementaryColor
|
||||||
|
val restoringTopAppBarColor = Color(0xFF8A8888)
|
||||||
|
|
||||||
val callout = Color(0xFFFFFFFF)
|
val callout = Color(0xFFFFFFFF)
|
||||||
val onCallout = Color(0xFFFFFFFF)
|
val onCallout = Color(0xFFFFFFFF)
|
||||||
|
@ -112,6 +113,7 @@ internal object Light {
|
||||||
val circularProgressBarScreen = Color(0xFF000000)
|
val circularProgressBarScreen = Color(0xFF000000)
|
||||||
val linearProgressBarTrack = Color(0xFFD9D9D9)
|
val linearProgressBarTrack = Color(0xFFD9D9D9)
|
||||||
val linearProgressBarBackground = complementaryColor
|
val linearProgressBarBackground = complementaryColor
|
||||||
|
val restoringTopAppBarColor = Color(0xFF8A8888)
|
||||||
|
|
||||||
val callout = Color(0xFFFFFFFF)
|
val callout = Color(0xFFFFFFFF)
|
||||||
val onCallout = Color(0xFFFFFFFF)
|
val onCallout = Color(0xFFFFFFFF)
|
||||||
|
@ -165,6 +167,7 @@ internal val DarkExtendedColorPalette =
|
||||||
circularProgressBarScreen = Dark.circularProgressBarScreen,
|
circularProgressBarScreen = Dark.circularProgressBarScreen,
|
||||||
linearProgressBarTrack = Dark.linearProgressBarTrack,
|
linearProgressBarTrack = Dark.linearProgressBarTrack,
|
||||||
linearProgressBarBackground = Dark.linearProgressBarBackground,
|
linearProgressBarBackground = Dark.linearProgressBarBackground,
|
||||||
|
restoringTopAppBarColor = Dark.restoringTopAppBarColor,
|
||||||
chipIndex = Dark.textChipIndex,
|
chipIndex = Dark.textChipIndex,
|
||||||
textCommon = Dark.textCommon,
|
textCommon = Dark.textCommon,
|
||||||
textMedium = Dark.textMedium,
|
textMedium = Dark.textMedium,
|
||||||
|
@ -207,6 +210,7 @@ internal val LightExtendedColorPalette =
|
||||||
circularProgressBarSmall = Light.circularProgressBarSmall,
|
circularProgressBarSmall = Light.circularProgressBarSmall,
|
||||||
linearProgressBarTrack = Light.linearProgressBarTrack,
|
linearProgressBarTrack = Light.linearProgressBarTrack,
|
||||||
linearProgressBarBackground = Light.linearProgressBarBackground,
|
linearProgressBarBackground = Light.linearProgressBarBackground,
|
||||||
|
restoringTopAppBarColor = Light.restoringTopAppBarColor,
|
||||||
chipIndex = Light.textChipIndex,
|
chipIndex = Light.textChipIndex,
|
||||||
textCommon = Light.textCommon,
|
textCommon = Light.textCommon,
|
||||||
textMedium = Dark.textMedium,
|
textMedium = Dark.textMedium,
|
||||||
|
@ -251,6 +255,7 @@ internal val LocalExtendedColors =
|
||||||
circularProgressBarSmall = Color.Unspecified,
|
circularProgressBarSmall = Color.Unspecified,
|
||||||
linearProgressBarTrack = Color.Unspecified,
|
linearProgressBarTrack = Color.Unspecified,
|
||||||
linearProgressBarBackground = Color.Unspecified,
|
linearProgressBarBackground = Color.Unspecified,
|
||||||
|
restoringTopAppBarColor = Color.Unspecified,
|
||||||
chipIndex = Color.Unspecified,
|
chipIndex = Color.Unspecified,
|
||||||
textCommon = Color.Unspecified,
|
textCommon = Color.Unspecified,
|
||||||
textMedium = Color.Unspecified,
|
textMedium = Color.Unspecified,
|
||||||
|
|
|
@ -191,6 +191,7 @@ data class ExtendedTypography(
|
||||||
val radioButton: TextStyle,
|
val radioButton: TextStyle,
|
||||||
// Grouping transaction item text styles to a wrapper class
|
// Grouping transaction item text styles to a wrapper class
|
||||||
val transactionItemStyles: TransactionItemTextStyles,
|
val transactionItemStyles: TransactionItemTextStyles,
|
||||||
|
val restoringTopAppBarStyle: TextStyle,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Suppress("CompositionLocalAllowlist")
|
@Suppress("CompositionLocalAllowlist")
|
||||||
|
@ -361,5 +362,10 @@ val LocalExtendedTypography =
|
||||||
fontWeight = FontWeight.SemiBold
|
fontWeight = FontWeight.SemiBold
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
restoringTopAppBarStyle =
|
||||||
|
SecondaryTypography.labelMedium.copy(
|
||||||
|
fontSize = 12.sp,
|
||||||
|
fontWeight = FontWeight.SemiBold
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,8 @@ import co.electriccoin.zcash.test.UiTestPrerequisites
|
||||||
import co.electriccoin.zcash.ui.common.compose.BrightenScreen
|
import co.electriccoin.zcash.ui.common.compose.BrightenScreen
|
||||||
import co.electriccoin.zcash.ui.common.compose.LocalScreenBrightness
|
import co.electriccoin.zcash.ui.common.compose.LocalScreenBrightness
|
||||||
import co.electriccoin.zcash.ui.common.compose.ScreenBrightness
|
import co.electriccoin.zcash.ui.common.compose.ScreenBrightness
|
||||||
|
import co.electriccoin.zcash.ui.common.compose.ScreenBrightnessState
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
|
@ -20,7 +20,6 @@ import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
|
||||||
class ScreenBrightnessTest : UiTestPrerequisites() {
|
class ScreenBrightnessTest : UiTestPrerequisites() {
|
||||||
@get:Rule
|
@get:Rule
|
||||||
val composeTestRule = createComposeRule()
|
val composeTestRule = createComposeRule()
|
||||||
|
@ -31,19 +30,19 @@ class ScreenBrightnessTest : UiTestPrerequisites() {
|
||||||
runTest {
|
runTest {
|
||||||
val testSetup = TestSetup(composeTestRule)
|
val testSetup = TestSetup(composeTestRule)
|
||||||
|
|
||||||
assertEquals(1, testSetup.getSecureBrightnessCount())
|
assertEquals(ScreenBrightnessState.FULL, testSetup.getSecureBrightnessCount())
|
||||||
|
|
||||||
testSetup.mutableScreenBrightnessFlag.update { false }
|
testSetup.mutableScreenBrightnessFlag.update { false }
|
||||||
composeTestRule.awaitIdle()
|
composeTestRule.awaitIdle()
|
||||||
assertEquals(0, testSetup.getSecureBrightnessCount())
|
assertEquals(ScreenBrightnessState.NORMAL, testSetup.getSecureBrightnessCount())
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestSetup(composeTestRule: ComposeContentTestRule) {
|
private class TestSetup(composeTestRule: ComposeContentTestRule) {
|
||||||
val mutableScreenBrightnessFlag = MutableStateFlow(true)
|
val mutableScreenBrightnessFlag = MutableStateFlow(true)
|
||||||
|
|
||||||
private val screenBrightness = ScreenBrightness()
|
private val screenBrightness = ScreenBrightness
|
||||||
|
|
||||||
fun getSecureBrightnessCount() = screenBrightness.referenceCount.value
|
fun getSecureBrightnessCount() = screenBrightness.referenceSwitch.value
|
||||||
|
|
||||||
init {
|
init {
|
||||||
runTest {
|
runTest {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package co.electriccoin.zcash.ui.screen.about.view
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
||||||
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
import co.electriccoin.zcash.ui.screen.support.model.ConfigInfo
|
import co.electriccoin.zcash.ui.screen.support.model.ConfigInfo
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
@ -24,10 +25,11 @@ class AboutViewTestSetup(
|
||||||
ZcashTheme {
|
ZcashTheme {
|
||||||
About(
|
About(
|
||||||
onBack = { onBackCount.incrementAndGet() },
|
onBack = { onBackCount.incrementAndGet() },
|
||||||
versionInfo = versionInfo,
|
|
||||||
configInfo = configInfo,
|
configInfo = configInfo,
|
||||||
onPrivacyPolicy = {},
|
onPrivacyPolicy = {},
|
||||||
snackbarHostState = SnackbarHostState()
|
snackbarHostState = SnackbarHostState(),
|
||||||
|
versionInfo = versionInfo,
|
||||||
|
walletRestoringState = WalletRestoringState.NONE
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package co.electriccoin.zcash.ui.screen.account
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
import co.electriccoin.zcash.ui.screen.account.history.fixture.TransactionHistoryUiStateFixture
|
import co.electriccoin.zcash.ui.screen.account.history.fixture.TransactionHistoryUiStateFixture
|
||||||
|
@ -58,8 +59,6 @@ class AccountTestSetup(
|
||||||
@Suppress("TestFunctionName")
|
@Suppress("TestFunctionName")
|
||||||
fun DefaultContent() {
|
fun DefaultContent() {
|
||||||
Account(
|
Account(
|
||||||
walletSnapshot = walletSnapshot,
|
|
||||||
isKeepScreenOnWhileSyncing = false,
|
|
||||||
goSettings = {
|
goSettings = {
|
||||||
onSettingsCount.incrementAndGet()
|
onSettingsCount.incrementAndGet()
|
||||||
},
|
},
|
||||||
|
@ -68,6 +67,8 @@ class AccountTestSetup(
|
||||||
onTransactionItemAction = {
|
onTransactionItemAction = {
|
||||||
onItemClickCount.incrementAndGet()
|
onItemClickCount.incrementAndGet()
|
||||||
},
|
},
|
||||||
|
walletSnapshot = walletSnapshot,
|
||||||
|
walletRestoringState = WalletRestoringState.NONE,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package co.electriccoin.zcash.ui.screen.account.history
|
package co.electriccoin.zcash.ui.screen.account.history
|
||||||
|
|
||||||
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
import co.electriccoin.zcash.ui.screen.account.model.TransactionUiState
|
import co.electriccoin.zcash.ui.screen.account.model.TransactionUiState
|
||||||
import co.electriccoin.zcash.ui.screen.account.view.HistoryContainer
|
import co.electriccoin.zcash.ui.screen.account.view.HistoryContainer
|
||||||
|
@ -30,7 +31,8 @@ class HistoryTestSetup(
|
||||||
transactionState = initialHistoryUiState,
|
transactionState = initialHistoryUiState,
|
||||||
onTransactionItemAction = {
|
onTransactionItemAction = {
|
||||||
onItemIdClickCount.incrementAndGet()
|
onItemIdClickCount.incrementAndGet()
|
||||||
}
|
},
|
||||||
|
walletRestoringState = WalletRestoringState.NONE
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,16 +7,16 @@ import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
||||||
internal object TransactionHistoryUiStateFixture {
|
internal object TransactionHistoryUiStateFixture {
|
||||||
val TRANSACTIONS = TransactionsFixture.new()
|
val TRANSACTIONS = TransactionsFixture.new()
|
||||||
val STATE = TransactionUiState.Prepared(TRANSACTIONS)
|
val STATE = TransactionUiState.Done(TRANSACTIONS)
|
||||||
|
|
||||||
fun new(
|
fun new(
|
||||||
transactions: ImmutableList<TransactionUi> = TRANSACTIONS,
|
transactions: ImmutableList<TransactionUi> = TRANSACTIONS,
|
||||||
state: TransactionUiState = STATE
|
state: TransactionUiState = STATE
|
||||||
) = when (state) {
|
) = when (state) {
|
||||||
is TransactionUiState.Loading -> state
|
is TransactionUiState.Loading -> state
|
||||||
is TransactionUiState.Syncing -> state
|
is TransactionUiState.Syncing -> state.copy(transactions)
|
||||||
is TransactionUiState.Prepared -> {
|
is TransactionUiState.Done -> state.copy(transactions)
|
||||||
state.copy(transactions)
|
TransactionUiState.DoneEmpty -> state
|
||||||
}
|
TransactionUiState.SyncingEmpty -> state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ class HistoryViewTest {
|
||||||
fun check_syncing_state() {
|
fun check_syncing_state() {
|
||||||
newTestSetup(
|
newTestSetup(
|
||||||
TransactionHistoryUiStateFixture.new(
|
TransactionHistoryUiStateFixture.new(
|
||||||
state = TransactionUiState.Prepared(persistentListOf()),
|
state = TransactionUiState.Syncing(persistentListOf()),
|
||||||
transactions = TransactionHistoryUiStateFixture.TRANSACTIONS
|
transactions = TransactionHistoryUiStateFixture.TRANSACTIONS
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -62,7 +62,7 @@ class HistoryViewTest {
|
||||||
fun check_done_state_no_transactions() {
|
fun check_done_state_no_transactions() {
|
||||||
newTestSetup(
|
newTestSetup(
|
||||||
TransactionHistoryUiStateFixture.new(
|
TransactionHistoryUiStateFixture.new(
|
||||||
state = TransactionUiState.Prepared(persistentListOf()),
|
state = TransactionUiState.Syncing(persistentListOf()),
|
||||||
transactions = TransactionHistoryUiStateFixture.TRANSACTIONS
|
transactions = TransactionHistoryUiStateFixture.TRANSACTIONS
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -85,7 +85,7 @@ class HistoryViewTest {
|
||||||
fun check_done_state_with_transactions() {
|
fun check_done_state_with_transactions() {
|
||||||
newTestSetup(
|
newTestSetup(
|
||||||
TransactionHistoryUiStateFixture.new(
|
TransactionHistoryUiStateFixture.new(
|
||||||
state = TransactionUiState.Prepared(persistentListOf()),
|
state = TransactionUiState.Syncing(persistentListOf()),
|
||||||
transactions = TransactionHistoryUiStateFixture.TRANSACTIONS
|
transactions = TransactionHistoryUiStateFixture.TRANSACTIONS
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package co.electriccoin.zcash.ui.screen.balances
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
import co.electriccoin.zcash.ui.screen.balances.model.ShieldState
|
import co.electriccoin.zcash.ui.screen.balances.model.ShieldState
|
||||||
|
@ -33,13 +34,13 @@ class BalancesTestSetup(
|
||||||
onSettingsCount.incrementAndGet()
|
onSettingsCount.incrementAndGet()
|
||||||
},
|
},
|
||||||
isFiatConversionEnabled = isShowFiatConversion,
|
isFiatConversionEnabled = isShowFiatConversion,
|
||||||
isKeepScreenOnWhileSyncing = false,
|
|
||||||
isUpdateAvailable = false,
|
isUpdateAvailable = false,
|
||||||
|
isShowingErrorDialog = false,
|
||||||
|
setShowErrorDialog = {},
|
||||||
onShielding = {},
|
onShielding = {},
|
||||||
shieldState = ShieldState.Available,
|
shieldState = ShieldState.Available,
|
||||||
walletSnapshot = walletSnapshot,
|
walletSnapshot = walletSnapshot,
|
||||||
isShowingErrorDialog = false,
|
walletRestoringState = WalletRestoringState.NONE
|
||||||
setShowErrorDialog = {}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package co.electriccoin.zcash.ui.screen.exportdata.view
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
@ -33,7 +34,7 @@ class ExportPrivateDataViewTestSetup(private val composeTestRule: ComposeContent
|
||||||
@Suppress("TestFunctionName")
|
@Suppress("TestFunctionName")
|
||||||
fun DefaultContent() {
|
fun DefaultContent() {
|
||||||
ExportPrivateData(
|
ExportPrivateData(
|
||||||
SnackbarHostState(),
|
snackbarHostState = SnackbarHostState(),
|
||||||
onBack = {
|
onBack = {
|
||||||
onBackCount.incrementAndGet()
|
onBackCount.incrementAndGet()
|
||||||
},
|
},
|
||||||
|
@ -42,7 +43,8 @@ class ExportPrivateDataViewTestSetup(private val composeTestRule: ComposeContent
|
||||||
},
|
},
|
||||||
onConfirm = {
|
onConfirm = {
|
||||||
onConfirmCount.incrementAndGet()
|
onConfirmCount.incrementAndGet()
|
||||||
}
|
},
|
||||||
|
walletRestoringState = WalletRestoringState.NONE
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import androidx.test.filters.MediumTest
|
||||||
import cash.z.ecc.android.sdk.fixture.WalletAddressesFixture
|
import cash.z.ecc.android.sdk.fixture.WalletAddressesFixture
|
||||||
import cash.z.ecc.android.sdk.model.WalletAddresses
|
import cash.z.ecc.android.sdk.model.WalletAddresses
|
||||||
import co.electriccoin.zcash.test.UiTestPrerequisites
|
import co.electriccoin.zcash.test.UiTestPrerequisites
|
||||||
|
import co.electriccoin.zcash.ui.common.compose.ScreenBrightnessState
|
||||||
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||||
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
|
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
|
@ -27,7 +28,7 @@ class ReceiveViewScreenBrightnessTest : UiTestPrerequisites() {
|
||||||
VersionInfoFixture.new(isDebuggable = true)
|
VersionInfoFixture.new(isDebuggable = true)
|
||||||
)
|
)
|
||||||
|
|
||||||
assertEquals(0, testSetup.getScreenBrightnessCount())
|
assertEquals(ScreenBrightnessState.NORMAL, testSetup.getScreenBrightness())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -41,13 +42,11 @@ class ReceiveViewScreenBrightnessTest : UiTestPrerequisites() {
|
||||||
VersionInfoFixture.new(isDebuggable = true)
|
VersionInfoFixture.new(isDebuggable = true)
|
||||||
)
|
)
|
||||||
|
|
||||||
assertEquals(false, testSetup.getOnAdjustBrightness())
|
assertEquals(ScreenBrightnessState.NORMAL, testSetup.getOnAdjustBrightness())
|
||||||
assertEquals(0, testSetup.getScreenBrightnessCount())
|
|
||||||
|
|
||||||
composeTestRule.clickAdjustBrightness()
|
composeTestRule.clickAdjustBrightness()
|
||||||
|
|
||||||
assertEquals(true, testSetup.getOnAdjustBrightness())
|
assertEquals(ScreenBrightnessState.FULL, testSetup.getOnAdjustBrightness())
|
||||||
assertEquals(1, testSetup.getScreenBrightnessCount())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun newTestSetup(
|
private fun newTestSetup(
|
||||||
|
|
|
@ -40,12 +40,10 @@ class ReceiveViewScreenTimeoutTest : UiTestPrerequisites() {
|
||||||
VersionInfoFixture.new(isDebuggable = true)
|
VersionInfoFixture.new(isDebuggable = true)
|
||||||
)
|
)
|
||||||
|
|
||||||
assertEquals(false, testSetup.getOnAdjustBrightness())
|
|
||||||
assertEquals(0, testSetup.getScreenTimeoutCount())
|
assertEquals(0, testSetup.getScreenTimeoutCount())
|
||||||
|
|
||||||
composeTestRule.clickAdjustBrightness()
|
composeTestRule.clickAdjustBrightness()
|
||||||
|
|
||||||
assertEquals(true, testSetup.getOnAdjustBrightness())
|
|
||||||
assertEquals(1, testSetup.getScreenTimeoutCount())
|
assertEquals(1, testSetup.getScreenTimeoutCount())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,12 +10,13 @@ import co.electriccoin.zcash.ui.R
|
||||||
import co.electriccoin.zcash.ui.common.compose.LocalScreenBrightness
|
import co.electriccoin.zcash.ui.common.compose.LocalScreenBrightness
|
||||||
import co.electriccoin.zcash.ui.common.compose.LocalScreenTimeout
|
import co.electriccoin.zcash.ui.common.compose.LocalScreenTimeout
|
||||||
import co.electriccoin.zcash.ui.common.compose.ScreenBrightness
|
import co.electriccoin.zcash.ui.common.compose.ScreenBrightness
|
||||||
|
import co.electriccoin.zcash.ui.common.compose.ScreenBrightnessState
|
||||||
import co.electriccoin.zcash.ui.common.compose.ScreenTimeout
|
import co.electriccoin.zcash.ui.common.compose.ScreenTimeout
|
||||||
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
|
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
|
||||||
import co.electriccoin.zcash.ui.test.getStringResource
|
import co.electriccoin.zcash.ui.test.getStringResource
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
|
||||||
class ReceiveViewTestSetup(
|
class ReceiveViewTestSetup(
|
||||||
|
@ -25,17 +26,17 @@ class ReceiveViewTestSetup(
|
||||||
) {
|
) {
|
||||||
private val onSettingsCount = AtomicInteger(0)
|
private val onSettingsCount = AtomicInteger(0)
|
||||||
private val onAddressDetailsCount = AtomicInteger(0)
|
private val onAddressDetailsCount = AtomicInteger(0)
|
||||||
private val screenBrightness = ScreenBrightness()
|
private val screenBrightness = ScreenBrightness
|
||||||
private val screenTimeout = ScreenTimeout()
|
private val screenTimeout = ScreenTimeout()
|
||||||
private val onAdjustBrightness = AtomicBoolean(false)
|
private var onAdjustBrightness: ScreenBrightnessState = ScreenBrightnessState.NORMAL
|
||||||
|
|
||||||
fun getScreenBrightnessCount() = screenBrightness.referenceCount.value
|
fun getScreenBrightness() = screenBrightness.referenceSwitch.value
|
||||||
|
|
||||||
fun getScreenTimeoutCount() = screenTimeout.referenceCount.value
|
fun getScreenTimeoutCount() = screenTimeout.referenceCount.value
|
||||||
|
|
||||||
fun getOnAdjustBrightness(): Boolean {
|
fun getOnAdjustBrightness(): ScreenBrightnessState {
|
||||||
composeTestRule.waitForIdle()
|
composeTestRule.waitForIdle()
|
||||||
return onAdjustBrightness.get()
|
return onAdjustBrightness
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getOnSettingsCount(): Int {
|
fun getOnSettingsCount(): Int {
|
||||||
|
@ -63,11 +64,14 @@ class ReceiveViewTestSetup(
|
||||||
onSettingsCount.getAndIncrement()
|
onSettingsCount.getAndIncrement()
|
||||||
},
|
},
|
||||||
onAdjustBrightness = {
|
onAdjustBrightness = {
|
||||||
onAdjustBrightness.getAndSet(it)
|
onAdjustBrightness = onAdjustBrightness.getChange()
|
||||||
|
screenTimeout.disableScreenTimeout()
|
||||||
},
|
},
|
||||||
onAddrCopyToClipboard = {},
|
onAddrCopyToClipboard = {},
|
||||||
onQrImageShare = {},
|
onQrImageShare = {},
|
||||||
versionInfo = versionInfo
|
screenBrightnessState = ScreenBrightnessState.NORMAL,
|
||||||
|
versionInfo = versionInfo,
|
||||||
|
walletRestoringState = WalletRestoringState.NONE
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
||||||
import cash.z.ecc.sdk.fixture.PersistableWalletFixture
|
import cash.z.ecc.sdk.fixture.PersistableWalletFixture
|
||||||
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
|
||||||
|
@ -39,10 +40,11 @@ class SeedRecoveryTestSetup(
|
||||||
SeedRecovery(
|
SeedRecovery(
|
||||||
PersistableWalletFixture.new(),
|
PersistableWalletFixture.new(),
|
||||||
onBack = { onBackCount.incrementAndGet() },
|
onBack = { onBackCount.incrementAndGet() },
|
||||||
onSeedCopy = { /* Not tested - debug mode feature only */ },
|
|
||||||
onBirthdayCopy = { onBirthdayCopyCount.incrementAndGet() },
|
onBirthdayCopy = { onBirthdayCopyCount.incrementAndGet() },
|
||||||
onDone = { onCompleteCallbackCount.incrementAndGet() },
|
onDone = { onCompleteCallbackCount.incrementAndGet() },
|
||||||
|
onSeedCopy = { /* Not tested - debug mode feature only */ },
|
||||||
versionInfo = versionInfo,
|
versionInfo = versionInfo,
|
||||||
|
walletRestoringState = WalletRestoringState.NONE,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import cash.z.ecc.sdk.fixture.PersistableWalletFixture
|
||||||
import co.electriccoin.zcash.test.UiTestPrerequisites
|
import co.electriccoin.zcash.test.UiTestPrerequisites
|
||||||
import co.electriccoin.zcash.ui.common.compose.LocalScreenSecurity
|
import co.electriccoin.zcash.ui.common.compose.LocalScreenSecurity
|
||||||
import co.electriccoin.zcash.ui.common.compose.ScreenSecurity
|
import co.electriccoin.zcash.ui.common.compose.ScreenSecurity
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
|
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
|
@ -45,10 +46,11 @@ class SeedRecoveryViewsSecuredScreenTest : UiTestPrerequisites() {
|
||||||
SeedRecovery(
|
SeedRecovery(
|
||||||
PersistableWalletFixture.new(),
|
PersistableWalletFixture.new(),
|
||||||
onBack = {},
|
onBack = {},
|
||||||
onSeedCopy = {},
|
|
||||||
onBirthdayCopy = {},
|
onBirthdayCopy = {},
|
||||||
onDone = {},
|
onDone = {},
|
||||||
versionInfo = VersionInfoFixture.new()
|
onSeedCopy = {},
|
||||||
|
versionInfo = VersionInfoFixture.new(),
|
||||||
|
walletRestoringState = WalletRestoringState.NONE
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import cash.z.ecc.android.sdk.model.MonetarySeparators
|
||||||
import cash.z.ecc.android.sdk.model.Zatoshi
|
import cash.z.ecc.android.sdk.model.Zatoshi
|
||||||
import cash.z.ecc.android.sdk.model.ZecSend
|
import cash.z.ecc.android.sdk.model.ZecSend
|
||||||
import cash.z.ecc.android.sdk.type.AddressType
|
import cash.z.ecc.android.sdk.type.AddressType
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
import co.electriccoin.zcash.ui.fixture.WalletSnapshotFixture
|
import co.electriccoin.zcash.ui.fixture.WalletSnapshotFixture
|
||||||
import co.electriccoin.zcash.ui.screen.send.ext.Saver
|
import co.electriccoin.zcash.ui.screen.send.ext.Saver
|
||||||
|
@ -137,6 +138,7 @@ class SendViewTestSetup(
|
||||||
setAmountState = {},
|
setAmountState = {},
|
||||||
memoState = MemoState.new(""),
|
memoState = MemoState.new(""),
|
||||||
setMemoState = {},
|
setMemoState = {},
|
||||||
|
walletRestoringState = WalletRestoringState.NONE
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import cash.z.ecc.android.sdk.model.MonetarySeparators
|
||||||
import cash.z.ecc.android.sdk.model.Zatoshi
|
import cash.z.ecc.android.sdk.model.Zatoshi
|
||||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||||
import cash.z.ecc.sdk.fixture.ZecSendFixture
|
import cash.z.ecc.sdk.fixture.ZecSendFixture
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.fixture.MockSynchronizer
|
import co.electriccoin.zcash.ui.fixture.MockSynchronizer
|
||||||
import co.electriccoin.zcash.ui.fixture.WalletSnapshotFixture
|
import co.electriccoin.zcash.ui.fixture.WalletSnapshotFixture
|
||||||
import co.electriccoin.zcash.ui.screen.send.WrapSend
|
import co.electriccoin.zcash.ui.screen.send.WrapSend
|
||||||
|
@ -78,7 +79,8 @@ class SendViewIntegrationTest {
|
||||||
hasCameraFeature = true,
|
hasCameraFeature = true,
|
||||||
goSettings = {},
|
goSettings = {},
|
||||||
monetarySeparators = monetarySeparators,
|
monetarySeparators = monetarySeparators,
|
||||||
goSendConfirmation = {}
|
goSendConfirmation = {},
|
||||||
|
walletRestoringState = WalletRestoringState.NONE,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package co.electriccoin.zcash.ui.screen.settings
|
package co.electriccoin.zcash.ui.screen.settings
|
||||||
|
|
||||||
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
import co.electriccoin.zcash.ui.screen.settings.model.TroubleshootingParameters
|
import co.electriccoin.zcash.ui.screen.settings.model.TroubleshootingParameters
|
||||||
import co.electriccoin.zcash.ui.screen.settings.view.Settings
|
import co.electriccoin.zcash.ui.screen.settings.view.Settings
|
||||||
|
@ -87,7 +88,8 @@ class SettingsViewTestSetup(
|
||||||
},
|
},
|
||||||
onAnalyticsSettingsChanged = {
|
onAnalyticsSettingsChanged = {
|
||||||
onAnalyticsChangedCount.incrementAndGet()
|
onAnalyticsChangedCount.incrementAndGet()
|
||||||
}
|
},
|
||||||
|
walletRestoringState = WalletRestoringState.NONE
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package co.electriccoin.zcash.ui.screen.support.view
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
import java.util.concurrent.atomic.AtomicReference
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
|
@ -36,7 +37,8 @@ class SupportViewTestSetup(private val composeTestRule: ComposeContentTestRule)
|
||||||
@Suppress("TestFunctionName")
|
@Suppress("TestFunctionName")
|
||||||
fun DefaultContent() {
|
fun DefaultContent() {
|
||||||
Support(
|
Support(
|
||||||
snackbarHostState = SnackbarHostState(),
|
isShowingDialog = false,
|
||||||
|
setShowDialog = {},
|
||||||
onBack = {
|
onBack = {
|
||||||
onBackCount.incrementAndGet()
|
onBackCount.incrementAndGet()
|
||||||
},
|
},
|
||||||
|
@ -44,8 +46,8 @@ class SupportViewTestSetup(private val composeTestRule: ComposeContentTestRule)
|
||||||
onSendCount.incrementAndGet()
|
onSendCount.incrementAndGet()
|
||||||
onSendMessage.set(it)
|
onSendMessage.set(it)
|
||||||
},
|
},
|
||||||
isShowingDialog = false,
|
snackbarHostState = SnackbarHostState(),
|
||||||
setShowDialog = {}
|
walletRestoringState = WalletRestoringState.NONE
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ import cash.z.ecc.sdk.type.fromResources
|
||||||
import co.electriccoin.zcash.spackle.FirebaseTestLabUtil
|
import co.electriccoin.zcash.spackle.FirebaseTestLabUtil
|
||||||
import co.electriccoin.zcash.ui.common.compose.BindCompLocalProvider
|
import co.electriccoin.zcash.ui.common.compose.BindCompLocalProvider
|
||||||
import co.electriccoin.zcash.ui.common.model.OnboardingState
|
import co.electriccoin.zcash.ui.common.model.OnboardingState
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.common.viewmodel.HomeViewModel
|
import co.electriccoin.zcash.ui.common.viewmodel.HomeViewModel
|
||||||
import co.electriccoin.zcash.ui.common.viewmodel.SecretState
|
import co.electriccoin.zcash.ui.common.viewmodel.SecretState
|
||||||
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||||
|
@ -53,7 +54,7 @@ import kotlin.time.Duration.Companion.milliseconds
|
||||||
import kotlin.time.Duration.Companion.seconds
|
import kotlin.time.Duration.Companion.seconds
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
val homeViewModel by viewModels<HomeViewModel>()
|
private val homeViewModel by viewModels<HomeViewModel>()
|
||||||
|
|
||||||
val walletViewModel by viewModels<WalletViewModel>()
|
val walletViewModel by viewModels<WalletViewModel>()
|
||||||
|
|
||||||
|
@ -173,6 +174,7 @@ class MainActivity : ComponentActivity() {
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
walletViewModel.persistNewWallet()
|
walletViewModel.persistNewWallet()
|
||||||
|
walletViewModel.persistWalletRestoringState(WalletRestoringState.INITIATING)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -74,9 +74,6 @@ internal fun MainActivity.Navigation() {
|
||||||
WrapHome(
|
WrapHome(
|
||||||
goBack = { finish() },
|
goBack = { finish() },
|
||||||
goScan = { navController.navigateJustOnce(SCAN) },
|
goScan = { navController.navigateJustOnce(SCAN) },
|
||||||
onPageChange = {
|
|
||||||
homeViewModel.screenIndex.value = it
|
|
||||||
},
|
|
||||||
goSendConfirmation = { zecSend ->
|
goSendConfirmation = { zecSend ->
|
||||||
navController.currentBackStackEntry?.savedStateHandle?.let { handle ->
|
navController.currentBackStackEntry?.savedStateHandle?.let { handle ->
|
||||||
fillInHandleForConfirmation(handle, zecSend, SendConfirmationStage.Confirmation)
|
fillInHandleForConfirmation(handle, zecSend, SendConfirmationStage.Confirmation)
|
||||||
|
@ -140,7 +137,7 @@ internal fun MainActivity.Navigation() {
|
||||||
},
|
},
|
||||||
goChooseServer = {
|
goChooseServer = {
|
||||||
navController.navigateJustOnce(CHOOSE_SERVER)
|
navController.navigateJustOnce(CHOOSE_SERVER)
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
composable(CHOOSE_SERVER) {
|
composable(CHOOSE_SERVER) {
|
||||||
|
@ -157,7 +154,7 @@ internal fun MainActivity.Navigation() {
|
||||||
},
|
},
|
||||||
onDone = {
|
onDone = {
|
||||||
navController.popBackStackJustOnce(SEED_RECOVERY)
|
navController.popBackStackJustOnce(SEED_RECOVERY)
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
composable(REQUEST) {
|
composable(REQUEST) {
|
||||||
|
|
|
@ -15,7 +15,7 @@ fun ComponentActivity.BindCompLocalProvider(content: @Composable () -> Unit) {
|
||||||
val screenSecurity = ScreenSecurity()
|
val screenSecurity = ScreenSecurity()
|
||||||
observeScreenSecurityFlag(screenSecurity)
|
observeScreenSecurityFlag(screenSecurity)
|
||||||
|
|
||||||
val screenBrightness = ScreenBrightness()
|
val screenBrightness = ScreenBrightness
|
||||||
observeScreenBrightnessFlag(screenBrightness)
|
observeScreenBrightnessFlag(screenBrightness)
|
||||||
|
|
||||||
val screenTimeout = ScreenTimeout()
|
val screenTimeout = ScreenTimeout()
|
||||||
|
@ -46,7 +46,9 @@ private fun ComponentActivity.observeScreenSecurityFlag(screenSecurity: ScreenSe
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ComponentActivity.observeScreenBrightnessFlag(screenBrightness: ScreenBrightness) {
|
private fun ComponentActivity.observeScreenBrightnessFlag(screenBrightness: ScreenBrightness) {
|
||||||
screenBrightness.referenceCount.map { it > 0 }.collectWith(lifecycleScope) { maxBrightness ->
|
screenBrightness.referenceSwitch
|
||||||
|
.map { it == ScreenBrightnessState.FULL }
|
||||||
|
.collectWith(lifecycleScope) { maxBrightness ->
|
||||||
if (maxBrightness) {
|
if (maxBrightness) {
|
||||||
window.attributes =
|
window.attributes =
|
||||||
window.attributes.apply {
|
window.attributes.apply {
|
||||||
|
|
|
@ -6,28 +6,32 @@ import androidx.compose.runtime.compositionLocalOf
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.flow.updateAndGet
|
|
||||||
|
|
||||||
class ScreenBrightness {
|
sealed class ScreenBrightnessState {
|
||||||
private val mutableReferenceCount: MutableStateFlow<Int> = MutableStateFlow(0)
|
fun getChange(): ScreenBrightnessState {
|
||||||
|
return when (this) {
|
||||||
val referenceCount = mutableReferenceCount.asStateFlow()
|
NORMAL -> FULL
|
||||||
|
FULL -> NORMAL
|
||||||
fun fullBrightness() {
|
|
||||||
mutableReferenceCount.update { it + 1 }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun restoreBrightness() {
|
|
||||||
val after = mutableReferenceCount.updateAndGet { it - 1 }
|
|
||||||
|
|
||||||
if (after < 0) {
|
|
||||||
error("Released brightness reference count too many times")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data object FULL : ScreenBrightnessState()
|
||||||
|
|
||||||
|
data object NORMAL : ScreenBrightnessState()
|
||||||
|
}
|
||||||
|
|
||||||
|
object ScreenBrightness {
|
||||||
|
private val mutableSwitch: MutableStateFlow<ScreenBrightnessState> = MutableStateFlow(ScreenBrightnessState.NORMAL)
|
||||||
|
|
||||||
|
val referenceSwitch = mutableSwitch.asStateFlow()
|
||||||
|
|
||||||
|
fun fullBrightness() = mutableSwitch.update { ScreenBrightnessState.FULL }
|
||||||
|
|
||||||
|
fun restoreBrightness() = mutableSwitch.update { ScreenBrightnessState.NORMAL }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("CompositionLocalAllowlist")
|
@Suppress("CompositionLocalAllowlist")
|
||||||
val LocalScreenBrightness = compositionLocalOf { ScreenBrightness() }
|
val LocalScreenBrightness = compositionLocalOf { ScreenBrightness }
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BrightenScreen() {
|
fun BrightenScreen() {
|
||||||
|
@ -37,3 +41,9 @@ fun BrightenScreen() {
|
||||||
onDispose { screenBrightness.restoreBrightness() }
|
onDispose { screenBrightness.restoreBrightness() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun RestoreScreenBrightness() {
|
||||||
|
val screenBrightness = LocalScreenBrightness.current
|
||||||
|
screenBrightness.restoreBrightness()
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package co.electriccoin.zcash.ui.common.model
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common wallet restoring state enum. This describes whether the current block synchronization run is in the
|
||||||
|
* restoring state or a subsequent synchronization state.
|
||||||
|
*
|
||||||
|
* WARN: Do NOT reorder or change the values; doing so would update their ordinal numbers, which could break the
|
||||||
|
* wallet UI.
|
||||||
|
*/
|
||||||
|
enum class WalletRestoringState {
|
||||||
|
NONE,
|
||||||
|
INITIATING, // New wallet syncing
|
||||||
|
RESTORING, // Existing wallet syncing
|
||||||
|
SYNCING; // Follow-up syncing
|
||||||
|
|
||||||
|
fun isRunningRestoring() = this == NONE || this == RESTORING
|
||||||
|
|
||||||
|
fun toNumber() = ordinal
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun fromNumber(ordinal: Int) = entries[ordinal]
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,6 +29,7 @@ import co.electriccoin.zcash.spackle.Twig
|
||||||
import co.electriccoin.zcash.ui.common.ANDROID_STATE_FLOW_TIMEOUT
|
import co.electriccoin.zcash.ui.common.ANDROID_STATE_FLOW_TIMEOUT
|
||||||
import co.electriccoin.zcash.ui.common.extension.throttle
|
import co.electriccoin.zcash.ui.common.extension.throttle
|
||||||
import co.electriccoin.zcash.ui.common.model.OnboardingState
|
import co.electriccoin.zcash.ui.common.model.OnboardingState
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
||||||
import co.electriccoin.zcash.ui.preference.EncryptedPreferenceKeys
|
import co.electriccoin.zcash.ui.preference.EncryptedPreferenceKeys
|
||||||
import co.electriccoin.zcash.ui.preference.EncryptedPreferenceSingleton
|
import co.electriccoin.zcash.ui.preference.EncryptedPreferenceSingleton
|
||||||
|
@ -98,6 +99,23 @@ class WalletViewModel(application: Application) : AndroidViewModel(application)
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A flow of the wallet block synchronization state.
|
||||||
|
*/
|
||||||
|
val walletRestoringState: StateFlow<WalletRestoringState> =
|
||||||
|
flow {
|
||||||
|
val preferenceProvider = StandardPreferenceSingleton.getInstance(application)
|
||||||
|
emitAll(
|
||||||
|
StandardPreferenceKeys.WALLET_RESTORING_STATE.observe(preferenceProvider).map { persistedNumber ->
|
||||||
|
WalletRestoringState.fromNumber(persistedNumber)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}.stateIn(
|
||||||
|
viewModelScope,
|
||||||
|
SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT),
|
||||||
|
WalletRestoringState.NONE
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A flow of the wallet onboarding state.
|
* A flow of the wallet onboarding state.
|
||||||
*/
|
*/
|
||||||
|
@ -288,12 +306,28 @@ class WalletViewModel(application: Application) : AndroidViewModel(application)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asynchronously notes that the wallet has completed the initial wallet restoring block synchronization run.
|
||||||
|
*
|
||||||
|
* Note that in the current SDK implementation, we don't have any information about the block synchronization
|
||||||
|
* state from the SDK, and thus, we need to note the wallet restoring state here on the client side.
|
||||||
|
*/
|
||||||
|
fun persistWalletRestoringState(walletRestoringState: WalletRestoringState) {
|
||||||
|
val application = getApplication<Application>()
|
||||||
|
|
||||||
|
viewModelScope.launch {
|
||||||
|
val preferenceProvider = StandardPreferenceSingleton.getInstance(application)
|
||||||
|
StandardPreferenceKeys.WALLET_RESTORING_STATE.putValue(preferenceProvider, walletRestoringState.toNumber())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method only has an effect if the synchronizer currently is loaded.
|
* This method only has an effect if the synchronizer currently is loaded.
|
||||||
*/
|
*/
|
||||||
fun rescanBlockchain() {
|
fun rescanBlockchain() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
walletCoordinator.rescanBlockchain()
|
walletCoordinator.rescanBlockchain()
|
||||||
|
persistWalletRestoringState(WalletRestoringState.RESTORING)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -435,4 +469,6 @@ private fun Synchronizer.toWalletSnapshot() =
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Synchronizer.Status.isSyncing() = this == Synchronizer.Status.SYNCING
|
fun Synchronizer.Status.isSyncing() = this == Synchronizer.Status.SYNCING
|
||||||
|
|
||||||
|
fun Synchronizer.Status.isSynced() = this == Synchronizer.Status.SYNCED
|
||||||
|
|
|
@ -4,6 +4,7 @@ import co.electriccoin.zcash.preference.model.entry.BooleanPreferenceDefault
|
||||||
import co.electriccoin.zcash.preference.model.entry.IntegerPreferenceDefault
|
import co.electriccoin.zcash.preference.model.entry.IntegerPreferenceDefault
|
||||||
import co.electriccoin.zcash.preference.model.entry.PreferenceKey
|
import co.electriccoin.zcash.preference.model.entry.PreferenceKey
|
||||||
import co.electriccoin.zcash.ui.common.model.OnboardingState
|
import co.electriccoin.zcash.ui.common.model.OnboardingState
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
|
|
||||||
object StandardPreferenceKeys {
|
object StandardPreferenceKeys {
|
||||||
/**
|
/**
|
||||||
|
@ -15,6 +16,16 @@ object StandardPreferenceKeys {
|
||||||
OnboardingState.NONE.toNumber()
|
OnboardingState.NONE.toNumber()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State defining whether the current block synchronization run is in the restoring state or a subsequent
|
||||||
|
* synchronization state.
|
||||||
|
*/
|
||||||
|
val WALLET_RESTORING_STATE =
|
||||||
|
IntegerPreferenceDefault(
|
||||||
|
PreferenceKey("wallet_restoring_state"),
|
||||||
|
WalletRestoringState.RESTORING.toNumber()
|
||||||
|
)
|
||||||
|
|
||||||
// Default to true until https://github.com/Electric-Coin-Company/zashi-android/issues/304
|
// Default to true until https://github.com/Electric-Coin-Company/zashi-android/issues/304
|
||||||
val IS_ANALYTICS_ENABLED = BooleanPreferenceDefault(PreferenceKey("is_analytics_enabled"), true)
|
val IS_ANALYTICS_ENABLED = BooleanPreferenceDefault(PreferenceKey("is_analytics_enabled"), true)
|
||||||
|
|
||||||
|
|
|
@ -4,15 +4,19 @@ package co.electriccoin.zcash.ui.screen.about
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.activity.viewModels
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import co.electriccoin.zcash.configuration.AndroidConfigurationFactory
|
import co.electriccoin.zcash.configuration.AndroidConfigurationFactory
|
||||||
import co.electriccoin.zcash.ui.MainActivity
|
import co.electriccoin.zcash.ui.MainActivity
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
|
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||||
import co.electriccoin.zcash.ui.screen.about.util.WebBrowserUtil
|
import co.electriccoin.zcash.ui.screen.about.util.WebBrowserUtil
|
||||||
import co.electriccoin.zcash.ui.screen.about.view.About
|
import co.electriccoin.zcash.ui.screen.about.view.About
|
||||||
import co.electriccoin.zcash.ui.screen.support.model.ConfigInfo
|
import co.electriccoin.zcash.ui.screen.support.model.ConfigInfo
|
||||||
|
@ -21,13 +25,22 @@ import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun MainActivity.WrapAbout(goBack: () -> Unit) {
|
internal fun MainActivity.WrapAbout(goBack: () -> Unit) {
|
||||||
WrapAbout(this, goBack)
|
val walletViewModel by viewModels<WalletViewModel>()
|
||||||
|
|
||||||
|
val walletRestoringState = walletViewModel.walletRestoringState.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
|
WrapAbout(
|
||||||
|
activity = this,
|
||||||
|
goBack = goBack,
|
||||||
|
walletRestoringState = walletRestoringState
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun WrapAbout(
|
internal fun WrapAbout(
|
||||||
activity: ComponentActivity,
|
activity: ComponentActivity,
|
||||||
goBack: () -> Unit
|
goBack: () -> Unit,
|
||||||
|
walletRestoringState: WalletRestoringState,
|
||||||
) {
|
) {
|
||||||
val configInfo = ConfigInfo.new(AndroidConfigurationFactory.getInstance(activity.applicationContext))
|
val configInfo = ConfigInfo.new(AndroidConfigurationFactory.getInstance(activity.applicationContext))
|
||||||
val versionInfo = VersionInfo.new(activity.applicationContext)
|
val versionInfo = VersionInfo.new(activity.applicationContext)
|
||||||
|
@ -38,6 +51,7 @@ internal fun WrapAbout(
|
||||||
}
|
}
|
||||||
|
|
||||||
val snackbarHostState = remember { SnackbarHostState() }
|
val snackbarHostState = remember { SnackbarHostState() }
|
||||||
|
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
About(
|
About(
|
||||||
|
@ -52,6 +66,7 @@ internal fun WrapAbout(
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
snackbarHostState = snackbarHostState,
|
snackbarHostState = snackbarHostState,
|
||||||
|
walletRestoringState = walletRestoringState,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ import androidx.compose.ui.text.withStyle
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
||||||
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
|
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
|
@ -55,29 +56,33 @@ private fun AboutPreview() {
|
||||||
GradientSurface {
|
GradientSurface {
|
||||||
About(
|
About(
|
||||||
onBack = {},
|
onBack = {},
|
||||||
versionInfo = VersionInfoFixture.new(),
|
|
||||||
configInfo = ConfigInfoFixture.new(),
|
configInfo = ConfigInfoFixture.new(),
|
||||||
snackbarHostState = SnackbarHostState(),
|
|
||||||
onPrivacyPolicy = {},
|
onPrivacyPolicy = {},
|
||||||
|
snackbarHostState = SnackbarHostState(),
|
||||||
|
versionInfo = VersionInfoFixture.new(),
|
||||||
|
walletRestoringState = WalletRestoringState.NONE,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@Suppress("LongParameterList")
|
||||||
fun About(
|
fun About(
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
configInfo: ConfigInfo,
|
configInfo: ConfigInfo,
|
||||||
onPrivacyPolicy: () -> Unit,
|
onPrivacyPolicy: () -> Unit,
|
||||||
snackbarHostState: SnackbarHostState,
|
snackbarHostState: SnackbarHostState,
|
||||||
versionInfo: VersionInfo,
|
versionInfo: VersionInfo,
|
||||||
|
walletRestoringState: WalletRestoringState,
|
||||||
) {
|
) {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
AboutTopAppBar(
|
AboutTopAppBar(
|
||||||
onBack = onBack,
|
onBack = onBack,
|
||||||
versionInfo = versionInfo,
|
versionInfo = versionInfo,
|
||||||
configInfo = configInfo
|
configInfo = configInfo,
|
||||||
|
showRestoring = walletRestoringState == WalletRestoringState.RESTORING,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
snackbarHost = { SnackbarHost(snackbarHostState) },
|
snackbarHost = { SnackbarHost(snackbarHostState) },
|
||||||
|
@ -105,9 +110,16 @@ fun About(
|
||||||
private fun AboutTopAppBar(
|
private fun AboutTopAppBar(
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
versionInfo: VersionInfo,
|
versionInfo: VersionInfo,
|
||||||
configInfo: ConfigInfo
|
configInfo: ConfigInfo,
|
||||||
|
showRestoring: Boolean
|
||||||
) {
|
) {
|
||||||
SmallTopAppBar(
|
SmallTopAppBar(
|
||||||
|
restoringLabel =
|
||||||
|
if (showRestoring) {
|
||||||
|
stringResource(id = R.string.restoring_wallet_label)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
},
|
||||||
titleText = stringResource(id = R.string.about_title).uppercase(),
|
titleText = stringResource(id = R.string.about_title).uppercase(),
|
||||||
backText = stringResource(id = R.string.about_back).uppercase(),
|
backText = stringResource(id = R.string.about_back).uppercase(),
|
||||||
backContentDescriptionText = stringResource(R.string.about_back_content_description),
|
backContentDescriptionText = stringResource(R.string.about_back_content_description),
|
||||||
|
@ -116,7 +128,7 @@ private fun AboutTopAppBar(
|
||||||
if (versionInfo.isDebuggable && !versionInfo.isRunningUnderTestService) {
|
if (versionInfo.isDebuggable && !versionInfo.isRunningUnderTestService) {
|
||||||
DebugMenu(versionInfo, configInfo)
|
DebugMenu(versionInfo, configInfo)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import cash.z.ecc.android.sdk.Synchronizer
|
||||||
import cash.z.ecc.android.sdk.internal.Twig
|
import cash.z.ecc.android.sdk.internal.Twig
|
||||||
import co.electriccoin.zcash.spackle.ClipboardManagerUtil
|
import co.electriccoin.zcash.spackle.ClipboardManagerUtil
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
||||||
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||||
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
|
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
|
||||||
|
@ -19,7 +20,6 @@ import co.electriccoin.zcash.ui.screen.account.model.TransactionUiState
|
||||||
import co.electriccoin.zcash.ui.screen.account.view.Account
|
import co.electriccoin.zcash.ui.screen.account.view.Account
|
||||||
import co.electriccoin.zcash.ui.screen.account.view.TrxItemAction
|
import co.electriccoin.zcash.ui.screen.account.view.TrxItemAction
|
||||||
import co.electriccoin.zcash.ui.screen.account.viewmodel.TransactionHistoryViewModel
|
import co.electriccoin.zcash.ui.screen.account.viewmodel.TransactionHistoryViewModel
|
||||||
import co.electriccoin.zcash.ui.screen.settings.viewmodel.SettingsViewModel
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.jetbrains.annotations.VisibleForTesting
|
import org.jetbrains.annotations.VisibleForTesting
|
||||||
|
@ -36,12 +36,8 @@ internal fun WrapAccount(
|
||||||
|
|
||||||
val transactionHistoryViewModel by activity.viewModels<TransactionHistoryViewModel>()
|
val transactionHistoryViewModel by activity.viewModels<TransactionHistoryViewModel>()
|
||||||
|
|
||||||
val settingsViewModel by activity.viewModels<SettingsViewModel>()
|
|
||||||
|
|
||||||
val walletSnapshot = walletViewModel.walletSnapshot.collectAsStateWithLifecycle().value
|
val walletSnapshot = walletViewModel.walletSnapshot.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
val isKeepScreenOnWhileSyncing = settingsViewModel.isKeepScreenOnWhileSyncing.collectAsStateWithLifecycle().value
|
|
||||||
|
|
||||||
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
|
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
val transactionsUiState = transactionHistoryViewModel.transactionUiState.collectAsStateWithLifecycle().value
|
val transactionsUiState = transactionHistoryViewModel.transactionUiState.collectAsStateWithLifecycle().value
|
||||||
|
@ -50,16 +46,18 @@ internal fun WrapAccount(
|
||||||
transactionHistoryViewModel.processTransactionState(value)
|
transactionHistoryViewModel.processTransactionState(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val walletRestoringState = walletViewModel.walletRestoringState.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
WrapAccount(
|
WrapAccount(
|
||||||
context = activity.applicationContext,
|
context = activity.applicationContext,
|
||||||
goBalances = goBalances,
|
goBalances = goBalances,
|
||||||
goSettings = goSettings,
|
goSettings = goSettings,
|
||||||
isKeepScreenOnWhileSyncing = isKeepScreenOnWhileSyncing,
|
|
||||||
scope = scope,
|
scope = scope,
|
||||||
synchronizer = synchronizer,
|
synchronizer = synchronizer,
|
||||||
transactionHistoryViewModel = transactionHistoryViewModel,
|
transactionHistoryViewModel = transactionHistoryViewModel,
|
||||||
transactionsUiState = transactionsUiState,
|
transactionsUiState = transactionsUiState,
|
||||||
walletSnapshot = walletSnapshot,
|
walletSnapshot = walletSnapshot,
|
||||||
|
walletRestoringState = walletRestoringState
|
||||||
)
|
)
|
||||||
|
|
||||||
// For benchmarking purposes
|
// For benchmarking purposes
|
||||||
|
@ -78,7 +76,7 @@ internal fun WrapAccount(
|
||||||
synchronizer: Synchronizer?,
|
synchronizer: Synchronizer?,
|
||||||
transactionHistoryViewModel: TransactionHistoryViewModel,
|
transactionHistoryViewModel: TransactionHistoryViewModel,
|
||||||
walletSnapshot: WalletSnapshot?,
|
walletSnapshot: WalletSnapshot?,
|
||||||
isKeepScreenOnWhileSyncing: Boolean?,
|
walletRestoringState: WalletRestoringState,
|
||||||
) {
|
) {
|
||||||
if (null == synchronizer || null == walletSnapshot) {
|
if (null == synchronizer || null == walletSnapshot) {
|
||||||
// TODO [#1146]: Consider moving CircularScreenProgressIndicator from Android layer to View layer
|
// TODO [#1146]: Consider moving CircularScreenProgressIndicator from Android layer to View layer
|
||||||
|
@ -88,7 +86,6 @@ internal fun WrapAccount(
|
||||||
} else {
|
} else {
|
||||||
Account(
|
Account(
|
||||||
walletSnapshot = walletSnapshot,
|
walletSnapshot = walletSnapshot,
|
||||||
isKeepScreenOnWhileSyncing = isKeepScreenOnWhileSyncing,
|
|
||||||
transactionsUiState = transactionsUiState,
|
transactionsUiState = transactionsUiState,
|
||||||
onTransactionItemAction = { action ->
|
onTransactionItemAction = { action ->
|
||||||
when (action) {
|
when (action) {
|
||||||
|
@ -130,6 +127,7 @@ internal fun WrapAccount(
|
||||||
},
|
},
|
||||||
goBalances = goBalances,
|
goBalances = goBalances,
|
||||||
goSettings = goSettings,
|
goSettings = goSettings,
|
||||||
|
walletRestoringState = walletRestoringState
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,13 @@ import kotlinx.collections.immutable.ImmutableList
|
||||||
sealed interface TransactionUiState {
|
sealed interface TransactionUiState {
|
||||||
data object Loading : TransactionUiState
|
data object Loading : TransactionUiState
|
||||||
|
|
||||||
data object Syncing : TransactionUiState
|
data object SyncingEmpty : TransactionUiState
|
||||||
|
|
||||||
data class Prepared(val transactions: ImmutableList<TransactionUi>) : TransactionUiState
|
data object DoneEmpty : TransactionUiState
|
||||||
|
|
||||||
|
sealed class Prepared(open val transactions: ImmutableList<TransactionUi>) : TransactionUiState
|
||||||
|
|
||||||
|
data class Syncing(override val transactions: ImmutableList<TransactionUi>) : Prepared(transactions)
|
||||||
|
|
||||||
|
data class Done(override val transactions: ImmutableList<TransactionUi>) : Prepared(transactions)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,7 @@ import kotlinx.collections.immutable.ImmutableList
|
||||||
sealed interface TransactionHistorySyncState {
|
sealed interface TransactionHistorySyncState {
|
||||||
data object Loading : TransactionHistorySyncState
|
data object Loading : TransactionHistorySyncState
|
||||||
|
|
||||||
sealed class Prepared(open val transactions: ImmutableList<TransactionOverviewExt>) : TransactionHistorySyncState
|
data class Syncing(val transactions: ImmutableList<TransactionOverviewExt>) : TransactionHistorySyncState
|
||||||
|
|
||||||
data class Syncing(override val transactions: ImmutableList<TransactionOverviewExt>) : Prepared(transactions)
|
data class Done(val transactions: ImmutableList<TransactionOverviewExt>) : TransactionHistorySyncState
|
||||||
|
|
||||||
data class Done(override val transactions: ImmutableList<TransactionOverviewExt>) : Prepared(transactions)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,9 @@ import androidx.compose.ui.platform.testTag
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import cash.z.ecc.android.sdk.Synchronizer
|
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
import co.electriccoin.zcash.ui.common.compose.BalanceWidget
|
import co.electriccoin.zcash.ui.common.compose.BalanceWidget
|
||||||
import co.electriccoin.zcash.ui.common.compose.DisableScreenTimeout
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
||||||
import co.electriccoin.zcash.ui.common.test.CommonTag
|
import co.electriccoin.zcash.ui.common.test.CommonTag
|
||||||
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
||||||
|
@ -36,11 +35,11 @@ private fun HistoryLoadingComposablePreview() {
|
||||||
GradientSurface {
|
GradientSurface {
|
||||||
Account(
|
Account(
|
||||||
walletSnapshot = WalletSnapshotFixture.new(),
|
walletSnapshot = WalletSnapshotFixture.new(),
|
||||||
isKeepScreenOnWhileSyncing = false,
|
|
||||||
goBalances = {},
|
goBalances = {},
|
||||||
goSettings = {},
|
goSettings = {},
|
||||||
transactionsUiState = TransactionUiState.Loading,
|
transactionsUiState = TransactionUiState.Loading,
|
||||||
onTransactionItemAction = {}
|
onTransactionItemAction = {},
|
||||||
|
walletRestoringState = WalletRestoringState.SYNCING
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,11 +53,11 @@ private fun HistoryListComposablePreview() {
|
||||||
@Suppress("MagicNumber")
|
@Suppress("MagicNumber")
|
||||||
Account(
|
Account(
|
||||||
walletSnapshot = WalletSnapshotFixture.new(),
|
walletSnapshot = WalletSnapshotFixture.new(),
|
||||||
isKeepScreenOnWhileSyncing = false,
|
|
||||||
goBalances = {},
|
goBalances = {},
|
||||||
goSettings = {},
|
goSettings = {},
|
||||||
transactionsUiState = TransactionUiState.Prepared(transactions = TransactionsFixture.new()),
|
transactionsUiState = TransactionUiState.Done(transactions = TransactionsFixture.new()),
|
||||||
onTransactionItemAction = {},
|
onTransactionItemAction = {},
|
||||||
|
walletRestoringState = WalletRestoringState.NONE
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,19 +68,22 @@ private fun HistoryListComposablePreview() {
|
||||||
internal fun Account(
|
internal fun Account(
|
||||||
goBalances: () -> Unit,
|
goBalances: () -> Unit,
|
||||||
goSettings: () -> Unit,
|
goSettings: () -> Unit,
|
||||||
isKeepScreenOnWhileSyncing: Boolean?,
|
|
||||||
onTransactionItemAction: (TrxItemAction) -> Unit,
|
onTransactionItemAction: (TrxItemAction) -> Unit,
|
||||||
transactionsUiState: TransactionUiState,
|
transactionsUiState: TransactionUiState,
|
||||||
|
walletRestoringState: WalletRestoringState,
|
||||||
walletSnapshot: WalletSnapshot,
|
walletSnapshot: WalletSnapshot,
|
||||||
) {
|
) {
|
||||||
Scaffold(topBar = {
|
Scaffold(topBar = {
|
||||||
AccountTopAppBar(onSettings = goSettings)
|
AccountTopAppBar(
|
||||||
|
showRestoring = walletRestoringState == WalletRestoringState.RESTORING,
|
||||||
|
onSettings = goSettings
|
||||||
|
)
|
||||||
}) { paddingValues ->
|
}) { paddingValues ->
|
||||||
AccountMainContent(
|
AccountMainContent(
|
||||||
walletSnapshot = walletSnapshot,
|
walletSnapshot = walletSnapshot,
|
||||||
isKeepScreenOnWhileSyncing = isKeepScreenOnWhileSyncing,
|
|
||||||
goBalances = goBalances,
|
goBalances = goBalances,
|
||||||
transactionState = transactionsUiState,
|
transactionState = transactionsUiState,
|
||||||
|
walletRestoringState = walletRestoringState,
|
||||||
onTransactionItemAction = onTransactionItemAction,
|
onTransactionItemAction = onTransactionItemAction,
|
||||||
modifier =
|
modifier =
|
||||||
Modifier.padding(
|
Modifier.padding(
|
||||||
|
@ -94,8 +96,17 @@ internal fun Account(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun AccountTopAppBar(onSettings: () -> Unit) {
|
private fun AccountTopAppBar(
|
||||||
|
onSettings: () -> Unit,
|
||||||
|
showRestoring: Boolean
|
||||||
|
) {
|
||||||
SmallTopAppBar(
|
SmallTopAppBar(
|
||||||
|
restoringLabel =
|
||||||
|
if (showRestoring) {
|
||||||
|
stringResource(id = R.string.restoring_wallet_label)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
},
|
||||||
showTitleLogo = true,
|
showTitleLogo = true,
|
||||||
hamburgerMenuActions = {
|
hamburgerMenuActions = {
|
||||||
IconButton(
|
IconButton(
|
||||||
|
@ -115,11 +126,11 @@ private fun AccountTopAppBar(onSettings: () -> Unit) {
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
private fun AccountMainContent(
|
private fun AccountMainContent(
|
||||||
walletSnapshot: WalletSnapshot,
|
walletSnapshot: WalletSnapshot,
|
||||||
isKeepScreenOnWhileSyncing: Boolean?,
|
|
||||||
goBalances: () -> Unit,
|
goBalances: () -> Unit,
|
||||||
onTransactionItemAction: (TrxItemAction) -> Unit,
|
onTransactionItemAction: (TrxItemAction) -> Unit,
|
||||||
transactionState: TransactionUiState,
|
transactionState: TransactionUiState,
|
||||||
modifier: Modifier = Modifier
|
walletRestoringState: WalletRestoringState,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
|
@ -139,12 +150,9 @@ private fun AccountMainContent(
|
||||||
|
|
||||||
HistoryContainer(
|
HistoryContainer(
|
||||||
transactionState = transactionState,
|
transactionState = transactionState,
|
||||||
|
walletRestoringState = walletRestoringState,
|
||||||
onTransactionItemAction = onTransactionItemAction,
|
onTransactionItemAction = onTransactionItemAction,
|
||||||
)
|
)
|
||||||
|
|
||||||
if (isKeepScreenOnWhileSyncing == true && walletSnapshot.status == Synchronizer.Status.SYNCING) {
|
|
||||||
DisableScreenTimeout()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ import cash.z.ecc.android.sdk.model.TransactionState
|
||||||
import cash.z.ecc.android.sdk.model.Zatoshi
|
import cash.z.ecc.android.sdk.model.Zatoshi
|
||||||
import cash.z.ecc.android.sdk.model.toZecString
|
import cash.z.ecc.android.sdk.model.toZecString
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.design.component.CircularMidProgressIndicator
|
import co.electriccoin.zcash.ui.design.component.CircularMidProgressIndicator
|
||||||
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
||||||
import co.electriccoin.zcash.ui.design.component.StyledBalance
|
import co.electriccoin.zcash.ui.design.component.StyledBalance
|
||||||
|
@ -70,7 +71,8 @@ private fun ComposablePreview() {
|
||||||
GradientSurface {
|
GradientSurface {
|
||||||
HistoryContainer(
|
HistoryContainer(
|
||||||
transactionState = TransactionUiState.Loading,
|
transactionState = TransactionUiState.Loading,
|
||||||
onTransactionItemAction = {}
|
onTransactionItemAction = {},
|
||||||
|
walletRestoringState = WalletRestoringState.SYNCING
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,8 +84,9 @@ private fun ComposableHistoryListPreview() {
|
||||||
ZcashTheme(forceDarkMode = false) {
|
ZcashTheme(forceDarkMode = false) {
|
||||||
GradientSurface {
|
GradientSurface {
|
||||||
HistoryContainer(
|
HistoryContainer(
|
||||||
transactionState = TransactionUiState.Prepared(transactions = TransactionsFixture.new()),
|
transactionState = TransactionUiState.Done(transactions = TransactionsFixture.new()),
|
||||||
onTransactionItemAction = {}
|
onTransactionItemAction = {},
|
||||||
|
walletRestoringState = WalletRestoringState.NONE
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,7 +105,8 @@ private val dateFormat: DateFormat by lazy {
|
||||||
internal fun HistoryContainer(
|
internal fun HistoryContainer(
|
||||||
transactionState: TransactionUiState,
|
transactionState: TransactionUiState,
|
||||||
onTransactionItemAction: (TrxItemAction) -> Unit,
|
onTransactionItemAction: (TrxItemAction) -> Unit,
|
||||||
modifier: Modifier = Modifier
|
walletRestoringState: WalletRestoringState,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier =
|
modifier =
|
||||||
|
@ -114,21 +118,49 @@ internal fun HistoryContainer(
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
when (transactionState) {
|
when (transactionState) {
|
||||||
TransactionUiState.Loading, TransactionUiState.Syncing -> {
|
TransactionUiState.Loading -> {
|
||||||
|
LoadingTransactionHistory()
|
||||||
|
}
|
||||||
|
TransactionUiState.SyncingEmpty -> {
|
||||||
|
if (walletRestoringState == WalletRestoringState.INITIATING) {
|
||||||
|
// In case we are syncing a new wallet, it's empty
|
||||||
|
EmptyTransactionHistory()
|
||||||
|
} else {
|
||||||
|
// Intentionally leaving the UI empty otherwise
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is TransactionUiState.Prepared -> {
|
||||||
|
HistoryList(
|
||||||
|
transactions = transactionState.transactions,
|
||||||
|
onAction = onTransactionItemAction,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is TransactionUiState.DoneEmpty -> {
|
||||||
|
EmptyTransactionHistory()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun LoadingTransactionHistory() {
|
||||||
Column(
|
Column(
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
) {
|
) {
|
||||||
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingUpLarge))
|
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingUpLarge))
|
||||||
|
|
||||||
CircularMidProgressIndicator(
|
CircularMidProgressIndicator(
|
||||||
modifier = Modifier.testTag(HistoryTag.PROGRESS),
|
modifier = Modifier.testTag(HistoryTag.PROGRESS),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is TransactionUiState.Prepared -> {
|
|
||||||
if (transactionState.transactions.isEmpty()) {
|
@Composable
|
||||||
|
private fun EmptyTransactionHistory() {
|
||||||
Column {
|
Column {
|
||||||
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingUpLarge))
|
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingUpLarge))
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
|
@ -136,18 +168,9 @@ internal fun HistoryContainer(
|
||||||
style = ZcashTheme.extendedTypography.transactionItemStyles.titleRegular,
|
style = ZcashTheme.extendedTypography.transactionItemStyles.titleRegular,
|
||||||
color = ZcashTheme.colors.textCommon,
|
color = ZcashTheme.colors.textCommon,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
HistoryList(
|
|
||||||
transactions = transactionState.transactions,
|
|
||||||
onAction = onTransactionItemAction,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
|
@ -8,6 +8,7 @@ import cash.z.ecc.android.sdk.internal.Twig
|
||||||
import cash.z.ecc.android.sdk.model.FirstClassByteArray
|
import cash.z.ecc.android.sdk.model.FirstClassByteArray
|
||||||
import cash.z.ecc.android.sdk.model.TransactionOverview
|
import cash.z.ecc.android.sdk.model.TransactionOverview
|
||||||
import co.electriccoin.zcash.ui.common.ANDROID_STATE_FLOW_TIMEOUT
|
import co.electriccoin.zcash.ui.common.ANDROID_STATE_FLOW_TIMEOUT
|
||||||
|
import co.electriccoin.zcash.ui.screen.account.ext.TransactionOverviewExt
|
||||||
import co.electriccoin.zcash.ui.screen.account.model.TransactionUi
|
import co.electriccoin.zcash.ui.screen.account.model.TransactionUi
|
||||||
import co.electriccoin.zcash.ui.screen.account.model.TransactionUiState
|
import co.electriccoin.zcash.ui.screen.account.model.TransactionUiState
|
||||||
import co.electriccoin.zcash.ui.screen.account.model.TrxItemState
|
import co.electriccoin.zcash.ui.screen.account.model.TrxItemState
|
||||||
|
@ -19,19 +20,23 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.WhileSubscribed
|
import kotlinx.coroutines.flow.WhileSubscribed
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
import kotlinx.coroutines.flow.toList
|
import kotlinx.coroutines.flow.toList
|
||||||
|
|
||||||
class TransactionHistoryViewModel(application: Application) : AndroidViewModel(application) {
|
class TransactionHistoryViewModel(application: Application) : AndroidViewModel(application) {
|
||||||
|
private val state: MutableStateFlow<State> = MutableStateFlow(State.LOADING)
|
||||||
|
|
||||||
private val transactions: MutableStateFlow<ImmutableList<TransactionUi>> = MutableStateFlow(persistentListOf())
|
private val transactions: MutableStateFlow<ImmutableList<TransactionUi>> = MutableStateFlow(persistentListOf())
|
||||||
|
|
||||||
val transactionUiState: StateFlow<TransactionUiState> =
|
val transactionUiState: StateFlow<TransactionUiState> =
|
||||||
transactions.map {
|
state.combine(transactions) { state: State, transactions: ImmutableList<TransactionUi> ->
|
||||||
if (it.isEmpty()) {
|
when (state) {
|
||||||
TransactionUiState.Syncing
|
State.LOADING -> TransactionUiState.Loading
|
||||||
} else {
|
State.SYNCING -> TransactionUiState.Syncing(transactions)
|
||||||
TransactionUiState.Prepared(it)
|
State.SYNCING_EMPTY -> TransactionUiState.SyncingEmpty
|
||||||
|
State.DONE -> TransactionUiState.Done(transactions)
|
||||||
|
State.DONE_EMPTY -> TransactionUiState.DoneEmpty
|
||||||
}
|
}
|
||||||
}.stateIn(
|
}.stateIn(
|
||||||
viewModelScope,
|
viewModelScope,
|
||||||
|
@ -40,26 +45,49 @@ class TransactionHistoryViewModel(application: Application) : AndroidViewModel(a
|
||||||
)
|
)
|
||||||
|
|
||||||
fun processTransactionState(dataState: TransactionHistorySyncState) {
|
fun processTransactionState(dataState: TransactionHistorySyncState) {
|
||||||
transactions.value =
|
|
||||||
when (dataState) {
|
when (dataState) {
|
||||||
TransactionHistorySyncState.Loading -> persistentListOf()
|
TransactionHistorySyncState.Loading -> {
|
||||||
is TransactionHistorySyncState.Prepared -> {
|
state.value = State.LOADING
|
||||||
dataState.transactions.map { data ->
|
transactions.value = persistentListOf()
|
||||||
val existingTransaction =
|
}
|
||||||
transactions.value.find {
|
is TransactionHistorySyncState.Syncing -> {
|
||||||
data.overview.rawId == it.overview.rawId
|
if (dataState.transactions.isEmpty()) {
|
||||||
|
state.value = State.SYNCING_EMPTY
|
||||||
|
} else {
|
||||||
|
state.value = State.SYNCING
|
||||||
|
transactions.value =
|
||||||
|
dataState.transactions
|
||||||
|
.map { data -> getOrUpdateTransactionItem(data) }
|
||||||
|
.toPersistentList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is TransactionHistorySyncState.Done -> {
|
||||||
|
if (dataState.transactions.isEmpty()) {
|
||||||
|
state.value = State.DONE_EMPTY
|
||||||
|
} else {
|
||||||
|
state.value = State.DONE
|
||||||
|
transactions.value =
|
||||||
|
dataState.transactions
|
||||||
|
.map { data -> getOrUpdateTransactionItem(data) }
|
||||||
|
.toPersistentList()
|
||||||
}
|
}
|
||||||
TransactionUi.new(
|
|
||||||
data = data,
|
|
||||||
expandableState = existingTransaction?.expandableState ?: TrxItemState.COLLAPSED,
|
|
||||||
messages = existingTransaction?.messages,
|
|
||||||
)
|
|
||||||
}.toPersistentList()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateTransaction(newTransaction: TransactionUi) {
|
private fun getOrUpdateTransactionItem(data: TransactionOverviewExt): TransactionUi {
|
||||||
|
val existingTransaction =
|
||||||
|
transactions.value.find {
|
||||||
|
data.overview.rawId == it.overview.rawId
|
||||||
|
}
|
||||||
|
return TransactionUi.new(
|
||||||
|
data = data,
|
||||||
|
expandableState = existingTransaction?.expandableState ?: TrxItemState.COLLAPSED,
|
||||||
|
messages = existingTransaction?.messages,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateTransactionInList(newTransaction: TransactionUi) {
|
||||||
transactions.value =
|
transactions.value =
|
||||||
transactions.value.map { item ->
|
transactions.value.map { item ->
|
||||||
if (item.overview.rawId == newTransaction.overview.rawId) {
|
if (item.overview.rawId == newTransaction.overview.rawId) {
|
||||||
|
@ -87,7 +115,7 @@ class TransactionHistoryViewModel(application: Application) : AndroidViewModel(a
|
||||||
val messages = loadMessageForTransaction(synchronizer, updated.overview)
|
val messages = loadMessageForTransaction(synchronizer, updated.overview)
|
||||||
updatedWithMessages = updated.copy(messages = messages)
|
updatedWithMessages = updated.copy(messages = messages)
|
||||||
}
|
}
|
||||||
updateTransaction(updatedWithMessages)
|
updateTransactionInList(updatedWithMessages)
|
||||||
} else {
|
} else {
|
||||||
Twig.warn { "Transaction not found" }
|
Twig.warn { "Transaction not found" }
|
||||||
}
|
}
|
||||||
|
@ -101,3 +129,11 @@ class TransactionHistoryViewModel(application: Application) : AndroidViewModel(a
|
||||||
Twig.info { "Transaction messages count: ${it.size}" }
|
Twig.info { "Transaction messages count: ${it.size}" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private enum class State {
|
||||||
|
LOADING,
|
||||||
|
SYNCING,
|
||||||
|
SYNCING_EMPTY,
|
||||||
|
DONE,
|
||||||
|
DONE_EMPTY,
|
||||||
|
}
|
||||||
|
|
|
@ -3,31 +3,41 @@
|
||||||
package co.electriccoin.zcash.ui.screen.advancedsettings
|
package co.electriccoin.zcash.ui.screen.advancedsettings
|
||||||
|
|
||||||
import androidx.activity.compose.BackHandler
|
import androidx.activity.compose.BackHandler
|
||||||
|
import androidx.activity.viewModels
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
|
import co.electriccoin.zcash.ui.MainActivity
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
|
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||||
import co.electriccoin.zcash.ui.screen.advancedsettings.view.AdvancedSettings
|
import co.electriccoin.zcash.ui.screen.advancedsettings.view.AdvancedSettings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun WrapAdvancedSettings(
|
internal fun MainActivity.WrapAdvancedSettings(
|
||||||
goBack: () -> Unit,
|
goBack: () -> Unit,
|
||||||
goExportPrivateData: () -> Unit,
|
goExportPrivateData: () -> Unit,
|
||||||
goSeedRecovery: () -> Unit,
|
goSeedRecovery: () -> Unit,
|
||||||
goChooseServer: () -> Unit,
|
goChooseServer: () -> Unit,
|
||||||
) {
|
) {
|
||||||
WrapSettings(
|
val walletViewModel by viewModels<WalletViewModel>()
|
||||||
|
|
||||||
|
val walletRestoringState = walletViewModel.walletRestoringState.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
|
WrapAdvancedSettings(
|
||||||
goBack = goBack,
|
goBack = goBack,
|
||||||
goExportPrivateData = goExportPrivateData,
|
goExportPrivateData = goExportPrivateData,
|
||||||
goChooseServer = goChooseServer,
|
goChooseServer = goChooseServer,
|
||||||
goSeedRecovery = goSeedRecovery,
|
goSeedRecovery = goSeedRecovery,
|
||||||
|
walletRestoringState = walletRestoringState
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@Suppress("LongParameterList")
|
private fun WrapAdvancedSettings(
|
||||||
private fun WrapSettings(
|
|
||||||
goBack: () -> Unit,
|
goBack: () -> Unit,
|
||||||
goExportPrivateData: () -> Unit,
|
goExportPrivateData: () -> Unit,
|
||||||
goChooseServer: () -> Unit,
|
goChooseServer: () -> Unit,
|
||||||
goSeedRecovery: () -> Unit,
|
goSeedRecovery: () -> Unit,
|
||||||
|
walletRestoringState: WalletRestoringState,
|
||||||
) {
|
) {
|
||||||
BackHandler {
|
BackHandler {
|
||||||
goBack()
|
goBack()
|
||||||
|
@ -37,6 +47,7 @@ private fun WrapSettings(
|
||||||
onBack = goBack,
|
onBack = goBack,
|
||||||
onSeedRecovery = goSeedRecovery,
|
onSeedRecovery = goSeedRecovery,
|
||||||
onExportPrivateData = goExportPrivateData,
|
onExportPrivateData = goExportPrivateData,
|
||||||
onChooseServer = goChooseServer
|
onChooseServer = goChooseServer,
|
||||||
|
walletRestoringState = walletRestoringState,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import androidx.compose.ui.platform.testTag
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
||||||
import co.electriccoin.zcash.ui.design.component.PrimaryButton
|
import co.electriccoin.zcash.ui.design.component.PrimaryButton
|
||||||
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
|
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
|
||||||
|
@ -34,8 +35,9 @@ private fun PreviewAdvancedSettings() {
|
||||||
AdvancedSettings(
|
AdvancedSettings(
|
||||||
onBack = {},
|
onBack = {},
|
||||||
onExportPrivateData = {},
|
onExportPrivateData = {},
|
||||||
onSeedRecovery = {},
|
|
||||||
onChooseServer = {},
|
onChooseServer = {},
|
||||||
|
onSeedRecovery = {},
|
||||||
|
walletRestoringState = WalletRestoringState.NONE,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,10 +49,12 @@ fun AdvancedSettings(
|
||||||
onExportPrivateData: () -> Unit,
|
onExportPrivateData: () -> Unit,
|
||||||
onChooseServer: () -> Unit,
|
onChooseServer: () -> Unit,
|
||||||
onSeedRecovery: () -> Unit,
|
onSeedRecovery: () -> Unit,
|
||||||
|
walletRestoringState: WalletRestoringState,
|
||||||
) {
|
) {
|
||||||
Scaffold(topBar = {
|
Scaffold(topBar = {
|
||||||
AdvancedSettingsTopAppBar(
|
AdvancedSettingsTopAppBar(
|
||||||
onBack = onBack,
|
onBack = onBack,
|
||||||
|
showRestoring = walletRestoringState == WalletRestoringState.RESTORING,
|
||||||
)
|
)
|
||||||
}) { paddingValues ->
|
}) { paddingValues ->
|
||||||
AdvancedSettingsMainContent(
|
AdvancedSettingsMainContent(
|
||||||
|
@ -73,13 +77,22 @@ fun AdvancedSettings(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun AdvancedSettingsTopAppBar(onBack: () -> Unit) {
|
private fun AdvancedSettingsTopAppBar(
|
||||||
|
onBack: () -> Unit,
|
||||||
|
showRestoring: Boolean
|
||||||
|
) {
|
||||||
SmallTopAppBar(
|
SmallTopAppBar(
|
||||||
|
restoringLabel =
|
||||||
|
if (showRestoring) {
|
||||||
|
stringResource(id = R.string.restoring_wallet_label)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
},
|
||||||
|
modifier = Modifier.testTag(AdvancedSettingsTag.ADVANCED_SETTINGS_TOP_APP_BAR),
|
||||||
|
showTitleLogo = true,
|
||||||
backText = stringResource(id = R.string.advanced_settings_back).uppercase(),
|
backText = stringResource(id = R.string.advanced_settings_back).uppercase(),
|
||||||
backContentDescriptionText = stringResource(R.string.advanced_settings_back_content_description),
|
backContentDescriptionText = stringResource(R.string.advanced_settings_back_content_description),
|
||||||
onBack = onBack,
|
onBack = onBack,
|
||||||
showTitleLogo = true,
|
|
||||||
modifier = Modifier.testTag(AdvancedSettingsTag.ADVANCED_SETTINGS_TOP_APP_BAR)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ import cash.z.ecc.android.sdk.Synchronizer
|
||||||
import cash.z.ecc.android.sdk.model.UnifiedSpendingKey
|
import cash.z.ecc.android.sdk.model.UnifiedSpendingKey
|
||||||
import cash.z.ecc.android.sdk.model.Zatoshi
|
import cash.z.ecc.android.sdk.model.Zatoshi
|
||||||
import co.electriccoin.zcash.spackle.Twig
|
import co.electriccoin.zcash.spackle.Twig
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
||||||
import co.electriccoin.zcash.ui.common.viewmodel.CheckUpdateViewModel
|
import co.electriccoin.zcash.ui.common.viewmodel.CheckUpdateViewModel
|
||||||
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||||
|
@ -24,7 +25,6 @@ import co.electriccoin.zcash.ui.screen.balances.model.ShieldState
|
||||||
import co.electriccoin.zcash.ui.screen.balances.view.Balances
|
import co.electriccoin.zcash.ui.screen.balances.view.Balances
|
||||||
import co.electriccoin.zcash.ui.screen.sendconfirmation.model.SubmitResult
|
import co.electriccoin.zcash.ui.screen.sendconfirmation.model.SubmitResult
|
||||||
import co.electriccoin.zcash.ui.screen.sendconfirmation.viewmodel.CreateTransactionsViewModel
|
import co.electriccoin.zcash.ui.screen.sendconfirmation.viewmodel.CreateTransactionsViewModel
|
||||||
import co.electriccoin.zcash.ui.screen.settings.viewmodel.SettingsViewModel
|
|
||||||
import co.electriccoin.zcash.ui.screen.update.AppUpdateCheckerImp
|
import co.electriccoin.zcash.ui.screen.update.AppUpdateCheckerImp
|
||||||
import co.electriccoin.zcash.ui.screen.update.model.UpdateState
|
import co.electriccoin.zcash.ui.screen.update.model.UpdateState
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
@ -47,6 +47,8 @@ internal fun WrapBalances(
|
||||||
|
|
||||||
val spendingKey = walletViewModel.spendingKey.collectAsStateWithLifecycle().value
|
val spendingKey = walletViewModel.spendingKey.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
|
val walletRestoringState = walletViewModel.walletRestoringState.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
val checkUpdateViewModel by activity.viewModels<CheckUpdateViewModel> {
|
val checkUpdateViewModel by activity.viewModels<CheckUpdateViewModel> {
|
||||||
CheckUpdateViewModel.CheckUpdateViewModelFactory(
|
CheckUpdateViewModel.CheckUpdateViewModelFactory(
|
||||||
activity.application,
|
activity.application,
|
||||||
|
@ -54,17 +56,15 @@ internal fun WrapBalances(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val settingsViewModel by activity.viewModels<SettingsViewModel>()
|
|
||||||
|
|
||||||
WrapBalances(
|
WrapBalances(
|
||||||
checkUpdateViewModel = checkUpdateViewModel,
|
checkUpdateViewModel = checkUpdateViewModel,
|
||||||
createTransactionsViewModel = createTransactionsViewModel,
|
createTransactionsViewModel = createTransactionsViewModel,
|
||||||
goSettings = goSettings,
|
goSettings = goSettings,
|
||||||
goMultiTrxSubmissionFailure = goMultiTrxSubmissionFailure,
|
goMultiTrxSubmissionFailure = goMultiTrxSubmissionFailure,
|
||||||
spendingKey = spendingKey,
|
spendingKey = spendingKey,
|
||||||
settingsViewModel = settingsViewModel,
|
|
||||||
synchronizer = synchronizer,
|
synchronizer = synchronizer,
|
||||||
walletSnapshot = walletSnapshot
|
walletSnapshot = walletSnapshot,
|
||||||
|
walletRestoringState = walletRestoringState,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,10 +78,10 @@ internal fun WrapBalances(
|
||||||
createTransactionsViewModel: CreateTransactionsViewModel,
|
createTransactionsViewModel: CreateTransactionsViewModel,
|
||||||
goSettings: () -> Unit,
|
goSettings: () -> Unit,
|
||||||
goMultiTrxSubmissionFailure: () -> Unit,
|
goMultiTrxSubmissionFailure: () -> Unit,
|
||||||
settingsViewModel: SettingsViewModel,
|
|
||||||
spendingKey: UnifiedSpendingKey?,
|
spendingKey: UnifiedSpendingKey?,
|
||||||
synchronizer: Synchronizer?,
|
synchronizer: Synchronizer?,
|
||||||
walletSnapshot: WalletSnapshot?,
|
walletSnapshot: WalletSnapshot?,
|
||||||
|
walletRestoringState: WalletRestoringState,
|
||||||
) {
|
) {
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
@ -91,8 +91,6 @@ internal fun WrapBalances(
|
||||||
it?.appUpdateInfo != null && it.state == UpdateState.Prepared
|
it?.appUpdateInfo != null && it.state == UpdateState.Prepared
|
||||||
}
|
}
|
||||||
|
|
||||||
val isKeepScreenOnWhileSyncing = settingsViewModel.isKeepScreenOnWhileSyncing.collectAsStateWithLifecycle().value
|
|
||||||
|
|
||||||
val isFiatConversionEnabled = ConfigurationEntries.IS_FIAT_CONVERSION_ENABLED.getValue(RemoteConfig.current)
|
val isFiatConversionEnabled = ConfigurationEntries.IS_FIAT_CONVERSION_ENABLED.getValue(RemoteConfig.current)
|
||||||
|
|
||||||
val (shieldState, setShieldState) =
|
val (shieldState, setShieldState) =
|
||||||
|
@ -128,7 +126,6 @@ internal fun WrapBalances(
|
||||||
Balances(
|
Balances(
|
||||||
onSettings = goSettings,
|
onSettings = goSettings,
|
||||||
isFiatConversionEnabled = isFiatConversionEnabled,
|
isFiatConversionEnabled = isFiatConversionEnabled,
|
||||||
isKeepScreenOnWhileSyncing = isKeepScreenOnWhileSyncing,
|
|
||||||
isUpdateAvailable = isUpdateAvailable,
|
isUpdateAvailable = isUpdateAvailable,
|
||||||
isShowingErrorDialog = isShowingErrorDialog,
|
isShowingErrorDialog = isShowingErrorDialog,
|
||||||
setShowErrorDialog = setShowErrorDialog,
|
setShowErrorDialog = setShowErrorDialog,
|
||||||
|
@ -187,6 +184,7 @@ internal fun WrapBalances(
|
||||||
},
|
},
|
||||||
shieldState = shieldState,
|
shieldState = shieldState,
|
||||||
walletSnapshot = walletSnapshot,
|
walletSnapshot = walletSnapshot,
|
||||||
|
walletRestoringState = walletRestoringState,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,14 +47,13 @@ import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import cash.z.ecc.android.sdk.Synchronizer
|
|
||||||
import cash.z.ecc.android.sdk.model.FiatCurrencyConversionRateState
|
import cash.z.ecc.android.sdk.model.FiatCurrencyConversionRateState
|
||||||
import cash.z.ecc.android.sdk.model.Zatoshi
|
import cash.z.ecc.android.sdk.model.Zatoshi
|
||||||
import cash.z.ecc.android.sdk.model.toZecString
|
import cash.z.ecc.android.sdk.model.toZecString
|
||||||
import cash.z.ecc.sdk.extension.toPercentageWithDecimal
|
import cash.z.ecc.sdk.extension.toPercentageWithDecimal
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
import co.electriccoin.zcash.ui.common.compose.BalanceWidget
|
import co.electriccoin.zcash.ui.common.compose.BalanceWidget
|
||||||
import co.electriccoin.zcash.ui.common.compose.DisableScreenTimeout
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
||||||
import co.electriccoin.zcash.ui.common.model.changePendingBalance
|
import co.electriccoin.zcash.ui.common.model.changePendingBalance
|
||||||
import co.electriccoin.zcash.ui.common.model.spendableBalance
|
import co.electriccoin.zcash.ui.common.model.spendableBalance
|
||||||
|
@ -86,13 +85,13 @@ private fun ComposableBalancesPreview() {
|
||||||
Balances(
|
Balances(
|
||||||
onSettings = {},
|
onSettings = {},
|
||||||
isFiatConversionEnabled = false,
|
isFiatConversionEnabled = false,
|
||||||
isKeepScreenOnWhileSyncing = false,
|
|
||||||
isUpdateAvailable = false,
|
isUpdateAvailable = false,
|
||||||
|
isShowingErrorDialog = false,
|
||||||
|
setShowErrorDialog = {},
|
||||||
onShielding = {},
|
onShielding = {},
|
||||||
shieldState = ShieldState.Available,
|
shieldState = ShieldState.Available,
|
||||||
walletSnapshot = WalletSnapshotFixture.new(),
|
walletSnapshot = WalletSnapshotFixture.new(),
|
||||||
isShowingErrorDialog = false,
|
walletRestoringState = WalletRestoringState.NONE,
|
||||||
setShowErrorDialog = {},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,13 +105,13 @@ private fun ComposableBalancesShieldFailurePreview() {
|
||||||
Balances(
|
Balances(
|
||||||
onSettings = {},
|
onSettings = {},
|
||||||
isFiatConversionEnabled = false,
|
isFiatConversionEnabled = false,
|
||||||
isKeepScreenOnWhileSyncing = false,
|
|
||||||
isUpdateAvailable = false,
|
isUpdateAvailable = false,
|
||||||
|
isShowingErrorDialog = true,
|
||||||
|
setShowErrorDialog = {},
|
||||||
onShielding = {},
|
onShielding = {},
|
||||||
shieldState = ShieldState.Available,
|
shieldState = ShieldState.Available,
|
||||||
walletSnapshot = WalletSnapshotFixture.new(),
|
walletSnapshot = WalletSnapshotFixture.new(),
|
||||||
isShowingErrorDialog = true,
|
walletRestoringState = WalletRestoringState.NONE,
|
||||||
setShowErrorDialog = {},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,23 +122,25 @@ private fun ComposableBalancesShieldFailurePreview() {
|
||||||
fun Balances(
|
fun Balances(
|
||||||
onSettings: () -> Unit,
|
onSettings: () -> Unit,
|
||||||
isFiatConversionEnabled: Boolean,
|
isFiatConversionEnabled: Boolean,
|
||||||
isKeepScreenOnWhileSyncing: Boolean?,
|
|
||||||
isUpdateAvailable: Boolean,
|
isUpdateAvailable: Boolean,
|
||||||
isShowingErrorDialog: Boolean,
|
isShowingErrorDialog: Boolean,
|
||||||
setShowErrorDialog: (Boolean) -> Unit,
|
setShowErrorDialog: (Boolean) -> Unit,
|
||||||
onShielding: () -> Unit,
|
onShielding: () -> Unit,
|
||||||
shieldState: ShieldState,
|
shieldState: ShieldState,
|
||||||
walletSnapshot: WalletSnapshot?,
|
walletSnapshot: WalletSnapshot?,
|
||||||
|
walletRestoringState: WalletRestoringState,
|
||||||
) {
|
) {
|
||||||
Scaffold(topBar = {
|
Scaffold(topBar = {
|
||||||
BalancesTopAppBar(onSettings = onSettings)
|
BalancesTopAppBar(
|
||||||
|
showRestoring = walletRestoringState == WalletRestoringState.RESTORING,
|
||||||
|
onSettings = onSettings
|
||||||
|
)
|
||||||
}) { paddingValues ->
|
}) { paddingValues ->
|
||||||
if (null == walletSnapshot) {
|
if (null == walletSnapshot) {
|
||||||
CircularScreenProgressIndicator()
|
CircularScreenProgressIndicator()
|
||||||
} else {
|
} else {
|
||||||
BalancesMainContent(
|
BalancesMainContent(
|
||||||
isFiatConversionEnabled = isFiatConversionEnabled,
|
isFiatConversionEnabled = isFiatConversionEnabled,
|
||||||
isKeepScreenOnWhileSyncing = isKeepScreenOnWhileSyncing,
|
|
||||||
isUpdateAvailable = isUpdateAvailable,
|
isUpdateAvailable = isUpdateAvailable,
|
||||||
onShielding = onShielding,
|
onShielding = onShielding,
|
||||||
walletSnapshot = walletSnapshot,
|
walletSnapshot = walletSnapshot,
|
||||||
|
@ -197,10 +198,19 @@ fun ShieldingErrorDialog(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun BalancesTopAppBar(onSettings: () -> Unit) {
|
private fun BalancesTopAppBar(
|
||||||
|
onSettings: () -> Unit,
|
||||||
|
showRestoring: Boolean
|
||||||
|
) {
|
||||||
SmallTopAppBar(
|
SmallTopAppBar(
|
||||||
showTitleLogo = false,
|
restoringLabel =
|
||||||
|
if (showRestoring) {
|
||||||
|
stringResource(id = R.string.restoring_wallet_label)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
},
|
||||||
titleText = stringResource(id = R.string.balances_title),
|
titleText = stringResource(id = R.string.balances_title),
|
||||||
|
showTitleLogo = false,
|
||||||
hamburgerMenuActions = {
|
hamburgerMenuActions = {
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = onSettings,
|
onClick = onSettings,
|
||||||
|
@ -211,7 +221,7 @@ private fun BalancesTopAppBar(onSettings: () -> Unit) {
|
||||||
contentDescription = stringResource(id = R.string.settings_menu_content_description)
|
contentDescription = stringResource(id = R.string.settings_menu_content_description)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +229,6 @@ private fun BalancesTopAppBar(onSettings: () -> Unit) {
|
||||||
@Composable
|
@Composable
|
||||||
private fun BalancesMainContent(
|
private fun BalancesMainContent(
|
||||||
isFiatConversionEnabled: Boolean,
|
isFiatConversionEnabled: Boolean,
|
||||||
isKeepScreenOnWhileSyncing: Boolean?,
|
|
||||||
isUpdateAvailable: Boolean,
|
isUpdateAvailable: Boolean,
|
||||||
onShielding: () -> Unit,
|
onShielding: () -> Unit,
|
||||||
walletSnapshot: WalletSnapshot,
|
walletSnapshot: WalletSnapshot,
|
||||||
|
@ -272,10 +281,6 @@ private fun BalancesMainContent(
|
||||||
walletSnapshot = walletSnapshot,
|
walletSnapshot = walletSnapshot,
|
||||||
isUpdateAvailable = isUpdateAvailable,
|
isUpdateAvailable = isUpdateAvailable,
|
||||||
)
|
)
|
||||||
|
|
||||||
if (isKeepScreenOnWhileSyncing == true && walletSnapshot.status == Synchronizer.Status.SYNCING) {
|
|
||||||
DisableScreenTimeout()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
package co.electriccoin.zcash.ui.screen.chooseserver
|
package co.electriccoin.zcash.ui.screen.chooseserver
|
||||||
|
|
||||||
import androidx.activity.compose.BackHandler
|
import androidx.activity.compose.BackHandler
|
||||||
|
import androidx.activity.viewModels
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
@ -18,17 +19,23 @@ import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||||
import cash.z.ecc.android.sdk.type.ServerValidation
|
import cash.z.ecc.android.sdk.type.ServerValidation
|
||||||
import cash.z.ecc.sdk.type.fromResources
|
import cash.z.ecc.sdk.type.fromResources
|
||||||
import co.electriccoin.zcash.ui.MainActivity
|
import co.electriccoin.zcash.ui.MainActivity
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.common.viewmodel.SecretState
|
import co.electriccoin.zcash.ui.common.viewmodel.SecretState
|
||||||
|
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||||
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
|
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
|
||||||
import co.electriccoin.zcash.ui.screen.chooseserver.view.ChooseServer
|
import co.electriccoin.zcash.ui.screen.chooseserver.view.ChooseServer
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun MainActivity.WrapChooseServer(goBack: () -> Unit) {
|
internal fun MainActivity.WrapChooseServer(goBack: () -> Unit) {
|
||||||
|
val walletViewModel by viewModels<WalletViewModel>()
|
||||||
|
|
||||||
val secretState = walletViewModel.secretState.collectAsStateWithLifecycle().value
|
val secretState = walletViewModel.secretState.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
|
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
|
val walletRestoringState = walletViewModel.walletRestoringState.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
WrapChooseServer(
|
WrapChooseServer(
|
||||||
activity = this,
|
activity = this,
|
||||||
goBack = goBack,
|
goBack = goBack,
|
||||||
|
@ -39,7 +46,8 @@ internal fun MainActivity.WrapChooseServer(goBack: () -> Unit) {
|
||||||
},
|
},
|
||||||
onWalletPersist = {
|
onWalletPersist = {
|
||||||
walletViewModel.persistExistingWallet(it)
|
walletViewModel.persistExistingWallet(it)
|
||||||
}
|
},
|
||||||
|
walletRestoringState = walletRestoringState
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +60,7 @@ private fun WrapChooseServer(
|
||||||
onWalletPersist: (PersistableWallet) -> Unit,
|
onWalletPersist: (PersistableWallet) -> Unit,
|
||||||
secretState: SecretState,
|
secretState: SecretState,
|
||||||
synchronizer: Synchronizer?,
|
synchronizer: Synchronizer?,
|
||||||
|
walletRestoringState: WalletRestoringState,
|
||||||
) {
|
) {
|
||||||
if (synchronizer == null || secretState !is SecretState.Ready) {
|
if (synchronizer == null || secretState !is SecretState.Ready) {
|
||||||
// TODO [#1146]: Consider moving CircularScreenProgressIndicator from Android layer to View layer
|
// TODO [#1146]: Consider moving CircularScreenProgressIndicator from Android layer to View layer
|
||||||
|
@ -118,7 +127,8 @@ private fun WrapChooseServer(
|
||||||
isShowingErrorDialog = isShowingErrorDialog,
|
isShowingErrorDialog = isShowingErrorDialog,
|
||||||
setShowErrorDialog = setShowErrorDialog,
|
setShowErrorDialog = setShowErrorDialog,
|
||||||
isShowingSuccessDialog = isShowingSuccessDialog,
|
isShowingSuccessDialog = isShowingSuccessDialog,
|
||||||
setShowSuccessDialog = setShowSuccessDialog
|
setShowSuccessDialog = setShowSuccessDialog,
|
||||||
|
walletRestoringState = walletRestoringState
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ import cash.z.ecc.sdk.extension.isValid
|
||||||
import cash.z.ecc.sdk.fixture.PersistableWalletFixture
|
import cash.z.ecc.sdk.fixture.PersistableWalletFixture
|
||||||
import co.electriccoin.lightwallet.client.model.LightWalletEndpoint
|
import co.electriccoin.lightwallet.client.model.LightWalletEndpoint
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.design.component.AppAlertDialog
|
import co.electriccoin.zcash.ui.design.component.AppAlertDialog
|
||||||
import co.electriccoin.zcash.ui.design.component.FormTextField
|
import co.electriccoin.zcash.ui.design.component.FormTextField
|
||||||
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
||||||
|
@ -62,6 +63,7 @@ private fun PreviewChooseServer() {
|
||||||
setShowErrorDialog = {},
|
setShowErrorDialog = {},
|
||||||
isShowingSuccessDialog = false,
|
isShowingSuccessDialog = false,
|
||||||
setShowSuccessDialog = {},
|
setShowSuccessDialog = {},
|
||||||
|
walletRestoringState = WalletRestoringState.NONE,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,10 +81,14 @@ fun ChooseServer(
|
||||||
setShowErrorDialog: (Boolean) -> Unit,
|
setShowErrorDialog: (Boolean) -> Unit,
|
||||||
isShowingSuccessDialog: Boolean,
|
isShowingSuccessDialog: Boolean,
|
||||||
setShowSuccessDialog: (Boolean) -> Unit,
|
setShowSuccessDialog: (Boolean) -> Unit,
|
||||||
|
walletRestoringState: WalletRestoringState,
|
||||||
) {
|
) {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
ChooseServerTopAppBar(onBack = onBack)
|
ChooseServerTopAppBar(
|
||||||
|
onBack = onBack,
|
||||||
|
showRestoring = walletRestoringState == WalletRestoringState.RESTORING,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
ChooseServerMainContent(
|
ChooseServerMainContent(
|
||||||
|
@ -120,13 +126,22 @@ fun ChooseServer(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ChooseServerTopAppBar(onBack: () -> Unit) {
|
private fun ChooseServerTopAppBar(
|
||||||
|
onBack: () -> Unit,
|
||||||
|
showRestoring: Boolean
|
||||||
|
) {
|
||||||
SmallTopAppBar(
|
SmallTopAppBar(
|
||||||
|
restoringLabel =
|
||||||
|
if (showRestoring) {
|
||||||
|
stringResource(id = R.string.restoring_wallet_label)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
},
|
||||||
|
modifier = Modifier.testTag(ChooseServerTag.CHOOSE_SERVER_TOP_APP_BAR),
|
||||||
|
showTitleLogo = true,
|
||||||
backText = stringResource(id = R.string.choose_server_back).uppercase(),
|
backText = stringResource(id = R.string.choose_server_back).uppercase(),
|
||||||
backContentDescriptionText = stringResource(R.string.choose_server_back_content_description),
|
backContentDescriptionText = stringResource(R.string.choose_server_back_content_description),
|
||||||
onBack = onBack,
|
onBack = onBack,
|
||||||
showTitleLogo = true,
|
|
||||||
modifier = Modifier.testTag(ChooseServerTag.CHOOSE_SERVER_TOP_APP_BAR)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ import cash.z.ecc.sdk.type.fromResources
|
||||||
import co.electriccoin.zcash.ui.MainActivity
|
import co.electriccoin.zcash.ui.MainActivity
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||||
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
|
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
|
||||||
import co.electriccoin.zcash.ui.screen.exportdata.view.ExportPrivateData
|
import co.electriccoin.zcash.ui.screen.exportdata.view.ExportPrivateData
|
||||||
|
@ -29,10 +30,18 @@ internal fun MainActivity.WrapExportPrivateData(
|
||||||
goBack: () -> Unit,
|
goBack: () -> Unit,
|
||||||
onConfirm: () -> Unit
|
onConfirm: () -> Unit
|
||||||
) {
|
) {
|
||||||
|
val walletViewModel by viewModels<WalletViewModel>()
|
||||||
|
|
||||||
|
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
|
val walletRestoringState = walletViewModel.walletRestoringState.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
WrapExportPrivateData(
|
WrapExportPrivateData(
|
||||||
this,
|
this,
|
||||||
onBack = goBack,
|
onBack = goBack,
|
||||||
onShare = onConfirm
|
onShare = onConfirm,
|
||||||
|
synchronizer = synchronizer,
|
||||||
|
walletRestoringState = walletRestoringState,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,11 +49,10 @@ internal fun MainActivity.WrapExportPrivateData(
|
||||||
internal fun WrapExportPrivateData(
|
internal fun WrapExportPrivateData(
|
||||||
activity: ComponentActivity,
|
activity: ComponentActivity,
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
onShare: () -> Unit
|
onShare: () -> Unit,
|
||||||
|
synchronizer: Synchronizer?,
|
||||||
|
walletRestoringState: WalletRestoringState,
|
||||||
) {
|
) {
|
||||||
val walletViewModel by activity.viewModels<WalletViewModel>()
|
|
||||||
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
|
|
||||||
|
|
||||||
if (synchronizer == null) {
|
if (synchronizer == null) {
|
||||||
// TODO [#1146]: Consider moving CircularScreenProgressIndicator from Android layer to View layer
|
// TODO [#1146]: Consider moving CircularScreenProgressIndicator from Android layer to View layer
|
||||||
// TODO [#1146]: Improve this by allowing screen composition and updating it after the data is available
|
// TODO [#1146]: Improve this by allowing screen composition and updating it after the data is available
|
||||||
|
@ -72,7 +80,8 @@ internal fun WrapExportPrivateData(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
walletRestoringState = walletRestoringState
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
|
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
|
||||||
import co.electriccoin.zcash.ui.design.component.Body
|
import co.electriccoin.zcash.ui.design.component.Body
|
||||||
import co.electriccoin.zcash.ui.design.component.CheckBox
|
import co.electriccoin.zcash.ui.design.component.CheckBox
|
||||||
|
@ -42,6 +43,7 @@ private fun ExportPrivateDataPreview() {
|
||||||
onBack = {},
|
onBack = {},
|
||||||
onAgree = {},
|
onAgree = {},
|
||||||
onConfirm = {},
|
onConfirm = {},
|
||||||
|
walletRestoringState = WalletRestoringState.NONE,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,9 +58,15 @@ fun ExportPrivateData(
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
onAgree: (Boolean) -> Unit,
|
onAgree: (Boolean) -> Unit,
|
||||||
onConfirm: () -> Unit,
|
onConfirm: () -> Unit,
|
||||||
|
walletRestoringState: WalletRestoringState,
|
||||||
) {
|
) {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = { ExportPrivateDataTopAppBar(onBack = onBack) },
|
topBar = {
|
||||||
|
ExportPrivateDataTopAppBar(
|
||||||
|
onBack = onBack,
|
||||||
|
showRestoring = walletRestoringState == WalletRestoringState.RESTORING,
|
||||||
|
)
|
||||||
|
},
|
||||||
snackbarHost = { SnackbarHost(snackbarHostState) },
|
snackbarHost = { SnackbarHost(snackbarHostState) },
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
ExportPrivateDataContent(
|
ExportPrivateDataContent(
|
||||||
|
@ -79,8 +87,17 @@ fun ExportPrivateData(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ExportPrivateDataTopAppBar(onBack: () -> Unit) {
|
private fun ExportPrivateDataTopAppBar(
|
||||||
|
onBack: () -> Unit,
|
||||||
|
showRestoring: Boolean
|
||||||
|
) {
|
||||||
SmallTopAppBar(
|
SmallTopAppBar(
|
||||||
|
restoringLabel =
|
||||||
|
if (showRestoring) {
|
||||||
|
stringResource(id = R.string.restoring_wallet_label)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
},
|
||||||
backText = stringResource(R.string.export_data_back).uppercase(),
|
backText = stringResource(R.string.export_data_back).uppercase(),
|
||||||
backContentDescriptionText = stringResource(R.string.export_data_back_content_description),
|
backContentDescriptionText = stringResource(R.string.export_data_back_content_description),
|
||||||
onBack = onBack,
|
onBack = onBack,
|
||||||
|
|
|
@ -8,10 +8,16 @@ import androidx.activity.viewModels
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import cash.z.ecc.android.sdk.model.ZecSend
|
import cash.z.ecc.android.sdk.model.ZecSend
|
||||||
import co.electriccoin.zcash.ui.MainActivity
|
import co.electriccoin.zcash.ui.MainActivity
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
|
import co.electriccoin.zcash.ui.common.compose.RestoreScreenBrightness
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
||||||
import co.electriccoin.zcash.ui.common.viewmodel.HomeViewModel
|
import co.electriccoin.zcash.ui.common.viewmodel.HomeViewModel
|
||||||
|
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||||
|
import co.electriccoin.zcash.ui.common.viewmodel.isSynced
|
||||||
import co.electriccoin.zcash.ui.screen.account.WrapAccount
|
import co.electriccoin.zcash.ui.screen.account.WrapAccount
|
||||||
import co.electriccoin.zcash.ui.screen.balances.WrapBalances
|
import co.electriccoin.zcash.ui.screen.balances.WrapBalances
|
||||||
import co.electriccoin.zcash.ui.screen.home.model.TabItem
|
import co.electriccoin.zcash.ui.screen.home.model.TabItem
|
||||||
|
@ -19,6 +25,7 @@ import co.electriccoin.zcash.ui.screen.home.view.Home
|
||||||
import co.electriccoin.zcash.ui.screen.receive.WrapReceive
|
import co.electriccoin.zcash.ui.screen.receive.WrapReceive
|
||||||
import co.electriccoin.zcash.ui.screen.send.WrapSend
|
import co.electriccoin.zcash.ui.screen.send.WrapSend
|
||||||
import co.electriccoin.zcash.ui.screen.send.model.SendArguments
|
import co.electriccoin.zcash.ui.screen.send.model.SendArguments
|
||||||
|
import co.electriccoin.zcash.ui.screen.settings.viewmodel.SettingsViewModel
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.coroutines.channels.BufferOverflow
|
import kotlinx.coroutines.channels.BufferOverflow
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
|
@ -26,7 +33,6 @@ import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
@Composable
|
@Composable
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
internal fun MainActivity.WrapHome(
|
internal fun MainActivity.WrapHome(
|
||||||
onPageChange: (HomeScreenIndex) -> Unit,
|
|
||||||
goBack: () -> Unit,
|
goBack: () -> Unit,
|
||||||
goSettings: () -> Unit,
|
goSettings: () -> Unit,
|
||||||
goMultiTrxSubmissionFailure: () -> Unit,
|
goMultiTrxSubmissionFailure: () -> Unit,
|
||||||
|
@ -34,15 +40,39 @@ internal fun MainActivity.WrapHome(
|
||||||
goSendConfirmation: (ZecSend) -> Unit,
|
goSendConfirmation: (ZecSend) -> Unit,
|
||||||
sendArguments: SendArguments
|
sendArguments: SendArguments
|
||||||
) {
|
) {
|
||||||
|
val homeViewModel by viewModels<HomeViewModel>()
|
||||||
|
|
||||||
|
val walletViewModel by viewModels<WalletViewModel>()
|
||||||
|
|
||||||
|
val settingsViewModel by viewModels<SettingsViewModel>()
|
||||||
|
|
||||||
|
val homeScreenIndex = homeViewModel.screenIndex.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
|
val isKeepScreenOnWhileSyncing = settingsViewModel.isKeepScreenOnWhileSyncing.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
|
val walletSnapshot = walletViewModel.walletSnapshot.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
|
val walletRestoringState = walletViewModel.walletRestoringState.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
|
// Once the wallet is fully synced and still in restoring state, persist the new state
|
||||||
|
if (walletSnapshot?.status?.isSynced() == true && walletRestoringState.isRunningRestoring()) {
|
||||||
|
walletViewModel.persistWalletRestoringState(WalletRestoringState.SYNCING)
|
||||||
|
}
|
||||||
|
|
||||||
WrapHome(
|
WrapHome(
|
||||||
this,
|
this,
|
||||||
onPageChange = onPageChange,
|
|
||||||
goBack = goBack,
|
goBack = goBack,
|
||||||
goScan = goScan,
|
goScan = goScan,
|
||||||
goSendConfirmation = goSendConfirmation,
|
goSendConfirmation = goSendConfirmation,
|
||||||
goSettings = goSettings,
|
goSettings = goSettings,
|
||||||
goMultiTrxSubmissionFailure = goMultiTrxSubmissionFailure,
|
goMultiTrxSubmissionFailure = goMultiTrxSubmissionFailure,
|
||||||
sendArguments = sendArguments
|
homeScreenIndex = homeScreenIndex,
|
||||||
|
isKeepScreenOnWhileSyncing = isKeepScreenOnWhileSyncing,
|
||||||
|
onPageChange = {
|
||||||
|
homeViewModel.screenIndex.value = it
|
||||||
|
},
|
||||||
|
sendArguments = sendArguments,
|
||||||
|
walletSnapshot = walletSnapshot
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,11 +85,12 @@ internal fun WrapHome(
|
||||||
goMultiTrxSubmissionFailure: () -> Unit,
|
goMultiTrxSubmissionFailure: () -> Unit,
|
||||||
goScan: () -> Unit,
|
goScan: () -> Unit,
|
||||||
goSendConfirmation: (ZecSend) -> Unit,
|
goSendConfirmation: (ZecSend) -> Unit,
|
||||||
|
homeScreenIndex: HomeScreenIndex,
|
||||||
|
isKeepScreenOnWhileSyncing: Boolean?,
|
||||||
onPageChange: (HomeScreenIndex) -> Unit,
|
onPageChange: (HomeScreenIndex) -> Unit,
|
||||||
sendArguments: SendArguments
|
sendArguments: SendArguments,
|
||||||
|
walletSnapshot: WalletSnapshot?,
|
||||||
) {
|
) {
|
||||||
val homeViewModel by activity.viewModels<HomeViewModel>()
|
|
||||||
|
|
||||||
// Flow for propagating the new page index to the pager in the view layer
|
// Flow for propagating the new page index to the pager in the view layer
|
||||||
val forceHomePageIndexFlow: MutableSharedFlow<ForcePage?> =
|
val forceHomePageIndexFlow: MutableSharedFlow<ForcePage?> =
|
||||||
MutableSharedFlow(
|
MutableSharedFlow(
|
||||||
|
@ -70,7 +101,7 @@ internal fun WrapHome(
|
||||||
val forceIndex = forceHomePageIndexFlow.collectAsState(initial = null).value
|
val forceIndex = forceHomePageIndexFlow.collectAsState(initial = null).value
|
||||||
|
|
||||||
val homeGoBack: () -> Unit = {
|
val homeGoBack: () -> Unit = {
|
||||||
when (homeViewModel.screenIndex.value) {
|
when (homeScreenIndex) {
|
||||||
HomeScreenIndex.ACCOUNT -> goBack()
|
HomeScreenIndex.ACCOUNT -> goBack()
|
||||||
HomeScreenIndex.SEND,
|
HomeScreenIndex.SEND,
|
||||||
HomeScreenIndex.RECEIVE,
|
HomeScreenIndex.RECEIVE,
|
||||||
|
@ -82,6 +113,11 @@ internal fun WrapHome(
|
||||||
homeGoBack()
|
homeGoBack()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset the screen brightness for all pages except Receive which maintain the screen brightness by itself
|
||||||
|
if (homeScreenIndex != HomeScreenIndex.RECEIVE) {
|
||||||
|
RestoreScreenBrightness()
|
||||||
|
}
|
||||||
|
|
||||||
val tabs =
|
val tabs =
|
||||||
persistentListOf(
|
persistentListOf(
|
||||||
TabItem(
|
TabItem(
|
||||||
|
@ -92,7 +128,7 @@ internal fun WrapHome(
|
||||||
WrapAccount(
|
WrapAccount(
|
||||||
activity = activity,
|
activity = activity,
|
||||||
goBalances = { forceHomePageIndexFlow.tryEmit(ForcePage(HomeScreenIndex.BALANCES)) },
|
goBalances = { forceHomePageIndexFlow.tryEmit(ForcePage(HomeScreenIndex.BALANCES)) },
|
||||||
goSettings = goSettings,
|
goSettings = goSettings
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
@ -119,7 +155,7 @@ internal fun WrapHome(
|
||||||
screenContent = {
|
screenContent = {
|
||||||
WrapReceive(
|
WrapReceive(
|
||||||
activity = activity,
|
activity = activity,
|
||||||
onSettings = goSettings,
|
onSettings = goSettings
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
@ -140,7 +176,9 @@ internal fun WrapHome(
|
||||||
Home(
|
Home(
|
||||||
subScreens = tabs,
|
subScreens = tabs,
|
||||||
forcePage = forceIndex,
|
forcePage = forceIndex,
|
||||||
onPageChange = onPageChange
|
isKeepScreenOnWhileSyncing = isKeepScreenOnWhileSyncing,
|
||||||
|
onPageChange = onPageChange,
|
||||||
|
walletSnapshot = walletSnapshot
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,10 +24,14 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.constraintlayout.compose.ConstraintLayout
|
import androidx.constraintlayout.compose.ConstraintLayout
|
||||||
import androidx.constraintlayout.compose.Dimension
|
import androidx.constraintlayout.compose.Dimension
|
||||||
|
import cash.z.ecc.android.sdk.Synchronizer
|
||||||
import co.electriccoin.zcash.spackle.Twig
|
import co.electriccoin.zcash.spackle.Twig
|
||||||
|
import co.electriccoin.zcash.ui.common.compose.DisableScreenTimeout
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
||||||
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
||||||
import co.electriccoin.zcash.ui.design.component.NavigationTabText
|
import co.electriccoin.zcash.ui.design.component.NavigationTabText
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
|
import co.electriccoin.zcash.ui.fixture.WalletSnapshotFixture
|
||||||
import co.electriccoin.zcash.ui.screen.home.ForcePage
|
import co.electriccoin.zcash.ui.screen.home.ForcePage
|
||||||
import co.electriccoin.zcash.ui.screen.home.HomeScreenIndex
|
import co.electriccoin.zcash.ui.screen.home.HomeScreenIndex
|
||||||
import co.electriccoin.zcash.ui.screen.home.model.TabItem
|
import co.electriccoin.zcash.ui.screen.home.model.TabItem
|
||||||
|
@ -42,9 +46,11 @@ private fun ComposablePreview() {
|
||||||
ZcashTheme(forceDarkMode = false) {
|
ZcashTheme(forceDarkMode = false) {
|
||||||
GradientSurface {
|
GradientSurface {
|
||||||
Home(
|
Home(
|
||||||
subScreens = persistentListOf(),
|
isKeepScreenOnWhileSyncing = false,
|
||||||
forcePage = null,
|
forcePage = null,
|
||||||
onPageChange = {}
|
onPageChange = {},
|
||||||
|
subScreens = persistentListOf(),
|
||||||
|
walletSnapshot = WalletSnapshotFixture.new(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,9 +60,11 @@ private fun ComposablePreview() {
|
||||||
@Suppress("LongMethod")
|
@Suppress("LongMethod")
|
||||||
@Composable
|
@Composable
|
||||||
fun Home(
|
fun Home(
|
||||||
subScreens: ImmutableList<TabItem>,
|
isKeepScreenOnWhileSyncing: Boolean?,
|
||||||
forcePage: ForcePage?,
|
forcePage: ForcePage?,
|
||||||
onPageChange: (HomeScreenIndex) -> Unit,
|
onPageChange: (HomeScreenIndex) -> Unit,
|
||||||
|
subScreens: ImmutableList<TabItem>,
|
||||||
|
walletSnapshot: WalletSnapshot?,
|
||||||
) {
|
) {
|
||||||
val pagerState =
|
val pagerState =
|
||||||
rememberPagerState(
|
rememberPagerState(
|
||||||
|
@ -169,4 +177,10 @@ fun Home(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isKeepScreenOnWhileSyncing == true &&
|
||||||
|
walletSnapshot?.status == Synchronizer.Status.SYNCING
|
||||||
|
) {
|
||||||
|
DisableScreenTimeout()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,7 @@ private fun NewWalletRecoveryTopAppBar(
|
||||||
if (versionInfo.isDebuggable && !versionInfo.isRunningUnderTestService) {
|
if (versionInfo.isDebuggable && !versionInfo.isRunningUnderTestService) {
|
||||||
DebugMenu(onCopyToClipboard = onSeedCopy)
|
DebugMenu(onCopyToClipboard = onSeedCopy)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ import co.electriccoin.zcash.spackle.FirebaseTestLabUtil
|
||||||
import co.electriccoin.zcash.ui.MainActivity
|
import co.electriccoin.zcash.ui.MainActivity
|
||||||
import co.electriccoin.zcash.ui.common.model.OnboardingState
|
import co.electriccoin.zcash.ui.common.model.OnboardingState
|
||||||
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||||
import co.electriccoin.zcash.ui.screen.onboarding.view.ShortOnboarding
|
import co.electriccoin.zcash.ui.screen.onboarding.view.ShortOnboarding
|
||||||
import co.electriccoin.zcash.ui.screen.onboarding.viewmodel.OnboardingViewModel
|
import co.electriccoin.zcash.ui.screen.onboarding.viewmodel.OnboardingViewModel
|
||||||
|
@ -117,4 +118,5 @@ internal fun persistExistingWalletWithSeedPhrase(
|
||||||
walletInitMode = WalletInitMode.RestoreWallet
|
walletInitMode = WalletInitMode.RestoreWallet
|
||||||
)
|
)
|
||||||
walletViewModel.persistExistingWallet(restoredWallet)
|
walletViewModel.persistExistingWallet(restoredWallet)
|
||||||
|
walletViewModel.persistWalletRestoringState(WalletRestoringState.RESTORING)
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,7 +164,7 @@ private fun OnboardingMainContent(
|
||||||
if (isDebugMenuEnabled) {
|
if (isDebugMenuEnabled) {
|
||||||
DebugMenu(onFixtureWallet)
|
DebugMenu(onFixtureWallet)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
Column(
|
Column(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
|
|
|
@ -16,9 +16,11 @@ import co.electriccoin.zcash.spackle.ClipboardManagerUtil
|
||||||
import co.electriccoin.zcash.spackle.Twig
|
import co.electriccoin.zcash.spackle.Twig
|
||||||
import co.electriccoin.zcash.spackle.getInternalCacheDirSuspend
|
import co.electriccoin.zcash.spackle.getInternalCacheDirSuspend
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
|
import co.electriccoin.zcash.ui.common.compose.ScreenBrightnessState
|
||||||
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||||
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||||
import co.electriccoin.zcash.ui.screen.receive.view.Receive
|
import co.electriccoin.zcash.ui.screen.receive.view.Receive
|
||||||
|
import co.electriccoin.zcash.ui.screen.settings.viewmodel.ScreenBrightnessViewModel
|
||||||
import co.electriccoin.zcash.ui.util.FileShareUtil
|
import co.electriccoin.zcash.ui.util.FileShareUtil
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.channels.awaitClose
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
|
@ -33,8 +35,15 @@ internal fun WrapReceive(
|
||||||
activity: ComponentActivity,
|
activity: ComponentActivity,
|
||||||
onSettings: () -> Unit,
|
onSettings: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val viewModel by activity.viewModels<WalletViewModel>()
|
val walletViewModel by activity.viewModels<WalletViewModel>()
|
||||||
val walletAddresses = viewModel.addresses.collectAsStateWithLifecycle().value
|
|
||||||
|
val brightnessViewModel by activity.viewModels<ScreenBrightnessViewModel>()
|
||||||
|
|
||||||
|
val screenBrightnessState = brightnessViewModel.screenBrightnessState.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
|
val walletAddresses = walletViewModel.addresses.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
|
val walletRestoringState = walletViewModel.walletRestoringState.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
val snackbarHostState = remember { SnackbarHostState() }
|
val snackbarHostState = remember { SnackbarHostState() }
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
@ -42,9 +51,13 @@ internal fun WrapReceive(
|
||||||
val versionInfo = VersionInfo.new(activity.applicationContext)
|
val versionInfo = VersionInfo.new(activity.applicationContext)
|
||||||
|
|
||||||
Receive(
|
Receive(
|
||||||
walletAddress = walletAddresses,
|
screenBrightnessState = screenBrightnessState,
|
||||||
snackbarHostState = snackbarHostState,
|
onAdjustBrightness = {
|
||||||
onAdjustBrightness = { /* Just for testing purposes */ },
|
when (it) {
|
||||||
|
ScreenBrightnessState.NORMAL -> brightnessViewModel.restoreBrightness()
|
||||||
|
ScreenBrightnessState.FULL -> brightnessViewModel.fullBrightness()
|
||||||
|
}
|
||||||
|
},
|
||||||
onAddrCopyToClipboard = { address ->
|
onAddrCopyToClipboard = { address ->
|
||||||
ClipboardManagerUtil.copyToClipboard(
|
ClipboardManagerUtil.copyToClipboard(
|
||||||
activity.applicationContext,
|
activity.applicationContext,
|
||||||
|
@ -72,7 +85,10 @@ internal fun WrapReceive(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSettings = onSettings,
|
onSettings = onSettings,
|
||||||
versionInfo = versionInfo
|
snackbarHostState = snackbarHostState,
|
||||||
|
versionInfo = versionInfo,
|
||||||
|
walletAddress = walletAddresses,
|
||||||
|
walletRestoringState = walletRestoringState,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,9 +13,6 @@ import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.wrapContentSize
|
import androidx.compose.foundation.layout.wrapContentSize
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.filled.BrightnessHigh
|
|
||||||
import androidx.compose.material.icons.filled.BrightnessLow
|
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
|
@ -23,9 +20,7 @@ import androidx.compose.material3.SnackbarHost
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.ImageBitmap
|
import androidx.compose.ui.graphics.ImageBitmap
|
||||||
|
@ -44,7 +39,9 @@ import cash.z.ecc.android.sdk.model.WalletAddresses
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
import co.electriccoin.zcash.ui.common.compose.BrightenScreen
|
import co.electriccoin.zcash.ui.common.compose.BrightenScreen
|
||||||
import co.electriccoin.zcash.ui.common.compose.DisableScreenTimeout
|
import co.electriccoin.zcash.ui.common.compose.DisableScreenTimeout
|
||||||
|
import co.electriccoin.zcash.ui.common.compose.ScreenBrightnessState
|
||||||
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.common.test.CommonTag
|
import co.electriccoin.zcash.ui.common.test.CommonTag
|
||||||
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
|
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
|
||||||
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
||||||
|
@ -64,13 +61,15 @@ private fun ComposablePreview() {
|
||||||
ZcashTheme(forceDarkMode = false) {
|
ZcashTheme(forceDarkMode = false) {
|
||||||
GradientSurface {
|
GradientSurface {
|
||||||
Receive(
|
Receive(
|
||||||
|
screenBrightnessState = ScreenBrightnessState.NORMAL,
|
||||||
walletAddress = runBlocking { WalletAddressesFixture.new() },
|
walletAddress = runBlocking { WalletAddressesFixture.new() },
|
||||||
snackbarHostState = SnackbarHostState(),
|
snackbarHostState = SnackbarHostState(),
|
||||||
onSettings = {},
|
onSettings = {},
|
||||||
onAdjustBrightness = {},
|
onAdjustBrightness = {},
|
||||||
onAddrCopyToClipboard = {},
|
onAddrCopyToClipboard = {},
|
||||||
onQrImageShare = {},
|
onQrImageShare = {},
|
||||||
versionInfo = VersionInfoFixture.new()
|
versionInfo = VersionInfoFixture.new(),
|
||||||
|
walletRestoringState = WalletRestoringState.NONE
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,25 +78,24 @@ private fun ComposablePreview() {
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
@Composable
|
@Composable
|
||||||
fun Receive(
|
fun Receive(
|
||||||
|
screenBrightnessState: ScreenBrightnessState,
|
||||||
walletAddress: WalletAddresses?,
|
walletAddress: WalletAddresses?,
|
||||||
snackbarHostState: SnackbarHostState,
|
snackbarHostState: SnackbarHostState,
|
||||||
onSettings: () -> Unit,
|
onSettings: () -> Unit,
|
||||||
onAdjustBrightness: (Boolean) -> Unit,
|
onAdjustBrightness: (ScreenBrightnessState) -> Unit,
|
||||||
onAddrCopyToClipboard: (String) -> Unit,
|
onAddrCopyToClipboard: (String) -> Unit,
|
||||||
onQrImageShare: (ImageBitmap) -> Unit,
|
onQrImageShare: (ImageBitmap) -> Unit,
|
||||||
versionInfo: VersionInfo,
|
versionInfo: VersionInfo,
|
||||||
|
walletRestoringState: WalletRestoringState,
|
||||||
) {
|
) {
|
||||||
val (brightness, setBrightness) = rememberSaveable { mutableStateOf(false) }
|
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
ReceiveTopAppBar(
|
ReceiveTopAppBar(
|
||||||
adjustBrightness = brightness,
|
|
||||||
onSettings = onSettings,
|
onSettings = onSettings,
|
||||||
onBrightness = {
|
onBrightness = {
|
||||||
onAdjustBrightness(!brightness)
|
onAdjustBrightness(screenBrightnessState.getChange())
|
||||||
setBrightness(!brightness)
|
|
||||||
},
|
},
|
||||||
|
showRestoring = walletRestoringState == WalletRestoringState.RESTORING,
|
||||||
versionInfo = versionInfo,
|
versionInfo = versionInfo,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
@ -110,7 +108,7 @@ fun Receive(
|
||||||
walletAddress = walletAddress,
|
walletAddress = walletAddress,
|
||||||
onAddressCopyToClipboard = onAddrCopyToClipboard,
|
onAddressCopyToClipboard = onAddrCopyToClipboard,
|
||||||
onQrImageShare = onQrImageShare,
|
onQrImageShare = onQrImageShare,
|
||||||
adjustBrightness = brightness,
|
screenBrightnessState = screenBrightnessState,
|
||||||
versionInfo = versionInfo,
|
versionInfo = versionInfo,
|
||||||
modifier =
|
modifier =
|
||||||
Modifier.padding(
|
Modifier.padding(
|
||||||
|
@ -126,30 +124,19 @@ fun Receive(
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ReceiveTopAppBar(
|
private fun ReceiveTopAppBar(
|
||||||
adjustBrightness: Boolean,
|
|
||||||
onSettings: () -> Unit,
|
onSettings: () -> Unit,
|
||||||
onBrightness: () -> Unit,
|
onBrightness: () -> Unit,
|
||||||
versionInfo: VersionInfo
|
versionInfo: VersionInfo,
|
||||||
|
showRestoring: Boolean
|
||||||
) {
|
) {
|
||||||
SmallTopAppBar(
|
SmallTopAppBar(
|
||||||
titleText = stringResource(id = R.string.receive_title),
|
restoringLabel =
|
||||||
regularActions = {
|
if (showRestoring) {
|
||||||
if (versionInfo.isDebuggable) {
|
stringResource(id = R.string.restoring_wallet_label)
|
||||||
IconButton(
|
|
||||||
onClick = onBrightness
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector =
|
|
||||||
if (adjustBrightness) {
|
|
||||||
Icons.Default.BrightnessLow
|
|
||||||
} else {
|
} else {
|
||||||
Icons.Default.BrightnessHigh
|
null
|
||||||
},
|
|
||||||
contentDescription = stringResource(R.string.receive_brightness_content_description)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
titleText = stringResource(id = R.string.receive_title),
|
||||||
hamburgerMenuActions = {
|
hamburgerMenuActions = {
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = onSettings,
|
onClick = onSettings,
|
||||||
|
@ -160,7 +147,19 @@ private fun ReceiveTopAppBar(
|
||||||
contentDescription = stringResource(id = R.string.settings_menu_content_description)
|
contentDescription = stringResource(id = R.string.settings_menu_content_description)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
regularActions = {
|
||||||
|
if (versionInfo.isDebuggable) {
|
||||||
|
IconButton(
|
||||||
|
onClick = onBrightness
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
imageVector = ImageVector.vectorResource(id = R.drawable.ic_adjust_brightness),
|
||||||
|
contentDescription = stringResource(R.string.receive_brightness_content_description)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,7 +169,7 @@ private fun ReceiveContents(
|
||||||
walletAddress: WalletAddresses,
|
walletAddress: WalletAddresses,
|
||||||
onAddressCopyToClipboard: (String) -> Unit,
|
onAddressCopyToClipboard: (String) -> Unit,
|
||||||
onQrImageShare: (ImageBitmap) -> Unit,
|
onQrImageShare: (ImageBitmap) -> Unit,
|
||||||
adjustBrightness: Boolean,
|
screenBrightnessState: ScreenBrightnessState,
|
||||||
versionInfo: VersionInfo,
|
versionInfo: VersionInfo,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
|
@ -182,7 +181,7 @@ private fun ReceiveContents(
|
||||||
.then(modifier),
|
.then(modifier),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
if (adjustBrightness) {
|
if (screenBrightnessState == ScreenBrightnessState.FULL) {
|
||||||
BrightenScreen()
|
BrightenScreen()
|
||||||
DisableScreenTimeout()
|
DisableScreenTimeout()
|
||||||
}
|
}
|
||||||
|
|
|
@ -294,6 +294,7 @@ private fun RestoreSeedTopAppBar(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
SmallTopAppBar(
|
SmallTopAppBar(
|
||||||
|
modifier = modifier,
|
||||||
backText = stringResource(id = R.string.restore_back).uppercase(),
|
backText = stringResource(id = R.string.restore_back).uppercase(),
|
||||||
backContentDescriptionText = stringResource(R.string.restore_back_content_description),
|
backContentDescriptionText = stringResource(R.string.restore_back_content_description),
|
||||||
onBack = onBack,
|
onBack = onBack,
|
||||||
|
@ -302,7 +303,6 @@ private fun RestoreSeedTopAppBar(
|
||||||
onSeedClear = onClear
|
onSeedClear = onClear
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
modifier = modifier,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,10 +312,10 @@ private fun RestoreSeedBirthdayTopAppBar(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
SmallTopAppBar(
|
SmallTopAppBar(
|
||||||
|
modifier = modifier,
|
||||||
backText = stringResource(id = R.string.restore_back).uppercase(),
|
backText = stringResource(id = R.string.restore_back).uppercase(),
|
||||||
backContentDescriptionText = stringResource(R.string.restore_back_content_description),
|
backContentDescriptionText = stringResource(R.string.restore_back_content_description),
|
||||||
onBack = onBack,
|
onBack = onBack,
|
||||||
modifier = modifier
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,12 @@ import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
|
import cash.z.ecc.android.sdk.Synchronizer
|
||||||
import co.electriccoin.zcash.spackle.ClipboardManagerUtil
|
import co.electriccoin.zcash.spackle.ClipboardManagerUtil
|
||||||
import co.electriccoin.zcash.ui.MainActivity
|
import co.electriccoin.zcash.ui.MainActivity
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.common.viewmodel.SecretState
|
import co.electriccoin.zcash.ui.common.viewmodel.SecretState
|
||||||
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||||
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
|
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
|
||||||
|
@ -16,31 +18,44 @@ import co.electriccoin.zcash.ui.screen.seedrecovery.view.SeedRecovery
|
||||||
@Composable
|
@Composable
|
||||||
internal fun MainActivity.WrapSeedRecovery(
|
internal fun MainActivity.WrapSeedRecovery(
|
||||||
goBack: () -> Unit,
|
goBack: () -> Unit,
|
||||||
onDone: () -> Unit
|
onDone: () -> Unit,
|
||||||
) {
|
) {
|
||||||
WrapSeedRecovery(this, goBack, onDone)
|
val walletViewModel by viewModels<WalletViewModel>()
|
||||||
|
|
||||||
|
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
|
val secretState = walletViewModel.secretState.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
|
val walletRestoringState = walletViewModel.walletRestoringState.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
|
WrapSeedRecovery(
|
||||||
|
activity = this,
|
||||||
|
goBack = goBack,
|
||||||
|
onDone = onDone,
|
||||||
|
secretState = secretState,
|
||||||
|
synchronizer = synchronizer,
|
||||||
|
walletRestoringState = walletRestoringState
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@Suppress("LongParameterList")
|
||||||
private fun WrapSeedRecovery(
|
private fun WrapSeedRecovery(
|
||||||
activity: ComponentActivity,
|
activity: ComponentActivity,
|
||||||
goBack: () -> Unit,
|
goBack: () -> Unit,
|
||||||
onDone: () -> Unit
|
onDone: () -> Unit,
|
||||||
|
walletRestoringState: WalletRestoringState,
|
||||||
|
synchronizer: Synchronizer?,
|
||||||
|
secretState: SecretState,
|
||||||
) {
|
) {
|
||||||
val versionInfo = VersionInfo.new(activity.applicationContext)
|
val versionInfo = VersionInfo.new(activity.applicationContext)
|
||||||
|
|
||||||
val walletViewModel by activity.viewModels<WalletViewModel>()
|
|
||||||
|
|
||||||
val persistableWallet =
|
val persistableWallet =
|
||||||
run {
|
|
||||||
val secretState = walletViewModel.secretState.collectAsStateWithLifecycle().value
|
|
||||||
if (secretState is SecretState.Ready) {
|
if (secretState is SecretState.Ready) {
|
||||||
secretState.persistableWallet
|
secretState.persistableWallet
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
|
||||||
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
|
|
||||||
|
|
||||||
if (null == synchronizer || null == persistableWallet) {
|
if (null == synchronizer || null == persistableWallet) {
|
||||||
// TODO [#1146]: Consider moving CircularScreenProgressIndicator from Android layer to View layer
|
// TODO [#1146]: Consider moving CircularScreenProgressIndicator from Android layer to View layer
|
||||||
|
@ -67,6 +82,7 @@ private fun WrapSeedRecovery(
|
||||||
},
|
},
|
||||||
onDone = onDone,
|
onDone = onDone,
|
||||||
versionInfo = versionInfo,
|
versionInfo = versionInfo,
|
||||||
|
walletRestoringState = walletRestoringState
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ import co.electriccoin.zcash.ui.R
|
||||||
import co.electriccoin.zcash.ui.common.compose.SecureScreen
|
import co.electriccoin.zcash.ui.common.compose.SecureScreen
|
||||||
import co.electriccoin.zcash.ui.common.compose.shouldSecureScreen
|
import co.electriccoin.zcash.ui.common.compose.shouldSecureScreen
|
||||||
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.common.test.CommonTag.WALLET_BIRTHDAY
|
import co.electriccoin.zcash.ui.common.test.CommonTag.WALLET_BIRTHDAY
|
||||||
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
|
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
|
||||||
import co.electriccoin.zcash.ui.design.component.BodySmall
|
import co.electriccoin.zcash.ui.design.component.BodySmall
|
||||||
|
@ -66,6 +67,7 @@ private fun ComposablePreview() {
|
||||||
onDone = {},
|
onDone = {},
|
||||||
onSeedCopy = {},
|
onSeedCopy = {},
|
||||||
versionInfo = VersionInfoFixture.new(),
|
versionInfo = VersionInfoFixture.new(),
|
||||||
|
walletRestoringState = WalletRestoringState.NONE,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,6 +88,7 @@ fun SeedRecovery(
|
||||||
onDone: () -> Unit,
|
onDone: () -> Unit,
|
||||||
onSeedCopy: () -> Unit,
|
onSeedCopy: () -> Unit,
|
||||||
versionInfo: VersionInfo,
|
versionInfo: VersionInfo,
|
||||||
|
walletRestoringState: WalletRestoringState,
|
||||||
) {
|
) {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
|
@ -93,6 +96,7 @@ fun SeedRecovery(
|
||||||
onBack = onBack,
|
onBack = onBack,
|
||||||
onSeedCopy = onSeedCopy,
|
onSeedCopy = onSeedCopy,
|
||||||
versionInfo = versionInfo,
|
versionInfo = versionInfo,
|
||||||
|
showRestoring = walletRestoringState == WalletRestoringState.RESTORING,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
|
@ -118,9 +122,16 @@ private fun SeedRecoveryTopAppBar(
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
onSeedCopy: () -> Unit,
|
onSeedCopy: () -> Unit,
|
||||||
versionInfo: VersionInfo,
|
versionInfo: VersionInfo,
|
||||||
|
showRestoring: Boolean,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
SmallTopAppBar(
|
SmallTopAppBar(
|
||||||
|
restoringLabel =
|
||||||
|
if (showRestoring) {
|
||||||
|
stringResource(id = R.string.restoring_wallet_label)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
},
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
backText = stringResource(id = R.string.seed_recovery_back).uppercase(),
|
backText = stringResource(id = R.string.seed_recovery_back).uppercase(),
|
||||||
backContentDescriptionText = stringResource(R.string.seed_recovery_back_content_description),
|
backContentDescriptionText = stringResource(R.string.seed_recovery_back_content_description),
|
||||||
|
@ -131,7 +142,7 @@ private fun SeedRecoveryTopAppBar(
|
||||||
onCopyToClipboard = onSeedCopy
|
onCopyToClipboard = onSeedCopy
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ import cash.z.ecc.android.sdk.model.ZecSend
|
||||||
import cash.z.ecc.android.sdk.model.proposeSend
|
import cash.z.ecc.android.sdk.model.proposeSend
|
||||||
import cash.z.ecc.android.sdk.model.toZecString
|
import cash.z.ecc.android.sdk.model.toZecString
|
||||||
import co.electriccoin.zcash.spackle.Twig
|
import co.electriccoin.zcash.spackle.Twig
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
||||||
import co.electriccoin.zcash.ui.common.viewmodel.HomeViewModel
|
import co.electriccoin.zcash.ui.common.viewmodel.HomeViewModel
|
||||||
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||||
|
@ -48,10 +49,10 @@ internal fun WrapSend(
|
||||||
goSendConfirmation: (ZecSend) -> Unit,
|
goSendConfirmation: (ZecSend) -> Unit,
|
||||||
goSettings: () -> Unit,
|
goSettings: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val hasCameraFeature = activity.packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)
|
|
||||||
|
|
||||||
val walletViewModel by activity.viewModels<WalletViewModel>()
|
val walletViewModel by activity.viewModels<WalletViewModel>()
|
||||||
|
|
||||||
|
val hasCameraFeature = activity.packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)
|
||||||
|
|
||||||
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
|
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
val walletSnapshot = walletViewModel.walletSnapshot.collectAsStateWithLifecycle().value
|
val walletSnapshot = walletViewModel.walletSnapshot.collectAsStateWithLifecycle().value
|
||||||
|
@ -71,6 +72,8 @@ internal fun WrapSend(
|
||||||
// TODO [#1171]: https://github.com/Electric-Coin-Company/zashi-android/issues/1171
|
// TODO [#1171]: https://github.com/Electric-Coin-Company/zashi-android/issues/1171
|
||||||
val monetarySeparators = MonetarySeparators.current(Locale.US)
|
val monetarySeparators = MonetarySeparators.current(Locale.US)
|
||||||
|
|
||||||
|
val walletRestoringState = walletViewModel.walletRestoringState.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
WrapSend(
|
WrapSend(
|
||||||
sendArguments,
|
sendArguments,
|
||||||
synchronizer,
|
synchronizer,
|
||||||
|
@ -83,7 +86,8 @@ internal fun WrapSend(
|
||||||
goSettings,
|
goSettings,
|
||||||
goSendConfirmation,
|
goSendConfirmation,
|
||||||
hasCameraFeature,
|
hasCameraFeature,
|
||||||
monetarySeparators
|
monetarySeparators,
|
||||||
|
walletRestoringState
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +106,8 @@ internal fun WrapSend(
|
||||||
goSettings: () -> Unit,
|
goSettings: () -> Unit,
|
||||||
goSendConfirmation: (ZecSend) -> Unit,
|
goSendConfirmation: (ZecSend) -> Unit,
|
||||||
hasCameraFeature: Boolean,
|
hasCameraFeature: Boolean,
|
||||||
monetarySeparators: MonetarySeparators
|
monetarySeparators: MonetarySeparators,
|
||||||
|
walletRestoringState: WalletRestoringState,
|
||||||
) {
|
) {
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
@ -213,7 +218,8 @@ internal fun WrapSend(
|
||||||
setAmountState = setAmountState,
|
setAmountState = setAmountState,
|
||||||
onQrScannerOpen = goToQrScanner,
|
onQrScannerOpen = goToQrScanner,
|
||||||
goBalances = goBalances,
|
goBalances = goBalances,
|
||||||
hasCameraFeature = hasCameraFeature
|
hasCameraFeature = hasCameraFeature,
|
||||||
|
walletRestoringState = walletRestoringState
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ import cash.z.ecc.sdk.type.ZcashCurrency
|
||||||
import co.electriccoin.zcash.spackle.Twig
|
import co.electriccoin.zcash.spackle.Twig
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
import co.electriccoin.zcash.ui.common.compose.BalanceWidget
|
import co.electriccoin.zcash.ui.common.compose.BalanceWidget
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
||||||
import co.electriccoin.zcash.ui.common.model.canSpend
|
import co.electriccoin.zcash.ui.common.model.canSpend
|
||||||
import co.electriccoin.zcash.ui.common.model.spendableBalance
|
import co.electriccoin.zcash.ui.common.model.spendableBalance
|
||||||
|
@ -94,7 +95,8 @@ private fun PreviewSendForm() {
|
||||||
setAmountState = {},
|
setAmountState = {},
|
||||||
amountState = AmountState.Valid(ZatoshiFixture.ZATOSHI_LONG.toString(), ZatoshiFixture.new()),
|
amountState = AmountState.Valid(ZatoshiFixture.ZATOSHI_LONG.toString(), ZatoshiFixture.new()),
|
||||||
setMemoState = {},
|
setMemoState = {},
|
||||||
memoState = MemoState.new("Test message")
|
memoState = MemoState.new("Test message"),
|
||||||
|
walletRestoringState = WalletRestoringState.NONE
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,7 +108,6 @@ private fun PreviewSendForm() {
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
@Composable
|
@Composable
|
||||||
fun Send(
|
fun Send(
|
||||||
walletSnapshot: WalletSnapshot,
|
|
||||||
sendStage: SendStage,
|
sendStage: SendStage,
|
||||||
onCreateZecSend: (ZecSend) -> Unit,
|
onCreateZecSend: (ZecSend) -> Unit,
|
||||||
focusManager: FocusManager,
|
focusManager: FocusManager,
|
||||||
|
@ -121,9 +122,14 @@ fun Send(
|
||||||
amountState: AmountState,
|
amountState: AmountState,
|
||||||
setMemoState: (MemoState) -> Unit,
|
setMemoState: (MemoState) -> Unit,
|
||||||
memoState: MemoState,
|
memoState: MemoState,
|
||||||
|
walletRestoringState: WalletRestoringState,
|
||||||
|
walletSnapshot: WalletSnapshot,
|
||||||
) {
|
) {
|
||||||
Scaffold(topBar = {
|
Scaffold(topBar = {
|
||||||
SendTopAppBar(onSettings = onSettings)
|
SendTopAppBar(
|
||||||
|
showRestoring = walletRestoringState == WalletRestoringState.RESTORING,
|
||||||
|
onSettings = onSettings
|
||||||
|
)
|
||||||
}) { paddingValues ->
|
}) { paddingValues ->
|
||||||
SendMainContent(
|
SendMainContent(
|
||||||
walletSnapshot = walletSnapshot,
|
walletSnapshot = walletSnapshot,
|
||||||
|
@ -153,8 +159,17 @@ fun Send(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun SendTopAppBar(onSettings: () -> Unit) {
|
private fun SendTopAppBar(
|
||||||
|
onSettings: () -> Unit,
|
||||||
|
showRestoring: Boolean
|
||||||
|
) {
|
||||||
SmallTopAppBar(
|
SmallTopAppBar(
|
||||||
|
restoringLabel =
|
||||||
|
if (showRestoring) {
|
||||||
|
stringResource(id = R.string.restoring_wallet_label)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
},
|
||||||
titleText = stringResource(id = R.string.send_stage_send_title),
|
titleText = stringResource(id = R.string.send_stage_send_title),
|
||||||
hamburgerMenuActions = {
|
hamburgerMenuActions = {
|
||||||
IconButton(
|
IconButton(
|
||||||
|
@ -166,7 +181,7 @@ private fun SendTopAppBar(onSettings: () -> Unit) {
|
||||||
contentDescription = stringResource(id = R.string.settings_menu_content_description)
|
contentDescription = stringResource(id = R.string.settings_menu_content_description)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ import cash.z.ecc.android.sdk.model.ZecSend
|
||||||
import co.electriccoin.zcash.spackle.Twig
|
import co.electriccoin.zcash.spackle.Twig
|
||||||
import co.electriccoin.zcash.ui.MainActivity
|
import co.electriccoin.zcash.ui.MainActivity
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||||
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
|
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
|
||||||
import co.electriccoin.zcash.ui.screen.send.ext.Saver
|
import co.electriccoin.zcash.ui.screen.send.ext.Saver
|
||||||
|
@ -52,13 +53,15 @@ internal fun MainActivity.WrapSendConfirmation(
|
||||||
|
|
||||||
val createTransactionsViewModel by viewModels<CreateTransactionsViewModel>()
|
val createTransactionsViewModel by viewModels<CreateTransactionsViewModel>()
|
||||||
|
|
||||||
val viewModel by viewModels<SupportViewModel>()
|
val supportViewModel by viewModels<SupportViewModel>()
|
||||||
|
|
||||||
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
|
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
val spendingKey = walletViewModel.spendingKey.collectAsStateWithLifecycle().value
|
val spendingKey = walletViewModel.spendingKey.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
val supportMessage = viewModel.supportInfo.collectAsStateWithLifecycle().value
|
val supportMessage = supportViewModel.supportInfo.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
|
val walletRestoringState = walletViewModel.walletRestoringState.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
WrapSendConfirmation(
|
WrapSendConfirmation(
|
||||||
activity = this,
|
activity = this,
|
||||||
|
@ -69,6 +72,7 @@ internal fun MainActivity.WrapSendConfirmation(
|
||||||
spendingKey = spendingKey,
|
spendingKey = spendingKey,
|
||||||
supportMessage = supportMessage,
|
supportMessage = supportMessage,
|
||||||
synchronizer = synchronizer,
|
synchronizer = synchronizer,
|
||||||
|
walletRestoringState = walletRestoringState,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +88,7 @@ internal fun WrapSendConfirmation(
|
||||||
spendingKey: UnifiedSpendingKey?,
|
spendingKey: UnifiedSpendingKey?,
|
||||||
supportMessage: SupportInfo?,
|
supportMessage: SupportInfo?,
|
||||||
synchronizer: Synchronizer?,
|
synchronizer: Synchronizer?,
|
||||||
|
walletRestoringState: WalletRestoringState
|
||||||
) {
|
) {
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
@ -193,7 +198,8 @@ internal fun WrapSendConfirmation(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
walletRestoringState = walletRestoringState
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ import cash.z.ecc.sdk.fixture.MemoFixture
|
||||||
import cash.z.ecc.sdk.fixture.ZatoshiFixture
|
import cash.z.ecc.sdk.fixture.ZatoshiFixture
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
import co.electriccoin.zcash.ui.common.compose.BalanceWidgetBigLineOnly
|
import co.electriccoin.zcash.ui.common.compose.BalanceWidgetBigLineOnly
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
|
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
|
||||||
import co.electriccoin.zcash.ui.design.component.AppAlertDialog
|
import co.electriccoin.zcash.ui.design.component.AppAlertDialog
|
||||||
import co.electriccoin.zcash.ui.design.component.Body
|
import co.electriccoin.zcash.ui.design.component.Body
|
||||||
|
@ -124,9 +125,16 @@ fun SendConfirmation(
|
||||||
stage: SendConfirmationStage,
|
stage: SendConfirmationStage,
|
||||||
submissionResults: ImmutableList<TransactionSubmitResult>,
|
submissionResults: ImmutableList<TransactionSubmitResult>,
|
||||||
zecSend: ZecSend?,
|
zecSend: ZecSend?,
|
||||||
|
walletRestoringState: WalletRestoringState,
|
||||||
) {
|
) {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = { SendConfirmationTopAppBar(onBack, stage) },
|
topBar = {
|
||||||
|
SendConfirmationTopAppBar(
|
||||||
|
onBack = onBack,
|
||||||
|
stage = stage,
|
||||||
|
showRestoring = walletRestoringState == WalletRestoringState.RESTORING,
|
||||||
|
)
|
||||||
|
},
|
||||||
snackbarHost = { SnackbarHost(snackbarHostState) },
|
snackbarHost = { SnackbarHost(snackbarHostState) },
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
SendConfirmationMainContent(
|
SendConfirmationMainContent(
|
||||||
|
@ -152,26 +160,49 @@ fun SendConfirmation(
|
||||||
@Composable
|
@Composable
|
||||||
private fun SendConfirmationTopAppBar(
|
private fun SendConfirmationTopAppBar(
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
stage: SendConfirmationStage
|
stage: SendConfirmationStage,
|
||||||
|
showRestoring: Boolean
|
||||||
) {
|
) {
|
||||||
when (stage) {
|
when (stage) {
|
||||||
SendConfirmationStage.Confirmation,
|
SendConfirmationStage.Confirmation,
|
||||||
SendConfirmationStage.Sending,
|
SendConfirmationStage.Sending,
|
||||||
is SendConfirmationStage.Failure -> {
|
is SendConfirmationStage.Failure -> {
|
||||||
SmallTopAppBar(titleText = stringResource(id = R.string.send_stage_confirmation_title))
|
SmallTopAppBar(
|
||||||
|
restoringLabel =
|
||||||
|
if (showRestoring) {
|
||||||
|
stringResource(id = R.string.restoring_wallet_label)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
},
|
||||||
|
titleText = stringResource(id = R.string.send_stage_confirmation_title),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
SendConfirmationStage.MultipleTrxFailure -> {
|
SendConfirmationStage.MultipleTrxFailure -> {
|
||||||
SmallTopAppBar(titleText = stringResource(id = R.string.send_confirmation_multiple_error_title))
|
SmallTopAppBar(
|
||||||
|
restoringLabel =
|
||||||
|
if (showRestoring) {
|
||||||
|
stringResource(id = R.string.restoring_wallet_label)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
},
|
||||||
|
titleText = stringResource(id = R.string.send_confirmation_multiple_error_title),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
SendConfirmationStage.MultipleTrxFailureReported -> {
|
SendConfirmationStage.MultipleTrxFailureReported -> {
|
||||||
SmallTopAppBar(
|
SmallTopAppBar(
|
||||||
|
restoringLabel =
|
||||||
|
if (showRestoring) {
|
||||||
|
stringResource(id = R.string.restoring_wallet_label)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
},
|
||||||
titleText = stringResource(id = R.string.send_confirmation_multiple_error_title),
|
titleText = stringResource(id = R.string.send_confirmation_multiple_error_title),
|
||||||
backText = stringResource(id = R.string.send_confirmation_multiple_error_back),
|
backText = stringResource(id = R.string.send_confirmation_multiple_error_back),
|
||||||
backContentDescriptionText =
|
backContentDescriptionText =
|
||||||
stringResource(
|
stringResource(
|
||||||
id = R.string.send_confirmation_multiple_error_back_content_description
|
id = R.string.send_confirmation_multiple_error_back_content_description
|
||||||
),
|
),
|
||||||
onBack = onBack
|
onBack = onBack,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import co.electriccoin.zcash.ui.MainActivity
|
import co.electriccoin.zcash.ui.MainActivity
|
||||||
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||||
import co.electriccoin.zcash.ui.configuration.ConfigurationEntries
|
import co.electriccoin.zcash.ui.configuration.ConfigurationEntries
|
||||||
import co.electriccoin.zcash.ui.configuration.RemoteConfig
|
import co.electriccoin.zcash.ui.configuration.RemoteConfig
|
||||||
|
@ -24,40 +25,47 @@ internal fun MainActivity.WrapSettings(
|
||||||
goBack: () -> Unit,
|
goBack: () -> Unit,
|
||||||
goFeedback: () -> Unit,
|
goFeedback: () -> Unit,
|
||||||
) {
|
) {
|
||||||
|
val walletViewModel by viewModels<WalletViewModel>()
|
||||||
|
|
||||||
|
val settingsViewModel by viewModels<SettingsViewModel>()
|
||||||
|
|
||||||
|
val walletRestoringState = walletViewModel.walletRestoringState.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
WrapSettings(
|
WrapSettings(
|
||||||
activity = this,
|
activity = this,
|
||||||
goAbout = goAbout,
|
goAbout = goAbout,
|
||||||
goAdvancedSettings = goAdvancedSettings,
|
goAdvancedSettings = goAdvancedSettings,
|
||||||
goBack = goBack,
|
goBack = goBack,
|
||||||
goFeedback = goFeedback,
|
goFeedback = goFeedback,
|
||||||
|
settingsViewModel = settingsViewModel,
|
||||||
|
walletViewModel = walletViewModel,
|
||||||
|
walletRestoringState = walletRestoringState
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@Suppress("LongParameterList")
|
||||||
private fun WrapSettings(
|
private fun WrapSettings(
|
||||||
activity: ComponentActivity,
|
activity: ComponentActivity,
|
||||||
goAbout: () -> Unit,
|
goAbout: () -> Unit,
|
||||||
goAdvancedSettings: () -> Unit,
|
goAdvancedSettings: () -> Unit,
|
||||||
goBack: () -> Unit,
|
goBack: () -> Unit,
|
||||||
goFeedback: () -> Unit,
|
goFeedback: () -> Unit,
|
||||||
|
settingsViewModel: SettingsViewModel,
|
||||||
|
walletViewModel: WalletViewModel,
|
||||||
|
walletRestoringState: WalletRestoringState,
|
||||||
) {
|
) {
|
||||||
val walletViewModel by activity.viewModels<WalletViewModel>()
|
|
||||||
val settingsViewModel by activity.viewModels<SettingsViewModel>()
|
|
||||||
|
|
||||||
val versionInfo = VersionInfo.new(activity.applicationContext)
|
|
||||||
|
|
||||||
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
|
|
||||||
val isBackgroundSyncEnabled = settingsViewModel.isBackgroundSync.collectAsStateWithLifecycle().value
|
val isBackgroundSyncEnabled = settingsViewModel.isBackgroundSync.collectAsStateWithLifecycle().value
|
||||||
val isKeepScreenOnWhileSyncing = settingsViewModel.isKeepScreenOnWhileSyncing.collectAsStateWithLifecycle().value
|
val isKeepScreenOnWhileSyncing = settingsViewModel.isKeepScreenOnWhileSyncing.collectAsStateWithLifecycle().value
|
||||||
val isAnalyticsEnabled = settingsViewModel.isAnalyticsEnabled.collectAsStateWithLifecycle().value
|
val isAnalyticsEnabled = settingsViewModel.isAnalyticsEnabled.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
|
val versionInfo = VersionInfo.new(activity.applicationContext)
|
||||||
|
|
||||||
BackHandler {
|
BackHandler {
|
||||||
goBack()
|
goBack()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("ComplexCondition")
|
if (null == isAnalyticsEnabled ||
|
||||||
if (null == synchronizer ||
|
|
||||||
null == isAnalyticsEnabled ||
|
|
||||||
null == isBackgroundSyncEnabled ||
|
null == isBackgroundSyncEnabled ||
|
||||||
null == isKeepScreenOnWhileSyncing
|
null == isKeepScreenOnWhileSyncing
|
||||||
) {
|
) {
|
||||||
|
@ -90,7 +98,8 @@ private fun WrapSettings(
|
||||||
},
|
},
|
||||||
onAnalyticsSettingsChanged = {
|
onAnalyticsSettingsChanged = {
|
||||||
settingsViewModel.setAnalyticsEnabled(it)
|
settingsViewModel.setAnalyticsEnabled(it)
|
||||||
}
|
},
|
||||||
|
walletRestoringState = walletRestoringState
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import androidx.compose.ui.platform.testTag
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
|
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
|
||||||
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
||||||
import co.electriccoin.zcash.ui.design.component.PrimaryButton
|
import co.electriccoin.zcash.ui.design.component.PrimaryButton
|
||||||
|
@ -60,6 +61,7 @@ private fun PreviewSettings() {
|
||||||
isAnalyticsEnabled = false,
|
isAnalyticsEnabled = false,
|
||||||
isRescanEnabled = false
|
isRescanEnabled = false
|
||||||
),
|
),
|
||||||
|
walletRestoringState = WalletRestoringState.NONE,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,6 +79,7 @@ fun Settings(
|
||||||
onKeepScreenOnDuringSyncSettingsChanged: (Boolean) -> Unit,
|
onKeepScreenOnDuringSyncSettingsChanged: (Boolean) -> Unit,
|
||||||
onAnalyticsSettingsChanged: (Boolean) -> Unit,
|
onAnalyticsSettingsChanged: (Boolean) -> Unit,
|
||||||
troubleshootingParameters: TroubleshootingParameters,
|
troubleshootingParameters: TroubleshootingParameters,
|
||||||
|
walletRestoringState: WalletRestoringState,
|
||||||
) {
|
) {
|
||||||
Scaffold(topBar = {
|
Scaffold(topBar = {
|
||||||
SettingsTopAppBar(
|
SettingsTopAppBar(
|
||||||
|
@ -86,6 +89,7 @@ fun Settings(
|
||||||
onAnalyticsSettingsChanged = onAnalyticsSettingsChanged,
|
onAnalyticsSettingsChanged = onAnalyticsSettingsChanged,
|
||||||
onRescanWallet = onRescanWallet,
|
onRescanWallet = onRescanWallet,
|
||||||
onBack = onBack,
|
onBack = onBack,
|
||||||
|
showRestoring = walletRestoringState == WalletRestoringState.RESTORING,
|
||||||
)
|
)
|
||||||
}) { paddingValues ->
|
}) { paddingValues ->
|
||||||
SettingsMainContent(
|
SettingsMainContent(
|
||||||
|
@ -116,12 +120,20 @@ private fun SettingsTopAppBar(
|
||||||
onAnalyticsSettingsChanged: (Boolean) -> Unit,
|
onAnalyticsSettingsChanged: (Boolean) -> Unit,
|
||||||
onRescanWallet: () -> Unit,
|
onRescanWallet: () -> Unit,
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
|
showRestoring: Boolean
|
||||||
) {
|
) {
|
||||||
SmallTopAppBar(
|
SmallTopAppBar(
|
||||||
|
restoringLabel =
|
||||||
|
if (showRestoring) {
|
||||||
|
stringResource(id = R.string.restoring_wallet_label)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
},
|
||||||
|
modifier = Modifier.testTag(SettingsTag.SETTINGS_TOP_APP_BAR),
|
||||||
|
showTitleLogo = true,
|
||||||
backText = stringResource(id = R.string.settings_back).uppercase(),
|
backText = stringResource(id = R.string.settings_back).uppercase(),
|
||||||
backContentDescriptionText = stringResource(R.string.settings_back_content_description),
|
backContentDescriptionText = stringResource(R.string.settings_back_content_description),
|
||||||
onBack = onBack,
|
onBack = onBack,
|
||||||
showTitleLogo = true,
|
|
||||||
regularActions = {
|
regularActions = {
|
||||||
if (troubleshootingParameters.isEnabled) {
|
if (troubleshootingParameters.isEnabled) {
|
||||||
TroubleshootingMenu(
|
TroubleshootingMenu(
|
||||||
|
@ -133,7 +145,6 @@ private fun SettingsTopAppBar(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
modifier = Modifier.testTag(SettingsTag.SETTINGS_TOP_APP_BAR)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package co.electriccoin.zcash.ui.screen.settings.viewmodel
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import androidx.lifecycle.AndroidViewModel
|
||||||
|
import co.electriccoin.zcash.ui.common.compose.ScreenBrightness
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
||||||
|
class ScreenBrightnessViewModel(application: Application) : AndroidViewModel(application) {
|
||||||
|
private val screenBrightness: MutableStateFlow<ScreenBrightness> = MutableStateFlow(ScreenBrightness)
|
||||||
|
|
||||||
|
val screenBrightnessState = screenBrightness.value.referenceSwitch
|
||||||
|
|
||||||
|
fun fullBrightness() {
|
||||||
|
screenBrightness.value.fullBrightness()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun restoreBrightness() {
|
||||||
|
screenBrightness.value.restoreBrightness()
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,6 +14,8 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import co.electriccoin.zcash.ui.MainActivity
|
import co.electriccoin.zcash.ui.MainActivity
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
|
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||||
import co.electriccoin.zcash.ui.screen.support.model.SupportInfo
|
import co.electriccoin.zcash.ui.screen.support.model.SupportInfo
|
||||||
import co.electriccoin.zcash.ui.screen.support.model.SupportInfoType
|
import co.electriccoin.zcash.ui.screen.support.model.SupportInfoType
|
||||||
import co.electriccoin.zcash.ui.screen.support.view.Support
|
import co.electriccoin.zcash.ui.screen.support.view.Support
|
||||||
|
@ -23,17 +25,31 @@ import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun MainActivity.WrapSupport(goBack: () -> Unit) {
|
internal fun MainActivity.WrapSupport(goBack: () -> Unit) {
|
||||||
WrapSupport(this, goBack)
|
val supportViewModel by viewModels<SupportViewModel>()
|
||||||
|
|
||||||
|
val walletViewModel by viewModels<WalletViewModel>()
|
||||||
|
|
||||||
|
val supportInfo = supportViewModel.supportInfo.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
|
val walletRestoringState = walletViewModel.walletRestoringState.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
|
WrapSupport(
|
||||||
|
activity = this,
|
||||||
|
goBack = goBack,
|
||||||
|
supportInfo = supportInfo,
|
||||||
|
walletRestoringState = walletRestoringState
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun WrapSupport(
|
internal fun WrapSupport(
|
||||||
activity: ComponentActivity,
|
activity: ComponentActivity,
|
||||||
goBack: () -> Unit
|
goBack: () -> Unit,
|
||||||
|
supportInfo: SupportInfo?,
|
||||||
|
walletRestoringState: WalletRestoringState,
|
||||||
) {
|
) {
|
||||||
val viewModel by activity.viewModels<SupportViewModel>()
|
|
||||||
val supportMessage = viewModel.supportInfo.collectAsStateWithLifecycle().value
|
|
||||||
val snackbarHostState = remember { SnackbarHostState() }
|
val snackbarHostState = remember { SnackbarHostState() }
|
||||||
|
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
val (isShowingDialog, setShowDialog) = rememberSaveable { mutableStateOf(false) }
|
val (isShowingDialog, setShowDialog) = rememberSaveable { mutableStateOf(false) }
|
||||||
|
@ -44,7 +60,7 @@ internal fun WrapSupport(
|
||||||
setShowDialog = setShowDialog,
|
setShowDialog = setShowDialog,
|
||||||
onBack = goBack,
|
onBack = goBack,
|
||||||
onSend = { userMessage ->
|
onSend = { userMessage ->
|
||||||
val fullMessage = formatMessage(userMessage, supportMessage)
|
val fullMessage = formatMessage(userMessage, supportInfo)
|
||||||
|
|
||||||
val mailIntent =
|
val mailIntent =
|
||||||
EmailUtil.newMailActivityIntent(
|
EmailUtil.newMailActivityIntent(
|
||||||
|
@ -67,7 +83,8 @@ internal fun WrapSupport(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
walletRestoringState = walletRestoringState
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package co.electriccoin.zcash.ui.screen.support.view
|
package co.electriccoin.zcash.ui.screen.support.view
|
||||||
|
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
|
@ -9,30 +10,33 @@ import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.filled.ArrowBack
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.SnackbarHost
|
import androidx.compose.material3.SnackbarHost
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
|
import androidx.compose.ui.focus.focusRequester
|
||||||
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.res.vectorResource
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
|
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
|
||||||
import co.electriccoin.zcash.ui.design.component.AppAlertDialog
|
import co.electriccoin.zcash.ui.design.component.AppAlertDialog
|
||||||
import co.electriccoin.zcash.ui.design.component.Body
|
import co.electriccoin.zcash.ui.design.component.Body
|
||||||
import co.electriccoin.zcash.ui.design.component.FormTextField
|
import co.electriccoin.zcash.ui.design.component.FormTextField
|
||||||
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
||||||
import co.electriccoin.zcash.ui.design.component.PrimaryButton
|
import co.electriccoin.zcash.ui.design.component.PrimaryButton
|
||||||
|
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
|
|
||||||
@Preview("Support")
|
@Preview("Support")
|
||||||
|
@ -41,11 +45,12 @@ private fun PreviewSupport() {
|
||||||
ZcashTheme(forceDarkMode = false) {
|
ZcashTheme(forceDarkMode = false) {
|
||||||
GradientSurface {
|
GradientSurface {
|
||||||
Support(
|
Support(
|
||||||
snackbarHostState = SnackbarHostState(),
|
isShowingDialog = false,
|
||||||
|
setShowDialog = {},
|
||||||
onBack = {},
|
onBack = {},
|
||||||
onSend = {},
|
onSend = {},
|
||||||
isShowingDialog = false,
|
snackbarHostState = SnackbarHostState(),
|
||||||
setShowDialog = {}
|
walletRestoringState = WalletRestoringState.NONE
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,18 +70,23 @@ private fun PreviewSupportPopup() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@Suppress("LongParameterList")
|
||||||
fun Support(
|
fun Support(
|
||||||
isShowingDialog: Boolean,
|
isShowingDialog: Boolean,
|
||||||
setShowDialog: (Boolean) -> Unit,
|
setShowDialog: (Boolean) -> Unit,
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
onSend: (String) -> Unit,
|
onSend: (String) -> Unit,
|
||||||
snackbarHostState: SnackbarHostState,
|
snackbarHostState: SnackbarHostState,
|
||||||
|
walletRestoringState: WalletRestoringState,
|
||||||
) {
|
) {
|
||||||
val (message, setMessage) = rememberSaveable { mutableStateOf("") }
|
val (message, setMessage) = rememberSaveable { mutableStateOf("") }
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
SupportTopAppBar(onBack = onBack)
|
SupportTopAppBar(
|
||||||
|
onBack = onBack,
|
||||||
|
showRestoring = walletRestoringState == WalletRestoringState.RESTORING,
|
||||||
|
)
|
||||||
},
|
},
|
||||||
snackbarHost = { SnackbarHost(snackbarHostState) }
|
snackbarHost = { SnackbarHost(snackbarHostState) }
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
|
@ -103,20 +113,21 @@ fun Support(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
private fun SupportTopAppBar(
|
||||||
private fun SupportTopAppBar(onBack: () -> Unit) {
|
onBack: () -> Unit,
|
||||||
TopAppBar(
|
showRestoring: Boolean
|
||||||
title = { Text(text = stringResource(id = R.string.support_header)) },
|
) {
|
||||||
navigationIcon = {
|
SmallTopAppBar(
|
||||||
IconButton(
|
restoringLabel =
|
||||||
onClick = onBack
|
if (showRestoring) {
|
||||||
) {
|
stringResource(id = R.string.restoring_wallet_label)
|
||||||
Icon(
|
} else {
|
||||||
imageVector = Icons.Filled.ArrowBack,
|
null
|
||||||
contentDescription = stringResource(R.string.support_back_content_description)
|
},
|
||||||
)
|
titleText = stringResource(id = R.string.support_header),
|
||||||
}
|
backText = stringResource(id = R.string.support_back).uppercase(),
|
||||||
}
|
backContentDescriptionText = stringResource(R.string.support_back_content_description),
|
||||||
|
onBack = onBack,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,6 +139,8 @@ private fun SupportMainContent(
|
||||||
setShowDialog: (Boolean) -> Unit,
|
setShowDialog: (Boolean) -> Unit,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
|
val focusRequester = remember { FocusRequester() }
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxHeight()
|
.fillMaxHeight()
|
||||||
|
@ -137,7 +150,19 @@ private fun SupportMainContent(
|
||||||
.then(modifier),
|
.then(modifier),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
Body(stringResource(id = R.string.support_information))
|
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall))
|
||||||
|
|
||||||
|
Image(
|
||||||
|
imageVector = ImageVector.vectorResource(R.drawable.zashi_logo_sign),
|
||||||
|
contentDescription = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingBig))
|
||||||
|
|
||||||
|
Body(
|
||||||
|
text = stringResource(id = R.string.support_information),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge))
|
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge))
|
||||||
|
|
||||||
|
@ -146,14 +171,13 @@ private fun SupportMainContent(
|
||||||
onValueChange = setMessage,
|
onValueChange = setMessage,
|
||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth()
|
||||||
|
.focusRequester(focusRequester),
|
||||||
placeholder = { Text(text = stringResource(id = R.string.support_hint)) },
|
placeholder = { Text(text = stringResource(id = R.string.support_hint)) },
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge))
|
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge))
|
||||||
|
|
||||||
Body(stringResource(id = R.string.support_disclaimer))
|
|
||||||
|
|
||||||
Spacer(
|
Spacer(
|
||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
|
@ -166,11 +190,19 @@ private fun SupportMainContent(
|
||||||
PrimaryButton(
|
PrimaryButton(
|
||||||
onClick = { setShowDialog(true) },
|
onClick = { setShowDialog(true) },
|
||||||
text = stringResource(id = R.string.support_send),
|
text = stringResource(id = R.string.support_send),
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = ZcashTheme.dimens.screenHorizontalSpacingRegular)
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingHuge))
|
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingHuge))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
// Causes the TextFiled to focus on the first screen visit
|
||||||
|
focusRequester.requestFocus()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
|
@ -131,7 +131,7 @@ private fun UpdateTopAppBar(updateInfo: UpdateInfo) {
|
||||||
R.string.update_header
|
R.string.update_header
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,4 +7,5 @@
|
||||||
<string name="balance_widget_available">Available Balance:</string>
|
<string name="balance_widget_available">Available Balance:</string>
|
||||||
<!-- This is replaced by a resource overlay via app/build.gradle.kts -->
|
<!-- This is replaced by a resource overlay via app/build.gradle.kts -->
|
||||||
<string name="support_email_address" />
|
<string name="support_email_address" />
|
||||||
|
<string name="restoring_wallet_label">[Restoring Your Wallet…]</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
<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="M10,3.585C9.73,3.585 9.51,3.365 9.51,3.095V0.49C9.51,0.219 9.73,0 10,0C10.27,0 10.49,0.219 10.49,0.49V3.095C10.49,3.365 10.27,3.585 10,3.585Z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M10,20C9.73,20 9.51,19.78 9.51,19.51V16.905C9.51,16.634 9.73,16.415 10,16.415C10.27,16.415 10.49,16.634 10.49,16.905V19.51C10.49,19.78 10.27,20 10,20Z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M10,13.811C12.105,13.811 13.811,12.105 13.811,10C13.811,7.895 12.105,6.189 10,6.189C7.895,6.189 6.189,7.895 6.189,10C6.189,12.105 7.895,13.811 10,13.811Z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M10,14.301C7.629,14.301 5.699,12.371 5.699,10C5.699,7.629 7.629,5.699 10,5.699C12.371,5.699 14.301,7.629 14.301,10C14.301,12.371 12.371,14.301 10,14.301ZM10,6.679C8.168,6.679 6.679,8.168 6.679,10C6.679,11.831 8.168,13.321 10,13.321C11.831,13.321 13.321,11.831 13.321,10C13.321,8.168 11.831,6.679 10,6.679Z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M10,13.404C11.88,13.404 13.403,11.88 13.403,10C13.403,8.121 11.88,6.597 10,6.597V13.404Z"
|
||||||
|
android:fillColor="#ffffff"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M3.095,10.49H0.49C0.219,10.49 0,10.27 0,10C0,9.73 0.219,9.51 0.49,9.51H3.095C3.365,9.51 3.585,9.73 3.585,10C3.585,10.27 3.365,10.49 3.095,10.49Z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M19.51,10.49H16.905C16.634,10.49 16.415,10.27 16.415,10C16.415,9.73 16.634,9.51 16.905,9.51H19.51C19.78,9.51 20,9.73 20,10C20,10.27 19.78,10.49 19.51,10.49Z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M5.117,5.607C4.992,5.607 4.867,5.559 4.771,5.464L2.928,3.622C2.737,3.431 2.737,3.12 2.928,2.929C3.119,2.738 3.43,2.738 3.621,2.929L5.463,4.772C5.654,4.963 5.654,5.273 5.463,5.464C5.367,5.56 5.242,5.607 5.116,5.607H5.117Z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M16.725,17.215C16.6,17.215 16.474,17.167 16.378,17.072L14.536,15.229C14.345,15.038 14.345,14.728 14.536,14.537C14.727,14.346 15.037,14.346 15.228,14.537L17.071,16.379C17.262,16.57 17.262,16.881 17.071,17.072C16.975,17.168 16.849,17.215 16.724,17.215H16.725Z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M3.275,17.215C3.15,17.215 3.024,17.167 2.928,17.072C2.737,16.881 2.737,16.57 2.928,16.379L4.771,14.537C4.962,14.346 5.272,14.346 5.463,14.537C5.654,14.728 5.654,15.038 5.463,15.229L3.621,17.072C3.525,17.168 3.4,17.215 3.274,17.215H3.275Z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M14.882,5.607C14.757,5.607 14.632,5.559 14.536,5.464C14.345,5.273 14.345,4.963 14.536,4.772L16.378,2.929C16.569,2.738 16.88,2.738 17.071,2.929C17.262,3.12 17.262,3.431 17.071,3.622L15.228,5.464C15.132,5.56 15.007,5.607 14.882,5.607H14.882Z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
</group>
|
||||||
|
</vector>
|
|
@ -1,5 +1,6 @@
|
||||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
<string name="support_header">Contact support</string>
|
<string name="support_header">Support</string>
|
||||||
|
<string name="support_back">Back</string>
|
||||||
<string name="support_back_content_description">Back</string>
|
<string name="support_back_content_description">Back</string>
|
||||||
|
|
||||||
<string name="support_hint">How can we help?</string>
|
<string name="support_hint">How can we help?</string>
|
||||||
|
@ -10,6 +11,5 @@
|
||||||
<string name="support_confirmation_explanation"><xliff:g id="app_name" example="Zcash">%1$s</xliff:g> is about to
|
<string name="support_confirmation_explanation"><xliff:g id="app_name" example="Zcash">%1$s</xliff:g> is about to
|
||||||
open your e-mail app with a pre-filled message.\n\nBe sure to hit send within your e-mail app.</string>
|
open your e-mail app with a pre-filled message.\n\nBe sure to hit send within your e-mail app.</string>
|
||||||
<string name="support_information">Please let us know about any problems you have had, or features you want to see in the future.</string>
|
<string name="support_information">Please let us know about any problems you have had, or features you want to see in the future.</string>
|
||||||
<string name="support_disclaimer">Information provided is handled in accordance with our Privacy Policy.</string>
|
|
||||||
<string name="support_unable_to_open_email">Unable to launch email app.</string>
|
<string name="support_unable_to_open_email">Unable to launch email app.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -507,7 +507,7 @@ private fun supportScreenshots(
|
||||||
tag: String,
|
tag: String,
|
||||||
composeTestRule: ComposeTestRule
|
composeTestRule: ComposeTestRule
|
||||||
) {
|
) {
|
||||||
composeTestRule.onNode(hasText(resContext.getString(R.string.support_header))).also {
|
composeTestRule.onNode(hasText(resContext.getString(R.string.support_header).uppercase())).also {
|
||||||
it.assertExists()
|
it.assertExists()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue