Keeping now bank icon's bytes directly on BankData so that we can persist is to database -> attackers don't see in filesystem added accounts anymore

This commit is contained in:
dankito 2020-10-03 04:37:36 +02:00
parent 7f14215907
commit fa1c2a0ddf
33 changed files with 214 additions and 111 deletions

View File

@ -13,8 +13,7 @@ import net.dankito.banking.ui.model.TypedBankData
import net.dankito.banking.ui.model.settings.AppSettings
import net.dankito.banking.ui.model.tan.MobilePhoneTanMedium
import net.dankito.banking.ui.model.tan.TanGeneratorTanMedium
import net.dankito.banking.util.persistence.doSaveUrlToFile
import net.dankito.utils.multiplatform.File
import net.dankito.banking.util.persistence.downloadIcon
import net.sqlcipher.database.SQLiteDatabase
import net.sqlcipher.database.SupportFactory
@ -197,8 +196,13 @@ open class RoomBankingPersistence(applicationContext: Context, password: String?
}
override fun saveUrlToFile(url: String, file: File) {
doSaveUrlToFile(url, file)
override fun saveBankIcon(bank: TypedBankData, iconUrl: String, fileExtension: String?) {
val iconData = downloadIcon(iconUrl)
bank.iconData = iconData
(bank as? Bank)?.let {
db.bankDao().saveOrUpdate(it)
}
}

View File

@ -21,7 +21,7 @@ open class Bank(
override var customerName: String,
override var userId: String = userName,
override var iconUrl: String? = null,
override var iconData: ByteArray? = null,
@Ignore
override var accounts: List<TypedBankAccount> = listOf(),

View File

@ -12,10 +12,12 @@ import net.dankito.utils.multiplatform.Date
open class RoomModelCreator : IModelCreator {
override fun createBank(bankCode: String, userName: String, password: String, finTsServerAddress: String, bankName: String,
bic: String, customerName: String, userId: String, iconUrl: String?): TypedBankData {
override fun createBank(
bankCode: String, userName: String, password: String, finTsServerAddress: String, bankName: String,
bic: String, customerName: String, userId: String, iconData: ByteArray?
): TypedBankData {
return Bank(bankCode, userName, password, finTsServerAddress, bankName, bic, customerName, userId, iconUrl)
return Bank(bankCode, userName, password, finTsServerAddress, bankName, bic, customerName, userId, iconData)
}
override fun createAccount(bank: TypedBankData, productName: String?, identifier: String): TypedBankAccount {

View File

@ -5,7 +5,7 @@ import net.dankito.banking.ui.model.*
import net.dankito.banking.ui.model.settings.AppSettings
import net.dankito.utils.multiplatform.File
import net.dankito.banking.util.ISerializer
import net.dankito.banking.util.persistence.doSaveUrlToFile
import net.dankito.banking.util.persistence.downloadIcon
open class BankingPersistenceJson(
@ -24,6 +24,8 @@ open class BankingPersistenceJson(
protected val appSettingsJsonFile: File
protected var readBanks: List<TypedBankData>? = null
init {
databaseFolder.mkdirs()
@ -42,7 +44,11 @@ open class BankingPersistenceJson(
}
override fun readPersistedBanks(): List<TypedBankData> {
return serializer.deserializeListOr(banksJsonFile, BankDataEntity::class).map { it as TypedBankData }
val banks = serializer.deserializeListOr(banksJsonFile, BankDataEntity::class).map { it as TypedBankData }
this.readBanks = banks
return banks
}
@ -66,8 +72,12 @@ open class BankingPersistenceJson(
}
override fun saveUrlToFile(url: String, file: File) {
doSaveUrlToFile(url, file)
override fun saveBankIcon(bank: TypedBankData, iconUrl: String, fileExtension: String?) {
bank.iconData = downloadIcon(iconUrl)
readBanks?.let {
saveOrUpdateBank(bank, it)
}
}
}

View File

@ -13,10 +13,12 @@ import net.dankito.utils.multiplatform.Date
open class EntitiesModelCreator : IModelCreator {
override fun createBank(bankCode: String, userName: String, password: String, finTsServerAddress: String, bankName: String, bic: String,
customerName: String, userId: String, iconUrl: String?): TypedBankData {
override fun createBank(
bankCode: String, userName: String, password: String, finTsServerAddress: String, bankName: String, bic: String,
customerName: String, userId: String, iconData: ByteArray?
): TypedBankData {
return BankDataEntity(bankCode, userName, password, finTsServerAddress, bankName, bic, customerName, userId, iconUrl) as TypedBankData
return BankDataEntity(bankCode, userName, password, finTsServerAddress, bankName, bic, customerName, userId, iconData) as TypedBankData
}

View File

@ -18,7 +18,7 @@ open class BankDataEntity(
override var bic: String,
override var customerName: String,
override var userId: String = userName,
override var iconUrl: String? = null,
override var iconData: ByteArray? = null,
override var accounts: List<BankAccountEntity> = listOf(),
override var supportedTanMethods: List<TanMethod> = listOf(),
override var selectedTanMethod: TanMethod? = null,

View File

@ -34,8 +34,6 @@ class BankingPersistenceJsonTest {
const val UserId = CustomerId
const val IconUrl = "http://i-do-not-exist.fail/favicon.ico"
val NowMillis = System.currentTimeMillis()
val TwoYearsAgoMillis = NowMillis - (2 * 365 * 24 * 60 * 60 * 1000L)
@ -116,7 +114,7 @@ class BankingPersistenceJsonTest {
private fun createBank(countAccounts: Int = 0, customerId: String = CustomerId): BankDataEntity {
val result = BankDataEntity(BankCode, customerId, Password, FinTsServerAddress, BankName, Bic, CustomerName, UserId, IconUrl)
val result = BankDataEntity(BankCode, customerId, Password, FinTsServerAddress, BankName, Bic, CustomerName, UserId, null)
result.accounts = createAccounts(countAccounts, result)
@ -180,7 +178,7 @@ class BankingPersistenceJsonTest {
assertThat(deserializedBank.bic).isEqualTo(bank.bic)
assertThat(deserializedBank.customerName).isEqualTo(bank.customerName)
assertThat(deserializedBank.userId).isEqualTo(bank.userId)
assertThat(deserializedBank.iconUrl).isEqualTo(bank.iconUrl)
assertThat(deserializedBank.iconData).isEqualTo(bank.iconData)
assertAccountsEqual(deserializedBank.accounts, bank.accounts)
}

View File

@ -1,10 +1,10 @@
package net.dankito.banking.ui.android.adapter
import android.net.Uri
import android.view.ContextMenu
import android.view.View
import net.dankito.banking.ui.android.R
import net.dankito.banking.ui.android.adapter.viewholder.AccountTransactionViewHolder
import net.dankito.banking.ui.android.extensions.setIcon
import net.dankito.banking.ui.android.extensions.showAmount
import net.dankito.banking.ui.model.IAccountTransaction
import net.dankito.banking.ui.presenter.BankingPresenter
@ -39,10 +39,10 @@ open class AccountTransactionAdapter(protected val presenter: BankingPresenter)
viewHolder.txtvwAmount.showAmount(presenter, item.amount, item.currency)
val iconUrl = item.account.bank.iconUrl
if (iconUrl != null && presenter.areAllAccountSelected) {
if (presenter.areAllAccountSelected) {
viewHolder.imgvwBankIcon.setIcon(item.account.bank)
// TODO: if bank icon isn't set: Show default icon? show at least an empty space to that amount and date don't shift up causing an inconsistent view?
viewHolder.imgvwBankIcon.visibility = View.VISIBLE
viewHolder.imgvwBankIcon.setImageURI(Uri.parse(iconUrl))
}
else {
viewHolder.imgvwBankIcon.visibility = View.GONE

View File

@ -0,0 +1,16 @@
package net.dankito.banking.ui.android.extensions
import android.content.res.Resources
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
fun ByteArray.toBitmap(): Bitmap {
return BitmapFactory.decodeByteArray(this, 0, this.size)
}
fun ByteArray.toDrawable(resources: Resources): Drawable {
return BitmapDrawable(resources, this.toBitmap())
}

View File

@ -1,6 +1,5 @@
package net.dankito.banking.ui.android.extensions
import android.net.Uri
import android.view.View
import android.widget.ImageView
import net.dankito.banking.ui.model.IBankData
@ -8,10 +7,21 @@ import net.dankito.banking.ui.model.IBankData
fun ImageView.setIcon(bank: IBankData<*, *>) {
try {
val iconUrl = bank.iconUrl
this.visibility = if (iconUrl == null) View.GONE else View.VISIBLE
this.setImageURI(Uri.parse(iconUrl))
val iconData = bank.iconData
if (iconData != null) {
this.visibility = View.VISIBLE
this.setImageFromBytes(iconData)
}
else {
this.visibility = View.GONE
this.setImageURI(null)
}
} catch (e: Exception) {
this.visibility = View.GONE
}
}
fun ImageView.setImageFromBytes(data: ByteArray) {
this.setImageBitmap(data.toBitmap())
}

View File

@ -21,6 +21,7 @@ import com.mikepenz.materialdrawer.widget.MaterialDrawerSliderView
import net.dankito.banking.ui.android.R
import net.dankito.banking.ui.android.dialogs.settings.BankSettingsDialog
import net.dankito.banking.ui.android.dialogs.settings.SettingsDialog
import net.dankito.banking.ui.android.extensions.toDrawable
import net.dankito.banking.ui.android.extensions.withIcon
import net.dankito.banking.ui.model.TypedBankData
import net.dankito.banking.ui.presenter.BankingPresenter
@ -87,6 +88,7 @@ open class DrawerView(
.withIdentifier(AllAccountsId)
.withLevel(BankLevel)
.withSelected(true)
// TODO: set default account icon (here and below if bank.iconUrl isn't set
.withIcon(activity, GoogleMaterial.Icon.gmd_account_balance, R.color.primaryTextColor_Dark)
.withOnDrawerItemClickListener { _, _, _ -> itemClicked { presenter.selectedAllAccounts() } }
,
@ -150,12 +152,13 @@ open class DrawerView(
.withSecondaryIcon(R.drawable.ic_baseline_settings_24)
.withSecondaryIconColor(activity, R.color.primaryTextColor_Dark)
.withOnSecondaryIconClickedListener { closeDrawerAndEditAccount(bank) }
.withIcon(bank.iconUrl ?: "")
.withIcon(bank.iconData?.toDrawable(activity.resources))
.withSelected(presenter.isSingleSelectedBank(bank))
.withOnDrawerItemClickListener { _, _, _ -> itemClicked { presenter.selectedBank(bank) } }
if (bank.iconUrl == null) {
accountItem.withIcon(activity, FontAwesome.Icon.faw_piggy_bank, R.color.primaryTextColor_Dark)
if (bank.iconData == null) {
// TODO: use better default icon
accountItem.withIcon(activity, GoogleMaterial.Icon.gmd_account_balance, R.color.primaryTextColor_Dark)
}

View File

@ -148,7 +148,7 @@
android:ellipsize="end"
android:gravity="center_vertical"
android:textAlignment="gravity"
android:textSize="@dimen/view_real_time_transfer_info_text_size"
android:textSize="@dimen/view_info_popup_text_size"
android:text="@string/dialog_transfer_money_real_time_transfer"
/>

View File

@ -19,6 +19,7 @@ import net.dankito.banking.ui.presenter.BankingPresenter
import net.dankito.banking.util.InputValidator
import net.dankito.banking.bankfinder.BankInfo
import net.dankito.banking.search.TransactionParty
import net.dankito.banking.ui.javafx.extensions.createBankIconImageView
import net.dankito.utils.multiplatform.toBigDecimal
import net.dankito.banking.ui.javafx.extensions.focusNextControl
import net.dankito.utils.javafx.ui.controls.AutoCompletionSearchTextField
@ -115,15 +116,8 @@ open class TransferMoneyDialog @JvmOverloads constructor(
cellFormat {
text = it.displayName
it.bank.iconUrl?.let { iconUrl ->
graphic = ImageView(iconUrl)?.apply {
this.fitHeight = BankIconSize
this.fitWidth = BankIconSize
this.isPreserveRatio = true
}
contentDisplay = ContentDisplay.LEFT
}
?: run { contentDisplay = ContentDisplay.TEXT_ONLY }
graphic = it.bank.createBankIconImageView(BankIconSize)
contentDisplay = ContentDisplay.LEFT
}
}

View File

@ -0,0 +1,17 @@
package net.dankito.banking.ui.javafx.extensions
import javafx.scene.image.ImageView
import net.dankito.banking.ui.model.IBankData
fun IBankData<*, *>.createBankIconImageView(iconSize: Double): ImageView {
// TODO: set default icon if iconData is null
val image = iconData?.toImage()
val iconImageView = ImageView(image)
iconImageView.fitHeight = iconSize
iconImageView.fitWidth = iconSize
iconImageView.isPreserveRatio = true
return iconImageView
}

View File

@ -0,0 +1,9 @@
package net.dankito.banking.ui.javafx.extensions
import javafx.scene.image.Image
import java.io.ByteArrayInputStream
fun ByteArray.toImage(): Image {
return Image(ByteArrayInputStream(this))
}

View File

@ -1,7 +1,7 @@
package net.dankito.banking.ui.javafx.model
import javafx.scene.Node
import javafx.scene.image.ImageView
import net.dankito.banking.ui.javafx.extensions.createBankIconImageView
import net.dankito.banking.ui.model.TypedBankData
@ -23,18 +23,7 @@ open class AccountsAccountTreeItem(val bank: TypedBankData) : AccountsTreeItemBa
}
protected open fun createIconImageView(): Node? {
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
return bank.createBankIconImageView(IconSize)
}
}

View File

@ -22,6 +22,6 @@ interface IBankingPersistence {
fun readPersistedAppSettings(): AppSettings?
fun saveUrlToFile(url: String, file: File)
fun saveBankIcon(bank: TypedBankData, iconUrl: String, fileExtension: String?)
}

View File

@ -2,7 +2,6 @@ package net.dankito.banking.persistence
import net.dankito.banking.ui.model.*
import net.dankito.banking.ui.model.settings.AppSettings
import net.dankito.utils.multiplatform.File
open class NoOpBankingPersistence : IBankingPersistence {
@ -34,7 +33,7 @@ open class NoOpBankingPersistence : IBankingPersistence {
}
override fun saveUrlToFile(url: String, file: File) {
override fun saveBankIcon(bank: TypedBankData, iconUrl: String, fileExtension: String?) {
}

View File

@ -14,7 +14,7 @@ open class BankData(
override var bic: String,
override var customerName: String,
override var userId: String = userName,
override var iconUrl: String? = null,
override var iconData: ByteArray? = null,
override var accounts: List<TypedBankAccount> = listOf()
) : TypedBankData {

View File

@ -23,7 +23,7 @@ interface IBankData<TAccount: IBankAccount<TAccountTransaction>, TAccountTransac
var customerName: String
var userId: String
var iconUrl: String?
var iconData: ByteArray?
var accounts: List<TAccount>

View File

@ -7,10 +7,12 @@ import net.dankito.utils.multiplatform.Date
open class DefaultModelCreator : IModelCreator {
override fun createBank(bankCode: String, userName: String, password: String, finTsServerAddress: String, bankName: String, bic: String,
customerName: String, userId: String, iconUrl: String?): TypedBankData {
override fun createBank(
bankCode: String, userName: String, password: String, finTsServerAddress: String, bankName: String, bic: String,
customerName: String, userId: String, iconData: ByteArray?
): TypedBankData {
return BankData(bankCode, userName, password, finTsServerAddress, bankName, bic, customerName, userId, iconUrl)
return BankData(bankCode, userName, password, finTsServerAddress, bankName, bic, customerName, userId, iconData)
}

View File

@ -9,7 +9,7 @@ import net.dankito.utils.multiplatform.Date
interface IModelCreator {
fun createBank(bankCode: String, userName: String, password: String, finTsServerAddress: String, bankName: String, bic: String,
customerName: String = "", userId: String = userName, iconUrl: String? = null): TypedBankData
customerName: String = "", userId: String = userName, iconData: ByteArray? = null): TypedBankData
fun createAccount(bank: TypedBankData, productName: String?, identifier: String) : TypedBankAccount

View File

@ -209,33 +209,15 @@ open class BankingPresenter(
}
protected open fun handleFindIconForBankResult(bank: TypedBankData, bankIconUrl: String) {
val bankIconFile = saveBankIconToDisk(bank, bankIconUrl)
var iconFilePath = bankIconFile.getAbsolutePath()
if (iconFilePath.startsWith("file://", true) == false) {
iconFilePath = "file://" + iconFilePath // without 'file://' Android will not find it
try {
persister.saveBankIcon(bank, bankIconUrl, getIconFileExtension(bankIconUrl))
} catch (e: Exception) {
log.error(e) { "Could not download bank icon from url $bankIconUrl" }
}
bank.iconUrl = iconFilePath
persistBankOffUiThread(bank)
callBanksChangedListeners()
}
protected open fun saveBankIconToDisk(bank: TypedBankData, bankIconUrl: String): File {
val bankIconsDir = File(dataFolder, "bank_icons")
bankIconsDir.mkdirs()
val extension = getIconFileExtension(bankIconUrl)
val bankIconFile = File(bankIconsDir, bank.bankCode + if (extension != null) (".$extension") else "")
persister.saveUrlToFile(bankIconUrl, bankIconFile)
return bankIconFile
}
protected open fun getIconFileExtension(bankIconUrl: String): String? {
try {
var iconFilename = File(bankIconUrl).filename

View File

@ -12,4 +12,10 @@ fun IBankingPersistence.doSaveUrlToFile(url: String, file: File) {
iconInputStream.copyTo(fileOutputStream)
}
}
}
fun IBankingPersistence.downloadIcon(url: String): ByteArray {
URL(url).openConnection().getInputStream().buffered().use { iconInputStream ->
return iconInputStream.readBytes()
}
}

View File

@ -0,0 +1,30 @@
package net.dankito.banking
import kotlinx.cinterop.*
import platform.Foundation.*
/**
* Swift doesn't see the ByteArray- and NSData extension methods from Common (why?) -> redefine them here in a way Swift sees them.
*/
class ByteArrayExtensions {
companion object {
fun toNSData(array: ByteArray): NSData {
return NSMutableData().apply {
if (array.isEmpty()) return@apply
array.usePinned {
appendBytes(it.addressOf(0), array.size.convert())
}
}
}
fun fromNSData(data: NSData): ByteArray {
val bytes: CPointer<ByteVar> = data.bytes!!.reinterpret()
return ByteArray(data.length.toInt()) { index -> bytes[index] }
}
}
}

View File

@ -77,7 +77,7 @@
<attribute name="customerName" attributeType="String"/>
<attribute name="displayIndex" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="finTsServerAddress" attributeType="String"/>
<attribute name="iconUrl" optional="YES" attributeType="String"/>
<attribute name="iconData" optional="YES" attributeType="Binary"/>
<attribute name="password" attributeType="String"/>
<attribute name="savePassword" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="selectedTanMethodCode" optional="YES" attributeType="String"/>

View File

@ -16,7 +16,7 @@ let previewFlickerCodeTanChallenge = FlickerCodeTanChallenge(flickerCode: Flicke
func createPreviewBanks() -> [IBankData] {
let bank1 = BankData(bankCode: "", userName: "", password: "", finTsServerAddress: "", bankName: "Abzockbank", bic: "", customerName: "Marieke Musterfrau", userId: "", iconUrl: "", accounts: [])
let bank1 = BankData(bankCode: "", userName: "", password: "", finTsServerAddress: "", bankName: "Abzockbank", bic: "", customerName: "Marieke Musterfrau", userId: "", iconData: nil, accounts: [])
bank1.accounts = [
BankAccount(bank: bank1, productName: "Girokonto", identifier: "1234567890"),
@ -25,7 +25,7 @@ func createPreviewBanks() -> [IBankData] {
]
let bank2 = BankData(bankCode: "", userName: "", password: "", finTsServerAddress: "", bankName: "Kundenverarschebank", bic: "", customerName: "Marieke Musterfrau", userId: "", iconUrl: "", accounts: [])
let bank2 = BankData(bankCode: "", userName: "", password: "", finTsServerAddress: "", bankName: "Kundenverarschebank", bic: "", customerName: "Marieke Musterfrau", userId: "", iconData: nil, accounts: [])
bank2.accounts = [
BankAccount(bank: bank2, productName: "Girokonto", identifier: "1234567890")

View File

@ -147,6 +147,19 @@ class CoreDataBankingPersistence: IBankingPersistence, ITransactionPartySearcher
}
func saveBankIcon(bank: IBankData, iconUrl: String, fileExtension: String?) {
do {
if let remoteUrl = URL.encoded(iconUrl) {
let iconData = try Data(contentsOf: remoteUrl)
bank.iconData = mapper.map(iconData)
saveOrUpdateBank(bank: bank, allBanks: [])
}
} catch {
NSLog("Could not get icon for bank \(bank) from url \(iconUrl): \(error)")
}
}
func saveUrlToFile(url: String, file: URL) {
if let remoteUrl = URL.encoded(url) {
if let fileData = try? Data(contentsOf: remoteUrl) {

View File

@ -6,8 +6,8 @@ import BankingUiSwift
class Mapper {
func map(_ bank: PersistedBankData) -> IBankData {
let mapped = BankData(bankCode: map(bank.bankCode), userName: map(bank.userName), password: map(bank.password), finTsServerAddress: map(bank.finTsServerAddress), bankName: map(bank.bankName), bic: map(bank.bic), customerName: map(bank.customerName), userId: map(bank.userId), iconUrl: bank.iconUrl, accounts: [])
let mapped = BankData(bankCode: map(bank.bankCode), userName: map(bank.userName), password: map(bank.password), finTsServerAddress: map(bank.finTsServerAddress), bankName: map(bank.bankName), bic: map(bank.bic), customerName: map(bank.customerName), userId: map(bank.userId), iconData: map(bank.iconData), accounts: [])
mapped.wrongCredentialsEntered = bank.wrongCredentialsEntered
mapped.savePassword = bank.savePassword
mapped.userSetDisplayName = bank.userSetDisplayName
@ -36,8 +36,8 @@ class Mapper {
mapped.bic = bank.bic
mapped.customerName = bank.customerName
mapped.userId = bank.userId
mapped.iconUrl = bank.iconUrl
mapped.iconData = map(bank.iconData)
mapped.wrongCredentialsEntered = bank.wrongCredentialsEntered
mapped.savePassword = bank.savePassword
mapped.userSetDisplayName = bank.userSetDisplayName
@ -448,4 +448,20 @@ class Mapper {
return string ?? ""
}
func map(_ array: KotlinByteArray?) -> Data? {
if let array = array {
return ByteArrayExtensions.Companion().toNSData(array: array)
}
return nil
}
func map(_ data: Data?) -> KotlinByteArray? {
if let data = data {
return ByteArrayExtensions.Companion().fromNSData(data: data)
}
return nil
}
}

View File

@ -1,9 +1,10 @@
import SwiftUI
import BankingUiSwift
struct IconView: View {
let iconUrl: String?
let iconData: KotlinByteArray?
let defaultIconName: String
@ -12,22 +13,22 @@ struct IconView: View {
var body: some View {
getBankIcon(self.iconUrl)
getBankIcon(self.iconData)
.renderingMode(Image.TemplateRenderingMode.original)
.resizable()
.scaledToFit()
.frame(width: Styles.AccountsIconWidth)
}
private func getBankIcon(_ iconUrl: String?) -> Image {
if let iconUrl = iconUrl {
if let iconData = persistence.readContentOfFile(iconUrl) {
if let uiImage = UIImage(data: iconData) {
return Image(uiImage: uiImage)
}
private func getBankIcon(_ iconData: KotlinByteArray?) -> Image {
if let iconData = iconData {
let nsData = ByteArrayExtensions.Companion().toNSData(array: iconData)
if let uiImage = UIImage(data: nsData) {
return Image(uiImage: uiImage)
}
}
return Image(defaultIconName)
}
@ -37,7 +38,7 @@ struct IconView: View {
struct IconView_Previews: PreviewProvider {
static var previews: some View {
IconView(iconUrl: nil, defaultIconName: "")
IconView(iconData: nil, defaultIconName: "")
}
}

View File

@ -6,7 +6,7 @@ struct IconedTitleView: View {
private var title: String
private var iconUrl: String?
private var iconData: KotlinByteArray?
private var defaultIconName: String
@ -14,16 +14,16 @@ struct IconedTitleView: View {
init(_ bank: IBankData, titleFont: Font? = nil) {
self.init(accountTitle: bank.displayName, iconUrl: bank.iconUrl, defaultIconName: Styles.AccountFallbackIcon, titleFont: titleFont)
self.init(accountTitle: bank.displayName, iconData: bank.iconData, defaultIconName: Styles.AccountFallbackIcon, titleFont: titleFont)
}
init(_ account: IBankAccount, titleFont: Font? = nil) {
self.init(accountTitle: account.displayName, iconUrl: account.bank.iconUrl, defaultIconName: Styles.AccountFallbackIcon, titleFont: titleFont)
self.init(accountTitle: account.displayName, iconData: account.bank.iconData, defaultIconName: Styles.AccountFallbackIcon, titleFont: titleFont)
}
init(accountTitle: String, iconUrl: String?, defaultIconName: String, titleFont: Font? = nil) {
init(accountTitle: String, iconData: KotlinByteArray?, defaultIconName: String, titleFont: Font? = nil) {
self.title = accountTitle
self.iconUrl = iconUrl
self.iconData = iconData
self.defaultIconName = defaultIconName
self.titleFont = titleFont
@ -32,7 +32,7 @@ struct IconedTitleView: View {
var body: some View {
HStack {
IconView(iconUrl: self.iconUrl, defaultIconName: self.defaultIconName)
IconView(iconData: self.iconData, defaultIconName: self.defaultIconName)
Spacer()
.frame(width: Styles.DefaultSpaceBetweenIconAndText)
@ -58,7 +58,7 @@ struct IconedTitleView: View {
struct IconedAccountTitle_Previews: PreviewProvider {
static var previews: some View {
IconedTitleView(accountTitle: "Abzockbank", iconUrl: nil, defaultIconName: Styles.AccountFallbackIcon)
IconedTitleView(accountTitle: "Abzockbank", iconData: nil, defaultIconName: Styles.AccountFallbackIcon)
}
}

View File

@ -40,7 +40,7 @@ struct AccountTransactionListItem: View {
if areMoreThanOneBanksTransactionsDisplayed {
Spacer()
IconView(iconUrl: transaction.account.bank.iconUrl, defaultIconName: Styles.AccountFallbackIcon)
IconView(iconData: transaction.account.bank.iconData, defaultIconName: Styles.AccountFallbackIcon)
}
Spacer()

View File

@ -16,7 +16,7 @@ struct AllBanksListItem: View {
Section {
NavigationLink(destination: EmptyView(), isActive: .constant(false)) { // NavigationLink navigated to AccountTransactionsDialog twice. So i disabled NavigationLink and implemented manual navigation
HStack {
IconedTitleView(accountTitle: "All accounts".localize(), iconUrl: nil, defaultIconName: Styles.AccountFallbackIcon, titleFont: .headline)
IconedTitleView(accountTitle: "All accounts".localize(), iconData: nil, defaultIconName: Styles.AccountFallbackIcon, titleFont: .headline)
Spacer()