Update chat folder display list.

This commit is contained in:
Michelle Tang
2024-10-15 13:30:15 -07:00
committed by Greyson Parrelli
parent dd4d674a61
commit 96dd77364e
11 changed files with 110 additions and 45 deletions

View File

@@ -44,6 +44,10 @@ public class FromTextView extends SimpleEmojiTextView {
}
public void setText(Recipient recipient, @Nullable CharSequence fromString, @Nullable CharSequence suffix, boolean asThread, boolean showSelfAsYou) {
setText(recipient, fromString, suffix, asThread, showSelfAsYou, false);
}
public void setText(Recipient recipient, @Nullable CharSequence fromString, @Nullable CharSequence suffix, boolean asThread, boolean showSelfAsYou, boolean isPinned) {
SpannableStringBuilder builder = new SpannableStringBuilder();
if (asThread && recipient.isSelf() && showSelfAsYou) {
@@ -66,25 +70,34 @@ public class FromTextView extends SimpleEmojiTextView {
.append(SpanUtil.buildCenteredImageSpan(official));
}
if (recipient.isMuted()) {
builder.append(" ")
.append(SpanUtil.buildCenteredImageSpan(getMuted()));
}
setText(builder);
if (recipient.isBlocked()) setCompoundDrawablesRelativeWithIntrinsicBounds(getBlocked(), null, null, null);
else if (recipient.isMuted()) setCompoundDrawablesRelativeWithIntrinsicBounds(getMuted(), null, null, null);
else if (isPinned) setCompoundDrawablesRelativeWithIntrinsicBounds(getPinned(), null, null, null);
else setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, 0, 0);
}
private Drawable getBlocked() {
return getDrawable(R.drawable.symbol_block_16);
return getDrawable(R.drawable.symbol_block_16, R.color.signal_icon_tint_secondary);
}
private Drawable getMuted() {
return getDrawable(R.drawable.ic_bell_disabled_16);
return getDrawable(R.drawable.ic_bell_disabled_16, R.color.signal_icon_tint_secondary);
}
private Drawable getDrawable(@DrawableRes int drawable) {
private Drawable getPinned() {
return getDrawable(R.drawable.symbol_pin_16, R.color.signal_colorOnSurface);
}
private Drawable getDrawable(@DrawableRes int drawable, int colorRes) {
Drawable mutedDrawable = ContextUtil.requireDrawable(getContext(), drawable);
mutedDrawable.setBounds(0, 0, ViewUtil.dpToPx(18), ViewUtil.dpToPx(18));
DrawableUtil.tint(mutedDrawable, ContextCompat.getColor(getContext(), R.color.signal_icon_tint_secondary));
mutedDrawable.setBounds(0, 0, ViewUtil.dpToPx(16), ViewUtil.dpToPx(16));
DrawableUtil.tint(mutedDrawable, ContextCompat.getColor(getContext(), colorRes));
return mutedDrawable;
}
}

View File

