[#3] Add skeleton Gradle project structure

This commit is contained in:
Carter Jernigan 2021-09-14 17:02:06 -04:00 committed by Carter Jernigan
parent 84d3f9a40b
commit 68a9cc7d27
54 changed files with 2277 additions and 22 deletions

View File

@ -6,7 +6,7 @@ This code review checklist is intended to serve as a starting point for the auth
- [ ] Automated tests: Did you add appropriate automated tests for any code changes?
- [ ] Manual tests: Did you update the [manual tests](../blob/main/docs/testing/manual_testing) as appropriate? _While we aim for automated testing of the application, some aspects require manual testing. If you had to manually test something during development of this pull request, write those steps down._
- [ ] Code coverage: Did you check the code coverage report for the automated tests? _While we are not looking for perfect coverage, the tool can point out potential cases that have been missed._
- [ ] Documentation: Did you update documentation as appropiate? (e.g [README.md](../blob/main/README.md), etc.)
- [ ] Documentation: Did you update documentation as appropriate? (e.g [README.md](../blob/main/README.md), etc.)
- [ ] Run the app: Did you run the app and try the changes?
- [ ] Screenshots: Did you provide before and after UI screenshots in the description of this pull request? _This is only applicable for changes that modify the UI._
- [ ] Rebase and squash: Did you pull in the latest changes from the main branch and squash your commits before assigning a reviewer? _Having your code up to date and squashed will make it easier for others to review. Use best judgement when squashing commits, as some changes (such as refactoring) might be easier to review as a separate commit._

1
.gitignore vendored
View File

@ -16,3 +16,4 @@ bin/
build/
gen/
local.properties
/.idea/deploymentTargetDropDown.xml

4
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
# Default ignored files
/shelf/
/workspace.xml
misc.xml

1
.idea/.name Normal file
View File

@ -0,0 +1 @@
zcash-android-app

View File

@ -0,0 +1,23 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="clean" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="clean" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration>
</component>

View File

@ -0,0 +1,23 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="dependencyUpdates" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="dependencyUpdates" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration>
</component>

View File

@ -0,0 +1,23 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="detektAll" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="detektAll" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration>
</component>

View File

@ -0,0 +1,23 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lint" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="lint" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration>
</component>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@ -9,9 +9,7 @@ While we aim to continue improving this sample, it is not an official product.
If you'd like to compile this application from source, please see our [Setup Documentation](docs/Setup.md) to get started.
# Reporting an issue
If you wish to report a security issue, please follow our [Responsible Disclosure guidelines](https://github.com/zcash/ZcashLightClientKit/blob/master/responsible_disclosure.md). See the [Wallet App Threat Model](https://zcash.readthedocs.io/en/latest/rtd_pages/wallet_threat_model.html) for more information about the security and privacy limitations of the wallet. There are some known security and privacy limitations:
- Traffic analysis, like in other cryptocurrency wallets, can leak some privacy of the user.
- The wallet requires a trust in the server to display accurate transaction information.
If you wish to report a security issue, please follow our [Responsible Disclosure guidelines](https://github.com/zcash/ZcashLightClientKit/blob/master/responsible_disclosure.md). See the [Wallet App Threat Model](https://zcash.readthedocs.io/en/latest/rtd_pages/wallet_threat_model.html) for more information about the security and privacy limitations of the wallet.
If you'd like to report a technical issue or feature request for the Android Wallet, please file a [GitHub issue](https://github.com/zcash/secant-android-wallet/issues/new/choose).
@ -21,3 +19,16 @@ General Zcash questions and/or support requests and are best directed to either:
# Contributing
Contributions are very much welcomed! Please read our [Contributing Guidelines](docs/CONTRIBUTING.md) to learn about our process.
# 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. Remove any copyrighted ZCash or Electric Coin Company icons, logos, or assets
1. Change the package name
1. Under [app/build.gradle.kts](app/build.gradle.kts), change the package name of the application
1. Under [app/proguard-project.txt](app/proguard-project.txt), change the `-repackageclasses` directive to your own package name
# Known Issues
1. During builds, a warning will be printed that says "Unable to detect AGP versions for included builds. All projects in the build should use the same AGP version." This can be safely ignored. The version under build-conventions is the same as the version used elsewhere in the application.

103
app/build.gradle.kts Normal file
View File

@ -0,0 +1,103 @@
plugins {
id("com.android.application")
kotlin("android")
id("kotlin-parcelize")
id("androidx.navigation.safeargs")
id("zcash.android-build-conventions")
}
val packageName = "cash.z.ecc.android"
android {
defaultConfig {
applicationId = packageName
versionCode = 1
versionName = "1.0"
}
buildFeatures {
viewBinding = true
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = libs.versions.compose.get()
}
flavorDimensions.add("network")
productFlavors {
// would rather name them "testnet" and "mainnet" but product flavor names cannot start with the word "test"
create("zcashtestnet") {
dimension = "network"
applicationId = "$packageName.testnet" // allow to be installed alongside mainnet
matchingFallbacks.addAll(listOf("zcashtestnet", "debug"))
}
create("zcashmainnet") {
dimension = "network"
applicationId = packageName
matchingFallbacks.addAll(listOf("zcashmainnet", "release"))
}
}
buildTypes {
getByName("release").apply {
isMinifyEnabled = project.property("IS_MINIFY_ENABLED").toString().toBoolean()
proguardFiles.addAll(
listOf(
getDefaultProguardFile("proguard-android-optimize.txt"),
File("proguard-project.txt")
)
)
}
}
signingConfigs {
val releaseKeystorePath = project.property("ZCASH_RELEASE_KEYSTORE_PATH").toString()
val releaseKeystorePassword = project.property("ZCASH_RELEASE_KEYSTORE_PASSWORD").toString()
val releaseKeyAlias = project.property("ZCASH_RELEASE_KEY_ALIAS").toString()
val releaseKeyAliasPassword =
project.property("ZCASH_RELEASE_KEY_ALIAS_PASSWORD").toString()
val isReleaseSigningConfigured = listOf(
releaseKeystorePath,
releaseKeystorePassword,
releaseKeyAlias,
releaseKeyAliasPassword
).all { !it.isNullOrBlank() }
if (isReleaseSigningConfigured) {
// If this block doesn't execute, the output will be unsigned
create("release").apply {
storeFile = File(releaseKeystorePath)
storePassword = releaseKeystorePassword
keyAlias = releaseKeyAlias
keyPassword = releaseKeyAliasPassword
}
}
}
// 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()
}
}
dependencies {
implementation(libs.androidx.activity)
implementation(libs.androidx.annotation)
implementation(libs.androidx.core)
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)
}

9
app/proguard-project.txt Normal file
View File

@ -0,0 +1,9 @@
# This improves obfuscation.
-repackageclasses 'cash.z.ecc.android'
# Ensure that stacktraces are reversible.
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable
# Generate the combined proguard configuration for debugging.
-printconfiguration build/outputs/proguard-config.txt

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="cash.z.ecc.android.sdk.demoapp">
<application
android:name="cash.z.ecc.android.app.App"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyApplication">
<!-- Alias acts as the entrypoint to the application.
Using an alias ensures we can refactor the actual Activity without breaking
clients. -->
<activity-alias
android:name=".LauncherActivity"
android:label="@string/"
android:targetActivity="cash.z.ecc.android.app.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

@ -0,0 +1,19 @@
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,38 @@
package cash.z.ecc.android.app
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material.MaterialTheme
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
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApplicationTheme {
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
Greeting("Android")
}
}
}
}
}
@Composable
fun Greeting(name: String) {
Text(text = "Hello $name!")
}
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
MyApplicationTheme {
Greeting("Android")
}
}

