Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/5970.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Make read receipt avatar list more compact
115 changes: 50 additions & 65 deletions vector/src/main/java/im/vector/app/core/ui/views/ReadReceiptsView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.home.room.detail.timeline.item.ReadReceiptData
import im.vector.app.features.home.room.detail.timeline.item.toMatrixItem

private const val MAX_RECEIPT_DISPLAYED = 5
private const val MAX_RECEIPT_DESCRIBED = 3
private const val MAX_RECEIPT_DISPLAYED = 3

class ReadReceiptsView @JvmOverloads constructor(
context: Context,
Expand All @@ -45,13 +44,7 @@ class ReadReceiptsView @JvmOverloads constructor(
}

private val receiptAvatars: List<ImageView> by lazy {
listOf(
views.receiptAvatar1,
views.receiptAvatar2,
views.receiptAvatar3,
views.receiptAvatar4,
views.receiptAvatar5
)
listOf(views.receiptAvatar1, views.receiptAvatar2, views.receiptAvatar3)
}

private fun setupView() {
Expand All @@ -60,66 +53,58 @@ class ReadReceiptsView @JvmOverloads constructor(
}

fun render(readReceipts: List<ReadReceiptData>, avatarRenderer: AvatarRenderer) {
if (readReceipts.isNotEmpty()) {
isVisible = true
for (index in 0 until MAX_RECEIPT_DISPLAYED) {
val receiptData = readReceipts.getOrNull(index)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I deleted this null check because I verified the call chain and List<ReadReceiptData> can never have null elements.

if (receiptData == null) {
receiptAvatars[index].visibility = View.INVISIBLE
} else {
receiptAvatars[index].visibility = View.VISIBLE
avatarRenderer.render(receiptData.toMatrixItem(), receiptAvatars[index])
}
}
receiptAvatars.forEach { it.isVisible = false }

readReceipts.take(MAX_RECEIPT_DISPLAYED).forEachIndexed { index, receiptData ->
receiptAvatars[index].isVisible = true
avatarRenderer.render(receiptData.toMatrixItem(), receiptAvatars[index])
}

val displayNames = readReceipts
.mapNotNull { it.displayName }
.filter { it.isNotBlank() }
.take(MAX_RECEIPT_DESCRIBED)
val displayNames = readReceipts
.mapNotNull { it.displayName }
.filter { it.isNotBlank() }
.take(MAX_RECEIPT_DISPLAYED)

if (readReceipts.size > MAX_RECEIPT_DISPLAYED) {
views.receiptMore.visibility = View.VISIBLE
views.receiptMore.text = context.getString(
R.string.x_plus, readReceipts.size - MAX_RECEIPT_DISPLAYED
)
} else {
views.receiptMore.visibility = View.GONE
}
contentDescription = when (readReceipts.size) {
1 ->
if (displayNames.size == 1) {
context.getString(R.string.one_user_read, displayNames[0])
} else {
context.resources.getQuantityString(R.plurals.fallback_users_read, readReceipts.size)
}
2 ->
if (displayNames.size == 2) {
context.getString(R.string.two_users_read, displayNames[0], displayNames[1])
} else {
context.resources.getQuantityString(R.plurals.fallback_users_read, readReceipts.size)
}
3 ->
if (displayNames.size == 3) {
context.getString(R.string.three_users_read, displayNames[0], displayNames[1], displayNames[2])
} else {
context.resources.getQuantityString(R.plurals.fallback_users_read, readReceipts.size)
}
else ->
if (displayNames.size >= 2) {
val qty = readReceipts.size - 2
context.resources.getQuantityString(
if (readReceipts.size > MAX_RECEIPT_DISPLAYED) {
views.receiptMore.visibility = View.VISIBLE
views.receiptMore.text = context.getString(
R.string.x_plus, readReceipts.size - MAX_RECEIPT_DISPLAYED
)
} else {
views.receiptMore.visibility = View.GONE
}
contentDescription = when (readReceipts.size) {
1 ->
if (displayNames.size == 1) {
context.getString(R.string.one_user_read, displayNames[0])
} else {
context.resources.getQuantityString(R.plurals.fallback_users_read, readReceipts.size)
}
2 ->
if (displayNames.size == 2) {
context.getString(R.string.two_users_read, displayNames[0], displayNames[1])
} else {
context.resources.getQuantityString(R.plurals.fallback_users_read, readReceipts.size)
}
3 ->
if (displayNames.size == 3) {
context.getString(R.string.three_users_read, displayNames[0], displayNames[1], displayNames[2])
} else {
context.resources.getQuantityString(R.plurals.fallback_users_read, readReceipts.size)
}
else ->
if (displayNames.size >= 2) {
val qty = readReceipts.size - 2
context.resources.getQuantityString(
R.plurals.two_and_some_others_read,
qty,
displayNames[0],
displayNames[1],
qty
qty,
displayNames[0],
displayNames[1],
qty
)
} else {
context.resources.getQuantityString(R.plurals.fallback_users_read, readReceipts.size)
}
}
} else {
isVisible = false
} else {
context.resources.getQuantityString(R.plurals.fallback_users_read, readReceipts.size)
}
}
}

Expand Down
32 changes: 10 additions & 22 deletions vector/src/main/res/layout/view_read_receipts.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="end"
tools:parentTag="android.widget.LinearLayout">

<TextView
Expand All @@ -18,53 +19,40 @@
android:textColor="?vctr_content_primary"
tools:text="999+" />

<ImageView
android:id="@+id/receiptAvatar5"
android:layout_width="@dimen/item_event_message_state_size"
android:layout_height="@dimen/item_event_message_state_size"
android:layout_marginStart="2dp"
android:adjustViewBounds="true"
android:importantForAccessibility="no"
android:scaleType="centerCrop"
tools:src="@sample/user_round_avatars" />

<ImageView
android:id="@+id/receiptAvatar4"
android:layout_width="@dimen/item_event_message_state_size"
android:layout_height="@dimen/item_event_message_state_size"
android:layout_marginStart="2dp"
android:adjustViewBounds="true"
android:importantForAccessibility="no"
android:scaleType="centerCrop"
tools:src="@sample/user_round_avatars" />

<ImageView
android:id="@+id/receiptAvatar3"
android:layout_width="@dimen/item_event_message_state_size"
android:layout_height="@dimen/item_event_message_state_size"
android:layout_marginStart="2dp"
android:layout_marginEnd="-6dp"
android:adjustViewBounds="true"
android:importantForAccessibility="no"
android:padding="1dp"
android:scaleType="centerCrop"
tools:ignore="NegativeMargin"
tools:src="@sample/user_round_avatars" />

<ImageView
android:id="@+id/receiptAvatar2"
android:layout_width="@dimen/item_event_message_state_size"
android:layout_height="@dimen/item_event_message_state_size"
android:layout_marginStart="2dp"
android:layout_marginEnd="-6dp"
android:adjustViewBounds="true"
android:background="@drawable/pill_receipt"
android:importantForAccessibility="no"
android:padding="1dp"
android:scaleType="centerCrop"
tools:ignore="NegativeMargin"
tools:src="@sample/user_round_avatars" />

<ImageView
android:id="@+id/receiptAvatar1"
android:layout_width="@dimen/item_event_message_state_size"
android:layout_height="@dimen/item_event_message_state_size"
android:layout_marginStart="2dp"
android:adjustViewBounds="true"
android:background="@drawable/pill_receipt"
android:importantForAccessibility="no"
android:padding="1dp"
android:scaleType="centerCrop"
tools:src="@sample/user_round_avatars" />

Expand Down
2 changes: 1 addition & 1 deletion vector/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1422,7 +1422,7 @@
<string name="merged_events_collapse">collapse</string>

<string name="generic_label_and_value">%1$s: %2$s</string>
<string name="x_plus">%d+</string>
<string name="x_plus">+%d</string>
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this okay to modify an existing string in such a simple case? I checked all current translations and every instance is the same string as in the default locale, there is no custom translation.

Copy link
Copy Markdown
Member

@bmarty bmarty May 9, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, this is OK. But with the new form, I think it would be better to have some avatars displayed, and after the "+3" text. Will check with design

<string name="no_valid_google_play_services_apk">No valid Google Play Services APK found. Notifications may not work properly.</string>

<!-- Passphrase -->
Expand Down