@@ -38,6 +38,7 @@ class ConversationListAdapter extends ListAdapter<Conversation, RecyclerView.Vie
private static final int TYPE_EMPTY = 5;
private static final int TYPE_CLEAR_FILTER_FOOTER = 6;
private static final int TYPE_CLEAR_FILTER_EMPTY = 7;
private static final int TYPE_CHAT_FOLDER_EMPTY = 8;
private enum Payload {
TYPING_INDICATOR,
@@ -45,19 +46,21 @@ class ConversationListAdapter extends ListAdapter<Conversation, RecyclerView.Vie
TIMESTAMP
}
private final LifecycleOwner lifecycleOwner;
private final RequestManager requestManager;
private final OnConversationClickListener onConversationClickListener;
private final ClearFilterViewHolder.OnClearFilterClickListener onClearFilterClicked;
private ConversationSet selectedConversations = new ConversationSet();
private final Set<Long> typingSet = new HashSet<>();
private final LifecycleOwner lifecycleOwner;
private final RequestManager requestManager;
private final OnConversationClickListener onConversationClickListener;
private final ClearFilterViewHolder.OnClearFilterClickListener onClearFilterClicked;
private final EmptyFolderViewHolder.OnFolderSettingsClickListener onFolderSettingsClicked;
private final Set<Long> typingSet = new HashSet<>();
private PagingController pagingController;
private ConversationSet selectedConversations = new ConversationSet();
private PagingController pagingController;
protected ConversationListAdapter(@NonNull LifecycleOwner lifecycleOwner,
@NonNull RequestManager requestManager,
@NonNull OnConversationClickListener onConversationClickListener,
@NonNull ClearFilterViewHolder.OnClearFilterClickListener onClearFilterClicked)
@NonNull ClearFilterViewHolder.OnClearFilterClickListener onClearFilterClicked,
@NonNull EmptyFolderViewHolder.OnFolderSettingsClickListener onFolderSettingsClicked)
{
super(new ConversationDiffCallback());
@@ -65,6 +68,7 @@ class ConversationListAdapter extends ListAdapter<Conversation, RecyclerView.Vie
this.requestManager = requestManager;
this.onConversationClickListener = onConversationClickListener;
this.onClearFilterClicked = onClearFilterClicked;
this.onFolderSettingsClicked = onFolderSettingsClicked;
}
@Override
@@ -118,6 +122,9 @@ class ConversationListAdapter extends ListAdapter<Conversation, RecyclerView.Vie
} else if (viewType == TYPE_CLEAR_FILTER_EMPTY) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.conversation_list_item_clear_filter_empty, parent, false);
return new ClearFilterViewHolder(v, onClearFilterClicked);
} else if (viewType == TYPE_CHAT_FOLDER_EMPTY) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.conversation_list_item_folder_empty, parent, false);
return new EmptyFolderViewHolder(v, onFolderSettingsClicked);
} else {
throw new IllegalStateException("Unknown type! " + viewType);
}
@@ -229,6 +236,8 @@ class ConversationListAdapter extends ListAdapter<Conversation, RecyclerView.Vie
return TYPE_CLEAR_FILTER_FOOTER;
case CONVERSATION_FILTER_EMPTY:
return TYPE_CLEAR_FILTER_EMPTY;
case CHAT_FOLDER_EMPTY:
return TYPE_CHAT_FOLDER_EMPTY;
case THREAD:
return TYPE_THREAD;
case EMPTY:
@@ -281,6 +290,18 @@ class ConversationListAdapter extends ListAdapter<Conversation, RecyclerView.Vie
}
}
static class EmptyFolderViewHolder extends RecyclerView.ViewHolder {
public EmptyFolderViewHolder(@NonNull View itemView, OnFolderSettingsClickListener listener) {
super(itemView);
itemView.findViewById(R.id.folder_settings).setOnClickListener(v -> listener.onFolderSettingsClick());
}
interface OnFolderSettingsClickListener {
void onFolderSettingsClick();
}
}
interface OnConversationClickListener {
void onConversationClick(@NonNull Conversation conversation);
boolean onConversationLongClick(@NonNull Conversation conversation, @NonNull View view);

View File

@@ -110,12 +110,14 @@ abstract class ConversationListDataSource implements PagedDataSource<Long, Conve
SignalTrace.endSection();
if (conversations.isEmpty() && start == 0 && length == 1) {
if (conversationFilter == ConversationFilter.OFF) {
return Collections.singletonList(new Conversation(ConversationReader.buildThreadRecordForType(Conversation.Type.EMPTY, 0, false)));
} else {
if (conversationFilter != ConversationFilter.OFF) {
return Collections.singletonList(new Conversation(ConversationReader.buildThreadRecordForType(Conversation.Type.CONVERSATION_FILTER_EMPTY,
0,
showConversationFooterTip)));
} else if (chatFolder.getFolderType() != ChatFolderRecord.FolderType.ALL) {
return Collections.singletonList(new Conversation(ConversationReader.buildThreadRecordForType(Conversation.Type.CHAT_FOLDER_EMPTY, 0, false)));
} else {
return Collections.singletonList(new Conversation(ConversationReader.buildThreadRecordForType(Conversation.Type.EMPTY, 0, false)));
}
} else {
return conversations;

View File

@@ -203,7 +203,8 @@ public class ConversationListFragment extends MainFragment implements ActionMode
ConversationListAdapter.OnConversationClickListener,
MegaphoneActionController,
ClearFilterViewHolder.OnClearFilterClickListener,
ChatFolderAdapter.Callbacks
ChatFolderAdapter.Callbacks,
ConversationListAdapter.EmptyFolderViewHolder.OnFolderSettingsClickListener
{
public static final short MESSAGE_REQUESTS_REQUEST_CODE_CREATE_NAME = 32562;
public static final short SMS_ROLE_REQUEST_CODE = 32563;
@@ -916,7 +917,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
private void initializeListAdapters() {
defaultAdapter = new ConversationListAdapter(getViewLifecycleOwner(), Glide.with(this), this, this);
defaultAdapter = new ConversationListAdapter(getViewLifecycleOwner(), Glide.with(this), this, this, this);
setAdapter(defaultAdapter);
@@ -1704,6 +1705,11 @@ public class ConversationListFragment extends MainFragment implements ActionMode
startActivity(AppSettingsActivity.chatFolders(requireContext()));
}
@Override
public void onFolderSettingsClick() {
startActivity(AppSettingsActivity.chatFolders(requireContext()));
}
private class ArchiveListenerCallback extends ItemTouchHelper.SimpleCallback {
private static final long SWIPE_ANIMATION_DURATION = 175;

View File

@@ -171,7 +171,6 @@ public final class ConversationListItem extends ConstraintLayout implements Bind
this.uncheckedView = findViewById(R.id.conversation_list_item_unchecked);
this.checkedView = findViewById(R.id.conversation_list_item_checked);
this.unreadMentions = findViewById(R.id.conversation_list_item_unread_mentions_indicator);
this.pinnedView = findViewById(R.id.conversation_list_item_pinned);
this.thumbSize = (int) DimensionUnit.SP.toPixels(16f);
this.thumbTarget = new GlideLiveDataTarget(thumbSize, thumbSize);
this.searchStyleFactory = () -> new CharacterStyle[] { new ForegroundColorSpan(ContextCompat.getColor(getContext(), R.color.signal_colorOnSurface)), SpanUtil.getBoldSpan() };
@@ -215,7 +214,7 @@ public final class ConversationListItem extends ConstraintLayout implements Bind
@NonNull Set<Long> typingThreads,
@NonNull ConversationSet selectedConversations)
{
bindThread(lifecycleOwner, thread, glideRequests, locale, typingThreads, selectedConversations, null, false);
bindThread(lifecycleOwner, thread, glideRequests, locale, typingThreads, selectedConversations, null, false, true);
}
public void bindThread(@NonNull LifecycleOwner lifecycleOwner,
@@ -225,7 +224,8 @@ public final class ConversationListItem extends ConstraintLayout implements Bind
@NonNull Set<Long> typingThreads,
@NonNull ConversationSet selectedConversations,
@Nullable String highlightSubstring,
boolean appendSystemContactIcon)
boolean appendSystemContactIcon,
boolean showPinned)
{
this.threadId = thread.getThreadId();
this.requestManager = requestManager;
@@ -250,9 +250,9 @@ public final class ConversationListItem extends ConstraintLayout implements Bind
if (highlightSubstring != null) {
String name = recipient.get().isSelf() ? getContext().getString(R.string.note_to_self) : recipient.get().getDisplayName(getContext());
this.fromView.setText(recipient.get(), SearchUtil.getHighlightedSpan(locale, searchStyleFactory, name, highlightSubstring, SearchUtil.MATCH_ALL), suffix);
this.fromView.setText(recipient.get(), SearchUtil.getHighlightedSpan(locale, searchStyleFactory, name, highlightSubstring, SearchUtil.MATCH_ALL), suffix, true, false, showPinned && thread.isPinned());
} else {
this.fromView.setText(recipient.get(), suffix);
this.fromView.setText(recipient.get(), recipient.get().getDisplayName(getContext()), suffix, true, false, showPinned && thread.isPinned());
}
this.typingThreads = typingThreads;
@@ -281,12 +281,6 @@ public final class ConversationListItem extends ConstraintLayout implements Bind
this.archivedView.setVisibility(View.GONE);
}
if (thread.isPinned()) {
this.pinnedView.setVisibility(View.VISIBLE);
} else {
this.pinnedView.setVisibility(View.GONE);
}
setStatusIcons(thread);
setSelectedConversations(selectedConversations);
setBadgeFromRecipient(recipient.get());
@@ -570,9 +564,9 @@ public final class ConversationListItem extends ConstraintLayout implements Bind
} else {
name = recipient.getDisplayName(getContext());
}
fromView.setText(recipient, SearchUtil.getHighlightedSpan(locale, searchStyleFactory, new SpannableString(name), highlightSubstring, SearchUtil.MATCH_ALL), null, thread != null);
fromView.setText(recipient, SearchUtil.getHighlightedSpan(locale, searchStyleFactory, new SpannableString(name), highlightSubstring, SearchUtil.MATCH_ALL), null, thread != null, false, thread != null && thread.isPinned());
} else {
fromView.setText(recipient);
fromView.setText(recipient, recipient.getDisplayName(getContext()), null, true, false, thread != null && thread.isPinned());
}
contactPhotoImage.setAvatar(requestManager, recipient, !batchMode, false);
setBadgeFromRecipient(recipient);

View File

@@ -121,7 +121,8 @@ class ConversationListSearchAdapter(
emptySet(),
ConversationSet(),
model.thread.query,
true
true,
false
)
}
}

View File

@@ -45,6 +45,7 @@ public class Conversation {
ARCHIVED_FOOTER,
CONVERSATION_FILTER_FOOTER,
CONVERSATION_FILTER_EMPTY,
CHAT_FOLDER_EMPTY,
EMPTY
}
}