View File

@ -0,0 +1,61 @@
package cash.z.ecc.android.app
import android.annotation.SuppressLint
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.os.StrictMode
object StrictModeHelper {
fun enableStrictMode() {
configureStrictMode()
// Workaround for Android bug
// https://issuetracker.google.com/issues/36951662
// Not needed if target O_MR1 and running on O_MR1
// Don't really need to check target, because of Google Play enforcement on targetSdkVersion for app updates
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) {
Handler(Looper.getMainLooper()).postAtFrontOfQueue { configureStrictMode() }
}
}
@SuppressLint("NewApi")
private fun configureStrictMode() {
StrictMode.enableDefaults()
StrictMode.setThreadPolicy(
StrictMode.ThreadPolicy.Builder().apply {
detectAll()
penaltyLog()
}.build()
)
// Don't enable missing network tags, because those are noisy.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
StrictMode.setVmPolicy(
StrictMode.VmPolicy.Builder().apply {
detectActivityLeaks()
detectCleartextNetwork()
detectContentUriWithoutPermission()
detectFileUriExposure()
detectLeakedClosableObjects()
detectLeakedRegistrationObjects()
detectLeakedSqlLiteObjects()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
// Disable because this is mostly flagging Android X and Play Services
// builder.detectNonSdkApiUsage();
}
}.build()
)
} else {
StrictMode.setVmPolicy(
StrictMode.VmPolicy.Builder().apply {
detectAll()
penaltyLog()
}.build()
)
}
}
}

View File

@ -0,0 +1,15 @@
package cash.z.ecc.android.app.ui.theme
import androidx.compose.ui.graphics.Color
@Suppress("MagicNumber")
val Purple200 = Color(0xFFBB86FC)
@Suppress("MagicNumber")
val Purple500 = Color(0xFF6200EE)
@Suppress("MagicNumber")
val Purple700 = Color(0xFF3700B3)
@Suppress("MagicNumber")
val Teal200 = Color(0xFF03DAC5)

View File

@ -0,0 +1,11 @@
package cash.z.ecc.android.app.ui.theme
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Shapes
import androidx.compose.ui.unit.dp
val Shapes = Shapes(
small = RoundedCornerShape(4.dp),
medium = RoundedCornerShape(4.dp),
large = RoundedCornerShape(0.dp)
)

View File

@ -0,0 +1,47 @@
package cash.z.ecc.android.app.ui.theme
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material.MaterialTheme
import androidx.compose.material.darkColors
import androidx.compose.material.lightColors
import androidx.compose.runtime.Composable
private val DarkColorPalette = darkColors(
primary = Purple200,
primaryVariant = Purple700,
secondary = Teal200
)
private val LightColorPalette = lightColors(
primary = Purple500,
primaryVariant = Purple700,
secondary = Teal200
/* Other default colors to override
background = Color.White,
surface = Color.White,
onPrimary = Color.White,
onSecondary = Color.Black,
onBackground = Color.Black,
onSurface = Color.Black,
*/
)
@Composable
fun MyApplicationTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable() () -> Unit
) {
val colors = if (darkTheme) {
DarkColorPalette
} else {
LightColorPalette
}
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
}

View File

@ -0,0 +1,28 @@
package cash.z.ecc.android.app.ui.theme
import androidx.compose.material.Typography
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
// Set of Material typography styles to start with
val Typography = Typography(
body1 = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 16.sp
)
/* Other default text styles to override
button = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.W500,
fontSize = 14.sp
),
caption = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 12.sp
)
*/
)

View File

@ -0,0 +1,31 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108"
android:width="108dp">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeColor="#00000000"
android:strokeWidth="1" />
</vector>

View File

@ -0,0 +1,171 @@
<?xml version="1.0" encoding="utf-8"?>
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108"
android:width="108dp">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
</vector>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon
xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon
xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

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>

