diff --git a/fints4k/src/main/kotlin/net/dankito/fints/FinTsClient.kt b/fints4k/src/main/kotlin/net/dankito/fints/FinTsClient.kt index b0ba1c3c..05de11d9 100644 --- a/fints4k/src/main/kotlin/net/dankito/fints/FinTsClient.kt +++ b/fints4k/src/main/kotlin/net/dankito/fints/FinTsClient.kt @@ -64,8 +64,9 @@ open class FinTsClient @JvmOverloads constructor( protected val messageLogField = CopyOnWriteArrayList() - open val messageLog: List - get() = ArrayList(messageLogField) + // in either case remove sensitive data after response is parsed as otherwise some information like account holder name and accounts may is not set yet on CustomerData + open val messageLogWithoutSensitiveData: List + get() = messageLogField.map { MessageLogEntry(removeSensitiveDataFromMessage(it.message, it.customer), it.time, it.customer) } /** @@ -648,29 +649,32 @@ open class FinTsClient @JvmOverloads constructor( protected open fun addMessageLog(message: String, type: MessageLogEntryType, dialogContext: DialogContext) { val timeStamp = Date() + val messagePrefix = "${if (type == MessageLogEntryType.Sent) "Sending" else "Received"} message:\r\n" // currently no need to translate val prettyPrintMessage = prettyPrintHbciMessage(message) - - val prettyPrintMessageWithoutSensitiveData = removeSensitiveDataFromMessage(prettyPrintMessage, dialogContext) - + val prettyPrintMessageWithPrefix = "$messagePrefix$prettyPrintMessage" if (log.isDebugEnabled) { - log.debug("${if (type == MessageLogEntryType.Sent) "Sending" else "Received"} message:\n$prettyPrintMessage") + log.debug(prettyPrintMessageWithPrefix) } - messageLogField.add(MessageLogEntry(prettyPrintMessageWithoutSensitiveData, timeStamp, dialogContext.customer)) + messageLogField.add(MessageLogEntry(prettyPrintMessageWithPrefix, timeStamp, dialogContext.customer)) } - protected open fun removeSensitiveDataFromMessage(prettyPrintMessage: String, dialogContext: DialogContext): String { - var prettyPrintMessageWithoutSensitiveData = prettyPrintMessage - .replace(dialogContext.customer.customerId, "") - .replace("+" + dialogContext.customer.pin, "+") + protected fun prettyPrintHbciMessage(message: String): String { + return message.replace("'", "'\r\n") + } - if (dialogContext.customer.name.isNotBlank()) { // TODO: log after response is parsed as otherwise this information may is not available + protected open fun removeSensitiveDataFromMessage(message: String, customer: CustomerData): String { + var prettyPrintMessageWithoutSensitiveData = message + .replace(customer.customerId, "") + .replace("+" + customer.pin, "+") + + if (customer.name.isNotBlank()) { prettyPrintMessageWithoutSensitiveData = prettyPrintMessageWithoutSensitiveData - .replace(dialogContext.customer.name, "", true) + .replace(customer.name, "", true) } - dialogContext.customer.accounts.forEach { account -> + customer.accounts.forEach { account -> prettyPrintMessageWithoutSensitiveData = prettyPrintMessageWithoutSensitiveData .replace(account.accountIdentifier, "") diff --git a/fints4k/src/main/kotlin/net/dankito/fints/FinTsClientForCustomer.kt b/fints4k/src/main/kotlin/net/dankito/fints/FinTsClientForCustomer.kt index 115f3709..a57feaca 100644 --- a/fints4k/src/main/kotlin/net/dankito/fints/FinTsClientForCustomer.kt +++ b/fints4k/src/main/kotlin/net/dankito/fints/FinTsClientForCustomer.kt @@ -32,6 +32,10 @@ open class FinTsClientForCustomer @JvmOverloads constructor( protected val client = FinTsClient(callback, base64Service, webClient, messageBuilder, responseParser, mt940Parser, threadPool, product) + open val messageLogWithoutSensitiveData: List + get() = client.messageLogWithoutSensitiveData + + open fun addAccountAsync(callback: (AddAccountResponse) -> Unit) { client.addAccountAsync(bank, customer, callback) } diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/fints4java/android/RouterAndroid.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/fints4java/android/RouterAndroid.kt index 7c7def6b..ae3baf28 100644 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/fints4java/android/RouterAndroid.kt +++ b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/fints4java/android/RouterAndroid.kt @@ -1,9 +1,6 @@ package net.dankito.banking.fints4java.android -import net.dankito.banking.fints4java.android.ui.dialogs.AddAccountDialog -import net.dankito.banking.fints4java.android.ui.dialogs.EnterAtcDialog -import net.dankito.banking.fints4java.android.ui.dialogs.EnterTanDialog -import net.dankito.banking.fints4java.android.ui.dialogs.TransferMoneyDialog +import net.dankito.banking.fints4java.android.ui.dialogs.* import net.dankito.banking.fints4java.android.ui.util.CurrentActivityTracker import net.dankito.banking.ui.IRouter import net.dankito.banking.ui.model.Account @@ -68,4 +65,12 @@ open class RouterAndroid(protected val activityTracker: CurrentActivityTracker) } } + override fun showSendMessageLogDialog(presenter: BankingPresenter) { + activityTracker.currentOrNextActivity { activity -> + activity.runOnUiThread { + SendMessageLogDialog().show(activity) + } + } + } + } \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/fints4java/android/di/BankingComponent.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/fints4java/android/di/BankingComponent.kt index e28a8137..c62dc29c 100644 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/fints4java/android/di/BankingComponent.kt +++ b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/fints4java/android/di/BankingComponent.kt @@ -5,6 +5,7 @@ import net.dankito.banking.fints4java.android.MainActivity import net.dankito.banking.fints4java.android.ui.activities.BaseActivity import net.dankito.banking.fints4java.android.ui.dialogs.AddAccountDialog import net.dankito.banking.fints4java.android.ui.dialogs.EnterTanDialog +import net.dankito.banking.fints4java.android.ui.dialogs.SendMessageLogDialog import net.dankito.banking.fints4java.android.ui.dialogs.TransferMoneyDialog import net.dankito.banking.fints4java.android.ui.home.HomeFragment import javax.inject.Singleton @@ -31,4 +32,6 @@ interface BankingComponent { fun inject(transferMoneyDialog: TransferMoneyDialog) + fun inject(sendMessageLogDialog: SendMessageLogDialog) + } \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/dialogs/SendMessageLogDialog.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/dialogs/SendMessageLogDialog.kt new file mode 100644 index 00000000..f4f0717a --- /dev/null +++ b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/dialogs/SendMessageLogDialog.kt @@ -0,0 +1,87 @@ +package net.dankito.banking.fints4java.android.ui.dialogs + +import android.content.ActivityNotFoundException +import android.content.Intent +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.DialogFragment +import kotlinx.android.synthetic.main.dialog_send_message_log.view.* +import net.dankito.banking.fints4java.android.R +import net.dankito.banking.fints4java.android.di.BankingComponent +import net.dankito.banking.ui.presenter.BankingPresenter +import javax.inject.Inject + + +open class SendMessageLogDialog : DialogFragment() { + + companion object { + const val DialogTag = "SendMessageLogDialog" + } + + + @Inject + protected lateinit var presenter: BankingPresenter + + + init { + BankingComponent.component.inject(this) + } + + + fun show(activity: AppCompatActivity, fullscreen: Boolean = false) { + val style = if(fullscreen) R.style.FullscreenDialogWithStatusBar else R.style.FloatingDialog + setStyle(STYLE_NORMAL, style) + + show(activity.supportFragmentManager, DialogTag) + } + + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + val rootView = inflater.inflate(R.layout.dialog_send_message_log, container, false) + + rootView?.let { + setupUI(rootView) + } + + return rootView + } + + protected open fun setupUI(rootView: View) { + val messageLog = presenter.getMessageLogForAccounts(presenter.accounts).joinToString("\r\n\r\n") + + if (messageLog.isBlank()) { + rootView.txtvwInfoNoMessageLogEntriesYet.visibility = View.VISIBLE + rootView.lytMessageLog.visibility = View.GONE + } + else { + rootView.edtxtMessageLog.setText(context?.getString(R.string.dialog_send_message_courteously_add_error_description, messageLog)) + } + + rootView.btnSendMessageLog.setOnClickListener { sendMessageLog(rootView.edtxtMessageLog.text.toString()) } + + rootView.btnCancel.setOnClickListener { dismiss() } + } + + protected open fun sendMessageLog(messageLog: String) { + val sendMailAction = Intent(Intent.ACTION_SEND) + sendMailAction.type = "message/rfc822" + sendMailAction.putExtra(Intent.EXTRA_EMAIL, arrayOf("panta.rhei@dankito.net")) + sendMailAction.putExtra(Intent.EXTRA_SUBJECT, context?.getString(R.string.dialog_send_message_log_mail_subject)) + sendMailAction.putExtra(Intent.EXTRA_TEXT, messageLog) + + try { + startActivity(Intent.createChooser(sendMailAction, 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() + } 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() + } + } + +} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/views/DrawerView.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/views/DrawerView.kt index 26ac12c5..c067fb3d 100644 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/views/DrawerView.kt +++ b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/views/DrawerView.kt @@ -8,6 +8,7 @@ import androidx.core.view.GravityCompat import androidx.drawerlayout.widget.DrawerLayout import com.mikepenz.iconics.typeface.library.fontawesome.FontAwesome import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial +import com.mikepenz.materialdrawer.model.DividerDrawerItem import com.mikepenz.materialdrawer.model.PrimaryDrawerItem import com.mikepenz.materialdrawer.model.SecondaryDrawerItem import com.mikepenz.materialdrawer.model.SectionDrawerItem @@ -39,7 +40,8 @@ open class DrawerView( private const val AllAccountsId = 1001L private const val AddAccountId = 1002L - private const val CountDefaultAccountItems = 3 + private const val CountDefaultAccountItems = 4 + private const val CountDefaultAccountItemsAtTop = 2 private val log = LoggerFactory.getLogger(DrawerView::class.java) @@ -94,6 +96,18 @@ open class DrawerView( .withIcon(activity, GoogleMaterial.Icon.gmd_add, R.color.primaryTextColor_Dark) .withSelectable(false) .withOnDrawerItemClickListener { _, _, _ -> itemClicked { presenter.showAddAccountDialog() } } + , + + DividerDrawerItem() + .withSelectable(false) + , + + PrimaryDrawerItem() + .withName(R.string.drawer_menu_send_message_log_title) + .withIcon(activity, GoogleMaterial.Icon.gmd_mail, R.color.primaryTextColor_Dark) + .withSelectable(false) + .withOnDrawerItemClickListener { _, _, _ -> itemClicked { presenter.showSendMessageLogDialog() } } + ) } } @@ -101,12 +115,12 @@ open class DrawerView( private fun updateDrawerItems() { // removes previously shown accounts; index 1 = 'Accounts header', 1 = 'All accounts', index 2 = 'Add account', don't remove these while (slider.itemAdapter.adapterItems.size > CountDefaultAccountItems) { - slider.removeItemByPosition(CountDefaultAccountItems) + slider.removeItemByPosition(CountDefaultAccountItemsAtTop) } val accountItems = createAccountsDrawerItems() - slider.addItemsAtPosition(CountDefaultAccountItems, *accountItems.toTypedArray()) + slider.addItemsAtPosition(CountDefaultAccountItemsAtTop, *accountItems.toTypedArray()) slider.getDrawerItem(AllAccountsId)?.let { allAccountsItem -> if (presenter.areAllAccountSelected) slider.selectExtension.select(allAccountsItem, false) 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 new file mode 100644 index 00000000..c461d718 --- /dev/null +++ b/ui/BankingAndroidApp/src/main/res/layout/dialog_send_message_log.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + +