taler-android

Android apps for GNU Taler (wallet, PoS, cashier)
Log | Files | Refs | README | LICENSE

commit 662fe62a9ce5204eb86620932e5f97b8c53e8344
parent e7b3fbad2849f63bc2c993890ef92a79478c42fd
Author: Iván Ávalos <avalos@disroot.org>
Date:   Wed, 17 Jul 2024 11:43:05 -0600

Bump library versions and fix some warnings

Diffstat:
Mbuild.gradle | 12++++++------
Mcashier/build.gradle | 2+-
Mmerchant-lib/build.gradle | 8+++++---
Mmerchant-terminal/build.gradle | 8++++----
Mtaler-kotlin-android/build.gradle | 4++--
Mtaler-kotlin-android/src/main/java/net/taler/common/Amount.kt | 40+++++++++++++++++++++-------------------
Mwallet/build.gradle | 19+++++++++++--------
Mwallet/src/main/java/net/taler/wallet/MainActivity.kt | 3+--
Mwallet/src/main/java/net/taler/wallet/deposit/PayToUriFragment.kt | 3++-
Mwallet/src/main/java/net/taler/wallet/peer/OutgoingPullComposable.kt | 3++-
Mwallet/src/main/java/net/taler/wallet/transactions/TransactionLinkComposable.kt | 3+--
Mwallet/src/main/java/net/taler/wallet/withdraw/manual/ManualWithdrawSuccessFragment.kt | 2+-
Mwallet/src/main/res/values/strings.xml | 18+++++++++---------
13 files changed, 66 insertions(+), 59 deletions(-)

