[#774] Redesign home with hamburger menu
--------- Co-authored-by: Honza <rychnovsky.honza@gmail.com>
This commit is contained in:
parent
9b966b4087
commit
6d01f210fe
|
@ -31,8 +31,8 @@ android {
|
||||||
"src/main/res/ui/common",
|
"src/main/res/ui/common",
|
||||||
"src/main/res/ui/home",
|
"src/main/res/ui/home",
|
||||||
"src/main/res/ui/onboarding",
|
"src/main/res/ui/onboarding",
|
||||||
"src/main/res/ui/profile",
|
|
||||||
"src/main/res/ui/scan",
|
"src/main/res/ui/scan",
|
||||||
|
"src/main/res/ui/receive",
|
||||||
"src/main/res/ui/restore",
|
"src/main/res/ui/restore",
|
||||||
"src/main/res/ui/request",
|
"src/main/res/ui/request",
|
||||||
"src/main/res/ui/seed",
|
"src/main/res/ui/seed",
|
||||||
|
|
|
@ -10,21 +10,37 @@ import java.util.concurrent.atomic.AtomicInteger
|
||||||
class HomeTestSetup(
|
class HomeTestSetup(
|
||||||
private val composeTestRule: ComposeContentTestRule,
|
private val composeTestRule: ComposeContentTestRule,
|
||||||
private val walletSnapshot: WalletSnapshot,
|
private val walletSnapshot: WalletSnapshot,
|
||||||
private val isRequestZecButtonEnabled: Boolean,
|
|
||||||
) {
|
) {
|
||||||
private val onScanCount = AtomicInteger(0)
|
private val onAboutCount = AtomicInteger(0)
|
||||||
private val onProfileCount = AtomicInteger(0)
|
private val onSeedCount = AtomicInteger(0)
|
||||||
|
private val onSettingsCount = AtomicInteger(0)
|
||||||
|
private val onSupportCount = AtomicInteger(0)
|
||||||
|
private val onReceiveCount = AtomicInteger(0)
|
||||||
private val onSendCount = AtomicInteger(0)
|
private val onSendCount = AtomicInteger(0)
|
||||||
private val onRequestCount = AtomicInteger(0)
|
|
||||||
|
|
||||||
fun getOnScanCount(): Int {
|
fun getOnAboutCount(): Int {
|
||||||
composeTestRule.waitForIdle()
|
composeTestRule.waitForIdle()
|
||||||
return onScanCount.get()
|
return onAboutCount.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getOnProfileCount(): Int {
|
fun getOnSettingsCount(): Int {
|
||||||
composeTestRule.waitForIdle()
|
composeTestRule.waitForIdle()
|
||||||
return onProfileCount.get()
|
return onSettingsCount.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getOnSupportCount(): Int {
|
||||||
|
composeTestRule.waitForIdle()
|
||||||
|
return onSupportCount.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getOnSeedCount(): Int {
|
||||||
|
composeTestRule.waitForIdle()
|
||||||
|
return onSeedCount.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getOnReceiveCount(): Int {
|
||||||
|
composeTestRule.waitForIdle()
|
||||||
|
return onReceiveCount.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getOnSendCount(): Int {
|
fun getOnSendCount(): Int {
|
||||||
|
@ -32,11 +48,6 @@ class HomeTestSetup(
|
||||||
return onSendCount.get()
|
return onSendCount.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getOnRequestCount(): Int {
|
|
||||||
composeTestRule.waitForIdle()
|
|
||||||
return onRequestCount.get()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getWalletSnapshot(): WalletSnapshot {
|
fun getWalletSnapshot(): WalletSnapshot {
|
||||||
composeTestRule.waitForIdle()
|
composeTestRule.waitForIdle()
|
||||||
return walletSnapshot
|
return walletSnapshot
|
||||||
|
@ -46,24 +57,29 @@ class HomeTestSetup(
|
||||||
fun getDefaultContent() {
|
fun getDefaultContent() {
|
||||||
Home(
|
Home(
|
||||||
walletSnapshot,
|
walletSnapshot,
|
||||||
isKeepScreenOnDuringSync = false,
|
|
||||||
isRequestZecButtonEnabled = isRequestZecButtonEnabled,
|
|
||||||
transactionHistory = emptyList(),
|
transactionHistory = emptyList(),
|
||||||
goScan = {
|
isKeepScreenOnDuringSync = false,
|
||||||
onScanCount.incrementAndGet()
|
isUpdateAvailable = false,
|
||||||
|
goSettings = {
|
||||||
|
onSettingsCount.incrementAndGet()
|
||||||
},
|
},
|
||||||
goProfile = {
|
goSeedPhrase = {
|
||||||
onProfileCount.incrementAndGet()
|
onSeedCount.incrementAndGet()
|
||||||
|
},
|
||||||
|
goSupport = {
|
||||||
|
onSupportCount.incrementAndGet()
|
||||||
|
},
|
||||||
|
goAbout = {
|
||||||
|
onAboutCount.incrementAndGet()
|
||||||
|
},
|
||||||
|
goReceive = {
|
||||||
|
onReceiveCount.incrementAndGet()
|
||||||
},
|
},
|
||||||
goSend = {
|
goSend = {
|
||||||
onSendCount.incrementAndGet()
|
onSendCount.incrementAndGet()
|
||||||
},
|
},
|
||||||
goRequest = {
|
|
||||||
onRequestCount.incrementAndGet()
|
|
||||||
},
|
|
||||||
resetSdk = {},
|
resetSdk = {},
|
||||||
isDebugMenuEnabled = false,
|
isDebugMenuEnabled = false,
|
||||||
updateAvailable = false
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,7 @@ class HomeViewIntegrationTest : UiTestPrerequisites() {
|
||||||
|
|
||||||
private fun newTestSetup(walletSnapshot: WalletSnapshot) = HomeTestSetup(
|
private fun newTestSetup(walletSnapshot: WalletSnapshot) = HomeTestSetup(
|
||||||
composeTestRule,
|
composeTestRule,
|
||||||
walletSnapshot,
|
walletSnapshot
|
||||||
isRequestZecButtonEnabled = false
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is just basic sanity check that we still have UI set up as expected after the state restore
|
// This is just basic sanity check that we still have UI set up as expected after the state restore
|
||||||
|
|
|
@ -28,11 +28,7 @@ class HomeViewTest : UiTestPrerequisites() {
|
||||||
fun check_all_elementary_ui_elements_displayed() {
|
fun check_all_elementary_ui_elements_displayed() {
|
||||||
newTestSetup()
|
newTestSetup()
|
||||||
|
|
||||||
composeTestRule.onNodeWithContentDescription(getStringResource(R.string.home_scan_content_description)).also {
|
composeTestRule.onNodeWithContentDescription(getStringResource(R.string.home_menu_content_description)).also {
|
||||||
it.assertIsDisplayed()
|
|
||||||
}
|
|
||||||
|
|
||||||
composeTestRule.onNodeWithContentDescription(getStringResource(R.string.home_profile_content_description)).also {
|
|
||||||
it.assertIsDisplayed()
|
it.assertIsDisplayed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,43 +40,21 @@ class HomeViewTest : UiTestPrerequisites() {
|
||||||
it.assertIsDisplayed()
|
it.assertIsDisplayed()
|
||||||
}
|
}
|
||||||
|
|
||||||
composeTestRule.onNodeWithText(getStringResource(R.string.home_button_request)).also {
|
composeTestRule.onNodeWithText(getStringResource(R.string.home_button_receive)).also {
|
||||||
it.assertIsDisplayed()
|
it.assertIsDisplayed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@MediumTest
|
@MediumTest
|
||||||
fun hide_request_zec() {
|
fun click_receive_button() {
|
||||||
newTestSetup(isRequestZecButtonEnabled = false)
|
|
||||||
|
|
||||||
composeTestRule.onNodeWithText(getStringResource(R.string.home_button_request)).also {
|
|
||||||
it.assertDoesNotExist()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@MediumTest
|
|
||||||
fun click_scan_button() {
|
|
||||||
val testSetup = newTestSetup()
|
val testSetup = newTestSetup()
|
||||||
|
|
||||||
assertEquals(0, testSetup.getOnScanCount())
|
assertEquals(0, testSetup.getOnReceiveCount())
|
||||||
|
|
||||||
composeTestRule.clickScan()
|
composeTestRule.clickReceive()
|
||||||
|
|
||||||
assertEquals(1, testSetup.getOnScanCount())
|
assertEquals(1, testSetup.getOnReceiveCount())
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@MediumTest
|
|
||||||
fun click_profile_button() {
|
|
||||||
val testSetup = newTestSetup()
|
|
||||||
|
|
||||||
assertEquals(0, testSetup.getOnProfileCount())
|
|
||||||
|
|
||||||
composeTestRule.clickProfile()
|
|
||||||
|
|
||||||
assertEquals(1, testSetup.getOnProfileCount())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -97,33 +71,84 @@ class HomeViewTest : UiTestPrerequisites() {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@MediumTest
|
@MediumTest
|
||||||
fun click_request_button() {
|
fun hamburger_seed() {
|
||||||
val testSetup = newTestSetup()
|
val testSetup = newTestSetup()
|
||||||
|
|
||||||
assertEquals(0, testSetup.getOnRequestCount())
|
assertEquals(0, testSetup.getOnReceiveCount())
|
||||||
|
|
||||||
composeTestRule.clickRequest()
|
composeTestRule.openNavigationDrawer()
|
||||||
|
|
||||||
assertEquals(1, testSetup.getOnRequestCount())
|
composeTestRule.onNodeWithText(getStringResource(R.string.home_menu_seed_phrase)).also {
|
||||||
|
it.performClick()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun newTestSetup(isRequestZecButtonEnabled: Boolean = true) = HomeTestSetup(
|
assertEquals(1, testSetup.getOnSeedCount())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@MediumTest
|
||||||
|
fun hamburger_settings() {
|
||||||
|
val testSetup = newTestSetup()
|
||||||
|
|
||||||
|
assertEquals(0, testSetup.getOnReceiveCount())
|
||||||
|
|
||||||
|
composeTestRule.openNavigationDrawer()
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(getStringResource(R.string.home_menu_settings)).also {
|
||||||
|
it.performClick()
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(1, testSetup.getOnSettingsCount())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@MediumTest
|
||||||
|
fun hamburger_support() {
|
||||||
|
val testSetup = newTestSetup()
|
||||||
|
|
||||||
|
assertEquals(0, testSetup.getOnReceiveCount())
|
||||||
|
|
||||||
|
composeTestRule.openNavigationDrawer()
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(getStringResource(R.string.home_menu_support)).also {
|
||||||
|
it.performClick()
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(1, testSetup.getOnSupportCount())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@MediumTest
|
||||||
|
fun hamburger_about() {
|
||||||
|
val testSetup = newTestSetup()
|
||||||
|
|
||||||
|
assertEquals(0, testSetup.getOnReceiveCount())
|
||||||
|
|
||||||
|
composeTestRule.openNavigationDrawer()
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(getStringResource(R.string.home_menu_about)).also {
|
||||||
|
it.performClick()
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(1, testSetup.getOnAboutCount())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun newTestSetup() = HomeTestSetup(
|
||||||
composeTestRule,
|
composeTestRule,
|
||||||
WalletSnapshotFixture.new(),
|
WalletSnapshotFixture.new()
|
||||||
isRequestZecButtonEnabled = isRequestZecButtonEnabled
|
|
||||||
).apply {
|
).apply {
|
||||||
setDefaultContent()
|
setDefaultContent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ComposeContentTestRule.clickScan() {
|
private fun ComposeContentTestRule.openNavigationDrawer() {
|
||||||
onNodeWithContentDescription(getStringResource(R.string.home_scan_content_description)).also {
|
onNodeWithContentDescription(getStringResource(R.string.home_menu_content_description)).also {
|
||||||
it.performClick()
|
it.performClick()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ComposeContentTestRule.clickProfile() {
|
private fun ComposeContentTestRule.clickReceive() {
|
||||||
onNodeWithContentDescription(getStringResource(R.string.home_profile_content_description)).also {
|
onNodeWithText(getStringResource(R.string.home_button_receive)).also {
|
||||||
it.performClick()
|
it.performClick()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,10 +159,3 @@ private fun ComposeContentTestRule.clickSend() {
|
||||||
it.performClick()
|
it.performClick()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ComposeContentTestRule.clickRequest() {
|
|
||||||
onNodeWithText(getStringResource(R.string.home_button_request)).also {
|
|
||||||
it.performScrollTo()
|
|
||||||
it.performClick()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,231 +0,0 @@
|
||||||
package co.electriccoin.zcash.ui.screen.profile.view
|
|
||||||
|
|
||||||
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
|
||||||
import androidx.compose.ui.test.junit4.createComposeRule
|
|
||||||
import androidx.compose.ui.test.onNodeWithContentDescription
|
|
||||||
import androidx.compose.ui.test.onNodeWithText
|
|
||||||
import androidx.compose.ui.test.performClick
|
|
||||||
import androidx.compose.ui.test.performScrollTo
|
|
||||||
import androidx.test.filters.MediumTest
|
|
||||||
import cash.z.ecc.android.sdk.fixture.WalletAddressFixture
|
|
||||||
import cash.z.ecc.android.sdk.model.WalletAddress
|
|
||||||
import co.electriccoin.zcash.ui.R
|
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
|
||||||
import co.electriccoin.zcash.ui.screen.profile.util.ProfileConfiguration
|
|
||||||
import co.electriccoin.zcash.ui.test.getStringResource
|
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|
||||||
import kotlinx.coroutines.test.runTest
|
|
||||||
import org.junit.Assert.assertEquals
|
|
||||||
import org.junit.Rule
|
|
||||||
import org.junit.Test
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Note: It is difficult to test the QR code from automated tests. There is a manual test case
|
|
||||||
* for that currently. A future enhancement could take a screenshot and try to analyze the
|
|
||||||
* screenshot contents.
|
|
||||||
*/
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
|
||||||
class ProfileViewTest {
|
|
||||||
@get:Rule
|
|
||||||
val composeTestRule = createComposeRule()
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@MediumTest
|
|
||||||
fun setup() = runTest {
|
|
||||||
val walletAddress = WalletAddressFixture.unified()
|
|
||||||
newTestSetup(walletAddress)
|
|
||||||
|
|
||||||
// Enable substring for ellipsizing
|
|
||||||
composeTestRule.onNodeWithText(walletAddress.address, substring = true).also {
|
|
||||||
it.assertExists()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@MediumTest
|
|
||||||
fun back() = runTest {
|
|
||||||
val testSetup = newTestSetup(WalletAddressFixture.unified())
|
|
||||||
|
|
||||||
assertEquals(0, testSetup.getOnBackCount())
|
|
||||||
|
|
||||||
composeTestRule.onNodeWithContentDescription(getStringResource(R.string.profile_back_content_description)).also {
|
|
||||||
it.performClick()
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(1, testSetup.getOnBackCount())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@MediumTest
|
|
||||||
fun address_details() = runTest {
|
|
||||||
val testSetup = newTestSetup(WalletAddressFixture.unified())
|
|
||||||
|
|
||||||
assertEquals(0, testSetup.getOnAddressDetailsCount())
|
|
||||||
|
|
||||||
composeTestRule.onNodeWithText(getStringResource(R.string.profile_see_address_details)).also {
|
|
||||||
it.performClick()
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(1, testSetup.getOnAddressDetailsCount())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@MediumTest
|
|
||||||
fun address_book() = runTest {
|
|
||||||
if (ProfileConfiguration.IS_ADDRESS_BOOK_ENABLED) {
|
|
||||||
val testSetup = newTestSetup(WalletAddressFixture.unified())
|
|
||||||
|
|
||||||
assertEquals(0, testSetup.getOnAddressBookCount())
|
|
||||||
|
|
||||||
composeTestRule.onNodeWithText(getStringResource(R.string.profile_address_book)).also {
|
|
||||||
it.performClick()
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(1, testSetup.getOnAddressBookCount())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@MediumTest
|
|
||||||
fun settings() = runTest {
|
|
||||||
val testSetup = newTestSetup(WalletAddressFixture.unified())
|
|
||||||
|
|
||||||
assertEquals(0, testSetup.getOnSettingsCount())
|
|
||||||
|
|
||||||
composeTestRule.onNodeWithText(getStringResource(R.string.profile_settings)).also {
|
|
||||||
it.performScrollTo()
|
|
||||||
it.performClick()
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(1, testSetup.getOnSettingsCount())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@MediumTest
|
|
||||||
fun coinholder_vote() = runTest {
|
|
||||||
if (ProfileConfiguration.IS_COINHOLDER_VOTE_ENABLED) {
|
|
||||||
val testSetup = newTestSetup(WalletAddressFixture.unified())
|
|
||||||
|
|
||||||
assertEquals(0, testSetup.getOnCoinholderVoteCount())
|
|
||||||
|
|
||||||
composeTestRule.onNodeWithText(getStringResource(R.string.profile_coinholder_vote)).also {
|
|
||||||
it.performScrollTo()
|
|
||||||
it.performClick()
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(1, testSetup.getOnCoinholderVoteCount())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@MediumTest
|
|
||||||
fun support() = runTest {
|
|
||||||
val testSetup = newTestSetup(WalletAddressFixture.unified())
|
|
||||||
|
|
||||||
assertEquals(0, testSetup.getOnSupportCount())
|
|
||||||
|
|
||||||
composeTestRule.onNodeWithText(getStringResource(R.string.profile_support)).also {
|
|
||||||
it.performScrollTo()
|
|
||||||
it.assertExists()
|
|
||||||
it.performClick()
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(1, testSetup.getOnSupportCount())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@MediumTest
|
|
||||||
fun about() = runTest {
|
|
||||||
val testSetup = newTestSetup(WalletAddressFixture.unified())
|
|
||||||
|
|
||||||
assertEquals(0, testSetup.getOnAboutCount())
|
|
||||||
|
|
||||||
composeTestRule.onNodeWithText(getStringResource(R.string.profile_about)).also {
|
|
||||||
it.performScrollTo()
|
|
||||||
it.assertExists()
|
|
||||||
it.performClick()
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(1, testSetup.getOnAboutCount())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun newTestSetup(walletAddress: WalletAddress) = TestSetup(composeTestRule, walletAddress)
|
|
||||||
|
|
||||||
private class TestSetup(private val composeTestRule: ComposeContentTestRule, walletAddress: WalletAddress) {
|
|
||||||
|
|
||||||
private val onBackCount = AtomicInteger(0)
|
|
||||||
private val onAddressDetailsCount = AtomicInteger(0)
|
|
||||||
private val onAddressBookCount = AtomicInteger(0)
|
|
||||||
private val onSettingsCount = AtomicInteger(0)
|
|
||||||
private val onCoinholderVoteCount = AtomicInteger(0)
|
|
||||||
private val onSupportCount = AtomicInteger(0)
|
|
||||||
private val onAboutCount = AtomicInteger(0)
|
|
||||||
|
|
||||||
fun getOnBackCount(): Int {
|
|
||||||
composeTestRule.waitForIdle()
|
|
||||||
return onBackCount.get()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getOnAddressDetailsCount(): Int {
|
|
||||||
composeTestRule.waitForIdle()
|
|
||||||
return onAddressDetailsCount.get()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getOnAddressBookCount(): Int {
|
|
||||||
composeTestRule.waitForIdle()
|
|
||||||
return onAddressBookCount.get()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getOnSettingsCount(): Int {
|
|
||||||
composeTestRule.waitForIdle()
|
|
||||||
return onSettingsCount.get()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getOnCoinholderVoteCount(): Int {
|
|
||||||
composeTestRule.waitForIdle()
|
|
||||||
return onCoinholderVoteCount.get()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getOnSupportCount(): Int {
|
|
||||||
composeTestRule.waitForIdle()
|
|
||||||
return onSupportCount.get()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getOnAboutCount(): Int {
|
|
||||||
composeTestRule.waitForIdle()
|
|
||||||
return onAboutCount.get()
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
composeTestRule.setContent {
|
|
||||||
ZcashTheme {
|
|
||||||
Profile(
|
|
||||||
walletAddress,
|
|
||||||
onBack = {
|
|
||||||
onBackCount.getAndIncrement()
|
|
||||||
},
|
|
||||||
onAddressDetails = {
|
|
||||||
onAddressDetailsCount.getAndIncrement()
|
|
||||||
},
|
|
||||||
onAddressBook = {
|
|
||||||
onAddressBookCount.getAndIncrement()
|
|
||||||
},
|
|
||||||
onSettings = {
|
|
||||||
onSettingsCount.getAndIncrement()
|
|
||||||
},
|
|
||||||
onCoinholderVote = {
|
|
||||||
onCoinholderVoteCount.getAndIncrement()
|
|
||||||
},
|
|
||||||
onSupport = {
|
|
||||||
onSupportCount.getAndIncrement()
|
|
||||||
},
|
|
||||||
onAbout = {
|
|
||||||
onAboutCount.getAndIncrement()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
package co.electriccoin.zcash.ui.screen.profile.view
|
package co.electriccoin.zcash.ui.screen.receive.view
|
||||||
|
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
||||||
|
@ -17,7 +17,7 @@ import org.junit.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
class ProfileViewScreenBrightnessTest : UiTestPrerequisites() {
|
class ReceiveViewScreenBrightnessTest : UiTestPrerequisites() {
|
||||||
@get:Rule
|
@get:Rule
|
||||||
val composeTestRule = createComposeRule()
|
val composeTestRule = createComposeRule()
|
||||||
|
|
||||||
|
@ -41,15 +41,10 @@ class ProfileViewScreenBrightnessTest : UiTestPrerequisites() {
|
||||||
CompositionLocalProvider(LocalScreenBrightness provides screenBrightness) {
|
CompositionLocalProvider(LocalScreenBrightness provides screenBrightness) {
|
||||||
ZcashTheme {
|
ZcashTheme {
|
||||||
ZcashTheme {
|
ZcashTheme {
|
||||||
Profile(
|
Receive(
|
||||||
walletAddress,
|
walletAddress,
|
||||||
onBack = { },
|
onBack = { },
|
||||||
onAddressDetails = { },
|
onAddressDetails = { },
|
||||||
onAddressBook = { },
|
|
||||||
onSettings = { },
|
|
||||||
onCoinholderVote = {},
|
|
||||||
onSupport = { },
|
|
||||||
onAbout = { }
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package co.electriccoin.zcash.ui.screen.profile.view
|
package co.electriccoin.zcash.ui.screen.receive.view
|
||||||
|
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
||||||
|
@ -17,7 +17,7 @@ import org.junit.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
class ProfileViewScreenTimeoutTest : UiTestPrerequisites() {
|
class ReceiveViewScreenTimeoutTest : UiTestPrerequisites() {
|
||||||
@get:Rule
|
@get:Rule
|
||||||
val composeTestRule = createComposeRule()
|
val composeTestRule = createComposeRule()
|
||||||
|
|
||||||
|
@ -42,15 +42,10 @@ class ProfileViewScreenTimeoutTest : UiTestPrerequisites() {
|
||||||
CompositionLocalProvider(LocalScreenTimeout provides screenTimeout) {
|
CompositionLocalProvider(LocalScreenTimeout provides screenTimeout) {
|
||||||
ZcashTheme {
|
ZcashTheme {
|
||||||
ZcashTheme {
|
ZcashTheme {
|
||||||
Profile(
|
Receive(
|
||||||
walletAddress,
|
walletAddress,
|
||||||
onBack = { },
|
onBack = { },
|
||||||
onAddressDetails = { },
|
onAddressDetails = { },
|
||||||
onAddressBook = { },
|
|
||||||
onSettings = { },
|
|
||||||
onCoinholderVote = {},
|
|
||||||
onSupport = { },
|
|
||||||
onAbout = { }
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
package co.electriccoin.zcash.ui.screen.receive.view
|
||||||
|
|
||||||
|
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
||||||
|
import androidx.compose.ui.test.junit4.createComposeRule
|
||||||
|
import androidx.compose.ui.test.onNodeWithContentDescription
|
||||||
|
import androidx.compose.ui.test.onNodeWithText
|
||||||
|
import androidx.compose.ui.test.performClick
|
||||||
|
import androidx.test.filters.MediumTest
|
||||||
|
import cash.z.ecc.android.sdk.fixture.WalletAddressFixture
|
||||||
|
import cash.z.ecc.android.sdk.model.WalletAddress
|
||||||
|
import co.electriccoin.zcash.ui.R
|
||||||
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
|
import co.electriccoin.zcash.ui.test.getStringResource
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: It is difficult to test the QR code from automated tests. There is a manual test case
|
||||||
|
* for that currently. A future enhancement could take a screenshot and try to analyze the
|
||||||
|
* screenshot contents.
|
||||||
|
*/
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
class ReceiveViewTest {
|
||||||
|
@get:Rule
|
||||||
|
val composeTestRule = createComposeRule()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@MediumTest
|
||||||
|
fun setup() = runTest {
|
||||||
|
val walletAddress = WalletAddressFixture.unified()
|
||||||
|
newTestSetup(walletAddress)
|
||||||
|
|
||||||
|
// Enable substring for ellipsizing
|
||||||
|
composeTestRule.onNodeWithText(walletAddress.address, substring = true).also {
|
||||||
|
it.assertExists()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@MediumTest
|
||||||
|
fun back() = runTest {
|
||||||
|
val testSetup = newTestSetup(WalletAddressFixture.unified())
|
||||||
|
|
||||||
|
assertEquals(0, testSetup.getOnBackCount())
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithContentDescription(getStringResource(R.string.receive_back_content_description)).also {
|
||||||
|
it.performClick()
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(1, testSetup.getOnBackCount())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@MediumTest
|
||||||
|
fun address_details() = runTest {
|
||||||
|
val testSetup = newTestSetup(WalletAddressFixture.unified())
|
||||||
|
|
||||||
|
assertEquals(0, testSetup.getOnAddressDetailsCount())
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(getStringResource(R.string.receive_see_address_details)).also {
|
||||||
|
it.performClick()
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(1, testSetup.getOnAddressDetailsCount())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun newTestSetup(walletAddress: WalletAddress) = TestSetup(composeTestRule, walletAddress)
|
||||||
|
|
||||||
|
private class TestSetup(private val composeTestRule: ComposeContentTestRule, walletAddress: WalletAddress) {
|
||||||
|
|
||||||
|
private val onBackCount = AtomicInteger(0)
|
||||||
|
private val onAddressDetailsCount = AtomicInteger(0)
|
||||||
|
|
||||||
|
fun getOnBackCount(): Int {
|
||||||
|
composeTestRule.waitForIdle()
|
||||||
|
return onBackCount.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getOnAddressDetailsCount(): Int {
|
||||||
|
composeTestRule.waitForIdle()
|
||||||
|
return onAddressDetailsCount.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
composeTestRule.setContent {
|
||||||
|
ZcashTheme {
|
||||||
|
Receive(
|
||||||
|
walletAddress,
|
||||||
|
onBack = {
|
||||||
|
onBackCount.getAndIncrement()
|
||||||
|
},
|
||||||
|
onAddressDetails = {
|
||||||
|
onAddressDetailsCount.getAndIncrement()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,10 +6,13 @@ import androidx.compose.ui.test.onNodeWithContentDescription
|
||||||
import androidx.compose.ui.test.onNodeWithText
|
import androidx.compose.ui.test.onNodeWithText
|
||||||
import androidx.compose.ui.test.performClick
|
import androidx.compose.ui.test.performClick
|
||||||
import androidx.test.filters.MediumTest
|
import androidx.test.filters.MediumTest
|
||||||
|
import co.electriccoin.zcash.configuration.model.map.StringConfiguration
|
||||||
import co.electriccoin.zcash.test.UiTestPrerequisites
|
import co.electriccoin.zcash.test.UiTestPrerequisites
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
|
import co.electriccoin.zcash.ui.configuration.ConfigurationEntries
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
import co.electriccoin.zcash.ui.test.getStringResource
|
import co.electriccoin.zcash.ui.test.getStringResource
|
||||||
|
import kotlinx.collections.immutable.toPersistentMap
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
|
@ -36,33 +39,25 @@ class SettingsViewTest : UiTestPrerequisites() {
|
||||||
assertEquals(1, testSetup.getOnBackCount())
|
assertEquals(1, testSetup.getOnBackCount())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
@MediumTest
|
|
||||||
fun backup() = runTest {
|
|
||||||
val testSetup = TestSetup(composeTestRule)
|
|
||||||
|
|
||||||
assertEquals(0, testSetup.getBackupCount())
|
|
||||||
|
|
||||||
composeTestRule.onNodeWithText(getStringResource(R.string.settings_backup)).also {
|
|
||||||
it.performClick()
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(1, testSetup.getBackupCount())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@MediumTest
|
@MediumTest
|
||||||
fun rescan() = runTest {
|
fun rescan() = runTest {
|
||||||
val testSetup = TestSetup(composeTestRule)
|
val testSetup = TestSetup(composeTestRule)
|
||||||
|
|
||||||
|
if (ConfigurationEntries.IS_RESCAN_ENABLED.getValue(StringConfiguration(emptyMap<String, String>().toPersistentMap(), null))) {
|
||||||
assertEquals(0, testSetup.getRescanCount())
|
assertEquals(0, testSetup.getRescanCount())
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithContentDescription(getStringResource(R.string.settings_overflow_content_description)).also {
|
||||||
|
it.performClick()
|
||||||
|
}
|
||||||
|
|
||||||
composeTestRule.onNodeWithText(getStringResource(R.string.settings_rescan)).also {
|
composeTestRule.onNodeWithText(getStringResource(R.string.settings_rescan)).also {
|
||||||
it.performClick()
|
it.performClick()
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(1, testSetup.getRescanCount())
|
assertEquals(1, testSetup.getRescanCount())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@MediumTest
|
@MediumTest
|
||||||
|
@ -152,12 +147,10 @@ class SettingsViewTest : UiTestPrerequisites() {
|
||||||
isBackgroundSyncEnabled = true,
|
isBackgroundSyncEnabled = true,
|
||||||
isKeepScreenOnDuringSyncEnabled = true,
|
isKeepScreenOnDuringSyncEnabled = true,
|
||||||
isAnalyticsEnabled = true,
|
isAnalyticsEnabled = true,
|
||||||
|
isRescanEnabled = true,
|
||||||
onBack = {
|
onBack = {
|
||||||
onBackCount.incrementAndGet()
|
onBackCount.incrementAndGet()
|
||||||
},
|
},
|
||||||
onBackupWallet = {
|
|
||||||
onBackupCount.incrementAndGet()
|
|
||||||
},
|
|
||||||
onRescanWallet = {
|
onRescanWallet = {
|
||||||
onRescanCount.incrementAndGet()
|
onRescanCount.incrementAndGet()
|
||||||
},
|
},
|
||||||
|
|
|
@ -9,7 +9,7 @@ import androidx.navigation.compose.composable
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import co.electriccoin.zcash.ui.NavigationTargets.ABOUT
|
import co.electriccoin.zcash.ui.NavigationTargets.ABOUT
|
||||||
import co.electriccoin.zcash.ui.NavigationTargets.HOME
|
import co.electriccoin.zcash.ui.NavigationTargets.HOME
|
||||||
import co.electriccoin.zcash.ui.NavigationTargets.PROFILE
|
import co.electriccoin.zcash.ui.NavigationTargets.RECEIVE
|
||||||
import co.electriccoin.zcash.ui.NavigationTargets.REQUEST
|
import co.electriccoin.zcash.ui.NavigationTargets.REQUEST
|
||||||
import co.electriccoin.zcash.ui.NavigationTargets.SCAN
|
import co.electriccoin.zcash.ui.NavigationTargets.SCAN
|
||||||
import co.electriccoin.zcash.ui.NavigationTargets.SEED
|
import co.electriccoin.zcash.ui.NavigationTargets.SEED
|
||||||
|
@ -22,7 +22,7 @@ import co.electriccoin.zcash.ui.configuration.RemoteConfig
|
||||||
import co.electriccoin.zcash.ui.screen.about.WrapAbout
|
import co.electriccoin.zcash.ui.screen.about.WrapAbout
|
||||||
import co.electriccoin.zcash.ui.screen.address.WrapWalletAddresses
|
import co.electriccoin.zcash.ui.screen.address.WrapWalletAddresses
|
||||||
import co.electriccoin.zcash.ui.screen.home.WrapHome
|
import co.electriccoin.zcash.ui.screen.home.WrapHome
|
||||||
import co.electriccoin.zcash.ui.screen.profile.WrapProfile
|
import co.electriccoin.zcash.ui.screen.receive.WrapReceive
|
||||||
import co.electriccoin.zcash.ui.screen.request.WrapRequest
|
import co.electriccoin.zcash.ui.screen.request.WrapRequest
|
||||||
import co.electriccoin.zcash.ui.screen.scan.WrapScanValidator
|
import co.electriccoin.zcash.ui.screen.scan.WrapScanValidator
|
||||||
import co.electriccoin.zcash.ui.screen.seed.WrapSeed
|
import co.electriccoin.zcash.ui.screen.seed.WrapSeed
|
||||||
|
@ -43,27 +43,18 @@ internal fun MainActivity.Navigation() {
|
||||||
NavHost(navController = navController, startDestination = HOME) {
|
NavHost(navController = navController, startDestination = HOME) {
|
||||||
composable(HOME) {
|
composable(HOME) {
|
||||||
WrapHome(
|
WrapHome(
|
||||||
goScan = { navController.navigateJustOnce(SCAN) },
|
goSeedPhrase = { navController.navigateJustOnce(SEED) },
|
||||||
goProfile = { navController.navigateJustOnce(PROFILE) },
|
goSettings = { navController.navigateJustOnce(SETTINGS) },
|
||||||
|
goSupport = { navController.navigateJustOnce(SUPPORT) },
|
||||||
|
goAbout = { navController.navigateJustOnce(ABOUT) },
|
||||||
|
goReceive = { navController.navigateJustOnce(RECEIVE) },
|
||||||
goSend = { navController.navigateJustOnce(SEND) },
|
goSend = { navController.navigateJustOnce(SEND) },
|
||||||
goRequest = { navController.navigateJustOnce(REQUEST) }
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if (ConfigurationEntries.IS_APP_UPDATE_CHECK_ENABLED.getValue(RemoteConfig.current)) {
|
if (ConfigurationEntries.IS_APP_UPDATE_CHECK_ENABLED.getValue(RemoteConfig.current)) {
|
||||||
WrapCheckForUpdate()
|
WrapCheckForUpdate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
composable(PROFILE) {
|
|
||||||
WrapProfile(
|
|
||||||
onBack = { navController.popBackStackJustOnce(PROFILE) },
|
|
||||||
onAddressDetails = { navController.navigateJustOnce(WALLET_ADDRESS_DETAILS) },
|
|
||||||
onAddressBook = { },
|
|
||||||
onSettings = { navController.navigateJustOnce(SETTINGS) },
|
|
||||||
onCoinholderVote = { },
|
|
||||||
onSupport = { navController.navigateJustOnce(SUPPORT) },
|
|
||||||
onAbout = { navController.navigateJustOnce(ABOUT) }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
composable(WALLET_ADDRESS_DETAILS) {
|
composable(WALLET_ADDRESS_DETAILS) {
|
||||||
WrapWalletAddresses(
|
WrapWalletAddresses(
|
||||||
goBack = {
|
goBack = {
|
||||||
|
@ -75,9 +66,6 @@ internal fun MainActivity.Navigation() {
|
||||||
WrapSettings(
|
WrapSettings(
|
||||||
goBack = {
|
goBack = {
|
||||||
navController.popBackStackJustOnce(SETTINGS)
|
navController.popBackStackJustOnce(SETTINGS)
|
||||||
},
|
|
||||||
goWalletBackup = {
|
|
||||||
navController.navigateJustOnce(SEED)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -88,6 +76,12 @@ internal fun MainActivity.Navigation() {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
composable(RECEIVE) {
|
||||||
|
WrapReceive(
|
||||||
|
onBack = { navController.popBackStackJustOnce(RECEIVE) },
|
||||||
|
onAddressDetails = { navController.navigateJustOnce(WALLET_ADDRESS_DETAILS) }
|
||||||
|
)
|
||||||
|
}
|
||||||
composable(REQUEST) {
|
composable(REQUEST) {
|
||||||
WrapRequest(goBack = { navController.popBackStackJustOnce(REQUEST) })
|
WrapRequest(goBack = { navController.popBackStackJustOnce(REQUEST) })
|
||||||
}
|
}
|
||||||
|
@ -146,14 +140,14 @@ private fun NavHostController.popBackStackJustOnce(currentRouteToBePopped: Strin
|
||||||
object NavigationTargets {
|
object NavigationTargets {
|
||||||
const val HOME = "home"
|
const val HOME = "home"
|
||||||
|
|
||||||
const val PROFILE = "profile"
|
|
||||||
|
|
||||||
const val WALLET_ADDRESS_DETAILS = "wallet_address_details"
|
const val WALLET_ADDRESS_DETAILS = "wallet_address_details"
|
||||||
|
|
||||||
const val SETTINGS = "settings"
|
const val SETTINGS = "settings"
|
||||||
|
|
||||||
const val SEED = "seed"
|
const val SEED = "seed"
|
||||||
|
|
||||||
|
const val RECEIVE = "receive"
|
||||||
|
|
||||||
const val REQUEST = "request"
|
const val REQUEST = "request"
|
||||||
|
|
||||||
const val SEND = "send"
|
const val SEND = "send"
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
package co.electriccoin.zcash.ui.common
|
||||||
|
|
||||||
|
import androidx.compose.material3.DrawerState
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
internal fun DrawerState.openDrawerMenu(scope: CoroutineScope) {
|
||||||
|
if (isOpen) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
scope.launch { open() }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun DrawerState.closeDrawerMenu(scope: CoroutineScope) {
|
||||||
|
if (isClosed) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
scope.launch { close() }
|
||||||
|
}
|
|
@ -6,13 +6,13 @@ import co.electriccoin.zcash.configuration.model.entry.ConfigKey
|
||||||
object ConfigurationEntries {
|
object ConfigurationEntries {
|
||||||
val IS_APP_UPDATE_CHECK_ENABLED = BooleanConfigurationEntry(ConfigKey("is_update_check_enabled"), true)
|
val IS_APP_UPDATE_CHECK_ENABLED = BooleanConfigurationEntry(ConfigKey("is_update_check_enabled"), true)
|
||||||
|
|
||||||
/*
|
|
||||||
* Disabled because we don't have the URI parser support in the SDK yet.
|
|
||||||
*/
|
|
||||||
val IS_REQUEST_ZEC_ENABLED = BooleanConfigurationEntry(ConfigKey("is_request_zec_enabled"), false)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The full onboarding flow is functional and tested, but it is disabled by default for an initially minimal feature set.
|
* The full onboarding flow is functional and tested, but it is disabled by default for an initially minimal feature set.
|
||||||
*/
|
*/
|
||||||
val IS_FULL_ONBOARDING_ENABLED = BooleanConfigurationEntry(ConfigKey("is_full_onboarding_enabled"), false)
|
val IS_FULL_ONBOARDING_ENABLED = BooleanConfigurationEntry(ConfigKey("is_full_onboarding_enabled"), false)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A troubleshooting step. If we fix our bugs, this should be unnecessary.
|
||||||
|
*/
|
||||||
|
val IS_RESCAN_ENABLED = BooleanConfigurationEntry(ConfigKey("is_rescan_enabled"), true)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,16 +3,19 @@
|
||||||
package co.electriccoin.zcash.ui.screen.home
|
package co.electriccoin.zcash.ui.screen.home
|
||||||
|
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
|
import androidx.compose.material3.DrawerValue
|
||||||
|
import androidx.compose.material3.rememberDrawerState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import co.electriccoin.zcash.spackle.EmulatorWtfUtil
|
import co.electriccoin.zcash.spackle.EmulatorWtfUtil
|
||||||
import co.electriccoin.zcash.spackle.FirebaseTestLabUtil
|
import co.electriccoin.zcash.spackle.FirebaseTestLabUtil
|
||||||
import co.electriccoin.zcash.ui.BuildConfig
|
import co.electriccoin.zcash.ui.BuildConfig
|
||||||
import co.electriccoin.zcash.ui.MainActivity
|
import co.electriccoin.zcash.ui.MainActivity
|
||||||
import co.electriccoin.zcash.ui.configuration.ConfigurationEntries
|
import co.electriccoin.zcash.ui.common.closeDrawerMenu
|
||||||
import co.electriccoin.zcash.ui.configuration.RemoteConfig
|
|
||||||
import co.electriccoin.zcash.ui.screen.home.view.Home
|
import co.electriccoin.zcash.ui.screen.home.view.Home
|
||||||
import co.electriccoin.zcash.ui.screen.home.viewmodel.CheckUpdateViewModel
|
import co.electriccoin.zcash.ui.screen.home.viewmodel.CheckUpdateViewModel
|
||||||
import co.electriccoin.zcash.ui.screen.home.viewmodel.WalletViewModel
|
import co.electriccoin.zcash.ui.screen.home.viewmodel.WalletViewModel
|
||||||
|
@ -21,28 +24,36 @@ 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
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@Suppress("LongParameterList")
|
||||||
internal fun MainActivity.WrapHome(
|
internal fun MainActivity.WrapHome(
|
||||||
goScan: () -> Unit,
|
goSeedPhrase: () -> Unit,
|
||||||
goProfile: () -> Unit,
|
goSettings: () -> Unit,
|
||||||
|
goSupport: () -> Unit,
|
||||||
|
goAbout: () -> Unit,
|
||||||
|
goReceive: () -> Unit,
|
||||||
goSend: () -> Unit,
|
goSend: () -> Unit,
|
||||||
goRequest: () -> Unit
|
|
||||||
) {
|
) {
|
||||||
WrapHome(
|
WrapHome(
|
||||||
this,
|
this,
|
||||||
goScan = goScan,
|
goSeedPhrase = goSeedPhrase,
|
||||||
goProfile = goProfile,
|
goSettings = goSettings,
|
||||||
|
goSupport = goSupport,
|
||||||
|
goAbout = goAbout,
|
||||||
|
goReceive = goReceive,
|
||||||
goSend = goSend,
|
goSend = goSend,
|
||||||
goRequest = goRequest
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@Suppress("LongParameterList")
|
||||||
internal fun WrapHome(
|
internal fun WrapHome(
|
||||||
activity: ComponentActivity,
|
activity: ComponentActivity,
|
||||||
goScan: () -> Unit,
|
goSeedPhrase: () -> Unit,
|
||||||
goProfile: () -> Unit,
|
goSettings: () -> Unit,
|
||||||
|
goSupport: () -> Unit,
|
||||||
|
goAbout: () -> Unit,
|
||||||
|
goReceive: () -> Unit,
|
||||||
goSend: () -> Unit,
|
goSend: () -> Unit,
|
||||||
goRequest: () -> Unit
|
|
||||||
) {
|
) {
|
||||||
// we want to show information about app update, if available
|
// we want to show information about app update, if available
|
||||||
val checkUpdateViewModel by activity.viewModels<CheckUpdateViewModel> {
|
val checkUpdateViewModel by activity.viewModels<CheckUpdateViewModel> {
|
||||||
|
@ -75,20 +86,29 @@ internal fun WrapHome(
|
||||||
|
|
||||||
val transactionSnapshot = walletViewModel.transactionSnapshot.collectAsStateWithLifecycle().value
|
val transactionSnapshot = walletViewModel.transactionSnapshot.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
|
val drawerState = rememberDrawerState(DrawerValue.Closed)
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
// override Android back navigation action to close drawer, if opened
|
||||||
|
BackHandler(drawerState.isOpen) {
|
||||||
|
drawerState.closeDrawerMenu(scope)
|
||||||
|
}
|
||||||
|
|
||||||
Home(
|
Home(
|
||||||
walletSnapshot,
|
walletSnapshot,
|
||||||
isKeepScreenOnDuringSync = isKeepScreenOnWhileSyncing,
|
|
||||||
isRequestZecButtonEnabled = ConfigurationEntries.IS_REQUEST_ZEC_ENABLED.getValue(RemoteConfig.current),
|
|
||||||
transactionSnapshot,
|
transactionSnapshot,
|
||||||
goScan = goScan,
|
isUpdateAvailable = updateAvailable,
|
||||||
goRequest = goRequest,
|
isKeepScreenOnDuringSync = isKeepScreenOnWhileSyncing,
|
||||||
goSend = goSend,
|
|
||||||
goProfile = goProfile,
|
|
||||||
isDebugMenuEnabled = isDebugMenuEnabled,
|
isDebugMenuEnabled = isDebugMenuEnabled,
|
||||||
|
goSeedPhrase = goSeedPhrase,
|
||||||
|
goSettings = goSettings,
|
||||||
|
goSupport = goSupport,
|
||||||
|
goAbout = goAbout,
|
||||||
|
goReceive = goReceive,
|
||||||
|
goSend = goSend,
|
||||||
resetSdk = {
|
resetSdk = {
|
||||||
walletViewModel.resetSdk()
|
walletViewModel.resetSdk()
|
||||||
},
|
}
|
||||||
updateAvailable = updateAvailable
|
|
||||||
)
|
)
|
||||||
|
|
||||||
activity.reportFullyDrawn()
|
activity.reportFullyDrawn()
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
|
@file:Suppress("TooManyFunctions")
|
||||||
|
|
||||||
package co.electriccoin.zcash.ui.screen.home.view
|
package co.electriccoin.zcash.ui.screen.home.view
|
||||||
|
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.aspectRatio
|
import androidx.compose.foundation.layout.aspectRatio
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
@ -16,21 +17,32 @@ import androidx.compose.foundation.lazy.items
|
||||||
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.Icons
|
||||||
|
import androidx.compose.material.icons.filled.ContactSupport
|
||||||
|
import androidx.compose.material.icons.filled.Info
|
||||||
|
import androidx.compose.material.icons.filled.Menu
|
||||||
import androidx.compose.material.icons.filled.MoreVert
|
import androidx.compose.material.icons.filled.MoreVert
|
||||||
import androidx.compose.material.icons.filled.Person
|
import androidx.compose.material.icons.filled.Password
|
||||||
import androidx.compose.material.icons.filled.QrCodeScanner
|
import androidx.compose.material.icons.filled.Settings
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
|
import androidx.compose.material3.DrawerState
|
||||||
|
import androidx.compose.material3.DrawerValue
|
||||||
import androidx.compose.material3.DropdownMenu
|
import androidx.compose.material3.DropdownMenu
|
||||||
import androidx.compose.material3.DropdownMenuItem
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.ModalDrawerSheet
|
||||||
|
import androidx.compose.material3.ModalNavigationDrawer
|
||||||
|
import androidx.compose.material3.NavigationDrawerItem
|
||||||
|
import androidx.compose.material3.NavigationDrawerItemDefaults
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
import androidx.compose.material3.TopAppBar
|
||||||
|
import androidx.compose.material3.rememberDrawerState
|
||||||
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
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
|
@ -48,19 +60,20 @@ import cash.z.ecc.android.sdk.model.PercentDecimal
|
||||||
import co.electriccoin.zcash.crash.android.GlobalCrashReporter
|
import co.electriccoin.zcash.crash.android.GlobalCrashReporter
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
import co.electriccoin.zcash.ui.common.DisableScreenTimeout
|
import co.electriccoin.zcash.ui.common.DisableScreenTimeout
|
||||||
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
|
import co.electriccoin.zcash.ui.common.closeDrawerMenu
|
||||||
|
import co.electriccoin.zcash.ui.common.openDrawerMenu
|
||||||
import co.electriccoin.zcash.ui.design.component.Body
|
import co.electriccoin.zcash.ui.design.component.Body
|
||||||
import co.electriccoin.zcash.ui.design.component.BodyWithFiatCurrencySymbol
|
import co.electriccoin.zcash.ui.design.component.BodyWithFiatCurrencySymbol
|
||||||
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
||||||
import co.electriccoin.zcash.ui.design.component.HeaderWithZecIcon
|
import co.electriccoin.zcash.ui.design.component.HeaderWithZecIcon
|
||||||
import co.electriccoin.zcash.ui.design.component.PrimaryButton
|
import co.electriccoin.zcash.ui.design.component.PrimaryButton
|
||||||
import co.electriccoin.zcash.ui.design.component.TertiaryButton
|
|
||||||
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.home.HomeTag
|
import co.electriccoin.zcash.ui.screen.home.HomeTag
|
||||||
import co.electriccoin.zcash.ui.screen.home.model.CommonTransaction
|
import co.electriccoin.zcash.ui.screen.home.model.CommonTransaction
|
||||||
import co.electriccoin.zcash.ui.screen.home.model.WalletDisplayValues
|
import co.electriccoin.zcash.ui.screen.home.model.WalletDisplayValues
|
||||||
import co.electriccoin.zcash.ui.screen.home.model.WalletSnapshot
|
import co.electriccoin.zcash.ui.screen.home.model.WalletSnapshot
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
|
@ -68,17 +81,18 @@ fun ComposablePreview() {
|
||||||
ZcashTheme(darkTheme = true) {
|
ZcashTheme(darkTheme = true) {
|
||||||
GradientSurface {
|
GradientSurface {
|
||||||
Home(
|
Home(
|
||||||
WalletSnapshotFixture.new(),
|
walletSnapshot = WalletSnapshotFixture.new(),
|
||||||
|
transactionHistory = emptyList(),
|
||||||
|
isUpdateAvailable = false,
|
||||||
isKeepScreenOnDuringSync = false,
|
isKeepScreenOnDuringSync = false,
|
||||||
isRequestZecButtonEnabled = false,
|
|
||||||
emptyList(),
|
|
||||||
goScan = {},
|
|
||||||
goProfile = {},
|
|
||||||
goSend = {},
|
|
||||||
goRequest = {},
|
|
||||||
resetSdk = {},
|
|
||||||
isDebugMenuEnabled = false,
|
isDebugMenuEnabled = false,
|
||||||
updateAvailable = false
|
goSeedPhrase = {},
|
||||||
|
goSettings = {},
|
||||||
|
goSupport = {},
|
||||||
|
goAbout = {},
|
||||||
|
goReceive = {},
|
||||||
|
goSend = {},
|
||||||
|
resetSdk = {}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,43 +103,72 @@ fun ComposablePreview() {
|
||||||
@Composable
|
@Composable
|
||||||
fun Home(
|
fun Home(
|
||||||
walletSnapshot: WalletSnapshot,
|
walletSnapshot: WalletSnapshot,
|
||||||
isKeepScreenOnDuringSync: Boolean?,
|
|
||||||
isRequestZecButtonEnabled: Boolean,
|
|
||||||
transactionHistory: List<CommonTransaction>,
|
transactionHistory: List<CommonTransaction>,
|
||||||
goScan: () -> Unit,
|
isUpdateAvailable: Boolean,
|
||||||
goProfile: () -> Unit,
|
isKeepScreenOnDuringSync: Boolean?,
|
||||||
goSend: () -> Unit,
|
|
||||||
goRequest: () -> Unit,
|
|
||||||
resetSdk: () -> Unit,
|
|
||||||
isDebugMenuEnabled: Boolean,
|
isDebugMenuEnabled: Boolean,
|
||||||
updateAvailable: Boolean
|
goSeedPhrase: () -> Unit,
|
||||||
|
goSettings: () -> Unit,
|
||||||
|
goSupport: () -> Unit,
|
||||||
|
goAbout: () -> Unit,
|
||||||
|
goReceive: () -> Unit,
|
||||||
|
goSend: () -> Unit,
|
||||||
|
resetSdk: () -> Unit,
|
||||||
|
drawerState: DrawerState = rememberDrawerState(DrawerValue.Closed),
|
||||||
|
scope: CoroutineScope = rememberCoroutineScope()
|
||||||
) {
|
) {
|
||||||
|
ModalNavigationDrawer(
|
||||||
|
drawerState = drawerState,
|
||||||
|
drawerContent = {
|
||||||
|
HomeDrawer(
|
||||||
|
onCloseDrawer = { drawerState.closeDrawerMenu(scope) },
|
||||||
|
goSeedPhrase = goSeedPhrase,
|
||||||
|
goSettings = goSettings,
|
||||||
|
goSupport = goSupport,
|
||||||
|
goAbout = goAbout
|
||||||
|
)
|
||||||
|
},
|
||||||
|
content = {
|
||||||
Scaffold(topBar = {
|
Scaffold(topBar = {
|
||||||
HomeTopAppBar(isDebugMenuEnabled, resetSdk)
|
HomeTopAppBar(
|
||||||
|
isDebugMenuEnabled = isDebugMenuEnabled,
|
||||||
|
openDrawer = { drawerState.openDrawerMenu(scope) },
|
||||||
|
resetSdk = resetSdk
|
||||||
|
)
|
||||||
}) { paddingValues ->
|
}) { paddingValues ->
|
||||||
HomeMainContent(
|
HomeMainContent(
|
||||||
paddingValues,
|
paddingValues,
|
||||||
walletSnapshot,
|
walletSnapshot,
|
||||||
isKeepScreenOnDuringSync = isKeepScreenOnDuringSync,
|
|
||||||
isRequestZecButtonEnabled = isRequestZecButtonEnabled,
|
|
||||||
transactionHistory,
|
transactionHistory,
|
||||||
goScan = goScan,
|
isUpdateAvailable = isUpdateAvailable,
|
||||||
goProfile = goProfile,
|
isKeepScreenOnDuringSync = isKeepScreenOnDuringSync,
|
||||||
|
goReceive = goReceive,
|
||||||
goSend = goSend,
|
goSend = goSend,
|
||||||
goRequest = goRequest,
|
|
||||||
updateAvailable = updateAvailable
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
private fun HomeTopAppBar(
|
private fun HomeTopAppBar(
|
||||||
isDebugMenuEnabled: Boolean,
|
isDebugMenuEnabled: Boolean,
|
||||||
|
openDrawer: () -> Unit,
|
||||||
resetSdk: () -> Unit,
|
resetSdk: () -> Unit,
|
||||||
) {
|
) {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
title = { Text(text = stringResource(id = R.string.app_name)) },
|
title = { Text(text = stringResource(id = R.string.app_name)) },
|
||||||
|
navigationIcon = {
|
||||||
|
IconButton(
|
||||||
|
onClick = openDrawer
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Filled.Menu,
|
||||||
|
contentDescription = stringResource(R.string.home_menu_content_description)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
actions = {
|
actions = {
|
||||||
if (isDebugMenuEnabled) {
|
if (isDebugMenuEnabled) {
|
||||||
DebugMenu(resetSdk)
|
DebugMenu(resetSdk)
|
||||||
|
@ -174,55 +217,82 @@ private fun DebugMenu(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun HomeDrawer(
|
||||||
|
onCloseDrawer: () -> Unit,
|
||||||
|
goSeedPhrase: () -> Unit,
|
||||||
|
goSettings: () -> Unit,
|
||||||
|
goSupport: () -> Unit,
|
||||||
|
goAbout: () -> Unit,
|
||||||
|
) {
|
||||||
|
ModalDrawerSheet {
|
||||||
|
Spacer(Modifier.height(12.dp))
|
||||||
|
NavigationDrawerItem(
|
||||||
|
icon = { Icon(Icons.Default.Password, contentDescription = null) },
|
||||||
|
label = { Text(stringResource(id = R.string.home_menu_seed_phrase)) },
|
||||||
|
selected = false,
|
||||||
|
onClick = {
|
||||||
|
onCloseDrawer()
|
||||||
|
goSeedPhrase()
|
||||||
|
},
|
||||||
|
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
|
||||||
|
)
|
||||||
|
NavigationDrawerItem(
|
||||||
|
icon = { Icon(Icons.Default.Settings, contentDescription = null) },
|
||||||
|
label = { Text(stringResource(id = R.string.home_menu_settings)) },
|
||||||
|
selected = false,
|
||||||
|
onClick = {
|
||||||
|
onCloseDrawer()
|
||||||
|
goSettings()
|
||||||
|
},
|
||||||
|
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
|
||||||
|
)
|
||||||
|
NavigationDrawerItem(
|
||||||
|
icon = { Icon(Icons.Default.ContactSupport, contentDescription = null) },
|
||||||
|
label = { Text(stringResource(id = R.string.home_menu_support)) },
|
||||||
|
selected = false,
|
||||||
|
onClick = {
|
||||||
|
onCloseDrawer()
|
||||||
|
goSupport()
|
||||||
|
},
|
||||||
|
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
|
||||||
|
)
|
||||||
|
NavigationDrawerItem(
|
||||||
|
icon = { Icon(Icons.Default.Info, contentDescription = null) },
|
||||||
|
label = { Text(stringResource(id = R.string.home_menu_about)) },
|
||||||
|
selected = false,
|
||||||
|
onClick = {
|
||||||
|
onCloseDrawer()
|
||||||
|
goAbout()
|
||||||
|
},
|
||||||
|
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
@Composable
|
@Composable
|
||||||
private fun HomeMainContent(
|
private fun HomeMainContent(
|
||||||
paddingValues: PaddingValues,
|
paddingValues: PaddingValues,
|
||||||
walletSnapshot: WalletSnapshot,
|
walletSnapshot: WalletSnapshot,
|
||||||
isKeepScreenOnDuringSync: Boolean?,
|
|
||||||
isRequestZecButtonEnabled: Boolean,
|
|
||||||
transactionHistory: List<CommonTransaction>,
|
transactionHistory: List<CommonTransaction>,
|
||||||
goScan: () -> Unit,
|
isUpdateAvailable: Boolean,
|
||||||
goProfile: () -> Unit,
|
isKeepScreenOnDuringSync: Boolean?,
|
||||||
|
goReceive: () -> Unit,
|
||||||
goSend: () -> Unit,
|
goSend: () -> Unit,
|
||||||
goRequest: () -> Unit,
|
|
||||||
updateAvailable: Boolean
|
|
||||||
) {
|
) {
|
||||||
Column(Modifier.verticalScroll(rememberScrollState())) {
|
Column(
|
||||||
Row(
|
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxWidth()
|
.verticalScroll(rememberScrollState())
|
||||||
.padding(top = paddingValues.calculateTopPadding())
|
.padding(top = paddingValues.calculateTopPadding())
|
||||||
) {
|
) {
|
||||||
IconButton(goScan) {
|
Status(walletSnapshot, isUpdateAvailable)
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Filled.QrCodeScanner,
|
|
||||||
contentDescription = stringResource(R.string.home_scan_content_description)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Spacer(
|
|
||||||
Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.weight(MINIMAL_WEIGHT)
|
|
||||||
)
|
|
||||||
IconButton(goProfile) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Filled.Person,
|
|
||||||
contentDescription = stringResource(R.string.home_profile_content_description)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Status(walletSnapshot, updateAvailable)
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
|
||||||
|
PrimaryButton(onClick = goReceive, text = stringResource(R.string.home_button_receive))
|
||||||
PrimaryButton(onClick = goSend, text = stringResource(R.string.home_button_send))
|
PrimaryButton(onClick = goSend, text = stringResource(R.string.home_button_send))
|
||||||
|
|
||||||
if (isRequestZecButtonEnabled) {
|
|
||||||
TertiaryButton(onClick = goRequest, text = stringResource(R.string.home_button_request))
|
|
||||||
}
|
|
||||||
|
|
||||||
History(transactionHistory)
|
History(transactionHistory)
|
||||||
|
|
||||||
if (isKeepScreenOnDuringSync == true && isSyncing(walletSnapshot.status)) {
|
if (isKeepScreenOnDuringSync == true && isSyncing(walletSnapshot.status)) {
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
package co.electriccoin.zcash.ui.screen.profile.util
|
|
||||||
|
|
||||||
object ProfileConfiguration {
|
|
||||||
const val IS_ADDRESS_BOOK_ENABLED = false
|
|
||||||
const val IS_COINHOLDER_VOTE_ENABLED = false
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
@file:Suppress("ktlint:filename")
|
@file:Suppress("ktlint:filename")
|
||||||
|
|
||||||
package co.electriccoin.zcash.ui.screen.profile
|
package co.electriccoin.zcash.ui.screen.receive
|
||||||
|
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
|
@ -9,82 +9,52 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import cash.z.ecc.android.sdk.model.WalletAddresses
|
import cash.z.ecc.android.sdk.model.WalletAddresses
|
||||||
import co.electriccoin.zcash.ui.MainActivity
|
import co.electriccoin.zcash.ui.MainActivity
|
||||||
import co.electriccoin.zcash.ui.screen.home.viewmodel.WalletViewModel
|
import co.electriccoin.zcash.ui.screen.home.viewmodel.WalletViewModel
|
||||||
import co.electriccoin.zcash.ui.screen.profile.view.Profile
|
import co.electriccoin.zcash.ui.screen.receive.view.Receive
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
internal fun MainActivity.WrapProfile(
|
internal fun MainActivity.WrapReceive(
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
onAddressDetails: () -> Unit,
|
onAddressDetails: () -> Unit,
|
||||||
onAddressBook: () -> Unit,
|
|
||||||
onSettings: () -> Unit,
|
|
||||||
onCoinholderVote: () -> Unit,
|
|
||||||
onSupport: () -> Unit,
|
|
||||||
onAbout: () -> Unit
|
|
||||||
) {
|
) {
|
||||||
WrapProfile(
|
WrapReceive(
|
||||||
this,
|
this,
|
||||||
onBack = onBack,
|
onBack = onBack,
|
||||||
onAddressDetails = onAddressDetails,
|
onAddressDetails = onAddressDetails,
|
||||||
onAddressBook = onAddressBook,
|
|
||||||
onSettings = onSettings,
|
|
||||||
onCoinholderVote = onCoinholderVote,
|
|
||||||
onSupport = onSupport,
|
|
||||||
onAbout = onAbout
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
internal fun WrapProfile(
|
internal fun WrapReceive(
|
||||||
activity: ComponentActivity,
|
activity: ComponentActivity,
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
onAddressDetails: () -> Unit,
|
onAddressDetails: () -> Unit,
|
||||||
onAddressBook: () -> Unit,
|
|
||||||
onSettings: () -> Unit,
|
|
||||||
onCoinholderVote: () -> Unit,
|
|
||||||
onSupport: () -> Unit,
|
|
||||||
onAbout: () -> Unit
|
|
||||||
) {
|
) {
|
||||||
val viewModel by activity.viewModels<WalletViewModel>()
|
val viewModel by activity.viewModels<WalletViewModel>()
|
||||||
val walletAddresses = viewModel.addresses.collectAsStateWithLifecycle().value
|
val walletAddresses = viewModel.addresses.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
WrapProfile(
|
WrapReceive(
|
||||||
walletAddresses,
|
walletAddresses,
|
||||||
onBack = onBack,
|
onBack = onBack,
|
||||||
onAddressDetails = onAddressDetails,
|
onAddressDetails = onAddressDetails,
|
||||||
onAddressBook = onAddressBook,
|
|
||||||
onSettings = onSettings,
|
|
||||||
onCoinholderVote = onCoinholderVote,
|
|
||||||
onSupport = onSupport,
|
|
||||||
onAbout = onAbout
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
internal fun WrapProfile(
|
internal fun WrapReceive(
|
||||||
walletAddresses: WalletAddresses?,
|
walletAddresses: WalletAddresses?,
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
onAddressDetails: () -> Unit,
|
onAddressDetails: () -> Unit,
|
||||||
onAddressBook: () -> Unit,
|
|
||||||
onSettings: () -> Unit,
|
|
||||||
onCoinholderVote: () -> Unit,
|
|
||||||
onSupport: () -> Unit,
|
|
||||||
onAbout: () -> Unit
|
|
||||||
) {
|
) {
|
||||||
if (null == walletAddresses) {
|
if (null == walletAddresses) {
|
||||||
// Display loading indicator
|
// Display loading indicator
|
||||||
} else {
|
} else {
|
||||||
Profile(
|
Receive(
|
||||||
walletAddresses.unified,
|
walletAddresses.unified,
|
||||||
onBack = onBack,
|
onBack = onBack,
|
||||||
onAddressDetails = onAddressDetails,
|
onAddressDetails = onAddressDetails,
|
||||||
onAddressBook = onAddressBook,
|
|
||||||
onSettings = onSettings,
|
|
||||||
onCoinholderVote = onCoinholderVote,
|
|
||||||
onSupport = onSupport,
|
|
||||||
onAbout = onAbout
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package co.electriccoin.zcash.ui.screen.profile.util
|
package co.electriccoin.zcash.ui.screen.receive.util
|
||||||
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
|
@ -1,4 +1,4 @@
|
||||||
package co.electriccoin.zcash.ui.screen.profile.util
|
package co.electriccoin.zcash.ui.screen.receive.util
|
||||||
|
|
||||||
import com.google.zxing.BarcodeFormat
|
import com.google.zxing.BarcodeFormat
|
||||||
import com.google.zxing.qrcode.QRCodeWriter
|
import com.google.zxing.qrcode.QRCodeWriter
|
|
@ -1,4 +1,4 @@
|
||||||
package co.electriccoin.zcash.ui.screen.profile.util
|
package co.electriccoin.zcash.ui.screen.receive.util
|
||||||
|
|
||||||
interface QrCodeGenerator {
|
interface QrCodeGenerator {
|
||||||
/**
|
/**
|
|
@ -1,4 +1,4 @@
|
||||||
package co.electriccoin.zcash.ui.screen.profile.util
|
package co.electriccoin.zcash.ui.screen.receive.util
|
||||||
|
|
||||||
import androidx.compose.ui.graphics.ImageBitmap
|
import androidx.compose.ui.graphics.ImageBitmap
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package co.electriccoin.zcash.ui.screen.profile.view
|
package co.electriccoin.zcash.ui.screen.receive.view
|
||||||
|
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
@ -6,7 +6,6 @@ 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.Icons
|
||||||
import androidx.compose.material.icons.filled.ArrowBack
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
import androidx.compose.material3.Divider
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
|
@ -30,11 +29,9 @@ import co.electriccoin.zcash.ui.common.DisableScreenTimeout
|
||||||
import co.electriccoin.zcash.ui.design.component.Body
|
import co.electriccoin.zcash.ui.design.component.Body
|
||||||
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.TertiaryButton
|
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
import co.electriccoin.zcash.ui.screen.profile.util.AndroidQrCodeImageGenerator
|
import co.electriccoin.zcash.ui.screen.receive.util.AndroidQrCodeImageGenerator
|
||||||
import co.electriccoin.zcash.ui.screen.profile.util.JvmQrCodeGenerator
|
import co.electriccoin.zcash.ui.screen.receive.util.JvmQrCodeGenerator
|
||||||
import co.electriccoin.zcash.ui.screen.profile.util.ProfileConfiguration
|
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
@ -43,15 +40,10 @@ import kotlin.math.roundToInt
|
||||||
fun ComposablePreview() {
|
fun ComposablePreview() {
|
||||||
ZcashTheme(darkTheme = true) {
|
ZcashTheme(darkTheme = true) {
|
||||||
GradientSurface {
|
GradientSurface {
|
||||||
Profile(
|
Receive(
|
||||||
walletAddress = runBlocking { WalletAddressFixture.unified() },
|
walletAddress = runBlocking { WalletAddressFixture.unified() },
|
||||||
onBack = {},
|
onBack = {},
|
||||||
onAddressDetails = {},
|
onAddressDetails = {},
|
||||||
onAddressBook = {},
|
|
||||||
onSettings = {},
|
|
||||||
onCoinholderVote = {},
|
|
||||||
onSupport = {},
|
|
||||||
onAbout = {}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,44 +51,32 @@ fun ComposablePreview() {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
fun Profile(
|
fun Receive(
|
||||||
walletAddress: WalletAddress,
|
walletAddress: WalletAddress,
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
onAddressDetails: () -> Unit,
|
onAddressDetails: () -> Unit,
|
||||||
onAddressBook: () -> Unit,
|
|
||||||
onSettings: () -> Unit,
|
|
||||||
onCoinholderVote: () -> Unit,
|
|
||||||
onSupport: () -> Unit,
|
|
||||||
onAbout: () -> Unit
|
|
||||||
) {
|
) {
|
||||||
Column {
|
Column {
|
||||||
ProfileTopAppBar(onBack = onBack)
|
ReceiveTopAppBar(onBack = onBack)
|
||||||
ProfileContents(
|
ReceiveContents(
|
||||||
walletAddress = walletAddress,
|
walletAddress = walletAddress,
|
||||||
onAddressDetails = onAddressDetails,
|
onAddressDetails = onAddressDetails,
|
||||||
onAddressBook = onAddressBook,
|
|
||||||
onSettings = onSettings,
|
|
||||||
onCoinholderVote = onCoinholderVote,
|
|
||||||
onSupport = onSupport,
|
|
||||||
onAbout = onAbout,
|
|
||||||
isAddressBookEnabled = ProfileConfiguration.IS_ADDRESS_BOOK_ENABLED,
|
|
||||||
isCoinholderVoteEnabled = ProfileConfiguration.IS_COINHOLDER_VOTE_ENABLED
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
private fun ProfileTopAppBar(onBack: () -> Unit) {
|
private fun ReceiveTopAppBar(onBack: () -> Unit) {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
title = { Text(text = stringResource(id = R.string.profile_title)) },
|
title = { Text(text = stringResource(id = R.string.receive_title)) },
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = onBack
|
onClick = onBack
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Filled.ArrowBack,
|
imageVector = Icons.Filled.ArrowBack,
|
||||||
contentDescription = stringResource(R.string.profile_back_content_description)
|
contentDescription = stringResource(R.string.receive_back_content_description)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,16 +87,9 @@ private val DEFAULT_QR_CODE_SIZE = 320.dp
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
private fun ProfileContents(
|
private fun ReceiveContents(
|
||||||
walletAddress: WalletAddress,
|
walletAddress: WalletAddress,
|
||||||
onAddressDetails: () -> Unit,
|
onAddressDetails: () -> Unit,
|
||||||
onAddressBook: () -> Unit,
|
|
||||||
onSettings: () -> Unit,
|
|
||||||
onCoinholderVote: () -> Unit,
|
|
||||||
onSupport: () -> Unit,
|
|
||||||
onAbout: () -> Unit,
|
|
||||||
isAddressBookEnabled: Boolean,
|
|
||||||
isCoinholderVoteEnabled: Boolean
|
|
||||||
) {
|
) {
|
||||||
Column(Modifier.verticalScroll(rememberScrollState())) {
|
Column(Modifier.verticalScroll(rememberScrollState())) {
|
||||||
QrCode(data = walletAddress.address, DEFAULT_QR_CODE_SIZE, Modifier.align(Alignment.CenterHorizontally))
|
QrCode(data = walletAddress.address, DEFAULT_QR_CODE_SIZE, Modifier.align(Alignment.CenterHorizontally))
|
||||||
|
@ -131,17 +104,7 @@ private fun ProfileContents(
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
maxLines = 1
|
maxLines = 1
|
||||||
)
|
)
|
||||||
PrimaryButton(onClick = onAddressDetails, text = stringResource(id = R.string.profile_see_address_details))
|
PrimaryButton(onClick = onAddressDetails, text = stringResource(id = R.string.receive_see_address_details))
|
||||||
if (isAddressBookEnabled) {
|
|
||||||
TertiaryButton(onClick = onAddressBook, text = stringResource(id = R.string.profile_address_book))
|
|
||||||
}
|
|
||||||
TertiaryButton(onClick = onSettings, text = stringResource(id = R.string.profile_settings))
|
|
||||||
Divider()
|
|
||||||
if (isCoinholderVoteEnabled) {
|
|
||||||
TertiaryButton(onClick = onCoinholderVote, text = stringResource(id = R.string.profile_coinholder_vote))
|
|
||||||
}
|
|
||||||
TertiaryButton(onClick = onSupport, text = stringResource(id = R.string.profile_support))
|
|
||||||
TertiaryButton(onClick = onAbout, text = stringResource(id = R.string.profile_about))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,7 +125,7 @@ private fun QrCode(data: String, size: Dp, modifier: Modifier) {
|
||||||
|
|
||||||
Image(
|
Image(
|
||||||
bitmap = qrCodeImage,
|
bitmap = qrCodeImage,
|
||||||
contentDescription = stringResource(R.string.profile_qr_code_content_description),
|
contentDescription = stringResource(R.string.receive_qr_code_content_description),
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
)
|
)
|
||||||
}
|
}
|
|
@ -24,7 +24,6 @@ import co.electriccoin.zcash.ui.common.SecureScreen
|
||||||
import co.electriccoin.zcash.ui.design.component.Body
|
import co.electriccoin.zcash.ui.design.component.Body
|
||||||
import co.electriccoin.zcash.ui.design.component.ChipGrid
|
import co.electriccoin.zcash.ui.design.component.ChipGrid
|
||||||
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
||||||
import co.electriccoin.zcash.ui.design.component.Header
|
|
||||||
import co.electriccoin.zcash.ui.design.component.TertiaryButton
|
import co.electriccoin.zcash.ui.design.component.TertiaryButton
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
|
|
||||||
|
@ -94,7 +93,6 @@ private fun SeedMainContent(
|
||||||
.verticalScroll(rememberScrollState())
|
.verticalScroll(rememberScrollState())
|
||||||
.padding(top = paddingValues.calculateTopPadding())
|
.padding(top = paddingValues.calculateTopPadding())
|
||||||
) {
|
) {
|
||||||
Header(stringResource(R.string.seed_header))
|
|
||||||
Body(stringResource(R.string.seed_body))
|
Body(stringResource(R.string.seed_body))
|
||||||
|
|
||||||
ChipGrid(persistableWallet.seedPhrase.split)
|
ChipGrid(persistableWallet.seedPhrase.split)
|
||||||
|
|
|
@ -7,19 +7,19 @@ 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 co.electriccoin.zcash.ui.MainActivity
|
import co.electriccoin.zcash.ui.MainActivity
|
||||||
|
import co.electriccoin.zcash.ui.configuration.ConfigurationEntries
|
||||||
|
import co.electriccoin.zcash.ui.configuration.RemoteConfig
|
||||||
import co.electriccoin.zcash.ui.screen.home.viewmodel.WalletViewModel
|
import co.electriccoin.zcash.ui.screen.home.viewmodel.WalletViewModel
|
||||||
import co.electriccoin.zcash.ui.screen.settings.view.Settings
|
import co.electriccoin.zcash.ui.screen.settings.view.Settings
|
||||||
import co.electriccoin.zcash.ui.screen.settings.viewmodel.SettingsViewModel
|
import co.electriccoin.zcash.ui.screen.settings.viewmodel.SettingsViewModel
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun MainActivity.WrapSettings(
|
internal fun MainActivity.WrapSettings(
|
||||||
goBack: () -> Unit,
|
goBack: () -> Unit
|
||||||
goWalletBackup: () -> Unit
|
|
||||||
) {
|
) {
|
||||||
WrapSettings(
|
WrapSettings(
|
||||||
activity = this,
|
activity = this,
|
||||||
goBack = goBack,
|
goBack = goBack,
|
||||||
goWalletBackup = goWalletBackup
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,6 @@ internal fun MainActivity.WrapSettings(
|
||||||
private fun WrapSettings(
|
private fun WrapSettings(
|
||||||
activity: ComponentActivity,
|
activity: ComponentActivity,
|
||||||
goBack: () -> Unit,
|
goBack: () -> Unit,
|
||||||
goWalletBackup: () -> Unit
|
|
||||||
) {
|
) {
|
||||||
val walletViewModel by activity.viewModels<WalletViewModel>()
|
val walletViewModel by activity.viewModels<WalletViewModel>()
|
||||||
val settingsViewModel by activity.viewModels<SettingsViewModel>()
|
val settingsViewModel by activity.viewModels<SettingsViewModel>()
|
||||||
|
@ -45,8 +44,8 @@ private fun WrapSettings(
|
||||||
isBackgroundSyncEnabled = isBackgroundSyncEnabled,
|
isBackgroundSyncEnabled = isBackgroundSyncEnabled,
|
||||||
isKeepScreenOnDuringSyncEnabled = isKeepScreenOnWhileSyncing,
|
isKeepScreenOnDuringSyncEnabled = isKeepScreenOnWhileSyncing,
|
||||||
isAnalyticsEnabled = isAnalyticsEnabled,
|
isAnalyticsEnabled = isAnalyticsEnabled,
|
||||||
|
isRescanEnabled = ConfigurationEntries.IS_RESCAN_ENABLED.getValue(RemoteConfig.current),
|
||||||
onBack = goBack,
|
onBack = goBack,
|
||||||
onBackupWallet = goWalletBackup,
|
|
||||||
onRescanWallet = {
|
onRescanWallet = {
|
||||||
walletViewModel.rescanBlockchain()
|
walletViewModel.rescanBlockchain()
|
||||||
},
|
},
|
||||||
|
|
|
@ -10,6 +10,9 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.ArrowBack
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
|
import androidx.compose.material.icons.filled.MoreVert
|
||||||
|
import androidx.compose.material3.DropdownMenu
|
||||||
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
|
@ -18,7 +21,11 @@ import androidx.compose.material3.Switch
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
import androidx.compose.material3.TopAppBar
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
@ -29,8 +36,6 @@ import co.electriccoin.zcash.ui.R
|
||||||
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.GradientSurface
|
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
||||||
import co.electriccoin.zcash.ui.design.component.PrimaryButton
|
|
||||||
import co.electriccoin.zcash.ui.design.component.TertiaryButton
|
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
|
|
||||||
@Preview("Settings")
|
@Preview("Settings")
|
||||||
|
@ -42,8 +47,8 @@ fun PreviewSettings() {
|
||||||
isBackgroundSyncEnabled = true,
|
isBackgroundSyncEnabled = true,
|
||||||
isKeepScreenOnDuringSyncEnabled = true,
|
isKeepScreenOnDuringSyncEnabled = true,
|
||||||
isAnalyticsEnabled = true,
|
isAnalyticsEnabled = true,
|
||||||
|
isRescanEnabled = true,
|
||||||
onBack = {},
|
onBack = {},
|
||||||
onBackupWallet = {},
|
|
||||||
onRescanWallet = {},
|
onRescanWallet = {},
|
||||||
onBackgroundSyncSettingsChanged = {},
|
onBackgroundSyncSettingsChanged = {},
|
||||||
onIsKeepScreenOnDuringSyncSettingsChanged = {},
|
onIsKeepScreenOnDuringSyncSettingsChanged = {},
|
||||||
|
@ -60,23 +65,25 @@ fun Settings(
|
||||||
isBackgroundSyncEnabled: Boolean,
|
isBackgroundSyncEnabled: Boolean,
|
||||||
isKeepScreenOnDuringSyncEnabled: Boolean,
|
isKeepScreenOnDuringSyncEnabled: Boolean,
|
||||||
isAnalyticsEnabled: Boolean,
|
isAnalyticsEnabled: Boolean,
|
||||||
|
isRescanEnabled: Boolean,
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
onBackupWallet: () -> Unit,
|
|
||||||
onRescanWallet: () -> Unit,
|
onRescanWallet: () -> Unit,
|
||||||
onBackgroundSyncSettingsChanged: (Boolean) -> Unit,
|
onBackgroundSyncSettingsChanged: (Boolean) -> Unit,
|
||||||
onIsKeepScreenOnDuringSyncSettingsChanged: (Boolean) -> Unit,
|
onIsKeepScreenOnDuringSyncSettingsChanged: (Boolean) -> Unit,
|
||||||
onAnalyticsSettingsChanged: (Boolean) -> Unit
|
onAnalyticsSettingsChanged: (Boolean) -> Unit
|
||||||
) {
|
) {
|
||||||
Scaffold(topBar = {
|
Scaffold(topBar = {
|
||||||
SettingsTopAppBar(onBack = onBack)
|
SettingsTopAppBar(
|
||||||
|
isRescanEnabled = isRescanEnabled,
|
||||||
|
onBack = onBack,
|
||||||
|
onRescanWallet = onRescanWallet
|
||||||
|
)
|
||||||
}) { paddingValues ->
|
}) { paddingValues ->
|
||||||
SettingsMainContent(
|
SettingsMainContent(
|
||||||
paddingValues,
|
paddingValues,
|
||||||
isBackgroundSyncEnabled = isBackgroundSyncEnabled,
|
isBackgroundSyncEnabled = isBackgroundSyncEnabled,
|
||||||
isKeepScreenOnDuringSyncEnabled = isKeepScreenOnDuringSyncEnabled,
|
isKeepScreenOnDuringSyncEnabled = isKeepScreenOnDuringSyncEnabled,
|
||||||
isAnalyticsEnabled = isAnalyticsEnabled,
|
isAnalyticsEnabled = isAnalyticsEnabled,
|
||||||
onBackupWallet = onBackupWallet,
|
|
||||||
onRescanWallet = onRescanWallet,
|
|
||||||
onBackgroundSyncSettingsChanged = onBackgroundSyncSettingsChanged,
|
onBackgroundSyncSettingsChanged = onBackgroundSyncSettingsChanged,
|
||||||
onIsKeepScreenOnDuringSyncSettingsChanged = onIsKeepScreenOnDuringSyncSettingsChanged,
|
onIsKeepScreenOnDuringSyncSettingsChanged = onIsKeepScreenOnDuringSyncSettingsChanged,
|
||||||
onAnalyticsSettingsChanged = onAnalyticsSettingsChanged
|
onAnalyticsSettingsChanged = onAnalyticsSettingsChanged
|
||||||
|
@ -86,7 +93,11 @@ fun Settings(
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
private fun SettingsTopAppBar(onBack: () -> Unit) {
|
private fun SettingsTopAppBar(
|
||||||
|
isRescanEnabled: Boolean,
|
||||||
|
onBack: () -> Unit,
|
||||||
|
onRescanWallet: () -> Unit
|
||||||
|
) {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
title = { Text(text = stringResource(id = R.string.settings_header)) },
|
title = { Text(text = stringResource(id = R.string.settings_header)) },
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
|
@ -98,10 +109,38 @@ private fun SettingsTopAppBar(onBack: () -> Unit) {
|
||||||
contentDescription = stringResource(R.string.settings_back_content_description)
|
contentDescription = stringResource(R.string.settings_back_content_description)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
actions = {
|
||||||
|
if (isRescanEnabled) {
|
||||||
|
TroubleshootingMenu(onRescanWallet)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun TroubleshootingMenu(
|
||||||
|
onRescanWallet: () -> Unit
|
||||||
|
) {
|
||||||
|
var expanded by rememberSaveable { mutableStateOf(false) }
|
||||||
|
IconButton(onClick = { expanded = true }) {
|
||||||
|
Icon(Icons.Default.MoreVert, contentDescription = stringResource(id = R.string.settings_overflow_content_description))
|
||||||
|
}
|
||||||
|
|
||||||
|
DropdownMenu(
|
||||||
|
expanded = expanded,
|
||||||
|
onDismissRequest = { expanded = false }
|
||||||
|
) {
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(stringResource(id = R.string.settings_rescan)) },
|
||||||
|
onClick = {
|
||||||
|
onRescanWallet()
|
||||||
|
expanded = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
private fun SettingsMainContent(
|
private fun SettingsMainContent(
|
||||||
|
@ -109,8 +148,6 @@ private fun SettingsMainContent(
|
||||||
isBackgroundSyncEnabled: Boolean,
|
isBackgroundSyncEnabled: Boolean,
|
||||||
isKeepScreenOnDuringSyncEnabled: Boolean,
|
isKeepScreenOnDuringSyncEnabled: Boolean,
|
||||||
isAnalyticsEnabled: Boolean,
|
isAnalyticsEnabled: Boolean,
|
||||||
onBackupWallet: () -> Unit,
|
|
||||||
onRescanWallet: () -> Unit,
|
|
||||||
onBackgroundSyncSettingsChanged: (Boolean) -> Unit,
|
onBackgroundSyncSettingsChanged: (Boolean) -> Unit,
|
||||||
onIsKeepScreenOnDuringSyncSettingsChanged: (Boolean) -> Unit,
|
onIsKeepScreenOnDuringSyncSettingsChanged: (Boolean) -> Unit,
|
||||||
onAnalyticsSettingsChanged: (Boolean) -> Unit
|
onAnalyticsSettingsChanged: (Boolean) -> Unit
|
||||||
|
@ -119,8 +156,6 @@ private fun SettingsMainContent(
|
||||||
Modifier
|
Modifier
|
||||||
.padding(top = paddingValues.calculateTopPadding())
|
.padding(top = paddingValues.calculateTopPadding())
|
||||||
) {
|
) {
|
||||||
PrimaryButton(onClick = onBackupWallet, text = stringResource(id = R.string.settings_backup))
|
|
||||||
TertiaryButton(onClick = onRescanWallet, text = stringResource(id = R.string.settings_rescan))
|
|
||||||
SwitchWithLabel(
|
SwitchWithLabel(
|
||||||
label = stringResource(id = R.string.settings_enable_background_sync),
|
label = stringResource(id = R.string.settings_enable_background_sync),
|
||||||
state = isBackgroundSyncEnabled,
|
state = isBackgroundSyncEnabled,
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
<string name="home_scan_content_description">Scan</string>
|
<string name="home_menu_content_description">Open menu</string>
|
||||||
<string name="home_profile_content_description">Profile</string>
|
<string name="home_button_receive">Receive</string>
|
||||||
<string name="home_button_send">Send</string>
|
<string name="home_button_send">Send</string>
|
||||||
<string name="home_button_request">Request ZEC</string>
|
|
||||||
|
<string name="home_menu_seed_phrase">My secret phrase</string>
|
||||||
|
<string name="home_menu_settings">Settings</string>
|
||||||
|
<string name="home_menu_about">About</string>
|
||||||
|
<string name="home_menu_support">Contact support</string>
|
||||||
|
|
||||||
|
|
||||||
<string name="home_status_syncing_format" formatted="true">Syncing - <xliff:g id="synced_percent" example="50">%1$d</xliff:g>%%</string> <!-- double %% for escaping -->
|
<string name="home_status_syncing_format" formatted="true">Syncing - <xliff:g id="synced_percent" example="50">%1$d</xliff:g>%%</string> <!-- double %% for escaping -->
|
||||||
<string name="home_status_syncing_catchup">Syncing</string>
|
<string name="home_status_syncing_catchup">Syncing</string>
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<string name="profile_title">Profile</string>
|
|
||||||
<string name="profile_back_content_description">Back</string>
|
|
||||||
<string name="profile_qr_code_content_description">QR code for unified address</string>
|
|
||||||
<string name="profile_caption">Your UA Address</string>
|
|
||||||
<string name="profile_see_address_details">See Address Details</string>
|
|
||||||
<string name="profile_address_book">Address Book</string>
|
|
||||||
<string name="profile_settings">Settings</string>
|
|
||||||
<string name="profile_coinholder_vote">Coinholder Vote</string>
|
|
||||||
<string name="profile_support">Support</string>
|
|
||||||
<string name="profile_about">About</string>
|
|
||||||
|
|
||||||
</resources>
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="receive_title">Receive</string>
|
||||||
|
<string name="receive_back_content_description">Back</string>
|
||||||
|
<string name="receive_qr_code_content_description">QR code for unified address</string>
|
||||||
|
<string name="receive_caption">Your UA Address</string>
|
||||||
|
<string name="receive_see_address_details">See Address Details</string>
|
||||||
|
|
||||||
|
</resources>
|
|
@ -1,5 +1,5 @@
|
||||||
<resources>
|
<resources>
|
||||||
<string name="seed_title">Backup Wallet</string>
|
<string name="seed_title">My secret phrase</string>
|
||||||
<string name="seed_back_content_description">Back</string>
|
<string name="seed_back_content_description">Back</string>
|
||||||
|
|
||||||
<string name="seed_header">Your Secret Recovery Phrase</string>
|
<string name="seed_header">Your Secret Recovery Phrase</string>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<resources xmlns:tools="http://schemas.android.com/tools" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
<resources xmlns:tools="http://schemas.android.com/tools" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
<string name="send_title">Send ZEC</string>
|
<string name="send_title">Send ZEC</string>
|
||||||
<string name="send_back_content_description">Back</string>
|
<string name="send_back_content_description">Back</string>
|
||||||
|
<string name="send_scan_content_description">Scan</string>
|
||||||
<string name="send_to">Who would you like to send ZEC to?</string>
|
<string name="send_to">Who would you like to send ZEC to?</string>
|
||||||
<string name="send_amount">How much?</string>
|
<string name="send_amount">How much?</string>
|
||||||
<string name="send_memo">Memo</string>
|
<string name="send_memo">Memo</string>
|
||||||
|
|
|
@ -2,10 +2,8 @@
|
||||||
<string name="settings_header">Settings</string>
|
<string name="settings_header">Settings</string>
|
||||||
<string name="settings_back_content_description">Back</string>
|
<string name="settings_back_content_description">Back</string>
|
||||||
|
|
||||||
<string name="settings_backup">Backup Wallet</string>
|
<string name="settings_overflow_content_description">Additional settings</string>
|
||||||
<string name="settings_wipe">Wipe Wallet Data</string>
|
<string name="settings_rescan">Rescan blockchain</string>
|
||||||
|
|
||||||
<string name="settings_rescan">Rescan Blockchain</string>
|
|
||||||
<string name="settings_enable_background_sync">Background sync</string>
|
<string name="settings_enable_background_sync">Background sync</string>
|
||||||
<string name="settings_enable_keep_screen_on">Keep screen on during sync</string>
|
<string name="settings_enable_keep_screen_on">Keep screen on during sync</string>
|
||||||
<string name="settings_enable_analytics">Report crashes</string>
|
<string name="settings_enable_analytics">Report crashes</string>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<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">Support</string>
|
<string name="support_header">Contact support</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>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="wallet_address_title">Wallet Addresses</string>
|
<string name="wallet_address_title">My wallet address</string>
|
||||||
<string name="wallet_address_back_content_description">Back</string>
|
<string name="wallet_address_back_content_description">Back</string>
|
||||||
<string name="wallet_address_unified">Your Unified Address</string>
|
<string name="wallet_address_unified">Your Unified Address</string>
|
||||||
<string name="wallet_address_header_includes">which includes</string>
|
<string name="wallet_address_header_includes">which includes</string>
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
@file:Suppress("TooManyFunctions")
|
||||||
|
|
||||||
package co.electroniccoin.zcash.ui.screenshot
|
package co.electroniccoin.zcash.ui.screenshot
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
@ -230,106 +232,29 @@ class ScreenshotTest : UiTestPrerequisites() {
|
||||||
backupScreenshots(resContext, tag, composeTestRule)
|
backupScreenshots(resContext, tag, composeTestRule)
|
||||||
homeScreenshots(resContext, tag, composeTestRule)
|
homeScreenshots(resContext, tag, composeTestRule)
|
||||||
|
|
||||||
// Profile screen
|
// These are the buttons on the home screen
|
||||||
// navigateTo(MainActivity.NAV_PROFILE)
|
navigateTo(NavigationTargets.SEND)
|
||||||
composeTestRule.onNode(hasContentDescription(resContext.getString(R.string.home_profile_content_description))).also {
|
|
||||||
it.assertExists()
|
|
||||||
it.performClick()
|
|
||||||
}
|
|
||||||
profileScreenshots(resContext, tag, composeTestRule)
|
|
||||||
|
|
||||||
// Settings is a subscreen of profile
|
|
||||||
composeTestRule.onNode(hasText(resContext.getString(R.string.profile_settings))).also {
|
|
||||||
it.performScrollTo()
|
|
||||||
it.assertExists()
|
|
||||||
it.performClick()
|
|
||||||
}
|
|
||||||
settingsScreenshots(resContext, tag, composeTestRule)
|
|
||||||
|
|
||||||
// Back to profile
|
|
||||||
composeTestRule.onNode(hasContentDescription(resContext.getString(R.string.settings_back_content_description))).also {
|
|
||||||
it.assertExists()
|
|
||||||
it.performClick()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Address Details is a subscreen of profile
|
|
||||||
composeTestRule.onNode(hasText(resContext.getString(R.string.profile_see_address_details))).also {
|
|
||||||
it.performScrollTo()
|
|
||||||
it.assertExists()
|
|
||||||
it.performClick()
|
|
||||||
}
|
|
||||||
addressDetailsScreenshots(resContext, tag, composeTestRule)
|
|
||||||
|
|
||||||
// Back to profile
|
|
||||||
composeTestRule.onNode(hasContentDescription(resContext.getString(R.string.wallet_address_back_content_description))).also {
|
|
||||||
it.assertExists()
|
|
||||||
it.performClick()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Contact Support is a subscreen of profile
|
|
||||||
composeTestRule.onNode(hasText(resContext.getString(R.string.profile_support))).also {
|
|
||||||
it.performScrollTo()
|
|
||||||
it.assertExists()
|
|
||||||
it.performClick()
|
|
||||||
}
|
|
||||||
supportScreenshots(resContext, tag, composeTestRule)
|
|
||||||
|
|
||||||
// Back to profile
|
|
||||||
composeTestRule.onNode(hasContentDescription(resContext.getString(R.string.support_back_content_description))).also {
|
|
||||||
it.assertExists()
|
|
||||||
it.performClick()
|
|
||||||
}
|
|
||||||
|
|
||||||
composeTestRule.onNode(hasText(resContext.getString(R.string.profile_title))).also {
|
|
||||||
it.assertExists()
|
|
||||||
}
|
|
||||||
|
|
||||||
// About is a subscreen of profile
|
|
||||||
composeTestRule.onNode(hasText(resContext.getString(R.string.profile_about))).also {
|
|
||||||
it.performScrollTo()
|
|
||||||
it.assertExists()
|
|
||||||
it.performClick()
|
|
||||||
}
|
|
||||||
aboutScreenshots(resContext, tag, composeTestRule)
|
|
||||||
|
|
||||||
// Back to profile
|
|
||||||
composeTestRule.onNode(hasContentDescription(resContext.getString(R.string.about_back_content_description))).also {
|
|
||||||
it.assertExists()
|
|
||||||
it.performClick()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Back to home
|
|
||||||
composeTestRule.onNode(hasContentDescription(resContext.getString(R.string.settings_back_content_description))).also {
|
|
||||||
it.assertExists()
|
|
||||||
it.performClick()
|
|
||||||
}
|
|
||||||
|
|
||||||
composeTestRule.waitUntil(DEFAULT_TIMEOUT_MILLISECONDS) { composeTestRule.activity.walletViewModel.secretState.value is SecretState.Ready }
|
|
||||||
|
|
||||||
if (ConfigurationEntries.IS_REQUEST_ZEC_ENABLED.getValue(emptyConfiguration)) {
|
|
||||||
composeTestRule.onNode(hasText(resContext.getString(R.string.home_button_request))).also {
|
|
||||||
it.assertExists()
|
|
||||||
it.performClick()
|
|
||||||
}
|
|
||||||
|
|
||||||
composeTestRule.waitUntil(DEFAULT_TIMEOUT_MILLISECONDS) { composeTestRule.activity.walletViewModel.walletSnapshot.value != null }
|
|
||||||
requestZecScreenshots(resContext, tag, composeTestRule)
|
|
||||||
|
|
||||||
navigateTo(NavigationTargets.HOME)
|
|
||||||
composeTestRule.waitUntil(DEFAULT_TIMEOUT_MILLISECONDS) { composeTestRule.activity.walletViewModel.secretState.value is SecretState.Ready }
|
|
||||||
}
|
|
||||||
|
|
||||||
composeTestRule.onNode(hasText(resContext.getString(R.string.home_button_send))).also {
|
|
||||||
it.assertExists()
|
|
||||||
it.performScrollTo()
|
|
||||||
it.performClick()
|
|
||||||
}
|
|
||||||
composeTestRule.waitUntil(DEFAULT_TIMEOUT_MILLISECONDS) { composeTestRule.activity.walletViewModel.synchronizer.value != null }
|
|
||||||
composeTestRule.waitUntil(DEFAULT_TIMEOUT_MILLISECONDS) { composeTestRule.activity.walletViewModel.spendingKey.value != null }
|
|
||||||
composeTestRule.waitUntil(DEFAULT_TIMEOUT_MILLISECONDS) { composeTestRule.activity.walletViewModel.walletSnapshot.value != null }
|
|
||||||
sendZecScreenshots(resContext, tag, composeTestRule)
|
sendZecScreenshots(resContext, tag, composeTestRule)
|
||||||
|
|
||||||
navigateTo(NavigationTargets.HOME)
|
navigateTo(NavigationTargets.RECEIVE)
|
||||||
|
receiveZecScreenshots(resContext, tag, composeTestRule)
|
||||||
|
|
||||||
|
// These are the hamburger menu items
|
||||||
|
// We could manually click on each one, which is a better integration test but a worse screenshot test
|
||||||
|
navigateTo(NavigationTargets.SEED)
|
||||||
|
seedScreenshots(resContext, tag, composeTestRule)
|
||||||
|
|
||||||
|
navigateTo(NavigationTargets.SETTINGS)
|
||||||
|
settingsScreenshots(resContext, tag, composeTestRule)
|
||||||
|
|
||||||
|
navigateTo(NavigationTargets.SUPPORT)
|
||||||
|
supportScreenshots(resContext, tag, composeTestRule)
|
||||||
|
|
||||||
|
navigateTo(NavigationTargets.ABOUT)
|
||||||
|
aboutScreenshots(resContext, tag, composeTestRule)
|
||||||
|
|
||||||
|
navigateTo(NavigationTargets.WALLET_ADDRESS_DETAILS)
|
||||||
|
addressDetailsScreenshots(resContext, tag, composeTestRule)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,17 +411,12 @@ private fun homeScreenshots(resContext: Context, tag: String, composeTestRule: A
|
||||||
it.assertExists()
|
it.assertExists()
|
||||||
ScreenshotTest.takeScreenshot(tag, "Home 1")
|
ScreenshotTest.takeScreenshot(tag, "Home 1")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun profileScreenshots(resContext: Context, tag: String, composeTestRule: AndroidComposeTestRule<ActivityScenarioRule<MainActivity>, MainActivity>) {
|
composeTestRule.onNode(hasContentDescription(resContext.getString(R.string.home_menu_content_description))).also {
|
||||||
// Note: increased timeout limit to satisfy time needed for SDK initialization
|
|
||||||
composeTestRule.waitUntil(DEFAULT_TIMEOUT_MILLISECONDS) { composeTestRule.activity.walletViewModel.addresses.value != null }
|
|
||||||
|
|
||||||
composeTestRule.onNode(hasText(resContext.getString(R.string.profile_title))).also {
|
|
||||||
it.assertExists()
|
it.assertExists()
|
||||||
|
it.performClick()
|
||||||
|
ScreenshotTest.takeScreenshot(tag, "Home 2 - Menu")
|
||||||
}
|
}
|
||||||
|
|
||||||
ScreenshotTest.takeScreenshot(tag, "Profile 1")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun settingsScreenshots(resContext: Context, tag: String, composeTestRule: ComposeTestRule) {
|
private fun settingsScreenshots(resContext: Context, tag: String, composeTestRule: ComposeTestRule) {
|
||||||
|
@ -515,6 +435,8 @@ private fun addressDetailsScreenshots(resContext: Context, tag: String, composeT
|
||||||
ScreenshotTest.takeScreenshot(tag, "Addresses 1")
|
ScreenshotTest.takeScreenshot(tag, "Addresses 1")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This screen is not currently navigable from the app
|
||||||
|
@Suppress("UnusedPrivateMember")
|
||||||
private fun requestZecScreenshots(resContext: Context, tag: String, composeTestRule: ComposeTestRule) {
|
private fun requestZecScreenshots(resContext: Context, tag: String, composeTestRule: ComposeTestRule) {
|
||||||
composeTestRule.onNode(hasText(resContext.getString(R.string.request_title))).also {
|
composeTestRule.onNode(hasText(resContext.getString(R.string.request_title))).also {
|
||||||
it.assertExists()
|
it.assertExists()
|
||||||
|
@ -523,7 +445,29 @@ private fun requestZecScreenshots(resContext: Context, tag: String, composeTestR
|
||||||
ScreenshotTest.takeScreenshot(tag, "Request 1")
|
ScreenshotTest.takeScreenshot(tag, "Request 1")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sendZecScreenshots(resContext: Context, tag: String, composeTestRule: ComposeTestRule) {
|
private fun receiveZecScreenshots(resContext: Context, tag: String, composeTestRule: AndroidComposeTestRule<ActivityScenarioRule<MainActivity>, MainActivity>) {
|
||||||
|
composeTestRule.waitUntil(DEFAULT_TIMEOUT_MILLISECONDS) { composeTestRule.activity.walletViewModel.addresses.value != null }
|
||||||
|
|
||||||
|
composeTestRule.onNode(hasText(resContext.getString(R.string.receive_title))).also {
|
||||||
|
it.assertExists()
|
||||||
|
}
|
||||||
|
|
||||||
|
ScreenshotTest.takeScreenshot(tag, "Receive 1")
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(resContext.getString(R.string.receive_see_address_details)).also {
|
||||||
|
it.performClick()
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.waitForIdle()
|
||||||
|
|
||||||
|
ScreenshotTest.takeScreenshot(tag, "Address details")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendZecScreenshots(resContext: Context, tag: String, composeTestRule: AndroidComposeTestRule<ActivityScenarioRule<MainActivity>, MainActivity>) {
|
||||||
|
composeTestRule.waitUntil(DEFAULT_TIMEOUT_MILLISECONDS) { composeTestRule.activity.walletViewModel.synchronizer.value != null }
|
||||||
|
composeTestRule.waitUntil(DEFAULT_TIMEOUT_MILLISECONDS) { composeTestRule.activity.walletViewModel.spendingKey.value != null }
|
||||||
|
composeTestRule.waitUntil(DEFAULT_TIMEOUT_MILLISECONDS) { composeTestRule.activity.walletViewModel.walletSnapshot.value != null }
|
||||||
|
|
||||||
composeTestRule.onNode(hasText(resContext.getString(R.string.send_title))).also {
|
composeTestRule.onNode(hasText(resContext.getString(R.string.send_title))).also {
|
||||||
it.assertExists()
|
it.assertExists()
|
||||||
}
|
}
|
||||||
|
@ -564,3 +508,11 @@ private fun aboutScreenshots(resContext: Context, tag: String, composeTestRule:
|
||||||
|
|
||||||
ScreenshotTest.takeScreenshot(tag, "About 1")
|
ScreenshotTest.takeScreenshot(tag, "About 1")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun seedScreenshots(resContext: Context, tag: String, composeTestRule: ComposeTestRule) {
|
||||||
|
composeTestRule.onNode(hasText(resContext.getString(R.string.seed_title))).also {
|
||||||
|
it.assertExists()
|
||||||
|
}
|
||||||
|
|
||||||
|
ScreenshotTest.takeScreenshot(tag, "Seed 1")
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue