[#15] Add ui-lib module

This commit is contained in:
Carter Jernigan 2021-10-09 10:36:58 -04:00
parent fa15c15e28
commit 403f5d6467
22 changed files with 223 additions and 41 deletions

View File

@ -0,0 +1,53 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="ui-lib:connectedCheck" type="AndroidTestRunConfigurationType" factoryName="Android Instrumented Tests">
<module name="zcash-android-app.ui-lib" />
<option name="TESTING_TYPE" value="0" />
<option name="METHOD_NAME" value="" />
<option name="CLASS_NAME" value="" />
<option name="PACKAGE_NAME" value="" />
<option name="INSTRUMENTATION_RUNNER_CLASS" value="" />
<option name="EXTRA_OPTIONS" value="" />
<option name="INCLUDE_GRADLE_EXTRA_OPTIONS" value="true" />
<option name="CLEAR_LOGCAT" value="false" />
<option name="SHOW_LOGCAT_AUTOMATICALLY" value="false" />
<option name="SKIP_NOOP_APK_INSTALLATIONS" value="true" />
<option name="FORCE_STOP_RUNNING_APP" value="true" />
<option name="TARGET_SELECTION_MODE" value="DEVICE_AND_SNAPSHOT_COMBO_BOX" />
<option name="SELECTED_CLOUD_MATRIX_CONFIGURATION_ID" value="-1" />
<option name="SELECTED_CLOUD_MATRIX_PROJECT_ID" value="" />
<option name="DEBUGGER_TYPE" value="Auto" />
<Auto>
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
<option name="SHOW_STATIC_VARS" value="true" />
<option name="WORKING_DIR" value="" />
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
</Auto>
<Hybrid>
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
<option name="SHOW_STATIC_VARS" value="true" />
<option name="WORKING_DIR" value="" />
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
</Hybrid>
<Java />
<Native>
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
<option name="SHOW_STATIC_VARS" value="true" />
<option name="WORKING_DIR" value="" />
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
</Native>
<Profilers>
<option name="ADVANCED_PROFILING_ENABLED" value="false" />
<option name="STARTUP_PROFILING_ENABLED" value="false" />
<option name="STARTUP_CPU_PROFILING_ENABLED" value="false" />
<option name="STARTUP_CPU_PROFILING_CONFIGURATION_NAME" value="Sample Java Methods" />
<option name="STARTUP_NATIVE_MEMORY_PROFILING_ENABLED" value="false" />
<option name="NATIVE_MEMORY_SAMPLE_RATE_BYTES" value="2048" />
</Profilers>
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>

View File

@ -6,7 +6,7 @@ plugins {
id("zcash.android-build-conventions")
}
val packageName = "cash.z.ecc.android"
val packageName = "cash.z.ecc"
android {
defaultConfig {
@ -99,6 +99,7 @@ dependencies {
implementation(libs.kotlinx.coroutines.android)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.zcash)
implementation(projects.uiLib)
androidTestImplementation(libs.bundles.androidx.test)
}

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="cash.z.ecc.android.sdk.demoapp">
package="cash.z.ecc">
<application
android:name="cash.z.ecc.android.app.App"
android:name="cash.z.ecc.app.AppImpl"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
@ -18,20 +18,13 @@
<activity-alias
android:name=".LauncherActivity"
android:label="@string/"
android:targetActivity="cash.z.ecc.android.app.MainActivity"
android:targetActivity="cash.z.ecc.ui.MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity
android:name="cash.z.ecc.android.app.MainActivity"
android:label="@string/app_name"
android:theme="@style/Theme.MyApplication"
android:exported="false">
</activity>
</application>
</manifest>

View File

@ -1,19 +0,0 @@
package cash.z.ecc.android.app
import android.app.Application
import cash.z.ecc.android.sdk.demoapp.BuildConfig
import cash.z.ecc.android.sdk.ext.TroubleshootingTwig
import cash.z.ecc.android.sdk.ext.Twig
class App : Application() {
override fun onCreate() {
super.onCreate()
if (BuildConfig.DEBUG) {
StrictModeHelper.enableStrictMode()
}
Twig.plant(TroubleshootingTwig())
}
}

View File

@ -0,0 +1,16 @@
package cash.z.ecc.app
import android.app.Application
import cash.z.ecc.BuildConfig
@Suppress("unused")
class AppImpl : Application() {
override fun onCreate() {
super.onCreate()
if (BuildConfig.DEBUG) {
StrictModeHelper.enableStrictMode()
}
}
}

View File

@ -1,4 +1,4 @@
package cash.z.ecc.android.app
package cash.z.ecc.app
import android.annotation.SuppressLint
import android.os.Build

View File

@ -4,4 +4,15 @@ TODO This is a placeholder for describing the app architecture.
* Versions are declared in [gradle.properties](../gradle.properties). There's still enough inconsistency in how versions are handled in Gradle, that this is as close as we can get to a universal system. A version catalog is used for dependencies and is configured in [settings.gradle.kts](../settings.gradle.kts), but other versions like Gradle Plug-ins, the NDK version, Java version, and Android SDK versions don't fit into the version catalog model and are read directly from the properties
* Much of the Gradle configuration lives in [build-conventions](../build-conventions/) to prevent repetitive configuration as additional modules are added to the project
* Build scripts are written in Kotlin, so that a single language is used across build and the app code bases
* Only Gradle, Google, and JetBrains plug-ins are included in the critical path. Third party plug-ins can be used, but they're outside the critical path. For example, the Gradle Versions Plugin could be removed and wouldn't negative impact building, testing, or deploying the app
* Only Gradle, Google, and JetBrains plug-ins are included in the critical path. Third party plug-ins can be used, but they're outside the critical path. For example, the Gradle Versions Plugin could be removed and wouldn't negative impact building, testing, or deploying the app
## App
The main entrypoints of the application are:
* [AppImpl.kt](../app/src/main/java/cash/z/ecc/app/AppImpl.kt) - The root Application object defined in the app module
* [MainActivity.kt](../ui-lib/src/main/java/cash/z/ecc/ui/MainActivity.kt) - The main Activity, defined in ui-lib. Note that the Activity is NOT exported. Instead, the app module defines an activity-alias in the AndroidManifest which is what presents the actual icon on the Android home screen.
## Modules
The logical components of the app are implemented as a number of Gradle modules.
* app — Compiles all of the modules together into the final application. This module contains minimal actual code. Note that the Java package structure for this module is under `cash.z.ecc.app` while the Android package name is `cash.z.ecc`.
* ui-lib — User interface that the user interacts with. This contains 99% of the UI code, along with localizations, icons, and other assets.

View File

@ -54,6 +54,7 @@ ANDROIDX_APPCOMPAT_VERSION=1.3.1
ANDROIDX_COMPOSE_VERSION=1.0.2
ANDROIDX_CORE_VERSION=1.6.0
ANDROIDX_ESPRESSO_VERSION=3.4.0
ANDROIDX_LIFECYCLE_VERSION=2.3.1
ANDROIDX_NAVIGATION_VERSION=2.3.5
ANDROIDX_TEST_JUNIT_VERSION=1.1.3
ANDROIDX_TEST_ORCHESTRATOR_VERSION=1.1.0-alpha1

View File

@ -35,6 +35,7 @@ dependencyResolutionManagement {
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 androidxTestJunitVersion = extra["ANDROIDX_TEST_JUNIT_VERSION"].toString()
val androidxTestOrchestratorVersion = extra["ANDROIDX_ESPRESSO_VERSION"].toString()
val androidxUiAutomatorVersion = extra["ANDROIDX_UI_AUTOMATOR_VERSION"].toString()
@ -53,21 +54,21 @@ dependencyResolutionManagement {
// Aliases
alias("androidx-activity").to("androidx.activity:activity-ktx:$androidxActivityVersion")
alias("androidx-activity-compose").to("androidx.activity:activity-compose:$androidxActivityVersion")
alias("androidx-appcompat").to("androidx.appcompat:appcompat:$androidxAppcompatVersion")
alias("androidx-annotation").to("androidx.annotation:annotation:$androidxAnnotationVersion")
alias("androidx-appcompat").to("androidx.appcompat:appcompat:$androidxAppcompatVersion")
alias("androidx-compose-foundation").to("androidx.compose.foundation:foundation:$androidxComposeVersion")
alias("androidx-compose-material").to("androidx.compose.material:material:$androidxComposeVersion")
alias("androidx-compose-material-icons-core").to("androidx.compose.material:material-icons-core:$androidxComposeVersion")
alias("androidx-compose-tooling").to("androidx.compose.ui:ui-tooling-preview:$androidxComposeVersion")
alias("androidx-compose-ui").to("androidx.compose.ui:ui:$androidxComposeVersion")
alias("androidx-core").to("androidx.core:core-ktx:$androidxCoreVersion")
alias("androidx-lifecycle-livedata").to("androidx.lifecycle:lifecycle-livedata-ktx:$androidxLifecycleVersion")
alias("androidx-viewmodel-compose").to("androidx.activity:activity-compose:$androidxActivityVersion")
alias("google-material").to("com.google.android.material:material:$googleMaterialVersion")
alias("kotlin").to("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion")
alias("kotlinx-coroutines-android").to("org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinxCoroutinesVersion")
alias("kotlinx-coroutines-core").to("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinxCoroutinesVersion")
alias("zcash").to("cash.z.ecc.android:zcash-android-sdk:$zcashSdkVersion")
// Test libraries
alias("androidx-espresso-contrib").to("androidx.test.espresso:espresso-contrib:$androidxEspressoVersion")
alias("androidx-espresso-core").to("androidx.test.espresso:espresso-core:$androidxEspressoVersion")
@ -95,7 +96,6 @@ dependencyResolutionManagement {
listOf(
"androidx-espresso-core",
"androidx-espresso-intents",
"androidx-espresso-contrib",
"androidx-junit"
)
)
@ -108,3 +108,4 @@ rootProject.name = "zcash-android-app"
includeBuild("build-conventions")
include("app")
include("ui-lib")

46
ui-lib/build.gradle.kts Normal file
View File

@ -0,0 +1,46 @@
plugins {
id("com.android.library")
kotlin("android")
id("kotlin-parcelize")
id("androidx.navigation.safeargs")
id("zcash.android-build-conventions")
}
val packageName = "cash.z.ecc.ui"
android {
buildFeatures {
viewBinding = true
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = libs.versions.compose.get()
}
// TODO [#5]: Figure out how to move this into the build-conventions
testCoverage {
jacocoVersion = libs.versions.jacoco.get()
}
// TODO [#6]: Figure out how to move this into the build-conventions
kotlinOptions {
jvmTarget = libs.versions.java.get()
allWarningsAsErrors = project.property("IS_TREAT_WARNINGS_AS_ERRORS").toString().toBoolean()
}
}
dependencies {
implementation(libs.androidx.activity)
implementation(libs.androidx.annotation)
implementation(libs.androidx.core)
implementation(libs.androidx.lifecycle.livedata)
implementation(libs.bundles.androidx.compose)
implementation(libs.google.material)
implementation(libs.kotlin)
implementation(libs.kotlinx.coroutines.android)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.zcash)
androidTestImplementation(libs.bundles.androidx.test)
}

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="cash.z.ecc">
<application>
<activity
android:name="cash.z.ecc.ui.MainActivity"
android:label="@string/app_name"
android:theme="@style/Theme.MyApplication"
android:exported="false">
</activity>
</application>
</manifest>

View File

@ -1,4 +1,4 @@
package cash.z.ecc.android.app
package cash.z.ecc.ui
import android.os.Bundle
import androidx.activity.ComponentActivity
@ -8,7 +8,7 @@ import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import cash.z.ecc.android.app.ui.theme.MyApplicationTheme
import cash.z.ecc.ui.theme.MyApplicationTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {

View File

@ -1,4 +1,4 @@
package cash.z.ecc.android.app.ui.theme
package cash.z.ecc.ui.theme
import androidx.compose.ui.graphics.Color

View File

@ -1,4 +1,4 @@
package cash.z.ecc.android.app.ui.theme
package cash.z.ecc.ui.theme
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Shapes

View File

@ -1,4 +1,4 @@
package cash.z.ecc.android.app.ui.theme
package cash.z.ecc.ui.theme
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material.MaterialTheme

View File

@ -1,4 +1,4 @@
package cash.z.ecc.android.app.ui.theme
package cash.z.ecc.ui.theme
import androidx.compose.material.Typography
import androidx.compose.ui.text.TextStyle

View File

@ -0,0 +1,16 @@
<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>

View File

@ -0,0 +1,11 @@
<?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>

View File

@ -0,0 +1,3 @@
<resources>
<string name="app_name">Demo App</string>
</resources>

View File

@ -0,0 +1,25 @@
<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>

View File

@ -0,0 +1,4 @@
<resources>
<string name="app_name">Mainnet Demo</string>
<string name="network_name">Mainnet</string>
</resources>

View File

@ -0,0 +1,4 @@
<resources>
<string name="app_name">Testnet Demo</string>
<string name="network_name">Testnet</string>
</resources>