[#14] Splash screen
This commit is contained in:
parent
1fdd86d2d8
commit
4a07b2e0b9
|
@ -23,8 +23,9 @@ Contributions are very much welcomed! Please read our [Contributing Guidelines]
|
|||
# Forking
|
||||
If you plan to fork the project to create a new app of your own, please make the following changes. (If you're making a GitHub fork to contribute back to the project, these steps are not necessary.)
|
||||
|
||||
1. Change the app name under app/
|
||||
1. Change the app name under app/src/main/res/values/strings.xml
|
||||
1. Remove any copyrighted ZCash or Electric Coin Company icons, logos, or assets
|
||||
1. ui-lib/src/main/res/common/ - All of the the ic_launcher assets
|
||||
1. Change the package name
|
||||
1. Under [app/build.gradle.kts](app/build.gradle.kts), change the package name of the application
|
||||
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.MyApplication" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||
<!-- Primary brand color. -->
|
||||
<item name="colorPrimary">@color/purple_200</item>
|
||||
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||
<item name="colorOnPrimary">@color/black</item>
|
||||
<!-- Secondary brand color. -->
|
||||
<item name="colorSecondary">@color/teal_200</item>
|
||||
<item name="colorSecondaryVariant">@color/teal_200</item>
|
||||
<item name="colorOnSecondary">@color/black</item>
|
||||
<!-- Status bar color. -->
|
||||
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
</resources>
|
|
@ -1,11 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="purple_200">#FFBB86FC</color>
|
||||
<color name="purple_500">#FF6200EE</color>
|
||||
<color name="purple_700">#FF3700B3</color>
|
||||
<color name="teal_200">#FF03DAC5</color>
|
||||
<color name="teal_700">#FF018786</color>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
|
||||
</resources>
|
|
@ -1,3 +1,3 @@
|
|||
<resources>
|
||||
<string name="app_name">Zcash Wallet</string>
|
||||
<string name="app_name">Zcash</string>
|
||||
</resources>
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.MyApplication" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||
<!-- Primary brand color. -->
|
||||
<item name="colorPrimary">@color/purple_500</item>
|
||||
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||
<item name="colorOnPrimary">@color/white</item>
|
||||
<!-- Secondary brand color. -->
|
||||
<item name="colorSecondary">@color/teal_200</item>
|
||||
<item name="colorSecondaryVariant">@color/teal_700</item>
|
||||
<item name="colorOnSecondary">@color/black</item>
|
||||
<!-- Status bar color. -->
|
||||
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
|
||||
<style name="Theme.MyApplication.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.MyApplication.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
||||
|
||||
<style name="Theme.MyApplication.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
||||
</resources>
|
|
@ -1,4 +1,6 @@
|
|||
<resources>
|
||||
<string name="app_name">Zcash Testnet Wallet</string>
|
||||
<string name="app_name">Zcash (Testnet)</string>
|
||||
|
||||
<!-- Important; this is the resource overlay that sets the Zcash network -->
|
||||
<string name="network_name">Testnet</string>
|
||||
</resources>
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
Android has different splash screen behavior starting with Android 12 (API 31), so the splash screen must be tested on both older and newer versions of Android.
|
||||
|
||||
Note that splash screens are only displayed when launched from the home screen. They are not displayed when the app is installed from Android Studio.
|
||||
|
||||
Note that if the splash screen appears too quickly, the `SPLASH_SCREEN_DELAY` can be set to keep the splash screen visible for longer.
|
||||
|
||||
# Android 11 (API 30) or lower
|
||||
1. Install the app
|
||||
1. Set the system to light theme (Android 10 introduced light/dark theme)
|
||||
1. Launch the app
|
||||
1. Verify the splash screen appears in the light theme
|
||||
1. Press back (NOT HOME) to leave the app
|
||||
1. For Android 10 and 11, set the system theme to dark theme
|
||||
1. Launch the app
|
||||
1. Verify the splash screen appears in the dark theme
|
||||
|
||||
# Android 12 (API 31) or greater
|
||||
1. Repeat the tests from above on Android 12 (API 31) or greater, verifying the splash screen looks effectively the same
|
|
@ -76,6 +76,7 @@ ANDROIDX_ESPRESSO_VERSION=3.4.0
|
|||
ANDROIDX_LIFECYCLE_VERSION=2.4.0
|
||||
ANDROIDX_NAVIGATION_VERSION=2.3.5
|
||||
ANDROIDX_SECURITY_CRYPTO_VERSION=1.1.0-alpha03
|
||||
ANDROIDX_SPLASH_SCREEN_VERSION=1.0.0-alpha02
|
||||
ANDROIDX_TEST_VERSION=1.4.1-alpha03
|
||||
ANDROIDX_TEST_JUNIT_VERSION=1.1.3
|
||||
ANDROIDX_TEST_ORCHESTRATOR_VERSION=1.4.1-rc01
|
||||
|
|
|
@ -51,24 +51,25 @@ dependencyResolutionManagement {
|
|||
val androidxActivityVersion = extra["ANDROIDX_ACTIVITY_VERSION"].toString()
|
||||
val androidxAnnotationVersion = extra["ANDROIDX_ANNOTATION_VERSION"].toString()
|
||||
val androidxAppcompatVersion = extra["ANDROIDX_APPCOMPAT_VERSION"].toString()
|
||||
val androidxComposeVersion = extra["ANDROIDX_COMPOSE_VERSION"].toString()
|
||||
val androidxComposeCompilerVersion = extra["ANDROIDX_COMPOSE_COMPILER_VERSION"].toString()
|
||||
val androidxComposeVersion = extra["ANDROIDX_COMPOSE_VERSION"].toString()
|
||||
val androidxCoreVersion = extra["ANDROIDX_CORE_VERSION"].toString()
|
||||
val androidxEspressoVersion = extra["ANDROIDX_ESPRESSO_VERSION"].toString()
|
||||
val androidxLifecycleVersion = extra["ANDROIDX_LIFECYCLE_VERSION"].toString()
|
||||
val androidxSecurityCryptoVersion = extra["ANDROIDX_SECURITY_CRYPTO_VERSION"].toString()
|
||||
val androidxSplashScreenVersion = extra["ANDROIDX_SPLASH_SCREEN_VERSION"].toString()
|
||||
val androidxTestJunitVersion = extra["ANDROIDX_TEST_JUNIT_VERSION"].toString()
|
||||
val androidxTestOrchestratorVersion = extra["ANDROIDX_TEST_ORCHESTRATOR_VERSION"].toString()
|
||||
val androidxTestVersion = extra["ANDROIDX_TEST_VERSION"].toString()
|
||||
val androidxUiAutomatorVersion = extra["ANDROIDX_UI_AUTOMATOR_VERSION"].toString()
|
||||
val androidxSecurityCryptoVersion = extra["ANDROIDX_SECURITY_CRYPTO_VERSION"].toString()
|
||||
val coreLibraryDesugaringVersion = extra["CORE_LIBRARY_DESUGARING_VERSION"].toString()
|
||||
val googleMaterialVersion = extra["GOOGLE_MATERIAL_VERSION"].toString()
|
||||
val jacocoVersion = extra["JACOCO_VERSION"].toString()
|
||||
val javaVersion = extra["ANDROID_JVM_TARGET"].toString()
|
||||
val kotlinVersion = extra["KOTLIN_VERSION"].toString()
|
||||
val kotlinxCoroutinesVersion = extra["KOTLINX_COROUTINES_VERSION"].toString()
|
||||
val zcashSdkVersion = extra["ZCASH_SDK_VERSION"].toString()
|
||||
val zcashBip39Version = extra["ZCASH_BIP39_VERSION"].toString()
|
||||
val zcashSdkVersion = extra["ZCASH_SDK_VERSION"].toString()
|
||||
|
||||
// Standalone versions
|
||||
version("jacoco", jacocoVersion)
|
||||
|
@ -89,6 +90,7 @@ dependencyResolutionManagement {
|
|||
alias("androidx-core").to("androidx.core:core-ktx:$androidxCoreVersion")
|
||||
alias("androidx-lifecycle-livedata").to("androidx.lifecycle:lifecycle-livedata-ktx:$androidxLifecycleVersion")
|
||||
alias("androidx-security-crypto").to("androidx.security:security-crypto-ktx:$androidxSecurityCryptoVersion")
|
||||
alias("androidx-splash").to("androidx.core:core-splashscreen:$androidxSplashScreenVersion")
|
||||
alias("androidx-viewmodel-compose").to("androidx.lifecycle:lifecycle-viewmodel-compose:$androidxLifecycleVersion")
|
||||
alias("desugaring").to("com.android.tools:desugar_jdk_libs:$coreLibraryDesugaringVersion")
|
||||
alias("google-material").to("com.google.android.material:material:$googleMaterialVersion")
|
||||
|
|
|
@ -41,6 +41,7 @@ dependencies {
|
|||
implementation(libs.androidx.annotation)
|
||||
implementation(libs.androidx.core)
|
||||
implementation(libs.androidx.lifecycle.livedata)
|
||||
implementation(libs.androidx.splash)
|
||||
implementation(libs.bundles.androidx.compose)
|
||||
implementation(libs.google.material)
|
||||
implementation(libs.kotlin.stdlib)
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package cash.z.ecc.ui
|
||||
|
||||
import androidx.test.filters.SmallTest
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
import kotlin.time.Duration
|
||||
|
||||
class MainActivityTest {
|
||||
|
||||
@Test
|
||||
@SmallTest
|
||||
fun splashScreenDelayDisabled() {
|
||||
assertEquals(Duration.Companion.ZERO, MainActivity.SPLASH_SCREEN_DELAY)
|
||||
}
|
||||
}
|
|
@ -1,18 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="cash.z.ecc.ui">
|
||||
|
||||
<application
|
||||
android:icon="@mipmap/ic_launcher_square"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.MaterialComponents.DayNight">
|
||||
android:theme="@style/Theme.App.Starting">
|
||||
|
||||
<activity
|
||||
android:name="cash.z.ecc.ui.MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:exported="false">
|
||||
</activity>
|
||||
android:exported="false"
|
||||
android:label="@string/app_name" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
|
@ -3,11 +3,14 @@ package cash.z.ecc.ui
|
|||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.os.Bundle
|
||||
import android.os.SystemClock
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.viewModels
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||
import cash.z.ecc.sdk.model.PersistableWallet
|
||||
import cash.z.ecc.ui.screen.backup.view.BackupWallet
|
||||
import cash.z.ecc.ui.screen.backup.viewmodel.BackupViewModel
|
||||
|
@ -17,6 +20,9 @@ import cash.z.ecc.ui.screen.home.viewmodel.WalletViewModel
|
|||
import cash.z.ecc.ui.screen.onboarding.view.Onboarding
|
||||
import cash.z.ecc.ui.screen.onboarding.viewmodel.OnboardingViewModel
|
||||
import cash.z.ecc.ui.theme.ZcashTheme
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
|
||||
|
@ -27,16 +33,46 @@ class MainActivity : ComponentActivity() {
|
|||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setupSplashScreen()
|
||||
|
||||
setContent {
|
||||
ZcashTheme {
|
||||
when (val walletState = walletViewModel.state.collectAsState().value) {
|
||||
val walletState = walletViewModel.state.collectAsState().value
|
||||
|
||||
when (walletState) {
|
||||
WalletState.Loading -> {
|
||||
// For now, keep displaying splash screen
|
||||
// For now, keep displaying splash screen using condition above.
|
||||
// In the future, we might consider displaying something different here.
|
||||
}
|
||||
WalletState.NoWallet -> {
|
||||
WrapOnboarding()
|
||||
}
|
||||
WalletState.NoWallet -> WrapOnboarding()
|
||||
is WalletState.NeedsBackup -> WrapBackup(walletState.persistableWallet)
|
||||
is WalletState.Ready -> Home(walletState.persistableWallet)
|
||||
is WalletState.Ready -> WrapHome(walletState.persistableWallet)
|
||||
}
|
||||
|
||||
if (walletState != WalletState.Loading) {
|
||||
reportFullyDrawn()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupSplashScreen() {
|
||||
installSplashScreen().also {
|
||||
val start = SystemClock.elapsedRealtime().milliseconds
|
||||
it.setKeepVisibleCondition {
|
||||
if (SPLASH_SCREEN_DELAY > Duration.ZERO) {
|
||||
val now = SystemClock.elapsedRealtime().milliseconds
|
||||
|
||||
// This delay is for debug purposes only; do not enable for production usage.
|
||||
if (now - start < SPLASH_SCREEN_DELAY) {
|
||||
return@setKeepVisibleCondition true
|
||||
}
|
||||
}
|
||||
|
||||
WalletState.Loading == walletViewModel.state.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,4 +104,14 @@ class MainActivity : ComponentActivity() {
|
|||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun WrapHome(persistableWallet: PersistableWallet) {
|
||||
Home(persistableWallet)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@VisibleForTesting
|
||||
internal val SPLASH_SCREEN_DELAY = 0.seconds
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="splash_screen_background">#FF273458</color>
|
||||
</resources>
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="splash_screen_background">#FFECF4FB</color>
|
||||
</resources>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="Theme.App.Starting" parent="Theme.SplashScreen">
|
||||
<item name="windowSplashScreenBackground">@color/splash_screen_background</item>
|
||||
<item name="windowSplashScreenAnimatedIcon">@drawable/ic_launcher_adaptive_foreground</item>
|
||||
<item name="postSplashScreenTheme">@style/Theme.MaterialComponents.DayNight</item>
|
||||
</style>
|
||||
</resources>
|
|
@ -1,16 +0,0 @@
|
|||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.MyApplication" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||
<!-- Primary brand color. -->
|
||||
<item name="colorPrimary">@color/purple_200</item>
|
||||
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||
<item name="colorOnPrimary">@color/black</item>
|
||||
<!-- Secondary brand color. -->
|
||||
<item name="colorSecondary">@color/teal_200</item>
|
||||
<item name="colorSecondaryVariant">@color/teal_200</item>
|
||||
<item name="colorOnSecondary">@color/black</item>
|
||||
<!-- Status bar color. -->
|
||||
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
</resources>
|
Loading…
Reference in New Issue