Implemented selected TAN procedure in EnterTanDialog

This commit is contained in:
dankl 2020-01-01 21:06:39 +01:00 committed by dankito
parent ce6f548ceb
commit 0175296c66
10 changed files with 96 additions and 49 deletions

View File

@ -11,15 +11,12 @@ import android.text.TextWatcher
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.Spinner
import android.widget.TextView import android.widget.TextView
import kotlinx.android.synthetic.main.dialog_add_account.* import kotlinx.android.synthetic.main.dialog_add_account.*
import kotlinx.android.synthetic.main.dialog_add_account.view.* import kotlinx.android.synthetic.main.dialog_add_account.view.*
import net.dankito.banking.fints4java.android.R import net.dankito.banking.fints4java.android.R
import net.dankito.banking.fints4java.android.ui.MainWindowPresenter import net.dankito.banking.fints4java.android.ui.MainWindowPresenter
import net.dankito.banking.fints4java.android.ui.adapter.BankListAdapter import net.dankito.banking.fints4java.android.ui.adapter.BankListAdapter
import net.dankito.banking.fints4java.android.ui.adapter.TanProceduresAdapter
import net.dankito.banking.ui.model.responses.AddAccountResponse import net.dankito.banking.ui.model.responses.AddAccountResponse
import net.dankito.fints.model.BankInfo import net.dankito.fints.model.BankInfo
import net.dankito.utils.android.extensions.asActivity import net.dankito.utils.android.extensions.asActivity
@ -129,25 +126,8 @@ open class AddAccountDialog : DialogFragment() {
val view = context.asActivity()?.layoutInflater?.inflate(R.layout.view_successfully_added_account, null) val view = context.asActivity()?.layoutInflater?.inflate(R.layout.view_successfully_added_account, null)
val adapter = TanProceduresAdapter()
adapter.setItems(response.account.supportedTanProcedures)
view?.findViewById<TextView>(R.id.txtSuccessfullyAddedAccountMessage)?.setText(messageId) view?.findViewById<TextView>(R.id.txtSuccessfullyAddedAccountMessage)?.setText(messageId)
view?.findViewById<Spinner>(R.id.spnTanProcedures)?.let { spinner ->
spinner.adapter = adapter
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onNothingSelected(parent: AdapterView<*>?) {}
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
response.account.selectedTanProcedure = adapter.getItem(position)
}
}
spinner.setSelection(adapter.getItems().indexOfFirst { it.displayName.contains("manuell", true) == false })
}
return view return view
} }

View File

