From d91bffdd0a64d13e0972e6909ce5d1819bd15c5e Mon Sep 17 00:00:00 2001 From: dankito Date: Mon, 27 Apr 2020 01:28:33 +0200 Subject: [PATCH] Implemented displaying icon for bank --- .../javafx/dialogs/mainwindow/MainWindow.kt | 5 +- .../javafx/model/AccountsAccountTreeItem.kt | 24 ++++++++++ .../banking/ui/presenter/BankingPresenter.kt | 47 +++++++++++++++++++ .../fints4java/android/di/BankingModule.kt | 15 ++++-- .../fints4java/android/ui/views/DrawerView.kt | 8 +++- 5 files changed, 93 insertions(+), 6 deletions(-) diff --git a/BankingJavaFxApp/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/mainwindow/MainWindow.kt b/BankingJavaFxApp/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/mainwindow/MainWindow.kt index ccf0b03e..71843621 100755 --- a/BankingJavaFxApp/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/mainwindow/MainWindow.kt +++ b/BankingJavaFxApp/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/mainwindow/MainWindow.kt @@ -9,6 +9,7 @@ import net.dankito.banking.ui.javafx.controls.AccountsView import net.dankito.banking.ui.javafx.dialogs.mainwindow.controls.MainMenuBar import net.dankito.banking.ui.javafx.util.Base64ServiceJava8 import net.dankito.banking.ui.presenter.BankingPresenter +import net.dankito.banking.util.BankIconFinder import net.dankito.fints.banks.LuceneBankFinder import net.dankito.utils.web.client.OkHttpWebClient import tornadofx.* @@ -25,9 +26,9 @@ class MainWindow : View(messages["application.title"]) { private val indexFolder = File(dataFolder, "index") private val presenter = BankingPresenter(fints4javaBankingClientCreator(OkHttpWebClient(), Base64ServiceJava8()), - LuceneBankFinder(indexFolder), databaseFolder, BankingPersistenceJson(File(databaseFolder, "accounts.json")), RouterJavaFx()) + LuceneBankFinder(indexFolder), databaseFolder, dataFolder, BankingPersistenceJson(File(databaseFolder, "accounts.json")), BankIconFinder(), RouterJavaFx()) // private val presenter = BankingPresenter(hbci4jBankingClientCreator(), LuceneBankFinder(indexFolder), databaseFolder, -// BankingPersistenceJson(File(databaseFolder, "accounts.json")), RouterJavaFx()) +// dataFolder, BankingPersistenceJson(File(databaseFolder, "accounts.json")), BankIconFinder(), RouterJavaFx()) diff --git a/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/model/AccountsAccountTreeItem.kt b/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/model/AccountsAccountTreeItem.kt index b0994999..7b8a8f2b 100755 --- a/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/model/AccountsAccountTreeItem.kt +++ b/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/model/AccountsAccountTreeItem.kt @@ -1,16 +1,40 @@ package net.dankito.banking.ui.javafx.model +import javafx.scene.Node +import javafx.scene.image.ImageView import net.dankito.banking.ui.model.Account open class AccountsAccountTreeItem(val account: Account) : AccountsTreeItemBase(account.displayName) { + companion object { + private const val IconSize = 16.0 + } + + init { isExpanded = true + graphic = createIconImageView() + account.bankAccounts.forEach { bankAccount -> children.add(AccountsBankAccountTreeItem(bankAccount)) } } + protected open fun createIconImageView(): Node? { + account.bank.iconUrl?.let { + val iconImageView = ImageView(it) + + iconImageView.fitHeight = IconSize + iconImageView.fitWidth = IconSize + iconImageView.isPreserveRatio = true + + return iconImageView + } + + // TODO: otherwise set default icon + return null + } + } \ No newline at end of file diff --git a/BankingUiCommon/src/main/java/net/dankito/banking/ui/presenter/BankingPresenter.kt b/BankingUiCommon/src/main/java/net/dankito/banking/ui/presenter/BankingPresenter.kt index d3ebeb53..85c9b3e9 100644 --- a/BankingUiCommon/src/main/java/net/dankito/banking/ui/presenter/BankingPresenter.kt +++ b/BankingUiCommon/src/main/java/net/dankito/banking/ui/presenter/BankingPresenter.kt @@ -16,6 +16,7 @@ import net.dankito.banking.ui.model.tan.EnterTanGeneratorAtcResult import net.dankito.banking.ui.model.tan.EnterTanResult import net.dankito.banking.ui.model.tan.TanChallenge import net.dankito.banking.ui.model.tan.TanGeneratorTanMedium +import net.dankito.banking.util.IBankIconFinder import net.dankito.fints.banks.IBankFinder import net.dankito.fints.model.BankInfo import net.dankito.utils.IThreadPool @@ -24,7 +25,9 @@ import net.dankito.utils.extensions.containsExactly import net.dankito.utils.extensions.ofMaxLength import org.slf4j.LoggerFactory import java.io.File +import java.io.FileOutputStream import java.math.BigDecimal +import java.net.URL import java.util.* import kotlin.collections.ArrayList @@ -33,7 +36,9 @@ open class BankingPresenter( protected val bankingClientCreator: IBankingClientCreator, protected val bankFinder: IBankFinder, protected val databaseFolder: File, + protected val dataFolder: File, protected val persister: IBankingPersistence, + protected val bankIconFinder: IBankIconFinder, protected val router: IRouter, protected val threadPool: IThreadPool = ThreadPool() ) { @@ -155,12 +160,54 @@ open class BankingPresenter( retrievedAccountTransactions(bankAccount, response) } } + + findIconForBankAsync(account) } callback(response) } } + protected open fun findIconForBankAsync(account: Account) { + threadPool.runAsync { + findIconForBank(account) + } + } + + protected open fun findIconForBank(account: Account) { + val bank = account.bank + + try { + bankIconFinder.findIconForBank(bank.name)?.let { bankIconUrl -> + val bankIconFile = saveBankIconToDisk(bankIconUrl) + + bank.iconUrl = "file://" + bankIconFile.absolutePath // without 'file://' Android will not find it + + persistAccount(account) + + callAccountsChangedListeners() + } + } catch (e: Exception) { + log.error("Could not get icon for bank $bank", e) + } + } + + private fun saveBankIconToDisk(bankIconUrl: String): File { + val bankIconsDir = File(dataFolder, "bank_icons") + bankIconsDir.mkdirs() + + val bankIconFile = File(bankIconsDir, File(bankIconUrl).name) + + URL(bankIconUrl).openConnection().getInputStream().buffered().use { iconInputStream -> + FileOutputStream(bankIconFile).use { fileOutputStream -> + iconInputStream.copyTo(fileOutputStream) + } + } + + return bankIconFile + } + + open fun deleteAccount(account: Account) { val wasSelected = isSingleSelectedAccount(account) or // either account or one of its bank accounts is currently selected (account.bankAccounts.firstOrNull { isSingleSelectedBankAccount(it) } != null) diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/di/BankingModule.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/di/BankingModule.kt index 2c25ba1d..334ff599 100644 --- a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/di/BankingModule.kt +++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/di/BankingModule.kt @@ -14,6 +14,8 @@ import net.dankito.banking.search.LuceneRemitteeSearcher import net.dankito.banking.ui.IBankingClientCreator import net.dankito.banking.ui.IRouter import net.dankito.banking.ui.presenter.BankingPresenter +import net.dankito.banking.util.BankIconFinder +import net.dankito.banking.util.IBankIconFinder import net.dankito.fints.banks.IBankFinder import net.dankito.fints.banks.LuceneBankFinder import net.dankito.utils.IThreadPool @@ -75,17 +77,24 @@ class BankingModule(internal val mainActivity: AppCompatActivity) { @Provides @Singleton fun provideBankingPresenter(bankingClientCreator: IBankingClientCreator, bankFinder: IBankFinder, - @Named(DatabaseFolderKey) databaseFolder: File, persister: IBankingPersistence, + @Named(DatabaseFolderKey) databaseFolder: File, @Named(DataFolderKey) dataFolder: File, + persister: IBankingPersistence, bankIconFinder: IBankIconFinder, router: IRouter, threadPool: IThreadPool) : BankingPresenter { - return BankingPresenter(bankingClientCreator, bankFinder, databaseFolder, persister, router, threadPool) + return BankingPresenter(bankingClientCreator, bankFinder, databaseFolder, dataFolder, persister, bankIconFinder, router, threadPool) } @Provides @Singleton - fun provideBankFinder(@Named(IndexFolderKey) indexFolder: File, threadPool: IThreadPool) : IBankFinder { + fun provideBankFinder(@Named(IndexFolderKey) indexFolder: File) : IBankFinder { return LuceneBankFinder(indexFolder) } + @Provides + @Singleton + fun provideBankIconFinder() : IBankIconFinder { + return BankIconFinder() + } + @Provides @Singleton fun provideBankingClientCreator(webClient: IWebClient, base64Service: net.dankito.banking.util.IBase64Service) : IBankingClientCreator { diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/views/DrawerView.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/views/DrawerView.kt index d300a352..18c2dc00 100644 --- a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/views/DrawerView.kt +++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/views/DrawerView.kt @@ -117,7 +117,7 @@ open class DrawerView( private fun createAccountDrawerItem(account: Account): IDrawerItem<*> { - return AccountDrawerItem() + val accountItem = AccountDrawerItem() .withName(account.displayName) .withLevel(AccountLevel) // .withSecondaryIcon(GoogleMaterial.Icon.gmd_settings) // used when editing account is implemented @@ -127,6 +127,12 @@ open class DrawerView( .withIcon(activity, FontAwesome.Icon.faw_piggy_bank, R.color.primaryTextColor_Dark) .withSelected(presenter.isSingleSelectedAccount(account)) .withOnDrawerItemClickListener { _, _, _ -> itemClicked { presenter.selectedAccount(account) } } + + account.bank.iconUrl?.let { bankIconUrl -> + accountItem.withIcon(bankIconUrl) + } + + return accountItem } private fun createBankAccountsDrawerItems(account: Account): List> {