diff --git a/build.gradle b/build.gradle @@ -1,10 +1,10 @@ buildscript { ext { - kotlin_version = '1.9.21' // observe compatibility with compose compiler - ktor_version = '2.3.5' - nav_version = '2.7.6' - material_version = '1.11.0' - lifecycle_version = '2.6.2' + kotlin_version = '1.9.24' // observe compatibility with compose compiler + ktor_version = '2.3.11' + nav_version = '2.7.7' + material_version = '1.12.0' + lifecycle_version = '2.8.3' constraintlayout_version = '2.1.4' junit_version = "4.13.2" // should debug build types be minified with D8 as well? good for catching issues early @@ -15,7 +15,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.2.0' + classpath 'com.android.tools.build:gradle:8.2.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version" classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version" diff --git a/cashier/build.gradle b/cashier/build.gradle @@ -28,7 +28,7 @@ android { defaultConfig { applicationId "net.taler.cashier" minSdkVersion 23 - targetSdkVersion 33 + targetSdkVersion 34 versionCode 3 versionName "0.3" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/merchant-lib/build.gradle b/merchant-lib/build.gradle @@ -14,6 +14,8 @@ * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + plugins { id 'com.android.library' id 'kotlin-android' @@ -65,8 +67,8 @@ dependencies { testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3' } -tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { - kotlinOptions { - freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn" +tasks.withType(KotlinCompile).configureEach { + compilerOptions { + freeCompilerArgs.add("-opt-in=kotlin.RequiresOptIn") } } diff --git a/merchant-terminal/build.gradle b/merchant-terminal/build.gradle @@ -12,7 +12,7 @@ android { defaultConfig { applicationId "net.taler.merchantpos" minSdkVersion 21 - targetSdkVersion 33 + targetSdkVersion 34 versionCode 7 versionName "0.2.5" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -58,7 +58,7 @@ android { lint { abortOnError true - ignore 'WrongConstant' + disable 'WrongConstant' ignoreWarnings false } } @@ -69,7 +69,7 @@ dependencies { implementation "com.google.android.material:material:$material_version" implementation "androidx.constraintlayout:constraintlayout:$constraintlayout_version" - implementation "androidx.recyclerview:recyclerview:1.3.1" + implementation "androidx.recyclerview:recyclerview:1.3.2" implementation "androidx.recyclerview:recyclerview-selection:1.1.0" // Navigation @@ -78,6 +78,6 @@ dependencies { implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0" - testImplementation 'androidx.test.ext:junit:1.1.5' + testImplementation 'androidx.test.ext:junit:1.2.1' testImplementation 'org.robolectric:robolectric:4.10.3' } diff --git a/taler-kotlin-android/build.gradle b/taler-kotlin-android/build.gradle @@ -59,8 +59,8 @@ android { } dependencies { - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'androidx.core:core-ktx:1.12.0' + implementation 'androidx.appcompat:appcompat:1.7.0' + implementation 'androidx.core:core-ktx:1.13.1' implementation "androidx.constraintlayout:constraintlayout:$constraintlayout_version" // Navigation diff --git a/taler-kotlin-android/src/main/java/net/taler/common/Amount.kt b/taler-kotlin-android/src/main/java/net/taler/common/Amount.kt @@ -17,6 +17,7 @@ package net.taler.common import android.os.Build +import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.KSerializer import kotlinx.serialization.Serializable import kotlinx.serialization.Serializer @@ -29,14 +30,14 @@ import kotlin.math.floor import kotlin.math.pow import kotlin.math.roundToInt -public class AmountParserException(msg: String? = null, cause: Throwable? = null) : +class AmountParserException(msg: String? = null, cause: Throwable? = null) : Exception(msg, cause) -public class AmountOverflowException(msg: String? = null, cause: Throwable? = null) : +class AmountOverflowException(msg: String? = null, cause: Throwable? = null) : Exception(msg, cause) @Serializable(with = KotlinXAmountSerializer::class) -public data class Amount( +data class Amount( /** * name of the currency using either a three-character ISO 4217 currency code, * or a regional currency identifier starting with a "*" followed by at most 10 characters. @@ -65,26 +66,26 @@ public data class Amount( val spec: CurrencySpecification? = null, ) : Comparable<Amount> { - public companion object { + companion object { private const val FRACTIONAL_BASE: Int = 100000000 // 1e8 private val REGEX_CURRENCY = Regex("""^[-_*A-Za-z0-9]{1,12}$""") - public val MAX_VALUE: Long = 2.0.pow(52).toLong() + val MAX_VALUE: Long = 2.0.pow(52).toLong() private const val MAX_FRACTION_LENGTH = 8 - public const val MAX_FRACTION: Int = 99_999_999 + const val MAX_FRACTION: Int = 99_999_999 - public fun zero(currency: String): Amount { + fun zero(currency: String): Amount { return Amount(checkCurrency(currency), 0, 0) } - public fun fromJSONString(str: String): Amount { + fun fromJSONString(str: String): Amount { val split = str.split(":") if (split.size != 2) throw AmountParserException("Invalid Amount Format") return fromString(split[0], split[1]) } - public fun fromString(currency: String, str: String): Amount { + fun fromString(currency: String, str: String): Amount { // value val valueSplit = str.split(".") val value = checkValue(valueSplit[0].toLongOrNull()) @@ -98,7 +99,7 @@ public data class Amount( return Amount(checkCurrency(currency), value, fraction) } - public fun isValidAmountStr(str: String): Boolean { + fun isValidAmountStr(str: String): Boolean { if (str.count { it == '.' } > 1) return false val split = str.split(".") try { @@ -122,8 +123,8 @@ public data class Amount( ?.roundToInt() } - public fun min(currency: String): Amount = Amount(currency, 0, 1) - public fun max(currency: String): Amount = Amount(currency, MAX_VALUE, MAX_FRACTION) + fun min(currency: String): Amount = Amount(currency, 0, 1) + fun max(currency: String): Amount = Amount(currency, MAX_VALUE, MAX_FRACTION) internal fun checkCurrency(currency: String): String { @@ -146,7 +147,7 @@ public data class Amount( } - public val amountStr: String + val amountStr: String get() = if (fraction == 0) "$value" else { var f = fraction var fractionStr = "" @@ -157,7 +158,7 @@ public data class Amount( "$value.$fractionStr" } - public operator fun plus(other: Amount): Amount { + operator fun plus(other: Amount): Amount { check(currency == other.currency) { "Can only subtract from same currency" } val resultValue = value + other.value + floor((fraction + other.fraction).toDouble() / FRACTIONAL_BASE).toLong() @@ -167,7 +168,7 @@ public data class Amount( return Amount(currency, resultValue, resultFraction) } - public operator fun times(factor: Int): Amount { + operator fun times(factor: Int): Amount { // TODO consider replacing with a faster implementation if (factor == 0) return zero(currency) var result = this @@ -175,13 +176,13 @@ public data class Amount( return result } - public fun withCurrency(currency: String): Amount { + fun withCurrency(currency: String): Amount { return Amount(checkCurrency(currency), this.value, this.fraction) } fun withSpec(spec: CurrencySpecification?) = copy(spec = spec) - public operator fun minus(other: Amount): Amount { + operator fun minus(other: Amount): Amount { check(currency == other.currency) { "Can only subtract from same currency" } var resultValue = value var resultFraction = fraction @@ -199,11 +200,11 @@ public data class Amount( return Amount(currency, resultValue, resultFraction) } - public fun isZero(): Boolean { + fun isZero(): Boolean { return value == 0L && fraction == 0 } - public fun toJSONString(): String { + fun toJSONString(): String { return "$currency:$amountStr" } @@ -268,6 +269,7 @@ public data class Amount( } +@OptIn(ExperimentalSerializationApi::class) @Suppress("EXPERIMENTAL_API_USAGE") @Serializer(forClass = Amount::class) internal object KotlinXAmountSerializer : KSerializer<Amount> { diff --git a/wallet/build.gradle b/wallet/build.gradle @@ -13,6 +13,9 @@ * You should have received a copy of the GNU General Public License along with * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ + +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + plugins { id "com.android.application" id "kotlin-android" @@ -40,7 +43,7 @@ android { defaultConfig { applicationId "net.taler.wallet" minSdkVersion 24 - targetSdkVersion 33 + targetSdkVersion 34 versionCode 42 versionName "0.11.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -87,7 +90,7 @@ android { } composeOptions { - kotlinCompilerExtensionVersion "1.5.7" + kotlinCompilerExtensionVersion "1.5.14" } buildFeatures { @@ -129,16 +132,16 @@ dependencies { implementation 'androidx.preference:preference-ktx:1.2.1' implementation "com.google.android.material:material:$material_version" implementation "androidx.constraintlayout:constraintlayout:$constraintlayout_version" - implementation "androidx.browser:browser:1.7.0" + implementation "androidx.browser:browser:1.8.0" // Compose - implementation platform('androidx.compose:compose-bom:2023.10.01') + implementation platform('androidx.compose:compose-bom:2024.06.00') implementation 'androidx.compose.material3:material3' implementation 'androidx.compose.material:material-icons-extended' implementation "androidx.compose.runtime:runtime-livedata" implementation "androidx.lifecycle:lifecycle-viewmodel-compose" implementation "com.google.accompanist:accompanist-themeadapter-material3:0.28.0" - implementation 'androidx.activity:activity-compose:1.8.2' + implementation 'androidx.activity:activity-compose:1.9.0' implementation 'androidx.compose.ui:ui-tooling-preview' debugImplementation 'androidx.compose.ui:ui-tooling' @@ -174,9 +177,9 @@ dependencies { testImplementation 'org.json:json:20220320' } -tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { - kotlinOptions { - freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn" +tasks.withType(KotlinCompile).configureEach { + compilerOptions { + freeCompilerArgs.add("-opt-in=kotlin.RequiresOptIn") } } diff --git a/wallet/src/main/java/net/taler/wallet/MainActivity.kt b/wallet/src/main/java/net/taler/wallet/MainActivity.kt @@ -27,7 +27,6 @@ import android.util.Log import android.view.Menu import android.view.MenuItem import android.view.View.GONE -import android.view.View.INVISIBLE import android.view.View.VISIBLE import android.widget.TextView import androidx.activity.viewModels @@ -151,7 +150,7 @@ class MainActivity : AppCompatActivity(), OnNavigationItemSelectedListener, else super.onBackPressed() } - override fun onNewIntent(intent: Intent?) { + override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) handleIntents(intent) } diff --git a/wallet/src/main/java/net/taler/wallet/deposit/PayToUriFragment.kt b/wallet/src/main/java/net/taler/wallet/deposit/PayToUriFragment.kt @@ -42,6 +42,7 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable @@ -191,7 +192,7 @@ fun CurrencyDropdown( readOnly: Boolean = false, ) { val initialIndex = currencies.indexOf(initialCurrency).let { if (it < 0) 0 else it } - var selectedIndex by remember { mutableStateOf(initialIndex) } + var selectedIndex by remember { mutableIntStateOf(initialIndex) } var expanded by remember { mutableStateOf(false) } Box( modifier = modifier, diff --git a/wallet/src/main/java/net/taler/wallet/peer/OutgoingPullComposable.kt b/wallet/src/main/java/net/taler/wallet/peer/OutgoingPullComposable.kt @@ -32,6 +32,7 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableLongStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable @@ -170,7 +171,7 @@ fun OutgoingPullIntroComposable( ) var option by rememberSaveable { mutableStateOf(DEFAULT_EXPIRY) } - var hours by rememberSaveable { mutableStateOf(DEFAULT_EXPIRY.hours) } + var hours by rememberSaveable { mutableLongStateOf(DEFAULT_EXPIRY.hours) } ExpirationComposable( modifier = Modifier.padding(top = 8.dp, bottom = 16.dp), option = option, diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionLinkComposable.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionLinkComposable.kt @@ -16,7 +16,6 @@ package net.taler.wallet.transactions -import android.R import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.foundation.text.ClickableText @@ -47,7 +46,7 @@ fun TransactionLinkComposable(label: String, info: String, onClick: () -> Unit) style = MaterialTheme.typography.bodyMedium, ) val context = LocalContext.current - val linkColor = Color(context.getAttrColor(R.attr.textColorLink)) + val linkColor = Color(context.getAttrColor(android.R.attr.textColorLink)) val annotatedString = buildAnnotatedString { pushStringAnnotation(tag = "url", annotation = info) withStyle(style = SpanStyle(color = linkColor)) { diff --git a/wallet/src/main/java/net/taler/wallet/withdraw/manual/ManualWithdrawSuccessFragment.kt b/wallet/src/main/java/net/taler/wallet/withdraw/manual/ManualWithdrawSuccessFragment.kt @@ -56,7 +56,7 @@ class ManualWithdrawSuccessFragment : Fragment() { supportActionBar?.subtitle = getString(R.string.withdraw_subtitle) } - findNavController().addOnDestinationChangedListener { controller, destination, args -> + findNavController().addOnDestinationChangedListener { _, destination, _ -> if (destination.id != R.id.nav_exchange_manual_withdrawal_success) { activity.apply { supportActionBar?.subtitle = null diff --git a/wallet/src/main/res/values/strings.xml b/wallet/src/main/res/values/strings.xml @@ -267,19 +267,19 @@ GNU Taler is immune against many types of fraud, such as phishing of credit card </plurals> <string name="exchange_fee_coin_expiration_label">Earliest Coin Expiry:</string> <string name="exchange_fee_coin_fees_label">Coin Fees</string> - <string name="exchange_fee_deposit_fee">Deposit Fee: %s</string> + <string name="exchange_fee_deposit_fee">Deposit Fee: %1$s</string> <string name="exchange_fee_overhead_label">Rounding Loss:</string> - <string name="exchange_fee_refresh_fee">Change Fee: %s</string> - <string name="exchange_fee_refund_fee">Refund Fee: %s</string> - <string name="exchange_fee_wire_fee_closing_fee">Closing Fee: %s</string> + <string name="exchange_fee_refresh_fee">Change Fee: %1$s</string> + <string name="exchange_fee_refund_fee">Refund Fee: %1$s</string> + <string name="exchange_fee_wire_fee_closing_fee">Closing Fee: %1$s</string> <string name="exchange_fee_wire_fee_timespan">Timespan: %1$s - %2$s</string> - <string name="exchange_fee_wire_fee_wire_fee">Wire Fee: %s</string> + <string name="exchange_fee_wire_fee_wire_fee">Wire Fee: %1$s</string> <string name="exchange_fee_wire_fees_label">Wire Fees</string> - <string name="exchange_fee_withdraw_fee">Withdraw Fee: %s</string> + <string name="exchange_fee_withdraw_fee">Withdraw Fee: %1$s</string> <string name="exchange_fee_withdrawal_fee_label">Withdrawal Fee:</string> <string name="exchange_list_add">Add provider</string> <string name="exchange_list_add_dev">Add development providers</string> - <string name="exchange_list_currency">Currency: %s</string> + <string name="exchange_list_currency">Currency: %1$s</string> <string name="exchange_list_empty">No providers known\n\nAdd one manually or withdraw digital cash!</string> <string name="exchange_list_error">Could not list providers</string> <string name="exchange_list_select">Select provider</string> @@ -290,7 +290,7 @@ GNU Taler is immune against many types of fraud, such as phishing of credit card <string name="exchange_settings_summary">Manage list of providers known to this wallet</string> <string name="exchange_settings_title">Providers</string> <string name="exchange_tos_accept">Accept Terms of Service</string> - <string name="exchange_tos_error">Error showing Terms of Service: %s</string> + <string name="exchange_tos_error">Error showing Terms of Service: %1$s</string> <!-- Losses --> @@ -352,7 +352,7 @@ GNU Taler is immune against many types of fraud, such as phishing of credit card <!-- Miscellaneous --> <string name="host_apdu_service_desc">Taler NFC Payments</string> - <string name="wifi_connect_error">Could not connect to free Wi-Fi: %s</string> + <string name="wifi_connect_error">Could not connect to free Wi-Fi: %1$s</string> <string name="wifi_disabled_error">Turn on Wi-Fi to get free Wi-Fi</string> </resources>