Ktlint 1.5.0

This commit is contained in:
Honza 2025-03-11 16:24:30 +01:00
parent 31ac7b8c6d
commit 37ed3841e4
231 changed files with 1971 additions and 1671 deletions

View File

@ -1,6 +1,8 @@
package model
enum class BuildType(val value: String) {
enum class BuildType(
val value: String
) {
DEBUG("debug"),
RELEASE("release"),
BENCHMARK("benchmark")

View File

@ -1,6 +1,8 @@
package model
enum class NetworkDimension(val value: String) {
enum class NetworkDimension(
val value: String
) {
MAINNET("zcashmainnet"),
TESTNET("zcashtestnet");
@ -9,7 +11,9 @@ enum class NetworkDimension(val value: String) {
}
}
enum class DistributionDimension(val value: String) {
enum class DistributionDimension(
val value: String
) {
STORE("store"),
FOSS("foss");

View File

@ -47,7 +47,8 @@ data class ChangelogEntry(
GsonBuilder()
.serializeNulls()
.create()
.toJson(this).replace("\"", "\\\"")
.toJson(this)
.replace("\"", "\\\"")
}
data class ChangelogEntrySection(

View File

@ -65,7 +65,8 @@ object ChangelogParser {
log("Parser: index from: $fromIndex")
val toIndex =
nodes.subList(fromIndex + 1, nodes.size)
nodes
.subList(fromIndex + 1, nodes.size)
.indexOfFirst { findNodeByPrefix(it) }
.let {
// Applies to the last or the only one entry
@ -117,24 +118,22 @@ object ChangelogParser {
subNode.startsWith("### ${titleByLanguage(TitleType.FIXED, languageTag)}") ||
subNode.startsWith("### ${titleByLanguage(TitleType.REMOVED, languageTag)}")
private fun List<String>.getVersionPart(versionNameFallback: String): String {
return if (this.contains("## [Unreleased]")) {
private fun List<String>.getVersionPart(versionNameFallback: String): String =
if (this.contains("## [Unreleased]")) {
versionNameFallback
} else {
// Parse just version name omitting version code as we currently don't need it in the UI
this[0].split("[")[1].split(" ")[0].trim()
}
}
private val dateFormatter = SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH)
private fun List<String>.getDatePart(): String {
return if (this.contains("## [Unreleased]")) {
private fun List<String>.getDatePart(): String =
if (this.contains("## [Unreleased]")) {
dateFormatter.format(Date())
} else {
this[0].split("- ")[1].trim()
}
}
private fun List<String>.getNodePart(title: String): ChangelogEntrySection? {
val fromContent = "### $title"
@ -160,7 +159,8 @@ object ChangelogParser {
// To remove hard line wrap from AS
.map { it.replace("\n ", "") }
.joinToString(prefix = "\n", separator = "\n")
.takeIf { it.isNotBlank() }?.let {
.takeIf { it.isNotBlank() }
?.let {
ChangelogEntrySection(title = title, content = it)
}
}
@ -168,8 +168,8 @@ object ChangelogParser {
private fun titleByLanguage(
type: TitleType,
languageTag: LanguageTag
): String {
return when (type) {
): String =
when (type) {
TitleType.ADDED ->
when (languageTag) {
is LanguageTag.English -> ADDED_PART_EN
@ -191,13 +191,18 @@ object ChangelogParser {
is LanguageTag.Spanish -> REMOVED_PART_ES
}
}
}
}
sealed class LanguageTag(open val tag: String) {
data class English(override val tag: String = ENGLISH_TAG) : LanguageTag(tag)
sealed class LanguageTag(
open val tag: String
) {
data class English(
override val tag: String = ENGLISH_TAG
) : LanguageTag(tag)
data class Spanish(override val tag: String = SPANISH_TAG) : LanguageTag(tag)
data class Spanish(
override val tag: String = SPANISH_TAG
) : LanguageTag(tag)
}
private enum class TitleType {

View File

@ -23,4 +23,7 @@ object Git {
}
}
data class GitInfo(val sha: String, val commitCount: Int)
data class GitInfo(
val sha: String,
val commitCount: Int
)

View File

@ -13,32 +13,35 @@ import kotlinx.datetime.Instant
class MergingConfigurationProvider(
private val configurationProviders: PersistentList<ConfigurationProvider>
) : ConfigurationProvider {
override fun peekConfiguration(): Configuration {
return MergingConfiguration(configurationProviders.map { it.peekConfiguration() }.toPersistentList())
}
override fun peekConfiguration(): Configuration =
MergingConfiguration(
configurationProviders
.map {
it.peekConfiguration()
}.toPersistentList()
)
override fun getConfigurationFlow(): Flow<Configuration> {
return if (configurationProviders.isEmpty()) {
override fun getConfigurationFlow(): Flow<Configuration> =
if (configurationProviders.isEmpty()) {
flowOf(MergingConfiguration(persistentListOf<Configuration>()))
} else {
combine(configurationProviders.map { it.getConfigurationFlow() }) { configurations ->
MergingConfiguration(configurations.toList().toPersistentList())
}
}
}
override fun hintToRefresh() {
configurationProviders.forEach { it.hintToRefresh() }
}
}
private data class MergingConfiguration(private val configurations: PersistentList<Configuration>) : Configuration {
private data class MergingConfiguration(
private val configurations: PersistentList<Configuration>
) : Configuration {
override val updatedAt: Instant?
get() = configurations.mapNotNull { it.updatedAt }.maxOrNull()
override fun hasKey(key: ConfigKey): Boolean {
return null != configurations.firstWithKey(key)
}
override fun hasKey(key: ConfigKey): Boolean = null != configurations.firstWithKey(key)
// TODO [#1373]: Catch and log Configuration Key Coercion Failures
// TODO [#1373]: https://github.com/Electric-Coin-Company/zashi-android/issues/1373

View File

@ -7,7 +7,9 @@ package co.electriccoin.zcash.configuration.model.entry
* least common denominator with some reasonable limits on what the keys can contain.
*/
@JvmInline
value class ConfigKey(val key: String) {
value class ConfigKey(
val key: String
) {
init {
requireKeyConstraints(key)
}

View File

@ -4,4 +4,7 @@ package co.electriccoin.zcash.configuration.model.exception
* Exception that may occur when parsing a value from the remote configuration. This could mean that someone made an
* error in the remote config console.
*/
class ConfigurationParseException(message: String, cause: Throwable?) : IllegalArgumentException(message, cause)
class ConfigurationParseException(
message: String,
cause: Throwable?
) : IllegalArgumentException(message, cause)

View File

@ -109,14 +109,12 @@ class MergingConfigurationProviderTest {
}
}
private class MockConfigurationProvider(private val configuration: Configuration) : ConfigurationProvider {
override fun peekConfiguration(): Configuration {
return configuration
}
private class MockConfigurationProvider(
private val configuration: Configuration
) : ConfigurationProvider {
override fun peekConfiguration(): Configuration = configuration
override fun getConfigurationFlow(): Flow<Configuration> {
return flowOf(configuration)
}
override fun getConfigurationFlow(): Flow<Configuration> = flowOf(configuration)
override fun hintToRefresh() {
// no-op

View File

@ -11,7 +11,9 @@ import kotlinx.datetime.Instant
* mutate the configuration by mutating the original map. The mapping is stored in a val field
* though, making the initial mapping thread-safe.
*/
class MockConfiguration(private val configurationMapping: Map<String, String> = emptyMap()) : Configuration {
class MockConfiguration(
private val configurationMapping: Map<String, String> = emptyMap()
) : Configuration {
override val updatedAt: Instant? = null
@Throws(ConfigurationParseException::class)

View File

@ -34,8 +34,8 @@ class IntentConfigurationReceiver : BroadcastReceiver() {
}
// https://issuetracker.google.com/issues/36927401
private fun Intent.defuse(): Intent? {
return try {
private fun Intent.defuse(): Intent? =
try {
extras?.containsKey(null)
this
} catch (
@ -43,4 +43,3 @@ private fun Intent.defuse(): Intent? {
) {
null
}
}

View File

@ -4,9 +4,8 @@ import android.content.Context
import co.electriccoin.zcash.crash.android.internal.local.LocalCrashReporter
class ListCrashReportersImpl : ListCrashReporters {
override fun provideReporters(context: Context): List<CrashReporter> {
return listOfNotNull(
override fun provideReporters(context: Context): List<CrashReporter> =
listOfNotNull(
LocalCrashReporter.getInstance(context),
)
}
}

View File

@ -10,7 +10,8 @@ import java.io.File
@Suppress("ReturnCount")
suspend fun ExceptionPath.getExceptionDirectory(context: Context): File? {
val exceptionDirectory =
context.getExternalFilesDirSuspend(null)
context
.getExternalFilesDirSuspend(null)
?.let { File(File(it, ExceptionPath.LOG_DIRECTORY_NAME), ExceptionPath.EXCEPTION_DIRECTORY_NAME) }
if (null == exceptionDirectory) {

View File

@ -64,5 +64,6 @@ object GlobalCrashReporter {
}
private fun isCrashProcess(context: Context) =
ProcessNameCompat.getProcessName(context)
ProcessNameCompat
.getProcessName(context)
.endsWith(GlobalCrashReporter.CRASH_PROCESS_NAME_SUFFIX)

View File

@ -13,7 +13,9 @@ import kotlinx.coroutines.launch
/**
* Registers an exception handler to write exceptions to disk.
*/
internal class LocalCrashReporter(private val applicationContext: Context) : CrashReporter {
internal class LocalCrashReporter(
private val applicationContext: Context
) : CrashReporter {
private val crashReportingScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
@AnyThread
@ -41,8 +43,6 @@ internal class LocalCrashReporter(private val applicationContext: Context) : Cra
LocalCrashReporter(it.applicationContext)
}
fun getInstance(context: Context): CrashReporter {
return lazyWithArgument.getInstance(context)
}
fun getInstance(context: Context): CrashReporter = lazyWithArgument.getInstance(context)
}
}

View File

@ -36,4 +36,6 @@ private suspend fun getFirebaseAppContainer(context: Context): FirebaseAppContai
FirebaseAppContainer(firebaseApp)
}
private class FirebaseAppContainer(val firebaseApp: FirebaseApp?)
private class FirebaseAppContainer(
val firebaseApp: FirebaseApp?
)

View File

@ -121,9 +121,7 @@ private class FirebaseCrashReporterImpl(
}
}
suspend fun getInstance(context: Context): CrashReporter? {
return lazyWithArgument.getInstance(context)
}
suspend fun getInstance(context: Context): CrashReporter? = lazyWithArgument.getInstance(context)
}
}

View File

@ -36,4 +36,6 @@ private suspend fun getFirebaseAppContainer(context: Context): FirebaseAppContai
FirebaseAppContainer(firebaseApp)
}
private class FirebaseAppContainer(val firebaseApp: FirebaseApp?)
private class FirebaseAppContainer(
val firebaseApp: FirebaseApp?
)

View File

@ -121,9 +121,7 @@ private class FirebaseCrashReporterImpl(
}
}
suspend fun getInstance(context: Context): CrashReporter? {
return lazyWithArgument.getInstance(context)
}
suspend fun getInstance(context: Context): CrashReporter? = lazyWithArgument.getInstance(context)
}
}

View File

@ -36,4 +36,6 @@ private suspend fun getFirebaseAppContainer(context: Context): FirebaseAppContai
FirebaseAppContainer(firebaseApp)
}
private class FirebaseAppContainer(val firebaseApp: FirebaseApp?)
private class FirebaseAppContainer(
val firebaseApp: FirebaseApp?
)

View File

@ -121,9 +121,7 @@ private class FirebaseCrashReporterImpl(
}
}
suspend fun getInstance(context: Context): CrashReporter? {
return lazyWithArgument.getInstance(context)
}
suspend fun getInstance(context: Context): CrashReporter? = lazyWithArgument.getInstance(context)
}
}

View File

@ -36,4 +36,6 @@ private suspend fun getFirebaseAppContainer(context: Context): FirebaseAppContai
FirebaseAppContainer(firebaseApp)
}
private class FirebaseAppContainer(val firebaseApp: FirebaseApp?)
private class FirebaseAppContainer(
val firebaseApp: FirebaseApp?
)

View File

@ -121,9 +121,7 @@ private class FirebaseCrashReporterImpl(
}
}
suspend fun getInstance(context: Context): CrashReporter? {
return lazyWithArgument.getInstance(context)
}
suspend fun getInstance(context: Context): CrashReporter? = lazyWithArgument.getInstance(context)
}
}

View File

@ -161,7 +161,7 @@ FULLADLE_VERSION=0.17.5
GOOGLE_PLAY_SERVICES_GRADLE_PLUGIN_VERSION=4.4.2
GRADLE_VERSIONS_PLUGIN_VERSION=0.52.0
JGIT_VERSION=6.4.0.202211300538-r
KTLINT_VERSION=1.2.1
KTLINT_VERSION=1.5.0
KOIN_VERSION=4.0.2
ACCOMPANIST_PERMISSIONS_VERSION=0.37.2

View File

@ -45,7 +45,8 @@ interface PreferenceDefault<T> {
* indicating what was stored in the preferences, in addition to subsequent updates.
*/
fun observe(preferenceProvider: PreferenceProvider): Flow<T> =
preferenceProvider.observe(key)
preferenceProvider
.observe(key)
.map { getValue(preferenceProvider) }
.distinctUntilChanged()
}

View File

@ -9,7 +9,9 @@ import kotlin.jvm.JvmInline
* find a least common denominator with some reasonable limits on what the keys can contain.
*/
@JvmInline
value class PreferenceKey(val key: String) {
value class PreferenceKey(
val key: String
) {
init {
requireKeyConstraints(key)
}

View File

@ -172,7 +172,9 @@ class AndroidPreferenceProvider private constructor(
val sharedPreferences =
withContext(singleThreadedDispatcher) {
val mainKey =
MasterKey.Builder(context).apply {
MasterKey
.Builder(context)
.apply {
setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
}.build()

View File

@ -3,8 +3,9 @@ package co.electriccoin.zcash.preference
import android.content.Context
import co.electriccoin.zcash.preference.api.PreferenceProvider
class EncryptedPreferenceProvider(private val context: Context) : PreferenceHolder() {
override suspend fun create(): PreferenceProvider {
return AndroidPreferenceProvider.newEncrypted(context, "co.electriccoin.zcash.encrypted")
}
class EncryptedPreferenceProvider(
private val context: Context
) : PreferenceHolder() {
override suspend fun create(): PreferenceProvider =
AndroidPreferenceProvider.newEncrypted(context, "co.electriccoin.zcash.encrypted")
}

View File

@ -3,8 +3,9 @@ package co.electriccoin.zcash.preference
import android.content.Context
import co.electriccoin.zcash.preference.api.PreferenceProvider
class StandardPreferenceProvider(private val context: Context) : PreferenceHolder() {
override suspend fun create(): PreferenceProvider {
return AndroidPreferenceProvider.newStandard(context, "co.electriccoin.zcash")
}
class StandardPreferenceProvider(
private val context: Context
) : PreferenceHolder() {
override suspend fun create(): PreferenceProvider =
AndroidPreferenceProvider.newStandard(context, "co.electriccoin.zcash")
}

View File

@ -10,9 +10,8 @@ import java.text.DecimalFormat
import java.util.Locale
@Suppress("MagicNumber")
fun PercentDecimal.toPercentageWithDecimal(decimalFormat: DecimalFormat = preparePercentDecimalFormat()): String {
return decimalFormat.format(decimal * 100)
}
fun PercentDecimal.toPercentageWithDecimal(decimalFormat: DecimalFormat = preparePercentDecimalFormat()): String =
decimalFormat.format(decimal * 100)
private fun preparePercentDecimalFormat(): DecimalFormat =
DecimalFormat().apply {

View File

@ -15,7 +15,9 @@ sealed class SeedPhraseValidation {
object FailedChecksum : SeedPhraseValidation()
class Valid(val seedPhrase: SeedPhrase) : SeedPhraseValidation()
class Valid(
val seedPhrase: SeedPhrase
) : SeedPhraseValidation()
companion object {
suspend fun new(list: List<String>): SeedPhraseValidation {

View File

@ -3,7 +3,11 @@ package cash.z.ecc.sdk.model
import cash.z.ecc.android.sdk.model.WalletAddress
import cash.z.ecc.android.sdk.model.Zatoshi
data class ZecRequest(val address: WalletAddress.Unified, val amount: Zatoshi, val message: ZecRequestMessage) {
data class ZecRequest(
val address: WalletAddress.Unified,
val amount: Zatoshi,
val message: ZecRequestMessage
) {
// TODO [#397]: Waiting for an implementation of Uri parser in SDK project
// TODO [#397]: https://github.com/Electric-Coin-Company/zcash-android-wallet-sdk/issues/397
suspend fun toUri(): String {
@ -21,7 +25,9 @@ data class ZecRequest(val address: WalletAddress.Unified, val amount: Zatoshi, v
}
@JvmInline
value class ZecRequestMessage(val value: String) {
value class ZecRequestMessage(
val value: String
) {
init {
require(value.length <= MAX_MESSAGE_LENGTH)
}

View File

@ -13,9 +13,7 @@ object AndroidApiVersion {
@ChecksSdkIntAtLeast(parameter = 0)
private fun isAtLeast(
@IntRange(from = Build.VERSION_CODES.BASE.toLong()) sdk: Int
): Boolean {
return Build.VERSION.SDK_INT >= sdk
}
): Boolean = Build.VERSION.SDK_INT >= sdk
/**
* @param sdk SDK version number to test against the current environment.
@ -23,9 +21,7 @@ object AndroidApiVersion {
*/
private fun isExactly(
@IntRange(from = Build.VERSION_CODES.BASE.toLong()) sdk: Int
): Boolean {
return Build.VERSION.SDK_INT == sdk
}
): Boolean = Build.VERSION.SDK_INT == sdk
val isExactlyO = isExactly(Build.VERSION_CODES.O_MR1)

View File

@ -10,7 +10,9 @@ import kotlinx.coroutines.launch
* @param broadcastReceiverScope Scope for performing asynchronous work in the broadcast receiver.
* It is not recommended to cancel this scope.
*/
abstract class CoroutineBroadcastReceiver(private val broadcastReceiverScope: CoroutineScope) : BroadcastReceiver() {
abstract class CoroutineBroadcastReceiver(
private val broadcastReceiverScope: CoroutineScope
) : BroadcastReceiver() {
final override fun onReceive(
context: Context,
intent: Intent

View File

@ -13,7 +13,9 @@ object StrictModeCompat {
StrictMode.enableDefaults()
StrictMode.setThreadPolicy(
StrictMode.ThreadPolicy.Builder().apply {
StrictMode.ThreadPolicy
.Builder()
.apply {
detectAll()
if (isCrashOnViolation) {
penaltyDeath()
@ -25,7 +27,9 @@ object StrictModeCompat {
// Don't enable missing network tags, because those are noisy.
StrictMode.setVmPolicy(
StrictMode.VmPolicy.Builder().apply {
StrictMode.VmPolicy
.Builder()
.apply {
if (AndroidApiVersion.isAtLeastS) {
detectUnsafeIntentLaunch()
}

View File

@ -50,37 +50,27 @@ open class AbstractProcessNameContentProvider : ContentProvider() {
selection: String?,
selectionArgs: Array<out String>?,
sortOrder: String?
): Cursor? {
throw UnsupportedOperationException()
}
): Cursor? = throw UnsupportedOperationException()
override fun getType(uri: Uri): String? {
throw UnsupportedOperationException()
}
override fun getType(uri: Uri): String? = throw UnsupportedOperationException()
override fun insert(
uri: Uri,
values: ContentValues?
): Uri? {
throw UnsupportedOperationException()
}
): Uri? = throw UnsupportedOperationException()
override fun delete(
uri: Uri,
selection: String?,
selectionArgs: Array<out String>?
): Int {
throw UnsupportedOperationException()
}
): Int = throw UnsupportedOperationException()
override fun update(
uri: Uri,
values: ContentValues?,
selection: String?,
selectionArgs: Array<out String>?
): Int {
throw UnsupportedOperationException()
}
): Int = throw UnsupportedOperationException()
companion object {
internal fun getProcessNameLegacy(

View File

@ -54,15 +54,14 @@ object ProcessNameCompat {
* @return Name of the current process. May return null if a failure occurs, which is possible
* due to some race conditions in Android.
*/
private fun searchForProcessName(context: Context): String? {
return if (AndroidApiVersion.isAtLeastTiramisu) {
private fun searchForProcessName(context: Context): String? =
if (AndroidApiVersion.isAtLeastTiramisu) {
getProcessNameTPlus()
} else if (AndroidApiVersion.isAtLeastP) {
getProcessNamePPlus()
} else {
searchForProcessNameLegacy(context)
}
}
@RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
private fun getProcessNameTPlus() = Process.myProcessName()

View File

@ -5,7 +5,9 @@ package co.electriccoin.zcash.spackle
*
* This class is thread-safe.
*/
class LazyWithArgument<in Input, out Output>(private val deferredCreator: ((Input) -> Output)) {
class LazyWithArgument<in Input, out Output>(
private val deferredCreator: ((Input) -> Output)
) {
@Volatile
private var singletonInstance: Output? = null

View File

@ -8,7 +8,9 @@ import kotlinx.coroutines.sync.withLock
*
* This class is thread-safe.
*/
class SuspendingLazy<in Input, out Output>(private val deferredCreator: suspend ((Input) -> Output)) {
class SuspendingLazy<in Input, out Output>(
private val deferredCreator: suspend ((Input) -> Output)
) {
private var singletonInstance: Output? = null
private val mutex = Mutex()

View File

@ -6,7 +6,9 @@ package co.electriccoin.zcash.spackle.model
* @param value A 0-based index. Must be >= 0
*/
@JvmInline
value class Index(val value: Int) {
value class Index(
val value: Int
) {
init {
require(value >= 0) { "Index must be >= 0 but actually is $value" }
}

View File

@ -1,6 +1,9 @@
package co.electriccoin.zcash.spackle.model
data class Progress(val current: Index, val last: Index) {
data class Progress(
val current: Index,
val last: Index
) {
init {
require(last.value > 0) { "last must be > 0 but was $last" }
require(last.value >= current.value) { "last ($last) must be >= current ($current)" }

View File

@ -28,7 +28,8 @@ open class UiTestPrerequisites {
private fun isScreenOn(): Boolean {
val powerService =
ApplicationProvider.getApplicationContext<Context>()
ApplicationProvider
.getApplicationContext<Context>()
.getSystemService(Context.POWER_SERVICE) as PowerManager
return powerService.isInteractive
}
@ -41,7 +42,8 @@ open class UiTestPrerequisites {
private fun isKeyguardLocked(): Boolean {
val keyguardService = (
ApplicationProvider.getApplicationContext<Context>()
ApplicationProvider
.getApplicationContext<Context>()
.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
)

View File

@ -13,7 +13,8 @@ open class ZcashUiTestRunner : AndroidJUnitRunner() {
super.onCreate(arguments)
val powerManager =
ApplicationProvider.getApplicationContext<Context>()
ApplicationProvider
.getApplicationContext<Context>()
.getSystemService(Context.POWER_SERVICE) as PowerManager
// There is no alternative to this deprecated API. The suggestion of a view to keep the screen

View File

@ -5,3 +5,4 @@ ktlint_standard_trailing-comma-on-call-site = disabled
ktlint_standard_trailing-comma-on-declaration-site = disabled
# When using Compose, suppress the `function-naming` rule in favor of PascalCase naming convention
ktlint_function_naming_ignore_when_annotated_with=Composable
ktlint_standard_function-signature=disabled

View File

@ -119,7 +119,8 @@ private fun splitBalance(balanceStringParts: ZecAmountTriple): Pair<String, Stri
Twig.debug { "Balance parts before calculation: $balanceStringParts" }
val cutPosition =
balanceStringParts.main.indexOf(
balanceStringParts.main
.indexOf(
startIndex = 0,
char = MonetarySeparators.current(Locale.getDefault()).decimal,
ignoreCase = true
@ -160,7 +161,10 @@ data class ZecAmountTriple(
)
@Immutable
data class BalanceTextStyle(val mostSignificantPart: TextStyle, val leastSignificantPart: TextStyle)
data class BalanceTextStyle(
val mostSignificantPart: TextStyle,
val leastSignificantPart: TextStyle
)
object StyledBalanceDefaults {
@Stable

View File

@ -103,8 +103,7 @@ fun LabeledCheckBox(
top = ZcashTheme.dimens.spacingTiny,
bottom = ZcashTheme.dimens.spacingTiny,
end = ZcashTheme.dimens.spacingTiny
)
.then(
).then(
if (checkBoxTestTag != null) {
Modifier.testTag(checkBoxTestTag)
} else {

View File

@ -120,8 +120,7 @@ fun ChipOnSurface(
color = ZcashTheme.colors.layoutStrokeSecondary
),
shape = RoundedCornerShape(size = ZcashTheme.dimens.regularRippleEffectCorner),
)
.clickable { onClick() },
).clickable { onClick() },
color = ZcashTheme.colors.primaryColor,
shadowElevation = ZcashTheme.dimens.chipShadowElevation,
) {
@ -134,8 +133,7 @@ fun ChipOnSurface(
.padding(
vertical = ZcashTheme.dimens.spacingMid,
horizontal = ZcashTheme.dimens.spacingDefault
)
.testTag(CommonTag.CHIP)
).testTag(CommonTag.CHIP)
)
}
}

View File

@ -45,7 +45,10 @@ fun Override(
}
}
data class ConfigurationOverride(val uiMode: UiMode?, val locale: LocaleList?) {
data class ConfigurationOverride(
val uiMode: UiMode?,
val locale: LocaleList?
) {
fun newConfiguration(fromConfiguration: Configuration) =
Configuration(fromConfiguration).apply {
this@ConfigurationOverride.uiMode?.let {

View File

@ -104,8 +104,7 @@ private fun PagerTab(
.fillMaxSize()
.background(
if (selected) Color.Transparent else ZcashTheme.colors.layoutStroke
)
.padding(vertical = ZcashTheme.dimens.spacingMid, horizontal = ZcashTheme.dimens.spacingXtiny),
).padding(vertical = ZcashTheme.dimens.spacingMid, horizontal = ZcashTheme.dimens.spacingXtiny),
contentAlignment = Alignment.Center,
) {
Text(

View File

@ -8,12 +8,11 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
sealed class ScreenBrightnessState {
fun getChange(): ScreenBrightnessState {
return when (this) {
fun getChange(): ScreenBrightnessState =
when (this) {
NORMAL -> FULL
FULL -> NORMAL
}
}
data object FULL : ScreenBrightnessState()

View File

@ -32,8 +32,7 @@ fun SwitchWithLabel(
indication = null,
role = Role.Switch,
onClick = { onStateChange(!state) }
)
.fillMaxWidth()
).fillMaxWidth()
) {
val (text, spacer, switchButton) = createRefs()
Body(

View File

@ -90,8 +90,7 @@ fun FormTextField(
}
}
}
}
.then(
}.then(
if (withBorder) {
Modifier.border(
width = 1.dp,
@ -105,8 +104,7 @@ fun FormTextField(
} else {
Modifier
}
)
.then(
).then(
if (testTag.isNullOrEmpty()) {
Modifier
} else {

View File

@ -32,6 +32,5 @@ internal val TextFieldColors.selectionColors: TextSelectionColors
@Composable get() = textSelectionColors
@Composable
internal fun TextFieldColors.cursorColor(isError: Boolean): State<Color> {
return rememberUpdatedState(if (isError) errorCursorColor else cursorColor)
}
internal fun TextFieldColors.cursorColor(isError: Boolean): State<Color> =
rememberUpdatedState(if (isError) errorCursorColor else cursorColor)

View File

@ -83,8 +83,7 @@ private fun AccountSwitch(state: AccountSwitchState) {
onClick =
state
.onAccountTypeClick
)
.padding(start = 4.dp),
).padding(start = 4.dp),
verticalAlignment = Alignment.CenterVertically
) {
Image(

View File

@ -163,8 +163,7 @@ private fun FullscreenDialogContent(
interactionSource = remember { MutableInteractionSource() },
indication = null,
onClick = onBack
)
.padding(start = 16.dp, end = 16.dp, bottom = 64.dp)
).padding(start = 16.dp, end = 16.dp, bottom = 64.dp)
) {
ZashiQrInternal(
modifier =

View File

@ -60,8 +60,7 @@ fun RadioButton(
interactionSource = remember { MutableInteractionSource() },
onClick = state.onClick,
role = Role.Button,
)
.padding(horizontal = 20.dp)
).padding(horizontal = 20.dp)
.then(
if (testTag != null) {
Modifier.testTag(testTag)

View File

@ -260,17 +260,13 @@ object ZashiListItemDefaults {
fun primaryColors(
borderColor: Color = Color.Unspecified,
backgroundColor: Color = Color.Transparent
): ZashiListItemColors {
return ZashiListItemColors(borderColor = borderColor, backgroundColor = backgroundColor)
}
): ZashiListItemColors = ZashiListItemColors(borderColor = borderColor, backgroundColor = backgroundColor)
@Composable
fun secondaryColors(
borderColor: Color = ZashiColors.Surfaces.strokeSecondary,
backgroundColor: Color = Color.Transparent
): ZashiListItemColors {
return ZashiListItemColors(borderColor = borderColor, backgroundColor = backgroundColor)
}
): ZashiListItemColors = ZashiListItemColors(borderColor = borderColor, backgroundColor = backgroundColor)
}
@PreviewScreens

View File

@ -14,7 +14,8 @@ object AndroidQrCodeImageGenerator : QrCodeImageGenerator {
): ImageBitmap {
val colorArray = bitArray.toThemeColorArray(colors)
return Bitmap.createBitmap(colorArray, sizePixels, sizePixels, Bitmap.Config.ARGB_8888)
return Bitmap
.createBitmap(colorArray, sizePixels, sizePixels, Bitmap.Config.ARGB_8888)
.asImageBitmap()
}
}

View File

@ -14,7 +14,9 @@ sealed interface ImageResource {
@JvmInline
@Immutable
value class DisplayString(val value: String) : ImageResource
value class DisplayString(
val value: String
) : ImageResource
}
@Stable

View File

@ -62,15 +62,13 @@ data class ScreenHeight(
val systemStatusBarHeight: Dp,
val systemNavigationBarHeight: Dp
) {
fun overallScreenHeight(): Dp {
return (contentHeight + systemBarsHeight()).also {
fun overallScreenHeight(): Dp =
(contentHeight + systemBarsHeight()).also {
Twig.debug { "Screen height: Overall height: $it" }
}
}
fun systemBarsHeight(): Dp {
return (systemStatusBarHeight + systemNavigationBarHeight).also {
fun systemBarsHeight(): Dp =
(systemStatusBarHeight + systemNavigationBarHeight).also {
Twig.debug { "Screen height: System bars height: $it" }
}
}
}

View File

@ -26,22 +26,37 @@ sealed interface StringResource {
@JvmInline
@Immutable
value class ByString(val value: String) : StringResource
value class ByString(
val value: String
) : StringResource
@Immutable
data class ByZatoshi(val zatoshi: Zatoshi) : StringResource
data class ByZatoshi(
val zatoshi: Zatoshi
) : StringResource
@Immutable
data class ByDateTime(val zonedDateTime: ZonedDateTime, val useFullFormat: Boolean) : StringResource
data class ByDateTime(
val zonedDateTime: ZonedDateTime,
val useFullFormat: Boolean
) : StringResource
@Immutable
data class ByYearMonth(val yearMonth: YearMonth) : StringResource
data class ByYearMonth(
val yearMonth: YearMonth
) : StringResource
@Immutable
data class ByTransactionId(val transactionId: String, val abbreviated: Boolean) : StringResource
data class ByTransactionId(
val transactionId: String,
val abbreviated: Boolean
) : StringResource
@Immutable
data class ByAddress(val address: String, val abbreviated: Boolean) : StringResource
data class ByAddress(
val address: String,
val abbreviated: Boolean
) : StringResource
}
@Stable
@ -142,15 +157,28 @@ object StringResourceDefaults {
.getDateTimeInstance(
DateFormat.MEDIUM,
DateFormat.SHORT,
).format(
Date.from(
res.zonedDateTime
.toInstant()
.toKotlinInstant()
.toJavaInstant()
)
)
.format(Date.from(res.zonedDateTime.toInstant().toKotlinInstant().toJavaInstant()))
} else {
val pattern = DateTimeFormatter.ofPattern("MMM dd")
val start = res.zonedDateTime.format(pattern).orEmpty()
val end =
DateFormat
.getTimeInstance(DateFormat.SHORT)
.format(Date.from(res.zonedDateTime.toInstant().toKotlinInstant().toJavaInstant()))
.format(
Date.from(
res.zonedDateTime
.toInstant()
.toKotlinInstant()
.toJavaInstant()
)
)
return "$start $end"
}
@ -161,23 +189,21 @@ object StringResourceDefaults {
return yearMonth.format(pattern).orEmpty()
}
fun convertAddress(res: StringResource.ByAddress): String {
return if (res.abbreviated && res.address.isNotBlank()) {
fun convertAddress(res: StringResource.ByAddress): String =
if (res.abbreviated && res.address.isNotBlank()) {
"${res.address.take(ADDRESS_MAX_LENGTH_ABBREVIATED)}..."
} else {
res.address
}
}
fun convertTransactionId(res: StringResource.ByTransactionId): String {
return if (res.abbreviated) {
fun convertTransactionId(res: StringResource.ByTransactionId): String =
if (res.abbreviated) {
"${res.transactionId.take(TRANSACTION_MAX_PREFIX_SUFFIX_LENGHT)}...${res.transactionId.takeLast(
TRANSACTION_MAX_PREFIX_SUFFIX_LENGHT
)}"
} else {
res.transactionId
}
}
}
private const val TRANSACTION_MAX_PREFIX_SUFFIX_LENGHT = 5

View File

@ -101,7 +101,8 @@ class ScanViewTest : UiTestPrerequisites() {
it.assertDoesNotExist()
}
composeTestRule.onNodeWithText(
composeTestRule
.onNodeWithText(
getStringResourceWithArgs(
resId = R.string.scan_state_permission,
getStringResource(R.string.app_name)

View File

@ -37,7 +37,9 @@ class ScreenBrightnessTest : UiTestPrerequisites() {
assertEquals(ScreenBrightnessState.NORMAL, testSetup.getSecureBrightnessCount())
}
private class TestSetup(composeTestRule: ComposeContentTestRule) {
private class TestSetup(
composeTestRule: ComposeContentTestRule
) {
val mutableScreenBrightnessFlag = MutableStateFlow(true)
private val screenBrightness = ScreenBrightness

View File

@ -58,7 +58,9 @@ class ScreenSecurityTest : UiTestPrerequisites() {
assertEquals(0, testSetup.getSecureScreenCount())
}
private class TestSetup(composeTestRule: ComposeContentTestRule) {
private class TestSetup(
composeTestRule: ComposeContentTestRule
) {
val mutableSecureScreenFlag = MutableStateFlow(true)
private val screenSecurity = ScreenSecurity()

View File

@ -38,7 +38,9 @@ class ScreenTimeoutTest : UiTestPrerequisites() {
assertEquals(0, testSetup.getScreenTimeoutCount())
}
private class TestSetup(composeTestRule: ComposeContentTestRule) {
private class TestSetup(
composeTestRule: ComposeContentTestRule
) {
val mutableScreenTimeoutFlag = MutableStateFlow(true)
private val screenTimeout = ScreenTimeout()

View File

@ -13,7 +13,8 @@ class ConfigurationEntriesTest {
fun keys_unique() {
val fieldValueSet = mutableSetOf<String>()
ConfigurationEntries::class.memberProperties
ConfigurationEntries::class
.memberProperties
.map { it.getter.call(ConfigurationEntries) }
.map { it as DefaultEntry<*> }
.map { it.key }

View File

@ -13,7 +13,8 @@ class StandardPreferenceKeysTest {
fun unique_keys() {
val fieldValueSet = mutableSetOf<String>()
StandardPreferenceKeys::class.memberProperties
StandardPreferenceKeys::class
.memberProperties
.map { it.getter.call(StandardPreferenceKeys) }
.map { it as PreferenceDefault<*> }
.map { it.key }

View File

@ -30,8 +30,7 @@ class AboutViewTest {
.onNodeWithContentDescription(
getStringResource(R.string.back_navigation_content_description),
ignoreCase = true
)
.also {
).also {
it.assertExists()
}
@ -60,7 +59,8 @@ class AboutViewTest {
assertEquals(0, testSetup.getOnBackCount())
composeTestRule.onNodeWithContentDescription(
composeTestRule
.onNodeWithContentDescription(
getStringResource(R.string.back_navigation_content_description)
).also {
it.performClick()

View File

@ -28,7 +28,8 @@ class AccountViewTest : UiTestPrerequisites() {
fun check_all_elementary_ui_elements_displayed() {
newTestSetup()
composeTestRule.onNodeWithTag(CommonTag.TOP_APP_BAR)
composeTestRule
.onNodeWithTag(CommonTag.TOP_APP_BAR)
.also {
it.assertIsDisplayed()
}

View File

@ -35,7 +35,8 @@ class BalancesViewTest : UiTestPrerequisites() {
fun check_all_elementary_ui_elements_displayed() {
newTestSetup()
composeTestRule.onNodeWithTag(CommonTag.TOP_APP_BAR)
composeTestRule
.onNodeWithTag(CommonTag.TOP_APP_BAR)
.also {
it.assertIsDisplayed()
}

View File

@ -8,7 +8,9 @@ import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicInteger
class ExportPrivateDataViewTestSetup(private val composeTestRule: ComposeContentTestRule) {
class ExportPrivateDataViewTestSetup(
private val composeTestRule: ComposeContentTestRule
) {
private val onBackCount = AtomicInteger(0)
private val onAgree = AtomicBoolean(false)

View File

@ -19,18 +19,18 @@ class OnboardingViewTest : UiTestPrerequisites() {
@get:Rule
val composeTestRule = createComposeRule()
private fun newTestSetup(): OnboardingTestSetup {
return OnboardingTestSetup(composeTestRule).apply {
private fun newTestSetup(): OnboardingTestSetup =
OnboardingTestSetup(composeTestRule).apply {
setDefaultContent()
}
}
@Test
@MediumTest
fun layout() {
newTestSetup()
composeTestRule.onNodeWithText(
composeTestRule
.onNodeWithText(
text = getStringResource(R.string.onboarding_create_new_wallet),
ignoreCase = true
).also {
@ -39,7 +39,8 @@ class OnboardingViewTest : UiTestPrerequisites() {
it.assertHasClickAction()
}
composeTestRule.onNodeWithText(
composeTestRule
.onNodeWithText(
text = getStringResource(R.string.onboarding_import_existing_wallet),
ignoreCase = true
).also {

View File

@ -32,7 +32,8 @@ class ReceiveViewTest {
newTestSetup()
// Enable substring for ellipsizing
composeTestRule.onNodeWithText(
composeTestRule
.onNodeWithText(
text = "${WalletAddressFixture.UNIFIED_ADDRESS_STRING.take(20)}...",
substring = true,
useUnmergedTree = true
@ -47,7 +48,8 @@ class ReceiveViewTest {
assertEquals(0, testSetup.getOnSettingsCount())
composeTestRule.onNodeWithContentDescription(
composeTestRule
.onNodeWithContentDescription(
getStringResource(R.string.settings_menu_content_description)
).also {
it.performClick()

View File

@ -34,7 +34,9 @@ class RestoreViewSecuredScreenTest : UiTestPrerequisites() {
assertEquals(1, testSetup.getSecureScreenCount())
}
private class TestSetup(composeTestRule: ComposeContentTestRule) {
private class TestSetup(
composeTestRule: ComposeContentTestRule
) {
private val screenSecurity = ScreenSecurity()
fun getSecureScreenCount() = screenSecurity.referenceCount.value

View File

@ -61,13 +61,15 @@ class RestoreViewTest : UiTestPrerequisites() {
it.assertTextContains("ab")
}
composeTestRule.onNode(
composeTestRule
.onNode(
matcher = hasText("abandon", substring = true) and hasTestTag(RestoreTag.AUTOCOMPLETE_ITEM)
).also {
it.assertExists()
}
composeTestRule.onNode(
composeTestRule
.onNode(
matcher = hasText("able", substring = true) and hasTestTag(RestoreTag.AUTOCOMPLETE_ITEM)
).also {
it.assertExists()
@ -83,7 +85,8 @@ class RestoreViewTest : UiTestPrerequisites() {
it.performTextInput("ab")
}
composeTestRule.onNode(
composeTestRule
.onNode(
matcher = hasText("abandon", substring = true) and hasTestTag(RestoreTag.AUTOCOMPLETE_ITEM)
).also {
it.performClick()
@ -119,7 +122,8 @@ class RestoreViewTest : UiTestPrerequisites() {
it.assertDoesNotExist()
}
composeTestRule.onNode(matcher = hasText(text = "abandon", substring = true))
composeTestRule
.onNode(matcher = hasText(text = "abandon", substring = true))
.also {
it.assertExists()
}
@ -130,7 +134,8 @@ class RestoreViewTest : UiTestPrerequisites() {
fun seed_invalid_phrase_does_not_progress() {
newTestSetup(initialWordsList = generateSequence { "abandon" }.take(SeedPhrase.SEED_PHRASE_SIZE).toList())
composeTestRule.onNodeWithText(
composeTestRule
.onNodeWithText(
text = getStringResource(R.string.restore_seed_button_next),
ignoreCase = true
).also {
@ -146,7 +151,8 @@ class RestoreViewTest : UiTestPrerequisites() {
newTestSetup(initialWordsList = SeedPhraseFixture.new().split)
composeTestRule.onNodeWithText(
composeTestRule
.onNodeWithText(
text = getStringResource(R.string.restore_seed_button_next),
ignoreCase = true
).also {
@ -159,7 +165,8 @@ class RestoreViewTest : UiTestPrerequisites() {
fun seed_clear() {
newTestSetup(initialWordsList = listOf("abandon"))
composeTestRule.onNode(
composeTestRule
.onNode(
matcher = hasText(text = "abandon", substring = true),
useUnmergedTree = true
).also {
@ -170,7 +177,8 @@ class RestoreViewTest : UiTestPrerequisites() {
it.performClick()
}
composeTestRule.onNode(
composeTestRule
.onNode(
matcher = hasText("abandon", substring = true) and hasTestTag(CommonTag.CHIP),
useUnmergedTree = true
).also {
@ -187,7 +195,8 @@ class RestoreViewTest : UiTestPrerequisites() {
initialWordsList = SeedPhraseFixture.new().split
)
composeTestRule.onNodeWithText(
composeTestRule
.onNodeWithText(
text = getStringResource(R.string.restore_birthday_button_restore),
ignoreCase = true
).also {
@ -210,10 +219,14 @@ class RestoreViewTest : UiTestPrerequisites() {
)
composeTestRule.onNodeWithTag(RestoreTag.BIRTHDAY_TEXT_FIELD).also {
it.performTextInput(ZcashNetwork.Mainnet.saplingActivationHeight.value.toString())
it.performTextInput(
ZcashNetwork.Mainnet.saplingActivationHeight.value
.toString()
)
}
composeTestRule.onNodeWithText(
composeTestRule
.onNodeWithText(
text = getStringResource(R.string.restore_birthday_button_restore),
ignoreCase = true
).also {
@ -234,7 +247,8 @@ class RestoreViewTest : UiTestPrerequisites() {
initialWordsList = SeedPhraseFixture.new().split
)
composeTestRule.onNodeWithText(
composeTestRule
.onNodeWithText(
text = getStringResource(R.string.restore_birthday_button_restore),
ignoreCase = true
).also {
@ -245,7 +259,8 @@ class RestoreViewTest : UiTestPrerequisites() {
it.performTextInput((ZcashNetwork.Mainnet.saplingActivationHeight.value - 1L).toString())
}
composeTestRule.onNodeWithText(
composeTestRule
.onNodeWithText(
text = getStringResource(R.string.restore_birthday_button_restore),
ignoreCase = true
).also {
@ -270,7 +285,8 @@ class RestoreViewTest : UiTestPrerequisites() {
it.performTextInput("1.2")
}
composeTestRule.onNodeWithText(
composeTestRule
.onNodeWithText(
text = getStringResource(R.string.restore_birthday_button_restore),
ignoreCase = true
).also {
@ -293,7 +309,8 @@ class RestoreViewTest : UiTestPrerequisites() {
assertEquals(0, testSetup.getOnFinishedCount())
composeTestRule.onNodeWithText(
composeTestRule
.onNodeWithText(
text = getStringResource(R.string.restore_birthday_button_restore),
ignoreCase = true
).also {
@ -310,7 +327,8 @@ class RestoreViewTest : UiTestPrerequisites() {
assertEquals(0, testSetup.getOnBackCount())
composeTestRule.onNodeWithContentDescription(
composeTestRule
.onNodeWithContentDescription(
getStringResource(R.string.back_navigation_content_description)
).also {
it.performClick()
@ -330,7 +348,8 @@ class RestoreViewTest : UiTestPrerequisites() {
assertEquals(0, testSetup.getOnBackCount())
composeTestRule.onNodeWithContentDescription(
composeTestRule
.onNodeWithContentDescription(
getStringResource(R.string.back_navigation_content_description)
).also {
it.performClick()

View File

@ -67,7 +67,8 @@ class ScanViewBasicTest : UiTestPrerequisites() {
// Permission denied ui items (not visible):
composeTestRule.onNodeWithText(
composeTestRule
.onNodeWithText(
text = getStringResource(R.string.scan_settings_button),
ignoreCase = true
).also {

View File

@ -7,7 +7,9 @@ import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicInteger
class SecurityWarningViewTestSetup(private val composeTestRule: ComposeContentTestRule) {
class SecurityWarningViewTestSetup(
private val composeTestRule: ComposeContentTestRule
) {
private val onBackCount = AtomicInteger(0)
private val onAcknowledged = AtomicBoolean(false)

View File

@ -29,7 +29,8 @@ class SettingsViewTest : UiTestPrerequisites() {
assertEquals(0, testSetup.getBackCount())
composeTestRule.onNodeWithContentDescription(
composeTestRule
.onNodeWithContentDescription(
getStringResource(R.string.back_navigation_content_description)
).also {
it.performClick()
@ -45,7 +46,8 @@ class SettingsViewTest : UiTestPrerequisites() {
assertEquals(0, testSetup.getFeedbackCount())
composeTestRule.onNodeWithText(
composeTestRule
.onNodeWithText(
text = getStringResource(R.string.settings_feedback),
ignoreCase = true
).also {
@ -62,7 +64,8 @@ class SettingsViewTest : UiTestPrerequisites() {
assertEquals(0, testSetup.getAdvancedSettingsCount())
composeTestRule.onNodeWithText(
composeTestRule
.onNodeWithText(
text = getStringResource(R.string.settings_advanced_settings),
ignoreCase = true
).also {
@ -79,7 +82,8 @@ class SettingsViewTest : UiTestPrerequisites() {
assertEquals(0, testSetup.getAboutCount())
composeTestRule.onNodeWithText(
composeTestRule
.onNodeWithText(
text = getStringResource(R.string.settings_about_us),
ignoreCase = true
).also {
@ -145,7 +149,8 @@ class SettingsViewTest : UiTestPrerequisites() {
composeTestRule.openTroubleshootingMenu()
composeTestRule.onNodeWithText(
composeTestRule
.onNodeWithText(
getStringResource(R.string.settings_troubleshooting_enable_background_sync)
).also {
it.performClick()
@ -168,7 +173,8 @@ class SettingsViewTest : UiTestPrerequisites() {
composeTestRule.openTroubleshootingMenu()
composeTestRule.onNodeWithText(
composeTestRule
.onNodeWithText(
getStringResource(R.string.settings_troubleshooting_enable_keep_screen_on)
).also {
it.performClick()
@ -191,7 +197,8 @@ class SettingsViewTest : UiTestPrerequisites() {
composeTestRule.openTroubleshootingMenu()
composeTestRule.onNodeWithText(
composeTestRule
.onNodeWithText(
getStringResource(R.string.settings_troubleshooting_enable_analytics)
).also {
it.performClick()

View File

@ -26,7 +26,11 @@ class QrCodeAnalyzerImpl(
override fun analyze(image: ImageProxy) {
image.use {
if (image.format in supportedImageFormats) {
val bytes = image.planes.first().buffer.toByteArray()
val bytes =
image.planes
.first()
.buffer
.toByteArray()
Twig.verbose {
"Scan result: " +
@ -89,7 +93,8 @@ class QrCodeAnalyzerImpl(
runCatching {
val result =
MultiFormatReader().apply {
MultiFormatReader()
.apply {
setHints(
mapOf(
DecodeHintType.POSSIBLE_FORMATS to arrayListOf(BarcodeFormat.QR_CODE),

View File

@ -12,8 +12,8 @@ fun WalletCoordinator.Companion.newInstance(
context: Context,
encryptedPreferenceProvider: EncryptedPreferenceProvider,
persistableWalletPreference: PersistableWalletPreferenceDefault
): WalletCoordinator {
return WalletCoordinator(
): WalletCoordinator =
WalletCoordinator(
context = context,
persistableWallet =
flow {
@ -22,6 +22,5 @@ fun WalletCoordinator.Companion.newInstance(
accountName = context.getString(R.string.zashi_wallet_name),
keySource = ZASHI_KEYSOURCE
)
}
private const val ZASHI_KEYSOURCE = "zashi"

View File

@ -42,11 +42,11 @@ class BiometricActivity : FragmentActivity() {
)
val promptInfo =
BiometricPrompt.PromptInfo.Builder()
BiometricPrompt.PromptInfo
.Builder()
.setTitle(
getString(R.string.authentication_system_ui_title, getString(R.string.app_name))
)
.setSubtitle(subtitle)
).setSubtitle(subtitle)
.setAllowedAuthenticators(biometricRepository.allowedAuthenticators)
.build()

View File

@ -472,7 +472,11 @@ private fun MainActivity.NavigationHome(
val isEnoughSpace by storageCheckViewModel.isEnoughSpace.collectAsStateWithLifecycle()
val sdkStatus = walletViewModel.currentWalletSnapshot.collectAsStateWithLifecycle().value?.status
val sdkStatus =
walletViewModel.currentWalletSnapshot
.collectAsStateWithLifecycle()
.value
?.status
val currentAppState = applicationStateProvider.state.collectAsStateWithLifecycle().value

View File

@ -69,13 +69,21 @@ class NavigationRouterImpl : NavigationRouter {
}
sealed interface NavigationCommand {
data class Forward(val route: Any) : NavigationCommand
data class Forward(
val route: Any
) : NavigationCommand
data class Replace(val route: Any) : NavigationCommand
data class Replace(
val route: Any
) : NavigationCommand
data class ReplaceAll(val route: Any) : NavigationCommand
data class ReplaceAll(
val route: Any
) : NavigationCommand
data class NewRoot(val route: Any) : NavigationCommand
data class NewRoot(
val route: Any
) : NavigationCommand
data object Back : NavigationCommand

View File

@ -106,8 +106,7 @@ class AccountDataSourceImpl(
)
}
}
}
?.flatMapLatest { accountsWithAddresses ->
}?.flatMapLatest { accountsWithAddresses ->
if (accountsWithAddresses == null) {
flowOf(null)
} else {
@ -132,8 +131,7 @@ class AccountDataSourceImpl(
}
}
}
}
?.retryWhen { _, attempt ->
}?.retryWhen { _, attempt ->
emit(null)
delay(attempt.coerceAtMost(RETRY_DELAY).seconds)
true
@ -189,8 +187,7 @@ class AccountDataSourceImpl(
accounts.size == 1,
)
}
}
?.sortedDescending()
}?.sortedDescending()
}.flowOn(Dispatchers.IO)
.stateIn(
scope = scope,
@ -202,15 +199,13 @@ class AccountDataSourceImpl(
allAccounts
.map { account ->
account?.firstOrNull { it.isSelected }
}
.distinctUntilChanged()
}.distinctUntilChanged()
override val zashiAccount: Flow<ZashiAccount?> =
allAccounts
.map { account ->
account?.filterIsInstance<ZashiAccount>()?.firstOrNull()
}
.distinctUntilChanged()
}.distinctUntilChanged()
override suspend fun getAllAccounts() =
withContext(Dispatchers.IO) {
@ -250,7 +245,8 @@ class AccountDataSourceImpl(
index: Long
): Account =
withContext(Dispatchers.IO) {
synchronizerProvider.getSynchronizer()
synchronizerProvider
.getSynchronizer()
.importAccountByUfvk(
AccountImportSetup(
accountName = context.getString(R.string.keystone_wallet_name),

View File

@ -108,7 +108,10 @@ class LocalAddressBookDataSourceImpl(
lastUpdated = lastUpdated,
version = ADDRESS_BOOK_SERIALIZATION_V1,
contacts =
addressBook?.contacts.orEmpty().toMutableList()
addressBook
?.contacts
.orEmpty()
.toMutableList()
.apply {
set(
indexOf(contact),
@ -118,8 +121,7 @@ class LocalAddressBookDataSourceImpl(
lastUpdated = Clock.System.now()
)
)
}
.toList(),
}.toList(),
).also {
addressBook = it
}
@ -138,11 +140,13 @@ class LocalAddressBookDataSourceImpl(
lastUpdated = lastUpdated,
version = ADDRESS_BOOK_SERIALIZATION_V1,
contacts =
addressBook?.contacts.orEmpty().toMutableList()
addressBook
?.contacts
.orEmpty()
.toMutableList()
.apply {
remove(addressBookContact)
}
.toList(),
}.toList(),
).also {
addressBook = it
}
@ -176,7 +180,8 @@ class LocalAddressBookDataSourceImpl(
}
return if (unencryptedFile != null) {
addressBookProvider.readLegacyUnencryptedAddressBookFromFile(unencryptedFile)
addressBookProvider
.readLegacyUnencryptedAddressBookFromFile(unencryptedFile)
.also { unencryptedAddressBook ->
writeAddressBookToLocalStorage(unencryptedAddressBook, addressBookKey)
unencryptedFile.deleteSuspend()

View File

@ -167,8 +167,8 @@ class MetadataDataSourceImpl(
txId: String,
key: MetadataKey,
transform: (AnnotationMetadata) -> AnnotationMetadata
): Metadata {
return updateMetadata(
): Metadata =
updateMetadata(
key = key,
transform = { metadata ->
metadata.copy(
@ -184,14 +184,13 @@ class MetadataDataSourceImpl(
)
}
)
}
private suspend fun updateMetadataBookmark(
txId: String,
key: MetadataKey,
transform: (BookmarkMetadata) -> BookmarkMetadata
): Metadata {
return updateMetadata(
): Metadata =
updateMetadata(
key = key,
transform = { metadata ->
metadata.copy(
@ -207,13 +206,12 @@ class MetadataDataSourceImpl(
)
}
)
}
private suspend fun updateMetadata(
key: MetadataKey,
transform: (AccountMetadata) -> AccountMetadata
): Metadata {
return withContext(Dispatchers.IO) {
): Metadata =
withContext(Dispatchers.IO) {
val metadata = getMetadataInternal(key)
val accountMetadata = metadata.accountMetadata
@ -228,7 +226,6 @@ class MetadataDataSourceImpl(
updatedMetadata
}
}
}
private fun defaultAccountMetadata() =
@ -258,11 +255,11 @@ private fun <T : Any> List<T>.replaceOrAdd(
): List<T> {
val index = this.indexOfFirst(predicate)
return if (index != -1) {
this.toMutableList()
this
.toMutableList()
.apply {
set(index, transform(this[index]))
}
.toList()
}.toList()
} else {
this + transform(null)
}

View File

@ -62,7 +62,9 @@ interface ProposalDataSource {
suspend fun redactPcztForSigner(pczt: Pczt): Pczt
}
class TransactionProposalNotCreatedException(reason: Exception) : Exception(reason)
class TransactionProposalNotCreatedException(
reason: Exception
) : Exception(reason)
@Suppress("TooManyFunctions")
class ProposalDataSourceImpl(
@ -150,7 +152,8 @@ class ProposalDataSourceImpl(
override suspend fun addProofsToPczt(pczt: Pczt): Pczt =
withContext(Dispatchers.IO) {
synchronizerProvider.getSynchronizer()
synchronizerProvider
.getSynchronizer()
.addProofsToPczt(pczt)
}
@ -178,7 +181,8 @@ class ProposalDataSourceImpl(
override suspend fun redactPcztForSigner(pczt: Pczt): Pczt =
withContext(Dispatchers.IO) {
synchronizerProvider.getSynchronizer()
synchronizerProvider
.getSynchronizer()
.redactPcztForSigner(pczt)
}
@ -232,13 +236,12 @@ class ProposalDataSourceImpl(
}
@Suppress("TooGenericExceptionCaught")
private inline fun <T : Any> getOrThrow(block: () -> T): T {
return try {
private inline fun <T : Any> getOrThrow(block: () -> T): T =
try {
block()
} catch (e: Exception) {
throw TransactionProposalNotCreatedException(e)
}
}
private suspend fun AddressType.toWalletAddress(value: String) =
when (this) {

View File

@ -23,8 +23,8 @@ class TransactionHistoryMapper {
data: ListTransactionData,
restoreTimestamp: Instant,
onTransactionClick: (Transaction) -> Unit
): TransactionState {
return TransactionState(
): TransactionState =
TransactionState(
key = data.transaction.id.txIdString(),
icon = getIcon(data),
title = getTitle(data),
@ -34,7 +34,6 @@ class TransactionHistoryMapper {
onClick = { onTransactionClick(data.transaction) },
isUnread = isUnread(data, restoreTimestamp)
)
}
private fun isUnread(
data: ListTransactionData,

View File

@ -6,4 +6,7 @@ import co.electriccoin.lightwallet.client.model.LightWalletEndpoint
* @property servers an ascended sorted list of fastest servers, or null if none loaded
* @property isLoading indicates whether newer data is being loaded
*/
data class FastestServersState(val servers: List<LightWalletEndpoint>?, val isLoading: Boolean)
data class FastestServersState(
val servers: List<LightWalletEndpoint>?,
val isLoading: Boolean
)

View File

@ -3,23 +3,31 @@ package co.electriccoin.zcash.ui.common.model
import cash.z.ecc.android.sdk.model.TransactionSubmitResult
sealed interface SubmitResult {
data class Success(val txIds: List<String>) : SubmitResult
data class Success(
val txIds: List<String>
) : SubmitResult
data class MultipleTrxFailure(val results: List<TransactionSubmitResult>) : SubmitResult
data class MultipleTrxFailure(
val results: List<TransactionSubmitResult>
) : SubmitResult
sealed interface SimpleTrxFailure : SubmitResult {
fun toErrorMessage(): String
fun toErrorStacktrace(): String
data class SimpleTrxFailureGrpc(val result: TransactionSubmitResult.Failure) : SimpleTrxFailure {
data class SimpleTrxFailureGrpc(
val result: TransactionSubmitResult.Failure
) : SimpleTrxFailure {
// Currently, we intentionally do not include any error related details
override fun toErrorMessage() = ""
override fun toErrorStacktrace() = ""
}
data class SimpleTrxFailureSubmit(val result: TransactionSubmitResult.Failure) : SimpleTrxFailure {
data class SimpleTrxFailureSubmit(
val result: TransactionSubmitResult.Failure
) : SimpleTrxFailure {
override fun toErrorMessage() =
buildString {
appendLine("Error code: ${result.code}")
@ -29,7 +37,9 @@ sealed interface SubmitResult {
override fun toErrorStacktrace(): String = toErrorMessage()
}
data class SimpleTrxFailureOther(val error: Throwable) : SimpleTrxFailure {
data class SimpleTrxFailureOther(
val error: Throwable
) : SimpleTrxFailure {
override fun toErrorMessage() = error.message ?: "Unknown error"
override fun toErrorStacktrace(): String = error.stackTraceToString()

View File

@ -1,4 +1,6 @@
package co.electriccoin.zcash.ui.common.model
@JvmInline
value class ValidContactName(val value: String)
value class ValidContactName(
val value: String
)

View File

@ -49,17 +49,18 @@ data class VersionInfo(
)
}
private fun resolveBestReleaseNotes(): String {
return if (Locale.getDefault().language.contains("es", ignoreCase = true)) {
private fun resolveBestReleaseNotes(): String =
if (Locale.getDefault().language.contains("es", ignoreCase = true)) {
releaseNotesEs
} else {
releaseNotesEn
}
}
}
}
enum class DistributionDimension(val value: String) {
enum class DistributionDimension(
val value: String
) {
STORE("store"),
FOSS("foss")
}

View File

@ -22,9 +22,7 @@ class AddressBookKeyStorageProviderImpl(
) : AddressBookKeyStorageProvider {
private val default = AddressBookKeyPreferenceDefault()
override suspend fun getAddressBookKey(): AddressBookKey? {
return default.getValue(encryptedPreferenceProvider())
}
override suspend fun getAddressBookKey(): AddressBookKey? = default.getValue(encryptedPreferenceProvider())
override suspend fun storeAddressBookKey(addressBookKey: AddressBookKey) {
default.putValue(encryptedPreferenceProvider(), addressBookKey)

View File

@ -43,18 +43,16 @@ class AddressBookProviderImpl(
override fun readAddressBookFromFile(
file: File,
addressBookKey: AddressBookKey
): AddressBook {
return file.inputStream().use { stream ->
): AddressBook =
file.inputStream().use { stream ->
addressBookEncryptor.decrypt(
key = addressBookKey,
inputStream = stream
)
}
}
override fun readLegacyUnencryptedAddressBookFromFile(file: File): AddressBook {
return file.inputStream().use { stream ->
override fun readLegacyUnencryptedAddressBookFromFile(file: File): AddressBook =
file.inputStream().use { stream ->
addressBookSerializer.deserializeAddressBook(stream)
}
}
}

View File

@ -20,15 +20,13 @@ interface AddressBookStorageProvider {
class AddressBookStorageProviderImpl(
private val context: Context
) : AddressBookStorageProvider {
override fun getStorageFile(addressBookKey: AddressBookKey): File? {
return File(getOrCreateAddressBookDir(), addressBookKey.fileIdentifier())
override fun getStorageFile(addressBookKey: AddressBookKey): File? =
File(getOrCreateAddressBookDir(), addressBookKey.fileIdentifier())
.takeIf { it.exists() && it.isFile }
}
override fun getLegacyUnencryptedStorageFile(): File? {
return File(context.noBackupFilesDir, LEGACY_UNENCRYPTED_ADDRESS_BOOK_FILE_NAME)
override fun getLegacyUnencryptedStorageFile(): File? =
File(context.noBackupFilesDir, LEGACY_UNENCRYPTED_ADDRESS_BOOK_FILE_NAME)
.takeIf { it.exists() && it.isFile }
}
override fun getOrCreateStorageFile(addressBookKey: AddressBookKey): File {
val file = File(getOrCreateAddressBookDir(), addressBookKey.fileIdentifier())

View File

@ -20,9 +20,7 @@ class ApplicationStateProviderImpl : ApplicationStateProvider {
override val state = _state.asStateFlow()
override suspend fun getApplicationState(): Lifecycle.Event? {
return _state.last()
}
override suspend fun getApplicationState(): Lifecycle.Event? = _state.last()
override fun setApplicationState(newState: Lifecycle.Event) {
_state.update { newState }

View File

@ -8,7 +8,9 @@ import co.electriccoin.lightwallet.client.model.LightWalletEndpoint
// TODO [#1273]: Add ChooseServer Tests #1273
// TODO [#1273]: https://github.com/Electric-Coin-Company/zashi-android/issues/1273
class GetDefaultServersProvider(private val application: Application) {
class GetDefaultServersProvider(
private val application: Application
) {
private val lightWalletEndpoints by lazy {
if (ZcashNetwork.fromResources(application) == ZcashNetwork.Mainnet) {
listOf(

View File

@ -3,6 +3,8 @@ package co.electriccoin.zcash.ui.common.provider
import android.app.Application
import co.electriccoin.zcash.ui.common.model.VersionInfo
class GetVersionInfoProvider(private val application: Application) {
class GetVersionInfoProvider(
private val application: Application
) {
operator fun invoke() = VersionInfo.new(application)
}

View File

@ -3,7 +3,9 @@ package co.electriccoin.zcash.ui.common.provider
import android.app.Application
import cash.z.ecc.sdk.type.ZcashCurrency
class GetZcashCurrencyProvider(private val application: Application) {
class GetZcashCurrencyProvider(
private val application: Application
) {
operator fun invoke() = ZcashCurrency.fromResources(application)
fun getLocalizedName() = ZcashCurrency.getLocalizedName(application)

View File

@ -25,12 +25,11 @@ class MetadataKeyStorageProviderImpl(
) : MetadataKeyStorageProvider {
private val default = MetadataKeyPreferenceDefault()
override suspend fun get(account: WalletAccount): MetadataKey? {
return default.getValue(
override suspend fun get(account: WalletAccount): MetadataKey? =
default.getValue(
walletAccount = account,
preferenceProvider = encryptedPreferenceProvider(),
)
}
override suspend fun store(
key: MetadataKey,
@ -51,11 +50,11 @@ private class MetadataKeyPreferenceDefault {
suspend fun getValue(
walletAccount: WalletAccount,
preferenceProvider: PreferenceProvider,
): MetadataKey? {
return preferenceProvider.getStringSet(
): MetadataKey? =
preferenceProvider
.getStringSet(
key = getKey(walletAccount)
)?.decode()
}
suspend fun putValue(
newValue: MetadataKey?,
@ -73,20 +72,19 @@ private class MetadataKeyPreferenceDefault {
PreferenceKey("metadata_key_${walletAccount.sdkAccount.accountUuid.value.toHexString()}")
@OptIn(ExperimentalEncodingApi::class)
private fun MetadataKey?.encode(): Set<String>? {
return this
private fun MetadataKey?.encode(): Set<String>? =
this
?.bytes
?.map {
Base64.encode(it.toByteArray(secretKeyAccess))
}
?.toSet()
}
}?.toSet()
@OptIn(ExperimentalEncodingApi::class)
private fun Set<String>?.decode() =
if (this != null) {
MetadataKey(
this.toList()
this
.toList()
.map {
SecretBytes.copyFrom(Base64.decode(it), secretKeyAccess)
}

Some files were not shown because too many files have changed in this diff Show More