Implemented changing TAN medium (HKTAU) in UI and entering ATC, but job result after changing TAN medium doesn't get passed on to UI yet

This commit is contained in:
dankl 2019-12-30 22:53:01 +01:00 committed by dankito
parent cb557812c4
commit fc2a5e6cf9
14 changed files with 353 additions and 18 deletions

View File

@ -8,8 +8,10 @@ import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar import android.support.v7.widget.Toolbar
import android.view.Menu import android.view.Menu
import androidx.navigation.findNavController import androidx.navigation.findNavController
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.dialogs.AddAccountDialog 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.EnterTanDialog
import net.dankito.fints.FinTsClientCallback import net.dankito.fints.FinTsClientCallback
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium import net.dankito.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium
@ -18,6 +20,7 @@ import net.dankito.fints.model.EnterTanGeneratorAtcResult
import net.dankito.fints.model.TanChallenge import net.dankito.fints.model.TanChallenge
import net.dankito.fints.model.TanProcedure import net.dankito.fints.model.TanProcedure
import java.util.concurrent.CountDownLatch import java.util.concurrent.CountDownLatch
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.atomic.AtomicReference import java.util.concurrent.atomic.AtomicReference
@ -37,7 +40,7 @@ class MainActivity : AppCompatActivity() {
} }
override fun enterTanGeneratorAtc(customer: CustomerData, tanMedium: TanGeneratorTanMedium): EnterTanGeneratorAtcResult? { override fun enterTanGeneratorAtc(customer: CustomerData, tanMedium: TanGeneratorTanMedium): EnterTanGeneratorAtcResult? {
return null return getAtcFromUserOffUiThread(customer, tanMedium)
} }
}) })
@ -96,18 +99,34 @@ class MainActivity : AppCompatActivity() {
val account = presenter.getAccountForCustomer(customer) val account = presenter.getAccountForCustomer(customer)
runOnUiThread { runOnUiThread {
EnterTanDialog().show(account, tanChallenge, this@MainActivity, false) { EnterTanDialog().show(account, tanChallenge, presenter, this@MainActivity, false) {
enteredTan.set(it) enteredTan.set(it)
tanEnteredLatch.countDown() tanEnteredLatch.countDown()
} }
} }
try { try { tanEnteredLatch.await() } catch (ignored: Exception) { }
tanEnteredLatch.await()
} catch (ignored: Exception) {
}
return enteredTan.get() return enteredTan.get()
} }
private fun getAtcFromUserOffUiThread(customer: CustomerData, tanMedium: TanGeneratorTanMedium): EnterTanGeneratorAtcResult? {
val enteredTan = AtomicReference<String>(null)
val enteredAtc = AtomicInteger()
val tanEnteredLatch = CountDownLatch(1)
runOnUiThread {
// TODO: don't create a fints4javaModelMapper instance here, let MainWindowPresenter do the job
EnterAtcDialog().show(fints4javaModelMapper().mapTanMedium(tanMedium), this@MainActivity, false) { tan, atc ->
enteredTan.set(tan)
atc?.let { enteredAtc.set(atc) }
tanEnteredLatch.countDown()
}
}
try { tanEnteredLatch.await() } catch (ignored: Exception) { }
return if (enteredTan.get() == null) null else EnterTanGeneratorAtcResult(enteredTan.get(), enteredAtc.get())
}
} }

View File

