Implemented autocomplete list for potential remittees in TransferMoneyDialog

This commit is contained in:
dankito 2020-06-04 13:48:40 +02:00
parent c7845ca779
commit d1bb7d81c3
12 changed files with 105 additions and 21 deletions

View File

@ -16,7 +16,7 @@ compileTestKotlin {
dependencies {
implementation project(":BankingUiCommon")
implementation project(":BankingPersistenceJson")
api project(":BankingPersistenceJson")
implementation "net.dankito.search:lucene-4-utils:$luceneUtilsVersion"

View File

@ -5,12 +5,11 @@ import androidx.recyclerview.widget.RecyclerView
import com.otaliastudios.autocomplete.RecyclerViewPresenter
import kotlinx.coroutines.*
import net.dankito.banking.ui.android.adapter.RemitteeListAdapter
import net.dankito.banking.search.IRemitteeSearcher
import net.dankito.banking.search.Remittee
import net.dankito.utils.Stopwatch
import net.dankito.banking.ui.presenter.BankingPresenter
open class RemitteePresenter(protected val remitteeSearcher: IRemitteeSearcher, context: Context) : RecyclerViewPresenter<Remittee>(context) {
open class RemitteePresenter(protected val bankingPresenter: BankingPresenter, context: Context) : RecyclerViewPresenter<Remittee>(context) {
protected val adapter = RemitteeListAdapter { dispatchClick(it) }
@ -25,7 +24,7 @@ open class RemitteePresenter(protected val remitteeSearcher: IRemitteeSearcher,
lastSearchRemitteeJob?.cancel()
lastSearchRemitteeJob = GlobalScope.launch(Dispatchers.IO) {
val potentialRemittees = Stopwatch.logDuration("findRemittees()") { remitteeSearcher.findRemittees(query?.toString() ?: "") }
val potentialRemittees = bankingPresenter.findRemitteesForName(query?.toString() ?: "")
withContext(Dispatchers.Main) {
adapter.items = potentialRemittees

View File

@ -78,9 +78,10 @@ class BankingModule(private val applicationContext: Context) {
@Singleton
fun provideBankingPresenter(bankingClientCreator: IBankingClientCreator, bankFinder: IBankFinder,
@Named(DatabaseFolderKey) databaseFolder: File, @Named(DataFolderKey) dataFolder: File,
persister: IBankingPersistence, bankIconFinder: IBankIconFinder,
persister: IBankingPersistence, bankIconFinder: IBankIconFinder, remitteeSearcher: IRemitteeSearcher,
router: IRouter, serializer: ISerializer, threadPool: IThreadPool) : BankingPresenter {
return BankingPresenter(bankingClientCreator, bankFinder, databaseFolder, dataFolder, persister, bankIconFinder, router, serializer, threadPool)
return BankingPresenter(bankingClientCreator, bankFinder, databaseFolder, dataFolder, persister,
remitteeSearcher, bankIconFinder, router, serializer, threadPool)
}
@Provides

View File

@ -60,9 +60,6 @@ open class TransferMoneyDialog : DialogFragment() {
@Inject
protected lateinit var presenter: BankingPresenter
@Inject
protected lateinit var remitteeSearcher: IRemitteeSearcher
init {
BankingComponent.component.inject(this)
@ -181,7 +178,7 @@ open class TransferMoneyDialog : DialogFragment() {
.with(6f)
.with(ColorDrawable(Color.WHITE))
.with(autocompleteCallback)
.with(RemitteePresenter(remitteeSearcher, edtxtRemitteeName.context))
.with(RemitteePresenter(presenter, edtxtRemitteeName.context))
.build()
.closePopupOnBackButtonPress(dialog)
}

View File

@ -24,7 +24,7 @@ dependencies {
implementation project(':fints4kBankingClient')
implementation project(':hbci4jBankingClient')
implementation project(':BankingPersistenceJson')
implementation project(':LuceneBankingPersistence')
implementation "ch.qos.logback:logback-classic:$logbackVersion"
}

View File

@ -2,7 +2,6 @@ package net.dankito.banking.ui.javafx.dialogs.mainwindow
import javafx.scene.control.SplitPane
import net.dankito.banking.fints4kBankingClientCreator
import net.dankito.banking.persistence.BankingPersistenceJson
import net.dankito.banking.ui.javafx.RouterJavaFx
import net.dankito.banking.ui.javafx.controls.AccountTransactionsView
import net.dankito.banking.ui.javafx.controls.AccountsView
@ -11,6 +10,8 @@ import net.dankito.banking.ui.javafx.util.Base64ServiceJava8
import net.dankito.banking.ui.presenter.BankingPresenter
import net.dankito.banking.util.BankIconFinder
import net.dankito.banking.fints.banks.LuceneBankFinder
import net.dankito.banking.persistence.LuceneBankingPersistence
import net.dankito.banking.search.LuceneRemitteeSearcher
import net.dankito.utils.web.client.OkHttpWebClient
import tornadofx.*
import tornadofx.FX.Companion.messages
@ -26,9 +27,10 @@ class MainWindow : View(messages["application.title"]) {
private val indexFolder = File(dataFolder, "index")
private val presenter = BankingPresenter(fints4kBankingClientCreator(OkHttpWebClient(), Base64ServiceJava8()),
LuceneBankFinder(indexFolder), databaseFolder, dataFolder, BankingPersistenceJson(File(databaseFolder, "accounts.json")), BankIconFinder(), RouterJavaFx())
LuceneBankFinder(indexFolder), databaseFolder, dataFolder, LuceneBankingPersistence(indexFolder, databaseFolder),
LuceneRemitteeSearcher(indexFolder), BankIconFinder(), RouterJavaFx())
// private val presenter = BankingPresenter(hbci4jBankingClientCreator(), LuceneBankFinder(indexFolder), databaseFolder,
// dataFolder, BankingPersistenceJson(File(databaseFolder, "accounts.json")), BankIconFinder(), RouterJavaFx())
// dataFolder, LuceneBankingPersistence(indexFolder, databaseFolder), LuceneRemitteeSearcher(indexFolder), BankIconFinder(), RouterJavaFx())

View File

@ -17,6 +17,7 @@ import net.dankito.banking.ui.model.responses.AddAccountResponse
import net.dankito.banking.ui.presenter.BankingPresenter
import net.dankito.banking.fints.model.BankInfo
import net.dankito.banking.ui.javafx.dialogs.addaccount.BankInfoListCellFragment
import net.dankito.banking.ui.javafx.extensions.focusNextControl
import net.dankito.utils.javafx.ui.controls.AutoCompletionSearchTextField
import net.dankito.utils.javafx.ui.controls.ProcessingIndicatorButton
import net.dankito.utils.javafx.ui.controls.autocompletionsearchtextfield
@ -209,7 +210,7 @@ open class AddAccountDialog(protected val presenter: BankingPresenter) : Window(
}
protected open fun bankSelected(bank: BankInfo) {
unfocusBankCodeTextField()
txtfldBankCode.focusNextControl()
selectedBank = bank
@ -222,10 +223,6 @@ open class AddAccountDialog(protected val presenter: BankingPresenter) : Window(
}
}
protected open fun unfocusBankCodeTextField() {
txtfldBankCode.impl_traverse(Direction.NEXT)
}
protected open fun showBankDoesNotSupportFinTs30ErrorMessage(bank: BankInfo) {
val errorMessage = String.format(messages["add.account.dialog.error.bank.does.not.support.fints.3.error.message"], bank.name)

View File

@ -0,0 +1,21 @@
package net.dankito.banking.ui.javafx.dialogs.cashtransfer
import net.dankito.banking.search.Remittee
import tornadofx.ListCellFragment
import tornadofx.bindTo
import tornadofx.label
import tornadofx.vbox
open class RemitteeListCellFragment : ListCellFragment<Remittee>() {
open val remittee = RemitteeViewModel().bindTo(this)
override val root = vbox {
label(remittee.name)
label(remittee.iban)
}
}

View File

@ -0,0 +1,14 @@
package net.dankito.banking.ui.javafx.dialogs.cashtransfer
import javafx.beans.property.SimpleStringProperty
import net.dankito.banking.search.Remittee
import tornadofx.ItemViewModel
open class RemitteeViewModel : ItemViewModel<Remittee>() {
val name = bind { SimpleStringProperty(item?.name) }
val iban = bind { SimpleStringProperty(item?.iban) }
}

View File

@ -10,6 +10,7 @@ import javafx.geometry.Pos
import javafx.scene.control.ContentDisplay
import javafx.scene.image.ImageView
import javafx.scene.layout.Priority
import kotlinx.coroutines.*
import net.dankito.banking.ui.javafx.dialogs.JavaFxDialogService
import net.dankito.banking.ui.model.BankAccount
import net.dankito.banking.ui.model.parameters.TransferMoneyData
@ -17,6 +18,10 @@ import net.dankito.banking.ui.model.responses.BankingClientResponse
import net.dankito.banking.ui.presenter.BankingPresenter
import net.dankito.banking.util.InputValidator
import net.dankito.banking.fints.model.BankInfo
import net.dankito.banking.search.Remittee
import net.dankito.banking.ui.javafx.extensions.focusNextControl
import net.dankito.utils.javafx.ui.controls.AutoCompletionSearchTextField
import net.dankito.utils.javafx.ui.controls.autocompletionsearchtextfield
import net.dankito.utils.javafx.ui.controls.doubleTextfield
import net.dankito.utils.javafx.ui.dialogs.Window
import net.dankito.utils.javafx.ui.extensions.ensureOnlyUsesSpaceIfVisible
@ -69,6 +74,11 @@ open class TransferMoneyDialog @JvmOverloads constructor(
protected val requiredDataEntered = SimpleBooleanProperty(false)
protected var txtfldRemitteeName: AutoCompletionSearchTextField<Remittee> by singleAssign()
protected var lastSearchRemitteeJob: Job? = null
protected val inputValidator = InputValidator()
protected val dialogService = JavaFxDialogService()
@ -124,8 +134,13 @@ open class TransferMoneyDialog @JvmOverloads constructor(
field(messages["transfer.money.dialog.remittee.name.label"]) {
fixedHeight = FieldHeight
textfield(this@TransferMoneyDialog.remitteeName) {
txtfldRemitteeName = autocompletionsearchtextfield(this@TransferMoneyDialog.remitteeName) {
fixedHeight = TextFieldHeight
textProperty().addListener { _, _, newValue -> searchRemittees(newValue) }
onAutoCompletion = { remitteeSelected(it) }
listCellFragment = RemitteeListCellFragment::class
}
}
@ -259,6 +274,28 @@ open class TransferMoneyDialog @JvmOverloads constructor(
}
}
protected open fun searchRemittees(query: String?) {
lastSearchRemitteeJob?.cancel()
lastSearchRemitteeJob = GlobalScope.launch(Dispatchers.IO) {
val potentialRemittees = presenter.findRemitteesForName(query?.toString() ?: "")
withContext(Dispatchers.Main) {
txtfldRemitteeName.setAutoCompleteList(potentialRemittees)
}
}
}
protected open fun remitteeSelected(remittee: Remittee) {
txtfldRemitteeName.focusNextControl()
remitteeName.value = remittee.name
remitteeBic.value = remittee.bic
remitteeIban.value = remittee.iban
}
protected open fun tryToGetBicFromIban(enteredIban: String) {
presenter.findUniqueBankForIbanAsync(enteredIban) { foundBank ->
runLater {

View File

@ -0,0 +1,9 @@
package net.dankito.banking.ui.javafx.extensions
import com.sun.javafx.scene.traversal.Direction
import javafx.scene.control.TextField
fun TextField.focusNextControl() {
this.impl_traverse(Direction.NEXT)
}

View File

@ -17,6 +17,8 @@ import net.dankito.banking.ui.model.tan.TanGeneratorTanMedium
import net.dankito.banking.util.IBankIconFinder
import net.dankito.banking.fints.banks.IBankFinder
import net.dankito.banking.fints.model.BankInfo
import net.dankito.banking.search.IRemitteeSearcher
import net.dankito.banking.search.Remittee
import net.dankito.banking.ui.model.parameters.GetTransactionsParameter
import net.dankito.banking.ui.model.settings.AppSettings
import net.dankito.utils.IThreadPool
@ -41,6 +43,7 @@ open class BankingPresenter(
protected val databaseFolder: File,
protected val dataFolder: File,
protected val persister: IBankingPersistence,
protected val remitteeSearcher: IRemitteeSearcher,
protected val bankIconFinder: IBankIconFinder,
protected val router: IRouter,
protected val serializer: ISerializer = JacksonJsonSerializer(),
@ -410,6 +413,10 @@ open class BankingPresenter(
return bankFinder.findBankByNameBankCodeOrCity(query)
}
open fun findRemitteesForName(name: String): List<Remittee> {
return remitteeSearcher.findRemittees(name)
}
open fun searchSelectedAccountTransactions(query: String): List<AccountTransaction> {
val queryLowercase = query.trim().toLowerCase()