hide money value in transfer drop down with privacy mode on
All checks were successful
Auto Tag on Version Change / check-version (push) Successful in 4s

This commit is contained in:
2026-05-23 22:42:48 +05:00
parent a6a1f28144
commit 339dae8a37
2 changed files with 33 additions and 7 deletions

View File

@@ -145,6 +145,7 @@ class ContactPickerSheetFragment : BottomSheetDialogFragment() {
viewModel.contacts.observe(viewLifecycleOwner) { pagerAdapter.rebuildAll() }
viewModel.accounts.observe(viewLifecycleOwner) { pagerAdapter.rebuildAll() }
viewModel.hideAmounts.observe(viewLifecycleOwner) { pagerAdapter.rebuildAll() }
(activity as? HomeActivity)?.loadAllContacts()
}
@@ -183,6 +184,7 @@ class ContactPickerSheetFragment : BottomSheetDialogFragment() {
private fun buildPageItems(tabTag: String?): List<ContactPickerAdapter.PickerItem> {
val search = binding.etSheetSearch.text?.toString()?.trim() ?: ""
val hide = viewModel.hideAmounts.value ?: false
val items = mutableListOf<ContactPickerAdapter.PickerItem>()
if (tabTag == RECENTS_TAG) {
@@ -223,10 +225,11 @@ 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
items.add(ContactPickerAdapter.PickerItem.Row(
accountNumber = acc.accountNumber,
displayName = acc.accountBriefName,
subtitle = "${acc.accountNumber} · ${acc.currencyName} ${acc.availableBalance}",
subtitle = "${acc.accountNumber} · ${acc.currencyName} $accBal",
colorHex = "#FE860E",
isSameAsFrom = isSame,
imageHash = acc.profileImageHash,
@@ -246,10 +249,11 @@ 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
items.add(ContactPickerAdapter.PickerItem.Row(
accountNumber = acc.accountNumber,
displayName = acc.accountBriefName,
subtitle = "${acc.accountNumber} · ${acc.currencyName} ${acc.availableBalance}",
subtitle = "${acc.accountNumber} · ${acc.currencyName} $cardBal",
colorHex = "#FE860E",
isSameAsFrom = isSame,
imageHash = acc.profileImageHash,
@@ -306,6 +310,11 @@ class ContactPickerSheetFragment : BottomSheetDialogFragment() {
}
}
private fun maskAmount(formatted: String): String {
val currency = formatted.substringBefore(' ', formatted)
return "$currency ••••••"
}
private fun currencyMismatchReason(fromCurrency: String, toCurrency: String): String? =
if (fromCurrency == "MVR" && toCurrency == "USD") "Cannot transfer from MVR to USD account" else null

View File

@@ -108,6 +108,7 @@ class TransferFragment : Fragment() {
val toAvatar: Bitmap?
)
private var pendingBmlTransfer: PendingBmlTransfer? = null
private var accountDropdownAdapter: AccountDropdownAdapter? = null
private val qrLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode != Activity.RESULT_OK) return@registerForActivityResult
@@ -178,6 +179,11 @@ class TransferFragment : Fragment() {
setupFromDropdown()
setupAccountLookup()
viewModel.hideAmounts.observe(viewLifecycleOwner) {
accountDropdownAdapter?.notifyDataSetChanged()
selectedAccount?.let { showFromCard(it) }
}
childFragmentManager.setFragmentResultListener(ContactPickerSheetFragment.REQUEST_KEY, viewLifecycleOwner) { _, bundle ->
val accountNumber = bundle.getString(ContactPickerSheetFragment.KEY_ACCOUNT_NUMBER) ?: return@setFragmentResultListener
val label = bundle.getString(ContactPickerSheetFragment.KEY_LABEL) ?: ""
@@ -236,6 +242,13 @@ class TransferFragment : Fragment() {
binding.tilTo.endIconDrawable = ContextCompat.getDrawable(requireContext(), android.R.drawable.ic_menu_search)
}
// ── Sensitive masking helpers ─────────────────────────────────────────────
private fun maskAmount(formatted: String): String {
val currency = formatted.substringBefore(' ', formatted)
return "$currency ••••••"
}
private fun setupFromDropdown() {
binding.btnClearFromInfo.setOnClickListener {
selectedAccount = null
@@ -247,11 +260,11 @@ class TransferFragment : Fragment() {
}
viewModel.accounts.observe(viewLifecycleOwner) { accounts ->
val adapter = AccountDropdownAdapter(requireContext(), accounts)
binding.actvFrom.setAdapter(adapter)
accountDropdownAdapter = AccountDropdownAdapter(requireContext(), accounts)
binding.actvFrom.setAdapter(accountDropdownAdapter)
binding.actvFrom.setOnItemClickListener { _, _, position, _ ->
val picked = adapter.getAccount(position) ?: return@setOnItemClickListener
val picked = accountDropdownAdapter?.getAccount(position) ?: return@setOnItemClickListener
selectedAccount = picked
updateAmountPrefix(picked)
showFromCard(picked)
@@ -290,9 +303,11 @@ class TransferFragment : Fragment() {
else -> account.profileType
}
val hide = viewModel.hideAmounts.value ?: false
val balancePart = "${account.currencyName} ${account.availableBalance}"
binding.tvFromAccountName.text = account.accountBriefName
binding.tvFromAccountNumber.text = account.accountNumber
binding.tvFromAccountDetails.text = listOfNotNull(bankLabel, typeLabel, "${account.currencyName} ${account.availableBalance}").joinToString(" · ")
binding.tvFromAccountDetails.text = listOfNotNull(bankLabel, typeLabel, if (hide) maskAmount(balancePart) else balancePart).joinToString(" · ")
binding.ivFromPhoto.setImageBitmap(makeInitialsBitmap(account.accountBriefName, colorHex))
binding.tilFrom.visibility = View.GONE
binding.cardFromInfo.visibility = View.VISIBLE
@@ -1389,9 +1404,11 @@ class TransferFragment : Fragment() {
val inactive = (acc.profileType == "BML_PREPAID" || acc.profileType == "BML_CREDIT" || acc.profileType == "BML_DEBIT") && !acc.statusDesc.equals("Active", ignoreCase = true)
val isBmlAccount = acc.bank == "BML"
val ownerPrefix = if (isBmlAccount && acc.profileName.isNotBlank()) "${acc.profileName} · " else ""
val hide = viewModel.hideAmounts.value ?: false
b.tvDropdownAccountName.text = "$ownerPrefix${acc.accountBriefName}"
b.tvDropdownAccountNumber.text = if (inactive) "${acc.accountNumber} · ${acc.statusDesc}" else acc.accountNumber
b.tvDropdownBalance.text = AccountListParser.from(acc)?.balance ?: ""
val balance = AccountListParser.from(acc)?.balance ?: ""
b.tvDropdownBalance.text = if (hide && balance.isNotBlank()) maskAmount(balance) else balance
b.root.alpha = if (inactive) 0.4f else 1f
b.root
}