fix contact add with multi BML logins

This commit is contained in:
2026-05-18 05:52:18 +05:00
parent 1753d648bd
commit 3ab75bff92
2 changed files with 46 additions and 10 deletions
@@ -12,6 +12,9 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import android.widget.Filter
import android.widget.Filterable
import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
@@ -20,6 +23,7 @@ import androidx.swiperefreshlayout.widget.CircularProgressDrawable
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import sh.sar.basedbank.util.ContactsCache import sh.sar.basedbank.util.ContactsCache
import sh.sar.basedbank.util.CredentialStore
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@@ -45,7 +49,9 @@ class AddContactSheetFragment : BottomSheetDialogFragment() {
private data class DestinationOption( private data class DestinationOption(
val label: String, val label: String,
val isBml: Boolean, val isBml: Boolean,
val mibProfile: MibProfile? = null val mibProfile: MibProfile? = null,
val bmlLoginId: String? = null,
val subtitle: String = ""
) )
private var destinations: List<DestinationOption> = emptyList() private var destinations: List<DestinationOption> = emptyList()
@@ -88,18 +94,44 @@ class AddContactSheetFragment : BottomSheetDialogFragment() {
for (profile in app.mibProfiles) { for (profile in app.mibProfiles) {
list.add(DestinationOption("MIB · ${profile.name}", isBml = false, mibProfile = profile)) list.add(DestinationOption("MIB · ${profile.name}", isBml = false, mibProfile = profile))
} }
if (app.anyBmlSession() != null) { val store = CredentialStore(requireContext())
list.add(DestinationOption("BML · Personal", isBml = true)) 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 return list
} }
private fun setupDestinationDropdown() { private fun setupDestinationDropdown() {
val labels = destinations.map { it.label } val adapter = object : ArrayAdapter<DestinationOption>(requireContext(), android.R.layout.simple_list_item_2, destinations) {
val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_dropdown_item_1line, labels) 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<TextView>(android.R.id.text1).text = opt.label
val text2 = view.findViewById<TextView>(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.setAdapter(adapter)
binding.actvDestination.setOnItemClickListener { _, _, position, _ -> binding.actvDestination.setOnItemClickListener { _, _, position, _ ->
selectedDest = destinations[position] selectedDest = destinations[position]
binding.actvDestination.setText(destinations[position].label, false)
clearLookupResult() clearLookupResult()
updateMibOnlyVisibility() updateMibOnlyVisibility()
binding.btnSave.isEnabled = false binding.btnSave.isEnabled = false
@@ -204,7 +236,8 @@ class AddContactSheetFragment : BottomSheetDialogFragment() {
} }
private fun lookupForBml(input: String): BmlAccountValidation? { 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() val bmlFlow = BmlLoginFlow()
// 1) Try BML validate // 1) Try BML validate
@@ -378,7 +411,8 @@ class AddContactSheetFragment : BottomSheetDialogFragment() {
} }
private fun saveToBml(alias: String): Boolean { 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 lookup = bmlLookup ?: return false
val bmlFlow = BmlLoginFlow() val bmlFlow = BmlLoginFlow()
val account = lookup.account val account = lookup.account
@@ -445,8 +479,8 @@ class AddContactSheetFragment : BottomSheetDialogFragment() {
requireActivity().lifecycleScope.launch(Dispatchers.IO) { requireActivity().lifecycleScope.launch(Dispatchers.IO) {
try { try {
if (dest.isBml) { if (dest.isBml) {
val bmlSess = app.anyBmlSession() ?: return@launch val loginId = dest.bmlLoginId ?: return@launch
val loginId = app.bmlSessions.entries.firstOrNull { it.value == bmlSess }?.key ?: "" val bmlSess = app.bmlSessions[loginId] ?: return@launch
val fresh = BmlLoginFlow().fetchContacts(bmlSess, loginId) val fresh = BmlLoginFlow().fetchContacts(bmlSess, loginId)
val existing = viewModel.contacts.value ?: emptyList() val existing = viewModel.contacts.value ?: emptyList()
val merged = existing.filter { it.benefCategoryId != "BML" } + fresh val merged = existing.filter { it.benefCategoryId != "BML" } + fresh
@@ -1009,7 +1009,9 @@ class TransferFragment : Fragment() {
.also { it.root.tag = it } .also { it.root.tag = it }
} }
val inactive = (acc.profileType == "BML_PREPAID" || acc.profileType == "BML_CREDIT") && !acc.statusDesc.equals("Active", ignoreCase = true) 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.tvDropdownAccountNumber.text = if (inactive) "${acc.accountNumber} · ${acc.statusDesc}" else acc.accountNumber
b.tvDropdownBalance.text = "${acc.currencyName} ${acc.availableBalance}" b.tvDropdownBalance.text = "${acc.currencyName} ${acc.availableBalance}"
b.root.alpha = if (inactive) 0.4f else 1f b.root.alpha = if (inactive) 0.4f else 1f