@ -103,11 +103,16 @@ open class fints4javaModelMapper {
protected open fun getDisplayNameForTanMedium(tanMedium: net.dankito.fints.messages.datenelemente.implementierte.tan.TanMedium): String { protected open fun getDisplayNameForTanMedium(tanMedium: net.dankito.fints.messages.datenelemente.implementierte.tan.TanMedium): String {
if (tanMedium is TanGeneratorTanMedium) { if (tanMedium is TanGeneratorTanMedium) {
tanMedium.mediaName?.let { mediaName -> var cardNumber = tanMedium.cardNumber
return "$mediaName ${tanMedium.cardNumber}" tanMedium.followUpCardNumber?.let {
cardNumber += " (Folgenummer $it)" // TODO: translate
} }
return "Card ${tanMedium.cardNumber}" // TODO: translate tanMedium.mediaName?.let { mediaName ->
return "$mediaName $cardNumber"
}
return "Karte $cardNumber" // TODO: translate
} }
return tanMedium.mediumClass.name return tanMedium.mediumClass.name

View File

@ -3,11 +3,13 @@ package net.dankito.banking.fints4java.android.ui
import net.dankito.banking.ui.model.Account import net.dankito.banking.ui.model.Account
import net.dankito.banking.ui.model.AccountTransaction import net.dankito.banking.ui.model.AccountTransaction
import net.dankito.banking.ui.model.BankAccount import net.dankito.banking.ui.model.BankAccount
import net.dankito.banking.ui.model.TanMedium
import net.dankito.banking.ui.model.responses.AddAccountResponse import net.dankito.banking.ui.model.responses.AddAccountResponse
import net.dankito.banking.ui.model.responses.GetTransactionsResponse import net.dankito.banking.ui.model.responses.GetTransactionsResponse
import net.dankito.fints.FinTsClientCallback import net.dankito.fints.FinTsClientCallback
import net.dankito.fints.FinTsClientForCustomer import net.dankito.fints.FinTsClientForCustomer
import net.dankito.fints.banks.BankFinder import net.dankito.fints.banks.BankFinder
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium
import net.dankito.fints.model.BankInfo import net.dankito.fints.model.BankInfo
import net.dankito.fints.model.BankTransferData import net.dankito.fints.model.BankTransferData
import net.dankito.fints.model.CustomerData import net.dankito.fints.model.CustomerData
@ -142,6 +144,16 @@ open class MainWindowPresenter(protected val base64Service: IBase64Service,
} }
open fun changeTanMediumAsync(newUsedTanMedium: TanMedium, account: Account, callback: (FinTsClientResponse) -> Unit) {
(newUsedTanMedium.originalObject as? TanGeneratorTanMedium)?.let { tanGeneratorTanMedium ->
getClientForAccount(account)?.changeTanMedium(tanGeneratorTanMedium, callback)
// TODO: find a way to update account.tanMedia afterwards
}
// TODO: what to do if newActiveTanMedium.originalObject is not of type TanGeneratorTanMedium?
}
open fun searchForBankAsync(enteredBankCode: String, callback: (List<BankInfo>) -> Unit) { open fun searchForBankAsync(enteredBankCode: String, callback: (List<BankInfo>) -> Unit) {
threadPool.runAsync { threadPool.runAsync {
callback(searchForBank(enteredBankCode)) callback(searchForBank(enteredBankCode))
@ -181,6 +193,11 @@ open class MainWindowPresenter(protected val base64Service: IBase64Service,
} }
open fun getErrorToShowToUser(response: FinTsClientResponse): String? {
return fints4javaModelMapper.mapErrorToShowToUser(response)
}
open val allTransactions: List<AccountTransaction> open val allTransactions: List<AccountTransaction>
get() = accounts.keys.flatMap { it.transactions }.sortedByDescending { it.bookingDate } // TODO: someday add unbooked transactions get() = accounts.keys.flatMap { it.transactions }.sortedByDescending { it.bookingDate } // TODO: someday add unbooked transactions

View File

@ -12,12 +12,12 @@ import net.dankito.utils.android.ui.adapter.ListAdapter
open class TanMediumAdapter : ListAdapter<TanMedium>() { open class TanMediumAdapter : ListAdapter<TanMedium>() {
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View? { override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View? {
val procedure = getItem(position) val tanMedium = getItem(position)
val view = convertView ?: parent?.context?.asActivity()?.layoutInflater?.inflate( val view = convertView ?: parent?.context?.asActivity()?.layoutInflater?.inflate(
R.layout.list_item_tan_medium, parent, false) R.layout.list_item_tan_medium, parent, false)
view?.findViewById<TextView>(R.id.txtTanMediumDisplayName)?.text = procedure.displayName view?.findViewById<TextView>(R.id.txtTanMediumDisplayName)?.text = tanMedium.displayName
return view return view
} }

View File

@ -134,7 +134,7 @@ open class BankTransferDialog : DialogFragment() {
else { else {
context.getString(R.string.dialog_bank_transfer_message_transfer_failed, context.getString(R.string.dialog_bank_transfer_message_transfer_failed,
String.format("%.02f", transferData.amount), "", transferData.creditorName, // TODO: where to get currency from? String.format("%.02f", transferData.amount), "", transferData.creditorName, // TODO: where to get currency from?
response.exception ?: response.errorsToShowToUser.joinToString("\n") presenter.getErrorToShowToUser(response)
) )
} }

View File

@ -0,0 +1,86 @@
package net.dankito.banking.fints4java.android.ui.dialogs
import android.os.Bundle
import android.support.v4.app.DialogFragment
import android.support.v7.app.AlertDialog
import android.support.v7.app.AppCompatActivity
import android.text.Html
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import kotlinx.android.synthetic.main.dialog_enter_atc.view.*
import net.dankito.banking.fints4java.android.R
import net.dankito.banking.ui.model.TanMedium
open class EnterAtcDialog : DialogFragment() {
companion object {
const val DialogTag = "EnterAtcDialog"
}
protected lateinit var tanMedium: TanMedium
protected lateinit var atcEnteredCallback: (tan: String?, atc: Int?) -> Unit
open fun show(tanMedium: TanMedium, activity: AppCompatActivity,
fullscreen: Boolean = false, atcEnteredCallback: (tan: String?, atc: Int?) -> Unit) {
this.tanMedium = tanMedium
this.atcEnteredCallback = atcEnteredCallback
val style = if(fullscreen) R.style.FullscreenDialogWithStatusBar else R.style.Dialog
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_enter_atc, container, false)
setupUI(rootView)
return rootView
}
protected open fun setupUI(rootView: View) {
val explanationHtml = rootView.context.getString(R.string.dialog_enter_atc_explanation, tanMedium.displayName)
rootView.txtAtcExplanationToShowToUser.text = Html.fromHtml(explanationHtml, Html.FROM_HTML_MODE_LEGACY)
rootView.btnCancel.setOnClickListener { enteringAtcDone(null, null) }
rootView.btnEnteringAtcDone.setOnClickListener { enteringAtcDone(rootView.edtxtEnteredTan.text.toString(), rootView.edtxtEnteredAtc.text.toString()) }
}
protected open fun enteringAtcDone(enteredTan: String?, enteredAtcString: String?) {
var enteredAtc: Int? = null
if (enteredAtcString != null) {
try {
enteredAtc = enteredAtcString.toInt()
} catch (e: Exception) {
showEnteredAtcIsNotANumberError(enteredAtcString)
return
}
}
atcEnteredCallback(enteredTan, enteredAtc)
dismiss()
}
protected open fun showEnteredAtcIsNotANumberError(enteredAtcString: String) {
activity?.let { context ->
AlertDialog.Builder(context)
.setMessage(context.getString(R.string.dialog_enter_atc_error_entered_atc_is_not_a_number, enteredAtcString))
.setPositiveButton(android.R.string.ok) { dialog, _ -> dialog.dismiss() }
.show()
}
}
}

View File

@ -1,7 +1,9 @@
package net.dankito.banking.fints4java.android.ui.dialogs package net.dankito.banking.fints4java.android.ui.dialogs
import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.support.v4.app.DialogFragment import android.support.v4.app.DialogFragment
import android.support.v7.app.AlertDialog
import android.support.v7.app.AppCompatActivity import android.support.v7.app.AppCompatActivity
import android.text.InputType import android.text.InputType
import android.view.LayoutInflater import android.view.LayoutInflater
@ -9,11 +11,15 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
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.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.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.TanMediumStatus import net.dankito.banking.ui.model.TanMediumStatus
import net.dankito.fints.model.TanChallenge import net.dankito.fints.model.TanChallenge
import net.dankito.fints.model.TanProcedureType import net.dankito.fints.model.TanProcedureType
import net.dankito.fints.response.client.FinTsClientResponse
import net.dankito.fints.tan.FlickercodeDecoder import net.dankito.fints.tan.FlickercodeDecoder
@ -28,16 +34,19 @@ open class EnterTanDialog : DialogFragment() {
protected lateinit var tanChallenge: TanChallenge protected lateinit var tanChallenge: TanChallenge
protected lateinit var presenter: MainWindowPresenter
protected lateinit var tanEnteredCallback: (String?) -> Unit protected lateinit var tanEnteredCallback: (String?) -> Unit
protected val tanMediumAdapter = TanMediumAdapter() protected val tanMediumAdapter = TanMediumAdapter()
open fun show(account: Account, tanChallenge: TanChallenge, activity: AppCompatActivity, open fun show(account: Account, tanChallenge: TanChallenge, presenter: MainWindowPresenter, activity: AppCompatActivity,
fullscreen: Boolean = false, tanEnteredCallback: (String?) -> Unit) { fullscreen: Boolean = false, tanEnteredCallback: (String?) -> Unit) {
this.account = account this.account = account
this.tanChallenge = tanChallenge this.tanChallenge = tanChallenge
this.presenter = presenter
this.tanEnteredCallback = tanEnteredCallback this.tanEnteredCallback = tanEnteredCallback
val style = if(fullscreen) R.style.FullscreenDialogWithStatusBar else R.style.Dialog val style = if(fullscreen) R.style.FullscreenDialogWithStatusBar else R.style.Dialog
@ -60,9 +69,7 @@ open class EnterTanDialog : DialogFragment() {
if (tanChallenge.tanProcedure.type == TanProcedureType.ChipTanOptisch) { if (tanChallenge.tanProcedure.type == TanProcedureType.ChipTanOptisch) {
if (account.tanMedia.isNotEmpty()) { if (account.tanMedia.isNotEmpty()) {
rootView.lytTanMedium.visibility = View.VISIBLE setupSelectTanMediumView(rootView)
tanMediumAdapter.setItems(account.tanMedia.sortedByDescending { it.status == TanMediumStatus.Used })
rootView.spnTanMedium.adapter = tanMediumAdapter
} }
flickerCodeView.visibility = View.VISIBLE flickerCodeView.visibility = View.VISIBLE
@ -78,6 +85,48 @@ open class EnterTanDialog : DialogFragment() {
rootView.btnEnteringTanDone.setOnClickListener { enteringTanDone(rootView.edtxtEnteredTan.text.toString()) } rootView.btnEnteringTanDone.setOnClickListener { enteringTanDone(rootView.edtxtEnteredTan.text.toString()) }
} }
protected open fun setupSelectTanMediumView(rootView: View) {
rootView.lytTanMedium.visibility = View.VISIBLE
tanMediumAdapter.setItems(account.tanMedia.sortedByDescending { it.status == TanMediumStatus.Used })
rootView.spnTanMedium.adapter = tanMediumAdapter
rootView.spnTanMedium.onItemSelectedListener = ListItemSelectedListener(tanMediumAdapter) { selectedTanMedium ->
if (selectedTanMedium.status != TanMediumStatus.Used) {
presenter.changeTanMediumAsync(selectedTanMedium, account) { response ->
handleChangeTanMediumResponse(selectedTanMedium, response)
}
}
}
}
private fun handleChangeTanMediumResponse(newUsedTanMedium: TanMedium, response: FinTsClientResponse) {
activity?.let { activity ->
activity.runOnUiThread {
handleChangeTanMediumResponseOnUiThread(activity, newUsedTanMedium, response)
}
}
}
protected open fun handleChangeTanMediumResponseOnUiThread(context: Context, newUsedTanMedium: TanMedium, response: FinTsClientResponse) {
if (response.isSuccessful) {
dismiss()
AlertDialog.Builder(context)
.setMessage(context.getString(R.string.dialog_enter_tan_tan_medium_successfully_changed, newUsedTanMedium.displayName))
.setPositiveButton(android.R.string.ok) { dialog, _ -> dialog.dismiss() }
.show()
}
else {
AlertDialog.Builder(context)
.setMessage(context.getString(R.string.dialog_enter_tan_error_changing_tan_medium, newUsedTanMedium.displayName, presenter.getErrorToShowToUser(response)))
.setPositiveButton(android.R.string.ok) { dialog, _ -> dialog.dismiss() }
.show()
}
}
protected open fun enteringTanDone(enteredTan: String?) { protected open fun enteringTanDone(enteredTan: String?) {
tanEnteredCallback(enteredTan) tanEnteredCallback(enteredTan)

View File

@ -0,0 +1,15 @@
package net.dankito.banking.fints4java.android.ui.listener
import android.view.View
import android.widget.AdapterView
open class ItemSelectedListener(val itemSelected: (position: Int) -> Unit) : AdapterView.OnItemSelectedListener {
override fun onNothingSelected(parent: AdapterView<*>?) { }
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
itemSelected(position)
}
}

View File

@ -0,0 +1,16 @@
package net.dankito.banking.fints4java.android.ui.listener
import android.view.View
import android.widget.AdapterView
import net.dankito.utils.android.ui.adapter.ListAdapter
open class ListItemSelectedListener<T>(val adapter: ListAdapter<T>, val itemSelected: (item: T) -> Unit) : AdapterView.OnItemSelectedListener {
override fun onNothingSelected(parent: AdapterView<*>?) { }
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
itemSelected(adapter.getItem(position))
}
}

View File

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/dialog_enter_atc_padding"
>
<TextView
android:id="@+id/txtAtcExplanationToShowToUser"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="@dimen/dialog_enter_atc_enter_value_field_height"
android:layout_marginBottom="@dimen/dialog_enter_atc_enter_value_field_margin_bottom"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:text="@string/dialog_enter_atc_tan_label"
/>
<EditText
android:id="@+id/edtxtEnteredTan"
android:layout_width="@dimen/dialog_enter_atc_enter_value_field_value_width"
android:layout_height="match_parent"
android:layout_marginLeft="@dimen/dialog_enter_atc_enter_value_field_value_margin_left"
android:layout_marginStart="@dimen/dialog_enter_atc_enter_value_field_value_margin_left"
android:inputType="number"
/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="@dimen/dialog_enter_atc_enter_value_field_height"
android:layout_marginBottom="@dimen/dialog_enter_atc_enter_value_field_margin_bottom"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:text="@string/dialog_enter_atc_atc_label"
/>
<EditText
android:id="@+id/edtxtEnteredAtc"
android:layout_width="@dimen/dialog_enter_atc_enter_value_field_value_width"
android:layout_height="match_parent"
android:layout_marginLeft="@dimen/dialog_enter_atc_enter_value_field_value_margin_left"
android:layout_marginStart="@dimen/dialog_enter_atc_enter_value_field_value_margin_left"
android:inputType="number"
/>
</LinearLayout>
<RelativeLayout
android:id="@+id/lytButtonBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
>
<Button
android:id="@+id/btnEnteringAtcDone"
android:layout_width="@dimen/dialog_enter_atc_buttons_width"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
style="?android:attr/buttonBarButtonStyle"
android:text="@android:string/ok"
/>
<Button
android:id="@+id/btnCancel"
android:layout_width="@dimen/dialog_enter_atc_buttons_width"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/btnEnteringAtcDone"
android:layout_toStartOf="@+id/btnEnteringAtcDone"
style="?android:attr/buttonBarButtonStyle"
android:text="@string/cancel"
/>
</RelativeLayout>
</LinearLayout>

View File

@ -21,6 +21,8 @@
android:text="@string/dialog_enter_tan_select_tan_medium" android:text="@string/dialog_enter_tan_select_tan_medium"
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:textSize="@dimen/view_change_tan_medium_text_size"
/> />
<Spinner <Spinner
@ -28,6 +30,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
android:layout_gravity="center_vertical"
/> />
</LinearLayout> </LinearLayout>

View File

@ -2,9 +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/txtTanMediumDisplayName" android:id="@+id/txtTanMediumDisplayName"
style="@style/TextAppearance.AppCompat.Small"
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.Small"
android:textSize="@dimen/view_change_tan_medium_text_size"
android:singleLine="true"
android:ellipsize="marquee" android:ellipsize="marquee"
android:padding="@dimen/list_item_tan_medium_padding"
/> />

View File

@ -59,4 +59,15 @@
<dimen name="dialog_enter_tan_enter_tan_margin_bottom">8dp</dimen> <dimen name="dialog_enter_tan_enter_tan_margin_bottom">8dp</dimen>
<dimen name="dialog_enter_tan_buttons_width">120dp</dimen> <dimen name="dialog_enter_tan_buttons_width">120dp</dimen>
<dimen name="view_change_tan_medium_text_size">15sp</dimen>
<dimen name="list_item_tan_medium_padding">4dp</dimen>
<dimen name="dialog_enter_atc_padding">4dp</dimen>
<dimen name="dialog_enter_atc_enter_value_field_height">50dp</dimen>
<dimen name="dialog_enter_atc_enter_value_field_margin_bottom">8dp</dimen>
<dimen name="dialog_enter_atc_enter_value_field_value_width">110dp</dimen>
<dimen name="dialog_enter_atc_enter_value_field_value_margin_left">6dp</dimen>
<dimen name="dialog_enter_atc_buttons_width">120dp</dimen>
</resources> </resources>

View File

@ -60,5 +60,19 @@
<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_error_changing_tan_medium">Could not change TAN medium to \'%s\':\n%s.</string>
<!-- Removed <p></p> from last paragraph as otherwise TextView has some padding at the end -->
<string name="dialog_enter_atc_explanation"><![CDATA[
<p>Your bank asks you to synchronize your TAN generator.</p>
<p>Please insert the card \'%s\' into your TAN generator.</p>
<p>Then press the \'TAN\' button for a few seconds till \'aktiviert\' gets displayed.</p>
<p>Then either press the \'TAN\' button again or enter the start code \'103\', press the \'OK\' twice and then the \'\' button (depends on your model).</p>
Now the values for \'TAN\' and \'ATC\' should be displayed. Enter these two values below:
]]></string>
<string name="dialog_enter_atc_tan_label">TAN:</string>
<string name="dialog_enter_atc_atc_label">ATC:</string>
<string name="dialog_enter_atc_error_entered_atc_is_not_a_number">ATC has to be a number.\n\nBut entered ATC value \'%s\' cannot be converted to a number.</string>
</resources> </resources>