View File

@ -0,0 +1,21 @@
import org.jetbrains.kotlin.konan.properties.loadProperties
plugins {
`kotlin-dsl`
}
dependencies {
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin")
implementation("com.android.tools.build:gradle:${getAndroidGradlePluginVersion()}")
}
fun getAndroidGradlePluginVersion(): String {
// A slightly gross way to use the root gradle.properties as the single source of truth for version numbers
val properties = run {
val rootPropertiesFile = File(project.projectDir.parentFile, "gradle.properties")
loadProperties(rootPropertiesFile.path)
}
return properties.getProperty("ANDROID_GRADLE_PLUGIN_VERSION")
}

View File

@ -0,0 +1,15 @@
pluginManagement {
repositories {
gradlePluginPortal()
}
}
@Suppress("UnstableApiUsage")
dependencyResolutionManagement {
repositories {
mavenCentral()
google()
}
}
rootProject.name = "build-conventions"

View File

@ -0,0 +1,85 @@
pluginManager.withPlugin("com.android.application") {
project.the<com.android.build.gradle.AppExtension>().apply {
configureBaseExtension()
defaultConfig {
minSdk = (project.property("ANDROID_MIN_SDK_VERSION").toString().toInt())
targetSdk = (project.property("ANDROID_TARGET_SDK_VERSION").toString().toInt())
// en_XA and ar_XB are pseudolocales for debugging.
// The rest of the locales provides an explicit list of the languages to keep in the
// final app. Doing this will strip out additional locales from libraries like
// Google Play Services and Firebase, which add unnecessary bloat.
resourceConfigurations.addAll(listOf("en", "en-rUS", "en-rGB", "en-rAU", "en_XA", "ar_XB"))
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
if (project.property("IS_USE_TEST_ORCHESTRATOR").toString().toBoolean()) {
testInstrumentationRunnerArguments["clearPackageData"] = "true"
}
}
}
}
pluginManager.withPlugin("com.android.library") {
project.the<com.android.build.gradle.LibraryExtension>().apply {
configureBaseExtension()
defaultConfig {
minSdk = project.property("ANDROID_MIN_SDK_VERSION").toString().toInt()
targetSdk = project.property("ANDROID_TARGET_SDK_VERSION").toString().toInt()
// The last two are for support of pseudolocales in debug builds.
// If we add other localizations, they should be included in this list.
// By explicitly setting supported locales, we strip out unused localizations from third party
// libraries (e.g. play services)
resourceConfigurations.addAll(listOf("en", "en-rUS", "en-rGB", "en-rAU", "en_XA", "ar_XB"))
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("proguard-consumer.txt")
if (project.property("IS_USE_TEST_ORCHESTRATOR").toString().toBoolean()) {
testInstrumentationRunnerArguments["clearPackageData"] = "true"
}
}
testCoverage {
jacocoVersion = project.property("JACOCO_VERSION").toString()
}
}
}
fun com.android.build.gradle.BaseExtension.configureBaseExtension() {
compileSdkVersion(project.property("ANDROID_COMPILE_SDK_VERSION").toString().toInt())
ndkVersion = project.property("ANDROID_NDK_VERSION").toString()
compileOptions {
val javaVersion = JavaVersion.toVersion(project.property("ANDROID_JVM_TARGET").toString())
sourceCompatibility = javaVersion
targetCompatibility = javaVersion
}
buildTypes {
getByName("debug").apply {
isTestCoverageEnabled = project.property("IS_COVERAGE_ENABLED").toString().toBoolean()
}
}
signingConfigs {
val debugKeystorePath = project.property("ZCASH_DEBUG_KEYSTORE_PATH").toString()
val isExplicitDebugSigningEnabled = !debugKeystorePath.isNullOrBlank()
if (isExplicitDebugSigningEnabled) {
// If this block doesn't execute, the output will still be signed with the default keystore
getByName("debug").apply {
storeFile = File(debugKeystorePath)
}
}
}
testOptions {
animationsDisabled = true
if (project.property("IS_USE_TEST_ORCHESTRATOR").toString().toBoolean()) {
execution = "ANDROIDX_TEST_ORCHESTRATOR"
}
}
}

58
build.gradle.kts Normal file
View File

@ -0,0 +1,58 @@
import org.gradle.internal.impldep.org.junit.experimental.categories.Categories.CategoryFilter.exclude
buildscript {
repositories {
google()
mavenCentral()
maven("https://jitpack.io")
gradlePluginPortal()
}
dependencies {
classpath("com.android.tools.build:gradle:${properties["ANDROID_GRADLE_PLUGIN_VERSION"]}")
classpath("androidx.navigation:navigation-safe-args-gradle-plugin:${properties["ANDROIDX_NAVIGATION_VERSION"]}")
}
}
plugins {
kotlin("jvm")
id("com.github.ben-manes.versions")
id("io.gitlab.arturbosch.detekt")
}
tasks {
register("detektAll", io.gitlab.arturbosch.detekt.Detekt::class) {
parallel = true
setSource(files(projectDir))
include("**/*.kt")
include("**/*.kts")
exclude("**/resources/**")
exclude("**/build/**")
exclude("**/commonTest/**")
exclude("**/jvmTest/**")
exclude("**/androidTest/**")
config.setFrom(files("${rootProject.projectDir}/tools/detekt.yml"))
buildUponDefaultConfig = true
}
withType<com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask> {
gradleReleaseChannel = "current"
resolutionStrategy {
componentSelection {
all {
if (isNonStable(candidate.version) && !isNonStable(currentVersion)) {
reject("Unstable")
}
}
}
}
}
}
val unstableKeywords = listOf("alpha", "beta", "rc", "m", "ea", "build")
fun isNonStable(version: String): Boolean {
val versionLowerCase = version.toLowerCase()
return unstableKeywords.any { versionLowerCase.contains(it) }
}

