Implemented saving TAN settings like TAN image size and flicker code frequency
This commit is contained in:
parent
3072517eef
commit
e86b17d08b
|
@ -79,8 +79,8 @@ class BankingModule(private val applicationContext: Context) {
|
||||||
fun provideBankingPresenter(bankingClientCreator: IBankingClientCreator, bankFinder: IBankFinder,
|
fun provideBankingPresenter(bankingClientCreator: IBankingClientCreator, bankFinder: IBankFinder,
|
||||||
@Named(DatabaseFolderKey) databaseFolder: File, @Named(DataFolderKey) dataFolder: File,
|
@Named(DatabaseFolderKey) databaseFolder: File, @Named(DataFolderKey) dataFolder: File,
|
||||||
persister: IBankingPersistence, bankIconFinder: IBankIconFinder,
|
persister: IBankingPersistence, bankIconFinder: IBankIconFinder,
|
||||||
router: IRouter, threadPool: IThreadPool) : BankingPresenter {
|
router: IRouter, serializer: ISerializer, threadPool: IThreadPool) : BankingPresenter {
|
||||||
return BankingPresenter(bankingClientCreator, bankFinder, databaseFolder, dataFolder, persister, bankIconFinder, router, threadPool)
|
return BankingPresenter(bankingClientCreator, bankFinder, databaseFolder, dataFolder, persister, bankIconFinder, router, serializer, threadPool)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package net.dankito.banking.ui.android.dialogs
|
package net.dankito.banking.ui.android.dialogs
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.BitmapFactory
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.text.InputType
|
import android.text.InputType
|
||||||
|
@ -13,8 +12,9 @@ import android.widget.Spinner
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import kotlinx.android.synthetic.main.dialog_enter_tan.*
|
||||||
import kotlinx.android.synthetic.main.dialog_enter_tan.view.*
|
import kotlinx.android.synthetic.main.dialog_enter_tan.view.*
|
||||||
import kotlinx.android.synthetic.main.view_tan_image.view.*
|
import kotlinx.android.synthetic.main.dialog_enter_tan.view.flickerCodeView
|
||||||
import net.dankito.banking.ui.android.R
|
import net.dankito.banking.ui.android.R
|
||||||
import net.dankito.banking.ui.android.di.BankingComponent
|
import net.dankito.banking.ui.android.di.BankingComponent
|
||||||
import net.dankito.banking.ui.android.adapter.TanMediumAdapter
|
import net.dankito.banking.ui.android.adapter.TanMediumAdapter
|
||||||
|
@ -30,6 +30,8 @@ import javax.inject.Inject
|
||||||
open class EnterTanDialog : DialogFragment() {
|
open class EnterTanDialog : DialogFragment() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
val QrCodeTanProcedures = listOf(TanProcedureType.ChipTanQrCode, TanProcedureType.QrCode)
|
||||||
|
|
||||||
val OpticalTanProcedures = listOf(TanProcedureType.ChipTanFlickercode, TanProcedureType.ChipTanQrCode,
|
val OpticalTanProcedures = listOf(TanProcedureType.ChipTanFlickercode, TanProcedureType.ChipTanQrCode,
|
||||||
TanProcedureType.ChipTanPhotoTanMatrixCode, TanProcedureType.photoTan, TanProcedureType.QrCode)
|
TanProcedureType.ChipTanPhotoTanMatrixCode, TanProcedureType.photoTan, TanProcedureType.QrCode)
|
||||||
|
|
||||||
|
@ -146,7 +148,7 @@ open class EnterTanDialog : DialogFragment() {
|
||||||
|
|
||||||
val flickerCode = (tanChallenge as FlickerCodeTanChallenge).flickerCode
|
val flickerCode = (tanChallenge as FlickerCodeTanChallenge).flickerCode
|
||||||
if (flickerCode.decodingSuccessful) {
|
if (flickerCode.decodingSuccessful) {
|
||||||
flickerCodeView.setCode(flickerCode)
|
flickerCodeView.setCode(flickerCode, presenter.appSettings.flickerCodeSettings)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
showDecodingTanChallengeFailedErrorDelayed(flickerCode.decodingError)
|
showDecodingTanChallengeFailedErrorDelayed(flickerCode.decodingError)
|
||||||
|
@ -157,15 +159,14 @@ open class EnterTanDialog : DialogFragment() {
|
||||||
|
|
||||||
val decodedImage = (tanChallenge as ImageTanChallenge).image
|
val decodedImage = (tanChallenge as ImageTanChallenge).image
|
||||||
if (decodedImage.decodingSuccessful) {
|
if (decodedImage.decodingSuccessful) {
|
||||||
val bitmap = BitmapFactory.decodeByteArray(decodedImage.imageBytes, 0, decodedImage.imageBytes.size)
|
rootView.tanImageView.setImage(tanChallenge as ImageTanChallenge, if (isQrTan(tanChallenge)) presenter.appSettings.qrCodeSettings else presenter.appSettings.photoTanSettings)
|
||||||
rootView.imgTanImageView.setImageBitmap(bitmap)
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
showDecodingTanChallengeFailedErrorDelayed(decodedImage.decodingError)
|
showDecodingTanChallengeFailedErrorDelayed(decodedImage.decodingError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rootView.edtxtEnteredTan.inputType = InputType.TYPE_CLASS_NUMBER
|
rootView.edtxtEnteredTan.inputType = InputType.TYPE_CLASS_NUMBER // TODO: is this always true that TAN is a number?
|
||||||
|
|
||||||
rootView.edtxtEnteredTan.setOnKeyListener { _, keyCode, _ ->
|
rootView.edtxtEnteredTan.setOnKeyListener { _, keyCode, _ ->
|
||||||
if (keyCode == KeyEvent.KEYCODE_ENTER) {
|
if (keyCode == KeyEvent.KEYCODE_ENTER) {
|
||||||
|
@ -230,7 +231,33 @@ open class EnterTanDialog : DialogFragment() {
|
||||||
|
|
||||||
tanEnteredCallback(result)
|
tanEnteredCallback(result)
|
||||||
|
|
||||||
|
checkIfAppSettingsChanged()
|
||||||
|
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected open fun checkIfAppSettingsChanged() {
|
||||||
|
if (flickerCodeView.didTanProcedureSettingsChange) {
|
||||||
|
presenter.appSettings.flickerCodeSettings = flickerCodeView.tanProcedureSettings
|
||||||
|
|
||||||
|
presenter.appSettingsChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tanImageView.didTanProcedureSettingsChange) {
|
||||||
|
if (isQrTan(tanChallenge)) {
|
||||||
|
presenter.appSettings.qrCodeSettings = tanImageView.tanProcedureSettings
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
presenter.appSettings.photoTanSettings = tanImageView.tanProcedureSettings
|
||||||
|
}
|
||||||
|
|
||||||
|
presenter.appSettingsChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun isQrTan(tanChallenge: TanChallenge): Boolean {
|
||||||
|
return QrCodeTanProcedures.contains(tanChallenge.tanProcedure.type)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -12,21 +12,24 @@ import net.dankito.banking.ui.android.R
|
||||||
import net.dankito.banking.ui.model.tan.FlickerCode
|
import net.dankito.banking.ui.model.tan.FlickerCode
|
||||||
import net.dankito.banking.ui.util.FlickerCodeAnimator
|
import net.dankito.banking.ui.util.FlickerCodeAnimator
|
||||||
import net.dankito.banking.fints.tan.Bit
|
import net.dankito.banking.fints.tan.Bit
|
||||||
|
import net.dankito.banking.ui.model.settings.ITanView
|
||||||
|
import net.dankito.banking.ui.model.settings.TanProcedureSettings
|
||||||
import net.dankito.utils.android.extensions.asActivity
|
import net.dankito.utils.android.extensions.asActivity
|
||||||
|
|
||||||
|
|
||||||
open class ChipTanFlickerCodeView @JvmOverloads constructor(
|
open class ChipTanFlickerCodeView @JvmOverloads constructor(
|
||||||
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
|
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
|
||||||
) : LinearLayout(context, attrs, defStyleAttr) {
|
) : LinearLayout(context, attrs, defStyleAttr), ITanView {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val FrequencyStepSize = 2
|
const val FrequencyStepSize = 2
|
||||||
const val MinFrequency = 2
|
const val MinFrequency = 2
|
||||||
const val MaxFrequency = 40
|
const val MaxFrequency = 40
|
||||||
|
const val DefaultFrequency = 30
|
||||||
|
|
||||||
const val StripesHeightStepSize = 7
|
const val StripesHeightStepSize = 7
|
||||||
const val StripesWidthStepSize = 2
|
const val StripesWidthStepSize = 2
|
||||||
const val StripesRightMarginStepSize = 1
|
const val SpaceBetweenStripesStepSize = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,13 +51,20 @@ open class ChipTanFlickerCodeView @JvmOverloads constructor(
|
||||||
|
|
||||||
protected var stripesHeight = 360
|
protected var stripesHeight = 360
|
||||||
protected var stripesWidth = 120
|
protected var stripesWidth = 120
|
||||||
protected var stripesMarginRight = 30.0 // set back to 30
|
protected var spaceBetweenStripes = 30
|
||||||
|
|
||||||
protected var currentFrequency = 30
|
protected var currentFrequency = DefaultFrequency
|
||||||
|
|
||||||
protected var isFlickerCodePaused = false
|
protected var isFlickerCodePaused = false
|
||||||
|
|
||||||
|
|
||||||
|
override var didTanProcedureSettingsChange: Boolean = false
|
||||||
|
protected set
|
||||||
|
|
||||||
|
override var tanProcedureSettings: TanProcedureSettings? = null
|
||||||
|
protected set
|
||||||
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
setupUi(context)
|
setupUi(context)
|
||||||
}
|
}
|
||||||
|
@ -82,12 +92,17 @@ open class ChipTanFlickerCodeView @JvmOverloads constructor(
|
||||||
|
|
||||||
stripesHeight = stripe1.layoutParams.height
|
stripesHeight = stripe1.layoutParams.height
|
||||||
stripesWidth = stripe1.layoutParams.width
|
stripesWidth = stripe1.layoutParams.width
|
||||||
(stripe1.layoutParams as? MarginLayoutParams)?.let { stripesMarginRight = it.rightMargin.toDouble() }
|
(stripe1.layoutParams as? MarginLayoutParams)?.let { spaceBetweenStripes = it.rightMargin }
|
||||||
|
|
||||||
tanGeneratorLeftMarker = rootView.findViewById(R.id.tanGeneratorLeftMarker)
|
tanGeneratorLeftMarker = rootView.findViewById(R.id.tanGeneratorLeftMarker)
|
||||||
tanGeneratorRightMarker = rootView.findViewById(R.id.tanGeneratorRightMarker)
|
tanGeneratorRightMarker = rootView.findViewById(R.id.tanGeneratorRightMarker)
|
||||||
|
|
||||||
setMarkerPositionAfterStripesLayoutSet()
|
setMarkerPositionAfterStripesLayoutSet()
|
||||||
|
|
||||||
|
tanProcedureSettings?.let {
|
||||||
|
setSize(it.width, it.height, it.space)
|
||||||
|
setFrequency(it.frequency)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -100,22 +115,30 @@ open class ChipTanFlickerCodeView @JvmOverloads constructor(
|
||||||
|
|
||||||
|
|
||||||
open fun decreaseSize() {
|
open fun decreaseSize() {
|
||||||
stripesHeight -= StripesHeightStepSize
|
setSize(
|
||||||
stripesWidth -= StripesWidthStepSize
|
stripesWidth - StripesWidthStepSize,
|
||||||
stripesMarginRight -= StripesRightMarginStepSize
|
stripesHeight - StripesHeightStepSize,
|
||||||
|
spaceBetweenStripes - SpaceBetweenStripesStepSize
|
||||||
setWidth(context)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun increaseSize() {
|
open fun increaseSize() {
|
||||||
stripesHeight += StripesHeightStepSize
|
setSize(
|
||||||
stripesWidth += StripesWidthStepSize
|
stripesWidth + StripesWidthStepSize,
|
||||||
stripesMarginRight += StripesRightMarginStepSize
|
stripesHeight + StripesHeightStepSize,
|
||||||
|
spaceBetweenStripes + SpaceBetweenStripesStepSize
|
||||||
setWidth(context)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun setWidth(context: Context) {
|
open fun setSize(width: Int, height: Int, spaceBetweenStripes: Int) {
|
||||||
|
this.stripesWidth = width
|
||||||
|
this.stripesHeight = height
|
||||||
|
this.spaceBetweenStripes = spaceBetweenStripes
|
||||||
|
|
||||||
|
applySize()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun applySize() {
|
||||||
allStripes.forEach { stripe ->
|
allStripes.forEach { stripe ->
|
||||||
val params = stripe.layoutParams
|
val params = stripe.layoutParams
|
||||||
params.height = stripesHeight
|
params.height = stripesHeight
|
||||||
|
@ -123,7 +146,7 @@ open class ChipTanFlickerCodeView @JvmOverloads constructor(
|
||||||
|
|
||||||
(params as? MarginLayoutParams)?.let { marginParams ->
|
(params as? MarginLayoutParams)?.let { marginParams ->
|
||||||
if (marginParams.rightMargin > 0) { // don't set a margin right on fifth stripe
|
if (marginParams.rightMargin > 0) { // don't set a margin right on fifth stripe
|
||||||
marginParams.rightMargin = stripesMarginRight.toInt()
|
marginParams.rightMargin = spaceBetweenStripes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,6 +156,8 @@ open class ChipTanFlickerCodeView @JvmOverloads constructor(
|
||||||
requestLayout()
|
requestLayout()
|
||||||
|
|
||||||
setMarkerPositionAfterStripesLayoutSet()
|
setMarkerPositionAfterStripesLayoutSet()
|
||||||
|
|
||||||
|
tanProcedureSettingsChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun setMarkerPositionAfterStripesLayoutSet() {
|
protected open fun setMarkerPositionAfterStripesLayoutSet() {
|
||||||
|
@ -148,22 +173,28 @@ open class ChipTanFlickerCodeView @JvmOverloads constructor(
|
||||||
|
|
||||||
open fun decreaseFrequency() {
|
open fun decreaseFrequency() {
|
||||||
if (currentFrequency - FrequencyStepSize >= MinFrequency) {
|
if (currentFrequency - FrequencyStepSize >= MinFrequency) {
|
||||||
currentFrequency -= FrequencyStepSize
|
setFrequency(currentFrequency - FrequencyStepSize)
|
||||||
|
|
||||||
setFrequency(currentFrequency)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun increaseFrequency() {
|
open fun increaseFrequency() {
|
||||||
if (currentFrequency + FrequencyStepSize <= MaxFrequency) {
|
if (currentFrequency + FrequencyStepSize <= MaxFrequency) {
|
||||||
currentFrequency += FrequencyStepSize
|
setFrequency(currentFrequency + FrequencyStepSize)
|
||||||
|
|
||||||
setFrequency(currentFrequency)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun setFrequency(frequency: Int) {
|
open fun setFrequency(frequency: Int) {
|
||||||
|
currentFrequency = frequency
|
||||||
|
|
||||||
animator.setFrequency(frequency)
|
animator.setFrequency(frequency)
|
||||||
|
|
||||||
|
tanProcedureSettingsChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun tanProcedureSettingsChanged() {
|
||||||
|
tanProcedureSettings = TanProcedureSettings(stripesWidth, stripesHeight, spaceBetweenStripes, currentFrequency)
|
||||||
|
|
||||||
|
didTanProcedureSettingsChange = true // we don't check if settings really changed, it's not that important
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -181,10 +212,19 @@ open class ChipTanFlickerCodeView @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
open fun setCode(flickerCode: FlickerCode) {
|
open fun setCode(flickerCode: FlickerCode, tanProcedureSettings: TanProcedureSettings?) {
|
||||||
animator.stop()
|
animator.stop()
|
||||||
|
|
||||||
setFrequency(currentFrequency)
|
tanProcedureSettings?.let {
|
||||||
|
setSize(it.width, it.height, it.space)
|
||||||
|
setFrequency(it.frequency)
|
||||||
|
}
|
||||||
|
?: run {
|
||||||
|
setFrequency(DefaultFrequency)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tanProcedureSettings = tanProcedureSettings
|
||||||
|
this.didTanProcedureSettingsChange = false
|
||||||
|
|
||||||
animator.animateFlickerCode(flickerCode) { step ->
|
animator.animateFlickerCode(flickerCode) { step ->
|
||||||
context.asActivity()?.runOnUiThread {
|
context.asActivity()?.runOnUiThread {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package net.dankito.banking.ui.android.views
|
package net.dankito.banking.ui.android.views
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.graphics.BitmapFactory
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
|
@ -8,11 +9,14 @@ import android.widget.LinearLayout
|
||||||
import kotlinx.android.synthetic.main.view_tan_image.view.*
|
import kotlinx.android.synthetic.main.view_tan_image.view.*
|
||||||
import kotlinx.android.synthetic.main.view_tan_image_size_controls.view.*
|
import kotlinx.android.synthetic.main.view_tan_image_size_controls.view.*
|
||||||
import net.dankito.banking.ui.android.R
|
import net.dankito.banking.ui.android.R
|
||||||
|
import net.dankito.banking.ui.model.settings.ITanView
|
||||||
|
import net.dankito.banking.ui.model.settings.TanProcedureSettings
|
||||||
|
import net.dankito.banking.ui.model.tan.ImageTanChallenge
|
||||||
|
|
||||||
|
|
||||||
open class TanImageView @JvmOverloads constructor(
|
open class TanImageView @JvmOverloads constructor(
|
||||||
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
|
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
|
||||||
) : LinearLayout(context, attrs, defStyleAttr) {
|
) : LinearLayout(context, attrs, defStyleAttr), ITanView {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val ChangeSizeStepSizeDp = 10f
|
const val ChangeSizeStepSizeDp = 10f
|
||||||
|
@ -26,6 +30,13 @@ open class TanImageView @JvmOverloads constructor(
|
||||||
protected lateinit var imgTanImageView: ImageView
|
protected lateinit var imgTanImageView: ImageView
|
||||||
|
|
||||||
|
|
||||||
|
override var didTanProcedureSettingsChange: Boolean = false
|
||||||
|
protected set
|
||||||
|
|
||||||
|
override var tanProcedureSettings: TanProcedureSettings? = null
|
||||||
|
protected set
|
||||||
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
MinHeight = convertDpToPx(context, 150f).toInt()
|
MinHeight = convertDpToPx(context, 150f).toInt()
|
||||||
MaxHeight = convertDpToPx(context, 500f).toInt()
|
MaxHeight = convertDpToPx(context, 500f).toInt()
|
||||||
|
@ -44,6 +55,17 @@ open class TanImageView @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
open fun setImage(challenge: ImageTanChallenge, tanProcedureSettings: TanProcedureSettings?) {
|
||||||
|
val decodedImage = challenge.image
|
||||||
|
|
||||||
|
val bitmap = BitmapFactory.decodeByteArray(decodedImage.imageBytes, 0, decodedImage.imageBytes.size)
|
||||||
|
rootView.imgTanImageView.setImageBitmap(bitmap)
|
||||||
|
|
||||||
|
tanProcedureSettings?.let {
|
||||||
|
setWidthAndHeight(it.width)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
open fun decreaseSize() {
|
open fun decreaseSize() {
|
||||||
changeSizeBy(ChangeSizeStepSizeDp * -1)
|
changeSizeBy(ChangeSizeStepSizeDp * -1)
|
||||||
}
|
}
|
||||||
|
@ -56,16 +78,30 @@ open class TanImageView @JvmOverloads constructor(
|
||||||
val params = imgTanImageView.layoutParams
|
val params = imgTanImageView.layoutParams
|
||||||
val newWidthAndHeight = params.height + convertDpToPx(context, changeSizeBy).toInt()
|
val newWidthAndHeight = params.height + convertDpToPx(context, changeSizeBy).toInt()
|
||||||
|
|
||||||
|
setWidthAndHeight(newWidthAndHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun setWidthAndHeight(newWidthAndHeight: Int) {
|
||||||
if (newWidthAndHeight in MinHeight..MaxHeight) {
|
if (newWidthAndHeight in MinHeight..MaxHeight) {
|
||||||
|
val params = imgTanImageView.layoutParams
|
||||||
|
|
||||||
params.height = newWidthAndHeight
|
params.height = newWidthAndHeight
|
||||||
params.width = newWidthAndHeight
|
params.width = newWidthAndHeight
|
||||||
|
|
||||||
imgTanImageView.layoutParams = params // TODO: needed?
|
imgTanImageView.layoutParams = params // TODO: needed?
|
||||||
|
|
||||||
requestLayout()
|
requestLayout()
|
||||||
|
|
||||||
|
tanProcedureSettingsChanged(newWidthAndHeight)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected open fun tanProcedureSettingsChanged(newWidthAndHeight: Int) {
|
||||||
|
tanProcedureSettings = TanProcedureSettings(newWidthAndHeight, newWidthAndHeight)
|
||||||
|
|
||||||
|
didTanProcedureSettingsChange = true // we don't check if settings really changed, it's not that important
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method converts dp unit to equivalent pixels, depending on device density.
|
* This method converts dp unit to equivalent pixels, depending on device density.
|
||||||
*
|
*
|
||||||
|
|
|
@ -11,6 +11,7 @@ import net.dankito.banking.ui.model.Account
|
||||||
import net.dankito.banking.ui.model.responses.BankingClientResponse
|
import net.dankito.banking.ui.model.responses.BankingClientResponse
|
||||||
import net.dankito.banking.ui.model.tan.*
|
import net.dankito.banking.ui.model.tan.*
|
||||||
import net.dankito.banking.ui.presenter.BankingPresenter
|
import net.dankito.banking.ui.presenter.BankingPresenter
|
||||||
|
import net.dankito.utils.extensions.htmlToPlainText
|
||||||
import net.dankito.utils.javafx.ui.dialogs.Window
|
import net.dankito.utils.javafx.ui.dialogs.Window
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
|
|
||||||
|
@ -23,6 +24,8 @@ open class EnterTanDialog(
|
||||||
) : Window() {
|
) : Window() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
val QrCodeTanProcedures = listOf(TanProcedureType.ChipTanQrCode, TanProcedureType.QrCode)
|
||||||
|
|
||||||
private val ButtonHeight = 40.0
|
private val ButtonHeight = 40.0
|
||||||
private val ButtonWidth = 150.0
|
private val ButtonWidth = 150.0
|
||||||
}
|
}
|
||||||
|
@ -30,6 +33,10 @@ open class EnterTanDialog(
|
||||||
|
|
||||||
protected val dialogService = JavaFxDialogService()
|
protected val dialogService = JavaFxDialogService()
|
||||||
|
|
||||||
|
protected var flickerCodeView: ChipTanFlickerCodeView? = null
|
||||||
|
|
||||||
|
protected var tanImageView: TanImageView? = null
|
||||||
|
|
||||||
|
|
||||||
protected val tanProceduresWithoutUnsupported = account.supportedTanProcedures.filterNot { it.type == TanProcedureType.ChipTanUsb } // USB tan generators are not supported
|
protected val tanProceduresWithoutUnsupported = account.supportedTanProcedures.filterNot { it.type == TanProcedureType.ChipTanUsb } // USB tan generators are not supported
|
||||||
|
|
||||||
|
@ -93,7 +100,9 @@ open class EnterTanDialog(
|
||||||
marginBottom = 12.0
|
marginBottom = 12.0
|
||||||
}
|
}
|
||||||
|
|
||||||
add(ChipTanFlickerCodeView(flickerCode))
|
add(ChipTanFlickerCodeView(flickerCode, presenter.appSettings.flickerCodeSettings).apply {
|
||||||
|
flickerCodeView = this
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -104,7 +113,8 @@ open class EnterTanDialog(
|
||||||
(challenge as? ImageTanChallenge)?.let { imageTanChallenge ->
|
(challenge as? ImageTanChallenge)?.let { imageTanChallenge ->
|
||||||
val decodedImage = imageTanChallenge.image
|
val decodedImage = imageTanChallenge.image
|
||||||
if (decodedImage.decodingSuccessful) {
|
if (decodedImage.decodingSuccessful) {
|
||||||
add(TanImageView(decodedImage).apply {
|
add(TanImageView(decodedImage, if (isQrTan(challenge)) presenter.appSettings.qrCodeSettings else presenter.appSettings.photoTanSettings).apply {
|
||||||
|
tanImageView = this
|
||||||
|
|
||||||
vboxConstraints {
|
vboxConstraints {
|
||||||
marginLeftRight(30.0)
|
marginLeftRight(30.0)
|
||||||
|
@ -216,6 +226,8 @@ open class EnterTanDialog(
|
||||||
else {
|
else {
|
||||||
tanEnteredCallback(EnterTanResult.userEnteredTan(enteredTan.value))
|
tanEnteredCallback(EnterTanResult.userEnteredTan(enteredTan.value))
|
||||||
|
|
||||||
|
checkIfAppSettingsChanged()
|
||||||
|
|
||||||
close()
|
close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,4 +238,28 @@ open class EnterTanDialog(
|
||||||
close()
|
close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected open fun checkIfAppSettingsChanged() {
|
||||||
|
if (flickerCodeView?.didTanProcedureSettingsChange == true) {
|
||||||
|
presenter.appSettings.flickerCodeSettings = flickerCodeView?.tanProcedureSettings
|
||||||
|
|
||||||
|
presenter.appSettingsChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tanImageView?.didTanProcedureSettingsChange == true) {
|
||||||
|
if (isQrTan(challenge)) {
|
||||||
|
presenter.appSettings.qrCodeSettings = tanImageView?.tanProcedureSettings
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
presenter.appSettings.photoTanSettings = tanImageView?.tanProcedureSettings
|
||||||
|
}
|
||||||
|
|
||||||
|
presenter.appSettingsChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun isQrTan(tanChallenge: TanChallenge): Boolean {
|
||||||
|
return QrCodeTanProcedures.contains(tanChallenge.tanProcedure.type)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -9,13 +9,18 @@ import net.dankito.banking.ui.util.FlickerCodeAnimator
|
||||||
import net.dankito.banking.fints.tan.Bit
|
import net.dankito.banking.fints.tan.Bit
|
||||||
import net.dankito.banking.javafx.dialogs.tan.controls.ChipTanFlickerCodeStripeView
|
import net.dankito.banking.javafx.dialogs.tan.controls.ChipTanFlickerCodeStripeView
|
||||||
import net.dankito.banking.javafx.dialogs.tan.controls.TanGeneratorMarkerView
|
import net.dankito.banking.javafx.dialogs.tan.controls.TanGeneratorMarkerView
|
||||||
|
import net.dankito.banking.ui.model.settings.ITanView
|
||||||
|
import net.dankito.banking.ui.model.settings.TanProcedureSettings
|
||||||
import net.dankito.utils.javafx.ui.extensions.fixedHeight
|
import net.dankito.utils.javafx.ui.extensions.fixedHeight
|
||||||
import net.dankito.utils.javafx.ui.extensions.fixedWidth
|
import net.dankito.utils.javafx.ui.extensions.fixedWidth
|
||||||
import net.dankito.utils.javafx.ui.extensions.setBackgroundToColor
|
import net.dankito.utils.javafx.ui.extensions.setBackgroundToColor
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
|
|
||||||
|
|
||||||
open class ChipTanFlickerCodeView(protected val flickerCode: FlickerCode): View() {
|
open class ChipTanFlickerCodeView(
|
||||||
|
protected val flickerCode: FlickerCode,
|
||||||
|
tanProcedureSettings: TanProcedureSettings?
|
||||||
|
): View(), ITanView {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val ChangeSizeStripeHeightStep = 7.0
|
const val ChangeSizeStripeHeightStep = 7.0
|
||||||
|
@ -26,6 +31,7 @@ open class ChipTanFlickerCodeView(protected val flickerCode: FlickerCode): View(
|
||||||
const val MaxFlickerCodeViewWidth = 1000.0 // what is a senseful value?
|
const val MaxFlickerCodeViewWidth = 1000.0 // what is a senseful value?
|
||||||
|
|
||||||
const val ChangeFrequencyStep = 5
|
const val ChangeFrequencyStep = 5
|
||||||
|
const val DefaultFrequency = 30
|
||||||
|
|
||||||
const val IconWidth = 26.0
|
const val IconWidth = 26.0
|
||||||
const val IconHeight = 26.0
|
const val IconHeight = 26.0
|
||||||
|
@ -34,9 +40,9 @@ open class ChipTanFlickerCodeView(protected val flickerCode: FlickerCode): View(
|
||||||
|
|
||||||
protected val flickerCodeLeftRightMargin = SimpleDoubleProperty(31.0)
|
protected val flickerCodeLeftRightMargin = SimpleDoubleProperty(31.0)
|
||||||
|
|
||||||
protected val stripeHeight = SimpleDoubleProperty(127.0)
|
protected val stripesHeight = SimpleDoubleProperty(tanProcedureSettings?.height?.toDouble() ?: 127.0)
|
||||||
protected val stripeWidth = SimpleDoubleProperty(42.0)
|
protected val stripesWidth = SimpleDoubleProperty(tanProcedureSettings?.width?.toDouble() ?: 42.0)
|
||||||
protected val spaceBetweenStripes = SimpleDoubleProperty(10.0)
|
protected val spaceBetweenStripes = SimpleDoubleProperty(tanProcedureSettings?.space?.toDouble() ?: 10.0)
|
||||||
|
|
||||||
protected val flickerCodeViewWidth = SimpleDoubleProperty()
|
protected val flickerCodeViewWidth = SimpleDoubleProperty()
|
||||||
|
|
||||||
|
@ -52,15 +58,22 @@ open class ChipTanFlickerCodeView(protected val flickerCode: FlickerCode): View(
|
||||||
protected val isMinFrequencyReached = SimpleBooleanProperty(false)
|
protected val isMinFrequencyReached = SimpleBooleanProperty(false)
|
||||||
protected val isMaxFrequencyReached = SimpleBooleanProperty(false)
|
protected val isMaxFrequencyReached = SimpleBooleanProperty(false)
|
||||||
|
|
||||||
protected var currentFrequency = 20
|
protected var currentFrequency = tanProcedureSettings?.frequency ?: DefaultFrequency
|
||||||
|
|
||||||
protected val animator = FlickerCodeAnimator()
|
protected val animator = FlickerCodeAnimator()
|
||||||
|
|
||||||
|
|
||||||
init {
|
override var didTanProcedureSettingsChange: Boolean = false
|
||||||
flickerCodeViewWidth.bind(stripeWidth.add(spaceBetweenStripes).multiply(4).add(stripeWidth).add(flickerCodeLeftRightMargin).add(flickerCodeLeftRightMargin))
|
protected set
|
||||||
|
|
||||||
animator.setFrequency(currentFrequency)
|
override var tanProcedureSettings: TanProcedureSettings? = tanProcedureSettings
|
||||||
|
protected set
|
||||||
|
|
||||||
|
|
||||||
|
init {
|
||||||
|
flickerCodeViewWidth.bind(stripesWidth.add(spaceBetweenStripes).multiply(4).add(stripesWidth).add(flickerCodeLeftRightMargin).add(flickerCodeLeftRightMargin))
|
||||||
|
|
||||||
|
setFrequency(currentFrequency)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -122,13 +135,13 @@ open class ChipTanFlickerCodeView(protected val flickerCode: FlickerCode): View(
|
||||||
add(TanGeneratorMarkerView().apply {
|
add(TanGeneratorMarkerView().apply {
|
||||||
setLeftMarkerPosition(this)
|
setLeftMarkerPosition(this)
|
||||||
|
|
||||||
stripeWidth.addListener { _, _, _ -> setLeftMarkerPosition(this) }
|
stripesWidth.addListener { _, _, _ -> setLeftMarkerPosition(this) }
|
||||||
})
|
})
|
||||||
|
|
||||||
add(TanGeneratorMarkerView().apply {
|
add(TanGeneratorMarkerView().apply {
|
||||||
setRightMarkerPosition(this)
|
setRightMarkerPosition(this)
|
||||||
|
|
||||||
stripeWidth.addListener { _, _, _ -> setRightMarkerPosition(this) }
|
stripesWidth.addListener { _, _, _ -> setRightMarkerPosition(this) }
|
||||||
})
|
})
|
||||||
|
|
||||||
vboxConstraints {
|
vboxConstraints {
|
||||||
|
@ -139,11 +152,11 @@ open class ChipTanFlickerCodeView(protected val flickerCode: FlickerCode): View(
|
||||||
hbox {
|
hbox {
|
||||||
minHeight = 150.0
|
minHeight = 150.0
|
||||||
|
|
||||||
add(ChipTanFlickerCodeStripeView(stripe1, stripeWidth, stripeHeight, spaceBetweenStripes))
|
add(ChipTanFlickerCodeStripeView(stripe1, stripesWidth, stripesHeight, spaceBetweenStripes))
|
||||||
add(ChipTanFlickerCodeStripeView(stripe2, stripeWidth, stripeHeight, spaceBetweenStripes))
|
add(ChipTanFlickerCodeStripeView(stripe2, stripesWidth, stripesHeight, spaceBetweenStripes))
|
||||||
add(ChipTanFlickerCodeStripeView(stripe3, stripeWidth, stripeHeight, spaceBetweenStripes))
|
add(ChipTanFlickerCodeStripeView(stripe3, stripesWidth, stripesHeight, spaceBetweenStripes))
|
||||||
add(ChipTanFlickerCodeStripeView(stripe4, stripeWidth, stripeHeight, spaceBetweenStripes))
|
add(ChipTanFlickerCodeStripeView(stripe4, stripesWidth, stripesHeight, spaceBetweenStripes))
|
||||||
add(ChipTanFlickerCodeStripeView(stripe5, stripeWidth, stripeHeight, SimpleDoubleProperty(0.0)))
|
add(ChipTanFlickerCodeStripeView(stripe5, stripesWidth, stripesHeight, SimpleDoubleProperty(0.0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
vboxConstraints {
|
vboxConstraints {
|
||||||
|
@ -153,6 +166,10 @@ open class ChipTanFlickerCodeView(protected val flickerCode: FlickerCode): View(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
updateMinAndMaxSizeReached()
|
||||||
|
updateMinAndMaxFrequencyReached()
|
||||||
|
|
||||||
animator.animateFlickerCode(flickerCode) { step ->
|
animator.animateFlickerCode(flickerCode) { step ->
|
||||||
runLater {
|
runLater {
|
||||||
paintFlickerCode(step)
|
paintFlickerCode(step)
|
||||||
|
@ -171,22 +188,23 @@ open class ChipTanFlickerCodeView(protected val flickerCode: FlickerCode): View(
|
||||||
|
|
||||||
protected open fun setLeftMarkerPosition(component: UIComponent) {
|
protected open fun setLeftMarkerPosition(component: UIComponent) {
|
||||||
component.root.anchorpaneConstraints {
|
component.root.anchorpaneConstraints {
|
||||||
leftAnchor = (stripeWidth.value / 2)
|
leftAnchor = (stripesWidth.value / 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun setRightMarkerPosition(component: UIComponent) {
|
protected open fun setRightMarkerPosition(component: UIComponent) {
|
||||||
component.root.anchorpaneConstraints {
|
component.root.anchorpaneConstraints {
|
||||||
rightAnchor = (stripeWidth.value / 2)
|
rightAnchor = (stripesWidth.value / 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected open fun increaseSize() {
|
protected open fun increaseSize() {
|
||||||
if (isMaxSizeReached.value == false) {
|
if (isMaxSizeReached.value == false) {
|
||||||
stripeHeight.value = stripeHeight.value + ChangeSizeStripeHeightStep
|
setSize(stripesWidth.value + ChangeSizeStripeWidthStep, stripesHeight.value + ChangeSizeStripeHeightStep,
|
||||||
stripeWidth.value = stripeWidth.value + ChangeSizeStripeWidthStep
|
spaceBetweenStripes.value + ChangeSizeSpaceBetweenStripesStep)
|
||||||
spaceBetweenStripes.value = spaceBetweenStripes.value + ChangeSizeSpaceBetweenStripesStep
|
|
||||||
|
tanProcedureSettingsChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
updateMinAndMaxSizeReached()
|
updateMinAndMaxSizeReached()
|
||||||
|
@ -194,16 +212,27 @@ open class ChipTanFlickerCodeView(protected val flickerCode: FlickerCode): View(
|
||||||
|
|
||||||
protected open fun decreaseSize() {
|
protected open fun decreaseSize() {
|
||||||
if (isMinSizeReached.value == false) {
|
if (isMinSizeReached.value == false) {
|
||||||
stripeHeight.value = stripeHeight.value - ChangeSizeStripeHeightStep
|
setSize(stripesWidth.value - ChangeSizeStripeWidthStep, stripesHeight.value - ChangeSizeStripeHeightStep,
|
||||||
stripeWidth.value = stripeWidth.value - ChangeSizeStripeWidthStep
|
spaceBetweenStripes.value - ChangeSizeSpaceBetweenStripesStep)
|
||||||
spaceBetweenStripes.value = spaceBetweenStripes.value - ChangeSizeSpaceBetweenStripesStep
|
|
||||||
|
tanProcedureSettingsChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
updateMinAndMaxSizeReached()
|
updateMinAndMaxSizeReached()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open fun setSize(width: Double, height: Double, spaceBetweenStripes: Double) {
|
||||||
|
this.stripesWidth.value = width
|
||||||
|
this.stripesHeight.value = height
|
||||||
|
this.spaceBetweenStripes.value = spaceBetweenStripes
|
||||||
|
|
||||||
|
tanProcedureSettingsChanged()
|
||||||
|
|
||||||
|
updateMinAndMaxSizeReached()
|
||||||
|
}
|
||||||
|
|
||||||
protected open fun updateMinAndMaxSizeReached() {
|
protected open fun updateMinAndMaxSizeReached() {
|
||||||
val flickerCodeWidth = stripeWidth.value * 5 + spaceBetweenStripes.value * 4
|
val flickerCodeWidth = stripesWidth.value * 5 + spaceBetweenStripes.value * 4
|
||||||
|
|
||||||
isMinSizeReached.value = flickerCodeWidth < MinFlickerCodeViewWidth
|
isMinSizeReached.value = flickerCodeWidth < MinFlickerCodeViewWidth
|
||||||
isMaxSizeReached.value = flickerCodeWidth > MaxFlickerCodeViewWidth
|
isMaxSizeReached.value = flickerCodeWidth > MaxFlickerCodeViewWidth
|
||||||
|
@ -213,8 +242,7 @@ open class ChipTanFlickerCodeView(protected val flickerCode: FlickerCode): View(
|
||||||
if (isMaxFrequencyReached.value == false
|
if (isMaxFrequencyReached.value == false
|
||||||
&& (currentFrequency + ChangeFrequencyStep) <= FlickerCodeAnimator.MaxFrequency) {
|
&& (currentFrequency + ChangeFrequencyStep) <= FlickerCodeAnimator.MaxFrequency) {
|
||||||
|
|
||||||
currentFrequency += ChangeFrequencyStep
|
setFrequency(currentFrequency + ChangeFrequencyStep)
|
||||||
animator.setFrequency(currentFrequency)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateMinAndMaxFrequencyReached()
|
updateMinAndMaxFrequencyReached()
|
||||||
|
@ -224,16 +252,33 @@ open class ChipTanFlickerCodeView(protected val flickerCode: FlickerCode): View(
|
||||||
if (isMinFrequencyReached.value == false
|
if (isMinFrequencyReached.value == false
|
||||||
&& (currentFrequency - ChangeFrequencyStep) >= FlickerCodeAnimator.MinFrequency) {
|
&& (currentFrequency - ChangeFrequencyStep) >= FlickerCodeAnimator.MinFrequency) {
|
||||||
|
|
||||||
currentFrequency -= ChangeFrequencyStep
|
setFrequency(currentFrequency - ChangeFrequencyStep)
|
||||||
animator.setFrequency(currentFrequency)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateMinAndMaxFrequencyReached()
|
updateMinAndMaxFrequencyReached()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected open fun setFrequency(frequency: Int) {
|
||||||
|
currentFrequency = frequency
|
||||||
|
|
||||||
|
animator.setFrequency(currentFrequency)
|
||||||
|
|
||||||
|
updateMinAndMaxFrequencyReached()
|
||||||
|
|
||||||
|
tanProcedureSettingsChanged()
|
||||||
|
}
|
||||||
|
|
||||||
protected open fun updateMinAndMaxFrequencyReached() {
|
protected open fun updateMinAndMaxFrequencyReached() {
|
||||||
isMaxFrequencyReached.value = (currentFrequency + ChangeFrequencyStep) > FlickerCodeAnimator.MaxFrequency
|
isMaxFrequencyReached.value = (currentFrequency + ChangeFrequencyStep) > FlickerCodeAnimator.MaxFrequency
|
||||||
isMinFrequencyReached.value = (currentFrequency - ChangeFrequencyStep) < FlickerCodeAnimator.MinFrequency
|
isMinFrequencyReached.value = (currentFrequency - ChangeFrequencyStep) < FlickerCodeAnimator.MinFrequency
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected open fun tanProcedureSettingsChanged() {
|
||||||
|
tanProcedureSettings = TanProcedureSettings(stripesWidth.value.toInt(), stripesHeight.value.toInt(),
|
||||||
|
spaceBetweenStripes.value.toInt(), currentFrequency)
|
||||||
|
|
||||||
|
didTanProcedureSettingsChange = true // we don't check if settings really changed, it's not that important
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -4,13 +4,18 @@ import javafx.beans.property.SimpleBooleanProperty
|
||||||
import javafx.geometry.Pos
|
import javafx.geometry.Pos
|
||||||
import javafx.scene.image.Image
|
import javafx.scene.image.Image
|
||||||
import javafx.scene.image.ImageView
|
import javafx.scene.image.ImageView
|
||||||
|
import net.dankito.banking.ui.model.settings.ITanView
|
||||||
|
import net.dankito.banking.ui.model.settings.TanProcedureSettings
|
||||||
import net.dankito.banking.ui.model.tan.TanImage
|
import net.dankito.banking.ui.model.tan.TanImage
|
||||||
import net.dankito.utils.javafx.ui.extensions.updateWindowSize
|
import net.dankito.utils.javafx.ui.extensions.updateWindowSize
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
|
|
||||||
|
|
||||||
open class TanImageView(protected val tanImage: TanImage) : View() {
|
open class TanImageView(
|
||||||
|
protected val tanImage: TanImage,
|
||||||
|
tanProcedureSettings: TanProcedureSettings?
|
||||||
|
) : View(), ITanView {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val ChangeSizeStepSize = 10.0
|
private const val ChangeSizeStepSize = 10.0
|
||||||
|
@ -29,6 +34,13 @@ open class TanImageView(protected val tanImage: TanImage) : View() {
|
||||||
protected var tanImageView: ImageView by singleAssign()
|
protected var tanImageView: ImageView by singleAssign()
|
||||||
|
|
||||||
|
|
||||||
|
override var didTanProcedureSettingsChange: Boolean = false
|
||||||
|
protected set
|
||||||
|
|
||||||
|
override var tanProcedureSettings: TanProcedureSettings? = tanProcedureSettings
|
||||||
|
protected set
|
||||||
|
|
||||||
|
|
||||||
override val root = vbox {
|
override val root = vbox {
|
||||||
add(TanImageSizeView(IconHeight, IconWidth, isMinSizeReached, isMaxSizeReached, { decreaseSize() }, { increaseSize() } ))
|
add(TanImageSizeView(IconHeight, IconWidth, isMinSizeReached, isMaxSizeReached, { decreaseSize() }, { increaseSize() } ))
|
||||||
|
|
||||||
|
@ -45,6 +57,12 @@ open class TanImageView(protected val tanImage: TanImage) : View() {
|
||||||
marginBottom = 4.0
|
marginBottom = 4.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tanProcedureSettings?.let {
|
||||||
|
runLater {
|
||||||
|
setWidthAndHeight(it.width.toDouble())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,14 +77,26 @@ open class TanImageView(protected val tanImage: TanImage) : View() {
|
||||||
protected open fun changeSizeBy(changeSizeBy: Double) {
|
protected open fun changeSizeBy(changeSizeBy: Double) {
|
||||||
val newWidthAndHeight = tanImageView.fitHeight + changeSizeBy
|
val newWidthAndHeight = tanImageView.fitHeight + changeSizeBy
|
||||||
|
|
||||||
|
setWidthAndHeight(newWidthAndHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun setWidthAndHeight(newWidthAndHeight: Double) {
|
||||||
if (newWidthAndHeight in MinHeight..MaxHeight) {
|
if (newWidthAndHeight in MinHeight..MaxHeight) {
|
||||||
tanImageView.fitHeight = newWidthAndHeight
|
tanImageView.fitHeight = newWidthAndHeight
|
||||||
|
|
||||||
updateWindowSize()
|
updateWindowSize()
|
||||||
|
|
||||||
|
tanProcedureSettingsChanged(newWidthAndHeight.toInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
isMinSizeReached.value = tanImageView.fitHeight <= MinHeight
|
isMinSizeReached.value = tanImageView.fitHeight <= MinHeight
|
||||||
isMaxSizeReached.value = tanImageView.fitHeight >= MaxHeight
|
isMaxSizeReached.value = tanImageView.fitHeight >= MaxHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected open fun tanProcedureSettingsChanged(newWidthAndHeight: Int) {
|
||||||
|
tanProcedureSettings = TanProcedureSettings(newWidthAndHeight, newWidthAndHeight)
|
||||||
|
|
||||||
|
didTanProcedureSettingsChange = true // we don't check if settings really changed, it's not that important
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package net.dankito.banking.ui.model.settings
|
||||||
|
|
||||||
|
|
||||||
|
open class AppSettings(
|
||||||
|
var flickerCodeSettings: TanProcedureSettings? = null,
|
||||||
|
var qrCodeSettings: TanProcedureSettings? = null,
|
||||||
|
var photoTanSettings: TanProcedureSettings? = null
|
||||||
|
) {
|
||||||
|
|
||||||
|
internal constructor() : this(null, null, null) // for object deserializers
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package net.dankito.banking.ui.model.settings
|
||||||
|
|
||||||
|
|
||||||
|
interface ITanView {
|
||||||
|
|
||||||
|
val didTanProcedureSettingsChange: Boolean
|
||||||
|
|
||||||
|
val tanProcedureSettings: TanProcedureSettings?
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package net.dankito.banking.ui.model.settings
|
||||||
|
|
||||||
|
|
||||||
|
open class TanProcedureSettings(
|
||||||
|
var width: Int,
|
||||||
|
var height: Int,
|
||||||
|
var space: Int = -1, // only needed for flicker code view
|
||||||
|
var frequency: Int = -1 // only needed for flicker code view
|
||||||
|
) {
|
||||||
|
|
||||||
|
internal constructor() : this(0, 0) // for object deserializers
|
||||||
|
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "Size $width x $height, frequency $frequency"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -17,10 +17,13 @@ import net.dankito.banking.ui.model.tan.TanGeneratorTanMedium
|
||||||
import net.dankito.banking.util.IBankIconFinder
|
import net.dankito.banking.util.IBankIconFinder
|
||||||
import net.dankito.banking.fints.banks.IBankFinder
|
import net.dankito.banking.fints.banks.IBankFinder
|
||||||
import net.dankito.banking.fints.model.BankInfo
|
import net.dankito.banking.fints.model.BankInfo
|
||||||
|
import net.dankito.banking.ui.model.settings.AppSettings
|
||||||
import net.dankito.utils.IThreadPool
|
import net.dankito.utils.IThreadPool
|
||||||
import net.dankito.utils.ThreadPool
|
import net.dankito.utils.ThreadPool
|
||||||
import net.dankito.utils.extensions.containsExactly
|
import net.dankito.utils.extensions.containsExactly
|
||||||
import net.dankito.utils.extensions.ofMaxLength
|
import net.dankito.utils.extensions.ofMaxLength
|
||||||
|
import net.dankito.utils.serialization.ISerializer
|
||||||
|
import net.dankito.utils.serialization.JacksonJsonSerializer
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
|
@ -39,6 +42,7 @@ open class BankingPresenter(
|
||||||
protected val persister: IBankingPersistence,
|
protected val persister: IBankingPersistence,
|
||||||
protected val bankIconFinder: IBankIconFinder,
|
protected val bankIconFinder: IBankIconFinder,
|
||||||
protected val router: IRouter,
|
protected val router: IRouter,
|
||||||
|
protected val serializer: ISerializer = JacksonJsonSerializer(),
|
||||||
protected val threadPool: IThreadPool = ThreadPool()
|
protected val threadPool: IThreadPool = ThreadPool()
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
@ -93,6 +97,7 @@ open class BankingPresenter(
|
||||||
|
|
||||||
init {
|
init {
|
||||||
threadPool.runAsync {
|
threadPool.runAsync {
|
||||||
|
readAppSettings()
|
||||||
readPersistedAccounts()
|
readPersistedAccounts()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -543,6 +548,36 @@ open class BankingPresenter(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var appSettings: AppSettings = AppSettings()
|
||||||
|
protected set
|
||||||
|
|
||||||
|
open fun appSettingsChanged() {
|
||||||
|
persistAppSettings()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun persistAppSettings() {
|
||||||
|
try {
|
||||||
|
serializer.serializeObject(appSettings, getAppSettingsFile())
|
||||||
|
} catch (e: Exception) {
|
||||||
|
log.error("Could not persist AppSettings to file ${getAppSettingsFile()}", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun readAppSettings() {
|
||||||
|
try {
|
||||||
|
serializer.deserializeObject(getAppSettingsFile(), AppSettings::class.java)?.let {
|
||||||
|
appSettings = it
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
log.error("Could not read AppSettings from file ${getAppSettingsFile()}", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun getAppSettingsFile(): File {
|
||||||
|
return File(dataFolder, "app_settings.json")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
open fun addAccountsChangedListener(listener: (List<Account>) -> Unit): Boolean {
|
open fun addAccountsChangedListener(listener: (List<Account>) -> Unit): Boolean {
|
||||||
return accountsChangedListeners.add(listener)
|
return accountsChangedListeners.add(listener)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue