redesign contacts page
All checks were successful
Auto Tag on Version Change / check-version (push) Successful in 2s

This commit is contained in:
2026-05-15 19:12:40 +05:00
parent b9be7cd1a3
commit 253e5400d8
3 changed files with 100 additions and 151 deletions

View File

@@ -4,7 +4,7 @@
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2025-04-17T17:14:16.980728222Z">
<DropdownSelection timestamp="2026-05-15T13:54:16.798188666Z">
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="PhysicalDevice" identifier="serial=a703e092" />

View File

@@ -8,7 +8,6 @@ import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
@@ -25,14 +24,12 @@ class ContactsAdapter(
private var allContacts: List<MibBeneficiary> = emptyList()
private var displayed: List<MibBeneficiary> = emptyList()
private val imageCache = mutableMapOf<String, Bitmap>()
private val expandedPositions = mutableSetOf<Int>()
private var activeCategoryId: String? = null
private var searchQuery: String = ""
fun updateContacts(contacts: List<MibBeneficiary>) {
allContacts = contacts
expandedPositions.clear()
applyFilter()
}
@@ -46,7 +43,6 @@ class ContactsAdapter(
fun setFilter(categoryId: String?, query: String) {
activeCategoryId = categoryId
searchQuery = query
expandedPositions.clear()
applyFilter()
}
@@ -64,7 +60,30 @@ class ContactsAdapter(
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ItemContactBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder(binding)
val holder = ViewHolder(binding)
binding.btnTransferContact.setOnClickListener {
val pos = holder.bindingAdapterPosition
if (pos != RecyclerView.NO_POSITION) onTransferClick(displayed[pos])
}
binding.btnEditContact.setOnClickListener {
Toast.makeText(it.context, R.string.work_in_progress, Toast.LENGTH_SHORT).show()
}
binding.btnDeleteContact.setOnClickListener {
val pos = holder.bindingAdapterPosition
if (pos != RecyclerView.NO_POSITION) onDeleteClick(displayed[pos])
}
binding.root.setOnLongClickListener {
val pos = holder.bindingAdapterPosition
if (pos == RecyclerView.NO_POSITION) return@setOnLongClickListener false
val account = displayed[pos].benefAccount
val clipboard = it.context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
clipboard.setPrimaryClip(ClipData.newPlainText("account", account))
Toast.makeText(it.context, account, Toast.LENGTH_SHORT).show()
true
}
return holder
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
@@ -72,34 +91,7 @@ class ContactsAdapter(
val cachedImage = contact.customerImgHash?.let { hash ->
imageCache[hash] ?: run { onImageNeeded(hash); null }
}
holder.bind(contact, cachedImage, position in expandedPositions)
holder.binding.root.setOnClickListener {
val pos = holder.bindingAdapterPosition
if (pos == RecyclerView.NO_POSITION) return@setOnClickListener
if (pos in expandedPositions) expandedPositions.remove(pos) else expandedPositions.add(pos)
notifyItemChanged(pos)
}
holder.binding.root.setOnLongClickListener {
val ctx = it.context
val clipboard = ctx.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
clipboard.setPrimaryClip(ClipData.newPlainText("account", contact.benefAccount))
Toast.makeText(ctx, contact.benefAccount, Toast.LENGTH_SHORT).show()
true
}
holder.binding.btnTransferContact.setOnClickListener {
onTransferClick(contact)
}
holder.binding.btnEditContact.setOnClickListener {
Toast.makeText(it.context, R.string.work_in_progress, Toast.LENGTH_SHORT).show()
}
holder.binding.btnDeleteContact.setOnClickListener {
onDeleteClick(contact)
}
holder.bind(contact, cachedImage)
}
override fun getItemCount() = displayed.size
@@ -107,10 +99,10 @@ class ContactsAdapter(
inner class ViewHolder(val binding: ItemContactBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(contact: MibBeneficiary, photo: Bitmap?, expanded: Boolean) {
fun bind(contact: MibBeneficiary, photo: Bitmap?) {
binding.tvContactName.text = contact.benefNickName
binding.tvContactBank.text = contact.benefBankName
binding.tvContactAccount.text = "${contact.benefAccount} · ${contact.transferCyDesc}"
binding.tvContactAccount.text = contact.benefAccount
binding.tvRealName.text = "${contact.benefName} · ${contact.transferCyDesc} · ${contact.benefBankName}"
if (photo != null) {
binding.ivContactPhoto.setImageBitmap(photo)
@@ -119,12 +111,6 @@ class ContactsAdapter(
makeInitialsBitmap(contact.benefNickName, contact.bankColor)
)
}
binding.tvRealName.text = contact.benefName
val vis = if (expanded) View.VISIBLE else View.GONE
binding.dividerExpand.visibility = vis
binding.expandedSection.visibility = vis
}
private fun makeInitialsBitmap(name: String, colorHex: String): Bitmap {

View File

@@ -1,140 +1,103 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
android:paddingHorizontal="16dp"
android:paddingVertical="10dp">
<!-- Header row — same look as before -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/ivContactPhoto"
android:layout_width="48dp"
android:layout_height="48dp"
app:shapeAppearanceOverlay="@style/ShapeAppearance.Circle"
android:scaleType="centerCrop"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<LinearLayout
android:id="@+id/actionButtons"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingVertical="10dp">
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/ivContactPhoto"
android:layout_width="48dp"
android:layout_height="48dp"
app:shapeAppearanceOverlay="@style/ShapeAppearance.Circle"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:scaleType="centerCrop" />
<ImageButton
android:id="@+id/btnTransferContact"
android:layout_width="36dp"
android:layout_height="36dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_nav_generic"
android:padding="6dp"
android:contentDescription="@string/transfer" />
<ImageButton
android:id="@+id/btnEditContact"
android:layout_width="36dp"
android:layout_height="36dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_edit"
android:padding="6dp"
android:contentDescription="@string/contact_edit" />
<ImageButton
android:id="@+id/btnDeleteContact"
android:layout_width="36dp"
android:layout_height="36dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_delete"
android:padding="6dp"
android:tint="?attr/colorError"
android:contentDescription="@string/contact_delete" />
</LinearLayout>
<LinearLayout
android:id="@+id/textGroup"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginStart="12dp"
android:layout_marginEnd="4dp"
app:layout_constraintStart_toEndOf="@id/ivContactPhoto"
app:layout_constraintEnd_toStartOf="@id/actionButtons"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<TextView
android:id="@+id/tvContactName"
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:textAppearance="?attr/textAppearanceBodyMedium"
android:textStyle="bold"
android:textColor="?attr/colorOnSurface"
android:maxLines="1"
android:ellipsize="end"
app:layout_constraintStart_toEndOf="@id/ivContactPhoto"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/ivContactPhoto" />
<TextView
android:id="@+id/tvContactBank"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginTop="2dp"
android:textAppearance="?attr/textAppearanceBodySmall"
android:textColor="?attr/colorOnSurfaceVariant"
android:maxLines="1"
android:ellipsize="end"
app:layout_constraintStart_toEndOf="@id/ivContactPhoto"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvContactName" />
android:ellipsize="end" />
<TextView
android:id="@+id/tvContactAccount"
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginTop="1dp"
android:textAppearance="?attr/textAppearanceLabelSmall"
android:textAppearance="?attr/textAppearanceBodySmall"
android:textColor="?attr/colorOnSurfaceVariant"
android:maxLines="1"
android:ellipsize="end"
app:layout_constraintStart_toEndOf="@id/ivContactPhoto"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvContactBank"
app:layout_constraintBottom_toBottomOf="@id/ivContactPhoto" />
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- Divider + expanded section, hidden by default -->
<View
android:id="@+id/dividerExpand"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginHorizontal="16dp"
android:background="?attr/colorOutlineVariant"
android:visibility="gone" />
<LinearLayout
android:id="@+id/expandedSection"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingHorizontal="16dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:visibility="gone">
android:ellipsize="end" />
<TextView
android:id="@+id/tvRealName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?attr/textAppearanceLabelMedium"
android:layout_marginTop="1dp"
android:textAppearance="?attr/textAppearanceLabelSmall"
android:textColor="?attr/colorOnSurfaceVariant"
android:paddingBottom="8dp" />
<!-- Action buttons -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.google.android.material.button.MaterialButton
android:id="@+id/btnTransferContact"
style="@style/Widget.Material3.Button.OutlinedButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/transfer"
app:icon="@drawable/ic_nav_generic" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btnEditContact"
style="@style/Widget.Material3.Button.OutlinedButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="6dp"
android:text="@string/contact_edit"
app:icon="@drawable/ic_edit" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btnDeleteContact"
style="@style/Widget.Material3.Button.OutlinedButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="6dp"
android:text="@string/contact_delete"
android:textColor="?attr/colorError"
app:strokeColor="?attr/colorError"
app:icon="@drawable/ic_delete"
app:iconTint="?attr/colorError" />
</LinearLayout>
android:maxLines="1"
android:ellipsize="end" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>