From a229b33997842a66295aa4d8dfb5dab6d2f769df Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 1 Jun 2022 13:31:38 +0200 Subject: use new annotation for polymorphic serialization --- build.gradle | 2 +- .../main/java/net/taler/cashier/MainViewModel.kt | 10 ++++- .../java/net/taler/cashier/config/ConfigManager.kt | 3 +- merchant-lib/build.gradle | 6 +++ .../main/java/net/taler/merchantlib/MerchantApi.kt | 16 +++++--- .../src/main/java/net/taler/merchantlib/Orders.kt | 8 ++-- .../java/net/taler/merchantlib/MerchantApiTest.kt | 3 +- .../java/net/taler/merchantlib/MockHttpClient.kt | 12 +++++- .../java/net/taler/merchantpos/MainActivity.kt | 4 +- taler-kotlin-android/build.gradle | 8 ---- taler-kotlin-android/src/main/AndroidManifest.xml | 4 +- .../src/main/java/net/taler/common/AndroidUtils.kt | 11 ------ .../java/net/taler/lib/android/Serialization.kt | 21 ---------- wallet/build.gradle | 11 +++++- wallet/src/main/AndroidManifest.xml | 1 + .../net/taler/wallet/backend/WalletBackendApi.kt | 5 --- .../net/taler/wallet/backend/WalletResponse.kt | 6 +-- .../net/taler/wallet/payment/PaymentResponses.kt | 8 ++-- .../net/taler/wallet/settings/SettingsFragment.kt | 46 +++++++++++++++++----- .../taler/wallet/payment/PaymentResponsesTest.kt | 1 - 20 files changed, 103 insertions(+), 83 deletions(-) delete mode 100644 taler-kotlin-android/src/main/java/net/taler/lib/android/Serialization.kt diff --git a/build.gradle b/build.gradle index 20b5c78..3179daa 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.2.0' + classpath 'com.android.tools.build:gradle:7.2.1' 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/src/main/java/net/taler/cashier/MainViewModel.kt b/cashier/src/main/java/net/taler/cashier/MainViewModel.kt index 1c819b9..2196e78 100644 --- a/cashier/src/main/java/net/taler/cashier/MainViewModel.kt +++ b/cashier/src/main/java/net/taler/cashier/MainViewModel.kt @@ -28,6 +28,7 @@ import io.ktor.client.plugins.contentnegotiation.ContentNegotiation import io.ktor.serialization.kotlinx.json.json import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import kotlinx.serialization.json.Json import net.taler.cashier.HttpHelper.makeJsonGetRequest import net.taler.cashier.config.ConfigManager import net.taler.cashier.withdraw.WithdrawManager @@ -45,8 +46,12 @@ class MainViewModel(private val app: Application) : AndroidViewModel(app) { retryOnConnectionFailure(true) } } + expectSuccess = true install(ContentNegotiation) { - json() + json(Json { + encodeDefaults = false + ignoreUnknownKeys = true + }) } } val configManager = ConfigManager(app, viewModelScope, httpClient) @@ -72,7 +77,8 @@ class MainViewModel(private val app: Application) : AndroidViewModel(app) { "debit" -> false else -> throw AmountParserException("Unexpected credit_debit_indicator: $creditDebitIndicator") } - BalanceResult.Success(SignedAmount(positive, Amount.fromJSONString(balanceAmount))) + BalanceResult.Success(SignedAmount(positive, + Amount.fromJSONString(balanceAmount))) } catch (e: Exception) { Log.e(TAG, "Error parsing balance", e) BalanceResult.Error("Invalid amount:\n${response.json.toString(2)}") diff --git a/cashier/src/main/java/net/taler/cashier/config/ConfigManager.kt b/cashier/src/main/java/net/taler/cashier/config/ConfigManager.kt index 882348f..2fde37d 100644 --- a/cashier/src/main/java/net/taler/cashier/config/ConfigManager.kt +++ b/cashier/src/main/java/net/taler/cashier/config/ConfigManager.kt @@ -29,6 +29,7 @@ import androidx.security.crypto.EncryptedSharedPreferences.PrefValueEncryptionSc import androidx.security.crypto.MasterKeys import androidx.security.crypto.MasterKeys.AES256_GCM_SPEC import io.ktor.client.HttpClient +import io.ktor.client.call.body import io.ktor.client.request.get import io.ktor.client.request.header import io.ktor.http.HttpHeaders.Authorization @@ -116,7 +117,7 @@ class ConfigManager( val url = "${config.bankUrl}/config" Log.d(TAG, "Checking config: $url") val configResponse = response { - httpClient.get(url) as ConfigResponse + httpClient.get(url).body() } if (configResponse.isFailure) { configResponse diff --git a/merchant-lib/build.gradle b/merchant-lib/build.gradle index c31009d..42dc3ec 100644 --- a/merchant-lib/build.gradle +++ b/merchant-lib/build.gradle @@ -65,3 +65,9 @@ dependencies { testImplementation "io.ktor:ktor-client-mock-jvm:$ktor_version" testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.1' } + +tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { + kotlinOptions { + freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn" + } +} \ No newline at end of file diff --git a/merchant-lib/src/main/java/net/taler/merchantlib/MerchantApi.kt b/merchant-lib/src/main/java/net/taler/merchantlib/MerchantApi.kt index d973813..c02907b 100644 --- a/merchant-lib/src/main/java/net/taler/merchantlib/MerchantApi.kt +++ b/merchant-lib/src/main/java/net/taler/merchantlib/MerchantApi.kt @@ -33,6 +33,8 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import net.taler.merchantlib.Response.Companion.response import io.ktor.serialization.kotlinx.json.* +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.json.Json class MerchantApi( private val httpClient: HttpClient = getDefaultHttpClient(), @@ -41,7 +43,7 @@ class MerchantApi( suspend fun getConfig(baseUrl: String): Response = withContext(ioDispatcher) { response { - httpClient.get("$baseUrl/config") as ConfigResponse + httpClient.get("$baseUrl/config").body() } } @@ -76,7 +78,7 @@ class MerchantApi( response { httpClient.delete(merchantConfig.urlFor("private/orders/$orderId")) { header(Authorization, "ApiKey ${merchantConfig.apiKey}") - } as Unit + }.body() } } @@ -85,7 +87,7 @@ class MerchantApi( response { httpClient.get(merchantConfig.urlFor("private/orders")) { header(Authorization, "ApiKey ${merchantConfig.apiKey}") - } as OrderHistory + }.body() } } @@ -99,18 +101,22 @@ class MerchantApi( header(Authorization, "ApiKey ${merchantConfig.apiKey}") contentType(Json) setBody(request) - } as RefundResponse + }.body() } } } fun getDefaultHttpClient(): HttpClient = HttpClient(OkHttp) { + expectSuccess = true engine { config { retryOnConnectionFailure(true) } } install(ContentNegotiation) { - json() + json(Json { + encodeDefaults = false + ignoreUnknownKeys = true + }) } } diff --git a/merchant-lib/src/main/java/net/taler/merchantlib/Orders.kt b/merchant-lib/src/main/java/net/taler/merchantlib/Orders.kt index 9572e07..391abf5 100644 --- a/merchant-lib/src/main/java/net/taler/merchantlib/Orders.kt +++ b/merchant-lib/src/main/java/net/taler/merchantlib/Orders.kt @@ -16,11 +16,12 @@ package net.taler.merchantlib +import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonClassDiscriminator import net.taler.common.ContractTerms import net.taler.common.Duration -import net.taler.lib.android.CustomClassDiscriminator @Serializable data class PostOrderRequest( @@ -36,9 +37,10 @@ data class PostOrderResponse( val orderId: String ) +@OptIn(ExperimentalSerializationApi::class) @Serializable -sealed class CheckPaymentResponse: CustomClassDiscriminator { - override val discriminator: String = "order_status" +@JsonClassDiscriminator("order_status") +sealed class CheckPaymentResponse { abstract val paid: Boolean @Serializable diff --git a/merchant-lib/src/test/java/net/taler/merchantlib/MerchantApiTest.kt b/merchant-lib/src/test/java/net/taler/merchantlib/MerchantApiTest.kt index 8a45c9f..a89e2d3 100644 --- a/merchant-lib/src/test/java/net/taler/merchantlib/MerchantApiTest.kt +++ b/merchant-lib/src/test/java/net/taler/merchantlib/MerchantApiTest.kt @@ -20,6 +20,7 @@ import io.ktor.http.HttpStatusCode.Companion.NotFound import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.TestCoroutineDispatcher +import kotlinx.coroutines.test.UnconfinedTestDispatcher import net.taler.common.Amount import net.taler.common.ContractProduct import net.taler.common.ContractTerms @@ -33,7 +34,7 @@ import org.junit.Test @ExperimentalCoroutinesApi class MerchantApiTest { - private val api = MerchantApi(httpClient, TestCoroutineDispatcher()) + private val api = MerchantApi(httpClient, UnconfinedTestDispatcher()) private val merchantConfig = MerchantConfig( baseUrl = "http://example.net/instances/testInstance", apiKey = "apiKeyFooBar" diff --git a/merchant-lib/src/test/java/net/taler/merchantlib/MockHttpClient.kt b/merchant-lib/src/test/java/net/taler/merchantlib/MockHttpClient.kt index 880228c..32c7ee1 100644 --- a/merchant-lib/src/test/java/net/taler/merchantlib/MockHttpClient.kt +++ b/merchant-lib/src/test/java/net/taler/merchantlib/MockHttpClient.kt @@ -20,6 +20,7 @@ import io.ktor.client.HttpClient import io.ktor.client.engine.mock.MockEngine import io.ktor.client.engine.mock.MockEngineConfig import io.ktor.client.engine.mock.respond +import io.ktor.client.plugins.contentnegotiation.ContentNegotiation import io.ktor.http.ContentType.Application.Json import io.ktor.http.HttpStatusCode import io.ktor.http.Url @@ -27,6 +28,8 @@ import io.ktor.http.content.TextContent import io.ktor.http.fullPath import io.ktor.http.headersOf import io.ktor.http.hostWithPort +import io.ktor.serialization.kotlinx.json.json +import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json.Default.parseToJsonElement import org.junit.Assert.assertEquals @@ -36,13 +39,20 @@ object MockHttpClient { engine { addHandler { error("No response handler set") } } + expectSuccess = true + install(ContentNegotiation) { + json(Json { + encodeDefaults = false + ignoreUnknownKeys = true + }) + } } fun HttpClient.giveJsonResponse( url: String, expectedBody: String? = null, statusCode: HttpStatusCode = HttpStatusCode.OK, - jsonProducer: () -> String + jsonProducer: () -> String, ) { val httpConfig = engineConfig as MockEngineConfig httpConfig.requestHandlers.removeAt(0) diff --git a/merchant-terminal/src/main/java/net/taler/merchantpos/MainActivity.kt b/merchant-terminal/src/main/java/net/taler/merchantpos/MainActivity.kt index 47da74e..29f5da4 100644 --- a/merchant-terminal/src/main/java/net/taler/merchantpos/MainActivity.kt +++ b/merchant-terminal/src/main/java/net/taler/merchantpos/MainActivity.kt @@ -55,11 +55,11 @@ class MainActivity : AppCompatActivity(), OnNavigationItemSelectedListener { ui = ActivityMainBinding.inflate(layoutInflater) setContentView(ui.root) - model.paymentManager.payment.observe(this, { payment -> + model.paymentManager.payment.observe(this) { payment -> payment?.talerPayUri?.let { nfcManager.setTagString(it) } - }) + } val navHostFragment = supportFragmentManager.findFragmentById(R.id.navHostFragment) as NavHostFragment diff --git a/taler-kotlin-android/build.gradle b/taler-kotlin-android/build.gradle index b4590c4..5fdb545 100644 --- a/taler-kotlin-android/build.gradle +++ b/taler-kotlin-android/build.gradle @@ -22,7 +22,6 @@ plugins { android { compileSdkVersion 32 - //noinspection GradleDependency buildToolsVersion "$build_tools_version" defaultConfig { @@ -72,13 +71,6 @@ dependencies { // QR codes implementation 'com.google.zxing:core:3.5.0' // needs minSdkVersion 24+ or desugar - // Logcat viewer - implementation('com.github.pedrovgs:lynx:1.6') { - exclude group: 'com.android.support' - exclude group: 'com.squareup' - } - implementation 'com.github.pedrovgs:renderers:4.1.0' - // JSON parsing and serialization api 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.3' diff --git a/taler-kotlin-android/src/main/AndroidManifest.xml b/taler-kotlin-android/src/main/AndroidManifest.xml index f475748..5533913 100644 --- a/taler-kotlin-android/src/main/AndroidManifest.xml +++ b/taler-kotlin-android/src/main/AndroidManifest.xml @@ -15,9 +15,7 @@ --> + package="net.taler.common"> - - diff --git a/taler-kotlin-android/src/main/java/net/taler/common/AndroidUtils.kt b/taler-kotlin-android/src/main/java/net/taler/common/AndroidUtils.kt index d86e744..5b57320 100644 --- a/taler-kotlin-android/src/main/java/net/taler/common/AndroidUtils.kt +++ b/taler-kotlin-android/src/main/java/net/taler/common/AndroidUtils.kt @@ -46,8 +46,6 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity import androidx.navigation.NavDirections import androidx.navigation.fragment.findNavController -import com.github.pedrovgs.lynx.LynxActivity -import com.github.pedrovgs.lynx.LynxConfig import net.taler.lib.android.ErrorBottomSheet fun View.fadeIn(endAction: () -> Unit = {}) { @@ -95,15 +93,6 @@ fun Context.isOnline(): Boolean { } } -fun Context.showLogViewer(logFilter: String? = null) { - val lynxActivityIntent = LynxActivity.getIntent(this, LynxConfig().apply { - maxNumberOfTracesToShow = 1500 // higher numbers seem to break share functionality - samplingRate = Int.MAX_VALUE // no updates please - logFilter?.let { filter = it } - }) - startActivity(lynxActivityIntent) -} - fun FragmentActivity.showError(mainText: String, detailText: String = "") = ErrorBottomSheet .newInstance(mainText, detailText) .show(supportFragmentManager, "ERROR_BOTTOM_SHEET") diff --git a/taler-kotlin-android/src/main/java/net/taler/lib/android/Serialization.kt b/taler-kotlin-android/src/main/java/net/taler/lib/android/Serialization.kt deleted file mode 100644 index 7eb4480..0000000 --- a/taler-kotlin-android/src/main/java/net/taler/lib/android/Serialization.kt +++ /dev/null @@ -1,21 +0,0 @@ -/* - * This file is part of GNU Taler - * (C) 2020 Taler Systems S.A. - * - * GNU Taler is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 3, or (at your option) any later version. - * - * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with - * GNU Taler; see the file COPYING. If not, see - */ - -package net.taler.lib.android - -interface CustomClassDiscriminator { - val discriminator: String -} diff --git a/wallet/build.gradle b/wallet/build.gradle index b0a8b97..faebdde 100644 --- a/wallet/build.gradle +++ b/wallet/build.gradle @@ -23,8 +23,8 @@ plugins { id "de.undercouch.download" } -def walletCoreVersion = "v0.9.0-dev.10" -def walletCoreSha256 = "3c9aa9afeb6d61091599553719ffd1010be7817b7368c2d0ace5f77d8089d513" +def walletCoreVersion = "v0.9.0-dev.11" +def walletCoreSha256 = "0ee5eae7d0afd6f251f7d33975758055d06926ccb67ae9099d589a79d34be39d" static def versionCodeEpoch() { return (new Date().getTime() / 1000).toInteger() @@ -188,7 +188,14 @@ task verifyWalletLibrary(type: Verify, dependsOn: downloadWalletLibrary) { algorithm 'SHA-256' checksum walletCoreSha256 } + tasks.withType(MergeResources) { inputs.dir walletLibraryDir dependsOn verifyWalletLibrary } + +tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { + kotlinOptions { + freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn" + } +} \ No newline at end of file diff --git a/wallet/src/main/AndroidManifest.xml b/wallet/src/main/AndroidManifest.xml index b0e4ffe..61191b6 100644 --- a/wallet/src/main/AndroidManifest.xml +++ b/wallet/src/main/AndroidManifest.xml @@ -20,6 +20,7 @@ + val json = Json { ignoreUnknownKeys = true - (T::class.companionObjectInstance as? CustomClassDiscriminator)?.let { - classDiscriminator = it.discriminator - } } sendRequest(operation, args?.invoke(JSONObject())) { isError, message -> val response = try { diff --git a/wallet/src/main/java/net/taler/wallet/backend/WalletResponse.kt b/wallet/src/main/java/net/taler/wallet/backend/WalletResponse.kt index 1071e9a..e52fd4f 100644 --- a/wallet/src/main/java/net/taler/wallet/backend/WalletResponse.kt +++ b/wallet/src/main/java/net/taler/wallet/backend/WalletResponse.kt @@ -32,13 +32,13 @@ sealed class WalletResponse { @Serializable @SerialName("response") data class Success( - val result: T + val result: T, ) : WalletResponse() @Serializable @SerialName("error") data class Error( - val error: TalerErrorInfo + val error: TalerErrorInfo, ) : WalletResponse() fun onSuccess(block: (result: T) -> Unit): WalletResponse { @@ -67,7 +67,7 @@ data class TalerErrorInfo( // Error details @Serializable(JSONObjectDeserializer::class) - val details: JSONObject? = null + val details: JSONObject? = null, ) { val userFacingMsg: String get() { diff --git a/wallet/src/main/java/net/taler/wallet/payment/PaymentResponses.kt b/wallet/src/main/java/net/taler/wallet/payment/PaymentResponses.kt index fb206be..7e03472 100644 --- a/wallet/src/main/java/net/taler/wallet/payment/PaymentResponses.kt +++ b/wallet/src/main/java/net/taler/wallet/payment/PaymentResponses.kt @@ -16,18 +16,18 @@ package net.taler.wallet.payment +import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonClassDiscriminator import net.taler.common.Amount import net.taler.common.ContractTerms -import net.taler.lib.android.CustomClassDiscriminator import net.taler.wallet.backend.TalerErrorInfo +@OptIn(ExperimentalSerializationApi::class) @Serializable +@JsonClassDiscriminator("status") sealed class PreparePayResponse { - companion object : CustomClassDiscriminator { - override val discriminator: String = "status" - } @Serializable @SerialName("payment-possible") diff --git a/wallet/src/main/java/net/taler/wallet/settings/SettingsFragment.kt b/wallet/src/main/java/net/taler/wallet/settings/SettingsFragment.kt index bd6ce1a..1a17d78 100644 --- a/wallet/src/main/java/net/taler/wallet/settings/SettingsFragment.kt +++ b/wallet/src/main/java/net/taler/wallet/settings/SettingsFragment.kt @@ -18,6 +18,8 @@ package net.taler.wallet.settings import android.os.Bundle import android.view.View +import android.widget.Toast +import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AlertDialog import androidx.fragment.app.activityViewModels import androidx.preference.Preference @@ -26,7 +28,6 @@ import androidx.preference.SwitchPreferenceCompat import com.google.android.material.snackbar.BaseTransientBottomBar.LENGTH_SHORT import com.google.android.material.snackbar.Snackbar import net.taler.common.showError -import net.taler.common.showLogViewer import net.taler.common.toRelativeTime import net.taler.wallet.BuildConfig.FLAVOR import net.taler.wallet.BuildConfig.VERSION_CODE @@ -64,6 +65,11 @@ class SettingsFragment : PreferenceFragmentCompat() { ) } + val createDocumentActivity = + registerForActivityResult(ActivityResultContracts.CreateDocument()) { uri -> + + } + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.settings_main, rootKey) prefBackup = findPreference("pref_backup")!! @@ -80,12 +86,12 @@ class SettingsFragment : PreferenceFragmentCompat() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - model.lastBackup.observe(viewLifecycleOwner, { + model.lastBackup.observe(viewLifecycleOwner) { val time = it.toRelativeTime(requireContext()) prefBackup.summary = getString(R.string.backup_last, time) - }) + } - model.devMode.observe(viewLifecycleOwner, { enabled -> + model.devMode.observe(viewLifecycleOwner) { enabled -> prefDevMode.isChecked = enabled if (enabled) { prefVersionApp.summary = "$VERSION_NAME ($FLAVOR $VERSION_CODE)" @@ -94,13 +100,13 @@ class SettingsFragment : PreferenceFragmentCompat() { model.merchantVersion?.let { prefVersionMerchant.summary = it } } devPrefs.forEach { it.isVisible = enabled } - }) + } prefDevMode.setOnPreferenceChangeListener { _, newValue -> model.devMode.value = newValue as Boolean true } - withdrawManager.testWithdrawalStatus.observe(viewLifecycleOwner, { status -> + withdrawManager.testWithdrawalStatus.observe(viewLifecycleOwner) { status -> if (status == null) return@observe val loading = status is WithdrawTestStatus.Withdrawing prefWithdrawTest.isEnabled = !loading @@ -109,14 +115,37 @@ class SettingsFragment : PreferenceFragmentCompat() { requireActivity().showError(R.string.withdraw_error_test, status.message) } withdrawManager.testWithdrawalStatus.value = null - }) + } prefWithdrawTest.setOnPreferenceClickListener { withdrawManager.withdrawTestkudos() true } prefLogcat.setOnPreferenceClickListener { - requireContext().showLogViewer("taler-wallet") + val toast = + Toast.makeText(requireActivity(), "Log export currently unavailable", Toast.LENGTH_LONG) + toast.show() + +// val myPid = android.os.Process.myPid() +// val proc = Runtime.getRuntime() +// .exec(arrayOf("logcat", "-d", "--pid=$myPid", "*:V")) +// val bytes = proc.inputStream.readBytes() +// val f = File(requireActivity().getExternalFilesDir(null), +// "taler-wallet-log-${System.currentTimeMillis()}.txt") +// f.writeBytes(bytes) +// val toast = Toast.makeText(requireActivity(), "Saved to ${f.absolutePath}", Toast.LENGTH_LONG) +// toast.show() +// val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply { +// addCategory(Intent.CATEGORY_OPENABLE) +// type = "application/pdf" +// putExtra(Intent.EXTRA_TITLE, "invoice.pdf") +// +// // Optionally, specify a URI for the directory that should be opened in +// // the system file picker before your app creates the document. +// putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri) +// } +// startActivityForResult(intent, CREATE_FILE) +// ActivityResultContracts.CreateDocument true } @@ -138,5 +167,4 @@ class SettingsFragment : PreferenceFragmentCompat() { } .show() } - } diff --git a/wallet/src/test/java/net/taler/wallet/payment/PaymentResponsesTest.kt b/wallet/src/test/java/net/taler/wallet/payment/PaymentResponsesTest.kt index fbdc07d..da2378e 100644 --- a/wallet/src/test/java/net/taler/wallet/payment/PaymentResponsesTest.kt +++ b/wallet/src/test/java/net/taler/wallet/payment/PaymentResponsesTest.kt @@ -23,7 +23,6 @@ class PaymentResponsesTest { private val json = Json { ignoreUnknownKeys = true - classDiscriminator = PreparePayResponse.discriminator } @Test -- cgit v1.2.3