View File

@ -1,2 +1,7 @@
# Architecture
TODO This is a placeholder for describing the app architecture.
TODO This is a placeholder for describing the app architecture.
## Gradle
* Versions are declared in `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`, 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` 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

View File

@ -1,8 +1,8 @@
# Overall:
- Does the contribution referece an existing Issue?
- Does the contribution reference an existing GitHub issue?
- Are the requirements well defined?
- Does static analysis pass? (e.g. `./gradlew detektAll` and `./gradlew lint`)
# Specification:

View File

@ -1,24 +1,18 @@
# Setup Guide
## Gradle
The app is built with Gradle and can be compiled on macOS, Windows, and Linux.
The app is built with Gradle and can be compiled on macOS, Windows, and Linux. Development is typically done with the latest stable release of Android Studio.
Tip: On macOS and Linux, Gradle is invoked with `./gradlew`. On Windows, Gradle is invoked with `gradlew`. Throughout the documentation, the macOS and Linux syntax is used by default.
Tip: You do NOT need to install Gradle yourself. Running it from the command line or building the application within Android Studio will download the necessary dependencies automatically.
## Android Studio
Development is typically done with the latest stable release of Android Studio.
## Step by Step
To get set up for development, there are several steps that you need to go through. Going through these steps in order is important, as each step in the progression builds on the prior steps.
Start by making sure the command line with Gradle works first, because **all the Android Studio run configurations use Gradle internally.** The run configurations are not magic—they map directly to command line invocations with different arguments.
When troubleshooting, fall back to trying the command line. Android Studio is a large and complex application, although under the hood it uses Gradle. Sometimes Android Studio will have a bug or failure that is bypassed by using the Gradle command line directly.
1. Install Java
1. Java 16 is currently recommended. Java 11 is the minimum requirement for Android Studio.
1. To simplify installation, use [Oracle's JDK](https://www.oracle.com/java/technologies/javase-jdk15-downloads.html) installer that will place the Java installation in the right place
1. To simplify installation, use [Oracle's JDK](https://www.oracle.com/java/technologies/javase-jdk16-downloads.html) installer that will place the Java installation in the right place
1. Install Android Studio and the Android SDK
1. Download the [stable release of Android Studio](https://developer.android.com/studio#downloads)
1. TODO: Fill in step-by-step instructions for setting up a new environment and installing the Android SDK from within Android Studio.
@ -31,14 +25,33 @@ When troubleshooting, fall back to trying the command line. Android Studio is a
1. From within Android Studio, choose to open an existing project and navigate to the checked out repo
1. After Android Studio finishes syncing with Gradle, look for the green "play" run button in the toolbar. To the left of it, choose the "App" run configuration under the dropdown menu. Then hit the run button
# Troubleshooting
Sometimes during upgrades to Gradle or Kotlin, corruption or weird issues can happen with a build. Try troubleshooting with the following steps:
## Troubleshooting
1. Try running from the command line instead of Android Studio, to rule out Android Studio issues. If it works from the command line, try this step to reset Android Studio
1. Quit Android Studio
2. Deleting the invisible `.idea` in the root directory of the project
3. Relaunch Android Studio
1. Quit Android Studio
2. Deleting the invisible `.idea` in the root directory of the project
3. Relaunch Android Studio
2. Clean the individual Gradle project by running `./gradlew clean` which will purge local build outputs.
3. Run Gradle with the flag `--rerun-tasks` which will effectively disable the build cache by re-running tasks and repopulating the cache. E.g. `./gradlew assemble --rerun-tasks`
4. Reboot your computer, which will ensure that Gradle and Kotlin daemons are completely killed and relaunched
5. Delete the global Gradle cache under `~/.gradle/caches`
5. Delete the global Gradle cache under `~/.gradle/caches`
## Gradle Tasks
A variety of Gradle tasks are set up within the project, and these tasks are also accessible in Android Studio as run configurations.
`assemble` - Compiles the application
`detektAll` - Performs static analysis with Detekt
`lint` - Performs static analysis with Android lint
`dependencyUpdates` - Checks for available dependency updates
## Gradle Properties
A variety of Gradle properties can be used to configure the build.
### Debug Signing
By default, the application is signed by the developers automatically generated debug signing key. In a team of developers, it may be advantageous to share a debug key so that debug builds can access key-restricted services such as Firebase or Google Maps. For such a setup, the path to a shared debug signing key can be set with the property `ZCASH_DEBUG_KEYSTORE_PATH`.
### Release Signing
To enable release signing, a release keystore needs to be provided during the build. This can be injected securely by setting the following Gradle properties.
* ZCASH_RELEASE_KEYSTORE_PATH
* ZCASH_RELEASE_KEYSTORE_PASSWORD
* ZCASH_RELEASE_KEY_ALIAS
* ZCASH_RELEASE_KEY_ALIAS_PASSWORD
On a developer machine, these might be set under the user's global properties (e.g. `~/.gradle/gradle.properties` on macOS and Linux). On a continuous integration machine, these can also be set using environment variables with the prefix `ORG_GRADLE_PROJECT_` (e.g. `ORG_GRADLE_PROJECT_ZCASH_RELEASE_KEYSTORE_PATH`). DO NOT set these in the gradle.properties inside the Git repository, as this will leak your keystore password.

63
gradle.properties Normal file
View File

@ -0,0 +1,63 @@
# Speed up builds. Keep these flags here for quick debugging of issues.
org.gradle.vfs.watch=true
org.gradle.configureondemand=false
org.gradle.caching=true
org.gradle.parallel=true
kapt.include.compile.classpath=false
kapt.incremental.apt=true
kapt.use.worker.api=true
android.useAndroidX=true
android.builder.sdkDownload=true
# Optionally configure code coverage, as historically Jacoco has at times been buggy with respect to new Kotlin versions
IS_COVERAGE_ENABLED=true
# Optionally configure test orchestrator.
# It is disabled by default, because it causes tests to take about 2x longer to run.
IS_USE_TEST_ORCHESTRATOR=false
# Optionally disable minification
IS_MINIFY_ENABLED=true
# Set keystore details to enable build signing. Typically these
# are overridden via ~/.gradle/gradle.properties to allow secure injection.
# Debug keystore is useful if using Google Maps or Firebase, which require API keys to be linked
# to a signing key. Without a debug keystore, the default Android debug keystore will be used.
# Without a release signing configuration, the release output will not be signed.
ZCASH_DEBUG_KEYSTORE_PATH=
ZCASH_RELEASE_KEYSTORE_PATH=
ZCASH_RELEASE_KEYSTORE_PASSWORD=
ZCASH_RELEASE_KEY_ALIAS=
ZCASH_RELEASE_KEY_ALIAS_PASSWORD=
# Versions
ANDROID_MIN_SDK_VERSION=24
ANDROID_TARGET_SDK_VERSION=31
ANDROID_COMPILE_SDK_VERSION=31
ANDROID_NDK_VERSION=23.0.7599858
ANDROID_GRADLE_PLUGIN_VERSION=7.0.2
DETEKT_VERSION=1.18.1
GRADLE_VERSIONS_PLUGIN_VERSION=0.38.0
ANDROIDX_ACTIVITY_VERSION=1.3.1
ANDROIDX_ANNOTATION_VERSION=1.2.0
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_NAVIGATION_VERSION=2.3.5
ANDROIDX_TEST_JUNIT_VERSION=1.1.3
ANDROIDX_TEST_ORCHESTRATOR_VERSION=1.1.0-alpha1
ANDROIDX_UI_AUTOMATOR_VERSION=2.2.0-alpha1
GOOGLE_MATERIAL_VERSION=1.4.0
JACOCO_VERSION=0.8.7
KOTLINX_COROUTINES_VERSION=1.5.1
KOTLIN_VERSION=1.5.21
ZCASH_SDK_VERSION=1.3.0-beta18
# This shouldn't be changed, as Android doesn't support targets beyond Java 8
ANDROID_JVM_TARGET=1.8

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

234
gradlew vendored Executable file
View File

@ -0,0 +1,234 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

89
gradlew.bat vendored Normal file
View File

@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

110
settings.gradle.kts Normal file
View File

@ -0,0 +1,110 @@
enableFeaturePreview("VERSION_CATALOGS")
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
pluginManagement {
repositories {
gradlePluginPortal()
google()
}
plugins {
val detektVersion = extra["DETEKT_VERSION"].toString()
val gradleVersionsPluginVersion = extra["GRADLE_VERSIONS_PLUGIN_VERSION"].toString()
val kotlinVersion = extra["KOTLIN_VERSION"].toString()
kotlin("jvm") version (kotlinVersion)
id("com.github.ben-manes.versions") version (gradleVersionsPluginVersion) apply (false)
id("io.gitlab.arturbosch.detekt") version (detektVersion) apply (false)
}
}
dependencyResolutionManagement {
@Suppress("UnstableApiUsage")
repositories {
google()
mavenCentral()
maven("https://jitpack.io")
}
@Suppress("UnstableApiUsage", "MaxLineLength")
versionCatalogs {
create("libs") {
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 androidxCoreVersion = extra["ANDROIDX_CORE_VERSION"].toString()
val androidxEspressoVersion = extra["ANDROIDX_ESPRESSO_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()
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()
// Standalone versions
version("compose", androidxComposeVersion)
version("jacoco", jacocoVersion)
version("java", javaVersion)
// 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-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-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}")
alias("androidx-espresso-intents").to("androidx.test.espresso:espresso-intents:${androidxEspressoVersion}")
alias("androidx-junit").to("androidx.test.ext:junit:${androidxTestJunitVersion}")
alias("androidx-testOrchestrator").to("androidx.test:orchestrator:${androidxTestOrchestratorVersion}")
alias("androidx-uiAutomator").to("androidx.test.uiautomator:uiautomator-v18:${androidxUiAutomatorVersion}")
alias("kotlinx-coroutines-test").to("org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinxCoroutinesVersion")
// Bundles
bundle(
"androidx-compose",
listOf(
"androidx-activity-compose",
"androidx-compose-foundation",
"androidx-compose-material",
"androidx-compose-material-icons-core",
"androidx-compose-tooling",
"androidx-compose-ui",
"androidx-viewmodel-compose"
)
)
bundle(
"androidx-test",
listOf(
"androidx-espresso-core",
"androidx-espresso-intents",
"androidx-espresso-contrib",
"androidx-junit"
)
)
}
}
}
rootProject.name = "zcash-android-app"
includeBuild("build-conventions")
include("app")

797
tools/detekt.yml Normal file
View File

@ -0,0 +1,797 @@
build:
maxIssues: 0
excludeCorrectable: false
weights:
# complexity: 2
# LongParameterList: 1
# style: 1
# comments: 1
config:
validation: true
warningsAsErrors: false
# when writing own rules with new properties, exclude the property path e.g.: 'my_rule_set,.*>.*>[my_property]'
excludes: ''
processors:
active: true
exclude:
- 'DetektProgressListener'
# - 'KtFileCountProcessor'
# - 'PackageCountProcessor'
# - 'ClassCountProcessor'
# - 'FunctionCountProcessor'
# - 'PropertyCountProcessor'
# - 'ProjectComplexityProcessor'
# - 'ProjectCognitiveComplexityProcessor'
# - 'ProjectLLOCProcessor'
# - 'ProjectCLOCProcessor'
# - 'ProjectLOCProcessor'
# - 'ProjectSLOCProcessor'
# - 'LicenseHeaderLoaderExtension'
console-reports:
active: true
exclude:
- 'ProjectStatisticsReport'
- 'ComplexityReport'
- 'NotificationReport'
# - 'FindingsReport'
- 'FileBasedFindingsReport'
output-reports:
active: true
exclude:
# - 'TxtOutputReport'
# - 'XmlOutputReport'
# - 'HtmlOutputReport'
comments:
active: true
AbsentOrWrongFileLicense:
active: false
licenseTemplateFile: 'license.template'
licenseTemplateIsRegex: false
CommentOverPrivateFunction:
active: false
CommentOverPrivateProperty:
active: false
DeprecatedBlockTag:
active: false
EndOfSentenceFormat:
active: false
endOfSentenceFormat: '([.?!][ \t\n\r\f<])|([.?!:]$)'
UndocumentedPublicClass:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
searchInNestedClass: true
searchInInnerClass: true
searchInInnerObject: true
searchInInnerInterface: true
UndocumentedPublicFunction:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
UndocumentedPublicProperty:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
complexity:
active: true
ComplexCondition:
active: true
threshold: 4
ComplexInterface:
active: false
threshold: 10
includeStaticDeclarations: false
includePrivateDeclarations: false
ComplexMethod:
active: true
threshold: 15
ignoreSingleWhenExpression: false
ignoreSimpleWhenEntries: false
ignoreNestingFunctions: false
nestingFunctions:
- 'also'
- 'apply'
- 'forEach'
- 'isNotNull'
- 'ifNull'
- 'let'
- 'run'
- 'use'
- 'with'
LabeledExpression:
active: false
ignoredLabels: []
LargeClass:
active: true
threshold: 600
LongMethod:
active: true
threshold: 60
ignoreAnnotated: []
LongParameterList:
active: true
functionThreshold: 6
constructorThreshold: 7
ignoreDefaultParameters: false
ignoreDataClasses: true
ignoreAnnotated: []
MethodOverloading:
active: false
threshold: 6
NamedArguments:
active: false
threshold: 3
NestedBlockDepth:
active: true
threshold: 4
ReplaceSafeCallChainWithRun:
active: false
StringLiteralDuplication:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
threshold: 3
ignoreAnnotation: true
excludeStringsWithLessThan5Characters: true
ignoreStringsRegex: '$^'
TooManyFunctions:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
thresholdInFiles: 11
thresholdInClasses: 11
thresholdInInterfaces: 11
thresholdInObjects: 11
thresholdInEnums: 11
ignoreDeprecated: false
ignorePrivate: false
ignoreOverridden: false
coroutines:
active: true
GlobalCoroutineUsage:
active: false
RedundantSuspendModifier:
active: false
SleepInsteadOfDelay:
active: false
SuspendFunWithFlowReturnType:
active: false
empty-blocks:
active: true
EmptyCatchBlock:
active: true
allowedExceptionNameRegex: '_|(ignore|expected).*'
EmptyClassBlock:
active: true
EmptyDefaultConstructor:
active: true
EmptyDoWhileBlock:
active: true
EmptyElseBlock:
active: true
EmptyFinallyBlock:
active: true
EmptyForBlock:
active: true
EmptyFunctionBlock:
active: true
ignoreOverridden: false
EmptyIfBlock:
active: true
EmptyInitBlock:
active: true
EmptyKtFile:
active: true
EmptySecondaryConstructor:
active: true
EmptyTryBlock:
active: true
EmptyWhenBlock:
active: true
EmptyWhileBlock:
active: true
exceptions:
active: true
ExceptionRaisedInUnexpectedLocation:
active: true
methodNames:
- 'equals'
- 'finalize'
- 'hashCode'
- 'toString'
InstanceOfCheckForException:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
NotImplementedDeclaration:
active: false
ObjectExtendsThrowable:
active: false
PrintStackTrace:
active: true
RethrowCaughtException:
active: true
ReturnFromFinally:
active: true
ignoreLabeled: false
SwallowedException:
active: true
ignoredExceptionTypes:
- 'InterruptedException'
- 'MalformedURLException'
- 'NumberFormatException'
- 'ParseException'
allowedExceptionNameRegex: '_|(ignore|expected).*'
ThrowingExceptionFromFinally:
active: true
ThrowingExceptionInMain:
active: false
ThrowingExceptionsWithoutMessageOrCause:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
exceptions:
- 'ArrayIndexOutOfBoundsException'
- 'Exception'
- 'IllegalArgumentException'
- 'IllegalMonitorStateException'
- 'IllegalStateException'
- 'IndexOutOfBoundsException'
- 'NullPointerException'
- 'RuntimeException'
- 'Throwable'
ThrowingNewInstanceOfSameException:
active: true
TooGenericExceptionCaught:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
exceptionNames:
- 'ArrayIndexOutOfBoundsException'
- 'Error'
- 'Exception'
- 'IllegalMonitorStateException'
- 'IndexOutOfBoundsException'
- 'NullPointerException'
- 'RuntimeException'
- 'Throwable'
allowedExceptionNameRegex: '_|(ignore|expected).*'
TooGenericExceptionThrown:
active: true
exceptionNames:
- 'Error'
- 'Exception'
- 'RuntimeException'
- 'Throwable'
formatting:
active: true
android: false
autoCorrect: true
AnnotationOnSeparateLine:
active: false
autoCorrect: true
AnnotationSpacing:
active: false
autoCorrect: true
ArgumentListWrapping:
active: false
autoCorrect: true
indentSize: 4
maxLineLength: 120
ChainWrapping:
active: true
autoCorrect: true
CommentSpacing:
active: true
autoCorrect: true
EnumEntryNameCase:
active: false
autoCorrect: true
Filename:
active: true
FinalNewline:
active: true
autoCorrect: true
insertFinalNewLine: true
ImportOrdering:
active: false
autoCorrect: true
layout: '*,java.**,javax.**,kotlin.**,^'
Indentation:
active: false
autoCorrect: true
indentSize: 4
continuationIndentSize: 4
MaximumLineLength:
active: true
maxLineLength: 120
ignoreBackTickedIdentifier: false
ModifierOrdering:
active: true
autoCorrect: true
MultiLineIfElse:
active: true
autoCorrect: true
NoBlankLineBeforeRbrace:
active: true
autoCorrect: true
NoConsecutiveBlankLines:
active: true
autoCorrect: true
NoEmptyClassBody:
active: true
autoCorrect: true
NoEmptyFirstLineInMethodBlock:
active: false
autoCorrect: true
NoLineBreakAfterElse:
active: true
autoCorrect: true
NoLineBreakBeforeAssignment:
active: true
autoCorrect: true
NoMultipleSpaces:
active: true
autoCorrect: true
NoSemicolons:
active: true
autoCorrect: true
NoTrailingSpaces:
active: true
autoCorrect: true
NoUnitReturn:
active: true
autoCorrect: true
NoUnusedImports:
active: true
autoCorrect: true
NoWildcardImports:
active: true
PackageName:
active: true
autoCorrect: true
ParameterListWrapping:
active: true
autoCorrect: true
indentSize: 4
maxLineLength: 120
SpacingAroundAngleBrackets:
active: false
autoCorrect: true
SpacingAroundColon:
active: true
autoCorrect: true
SpacingAroundComma:
active: true
autoCorrect: true
SpacingAroundCurly:
active: true
autoCorrect: true
SpacingAroundDot:
active: true
autoCorrect: true
SpacingAroundDoubleColon:
active: false
autoCorrect: true
SpacingAroundKeyword:
active: true
autoCorrect: true
SpacingAroundOperators:
active: true
autoCorrect: true
SpacingAroundParens:
active: true
autoCorrect: true
SpacingAroundRangeOperator:
active: true
autoCorrect: true
SpacingAroundUnaryOperator:
active: false
autoCorrect: true
SpacingBetweenDeclarationsWithAnnotations:
active: false
autoCorrect: true
SpacingBetweenDeclarationsWithComments:
active: false
autoCorrect: true
StringTemplate:
active: true
autoCorrect: true
naming:
active: true
BooleanPropertyNaming:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
allowedPattern: '^(is|has|are)'
ClassNaming:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
classPattern: '[A-Z][a-zA-Z0-9]*'
ConstructorParameterNaming:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
parameterPattern: '[a-z][A-Za-z0-9]*'
privateParameterPattern: '[a-z][A-Za-z0-9]*'
excludeClassPattern: '$^'
ignoreOverridden: true
EnumNaming:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
enumEntryPattern: '[A-Z][_a-zA-Z0-9]*'
ForbiddenClassName:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
forbiddenName: []
FunctionMaxLength:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
maximumFunctionNameLength: 30
FunctionMinLength:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
minimumFunctionNameLength: 3
FunctionNaming:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
functionPattern: '([a-z][a-zA-Z0-9]*)|(`.*`)'
excludeClassPattern: '$^'
ignoreOverridden: true
ignoreAnnotated:
- 'Composable'
FunctionParameterNaming:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
parameterPattern: '[a-z][A-Za-z0-9]*'
excludeClassPattern: '$^'
ignoreOverridden: true
InvalidPackageDeclaration:
active: false
excludes: ['**/*.kts']
rootPackage: ''
MatchingDeclarationName:
active: true
mustBeFirst: true
MemberNameEqualsClassName:
active: true
ignoreOverridden: true
NoNameShadowing:
active: false
NonBooleanPropertyPrefixedWithIs:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
ObjectPropertyNaming:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
constantPattern: '[A-Za-z][_A-Za-z0-9]*'
propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
privatePropertyPattern: '(_)?[A-Za-z][_A-Za-z0-9]*'
PackageNaming:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
packagePattern: '[a-z]+(\.[a-z][A-Za-z0-9]*)*'
TopLevelPropertyNaming:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
constantPattern: '[A-Z][_A-Z0-9]*'
propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
privatePropertyPattern: '_?[A-Za-z][_A-Za-z0-9]*'
VariableMaxLength:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
maximumVariableNameLength: 64
VariableMinLength:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
minimumVariableNameLength: 1
VariableNaming:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
variablePattern: '[a-z][A-Za-z0-9]*'
privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*'
excludeClassPattern: '$^'
ignoreOverridden: true
performance:
active: true
ArrayPrimitive:
active: true
ForEachOnRange:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
SpreadOperator:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
UnnecessaryTemporaryInstantiation:
active: true
potential-bugs:
active: true
AvoidReferentialEquality:
active: false
forbiddenTypePatterns:
- 'kotlin.String'
CastToNullableType:
active: false
Deprecation:
active: false
DontDowncastCollectionTypes:
active: false
DoubleMutabilityForCollection:
active: false
DuplicateCaseInWhenExpression:
active: true
EqualsAlwaysReturnsTrueOrFalse:
active: true
EqualsWithHashCodeExist:
active: true
ExitOutsideMain:
active: false
ExplicitGarbageCollectionCall:
active: true
HasPlatformType:
active: false
IgnoredReturnValue:
active: false
restrictToAnnotatedMethods: true
returnValueAnnotations:
- '*.CheckResult'
- '*.CheckReturnValue'
ignoreReturnValueAnnotations:
- '*.CanIgnoreReturnValue'
ImplicitDefaultLocale:
active: true
ImplicitUnitReturnType:
active: false
allowExplicitReturnType: true
InvalidRange:
active: true
IteratorHasNextCallsNextMethod:
active: true
IteratorNotThrowingNoSuchElementException:
active: true
LateinitUsage:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
excludeAnnotatedProperties: []
ignoreOnClassesPattern: ''
MapGetWithNotNullAssertionOperator:
active: false
MissingWhenCase:
active: true
allowElseExpression: true
NullableToStringCall:
active: false
RedundantElseInWhen:
active: true
UnconditionalJumpStatementInLoop:
active: false
UnnecessaryNotNullOperator:
active: true
UnnecessarySafeCall:
active: true
UnreachableCatchBlock:
active: false
UnreachableCode:
active: true
UnsafeCallOnNullableType:
active: true
UnsafeCast:
active: true
UnusedUnaryOperator:
active: false
UselessPostfixExpression:
active: false
WrongEqualsTypeParameter:
active: true
style:
active: true
ClassOrdering:
active: false
CollapsibleIfStatements:
active: false
DataClassContainsFunctions:
active: false
conversionFunctionPrefix: 'to'
DataClassShouldBeImmutable:
active: false
DestructuringDeclarationWithTooManyEntries:
active: false
maxDestructuringEntries: 3
EqualsNullCall:
active: true
EqualsOnSignatureLine:
active: false
ExplicitCollectionElementAccessMethod:
active: false
ExplicitItLambdaParameter:
active: false
ExpressionBodySyntax:
active: false
includeLineWrapping: false
ForbiddenComment:
active: true
values:
- 'FIXME:'
- 'STOPSHIP:'
- 'TODO:'
allowedPatterns: '\[[^\]]\d+\]'
ForbiddenImport:
active: false
imports: []
forbiddenPatterns: ''
ForbiddenMethodCall:
active: false
methods:
- 'kotlin.io.print'
- 'kotlin.io.println'
ForbiddenPublicDataClass:
active: true
excludes: ['**']
ignorePackages:
- '*.internal'
- '*.internal.*'
ForbiddenVoid:
active: false
ignoreOverridden: false
ignoreUsageInGenerics: false
FunctionOnlyReturningConstant:
active: true
ignoreOverridableFunction: true
ignoreActualFunction: true
excludedFunctions: ''
excludeAnnotatedFunction:
- 'dagger.Provides'
LibraryCodeMustSpecifyReturnType:
active: true
excludes: ['**']
LibraryEntitiesShouldNotBePublic:
active: true
excludes: ['**']
LoopWithTooManyJumpStatements:
active: true
maxJumpCount: 1
MagicNumber:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
ignoreNumbers:
- '-1'
- '0'
- '1'
- '2'
ignoreHashCodeFunction: true
ignorePropertyDeclaration: false
ignoreLocalVariableDeclaration: false
ignoreConstantDeclaration: true
ignoreCompanionObjectPropertyDeclaration: true
ignoreAnnotation: false
ignoreNamedArgument: true
ignoreEnums: false
ignoreRanges: false
ignoreExtensionFunctions: true
MandatoryBracesIfStatements:
active: false
MandatoryBracesLoops:
active: false
MaxLineLength:
active: true
maxLineLength: 120
excludePackageStatements: true
excludeImportStatements: true
excludeCommentStatements: false
MayBeConst:
active: true
ModifierOrder:
active: true
MultilineLambdaItParameter:
active: false
NestedClassesVisibility:
active: true
NewLineAtEndOfFile:
active: true
NoTabs:
active: false
ObjectLiteralToLambda:
active: false
OptionalAbstractKeyword:
active: true
OptionalUnit:
active: false
OptionalWhenBraces:
active: false
PreferToOverPairSyntax:
active: false
ProtectedMemberInFinalClass:
active: true
RedundantExplicitType:
active: false
RedundantHigherOrderMapUsage:
active: false
RedundantVisibilityModifierRule:
active: false
ReturnCount:
active: true
max: 2
excludedFunctions: 'equals'
excludeLabeled: false
excludeReturnFromLambda: true
excludeGuardClauses: false
SafeCast:
active: true
SerialVersionUIDInSerializableClass:
active: true
SpacingBetweenPackageAndImports:
active: false
ThrowsCount:
active: true
max: 2
excludeGuardClauses: false
TrailingWhitespace:
active: false
UnderscoresInNumericLiterals:
active: false
acceptableDecimalLength: 5
UnnecessaryAbstractClass:
active: true
excludeAnnotatedClasses:
- 'dagger.Module'
UnnecessaryAnnotationUseSiteTarget:
active: false
UnnecessaryApply:
active: true
UnnecessaryFilter:
active: false
UnnecessaryInheritance:
active: true
UnnecessaryLet:
active: false
UnnecessaryParentheses:
active: false
UntilInsteadOfRangeTo:
active: false
UnusedImports:
active: false
UnusedPrivateClass:
active: true
UnusedPrivateMember:
active: true
allowedNames: '(_|ignored|expected|serialVersionUID)'
UseArrayLiteralsInAnnotations:
active: false
UseCheckNotNull:
active: false
UseCheckOrError:
active: false
UseDataClass:
active: false
excludeAnnotatedClasses: []
allowVars: false
UseEmptyCounterpart:
active: false
UseIfEmptyOrIfBlank:
active: false
UseIfInsteadOfWhen:
active: false
UseIsNullOrEmpty:
active: false
UseOrEmpty:
active: false
UseRequire:
active: false
UseRequireNotNull:
active: false
UselessCallOnNotNull:
active: true
UtilityClassWithPublicConstructor:
active: true
VarCouldBeVal:
active: true
WildcardImport:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
excludeImports:
- 'java.util.*'
- 'kotlinx.android.synthetic.*'