From 3ab75bff923c892041d15e6afc7254f616908b93 Mon Sep 17 00:00:00 2001 From: Shihaam Abdul Rahman Date: Mon, 18 May 2026 05:52:18 +0500 Subject: [PATCH] fix contact add with multi BML logins --- .../ui/home/AddContactSheetFragment.kt | 52 +++++++++++++++---- .../sar/basedbank/ui/home/TransferFragment.kt | 4 +- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/AddContactSheetFragment.kt b/app/src/main/java/sh/sar/basedbank/ui/home/AddContactSheetFragment.kt index bfa5aab..a390fe1 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/AddContactSheetFragment.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/AddContactSheetFragment.kt @@ -12,6 +12,9 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ArrayAdapter +import android.widget.Filter +import android.widget.Filterable +import android.widget.TextView import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts import androidx.core.content.ContextCompat @@ -20,6 +23,7 @@ import androidx.swiperefreshlayout.widget.CircularProgressDrawable import androidx.lifecycle.lifecycleScope import com.google.android.material.bottomsheet.BottomSheetDialogFragment import sh.sar.basedbank.util.ContactsCache +import sh.sar.basedbank.util.CredentialStore import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -45,7 +49,9 @@ class AddContactSheetFragment : BottomSheetDialogFragment() { private data class DestinationOption( val label: String, val isBml: Boolean, - val mibProfile: MibProfile? = null + val mibProfile: MibProfile? = null, + val bmlLoginId: String? = null, + val subtitle: String = "" ) private var destinations: List = emptyList() @@ -88,18 +94,44 @@ class AddContactSheetFragment : BottomSheetDialogFragment() { for (profile in app.mibProfiles) { list.add(DestinationOption("MIB · ${profile.name}", isBml = false, mibProfile = profile)) } - if (app.anyBmlSession() != null) { - list.add(DestinationOption("BML · Personal", isBml = true)) + val store = CredentialStore(requireContext()) + for ((loginId, _) in app.bmlSessions) { + val ownerName = store.loadBmlUserProfile(loginId)?.fullName?.takeIf { it.isNotBlank() } ?: loginId + val profileName = app.bmlAccounts.firstOrNull { it.loginTag == "bml_$loginId" }?.profileName ?: "" + list.add(DestinationOption("BML · $ownerName", isBml = true, bmlLoginId = loginId, subtitle = profileName)) } return list } private fun setupDestinationDropdown() { - val labels = destinations.map { it.label } - val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_dropdown_item_1line, labels) + val adapter = object : ArrayAdapter(requireContext(), android.R.layout.simple_list_item_2, destinations) { + override fun getView(position: Int, convertView: View?, parent: ViewGroup) = + getDropDownView(position, convertView, parent) + + override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View { + val view = convertView ?: LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_2, parent, false) + val opt = destinations[position] + view.findViewById(android.R.id.text1).text = opt.label + val text2 = view.findViewById(android.R.id.text2) + if (opt.subtitle.isNotBlank()) { + text2.text = opt.subtitle + text2.visibility = View.VISIBLE + } else { + text2.visibility = View.GONE + } + return view + } + + override fun getFilter() = object : Filter() { + override fun performFiltering(c: CharSequence?) = FilterResults().apply { values = destinations; count = destinations.size } + override fun publishResults(c: CharSequence?, r: FilterResults?) = notifyDataSetChanged() + override fun convertResultToString(r: Any?) = "" + } + } binding.actvDestination.setAdapter(adapter) binding.actvDestination.setOnItemClickListener { _, _, position, _ -> selectedDest = destinations[position] + binding.actvDestination.setText(destinations[position].label, false) clearLookupResult() updateMibOnlyVisibility() binding.btnSave.isEnabled = false @@ -204,7 +236,8 @@ class AddContactSheetFragment : BottomSheetDialogFragment() { } private fun lookupForBml(input: String): BmlAccountValidation? { - val bmlSess = app.anyBmlSession() ?: return null + val loginId = selectedDest?.bmlLoginId ?: return null + val bmlSess = app.bmlSessions[loginId] ?: return null val bmlFlow = BmlLoginFlow() // 1) Try BML validate @@ -378,7 +411,8 @@ class AddContactSheetFragment : BottomSheetDialogFragment() { } private fun saveToBml(alias: String): Boolean { - val bmlSess = app.anyBmlSession() ?: return false + val loginId = selectedDest?.bmlLoginId ?: return false + val bmlSess = app.bmlSessions[loginId] ?: return false val lookup = bmlLookup ?: return false val bmlFlow = BmlLoginFlow() val account = lookup.account @@ -445,8 +479,8 @@ class AddContactSheetFragment : BottomSheetDialogFragment() { requireActivity().lifecycleScope.launch(Dispatchers.IO) { try { if (dest.isBml) { - val bmlSess = app.anyBmlSession() ?: return@launch - val loginId = app.bmlSessions.entries.firstOrNull { it.value == bmlSess }?.key ?: "" + val loginId = dest.bmlLoginId ?: return@launch + val bmlSess = app.bmlSessions[loginId] ?: return@launch val fresh = BmlLoginFlow().fetchContacts(bmlSess, loginId) val existing = viewModel.contacts.value ?: emptyList() val merged = existing.filter { it.benefCategoryId != "BML" } + fresh 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 1f502a5..96593d8 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 @@ -1009,7 +1009,9 @@ class TransferFragment : Fragment() { .also { it.root.tag = it } } val inactive = (acc.profileType == "BML_PREPAID" || acc.profileType == "BML_CREDIT") && !acc.statusDesc.equals("Active", ignoreCase = true) - b.tvDropdownAccountName.text = acc.accountBriefName + val isBmlAccount = acc.profileType.startsWith("BML") + val ownerPrefix = if (isBmlAccount && acc.profileName.isNotBlank()) "${acc.profileName} · " else "" + b.tvDropdownAccountName.text = "$ownerPrefix${acc.accountBriefName}" b.tvDropdownAccountNumber.text = if (inactive) "${acc.accountNumber} · ${acc.statusDesc}" else acc.accountNumber b.tvDropdownBalance.text = "${acc.currencyName} ${acc.availableBalance}" b.root.alpha = if (inactive) 0.4f else 1f