Implemented autocomplete list for potential remittees in TransferMoneyDialog
This commit is contained in:
parent
c7845ca779
commit
d1bb7d81c3
|
@ -16,7 +16,7 @@ compileTestKotlin {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(":BankingUiCommon")
|
implementation project(":BankingUiCommon")
|
||||||
|
|
||||||
implementation project(":BankingPersistenceJson")
|
api project(":BankingPersistenceJson")
|
||||||
|
|
||||||
implementation "net.dankito.search:lucene-4-utils:$luceneUtilsVersion"
|
implementation "net.dankito.search:lucene-4-utils:$luceneUtilsVersion"
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,11 @@ import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.otaliastudios.autocomplete.RecyclerViewPresenter
|
import com.otaliastudios.autocomplete.RecyclerViewPresenter
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import net.dankito.banking.ui.android.adapter.RemitteeListAdapter
|
import net.dankito.banking.ui.android.adapter.RemitteeListAdapter
|
||||||
import net.dankito.banking.search.IRemitteeSearcher
|
|
||||||
import net.dankito.banking.search.Remittee
|
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) }
|
protected val adapter = RemitteeListAdapter { dispatchClick(it) }
|
||||||
|
|
||||||
|
@ -25,7 +24,7 @@ open class RemitteePresenter(protected val remitteeSearcher: IRemitteeSearcher,
|
||||||
lastSearchRemitteeJob?.cancel()
|
lastSearchRemitteeJob?.cancel()
|
||||||
|
|
||||||
lastSearchRemitteeJob = GlobalScope.launch(Dispatchers.IO) {
|
lastSearchRemitteeJob = GlobalScope.launch(Dispatchers.IO) {
|
||||||
val potentialRemittees = Stopwatch.logDuration("findRemittees()") { remitteeSearcher.findRemittees(query?.toString() ?: "") }
|
val potentialRemittees = bankingPresenter.findRemitteesForName(query?.toString() ?: "")
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
adapter.items = potentialRemittees
|
adapter.items = potentialRemittees
|
||||||
|
|
|
@ -78,9 +78,10 @@ class BankingModule(private val applicationContext: Context) {
|
||||||
@Singleton
|
@Singleton
|
||||||
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, remitteeSearcher: IRemitteeSearcher,
|
||||||
router: IRouter, serializer: ISerializer, threadPool: IThreadPool) : BankingPresenter {
|
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
|
@Provides
|
||||||
|
|
|
@ -60,9 +60,6 @@ open class TransferMoneyDialog : DialogFragment() {
|
||||||
@Inject
|
@Inject
|
||||||
protected lateinit var presenter: BankingPresenter
|
protected lateinit var presenter: BankingPresenter
|
||||||
|
|
||||||
@Inject
|
|
||||||
protected lateinit var remitteeSearcher: IRemitteeSearcher
|
|
||||||
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
BankingComponent.component.inject(this)
|
BankingComponent.component.inject(this)
|
||||||
|
@ -181,7 +178,7 @@ open class TransferMoneyDialog : DialogFragment() {
|
||||||
.with(6f)
|
.with(6f)
|
||||||
.with(ColorDrawable(Color.WHITE))
|
.with(ColorDrawable(Color.WHITE))
|
||||||
.with(autocompleteCallback)
|
.with(autocompleteCallback)
|
||||||
.with(RemitteePresenter(remitteeSearcher, edtxtRemitteeName.context))
|
.with(RemitteePresenter(presenter, edtxtRemitteeName.context))
|
||||||
.build()
|
.build()
|
||||||
.closePopupOnBackButtonPress(dialog)
|
.closePopupOnBackButtonPress(dialog)
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ dependencies {
|
||||||
implementation project(':fints4kBankingClient')
|
implementation project(':fints4kBankingClient')
|
||||||
implementation project(':hbci4jBankingClient')
|
implementation project(':hbci4jBankingClient')
|
||||||
|
|
||||||
implementation project(':BankingPersistenceJson')
|
implementation project(':LuceneBankingPersistence')
|
||||||
|
|
||||||
implementation "ch.qos.logback:logback-classic:$logbackVersion"
|
implementation "ch.qos.logback:logback-classic:$logbackVersion"
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package net.dankito.banking.ui.javafx.dialogs.mainwindow
|
||||||
|
|
||||||
import javafx.scene.control.SplitPane
|
import javafx.scene.control.SplitPane
|
||||||
import net.dankito.banking.fints4kBankingClientCreator
|
import net.dankito.banking.fints4kBankingClientCreator
|
||||||
import net.dankito.banking.persistence.BankingPersistenceJson
|
|
||||||
import net.dankito.banking.ui.javafx.RouterJavaFx
|
import net.dankito.banking.ui.javafx.RouterJavaFx
|
||||||
import net.dankito.banking.ui.javafx.controls.AccountTransactionsView
|
import net.dankito.banking.ui.javafx.controls.AccountTransactionsView
|
||||||
import net.dankito.banking.ui.javafx.controls.AccountsView
|
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.ui.presenter.BankingPresenter
|
||||||
import net.dankito.banking.util.BankIconFinder
|
import net.dankito.banking.util.BankIconFinder
|
||||||
import net.dankito.banking.fints.banks.LuceneBankFinder
|
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 net.dankito.utils.web.client.OkHttpWebClient
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
import tornadofx.FX.Companion.messages
|
import tornadofx.FX.Companion.messages
|
||||||
|
@ -26,9 +27,10 @@ class MainWindow : View(messages["application.title"]) {
|
||||||
private val indexFolder = File(dataFolder, "index")
|
private val indexFolder = File(dataFolder, "index")
|
||||||
|
|
||||||
private val presenter = BankingPresenter(fints4kBankingClientCreator(OkHttpWebClient(), Base64ServiceJava8()),
|
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,
|
// private val presenter = BankingPresenter(hbci4jBankingClientCreator(), LuceneBankFinder(indexFolder), databaseFolder,
|
||||||
// dataFolder, BankingPersistenceJson(File(databaseFolder, "accounts.json")), BankIconFinder(), RouterJavaFx())
|
// dataFolder, LuceneBankingPersistence(indexFolder, databaseFolder), LuceneRemitteeSearcher(indexFolder), BankIconFinder(), RouterJavaFx())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import net.dankito.banking.ui.model.responses.AddAccountResponse
|
||||||
import net.dankito.banking.ui.presenter.BankingPresenter
|
import net.dankito.banking.ui.presenter.BankingPresenter
|
||||||
import net.dankito.banking.fints.model.BankInfo
|
import net.dankito.banking.fints.model.BankInfo
|
||||||
import net.dankito.banking.ui.javafx.dialogs.addaccount.BankInfoListCellFragment
|
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.AutoCompletionSearchTextField
|
||||||
import net.dankito.utils.javafx.ui.controls.ProcessingIndicatorButton
|
import net.dankito.utils.javafx.ui.controls.ProcessingIndicatorButton
|
||||||
import net.dankito.utils.javafx.ui.controls.autocompletionsearchtextfield
|
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) {
|
protected open fun bankSelected(bank: BankInfo) {
|
||||||
unfocusBankCodeTextField()
|
txtfldBankCode.focusNextControl()
|
||||||
|
|
||||||
selectedBank = bank
|
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) {
|
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)
|
val errorMessage = String.format(messages["add.account.dialog.error.bank.does.not.support.fints.3.error.message"], bank.name)
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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) }
|
||||||
|
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ import javafx.geometry.Pos
|
||||||
import javafx.scene.control.ContentDisplay
|
import javafx.scene.control.ContentDisplay
|
||||||
import javafx.scene.image.ImageView
|
import javafx.scene.image.ImageView
|
||||||
import javafx.scene.layout.Priority
|
import javafx.scene.layout.Priority
|
||||||
|
import kotlinx.coroutines.*
|
||||||
import net.dankito.banking.ui.javafx.dialogs.JavaFxDialogService
|
import net.dankito.banking.ui.javafx.dialogs.JavaFxDialogService
|
||||||
import net.dankito.banking.ui.model.BankAccount
|
import net.dankito.banking.ui.model.BankAccount
|
||||||
import net.dankito.banking.ui.model.parameters.TransferMoneyData
|
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.ui.presenter.BankingPresenter
|
||||||
import net.dankito.banking.util.InputValidator
|
import net.dankito.banking.util.InputValidator
|
||||||
import net.dankito.banking.fints.model.BankInfo
|
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.controls.doubleTextfield
|
||||||
import net.dankito.utils.javafx.ui.dialogs.Window
|
import net.dankito.utils.javafx.ui.dialogs.Window
|
||||||
import net.dankito.utils.javafx.ui.extensions.ensureOnlyUsesSpaceIfVisible
|
import net.dankito.utils.javafx.ui.extensions.ensureOnlyUsesSpaceIfVisible
|
||||||
|
@ -69,6 +74,11 @@ open class TransferMoneyDialog @JvmOverloads constructor(
|
||||||
protected val requiredDataEntered = SimpleBooleanProperty(false)
|
protected val requiredDataEntered = SimpleBooleanProperty(false)
|
||||||
|
|
||||||
|
|
||||||
|
protected var txtfldRemitteeName: AutoCompletionSearchTextField<Remittee> by singleAssign()
|
||||||
|
|
||||||
|
protected var lastSearchRemitteeJob: Job? = null
|
||||||
|
|
||||||
|
|
||||||
protected val inputValidator = InputValidator()
|
protected val inputValidator = InputValidator()
|
||||||
|
|
||||||
protected val dialogService = JavaFxDialogService()
|
protected val dialogService = JavaFxDialogService()
|
||||||
|
@ -124,8 +134,13 @@ open class TransferMoneyDialog @JvmOverloads constructor(
|
||||||
field(messages["transfer.money.dialog.remittee.name.label"]) {
|
field(messages["transfer.money.dialog.remittee.name.label"]) {
|
||||||
fixedHeight = FieldHeight
|
fixedHeight = FieldHeight
|
||||||
|
|
||||||
textfield(this@TransferMoneyDialog.remitteeName) {
|
txtfldRemitteeName = autocompletionsearchtextfield(this@TransferMoneyDialog.remitteeName) {
|
||||||
fixedHeight = TextFieldHeight
|
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) {
|
protected open fun tryToGetBicFromIban(enteredIban: String) {
|
||||||
presenter.findUniqueBankForIbanAsync(enteredIban) { foundBank ->
|
presenter.findUniqueBankForIbanAsync(enteredIban) { foundBank ->
|
||||||
runLater {
|
runLater {
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
|
@ -17,6 +17,8 @@ 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.search.IRemitteeSearcher
|
||||||
|
import net.dankito.banking.search.Remittee
|
||||||
import net.dankito.banking.ui.model.parameters.GetTransactionsParameter
|
import net.dankito.banking.ui.model.parameters.GetTransactionsParameter
|
||||||
import net.dankito.banking.ui.model.settings.AppSettings
|
import net.dankito.banking.ui.model.settings.AppSettings
|
||||||
import net.dankito.utils.IThreadPool
|
import net.dankito.utils.IThreadPool
|
||||||
|
@ -41,6 +43,7 @@ open class BankingPresenter(
|
||||||
protected val databaseFolder: File,
|
protected val databaseFolder: File,
|
||||||
protected val dataFolder: File,
|
protected val dataFolder: File,
|
||||||
protected val persister: IBankingPersistence,
|
protected val persister: IBankingPersistence,
|
||||||
|
protected val remitteeSearcher: IRemitteeSearcher,
|
||||||
protected val bankIconFinder: IBankIconFinder,
|
protected val bankIconFinder: IBankIconFinder,
|
||||||
protected val router: IRouter,
|
protected val router: IRouter,
|
||||||
protected val serializer: ISerializer = JacksonJsonSerializer(),
|
protected val serializer: ISerializer = JacksonJsonSerializer(),
|
||||||
|
@ -410,6 +413,10 @@ open class BankingPresenter(
|
||||||
return bankFinder.findBankByNameBankCodeOrCity(query)
|
return bankFinder.findBankByNameBankCodeOrCity(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open fun findRemitteesForName(name: String): List<Remittee> {
|
||||||
|
return remitteeSearcher.findRemittees(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
open fun searchSelectedAccountTransactions(query: String): List<AccountTransaction> {
|
open fun searchSelectedAccountTransactions(query: String): List<AccountTransaction> {
|
||||||
val queryLowercase = query.trim().toLowerCase()
|
val queryLowercase = query.trim().toLowerCase()
|
||||||
|
|
Loading…
Reference in New Issue