mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-27 13:13:43 +00:00
Update conversation list multi-select to use checkboxes.
This commit is contained in:
@@ -17,12 +17,8 @@
|
||||
package org.thoughtcrime.securesms.conversationlist;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.RippleDrawable;
|
||||
import android.os.Build;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.SpannableStringBuilder;
|
||||
@@ -46,7 +42,6 @@ import androidx.lifecycle.Transformations;
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
||||
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.makeramen.roundedimageview.RoundedDrawable;
|
||||
|
||||
import org.signal.core.util.DimensionUnit;
|
||||
@@ -122,6 +117,9 @@ public final class ConversationListItem extends ConstraintLayout
|
||||
private Locale locale;
|
||||
private String highlightSubstring;
|
||||
private BadgeImageView badge;
|
||||
private View checkContainer;
|
||||
private View uncheckedView;
|
||||
private View checkedView;
|
||||
|
||||
private int unreadCount;
|
||||
private AvatarImageView contactPhotoImage;
|
||||
@@ -151,6 +149,11 @@ public final class ConversationListItem extends ConstraintLayout
|
||||
this.archivedView = findViewById(R.id.conversation_list_item_archived);
|
||||
this.unreadIndicator = findViewById(R.id.conversation_list_item_unread_indicator);
|
||||
this.badge = findViewById(R.id.conversation_list_item_badge);
|
||||
this.checkContainer = findViewById(R.id.conversation_list_item_check_container);
|
||||
this.uncheckedView = findViewById(R.id.conversation_list_item_unchecked);
|
||||
this.checkedView = findViewById(R.id.conversation_list_item_checked);
|
||||
|
||||
getLayoutTransition().setDuration(150);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -161,16 +164,16 @@ public final class ConversationListItem extends ConstraintLayout
|
||||
@NonNull Set<Long> selectedThreads,
|
||||
boolean batchMode)
|
||||
{
|
||||
bind(thread, glideRequests, locale, typingThreads, selectedThreads, batchMode, null);
|
||||
bindThread(thread, glideRequests, locale, typingThreads, selectedThreads, batchMode, null);
|
||||
}
|
||||
|
||||
public void bind(@NonNull ThreadRecord thread,
|
||||
@NonNull GlideRequests glideRequests,
|
||||
@NonNull Locale locale,
|
||||
@NonNull Set<Long> typingThreads,
|
||||
@NonNull Set<Long> selectedThreads,
|
||||
boolean batchMode,
|
||||
@Nullable String highlightSubstring)
|
||||
public void bindThread(@NonNull ThreadRecord thread,
|
||||
@NonNull GlideRequests glideRequests,
|
||||
@NonNull Locale locale,
|
||||
@NonNull Set<Long> typingThreads,
|
||||
@NonNull Set<Long> selectedThreads,
|
||||
boolean batchMode,
|
||||
@Nullable String highlightSubstring)
|
||||
{
|
||||
observeRecipient(thread.getRecipient().live());
|
||||
observeDisplayBody(null);
|
||||
@@ -214,16 +217,15 @@ public final class ConversationListItem extends ConstraintLayout
|
||||
|
||||
setStatusIcons(thread);
|
||||
setBatchMode(batchMode);
|
||||
setRippleColor(recipient.get());
|
||||
badge.setBadgeFromRecipient(recipient.get());
|
||||
setUnreadIndicator(thread);
|
||||
this.contactPhotoImage.setAvatar(glideRequests, recipient.get(), !batchMode);
|
||||
}
|
||||
|
||||
public void bind(@NonNull Recipient contact,
|
||||
@NonNull GlideRequests glideRequests,
|
||||
@NonNull Locale locale,
|
||||
@Nullable String highlightSubstring)
|
||||
public void bindContact(@NonNull Recipient contact,
|
||||
@NonNull GlideRequests glideRequests,
|
||||
@NonNull Locale locale,
|
||||
@Nullable String highlightSubstring)
|
||||
{
|
||||
observeRecipient(contact.live());
|
||||
observeDisplayBody(null);
|
||||
@@ -243,15 +245,14 @@ public final class ConversationListItem extends ConstraintLayout
|
||||
alertView.setNone();
|
||||
|
||||
setBatchMode(false);
|
||||
setRippleColor(contact);
|
||||
badge.setBadgeFromRecipient(recipient.get());
|
||||
contactPhotoImage.setAvatar(glideRequests, recipient.get(), !batchMode);
|
||||
}
|
||||
|
||||
public void bind(@NonNull MessageResult messageResult,
|
||||
@NonNull GlideRequests glideRequests,
|
||||
@NonNull Locale locale,
|
||||
@Nullable String highlightSubstring)
|
||||
public void bindMessage(@NonNull MessageResult messageResult,
|
||||
@NonNull GlideRequests glideRequests,
|
||||
@NonNull Locale locale,
|
||||
@Nullable String highlightSubstring)
|
||||
{
|
||||
observeRecipient(messageResult.getConversationRecipient().live());
|
||||
observeDisplayBody(null);
|
||||
@@ -271,7 +272,6 @@ public final class ConversationListItem extends ConstraintLayout
|
||||
alertView.setNone();
|
||||
|
||||
setBatchMode(false);
|
||||
setRippleColor(recipient.get());
|
||||
badge.setBadgeFromRecipient(recipient.get());
|
||||
contactPhotoImage.setAvatar(glideRequests, recipient.get(), !batchMode);
|
||||
}
|
||||
@@ -290,7 +290,23 @@ public final class ConversationListItem extends ConstraintLayout
|
||||
@Override
|
||||
public void setBatchMode(boolean batchMode) {
|
||||
this.batchMode = batchMode;
|
||||
setSelected(batchMode && selectedThreads.contains(thread.getThreadId()));
|
||||
|
||||
boolean selected = batchMode && selectedThreads.contains(thread.getThreadId());
|
||||
setSelected(selected);
|
||||
|
||||
if (batchMode && selected) {
|
||||
checkContainer.setVisibility(VISIBLE);
|
||||
uncheckedView.setVisibility(GONE);
|
||||
checkedView.setVisibility(VISIBLE);
|
||||
} else if (batchMode) {
|
||||
checkContainer.setVisibility(VISIBLE);
|
||||
uncheckedView.setVisibility(VISIBLE);
|
||||
checkedView.setVisibility(GONE);
|
||||
} else {
|
||||
checkContainer.setVisibility(GONE);
|
||||
uncheckedView.setVisibility(GONE);
|
||||
checkedView.setVisibility(GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -402,13 +418,6 @@ public final class ConversationListItem extends ConstraintLayout
|
||||
}
|
||||
}
|
||||
|
||||
private void setRippleColor(Recipient recipient) {
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
((RippleDrawable)(getBackground()).mutate())
|
||||
.setColor(ColorStateList.valueOf(recipient.getChatColors().asSingleColor()));
|
||||
}
|
||||
}
|
||||
|
||||
private void setUnreadIndicator(ThreadRecord thread) {
|
||||
if ((thread.isOutgoing() && !thread.isForcedUnread()) || thread.isRead()) {
|
||||
unreadIndicator.setVisibility(View.GONE);
|
||||
@@ -433,7 +442,6 @@ public final class ConversationListItem extends ConstraintLayout
|
||||
fromView.setText(recipient, false);
|
||||
}
|
||||
contactPhotoImage.setAvatar(glideRequests, recipient, !batchMode);
|
||||
setRippleColor(recipient);
|
||||
badge.setBadgeFromRecipient(recipient);
|
||||
}
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ class ConversationListSearchAdapter extends RecyclerView.Adapter<Conversation
|
||||
@NonNull Locale locale,
|
||||
@Nullable String query)
|
||||
{
|
||||
root.bind(conversationResult, glideRequests, locale, Collections.emptySet(), Collections.emptySet(), false, query);
|
||||
root.bindThread(conversationResult, glideRequests, locale, Collections.emptySet(), Collections.emptySet(), false, query);
|
||||
root.setOnClickListener(view -> eventListener.onConversationClicked(conversationResult));
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ class ConversationListSearchAdapter extends RecyclerView.Adapter<Conversation
|
||||
@NonNull Locale locale,
|
||||
@Nullable String query)
|
||||
{
|
||||
root.bind(contactResult, glideRequests, locale, query);
|
||||
root.bindContact(contactResult, glideRequests, locale, query);
|
||||
root.setOnClickListener(view -> eventListener.onContactClicked(contactResult));
|
||||
}
|
||||
|
||||
@@ -182,7 +182,7 @@ class ConversationListSearchAdapter extends RecyclerView.Adapter<Conversation
|
||||
@NonNull Locale locale,
|
||||
@Nullable String query)
|
||||
{
|
||||
root.bind(messageResult, glideRequests, locale, query);
|
||||
root.bindMessage(messageResult, glideRequests, locale, query);
|
||||
root.setOnClickListener(view -> eventListener.onMessageClicked(messageResult));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="@color/core_ultramarine">
|
||||
<item android:id="@android:id/mask" android:drawable="@android:color/black" />
|
||||
<item>
|
||||
<selector>
|
||||
<item android:drawable="@color/core_ultramarine_33" android:state_selected="true" />
|
||||
</selector>
|
||||
<selector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:enterFadeDuration="100"
|
||||
android:exitFadeDuration="100">
|
||||
|
||||
<item android:state_selected="true">
|
||||
<inset
|
||||
android:insetLeft="12dp"
|
||||
android:insetRight="12dp"
|
||||
android:insetTop="2dp"
|
||||
android:insetBottom="2dp">
|
||||
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/conversation_list_selected_color" />
|
||||
<corners android:radius="18dp" />
|
||||
</shape>
|
||||
</inset>
|
||||
</item>
|
||||
</ripple>
|
||||
|
||||
<item>
|
||||
<ripple android:color="@color/conversation_list_selected_color">
|
||||
<item android:id="@android:id/mask">
|
||||
<inset
|
||||
android:insetLeft="12dp"
|
||||
android:insetRight="12dp"
|
||||
android:insetTop="2dp"
|
||||
android:insetBottom="2dp">
|
||||
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/transparent_black_60" />
|
||||
<corners android:radius="18dp" />
|
||||
</shape>
|
||||
</inset>
|
||||
</item>
|
||||
</ripple>
|
||||
</item>
|
||||
</selector>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="@color/conversation_list_selected_color">
|
||||
<item android:id="@android:id/mask" android:drawable="@android:color/black" />
|
||||
</ripple>
|
||||
10
app/src/main/res/drawable/multiselect_empty_ring.xml
Normal file
10
app/src/main/res/drawable/multiselect_empty_ring.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
|
||||
<stroke
|
||||
android:width="2dp"
|
||||
android:color="@color/core_grey_25" />
|
||||
|
||||
</shape>
|
||||
@@ -10,17 +10,48 @@
|
||||
android:nextFocusLeft="@+id/container"
|
||||
android:nextFocusRight="@+id/fab"
|
||||
android:paddingStart="@dimen/dsl_settings_gutter"
|
||||
android:paddingEnd="@dimen/dsl_settings_gutter">
|
||||
android:paddingEnd="@dimen/dsl_settings_gutter"
|
||||
android:animateLayoutChanges="true">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/conversation_list_item_check_container"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/conversation_list_item_unchecked"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:srcCompat="@drawable/multiselect_empty_ring"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/conversation_list_item_checked"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
app:srcCompat="@drawable/ic_check_circle_solid_24"
|
||||
app:tint="@color/signal_accent_primary"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<org.thoughtcrime.securesms.components.AvatarImageView
|
||||
android:id="@+id/conversation_list_item_avatar"
|
||||
android:layout_width="@dimen/conversation_list_avatar_size"
|
||||
android:layout_height="@dimen/conversation_list_avatar_size"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:contentDescription="@string/conversation_list_item_view__contact_photo_image"
|
||||
android:foreground="@drawable/contact_photo_background"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/conversation_list_item_check_container"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_goneMarginStart="0dp"
|
||||
tools:src="@drawable/ic_contact_picture" />
|
||||
|
||||
<org.thoughtcrime.securesms.components.FromTextView
|
||||
|
||||
@@ -98,6 +98,7 @@
|
||||
<color name="conversation_scroll_to_bottom_foreground_color">@color/core_white</color>
|
||||
|
||||
<color name="conversation_list_camera_button_background">@color/core_grey_85</color>
|
||||
<color name="conversation_list_selected_color">#4c6191f3</color>
|
||||
|
||||
<color name="camera_icon_background_tint">@color/core_grey_75</color>
|
||||
|
||||
|
||||
@@ -98,6 +98,7 @@
|
||||
<color name="conversation_scroll_to_bottom_foreground_color">@color/grey_600</color>
|
||||
|
||||
<color name="conversation_list_camera_button_background">@color/core_white</color>
|
||||
<color name="conversation_list_selected_color">#222c6bed</color>
|
||||
|
||||
<color name="camera_icon_background_tint">@color/core_grey_02</color>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user