@ -9,10 +9,13 @@ import android.text.InputType
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Spinner
import kotlinx.android.synthetic.main.dialog_enter_tan.view.* import kotlinx.android.synthetic.main.dialog_enter_tan.view.*
import net.dankito.banking.fints4java.android.R import net.dankito.banking.fints4java.android.R
import net.dankito.banking.fints4java.android.mapper.fints4javaModelMapper
import net.dankito.banking.fints4java.android.ui.MainWindowPresenter import net.dankito.banking.fints4java.android.ui.MainWindowPresenter
import net.dankito.banking.fints4java.android.ui.adapter.TanMediumAdapter import net.dankito.banking.fints4java.android.ui.adapter.TanMediumAdapter
import net.dankito.banking.fints4java.android.ui.adapter.TanProceduresAdapter
import net.dankito.banking.fints4java.android.ui.listener.ListItemSelectedListener import net.dankito.banking.fints4java.android.ui.listener.ListItemSelectedListener
import net.dankito.banking.ui.model.Account import net.dankito.banking.ui.model.Account
import net.dankito.banking.ui.model.TanMedium import net.dankito.banking.ui.model.TanMedium
@ -69,6 +72,8 @@ open class EnterTanDialog : DialogFragment() {
protected open fun setupUI(rootView: View) { protected open fun setupUI(rootView: View) {
val flickerCodeView = rootView.flickerCodeView val flickerCodeView = rootView.flickerCodeView
setupSelectTanProcedureView(rootView)
if (tanChallenge.tanProcedure.type == TanProcedureType.ChipTanOptisch) { if (tanChallenge.tanProcedure.type == TanProcedureType.ChipTanOptisch) {
if (account.tanMedia.isNotEmpty()) { if (account.tanMedia.isNotEmpty()) {
setupSelectTanMediumView(rootView) setupSelectTanMediumView(rootView)
@ -87,6 +92,29 @@ open class EnterTanDialog : DialogFragment() {
rootView.btnEnteringTanDone.setOnClickListener { enteringTanDone(rootView.edtxtEnteredTan.text.toString()) } rootView.btnEnteringTanDone.setOnClickListener { enteringTanDone(rootView.edtxtEnteredTan.text.toString()) }
} }
protected open fun setupSelectTanProcedureView(rootView: View) {
val adapter = TanProceduresAdapter()
adapter.setItems(account.supportedTanProcedures)
rootView.findViewById<Spinner>(R.id.spnTanProcedures)?.let { spinner ->
spinner.adapter = adapter
val selectedTanProcedure = account.selectedTanProcedure
?: account.supportedTanProcedures.firstOrNull()
selectedTanProcedure?.let { spinner.setSelection(adapter.getItems().indexOf(selectedTanProcedure)) }
spinner.onItemSelectedListener = ListItemSelectedListener(adapter) { newSelectedTanProcedure ->
if (newSelectedTanProcedure != selectedTanProcedure) {
val mappedTanProcedure = fints4javaModelMapper().mapTanProcedureBack(newSelectedTanProcedure) // TODO: move to MainWindowPresenter
tanEnteredCallback(EnterTanResult.userAsksToChangeTanProcedure(mappedTanProcedure))
// TODO: find a way to update account.selectedTanProcedure afterwards
dismiss()
}
}
}
}
protected open fun setupSelectTanMediumView(rootView: View) { protected open fun setupSelectTanMediumView(rootView: View) {
rootView.lytTanMedium.visibility = View.VISIBLE rootView.lytTanMedium.visibility = View.VISIBLE

View File

@ -6,6 +6,33 @@
android:padding="@dimen/dialog_enter_tan_padding" android:padding="@dimen/dialog_enter_tan_padding"
> >
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="@dimen/dialog_enter_tan_tan_procedure_height"
android:gravity="center_vertical"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="@string/dialog_enter_tan_select_tan_procedure"
android:layout_marginRight="@dimen/dialog_enter_tan_tan_procedure_label_right_margin"
android:layout_marginEnd="@dimen/dialog_enter_tan_tan_procedure_label_right_margin"
android:gravity="center_vertical"
android:textSize="@dimen/dialog_enter_tan_tan_procedure_text_size"
/>
<Spinner
android:id="@+id/spnTanProcedures"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
/>
</LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/lytTanMedium" android:id="@+id/lytTanMedium"
android:orientation="horizontal" android:orientation="horizontal"
@ -22,7 +49,7 @@
android:layout_marginRight="@dimen/dialog_enter_tan_tan_medium_label_right_margin" android:layout_marginRight="@dimen/dialog_enter_tan_tan_medium_label_right_margin"
android:layout_marginEnd="@dimen/dialog_enter_tan_tan_medium_label_right_margin" android:layout_marginEnd="@dimen/dialog_enter_tan_tan_medium_label_right_margin"
android:gravity="center_vertical" android:gravity="center_vertical"
android:textSize="@dimen/view_change_tan_medium_text_size" android:textSize="@dimen/dialog_enter_tan_tan_medium_text_size"
/> />
<Spinner <Spinner

View File

@ -5,7 +5,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
style="@style/TextAppearance.AppCompat.Small" style="@style/TextAppearance.AppCompat.Small"
android:textSize="@dimen/view_change_tan_medium_text_size" android:textSize="@dimen/dialog_enter_tan_tan_medium_text_size"
android:singleLine="true" android:singleLine="true"
android:ellipsize="marquee" android:ellipsize="marquee"
android:padding="@dimen/list_item_tan_medium_padding" android:padding="@dimen/list_item_tan_medium_padding"

View File

@ -2,10 +2,11 @@
<TextView <TextView
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/txtTanProcedureDisplayName" android:id="@+id/txtTanProcedureDisplayName"
style="@style/TextAppearance.AppCompat.Medium"
android:singleLine="true"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
style="@style/TextAppearance.AppCompat.Medium"
android:textSize="@dimen/dialog_enter_tan_tan_procedure_text_size"
android:singleLine="true"
android:ellipsize="marquee" android:ellipsize="marquee"
android:padding="@dimen/list_item_tan_procedure_padding" android:padding="@dimen/list_item_tan_procedure_padding"
/> />

View File

@ -15,21 +15,4 @@
style="@style/TextAppearance.AppCompat.Medium" style="@style/TextAppearance.AppCompat.Medium"
/> />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="@dimen/view_successfully_added_account_tan_procedures_height"
android:gravity="center_vertical"
>
<Spinner
android:id="@+id/spnTanProcedures"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
/>
</LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -50,8 +50,12 @@
<dimen name="view_tan_generator_marker_margin_bottom">6dp</dimen> <dimen name="view_tan_generator_marker_margin_bottom">6dp</dimen>
<dimen name="dialog_enter_tan_padding">4dp</dimen> <dimen name="dialog_enter_tan_padding">4dp</dimen>
<dimen name="dialog_enter_tan_tan_procedure_height">30dp</dimen>
<dimen name="dialog_enter_tan_tan_procedure_label_right_margin">8dp</dimen>
<dimen name="dialog_enter_tan_tan_procedure_text_size">15sp</dimen>
<dimen name="dialog_enter_tan_tan_medium_height">30dp</dimen> <dimen name="dialog_enter_tan_tan_medium_height">30dp</dimen>
<dimen name="dialog_enter_tan_tan_medium_label_right_margin">8dp</dimen> <dimen name="dialog_enter_tan_tan_medium_label_right_margin">8dp</dimen>
<dimen name="dialog_enter_tan_tan_medium_text_size">15sp</dimen>
<dimen name="dialog_enter_tan_flicker_view_height">175dp</dimen> <dimen name="dialog_enter_tan_flicker_view_height">175dp</dimen>
<dimen name="dialog_enter_tan_flicker_view_margin_top_bottom">20dp</dimen> <dimen name="dialog_enter_tan_flicker_view_margin_top_bottom">20dp</dimen>
<dimen name="dialog_enter_tan_enter_tan_height">50dp</dimen> <dimen name="dialog_enter_tan_enter_tan_height">50dp</dimen>
@ -62,8 +66,6 @@
<dimen name="list_item_tan_procedure_padding">4dp</dimen> <dimen name="list_item_tan_procedure_padding">4dp</dimen>
<dimen name="view_change_tan_medium_text_size">15sp</dimen>
<dimen name="list_item_tan_medium_padding">4dp</dimen> <dimen name="list_item_tan_medium_padding">4dp</dimen>
<dimen name="dialog_enter_atc_padding">4dp</dimen> <dimen name="dialog_enter_atc_padding">4dp</dimen>

View File

@ -34,13 +34,11 @@
<string name="dialog_add_account_message_successfully_added_account"> <string name="dialog_add_account_message_successfully_added_account">
Successfully added account. Successfully added account.
\n\nWould you like to fetch all account transactions now? If so entering a TAN is required. \n\nWould you like to fetch all account transactions now? If so entering a TAN is required.
\n\nEven if not, please choose your TAN procedure here:
</string> </string>
<string name="dialog_add_account_message_successfully_added_account_support_retrieving_transactions_of_last_90_days_without_tan"> <string name="dialog_add_account_message_successfully_added_account_support_retrieving_transactions_of_last_90_days_without_tan">
Successfully added account. Successfully added account.
\n\nYour bank supports retrieving account transactions of last 90 days without TAN. These are already displayed in background. \n\nYour bank supports retrieving account transactions of last 90 days without TAN. These are already displayed in background.
\n\nWould you like to fetch all account transactions now? If so entering a TAN is required. \n\nWould you like to fetch all account transactions now? If so entering a TAN is required.
\n\nEven if not, please choose your TAN procedure here:
</string> </string>
<string name="dialog_bank_transfer_remittee_name">Name:</string> <string name="dialog_bank_transfer_remittee_name">Name:</string>
@ -59,6 +57,7 @@
<string name="view_flicker_code_increase_frequency">+</string> <string name="view_flicker_code_increase_frequency">+</string>
<string name="view_flicker_code_decrease_frequency">-</string> <string name="view_flicker_code_decrease_frequency">-</string>
<string name="dialog_enter_tan_select_tan_procedure">TAN procedure</string>
<string name="dialog_enter_tan_select_tan_medium">TAN medium</string> <string name="dialog_enter_tan_select_tan_medium">TAN medium</string>
<string name="dialog_enter_tan_enter_tan">Enter TAN:</string> <string name="dialog_enter_tan_enter_tan">Enter TAN:</string>
<string name="dialog_enter_tan_tan_medium_successfully_changed">TAN medium successfully changed to \'%s\'.</string> <string name="dialog_enter_tan_tan_medium_successfully_changed">TAN medium successfully changed to \'%s\'.</string>

View File

@ -611,7 +611,11 @@ open class FinTsClient @JvmOverloads constructor(
val enteredTanResult = callback.enterTan(customer, TanChallenge(tanResponse.challenge ?: "", val enteredTanResult = callback.enterTan(customer, TanChallenge(tanResponse.challenge ?: "",
tanResponse.challengeHHD_UC ?: "", customer.selectedTanProcedure)) tanResponse.challengeHHD_UC ?: "", customer.selectedTanProcedure))
if (enteredTanResult.changeTanMediumTo is TanGeneratorTanMedium) { if (enteredTanResult.changeTanProcedureTo != null) {
return handleUserAsksToChangeTanProcedureAndResendLastMessage(enteredTanResult.changeTanProcedureTo,
bank, customer, dialogData)
}
else if (enteredTanResult.changeTanMediumTo is TanGeneratorTanMedium) {
return handleUserAsksToChangeTanMediumAndResendLastMessage(enteredTanResult.changeTanMediumTo, return handleUserAsksToChangeTanMediumAndResendLastMessage(enteredTanResult.changeTanMediumTo,
bank, customer, dialogData, enteredTanResult.changeTanMediumResultCallback) bank, customer, dialogData, enteredTanResult.changeTanMediumResultCallback)
} }
@ -646,6 +650,24 @@ open class FinTsClient @JvmOverloads constructor(
return getAndHandleResponseForMessageThatMayRequiresTan(message, bank, customer, dialogData) return getAndHandleResponseForMessageThatMayRequiresTan(message, bank, customer, dialogData)
} }
protected open fun handleUserAsksToChangeTanProcedureAndResendLastMessage(changeTanProcedureTo: TanProcedure, bank: BankData,
customer: CustomerData, dialogData: DialogData): Response {
val lastCreatedMessage = messageBuilder.lastCreatedMessage
customer.selectedTanProcedure = changeTanProcedureTo
lastCreatedMessage?.let {
closeDialog(bank, customer, dialogData)
return resendMessageInNewDialog(lastCreatedMessage, bank, customer)
}
val errorMessage = "There's no last action (like retrieve account transactions, transfer money, ...) to re-send with new TAN procedure. Probably an internal programming error." // TODO: translate
return Response(false, exception = Exception(errorMessage)) // should never come to this
}
protected open fun handleUserAsksToChangeTanMediumAndResendLastMessage(changeTanMediumTo: TanGeneratorTanMedium, bank: BankData, protected open fun handleUserAsksToChangeTanMediumAndResendLastMessage(changeTanMediumTo: TanGeneratorTanMedium, bank: BankData,
customer: CustomerData, dialogData: DialogData, customer: CustomerData, dialogData: DialogData,
changeTanMediumResultCallback: ((FinTsClientResponse) -> Unit)?): Response { changeTanMediumResultCallback: ((FinTsClientResponse) -> Unit)?): Response {

View File

@ -6,6 +6,7 @@ import net.dankito.fints.response.client.FinTsClientResponse
open class EnterTanResult protected constructor( open class EnterTanResult protected constructor(
val enteredTan: String?, val enteredTan: String?,
val changeTanProcedureTo: TanProcedure?,
val changeTanMediumTo: TanMedium?, val changeTanMediumTo: TanMedium?,
val changeTanMediumResultCallback: ((FinTsClientResponse) -> Unit)? = null val changeTanMediumResultCallback: ((FinTsClientResponse) -> Unit)? = null
) { ) {
@ -13,15 +14,19 @@ open class EnterTanResult protected constructor(
companion object { companion object {
fun userEnteredTan(enteredTan: String): EnterTanResult { fun userEnteredTan(enteredTan: String): EnterTanResult {
return EnterTanResult(enteredTan, null) return EnterTanResult(enteredTan, null, null)
} }
fun userDidNotEnterTan(): EnterTanResult { fun userDidNotEnterTan(): EnterTanResult {
return EnterTanResult(null, null) return EnterTanResult(null, null, null)
}
fun userAsksToChangeTanProcedure(changeTanProcedureTo: TanProcedure): EnterTanResult {
return EnterTanResult(null, changeTanProcedureTo, null)
} }
fun userAsksToChangeTanMedium(changeTanMediumTo: TanMedium, changeTanMediumResultCallback: (FinTsClientResponse) -> Unit): EnterTanResult { fun userAsksToChangeTanMedium(changeTanMediumTo: TanMedium, changeTanMediumResultCallback: (FinTsClientResponse) -> Unit): EnterTanResult {
return EnterTanResult(null, changeTanMediumTo, changeTanMediumResultCallback) return EnterTanResult(null, null, changeTanMediumTo, changeTanMediumResultCallback)
} }
} }