diff --git a/build.gradle b/build.gradle
index 1c9b0a2f..ed0dacea 100644
--- a/build.gradle
+++ b/build.gradle
@@ -11,7 +11,7 @@ ext {
kotlinCoroutinesVersion = "1.3.7"
- ktorVersion = "1.3.2"
+ ktorVersion = "1.4.2"
javaUtilsVersion = '1.0.16'
diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/SendMessageLogDialog.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/SendMessageLogDialog.kt
index dc92650d..a74a8e5c 100644
--- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/SendMessageLogDialog.kt
+++ b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/SendMessageLogDialog.kt
@@ -2,6 +2,7 @@ package net.dankito.banking.ui.android.dialogs
import android.content.ActivityNotFoundException
import android.content.Intent
+import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@@ -15,6 +16,15 @@ import net.dankito.banking.ui.android.di.BankingComponent
import net.dankito.banking.ui.presenter.BankingPresenter
import net.dankito.utils.android.extensions.hide
import net.dankito.utils.android.extensions.show
+import net.dankito.utils.multiplatform.getInnerExceptionMessage
+import net.dankito.utils.multiplatform.os.DeviceInfo
+import net.dankito.banking.ui.model.issues.CreateTicketRequestDto
+import net.dankito.banking.ui.model.issues.IssueDescriptionFormat
+import net.dankito.utils.android.extensions.asActivity
+import net.dankito.utils.serialization.JacksonJsonSerializer
+import net.dankito.utils.web.client.OkHttpWebClient
+import net.dankito.utils.web.client.RequestParameters
+import net.dankito.utils.web.client.WebClientResponse
import javax.inject.Inject
@@ -63,12 +73,15 @@ open class SendMessageLogDialog : DialogFragment() {
rootView.edtxtMessageLog.setText(context?.getString(R.string.dialog_send_message_courteously_add_error_description, messageLog))
}
- rootView.btnSendMessageLog.setOnClickListener { sendMessageLog(rootView.edtxtMessageLog.text.toString()) }
+ rootView.btnSendMessageLogDirectly.setOnClickListener { sendMessageLogDirectly(rootView.edtxtMessageLog.text.toString()) }
+ rootView.btnSendMessageLogViaEMail.setOnClickListener { sendMessageLogViaEMail(rootView.edtxtMessageLog.text.toString()) }
rootView.btnCancel.setOnClickListener { dismiss() }
}
- protected open fun sendMessageLog(messageLog: String) {
+ protected open fun sendMessageLogViaEMail(messageLog: String) {
+ // TODO: check if message log exceeds 120.000 characters
+
val sendMailActivity = Intent(Intent.ACTION_SEND)
sendMailActivity.type = "message/rfc822"
sendMailActivity.putExtra(Intent.EXTRA_EMAIL, arrayOf("panta.rhei@dankito.net"))
@@ -78,12 +91,43 @@ open class SendMessageLogDialog : DialogFragment() {
try {
startActivity(Intent.createChooser(sendMailActivity, context?.getString(R.string.dialog_send_message_log_action_send_chooser_title)))
- Toast.makeText(context, context?.getString(R.string.dialog_send_message_log_thanks_for_helping_making_app_better), Toast.LENGTH_LONG).show()
-
- dismiss()
+ showSuccessfullySentMessageLog()
} catch (e: ActivityNotFoundException) {
Toast.makeText(context, context?.getString(R.string.dialog_send_message_log_error_no_app_to_send_message_found), Toast.LENGTH_LONG).show()
}
}
+ protected open fun sendMessageLogDirectly(messageLog: String) {
+ val deviceInfo = DeviceInfo(Build.MANUFACTURER.capitalize(), Build.MODEL, "Android", Build.VERSION.RELEASE, System.getProperty("os.arch") ?: "")
+
+ // TODO: sending with Ktor did not work
+ //presenter.sendMessageLogDirectly(messageLog, deviceInfo)
+
+ val requestBodyDto = CreateTicketRequestDto(messageLog, "Bankmeister", IssueDescriptionFormat.PlainText,
+ deviceInfo.osName, deviceInfo.osVersion, deviceInfo.manufacturer, deviceInfo.deviceModel)
+ val requestBody = JacksonJsonSerializer().serializeObject(requestBodyDto)
+
+ OkHttpWebClient().postAsync(RequestParameters("https://codinux.uber.space/issues", requestBody, "application/json")) { response ->
+ context?.asActivity()?.runOnUiThread {
+ handleSendMessageLogDirectlyResponseOnUiThread(response)
+ }
+ }
+ }
+
+ protected open fun handleSendMessageLogDirectlyResponseOnUiThread(response: WebClientResponse) {
+ if (response.isSuccessResponse) {
+ showSuccessfullySentMessageLog()
+ }
+ else {
+ Toast.makeText(context, context?.getString(R.string.dialog_send_message_log_error_could_not_sent_message_log, response.error?.getInnerExceptionMessage()),
+ Toast.LENGTH_LONG).show()
+ }
+ }
+
+ protected open fun showSuccessfullySentMessageLog() {
+ Toast.makeText(context, context?.getString(R.string.dialog_send_message_log_thanks_for_helping_making_app_better), Toast.LENGTH_LONG).show()
+
+ dismiss()
+ }
+
}
\ No newline at end of file
diff --git a/ui/BankingAndroidApp/src/main/res/layout/dialog_send_message_log.xml b/ui/BankingAndroidApp/src/main/res/layout/dialog_send_message_log.xml
index c461d718..02649e86 100644
--- a/ui/BankingAndroidApp/src/main/res/layout/dialog_send_message_log.xml
+++ b/ui/BankingAndroidApp/src/main/res/layout/dialog_send_message_log.xml
@@ -54,23 +54,33 @@
>
+
+
+
+
-
-
diff --git a/ui/BankingAndroidApp/src/main/res/values-de/strings.xml b/ui/BankingAndroidApp/src/main/res/values-de/strings.xml
index 3acc2662..9e3b8732 100644
--- a/ui/BankingAndroidApp/src/main/res/values-de/strings.xml
+++ b/ui/BankingAndroidApp/src/main/res/values-de/strings.xml
@@ -222,12 +222,14 @@
Message Log
- Senden
+ Per E-Mail
+ Direkt senden
Noch keine Message Log Einträge vorhanden. Führen Sie erst ein paar Aktionen durch, z. B. Abholen der Umsätze.
Könnten Sie noch eine kurze Beschreibung des aufgetretenen Fehlers hinzufügen (z. B. was Sie zuvor in der App gemacht haben oder welches TAN Verfahren Sie verwendet haben)?\n\n\n%s
Message Log
Message Log senden …
Vielen Dank, dass sie uns dabei helfen die App besser zu machen!
+ Message Log konnte nicht gesendet werden:\n%s
Keine E-Mail App zum Senden des Message Logs gefunden.
diff --git a/ui/BankingAndroidApp/src/main/res/values/strings.xml b/ui/BankingAndroidApp/src/main/res/values/strings.xml
index cc7a3b3d..725d0102 100644
--- a/ui/BankingAndroidApp/src/main/res/values/strings.xml
+++ b/ui/BankingAndroidApp/src/main/res/values/strings.xml
@@ -223,12 +223,14 @@
Message log
- Send
+ E-mail
+ Send directly
No message log entries yet. First do some actions like requesting account transactions from bank.
Could you courteously add a short description of the occurred error?\n\n\n%s
Message Log
Send message log…
Thanks a lot for helping us make the app better!
+ Message log could not be sent:\n%s
There are no email clients to send message installed.
diff --git a/ui/BankingUiCommon/build.gradle b/ui/BankingUiCommon/build.gradle
index fbd9d701..9d9257f6 100644
--- a/ui/BankingUiCommon/build.gradle
+++ b/ui/BankingUiCommon/build.gradle
@@ -42,6 +42,13 @@ kotlin {
api project(":BankFinder")
api project(":EpcQrCodeParser")
+
+ // Ktor
+ api "io.ktor:ktor-client-core:$ktorVersion"
+ api "io.ktor:ktor-client-cio:$ktorVersion"
+ api "io.ktor:ktor-client-serialization:$ktorVersion"
+ api "io.ktor:ktor-client-logging:$ktorVersion"
+ api "org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.1"
}
}
diff --git a/ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/issues/CreateTicketRequestDto.kt b/ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/issues/CreateTicketRequestDto.kt
new file mode 100644
index 00000000..8374db94
--- /dev/null
+++ b/ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/issues/CreateTicketRequestDto.kt
@@ -0,0 +1,15 @@
+package net.dankito.banking.ui.model.issues
+
+import kotlinx.serialization.Serializable
+
+
+@Serializable
+class CreateTicketRequestDto(
+ val issueDescription: String,
+ val applicationName: String,
+ val format: IssueDescriptionFormat = IssueDescriptionFormat.PlainText,
+ val osName: String? = null,
+ val osVersion: String? = null,
+ val deviceManufacturer: String? = null,
+ val deviceModel: String? = null
+)
\ No newline at end of file
diff --git a/ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/issues/IssueDescriptionFormat.kt b/ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/issues/IssueDescriptionFormat.kt
new file mode 100644
index 00000000..5dfc5b26
--- /dev/null
+++ b/ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/issues/IssueDescriptionFormat.kt
@@ -0,0 +1,10 @@
+package net.dankito.banking.ui.model.issues
+
+
+enum class IssueDescriptionFormat {
+
+ PlainText,
+
+ Html
+
+}
\ No newline at end of file
diff --git a/ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/presenter/BankingPresenter.kt b/ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/presenter/BankingPresenter.kt
index 027d9d26..32b3ce1d 100644
--- a/ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/presenter/BankingPresenter.kt
+++ b/ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/presenter/BankingPresenter.kt
@@ -35,8 +35,22 @@ import net.dankito.banking.util.extraction.NoOpTextExtractorRegistry
import net.codinux.banking.tools.epcqrcode.*
import net.dankito.banking.service.testaccess.TestAccessBankingClientCreator
import net.dankito.utils.multiplatform.*
+import net.dankito.utils.multiplatform.getInnerExceptionMessage
import net.dankito.utils.multiplatform.log.LoggerFactory
+import net.dankito.utils.multiplatform.os.DeviceInfo
+import net.dankito.utils.multiplatform.os.DeviceInfoRetriever
import kotlin.collections.ArrayList
+import io.ktor.client.*
+import io.ktor.client.engine.cio.*
+import io.ktor.client.features.json.*
+import io.ktor.client.features.json.serializer.*
+import io.ktor.client.request.*
+import io.ktor.http.cio.*
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.launch
+import net.dankito.banking.ui.model.issues.CreateTicketRequestDto
+import net.dankito.banking.ui.model.issues.IssueDescriptionFormat
open class BankingPresenter(
@@ -85,6 +99,18 @@ open class BankingPresenter(
protected set
+ protected val httpClient = HttpClient(CIO) {
+ install(JsonFeature) {
+ serializer = KotlinxSerializer(kotlinx.serialization.json.Json {
+ isLenient = true
+ ignoreUnknownKeys = true
+ allowSpecialFloatingPointValues = true
+ useArrayPolymorphism = false
+ })
+ }
+ }
+
+
protected val bankingClientsForBanks = mutableMapOf()
protected val messageLogsOfFailedAccountAdditions = mutableListOf()
@@ -813,6 +839,39 @@ open class BankingPresenter(
}
+ open fun sendMessageLogDirectly(messageLog: String) {
+ return sendMessageLogDirectly(messageLog, DeviceInfoRetriever().getDeviceInfo())
+ }
+
+ open fun sendMessageLogDirectly(messageLog: String, deviceInfo: DeviceInfo) {
+ // TODO: serialization with @Serializable does not work
+ //val requestBody = CreateTicketRequestDto(messageLog, "Bankmeister", IssueDescriptionFormat.PlainText,
+ //deviceInfo.osName, deviceInfo.osVersion, deviceInfo.manufacturer, deviceInfo.deviceModel)
+
+ val requestBody = """{
+ "applicationName": "Bankmeister",
+ "osName": "Android",
+ "issueDescription": "Test"
+ }""".trimIndent()
+ log.info("testBody: $requestBody")
+
+ GlobalScope.launch(Dispatchers.Main) {
+ try {
+ // TODO: sending with Ktor does not work. Sends request body in a way that it's not deserializable for Jackson
+ val response = httpClient.post("https://codinux.uber.space/issues") {
+ header("Content-Type", "application/json")
+
+ body = requestBody
+ }
+
+ log.info("Response: $response")
+ } catch (e: Exception) {
+ log.error("Could not create ticket directly: ${e.getInnerExceptionMessage()}", e)
+ }
+ }
+ }
+
+
open fun showAddAccountDialog() {
router.showAddAccountDialog(this)
}