diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/ContactPickerAdapter.kt b/app/src/main/java/sh/sar/basedbank/ui/home/ContactPickerAdapter.kt index 81cca45..85569b9 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/ContactPickerAdapter.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/ContactPickerAdapter.kt @@ -31,7 +31,9 @@ class ContactPickerAdapter( val isSameAsFrom: Boolean = false, val isManualEntry: Boolean = false, val imageHash: String? = null, - val inactiveReason: String? = null + val inactiveReason: String? = null, + val balance: String? = null, + val bankLogoRes: Int? = null ) : PickerItem() } @@ -89,14 +91,31 @@ class ContactPickerAdapter( binding.tvPrimary.text = item.displayName binding.tvSecondary.text = item.subtitle - val cached = item.imageHash?.let { imageCache[it] } - if (cached != null) { - binding.ivIcon.setImageBitmap(cached) + if (item.balance != null) { + binding.tvBalance.text = item.balance + binding.tvBalance.visibility = android.view.View.VISIBLE } else { - val iconChar = if (item.isManualEntry) "→" else item.displayName.firstOrNull()?.uppercaseChar()?.toString() ?: "?" - val iconColor = if (item.isManualEntry) "#546E7A" else item.colorHex - binding.ivIcon.setImageBitmap(makeInitialsBitmap(iconChar, iconColor, binding.ivIcon.context)) - if (item.imageHash != null) onImageNeeded?.invoke(item.imageHash) + binding.tvBalance.visibility = android.view.View.GONE + } + + val cached = item.imageHash?.let { imageCache[it] } + when { + cached != null -> { + binding.ivIcon.scaleType = android.widget.ImageView.ScaleType.CENTER_CROP + binding.ivIcon.setImageBitmap(cached) + } + item.bankLogoRes != null -> { + binding.ivIcon.scaleType = android.widget.ImageView.ScaleType.FIT_CENTER + binding.ivIcon.setImageResource(item.bankLogoRes) + if (item.imageHash != null) onImageNeeded?.invoke(item.imageHash) + } + else -> { + binding.ivIcon.scaleType = android.widget.ImageView.ScaleType.CENTER_CROP + val iconChar = if (item.isManualEntry) "→" else item.displayName.firstOrNull()?.uppercaseChar()?.toString() ?: "?" + val iconColor = if (item.isManualEntry) "#546E7A" else item.colorHex + binding.ivIcon.setImageBitmap(makeInitialsBitmap(iconChar, iconColor, binding.ivIcon.context)) + if (item.imageHash != null) onImageNeeded?.invoke(item.imageHash) + } } binding.root.alpha = if (item.isSameAsFrom || item.inactiveReason != null) 0.4f else 1.0f diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/ContactPickerSheetFragment.kt b/app/src/main/java/sh/sar/basedbank/ui/home/ContactPickerSheetFragment.kt index 1fe9811..f71ff37 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/ContactPickerSheetFragment.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/ContactPickerSheetFragment.kt @@ -24,7 +24,10 @@ import sh.sar.basedbank.BasedBankApp import sh.sar.basedbank.R import sh.sar.basedbank.api.mib.MibContactsClient import sh.sar.basedbank.databinding.SheetContactPickerBinding +import sh.sar.basedbank.util.AccountListParser import sh.sar.basedbank.util.RecentsCache +import sh.sar.basedbank.util.bmlapi.BmlCardParser +import sh.sar.basedbank.util.bmlapi.BmlDashboardParser class ContactPickerSheetFragment : BottomSheetDialogFragment() { @@ -225,17 +228,27 @@ class ContactPickerSheetFragment : BottomSheetDialogFragment() { for (acc in filteredRegular) { if (acc.profileImageHash != null) profileImageHashes.add(acc.profileImageHash) val isSame = acc.accountNumber == fromAccountNumber - val accBal = if (hide) "••••••" else acc.availableBalance + val parsedBalance = AccountListParser.from(acc)?.balance + ?: "${acc.currencyName} ${acc.availableBalance}" + val balance = if (hide) maskAmount(parsedBalance) else parsedBalance + val logoRes = when (acc.bank) { + "BML" -> R.drawable.bml_logo_vector + "FAHIPAY" -> R.drawable.fahipay_logo + "MIB" -> R.drawable.mib_logo + else -> null + } items.add(ContactPickerAdapter.PickerItem.Row( accountNumber = acc.accountNumber, displayName = acc.accountBriefName, - subtitle = "${acc.accountNumber} · ${acc.currencyName} $accBal", + subtitle = acc.accountNumber, colorHex = "#FE860E", isSameAsFrom = isSame, imageHash = acc.profileImageHash, inactiveReason = if (isSame) null else if (fromIsCard && acc.loginTag != fromLoginTag) "Cards can only be used within the same BML account" - else currencyMismatchReason(fromCurrency, acc.currencyName) + else currencyMismatchReason(fromCurrency, acc.currencyName), + balance = balance, + bankLogoRes = logoRes )) } } @@ -249,18 +262,24 @@ class ContactPickerSheetFragment : BottomSheetDialogFragment() { if (acc.profileImageHash != null) profileImageHashes.add(acc.profileImageHash) val isSame = acc.accountNumber == fromAccountNumber val isActive = acc.statusDesc.equals("Active", ignoreCase = true) - val cardBal = if (hide) "••••••" else acc.availableBalance + val isDebit = acc.profileType == "BML_DEBIT" + val parsedBalance = if (isDebit) null + else AccountListParser.from(acc)?.balance ?: "${acc.currencyName} ${acc.availableBalance}" + val balance = parsedBalance?.let { if (hide) maskAmount(it) else it } + val logoRes = BmlCardParser.cardNetworkIcon(acc) ?: R.drawable.bml_logo_vector items.add(ContactPickerAdapter.PickerItem.Row( accountNumber = acc.accountNumber, displayName = acc.accountBriefName, - subtitle = "${acc.accountNumber} · ${acc.currencyName} $cardBal", + subtitle = acc.accountNumber, colorHex = "#FE860E", isSameAsFrom = isSame, imageHash = acc.profileImageHash, inactiveReason = if (isSame) null else if (!isActive) acc.statusDesc else if (acc.loginTag != fromLoginTag) "Cards can only be used within the same BML account" - else currencyMismatchReason(fromCurrency, acc.currencyName) + else currencyMismatchReason(fromCurrency, acc.currencyName), + balance = balance, + bankLogoRes = logoRes )) } } diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/PayMvQrFragment.kt b/app/src/main/java/sh/sar/basedbank/ui/home/PayMvQrFragment.kt index 13aa3d4..5d84a88 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/PayMvQrFragment.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/PayMvQrFragment.kt @@ -32,11 +32,15 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import sh.sar.basedbank.BasedBankApp import sh.sar.basedbank.R import sh.sar.basedbank.api.models.BankAccount import sh.sar.basedbank.databinding.FragmentPayMvQrBinding import sh.sar.basedbank.databinding.ItemAccountDropdownBinding +import sh.sar.basedbank.util.AccountListParser import sh.sar.basedbank.util.PaymvQrParser +import sh.sar.basedbank.util.bmlapi.BmlCardParser +import sh.sar.basedbank.util.bmlapi.BmlDashboardParser import java.io.File import java.io.FileOutputStream @@ -49,6 +53,7 @@ class PayMvQrFragment : Fragment() { private var selectedAccount: BankAccount? = null private var generatedBitmap: Bitmap? = null private var generateJob: Job? = null + private val dropdownProfileImageCache = mutableMapOf() private val qrLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode != Activity.RESULT_OK) return@registerForActivityResult @@ -410,9 +415,66 @@ class PayMvQrFragment : Fragment() { } val ownerPrefix = if (acc.bank == "BML" && acc.profileName.isNotBlank()) "${acc.profileName} · " else "" b.tvDropdownAccountName.text = "$ownerPrefix${acc.accountBriefName}" + + val displayData = AccountListParser.from(acc) + val typeLabel = displayData?.typeLabel + ?: if (acc.bank == "BML") BmlDashboardParser.productLabel(acc.accountTypeName) + else acc.accountTypeName.trim() b.tvDropdownAccountNumber.text = acc.accountNumber - b.tvDropdownBalance.text = "" + if (typeLabel.isNotBlank()) { + b.tvDropdownAccountType.text = typeLabel + b.tvDropdownAccountType.visibility = View.VISIBLE + } else { + b.tvDropdownAccountType.visibility = View.GONE + } + b.tvDropdownBalance.text = displayData?.balance ?: "" b.root.alpha = 1f + + val networkIcon = BmlCardParser.cardNetworkIcon(acc) + when { + networkIcon != null -> { + b.ivDropdownCardLogo.setImageResource(networkIcon) + b.ivDropdownCardLogo.visibility = View.VISIBLE + } + acc.bank == "BML" -> { + b.ivDropdownCardLogo.setImageResource(R.drawable.bml_logo_vector) + b.ivDropdownCardLogo.visibility = View.VISIBLE + } + acc.bank == "FAHIPAY" -> { + b.ivDropdownCardLogo.setImageResource(R.drawable.fahipay_logo) + b.ivDropdownCardLogo.visibility = View.VISIBLE + } + acc.bank == "MIB" -> { + val hash = acc.profileImageHash + val cached = hash?.let { dropdownProfileImageCache[it] } + val imageView = b.ivDropdownCardLogo + imageView.tag = hash + if (cached != null) { + imageView.setImageBitmap(cached) + } else { + imageView.setImageResource(R.drawable.mib_logo) + if (hash != null) { + val app = requireActivity().application as BasedBankApp + viewLifecycleOwner.lifecycleScope.launch { + val bitmap = withContext(Dispatchers.IO) { + try { + val sess = app.anyMibSession() ?: return@withContext null + val b64 = app.anyMibFlow()?.fetchProfileImage(sess, hash) ?: return@withContext null + val bytes = android.util.Base64.decode(b64, android.util.Base64.DEFAULT) + BitmapFactory.decodeByteArray(bytes, 0, bytes.size) + } catch (_: Exception) { null } + } + if (bitmap != null) { + dropdownProfileImageCache[hash] = bitmap + if (imageView.tag == hash) imageView.setImageBitmap(bitmap) + } + } + } + } + imageView.visibility = View.VISIBLE + } + else -> b.ivDropdownCardLogo.visibility = View.GONE + } return b.root } diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/TransferFragment.kt b/app/src/main/java/sh/sar/basedbank/ui/home/TransferFragment.kt index 5d0642d..d37ece6 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/TransferFragment.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/TransferFragment.kt @@ -62,6 +62,7 @@ import sh.sar.basedbank.util.CredentialStore import sh.sar.basedbank.util.AccountInputParser import sh.sar.basedbank.util.PaymvQrParser import sh.sar.basedbank.util.bmlapi.BmlCardParser +import sh.sar.basedbank.util.bmlapi.BmlDashboardParser import sh.sar.basedbank.util.RecentPick import sh.sar.basedbank.util.RecentsCache import sh.sar.basedbank.util.ReceiptStore @@ -85,6 +86,7 @@ class TransferFragment : Fragment() { private var resolvedAccountNumber = "" private var resolvedRecipientName = "" private var resolvedBankName = "" + private var resolvedToOwnAccount: BankAccount? = null // Selected Fahipay service when source is Fahipay and destination is a phone number // Values: "FAHIPAY_TRANSFER", "RAASTAS", "OOREDOO_BILL" @@ -206,6 +208,7 @@ class TransferFragment : Fragment() { viewModel.hideAmounts.observe(viewLifecycleOwner) { accountDropdownAdapter?.notifyDataSetChanged() selectedAccount?.let { showFromCard(it) } + resolvedToOwnAccount?.let { showToCard(it) } } childFragmentManager.setFragmentResultListener(ContactPickerSheetFragment.REQUEST_KEY, viewLifecycleOwner) { _, bundle -> @@ -281,6 +284,9 @@ class TransferFragment : Fragment() { // Show merchant in the "To" card — clear button hidden (can't change recipient for QR) binding.tvToAccountName.text = info.merchantName binding.tvToBankBic.text = info.merchantAddress.ifBlank { "BML Merchant" } + binding.tvToAccountDetails.visibility = View.GONE + binding.tvToBalance.visibility = View.GONE + binding.ivToPhoto.scaleType = android.widget.ImageView.ScaleType.CENTER_CROP binding.ivToPhoto.setImageBitmap(makeInitialsBitmap(info.merchantName, "#0066A1")) binding.btnClearToInfo.visibility = View.GONE binding.cardToInfo.visibility = View.VISIBLE @@ -366,34 +372,102 @@ class TransferFragment : Fragment() { val bankLabel = when (account.bank) { "BML" -> "BML" "FAHIPAY" -> "FP" + "MIB" -> "MIB" else -> null } - val typeLabel = when { - account.profileType == "BML_PREPAID" -> "Prepaid Card" - account.profileType == "BML_CREDIT" -> "Credit Card" - account.profileType == "BML_DEBIT" -> "Debit Card" - account.accountTypeName.isNotBlank() -> account.accountTypeName - else -> account.profileType - } + val typeLabel = AccountListParser.from(account)?.typeLabel + ?: if (account.bank == "BML") BmlDashboardParser.productLabel(account.accountTypeName) + else account.accountTypeName.ifBlank { account.profileType } val hide = viewModel.hideAmounts.value ?: false val isDebitCard = account.profileType == "BML_DEBIT" val balancePart = if (isDebitCard) null else "${account.currencyName} ${account.availableBalance}" binding.tvFromAccountName.text = account.accountBriefName binding.tvFromAccountNumber.text = account.accountNumber + binding.tvFromAccountDetails.text = listOfNotNull(bankLabel, typeLabel).joinToString(" · ") val balanceDisplay = balancePart?.let { if (hide) maskAmount(it) else it } - binding.tvFromAccountDetails.text = listOfNotNull(bankLabel, typeLabel, balanceDisplay).joinToString(" · ") - val networkIcon = BmlCardParser.cardNetworkIcon(account) - if (networkIcon != null) { - binding.ivFromPhoto.setImageResource(networkIcon) + if (balanceDisplay != null) { + binding.tvFromBalance.text = balanceDisplay + binding.tvFromBalance.visibility = View.VISIBLE } else { - binding.ivFromPhoto.setImageBitmap(makeInitialsBitmap(account.accountBriefName, colorHex)) + binding.tvFromBalance.visibility = View.GONE + } + val networkIcon = BmlCardParser.cardNetworkIcon(account) + when { + networkIcon != null -> { + binding.ivFromPhoto.scaleType = android.widget.ImageView.ScaleType.FIT_CENTER + binding.ivFromPhoto.setImageResource(networkIcon) + } + account.bank == "BML" -> { + binding.ivFromPhoto.scaleType = android.widget.ImageView.ScaleType.FIT_CENTER + binding.ivFromPhoto.setImageResource(R.drawable.bml_logo_vector) + } + account.bank == "FAHIPAY" -> { + binding.ivFromPhoto.scaleType = android.widget.ImageView.ScaleType.FIT_CENTER + binding.ivFromPhoto.setImageResource(R.drawable.fahipay_logo) + } + else -> { + binding.ivFromPhoto.scaleType = android.widget.ImageView.ScaleType.FIT_CENTER + binding.ivFromPhoto.setImageResource(R.drawable.mib_logo) + if (account.profileImageHash != null) loadFromPhoto(account.profileImageHash) + } } binding.tilFrom.visibility = View.GONE binding.cardFromInfo.visibility = View.VISIBLE + } - if (account.bank != "BML" && account.profileImageHash != null) { - loadFromPhoto(account.profileImageHash) + private fun showToCard(account: BankAccount) { + resolvedToOwnAccount = account + val colorHex = when (account.bank) { + "BML" -> "#0066A1" + "FAHIPAY" -> "#15BEA7" + else -> "#FE860E" + } + val bankLabel = when (account.bank) { + "BML" -> "BML" + "FAHIPAY" -> "FP" + "MIB" -> "MIB" + else -> null + } + val typeLabel = AccountListParser.from(account)?.typeLabel + ?: if (account.bank == "BML") BmlDashboardParser.productLabel(account.accountTypeName) + else account.accountTypeName.ifBlank { account.profileType } + + val hide = viewModel.hideAmounts.value ?: false + val isDebitCard = account.profileType == "BML_DEBIT" + val balancePart = if (isDebitCard) null else AccountListParser.from(account)?.balance + ?: "${account.currencyName} ${account.availableBalance}" + + binding.tvToAccountName.text = account.accountBriefName + binding.tvToBankBic.text = account.accountNumber + binding.tvToAccountDetails.text = listOfNotNull(bankLabel, typeLabel).joinToString(" · ") + binding.tvToAccountDetails.visibility = View.VISIBLE + val balanceDisplay = balancePart?.let { if (hide) maskAmount(it) else it } + if (balanceDisplay != null) { + binding.tvToBalance.text = balanceDisplay + binding.tvToBalance.visibility = View.VISIBLE + } else { + binding.tvToBalance.visibility = View.GONE + } + val networkIcon = BmlCardParser.cardNetworkIcon(account) + when { + networkIcon != null -> { + binding.ivToPhoto.scaleType = android.widget.ImageView.ScaleType.FIT_CENTER + binding.ivToPhoto.setImageResource(networkIcon) + } + account.bank == "BML" -> { + binding.ivToPhoto.scaleType = android.widget.ImageView.ScaleType.FIT_CENTER + binding.ivToPhoto.setImageResource(R.drawable.bml_logo_vector) + } + account.bank == "FAHIPAY" -> { + binding.ivToPhoto.scaleType = android.widget.ImageView.ScaleType.FIT_CENTER + binding.ivToPhoto.setImageResource(R.drawable.fahipay_logo) + } + else -> { + binding.ivToPhoto.scaleType = android.widget.ImageView.ScaleType.FIT_CENTER + binding.ivToPhoto.setImageResource(R.drawable.mib_logo) + if (account.profileImageHash != null) loadToPhoto(account.profileImageHash, isProfile = true) + } } } @@ -406,7 +480,10 @@ class TransferFragment : Fragment() { val bytes = Base64.decode(base64, Base64.DEFAULT) val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size) ?: return@launch withContext(Dispatchers.Main) { - if (_binding != null) binding.ivFromPhoto.setImageBitmap(bitmap) + if (_binding != null) { + binding.ivFromPhoto.scaleType = android.widget.ImageView.ScaleType.CENTER_CROP + binding.ivFromPhoto.setImageBitmap(bitmap) + } } } catch (_: Exception) { } } @@ -422,6 +499,7 @@ class TransferFragment : Fragment() { binding.btnClearToInfo.setOnClickListener { resolvedAccountNumber = "" resolvedRecipientName = "" + resolvedToOwnAccount = null selectedFahipayService = null binding.cardToInfo.visibility = View.GONE binding.layoutServiceSelector.visibility = View.INVISIBLE @@ -437,6 +515,7 @@ class TransferFragment : Fragment() { if (binding.cardToInfo.visibility == View.VISIBLE) { resolvedAccountNumber = "" resolvedRecipientName = "" + resolvedToOwnAccount = null binding.cardToInfo.visibility = View.GONE binding.tilTo.visibility = View.VISIBLE binding.btnPickContact.visibility = View.VISIBLE @@ -546,9 +625,16 @@ class TransferFragment : Fragment() { resolvedRecipientName = info.accountName resolvedBankName = info.bankId - binding.tvToAccountName.text = displayName - binding.tvToBankBic.text = "${info.accountNumber} · ${info.bankId}" - binding.ivToPhoto.setImageBitmap(makeInitialsBitmap(displayName, colorHex)) + if (matchedAcc != null) { + showToCard(matchedAcc) + } else { + binding.tvToAccountName.text = displayName + binding.tvToBankBic.text = "${info.accountNumber} · ${info.bankId}" + binding.tvToAccountDetails.visibility = View.GONE + binding.tvToBalance.visibility = View.GONE + binding.ivToPhoto.scaleType = android.widget.ImageView.ScaleType.CENTER_CROP + binding.ivToPhoto.setImageBitmap(makeInitialsBitmap(displayName, colorHex)) + } binding.tilTo.visibility = View.GONE binding.btnPickContact.visibility = View.GONE binding.btnScanQr.visibility = View.GONE @@ -673,9 +759,18 @@ class TransferFragment : Fragment() { val contacts = viewModel.contacts.value ?: emptyList() resolvedBankName = contacts.firstOrNull { it.benefAccount == accountNumber }?.benefBankName ?: "" - binding.tvToAccountName.text = displayName - binding.tvToBankBic.text = subtitle - binding.ivToPhoto.setImageBitmap(makeInitialsBitmap(displayName, colorHex)) + val ownAccount = viewModel.accounts.value?.firstOrNull { it.accountNumber == accountNumber } + if (ownAccount != null) { + showToCard(ownAccount) + } else { + resolvedToOwnAccount = null + binding.tvToAccountName.text = displayName + binding.tvToBankBic.text = subtitle + binding.tvToAccountDetails.visibility = View.GONE + binding.tvToBalance.visibility = View.GONE + binding.ivToPhoto.scaleType = android.widget.ImageView.ScaleType.CENTER_CROP + binding.ivToPhoto.setImageBitmap(makeInitialsBitmap(displayName, colorHex)) + } binding.tilTo.visibility = View.GONE binding.btnPickContact.visibility = View.GONE binding.btnScanQr.visibility = View.GONE @@ -1479,6 +1574,7 @@ class TransferFragment : Fragment() { resolvedAccountNumber = "" resolvedRecipientName = "" resolvedBankName = "" + resolvedToOwnAccount = null selectedFahipayService = null binding.cardToInfo.visibility = View.GONE binding.chipGroupService.visibility = View.GONE @@ -1505,7 +1601,10 @@ class TransferFragment : Fragment() { val bytes = Base64.decode(base64, Base64.DEFAULT) val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size) ?: return@launch withContext(Dispatchers.Main) { - if (_binding != null) binding.ivToPhoto.setImageBitmap(bitmap) + if (_binding != null) { + binding.ivToPhoto.scaleType = android.widget.ImageView.ScaleType.CENTER_CROP + binding.ivToPhoto.setImageBitmap(bitmap) + } } } catch (_: Exception) { } } @@ -1633,8 +1732,18 @@ class TransferFragment : Fragment() { val ownerPrefix = if (isBmlAccount && acc.profileName.isNotBlank()) "${acc.profileName} · " else "" val hide = viewModel.hideAmounts.value ?: false b.tvDropdownAccountName.text = "$ownerPrefix${acc.accountBriefName}" + val displayData = AccountListParser.from(acc) + val typeLabel = displayData?.typeLabel + ?: if (acc.bank == "BML") BmlDashboardParser.productLabel(acc.accountTypeName) + else acc.accountTypeName.trim() b.tvDropdownAccountNumber.text = if (inactive) "${acc.accountNumber} · ${acc.statusDesc}" else acc.accountNumber - val balance = AccountListParser.from(acc)?.balance ?: "" + if (typeLabel.isNotBlank()) { + b.tvDropdownAccountType.text = typeLabel + b.tvDropdownAccountType.visibility = View.VISIBLE + } else { + b.tvDropdownAccountType.visibility = View.GONE + } + val balance = displayData?.balance ?: "" b.tvDropdownBalance.text = if (hide && balance.isNotBlank()) maskAmount(balance) else balance b.root.alpha = if (inactive) 0.4f else 1f val networkIcon = BmlCardParser.cardNetworkIcon(acc) diff --git a/app/src/main/res/layout/fragment_pay_mv_qr.xml b/app/src/main/res/layout/fragment_pay_mv_qr.xml index ae28bdf..1daeb6c 100644 --- a/app/src/main/res/layout/fragment_pay_mv_qr.xml +++ b/app/src/main/res/layout/fragment_pay_mv_qr.xml @@ -55,6 +55,7 @@ + + + + android:textColor="?attr/colorOnSurfaceVariant" + android:fontFamily="monospace" /> + + + + + + diff --git a/app/src/main/res/layout/item_picker_row.xml b/app/src/main/res/layout/item_picker_row.xml index 38024e0..3f392dd 100644 --- a/app/src/main/res/layout/item_picker_row.xml +++ b/app/src/main/res/layout/item_picker_row.xml @@ -47,4 +47,13 @@ + +