[#947] About screen UI/logic/tests
* [#947] About screen UI (partially implemented) * [#947] About screen UI * [#947] Fixed failing test case * [#947] Added Zashi text logo --------- Co-authored-by: Honza Rychnovský <rychnovsky.honza@gmail.com> * [#947] UI: About Screen * [#1005] Remove DebugMenu from Home screen - The new design does not require it on the Home screen - Partially moved to the Settings and About screens * [#392] Update About screen texts Closes #392 as not needed now * [#1006] Enhance VersionInfo with other fields * [#947] About screen UI + logic + tests * Adopt VersionInfo on different screens * VersionInfo test Update .gitignore --------- Co-authored-by: Venkat-corebts <143575548+Venkat-corebts@users.noreply.github.com>
This commit is contained in:
parent
e871c4eb45
commit
16bf1afa90
|
@ -23,3 +23,4 @@ local.properties
|
||||||
/.idea/androidTestResultsUserPreferences.xml
|
/.idea/androidTestResultsUserPreferences.xml
|
||||||
google-services.json
|
google-services.json
|
||||||
/.idea/kotlinc.xml
|
/.idea/kotlinc.xml
|
||||||
|
/.idea/other.xml
|
||||||
|
|
|
@ -6,7 +6,6 @@ import co.electriccoin.zcash.configuration.test.fixture.BooleanDefaultEntryFixtu
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.collections.immutable.persistentMapOf
|
import kotlinx.collections.immutable.persistentMapOf
|
||||||
import kotlinx.collections.immutable.toPersistentList
|
import kotlinx.collections.immutable.toPersistentList
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.flow.flowOf
|
import kotlinx.coroutines.flow.flowOf
|
||||||
|
@ -34,7 +33,6 @@ class MergingConfigurationProviderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
|
||||||
fun getFlow_ordering() = runTest {
|
fun getFlow_ordering() = runTest {
|
||||||
val configurationProvider = MergingConfigurationProvider(
|
val configurationProvider = MergingConfigurationProvider(
|
||||||
persistentListOf(
|
persistentListOf(
|
||||||
|
@ -53,7 +51,6 @@ class MergingConfigurationProviderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
|
||||||
fun getFlow_empty() = runTest {
|
fun getFlow_empty() = runTest {
|
||||||
val configurationProvider = MergingConfigurationProvider(
|
val configurationProvider = MergingConfigurationProvider(
|
||||||
emptyList<ConfigurationProvider>().toPersistentList()
|
emptyList<ConfigurationProvider>().toPersistentList()
|
||||||
|
@ -65,7 +62,6 @@ class MergingConfigurationProviderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
|
||||||
fun getUpdatedAt_newest() = runTest {
|
fun getUpdatedAt_newest() = runTest {
|
||||||
val older = "2023-01-15T08:38:45.415Z".toInstant()
|
val older = "2023-01-15T08:38:45.415Z".toInstant()
|
||||||
val newer = "2023-01-17T08:38:45.415Z".toInstant()
|
val newer = "2023-01-17T08:38:45.415Z".toInstant()
|
||||||
|
|
|
@ -27,6 +27,7 @@ data class Dimens(
|
||||||
val defaultButtonHeight: Dp,
|
val defaultButtonHeight: Dp,
|
||||||
val zcashLogoHeight: Dp,
|
val zcashLogoHeight: Dp,
|
||||||
val zcashLogoWidth: Dp,
|
val zcashLogoWidth: Dp,
|
||||||
|
val zcashTextLogoHeight: Dp
|
||||||
)
|
)
|
||||||
|
|
||||||
private val defaultDimens = Dimens(
|
private val defaultDimens = Dimens(
|
||||||
|
@ -45,6 +46,7 @@ private val defaultDimens = Dimens(
|
||||||
defaultButtonHeight = 50.dp,
|
defaultButtonHeight = 50.dp,
|
||||||
zcashLogoHeight = 100.dp,
|
zcashLogoHeight = 100.dp,
|
||||||
zcashLogoWidth = 60.dp,
|
zcashLogoWidth = 60.dp,
|
||||||
|
zcashTextLogoHeight = 30.dp
|
||||||
)
|
)
|
||||||
|
|
||||||
private val normalDimens = defaultDimens
|
private val normalDimens = defaultDimens
|
||||||
|
|
|
@ -31,6 +31,7 @@ data class ExtendedColors(
|
||||||
val disabledButtonTextColor: Color,
|
val disabledButtonTextColor: Color,
|
||||||
val buttonShadowColor: Color,
|
val buttonShadowColor: Color,
|
||||||
val screenTitleColor: Color,
|
val screenTitleColor: Color,
|
||||||
|
val aboutTextColor: Color,
|
||||||
val welcomeAnimationColor: Color,
|
val welcomeAnimationColor: Color,
|
||||||
) {
|
) {
|
||||||
@Composable
|
@Composable
|
||||||
|
|
|
@ -60,6 +60,9 @@ internal object Dark {
|
||||||
|
|
||||||
val buttonShadowColor = Color(0xFFFFFFFF)
|
val buttonShadowColor = Color(0xFFFFFFFF)
|
||||||
|
|
||||||
|
// to be added later
|
||||||
|
val aboutTextColor = Color.Unspecified
|
||||||
|
|
||||||
val screenTitleColor = Color(0xFF040404)
|
val screenTitleColor = Color(0xFF040404)
|
||||||
|
|
||||||
val welcomeAnimationColor = Color(0xFF231F20)
|
val welcomeAnimationColor = Color(0xFF231F20)
|
||||||
|
@ -122,6 +125,8 @@ internal object Light {
|
||||||
|
|
||||||
val screenTitleColor = Color(0xFF040404)
|
val screenTitleColor = Color(0xFF040404)
|
||||||
|
|
||||||
|
val aboutTextColor = Color(0xFF4E4E4E)
|
||||||
|
|
||||||
val welcomeAnimationColor = Color(0xFF231F20)
|
val welcomeAnimationColor = Color(0xFF231F20)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,6 +176,7 @@ internal val DarkExtendedColorPalette = ExtendedColors(
|
||||||
reference = Dark.reference,
|
reference = Dark.reference,
|
||||||
buttonShadowColor = Dark.buttonShadowColor,
|
buttonShadowColor = Dark.buttonShadowColor,
|
||||||
screenTitleColor = Dark.screenTitleColor,
|
screenTitleColor = Dark.screenTitleColor,
|
||||||
|
aboutTextColor = Dark.aboutTextColor,
|
||||||
welcomeAnimationColor = Dark.welcomeAnimationColor
|
welcomeAnimationColor = Dark.welcomeAnimationColor
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -198,6 +204,7 @@ internal val LightExtendedColorPalette = ExtendedColors(
|
||||||
reference = Light.reference,
|
reference = Light.reference,
|
||||||
buttonShadowColor = Light.buttonShadowColor,
|
buttonShadowColor = Light.buttonShadowColor,
|
||||||
screenTitleColor = Light.screenTitleColor,
|
screenTitleColor = Light.screenTitleColor,
|
||||||
|
aboutTextColor = Light.aboutTextColor,
|
||||||
welcomeAnimationColor = Light.welcomeAnimationColor
|
welcomeAnimationColor = Light.welcomeAnimationColor
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -227,6 +234,7 @@ internal val LocalExtendedColors = staticCompositionLocalOf {
|
||||||
reference = Color.Unspecified,
|
reference = Color.Unspecified,
|
||||||
buttonShadowColor = Color.Unspecified,
|
buttonShadowColor = Color.Unspecified,
|
||||||
screenTitleColor = Color.Unspecified,
|
screenTitleColor = Color.Unspecified,
|
||||||
|
aboutTextColor = Color.Unspecified,
|
||||||
welcomeAnimationColor = Color.Unspecified,
|
welcomeAnimationColor = Color.Unspecified,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,6 +112,7 @@ data class ExtendedTypography(
|
||||||
val chipIndex: TextStyle,
|
val chipIndex: TextStyle,
|
||||||
val listItem: TextStyle,
|
val listItem: TextStyle,
|
||||||
val zecBalance: TextStyle,
|
val zecBalance: TextStyle,
|
||||||
|
val aboutText: TextStyle,
|
||||||
val buttonText: TextStyle,
|
val buttonText: TextStyle,
|
||||||
val checkboxText: TextStyle,
|
val checkboxText: TextStyle,
|
||||||
val securityWarningText: TextStyle
|
val securityWarningText: TextStyle
|
||||||
|
@ -141,6 +142,10 @@ val LocalExtendedTypography = staticCompositionLocalOf {
|
||||||
fontWeight = FontWeight.Normal,
|
fontWeight = FontWeight.Normal,
|
||||||
fontSize = 30.sp
|
fontSize = 30.sp
|
||||||
),
|
),
|
||||||
|
aboutText = PrimaryTypography.bodyLarge.copy(
|
||||||
|
fontSize = 14.sp,
|
||||||
|
lineHeight = 20.sp
|
||||||
|
),
|
||||||
buttonText = PrimaryTypography.bodySmall.copy(
|
buttonText = PrimaryTypography.bodySmall.copy(
|
||||||
fontSize = 14.sp
|
fontSize = 14.sp
|
||||||
),
|
),
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
package co.electriccoin.zcash.ui.common.model
|
||||||
|
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import co.electriccoin.zcash.ui.test.getAppContext
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertNotEquals
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
class VersionInfoTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SmallTest
|
||||||
|
fun sanity_check_version_info_in_testing() {
|
||||||
|
val versionInfo = VersionInfo.new(getAppContext())
|
||||||
|
|
||||||
|
// We expect some VersionInfo object parameters to be empty during the testing
|
||||||
|
// isDebuggable is not tested as it's not static during UI testing in CI or locally
|
||||||
|
|
||||||
|
assertEquals("null", versionInfo.versionName)
|
||||||
|
assertEquals(0, versionInfo.versionCode)
|
||||||
|
assertNotEquals(versionInfo.gitSha, "")
|
||||||
|
assertTrue(versionInfo.gitCommitCount >= 1)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,84 +0,0 @@
|
||||||
package co.electriccoin.zcash.ui.screen.about
|
|
||||||
|
|
||||||
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 co.electriccoin.zcash.build.gitSha
|
|
||||||
import co.electriccoin.zcash.ui.R
|
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
|
||||||
import co.electriccoin.zcash.ui.fixture.ConfigInfoFixture
|
|
||||||
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
|
|
||||||
import co.electriccoin.zcash.ui.screen.about.model.VersionInfo
|
|
||||||
import co.electriccoin.zcash.ui.screen.about.view.About
|
|
||||||
import co.electriccoin.zcash.ui.screen.support.model.ConfigInfo
|
|
||||||
import co.electriccoin.zcash.ui.test.getStringResource
|
|
||||||
import org.junit.Assert.assertEquals
|
|
||||||
import org.junit.Rule
|
|
||||||
import org.junit.Test
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
|
||||||
|
|
||||||
class AboutViewTest {
|
|
||||||
@get:Rule
|
|
||||||
val composeTestRule = createComposeRule()
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@MediumTest
|
|
||||||
fun setup() {
|
|
||||||
newTestSetup()
|
|
||||||
|
|
||||||
composeTestRule.onNodeWithText(VersionInfoFixture.VERSION_NAME, substring = true).also {
|
|
||||||
it.assertExists()
|
|
||||||
}
|
|
||||||
|
|
||||||
composeTestRule.onNodeWithText(gitSha, substring = true).also {
|
|
||||||
it.assertExists()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@MediumTest
|
|
||||||
fun back() {
|
|
||||||
val testSetup = newTestSetup()
|
|
||||||
|
|
||||||
assertEquals(0, testSetup.getOnBackCount())
|
|
||||||
|
|
||||||
composeTestRule.onNodeWithContentDescription(getStringResource(R.string.about_back_content_description)).also {
|
|
||||||
it.performClick()
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(1, testSetup.getOnBackCount())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun newTestSetup() = TestSetup(
|
|
||||||
composeTestRule,
|
|
||||||
VersionInfoFixture.new(),
|
|
||||||
ConfigInfoFixture.new()
|
|
||||||
)
|
|
||||||
|
|
||||||
private class TestSetup(
|
|
||||||
private val composeTestRule: ComposeContentTestRule,
|
|
||||||
versionInfo: VersionInfo,
|
|
||||||
configInfo: ConfigInfo
|
|
||||||
) {
|
|
||||||
|
|
||||||
private val onBackCount = AtomicInteger(0)
|
|
||||||
|
|
||||||
fun getOnBackCount(): Int {
|
|
||||||
composeTestRule.waitForIdle()
|
|
||||||
return onBackCount.get()
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
composeTestRule.setContent {
|
|
||||||
ZcashTheme {
|
|
||||||
About(versionInfo = versionInfo, configInfo = configInfo) {
|
|
||||||
onBackCount.incrementAndGet()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
package co.electriccoin.zcash.ui.screen.about.view
|
||||||
|
|
||||||
|
import androidx.compose.ui.test.junit4.createComposeRule
|
||||||
|
import androidx.compose.ui.test.onNodeWithContentDescription
|
||||||
|
import androidx.compose.ui.test.onNodeWithTag
|
||||||
|
import androidx.compose.ui.test.onNodeWithText
|
||||||
|
import androidx.compose.ui.test.performClick
|
||||||
|
import androidx.test.filters.MediumTest
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import co.electriccoin.zcash.ui.R
|
||||||
|
import co.electriccoin.zcash.ui.fixture.ConfigInfoFixture
|
||||||
|
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
|
||||||
|
import co.electriccoin.zcash.ui.screen.about.AboutTag
|
||||||
|
import co.electriccoin.zcash.ui.test.getStringResource
|
||||||
|
import org.junit.Rule
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class AboutViewTest {
|
||||||
|
@get:Rule
|
||||||
|
val composeTestRule = createComposeRule()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@MediumTest
|
||||||
|
fun default_ui_state_test() {
|
||||||
|
val testSetup = newTestSetup()
|
||||||
|
|
||||||
|
assertEquals(0, testSetup.getOnBackCount())
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(getStringResource(R.string.about_back).uppercase()).also {
|
||||||
|
it.assertExists()
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithContentDescription(
|
||||||
|
label = getStringResource(R.string.about_app_logo_content_description)
|
||||||
|
).also {
|
||||||
|
it.assertExists()
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(getStringResource(R.string.about_description)).also {
|
||||||
|
it.assertExists()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@MediumTest
|
||||||
|
fun version_setup_test() {
|
||||||
|
newTestSetup()
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(VersionInfoFixture.VERSION_NAME, substring = true).also {
|
||||||
|
it.assertExists()
|
||||||
|
}
|
||||||
|
composeTestRule.onNodeWithText(VersionInfoFixture.VERSION_CODE.toString(), substring = true).also {
|
||||||
|
it.assertExists()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@MediumTest
|
||||||
|
fun back_test() {
|
||||||
|
val testSetup = newTestSetup()
|
||||||
|
|
||||||
|
assertEquals(0, testSetup.getOnBackCount())
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithContentDescription(getStringResource(R.string.about_back_content_description)).also {
|
||||||
|
it.performClick()
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(1, testSetup.getOnBackCount())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SmallTest
|
||||||
|
fun debug_menu_visible_test() {
|
||||||
|
newTestSetup(isDebuggable = true)
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithTag(AboutTag.DEBUG_MENU_TAG).also {
|
||||||
|
it.assertExists()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SmallTest
|
||||||
|
fun debug_menu_not_visible_test() {
|
||||||
|
newTestSetup(isDebuggable = false)
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithTag(AboutTag.DEBUG_MENU_TAG).also {
|
||||||
|
it.assertDoesNotExist()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun newTestSetup(isDebuggable: Boolean = false) = AboutViewTestSetup(
|
||||||
|
composeTestRule,
|
||||||
|
VersionInfoFixture.new(isDebuggable = isDebuggable),
|
||||||
|
ConfigInfoFixture.new()
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package co.electriccoin.zcash.ui.screen.about.view
|
||||||
|
|
||||||
|
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
||||||
|
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||||
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
|
import co.electriccoin.zcash.ui.screen.support.model.ConfigInfo
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
|
||||||
|
class AboutViewTestSetup(
|
||||||
|
private val composeTestRule: ComposeContentTestRule,
|
||||||
|
versionInfo: VersionInfo,
|
||||||
|
configInfo: ConfigInfo
|
||||||
|
) {
|
||||||
|
|
||||||
|
private val onBackCount = AtomicInteger(0)
|
||||||
|
|
||||||
|
fun getOnBackCount(): Int {
|
||||||
|
composeTestRule.waitForIdle()
|
||||||
|
return onBackCount.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
composeTestRule.setContent {
|
||||||
|
ZcashTheme {
|
||||||
|
About(
|
||||||
|
onBack = { onBackCount.incrementAndGet() },
|
||||||
|
versionInfo = versionInfo,
|
||||||
|
configInfo = configInfo
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -71,7 +71,6 @@ class HomeTestSetup(
|
||||||
isKeepScreenOnDuringSync = false,
|
isKeepScreenOnDuringSync = false,
|
||||||
isFiatConversionEnabled = isShowFiatConversion,
|
isFiatConversionEnabled = isShowFiatConversion,
|
||||||
isCircularProgressBarEnabled = isCircularProgressBar,
|
isCircularProgressBarEnabled = isCircularProgressBar,
|
||||||
isDebugMenuEnabled = false,
|
|
||||||
goSettings = {
|
goSettings = {
|
||||||
onSettingsCount.incrementAndGet()
|
onSettingsCount.incrementAndGet()
|
||||||
},
|
},
|
||||||
|
@ -93,7 +92,6 @@ class HomeTestSetup(
|
||||||
goHistory = {
|
goHistory = {
|
||||||
onHistoryCount.incrementAndGet()
|
onHistoryCount.incrementAndGet()
|
||||||
},
|
},
|
||||||
resetSdk = {},
|
|
||||||
drawerState = drawerValues.drawerState,
|
drawerState = drawerValues.drawerState,
|
||||||
scope = drawerValues.scope
|
scope = drawerValues.scope
|
||||||
)
|
)
|
||||||
|
|
|
@ -3,10 +3,8 @@ package co.electriccoin.zcash.ui.screen.securitywarning.view
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
||||||
import co.electriccoin.zcash.spackle.getPackageInfoCompat
|
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
import co.electriccoin.zcash.ui.screen.about.model.VersionInfo
|
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
|
||||||
import co.electriccoin.zcash.ui.test.getAppContext
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
|
||||||
|
@ -50,9 +48,7 @@ class SecurityWarningViewTestSetup(private val composeTestRule: ComposeContentTe
|
||||||
onConfirm = {
|
onConfirm = {
|
||||||
onConfirmCount.incrementAndGet()
|
onConfirmCount.incrementAndGet()
|
||||||
},
|
},
|
||||||
versionInfo = VersionInfo.new(
|
versionInfo = VersionInfoFixture.new()
|
||||||
getAppContext().packageManager.getPackageInfoCompat(getAppContext().packageName, 0L)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,6 +74,9 @@ internal fun MainActivity.Navigation() {
|
||||||
WrapSettings(
|
WrapSettings(
|
||||||
goBack = {
|
goBack = {
|
||||||
navController.popBackStackJustOnce(SETTINGS)
|
navController.popBackStackJustOnce(SETTINGS)
|
||||||
|
},
|
||||||
|
goAbout = {
|
||||||
|
navController.navigateJustOnce(ABOUT)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
package co.electriccoin.zcash.ui.common.model
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.pm.ApplicationInfo
|
||||||
|
import co.electriccoin.zcash.build.gitCommitCount
|
||||||
|
import co.electriccoin.zcash.build.gitSha
|
||||||
|
import co.electriccoin.zcash.spackle.EmulatorWtfUtil
|
||||||
|
import co.electriccoin.zcash.spackle.FirebaseTestLabUtil
|
||||||
|
import co.electriccoin.zcash.spackle.getPackageInfoCompat
|
||||||
|
import co.electriccoin.zcash.spackle.versionCodeCompat
|
||||||
|
|
||||||
|
data class VersionInfo(
|
||||||
|
val versionName: String,
|
||||||
|
val versionCode: Long,
|
||||||
|
val isDebuggable: Boolean,
|
||||||
|
val gitSha: String,
|
||||||
|
val gitCommitCount: Long
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
fun new(context: Context): VersionInfo {
|
||||||
|
val packageInfo = context.packageManager.getPackageInfoCompat(context.packageName, 0L)
|
||||||
|
val applicationInfo = context.applicationInfo
|
||||||
|
|
||||||
|
return VersionInfo(
|
||||||
|
versionName = packageInfo.versionName ?: "null", // Should only be null during tests
|
||||||
|
versionCode = packageInfo.versionCodeCompat, // Should only be 0 during tests
|
||||||
|
isDebuggable = (
|
||||||
|
(0 != applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE) &&
|
||||||
|
!FirebaseTestLabUtil.isFirebaseTestLab(context.applicationContext) &&
|
||||||
|
!EmulatorWtfUtil.isEmulatorWtf(context.applicationContext)
|
||||||
|
),
|
||||||
|
gitSha = gitSha,
|
||||||
|
gitCommitCount = gitCommitCount.toLong()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +1,27 @@
|
||||||
package co.electriccoin.zcash.ui.fixture
|
package co.electriccoin.zcash.ui.fixture
|
||||||
|
|
||||||
import co.electriccoin.zcash.ui.screen.about.model.VersionInfo
|
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||||
|
|
||||||
// Magic Number doesn't matter here for hard-coded fixture values
|
// Magic Number doesn't matter here for hard-coded fixture values
|
||||||
@Suppress("MagicNumber")
|
@Suppress("MagicNumber")
|
||||||
object VersionInfoFixture {
|
object VersionInfoFixture {
|
||||||
const val VERSION_NAME = "1.0.3"
|
const val VERSION_NAME = "1.0.0"
|
||||||
const val VERSION_CODE = 3L
|
const val VERSION_CODE = 1L
|
||||||
|
const val IS_DEBUGGABLE = false
|
||||||
|
const val GIT_SHA = "635dac0eb9ddc2bc6da5177f0dd495d8b76af4dc"
|
||||||
|
const val GIT_COMMIT_COUNT = 1L
|
||||||
|
|
||||||
fun new(
|
fun new(
|
||||||
versionName: String = VERSION_NAME,
|
versionName: String = VERSION_NAME,
|
||||||
versionCode: Long = VERSION_CODE
|
versionCode: Long = VERSION_CODE,
|
||||||
) = VersionInfo(versionName, versionCode)
|
isDebuggable: Boolean = IS_DEBUGGABLE,
|
||||||
|
gitSha: String = GIT_SHA,
|
||||||
|
gitCommitCount: Long = GIT_COMMIT_COUNT
|
||||||
|
) = VersionInfo(
|
||||||
|
versionName,
|
||||||
|
versionCode,
|
||||||
|
isDebuggable,
|
||||||
|
gitSha,
|
||||||
|
gitCommitCount
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
package co.electriccoin.zcash.ui.screen.about
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These are only used for automated testing.
|
||||||
|
*/
|
||||||
|
object AboutTag {
|
||||||
|
const val DEBUG_MENU_TAG = "debug_menu"
|
||||||
|
}
|
|
@ -6,9 +6,8 @@ import androidx.activity.ComponentActivity
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import co.electriccoin.zcash.configuration.AndroidConfigurationFactory
|
import co.electriccoin.zcash.configuration.AndroidConfigurationFactory
|
||||||
import co.electriccoin.zcash.spackle.getPackageInfoCompat
|
|
||||||
import co.electriccoin.zcash.ui.MainActivity
|
import co.electriccoin.zcash.ui.MainActivity
|
||||||
import co.electriccoin.zcash.ui.screen.about.model.VersionInfo
|
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||||
import co.electriccoin.zcash.ui.screen.about.view.About
|
import co.electriccoin.zcash.ui.screen.about.view.About
|
||||||
import co.electriccoin.zcash.ui.screen.support.model.ConfigInfo
|
import co.electriccoin.zcash.ui.screen.support.model.ConfigInfo
|
||||||
|
|
||||||
|
@ -24,13 +23,17 @@ internal fun WrapAbout(
|
||||||
activity: ComponentActivity,
|
activity: ComponentActivity,
|
||||||
goBack: () -> Unit
|
goBack: () -> Unit
|
||||||
) {
|
) {
|
||||||
val packageInfo = activity.packageManager.getPackageInfoCompat(activity.packageName, 0L)
|
val configInfo = ConfigInfo.new(AndroidConfigurationFactory.getInstance(activity.applicationContext))
|
||||||
val configurationProvider = AndroidConfigurationFactory.getInstance(activity.applicationContext)
|
val versionInfo = VersionInfo.new(activity.applicationContext)
|
||||||
|
|
||||||
About(VersionInfo.new(packageInfo), ConfigInfo.new(configurationProvider), goBack)
|
|
||||||
|
|
||||||
// Allows an implicit way to force configuration refresh by simply visiting the About screen
|
// Allows an implicit way to force configuration refresh by simply visiting the About screen
|
||||||
LaunchedEffect(key1 = true) {
|
LaunchedEffect(key1 = true) {
|
||||||
AndroidConfigurationFactory.getInstance(activity.applicationContext).hintToRefresh()
|
AndroidConfigurationFactory.getInstance(activity.applicationContext).hintToRefresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
About(
|
||||||
|
onBack = goBack,
|
||||||
|
versionInfo = versionInfo,
|
||||||
|
configInfo = configInfo
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
package co.electriccoin.zcash.ui.screen.about.model
|
|
||||||
|
|
||||||
import android.content.pm.PackageInfo
|
|
||||||
import co.electriccoin.zcash.spackle.versionCodeCompat
|
|
||||||
|
|
||||||
data class VersionInfo(val versionName: String, val versionCode: Long) {
|
|
||||||
companion object {
|
|
||||||
fun new(packageInfo: PackageInfo) = VersionInfo(
|
|
||||||
packageInfo.versionName ?: "null", // Should only be null during tests
|
|
||||||
packageInfo.versionCodeCompat
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,34 +1,47 @@
|
||||||
package co.electriccoin.zcash.ui.screen.about.view
|
package co.electriccoin.zcash.ui.screen.about.view
|
||||||
|
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
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.ArrowBack
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
|
import androidx.compose.material.icons.filled.MoreVert
|
||||||
|
import androidx.compose.material3.CenterAlignedTopAppBar
|
||||||
|
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
|
||||||
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.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.testTag
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.semantics.contentDescription
|
||||||
|
import androidx.compose.ui.semantics.semantics
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import co.electriccoin.zcash.build.gitSha
|
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
import co.electriccoin.zcash.ui.design.component.Body
|
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||||
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.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
import co.electriccoin.zcash.ui.fixture.ConfigInfoFixture
|
import co.electriccoin.zcash.ui.fixture.ConfigInfoFixture
|
||||||
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
|
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
|
||||||
import co.electriccoin.zcash.ui.screen.about.model.VersionInfo
|
import co.electriccoin.zcash.ui.screen.about.AboutTag
|
||||||
import co.electriccoin.zcash.ui.screen.support.model.ConfigInfo
|
import co.electriccoin.zcash.ui.screen.support.model.ConfigInfo
|
||||||
|
|
||||||
@Preview("About")
|
@Preview("About")
|
||||||
|
@ -37,9 +50,9 @@ private fun AboutPreview() {
|
||||||
ZcashTheme(darkTheme = false) {
|
ZcashTheme(darkTheme = false) {
|
||||||
GradientSurface {
|
GradientSurface {
|
||||||
About(
|
About(
|
||||||
|
onBack = {},
|
||||||
versionInfo = VersionInfoFixture.new(),
|
versionInfo = VersionInfoFixture.new(),
|
||||||
configInfo = ConfigInfoFixture.new(),
|
configInfo = ConfigInfoFixture.new()
|
||||||
goBack = {}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,16 +60,19 @@ private fun AboutPreview() {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun About(
|
fun About(
|
||||||
|
onBack: () -> Unit,
|
||||||
versionInfo: VersionInfo,
|
versionInfo: VersionInfo,
|
||||||
configInfo: ConfigInfo,
|
configInfo: ConfigInfo
|
||||||
goBack: () -> Unit
|
|
||||||
) {
|
) {
|
||||||
Scaffold(topBar = {
|
Scaffold(topBar = {
|
||||||
AboutTopAppBar(onBack = goBack)
|
AboutTopAppBar(
|
||||||
|
onBack = onBack,
|
||||||
|
versionInfo = versionInfo,
|
||||||
|
configInfo = configInfo
|
||||||
|
)
|
||||||
}) { paddingValues ->
|
}) { paddingValues ->
|
||||||
AboutMainContent(
|
AboutMainContent(
|
||||||
versionInfo,
|
versionInfo = versionInfo,
|
||||||
configInfo,
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxHeight()
|
.fillMaxHeight()
|
||||||
.verticalScroll(
|
.verticalScroll(
|
||||||
|
@ -65,8 +81,8 @@ fun About(
|
||||||
.padding(
|
.padding(
|
||||||
top = paddingValues.calculateTopPadding() + ZcashTheme.dimens.spacingDefault,
|
top = paddingValues.calculateTopPadding() + ZcashTheme.dimens.spacingDefault,
|
||||||
bottom = paddingValues.calculateBottomPadding() + ZcashTheme.dimens.spacingDefault,
|
bottom = paddingValues.calculateBottomPadding() + ZcashTheme.dimens.spacingDefault,
|
||||||
start = ZcashTheme.dimens.spacingDefault,
|
start = ZcashTheme.dimens.spacingHuge,
|
||||||
end = ZcashTheme.dimens.spacingDefault
|
end = ZcashTheme.dimens.spacingHuge
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -74,52 +90,122 @@ fun About(
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
private fun AboutTopAppBar(onBack: () -> Unit) {
|
private fun AboutTopAppBar(
|
||||||
TopAppBar(
|
onBack: () -> Unit,
|
||||||
title = { Text(text = stringResource(id = R.string.about_title)) },
|
versionInfo: VersionInfo,
|
||||||
|
configInfo: ConfigInfo
|
||||||
|
) {
|
||||||
|
CenterAlignedTopAppBar(
|
||||||
|
title = {
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.about_title).uppercase(),
|
||||||
|
style = ZcashTheme.typography.primary.titleSmall,
|
||||||
|
color = ZcashTheme.colors.screenTitleColor
|
||||||
|
)
|
||||||
|
},
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
IconButton(
|
Row(
|
||||||
onClick = onBack
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
) {
|
) {
|
||||||
Icon(
|
IconButton(
|
||||||
imageVector = Icons.Filled.ArrowBack,
|
onClick = onBack
|
||||||
contentDescription = stringResource(R.string.about_back_content_description)
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Filled.ArrowBack,
|
||||||
|
contentDescription = stringResource(R.string.about_back_content_description)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.about_back).uppercase(),
|
||||||
|
style = ZcashTheme.typography.primary.bodyMedium
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
actions = {
|
||||||
|
if (versionInfo.isDebuggable) {
|
||||||
|
DebugMenu(versionInfo, configInfo)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun DebugMenu(
|
||||||
|
versionInfo: VersionInfo,
|
||||||
|
configInfo: ConfigInfo
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.testTag(AboutTag.DEBUG_MENU_TAG)
|
||||||
|
) {
|
||||||
|
var expanded by rememberSaveable { mutableStateOf(false) }
|
||||||
|
IconButton(onClick = { expanded = true }) {
|
||||||
|
Icon(Icons.Default.MoreVert, contentDescription = null)
|
||||||
|
}
|
||||||
|
DropdownMenu(
|
||||||
|
expanded = expanded,
|
||||||
|
onDismissRequest = { expanded = false }
|
||||||
|
) {
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = {
|
||||||
|
Column {
|
||||||
|
Text(stringResource(R.string.about_debug_menu_build, versionInfo.gitSha))
|
||||||
|
Text(configInfo.toSupportString())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onClick = {
|
||||||
|
expanded = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AboutMainContent(
|
fun AboutMainContent(
|
||||||
versionInfo: VersionInfo,
|
versionInfo: VersionInfo,
|
||||||
configInfo: ConfigInfo,
|
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
Column(modifier) {
|
Column(modifier) {
|
||||||
Icon(painterResource(id = R.drawable.zashi_logo), contentDescription = null)
|
val logoContentDescription = stringResource(R.string.about_app_logo_content_description)
|
||||||
Text(stringResource(id = R.string.app_name))
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge))
|
modifier = Modifier.semantics(mergeDescendants = true) {
|
||||||
|
contentDescription = logoContentDescription
|
||||||
Header(stringResource(id = R.string.about_version_header))
|
}
|
||||||
Body(stringResource(R.string.about_version_format, versionInfo.versionName, versionInfo.versionCode))
|
) {
|
||||||
|
Image(
|
||||||
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge))
|
painter = painterResource(id = R.drawable.zashi_logo_without_text),
|
||||||
|
contentDescription = null,
|
||||||
Header(stringResource(id = R.string.about_build_header))
|
Modifier
|
||||||
Body(gitSha)
|
.height(ZcashTheme.dimens.zcashLogoHeight)
|
||||||
|
.width(ZcashTheme.dimens.zcashLogoWidth)
|
||||||
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge))
|
)
|
||||||
|
Spacer(modifier = Modifier.width(ZcashTheme.dimens.spacingDefault))
|
||||||
configInfo.configurationUpdatedAt?.let { updatedAt ->
|
Image(
|
||||||
Header(stringResource(id = R.string.about_build_configuration))
|
painter = painterResource(id = R.drawable.zashi_text_logo),
|
||||||
Body(updatedAt.toString())
|
contentDescription = null,
|
||||||
|
modifier = Modifier.height(ZcashTheme.dimens.zcashTextLogoHeight)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge))
|
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge))
|
||||||
|
|
||||||
Header(stringResource(id = R.string.about_legal_header))
|
Text(
|
||||||
Body(stringResource(id = R.string.about_legal_info))
|
text = stringResource(
|
||||||
|
R.string.about_version_format,
|
||||||
|
versionInfo.versionName,
|
||||||
|
versionInfo.versionCode
|
||||||
|
),
|
||||||
|
style = ZcashTheme.typography.primary.titleSmall
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.about_description),
|
||||||
|
color = ZcashTheme.colors.aboutTextColor,
|
||||||
|
style = ZcashTheme.extendedTypography.aboutText
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,7 @@ import androidx.compose.material3.DrawerValue
|
||||||
import androidx.compose.material3.rememberDrawerState
|
import androidx.compose.material3.rememberDrawerState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
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.FirebaseTestLabUtil
|
|
||||||
import co.electriccoin.zcash.ui.BuildConfig
|
|
||||||
import co.electriccoin.zcash.ui.MainActivity
|
import co.electriccoin.zcash.ui.MainActivity
|
||||||
import co.electriccoin.zcash.ui.common.closeDrawerMenu
|
import co.electriccoin.zcash.ui.common.closeDrawerMenu
|
||||||
import co.electriccoin.zcash.ui.configuration.ConfigurationEntries
|
import co.electriccoin.zcash.ui.configuration.ConfigurationEntries
|
||||||
|
@ -86,23 +82,14 @@ internal fun WrapHome(
|
||||||
if (null == walletSnapshot) {
|
if (null == walletSnapshot) {
|
||||||
// Display loading indicator
|
// Display loading indicator
|
||||||
} else {
|
} else {
|
||||||
val context = LocalContext.current
|
|
||||||
|
|
||||||
// We might eventually want to check the debuggable property of the manifest instead
|
|
||||||
// of relying on BuildConfig.
|
|
||||||
val isDebugMenuEnabled = BuildConfig.DEBUG &&
|
|
||||||
!FirebaseTestLabUtil.isFirebaseTestLab(context) &&
|
|
||||||
!EmulatorWtfUtil.isEmulatorWtf(context)
|
|
||||||
|
|
||||||
val drawerValues = drawerBackHandler()
|
val drawerValues = drawerBackHandler()
|
||||||
|
|
||||||
Home(
|
Home(
|
||||||
walletSnapshot,
|
walletSnapshot = walletSnapshot,
|
||||||
isUpdateAvailable = updateAvailable,
|
isUpdateAvailable = updateAvailable,
|
||||||
isKeepScreenOnDuringSync = isKeepScreenOnWhileSyncing,
|
isKeepScreenOnDuringSync = isKeepScreenOnWhileSyncing,
|
||||||
isFiatConversionEnabled = isFiatConversionEnabled,
|
isFiatConversionEnabled = isFiatConversionEnabled,
|
||||||
isCircularProgressBarEnabled = isCircularProgressBarEnabled,
|
isCircularProgressBarEnabled = isCircularProgressBarEnabled,
|
||||||
isDebugMenuEnabled = isDebugMenuEnabled,
|
|
||||||
goSeedPhrase = goSeedPhrase,
|
goSeedPhrase = goSeedPhrase,
|
||||||
goSettings = goSettings,
|
goSettings = goSettings,
|
||||||
goSupport = goSupport,
|
goSupport = goSupport,
|
||||||
|
@ -110,9 +97,6 @@ internal fun WrapHome(
|
||||||
goReceive = goReceive,
|
goReceive = goReceive,
|
||||||
goSend = goSend,
|
goSend = goSend,
|
||||||
goHistory = goHistory,
|
goHistory = goHistory,
|
||||||
resetSdk = {
|
|
||||||
walletViewModel.resetSdk()
|
|
||||||
},
|
|
||||||
drawerState = drawerValues.drawerState,
|
drawerState = drawerValues.drawerState,
|
||||||
scope = drawerValues.scope
|
scope = drawerValues.scope
|
||||||
)
|
)
|
||||||
|
|
|
@ -19,14 +19,11 @@ import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.ContactSupport
|
import androidx.compose.material.icons.filled.ContactSupport
|
||||||
import androidx.compose.material.icons.filled.Info
|
import androidx.compose.material.icons.filled.Info
|
||||||
import androidx.compose.material.icons.filled.Menu
|
import androidx.compose.material.icons.filled.Menu
|
||||||
import androidx.compose.material.icons.filled.MoreVert
|
|
||||||
import androidx.compose.material.icons.filled.Password
|
import androidx.compose.material.icons.filled.Password
|
||||||
import androidx.compose.material.icons.filled.Settings
|
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.DrawerState
|
||||||
import androidx.compose.material3.DrawerValue
|
import androidx.compose.material3.DrawerValue
|
||||||
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
|
||||||
|
@ -40,9 +37,7 @@ import androidx.compose.material3.TopAppBar
|
||||||
import androidx.compose.material3.rememberDrawerState
|
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.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
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
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
@ -56,7 +51,6 @@ import androidx.compose.ui.unit.dp
|
||||||
import cash.z.ecc.android.sdk.Synchronizer
|
import cash.z.ecc.android.sdk.Synchronizer
|
||||||
import cash.z.ecc.android.sdk.model.FiatCurrencyConversionRateState
|
import cash.z.ecc.android.sdk.model.FiatCurrencyConversionRateState
|
||||||
import cash.z.ecc.android.sdk.model.PercentDecimal
|
import cash.z.ecc.android.sdk.model.PercentDecimal
|
||||||
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.common.closeDrawerMenu
|
import co.electriccoin.zcash.ui.common.closeDrawerMenu
|
||||||
|
@ -83,7 +77,6 @@ private fun ComposablePreview() {
|
||||||
walletSnapshot = WalletSnapshotFixture.new(),
|
walletSnapshot = WalletSnapshotFixture.new(),
|
||||||
isUpdateAvailable = false,
|
isUpdateAvailable = false,
|
||||||
isKeepScreenOnDuringSync = false,
|
isKeepScreenOnDuringSync = false,
|
||||||
isDebugMenuEnabled = false,
|
|
||||||
isFiatConversionEnabled = false,
|
isFiatConversionEnabled = false,
|
||||||
isCircularProgressBarEnabled = false,
|
isCircularProgressBarEnabled = false,
|
||||||
goSeedPhrase = {},
|
goSeedPhrase = {},
|
||||||
|
@ -93,7 +86,6 @@ private fun ComposablePreview() {
|
||||||
goReceive = {},
|
goReceive = {},
|
||||||
goSend = {},
|
goSend = {},
|
||||||
goHistory = {},
|
goHistory = {},
|
||||||
resetSdk = {},
|
|
||||||
drawerState = rememberDrawerState(DrawerValue.Closed),
|
drawerState = rememberDrawerState(DrawerValue.Closed),
|
||||||
scope = rememberCoroutineScope()
|
scope = rememberCoroutineScope()
|
||||||
)
|
)
|
||||||
|
@ -109,7 +101,6 @@ fun Home(
|
||||||
isKeepScreenOnDuringSync: Boolean?,
|
isKeepScreenOnDuringSync: Boolean?,
|
||||||
isFiatConversionEnabled: Boolean,
|
isFiatConversionEnabled: Boolean,
|
||||||
isCircularProgressBarEnabled: Boolean,
|
isCircularProgressBarEnabled: Boolean,
|
||||||
isDebugMenuEnabled: Boolean,
|
|
||||||
goSeedPhrase: () -> Unit,
|
goSeedPhrase: () -> Unit,
|
||||||
goSettings: () -> Unit,
|
goSettings: () -> Unit,
|
||||||
goSupport: () -> Unit,
|
goSupport: () -> Unit,
|
||||||
|
@ -117,7 +108,6 @@ fun Home(
|
||||||
goReceive: () -> Unit,
|
goReceive: () -> Unit,
|
||||||
goSend: () -> Unit,
|
goSend: () -> Unit,
|
||||||
goHistory: () -> Unit,
|
goHistory: () -> Unit,
|
||||||
resetSdk: () -> Unit,
|
|
||||||
drawerState: DrawerState,
|
drawerState: DrawerState,
|
||||||
scope: CoroutineScope
|
scope: CoroutineScope
|
||||||
) {
|
) {
|
||||||
|
@ -135,9 +125,7 @@ fun Home(
|
||||||
content = {
|
content = {
|
||||||
Scaffold(topBar = {
|
Scaffold(topBar = {
|
||||||
HomeTopAppBar(
|
HomeTopAppBar(
|
||||||
isDebugMenuEnabled = isDebugMenuEnabled,
|
openDrawer = { drawerState.openDrawerMenu(scope) }
|
||||||
openDrawer = { drawerState.openDrawerMenu(scope) },
|
|
||||||
resetSdk = resetSdk
|
|
||||||
)
|
)
|
||||||
}) { paddingValues ->
|
}) { paddingValues ->
|
||||||
HomeMainContent(
|
HomeMainContent(
|
||||||
|
@ -164,9 +152,7 @@ fun Home(
|
||||||
@Composable
|
@Composable
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
private fun HomeTopAppBar(
|
private fun HomeTopAppBar(
|
||||||
isDebugMenuEnabled: Boolean,
|
openDrawer: () -> Unit
|
||||||
openDrawer: () -> Unit,
|
|
||||||
resetSdk: () -> Unit,
|
|
||||||
) {
|
) {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
title = { Text(text = stringResource(id = R.string.app_name)) },
|
title = { Text(text = stringResource(id = R.string.app_name)) },
|
||||||
|
@ -180,59 +166,10 @@ private fun HomeTopAppBar(
|
||||||
contentDescription = stringResource(R.string.home_menu_content_description)
|
contentDescription = stringResource(R.string.home_menu_content_description)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
|
||||||
actions = {
|
|
||||||
if (isDebugMenuEnabled) {
|
|
||||||
DebugMenu(resetSdk)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun DebugMenu(
|
|
||||||
resetSdk: () -> Unit
|
|
||||||
) {
|
|
||||||
Column {
|
|
||||||
var expanded by rememberSaveable { mutableStateOf(false) }
|
|
||||||
IconButton(onClick = { expanded = true }) {
|
|
||||||
Icon(Icons.Default.MoreVert, contentDescription = null)
|
|
||||||
}
|
|
||||||
|
|
||||||
DropdownMenu(
|
|
||||||
expanded = expanded,
|
|
||||||
onDismissRequest = { expanded = false }
|
|
||||||
) {
|
|
||||||
DropdownMenuItem(
|
|
||||||
text = { Text("Throw Uncaught Exception") },
|
|
||||||
onClick = {
|
|
||||||
// Supposed to be generic, for manual debugging only
|
|
||||||
@Suppress("TooGenericExceptionThrown")
|
|
||||||
throw RuntimeException("Manually crashed from debug menu")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
DropdownMenuItem(
|
|
||||||
text = { Text("Report Caught Exception") },
|
|
||||||
onClick = {
|
|
||||||
// Eventually this shouldn't rely on the Android implementation, but rather an expect/actual
|
|
||||||
// should be used at the crash API level.
|
|
||||||
GlobalCrashReporter.reportCaughtException(
|
|
||||||
RuntimeException("Manually caught exception from debug menu")
|
|
||||||
)
|
|
||||||
expanded = false
|
|
||||||
}
|
|
||||||
)
|
|
||||||
DropdownMenuItem(
|
|
||||||
text = { Text("Reset SDK") },
|
|
||||||
onClick = {
|
|
||||||
resetSdk()
|
|
||||||
expanded = false
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun HomeDrawer(
|
private fun HomeDrawer(
|
||||||
onCloseDrawer: () -> Unit,
|
onCloseDrawer: () -> Unit,
|
||||||
|
|
|
@ -6,7 +6,6 @@ import android.content.Context
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import cash.z.ecc.android.sdk.WalletInitMode
|
import cash.z.ecc.android.sdk.WalletInitMode
|
||||||
import cash.z.ecc.android.sdk.fixture.WalletFixture
|
import cash.z.ecc.android.sdk.fixture.WalletFixture
|
||||||
|
@ -17,10 +16,9 @@ import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||||
import cash.z.ecc.android.sdk.model.defaultForNetwork
|
import cash.z.ecc.android.sdk.model.defaultForNetwork
|
||||||
import cash.z.ecc.sdk.type.fromResources
|
import cash.z.ecc.sdk.type.fromResources
|
||||||
import co.electriccoin.lightwallet.client.model.LightWalletEndpoint
|
import co.electriccoin.lightwallet.client.model.LightWalletEndpoint
|
||||||
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.MainActivity
|
import co.electriccoin.zcash.ui.MainActivity
|
||||||
|
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||||
import co.electriccoin.zcash.ui.configuration.ConfigurationEntries
|
import co.electriccoin.zcash.ui.configuration.ConfigurationEntries
|
||||||
import co.electriccoin.zcash.ui.configuration.RemoteConfig
|
import co.electriccoin.zcash.ui.configuration.RemoteConfig
|
||||||
import co.electriccoin.zcash.ui.screen.home.model.OnboardingState
|
import co.electriccoin.zcash.ui.screen.home.model.OnboardingState
|
||||||
|
@ -43,13 +41,7 @@ internal fun WrapOnboarding(
|
||||||
val walletViewModel by activity.viewModels<WalletViewModel>()
|
val walletViewModel by activity.viewModels<WalletViewModel>()
|
||||||
val onboardingViewModel by activity.viewModels<OnboardingViewModel>()
|
val onboardingViewModel by activity.viewModels<OnboardingViewModel>()
|
||||||
|
|
||||||
val applicationContext = LocalContext.current.applicationContext
|
val versionInfo = VersionInfo.new(activity.applicationContext)
|
||||||
|
|
||||||
// We might eventually want to check the debuggable property of the manifest instead
|
|
||||||
// of relying on BuildConfig.
|
|
||||||
val isDebugMenuEnabled = BuildConfig.DEBUG &&
|
|
||||||
!FirebaseTestLabUtil.isFirebaseTestLab(applicationContext) &&
|
|
||||||
!EmulatorWtfUtil.isEmulatorWtf(applicationContext)
|
|
||||||
|
|
||||||
// TODO [#383]: https://github.com/zcash/secant-android-wallet/issues/383
|
// TODO [#383]: https://github.com/zcash/secant-android-wallet/issues/383
|
||||||
// TODO [#383]: Refactoring of UI state retention into rememberSaveable fields
|
// TODO [#383]: Refactoring of UI state retention into rememberSaveable fields
|
||||||
|
@ -63,12 +55,12 @@ internal fun WrapOnboarding(
|
||||||
// Firebase Test Lab or Google Play pre-launch report, we want to skip creating
|
// Firebase Test Lab or Google Play pre-launch report, we want to skip creating
|
||||||
// a new or restoring an existing wallet screens by persisting an existing wallet
|
// a new or restoring an existing wallet screens by persisting an existing wallet
|
||||||
// with a mock seed.
|
// with a mock seed.
|
||||||
if (FirebaseTestLabUtil.isFirebaseTestLab(applicationContext)) {
|
if (FirebaseTestLabUtil.isFirebaseTestLab(activity.applicationContext)) {
|
||||||
persistExistingWalletWithSeedPhrase(
|
persistExistingWalletWithSeedPhrase(
|
||||||
applicationContext,
|
activity.applicationContext,
|
||||||
walletViewModel,
|
walletViewModel,
|
||||||
SeedPhrase.new(WalletFixture.Alice.seedPhrase),
|
SeedPhrase.new(WalletFixture.Alice.seedPhrase),
|
||||||
birthday = WalletFixture.Alice.getBirthday(ZcashNetwork.fromResources(applicationContext))
|
birthday = WalletFixture.Alice.getBirthday(ZcashNetwork.fromResources(activity.applicationContext))
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
onboardingViewModel.setIsImporting(true)
|
onboardingViewModel.setIsImporting(true)
|
||||||
|
@ -79,10 +71,10 @@ internal fun WrapOnboarding(
|
||||||
|
|
||||||
val onFixtureWallet = {
|
val onFixtureWallet = {
|
||||||
persistExistingWalletWithSeedPhrase(
|
persistExistingWalletWithSeedPhrase(
|
||||||
applicationContext,
|
activity.applicationContext,
|
||||||
walletViewModel,
|
walletViewModel,
|
||||||
SeedPhrase.new(WalletFixture.Alice.seedPhrase),
|
SeedPhrase.new(WalletFixture.Alice.seedPhrase),
|
||||||
birthday = WalletFixture.Alice.getBirthday(ZcashNetwork.fromResources(applicationContext))
|
birthday = WalletFixture.Alice.getBirthday(ZcashNetwork.fromResources(activity.applicationContext))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +92,7 @@ internal fun WrapOnboarding(
|
||||||
} else {
|
} else {
|
||||||
LongOnboarding(
|
LongOnboarding(
|
||||||
onboardingState = onboardingViewModel.onboardingState,
|
onboardingState = onboardingViewModel.onboardingState,
|
||||||
isDebugMenuEnabled = isDebugMenuEnabled,
|
isDebugMenuEnabled = versionInfo.isDebuggable,
|
||||||
onImportWallet = onImportWallet,
|
onImportWallet = onImportWallet,
|
||||||
onCreateWallet = onCreateWallet,
|
onCreateWallet = onCreateWallet,
|
||||||
onFixtureWallet = onFixtureWallet
|
onFixtureWallet = onFixtureWallet
|
||||||
|
|
|
@ -8,10 +8,9 @@ import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import co.electriccoin.zcash.configuration.AndroidConfigurationFactory
|
import co.electriccoin.zcash.configuration.AndroidConfigurationFactory
|
||||||
import co.electriccoin.zcash.spackle.getPackageInfoCompat
|
|
||||||
import co.electriccoin.zcash.ui.MainActivity
|
import co.electriccoin.zcash.ui.MainActivity
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
import co.electriccoin.zcash.ui.screen.about.model.VersionInfo
|
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||||
import co.electriccoin.zcash.ui.screen.securitywarning.util.WebBrowserUtil
|
import co.electriccoin.zcash.ui.screen.securitywarning.util.WebBrowserUtil
|
||||||
import co.electriccoin.zcash.ui.screen.securitywarning.view.SecurityWarning
|
import co.electriccoin.zcash.ui.screen.securitywarning.view.SecurityWarning
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
@ -35,14 +34,12 @@ internal fun WrapSecurityWarning(
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
onConfirm: () -> Unit
|
onConfirm: () -> Unit
|
||||||
) {
|
) {
|
||||||
val packageInfo = activity.packageManager.getPackageInfoCompat(activity.packageName, 0L)
|
|
||||||
|
|
||||||
val snackbarHostState = remember { SnackbarHostState() }
|
val snackbarHostState = remember { SnackbarHostState() }
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
SecurityWarning(
|
SecurityWarning(
|
||||||
snackbarHostState = snackbarHostState,
|
snackbarHostState = snackbarHostState,
|
||||||
versionInfo = VersionInfo.new(packageInfo),
|
versionInfo = VersionInfo.new(activity.applicationContext),
|
||||||
onBack = onBack,
|
onBack = onBack,
|
||||||
onAcknowledged = {
|
onAcknowledged = {
|
||||||
// Needed for UI testing only
|
// Needed for UI testing only
|
||||||
|
|
|
@ -36,13 +36,13 @@ import androidx.compose.ui.text.style.TextDecoration
|
||||||
import androidx.compose.ui.text.withStyle
|
import androidx.compose.ui.text.withStyle
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
|
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||||
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
|
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
|
||||||
import co.electriccoin.zcash.ui.design.component.CheckBox
|
import co.electriccoin.zcash.ui.design.component.CheckBox
|
||||||
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.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
|
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
|
||||||
import co.electriccoin.zcash.ui.screen.about.model.VersionInfo
|
|
||||||
|
|
||||||
@Preview("Security Warning")
|
@Preview("Security Warning")
|
||||||
@Composable
|
@Composable
|
||||||
|
|
|
@ -6,8 +6,8 @@ import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import co.electriccoin.zcash.ui.BuildConfig
|
|
||||||
import co.electriccoin.zcash.ui.MainActivity
|
import co.electriccoin.zcash.ui.MainActivity
|
||||||
|
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||||
import co.electriccoin.zcash.ui.configuration.ConfigurationEntries
|
import co.electriccoin.zcash.ui.configuration.ConfigurationEntries
|
||||||
import co.electriccoin.zcash.ui.configuration.RemoteConfig
|
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
|
||||||
|
@ -17,11 +17,13 @@ import co.electriccoin.zcash.ui.screen.settings.viewmodel.SettingsViewModel
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun MainActivity.WrapSettings(
|
internal fun MainActivity.WrapSettings(
|
||||||
goBack: () -> Unit
|
goBack: () -> Unit,
|
||||||
|
goAbout: () -> Unit,
|
||||||
) {
|
) {
|
||||||
WrapSettings(
|
WrapSettings(
|
||||||
activity = this,
|
activity = this,
|
||||||
goBack = goBack,
|
goBack = goBack,
|
||||||
|
goAbout = goAbout
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,10 +31,13 @@ internal fun MainActivity.WrapSettings(
|
||||||
private fun WrapSettings(
|
private fun WrapSettings(
|
||||||
activity: ComponentActivity,
|
activity: ComponentActivity,
|
||||||
goBack: () -> Unit,
|
goBack: () -> Unit,
|
||||||
|
goAbout: () -> 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>()
|
||||||
|
|
||||||
|
val versionInfo = VersionInfo.new(activity.applicationContext)
|
||||||
|
|
||||||
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
|
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
|
||||||
val isBackgroundSyncEnabled = settingsViewModel.isBackgroundSync.collectAsStateWithLifecycle().value
|
val isBackgroundSyncEnabled = settingsViewModel.isBackgroundSync.collectAsStateWithLifecycle().value
|
||||||
val isKeepScreenOnWhileSyncing = settingsViewModel.isKeepScreenOnWhileSyncing.collectAsStateWithLifecycle().value
|
val isKeepScreenOnWhileSyncing = settingsViewModel.isKeepScreenOnWhileSyncing.collectAsStateWithLifecycle().value
|
||||||
|
@ -48,7 +53,7 @@ private fun WrapSettings(
|
||||||
} else {
|
} else {
|
||||||
Settings(
|
Settings(
|
||||||
TroubleshootingParameters(
|
TroubleshootingParameters(
|
||||||
isEnabled = BuildConfig.DEBUG,
|
isEnabled = versionInfo.isDebuggable,
|
||||||
isBackgroundSyncEnabled = isBackgroundSyncEnabled,
|
isBackgroundSyncEnabled = isBackgroundSyncEnabled,
|
||||||
isKeepScreenOnDuringSyncEnabled = isKeepScreenOnWhileSyncing,
|
isKeepScreenOnDuringSyncEnabled = isKeepScreenOnWhileSyncing,
|
||||||
isAnalyticsEnabled = isAnalyticsEnabled,
|
isAnalyticsEnabled = isAnalyticsEnabled,
|
||||||
|
@ -59,7 +64,7 @@ private fun WrapSettings(
|
||||||
onDocumentation = {},
|
onDocumentation = {},
|
||||||
onPrivacyPolicy = {},
|
onPrivacyPolicy = {},
|
||||||
onFeedback = {},
|
onFeedback = {},
|
||||||
onAbout = {},
|
onAbout = goAbout,
|
||||||
onRescanWallet = {
|
onRescanWallet = {
|
||||||
walletViewModel.rescanBlockchain()
|
walletViewModel.rescanBlockchain()
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
<string name="about_title">About</string>
|
<string name="about_title">About</string>
|
||||||
|
<string name="about_back">Back</string>
|
||||||
<string name="about_back_content_description">Back</string>
|
<string name="about_back_content_description">Back</string>
|
||||||
<string name="about_icon_content_description">Zcash icon</string>
|
<string name="about_app_logo_content_description">Zcash logo</string>
|
||||||
<string name="about_version_header">Version</string>
|
<string name="about_version_format" formatted="true">Version <xliff:g example="1.0" id="version_name">%1$s
|
||||||
<string name="about_version_format" formatted="true"><xliff:g id="version_name" example="1.0">%1$s</xliff:g> (<xliff:g id="version_code" example="1.0">%2$d</xliff:g>)</string>
|
</xliff:g> (<xliff:g example="1.0" id="version_code">%2$d</xliff:g>)</string>
|
||||||
<string name="about_build_header">Build</string>
|
<string name="about_debug_menu_build">Build: <xliff:g example="635dac0eb9ddc2bc6da5177f0dd495d8b76af4dc"
|
||||||
<string name="about_build_configuration">Configuration</string>
|
id="git_commit_hash">%1$s</xliff:g></string>
|
||||||
<string name="about_legal_header">Legal</string>
|
<string name="about_description">Send and receive ZEC on Zashi! Zashi is a minimal-design, self-custody, ZEC-only
|
||||||
<!-- TODO [#392] Update with real legal info. -->
|
shielded wallet that keeps your transaction history and wallet balance private. Built by Zcashers, for
|
||||||
<!-- TODO [#392] https://github.com/zcash/secant-android-wallet/issues/392 -->
|
Zcashers. Developed and maintained by Electric Coin Co., the inventor of Zcash, Zashi features a built-in
|
||||||
<string name="about_legal_info">GitHub Issue #392</string>
|
user-feedback mechanism to enable more features, more quickly.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -680,7 +680,9 @@ private fun supportScreenshots(resContext: Context, tag: String, composeTestRule
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun aboutScreenshots(resContext: Context, tag: String, composeTestRule: ComposeTestRule) {
|
private fun aboutScreenshots(resContext: Context, tag: String, composeTestRule: ComposeTestRule) {
|
||||||
composeTestRule.onNode(hasText(resContext.getString(R.string.about_title))).also {
|
composeTestRule.onNode(
|
||||||
|
hasText(resContext.getString(R.string.about_title).uppercase())
|
||||||
|
).also {
|
||||||
it.assertExists()
|
it.assertExists()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue