optimize contact picker for usd contacts and transfer page
All checks were successful
Auto Tag on Version Change / check-version (push) Successful in 2s

This commit is contained in:
2026-05-16 14:50:07 +05:00
parent 480f4e42d7
commit 0a6a199e9e
3 changed files with 132 additions and 17 deletions

View File

@@ -153,17 +153,19 @@ class ContactPickerSheetFragment : BottomSheetDialogFragment() {
val account = accounts.firstOrNull { it.accountNumber == accountNumber }
val bundle = bundleOf(KEY_ACCOUNT_NUMBER to accountNumber, KEY_LABEL to label)
when {
account?.profileType == "BML_PREPAID" -> {
bundle.putBoolean(KEY_SKIP_LOOKUP, true)
account != null -> {
bundle.putString(KEY_SUBTITLE, "${account.accountNumber} · ${account.currencyName} ${account.availableBalance}")
bundle.putString(KEY_COLOR, "#FE860E")
}
contact != null && !contact.transferCyDesc.equals("MVR", ignoreCase = true) -> {
bundle.putBoolean(KEY_SKIP_LOOKUP, true)
contact != null -> {
bundle.putString(KEY_SUBTITLE, "${contact.benefBankName} · ${contact.benefAccount}")
bundle.putString(KEY_COLOR, contact.bankColor)
contact.customerImgHash?.let { bundle.putString(KEY_IMAGE_HASH, it) }
}
else -> {
bundle.putString(KEY_SUBTITLE, accountNumber)
bundle.putString(KEY_COLOR, "#607D8B")
}
}
setFragmentResult(REQUEST_KEY, bundle)
dismiss()
@@ -306,7 +308,6 @@ class ContactPickerSheetFragment : BottomSheetDialogFragment() {
const val REQUEST_KEY = "contact_picker"
const val KEY_ACCOUNT_NUMBER = "accountNumber"
const val KEY_LABEL = "label"
const val KEY_SKIP_LOOKUP = "skipLookup"
const val KEY_SUBTITLE = "subtitle"
const val KEY_COLOR = "color"
const val KEY_IMAGE_HASH = "imageHash"

View File

@@ -113,15 +113,11 @@ class TransferFragment : Fragment() {
childFragmentManager.setFragmentResultListener(ContactPickerSheetFragment.REQUEST_KEY, viewLifecycleOwner) { _, bundle ->
val accountNumber = bundle.getString(ContactPickerSheetFragment.KEY_ACCOUNT_NUMBER) ?: return@setFragmentResultListener
val label = bundle.getString(ContactPickerSheetFragment.KEY_LABEL) ?: ""
if (bundle.getBoolean(ContactPickerSheetFragment.KEY_SKIP_LOOKUP, false)) {
val subtitle = bundle.getString(ContactPickerSheetFragment.KEY_SUBTITLE) ?: accountNumber
val colorHex = bundle.getString(ContactPickerSheetFragment.KEY_COLOR) ?: "#607D8B"
val imageHash = bundle.getString(ContactPickerSheetFragment.KEY_IMAGE_HASH)
prefillToDirectly(accountNumber, label, subtitle, colorHex, imageHash)
} else {
prefillToFromContact(accountNumber, label)
}
val label = bundle.getString(ContactPickerSheetFragment.KEY_LABEL) ?: ""
val subtitle = bundle.getString(ContactPickerSheetFragment.KEY_SUBTITLE) ?: accountNumber
val colorHex = bundle.getString(ContactPickerSheetFragment.KEY_COLOR) ?: "#607D8B"
val imageHash = bundle.getString(ContactPickerSheetFragment.KEY_IMAGE_HASH)
prefillToDirectly(accountNumber, label, subtitle, colorHex, imageHash)
}
binding.btnPickContact.setOnClickListener {
@@ -148,21 +144,64 @@ class TransferFragment : Fragment() {
}
private fun setupFromDropdown() {
binding.btnClearFromInfo.setOnClickListener {
selectedAccount = null
binding.tilAmount.prefixText = null
binding.cardFromInfo.visibility = View.GONE
binding.tilFrom.visibility = View.VISIBLE
binding.actvFrom.setText("", false)
}
viewModel.accounts.observe(viewLifecycleOwner) { accounts ->
val adapter = AccountDropdownAdapter(requireContext(), accounts)
binding.actvFrom.setAdapter(adapter)
// No default selection — user must explicitly pick a source account
binding.actvFrom.setOnItemClickListener { _, _, position, _ ->
val picked = adapter.getAccount(position) ?: return@setOnItemClickListener
selectedAccount = picked
binding.actvFrom.setText(picked.toDisplayString(), false)
updateAmountPrefix(picked)
showFromCard(picked)
}
}
}
private fun showFromCard(account: MibAccount) {
val isBml = account.profileType.startsWith("BML")
val colorHex = if (isBml) "#0066A1" else "#FE860E"
val bankLabel = if (isBml) "BML" else "MIB"
val typeLabel = when {
account.profileType == "BML_PREPAID" -> "Prepaid Card"
account.accountTypeName.isNotBlank() -> account.accountTypeName
else -> account.profileType
}
binding.tvFromAccountName.text = account.accountBriefName
binding.tvFromAccountNumber.text = account.accountNumber
binding.tvFromAccountDetails.text = "$bankLabel · $typeLabel · ${account.currencyName} ${account.availableBalance}"
binding.ivFromPhoto.setImageBitmap(makeInitialsBitmap(account.accountBriefName, colorHex))
binding.tilFrom.visibility = View.GONE
binding.cardFromInfo.visibility = View.VISIBLE
if (!isBml && account.profileImageHash != null) {
loadFromPhoto(account.profileImageHash)
}
}
private fun loadFromPhoto(hash: String) {
val sess = session ?: return
val app = requireActivity().application as BasedBankApp
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
try {
val base64 = app.mibLoginFlow.fetchProfileImage(sess, hash) ?: return@launch
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)
}
} catch (_: Exception) { }
}
}
private fun updateAmountPrefix(account: MibAccount) {
binding.tilAmount.prefixText = if (account.currencyName == "USD") "USD " else "MVR "
}
@@ -606,6 +645,8 @@ class TransferFragment : Fragment() {
private fun clearForm() {
selectedAccount = null
binding.actvFrom.setText("", false)
binding.cardFromInfo.visibility = View.GONE
binding.tilFrom.visibility = View.VISIBLE
binding.tilAmount.prefixText = null
binding.etAmount.setText("")
binding.etRemarks.setText("")

View File

@@ -45,6 +45,79 @@
</com.google.android.material.textfield.TextInputLayout>
<!-- Selected source account info card -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/cardFromInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_marginBottom="16dp"
app:cardCornerRadius="4dp"
app:cardElevation="0dp"
app:strokeWidth="1dp"
app:strokeColor="?attr/colorPrimary">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingStart="12dp"
android:paddingEnd="4dp"
android:paddingVertical="12dp"
android:gravity="center_vertical">
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/ivFromPhoto"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginEnd="12dp"
app:shapeAppearanceOverlay="@style/ShapeAppearance.Circle" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/tvFromAccountName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?attr/textAppearanceBodyMedium"
android:textStyle="bold"
android:textColor="?attr/colorOnSurface" />
<TextView
android:id="@+id/tvFromAccountNumber"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:textAppearance="?attr/textAppearanceBodySmall"
android:textColor="?attr/colorOnSurfaceVariant"
android:fontFamily="monospace" />
<TextView
android:id="@+id/tvFromAccountDetails"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:textAppearance="?attr/textAppearanceBodySmall"
android:textColor="?attr/colorOnSurfaceVariant" />
</LinearLayout>
<ImageButton
android:id="@+id/btnClearFromInfo"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@android:drawable/ic_menu_close_clear_cancel"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/transfer_clear_recipient" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- To field row: input + pick contact button -->
<LinearLayout
android:layout_width="match_parent"