Fix conversation list memory leak.

fork-5.53.8
Cody Henthorne 2022-05-24 16:09:55 -04:00 zatwierdzone przez Alex Hart
rodzic 2a91c67c51
commit 5dba1067d6
7 zmienionych plików z 119 dodań i 142 usunięć

Wyświetl plik

@ -1,6 +1,7 @@
package org.thoughtcrime.securesms; package org.thoughtcrime.securesms;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.lifecycle.LifecycleOwner;
import org.thoughtcrime.securesms.conversationlist.model.ConversationSet; import org.thoughtcrime.securesms.conversationlist.model.ConversationSet;
import org.thoughtcrime.securesms.database.model.ThreadRecord; import org.thoughtcrime.securesms.database.model.ThreadRecord;
@ -11,7 +12,8 @@ import java.util.Set;
public interface BindableConversationListItem extends Unbindable { public interface BindableConversationListItem extends Unbindable {
void bind(@NonNull ThreadRecord thread, void bind(@NonNull LifecycleOwner lifecycleOwner,
@NonNull ThreadRecord thread,
@NonNull GlideRequests glideRequests, @NonNull Locale locale, @NonNull GlideRequests glideRequests, @NonNull Locale locale,
@NonNull Set<Long> typingThreads, @NonNull Set<Long> typingThreads,
@NonNull ConversationSet selectedConversations); @NonNull ConversationSet selectedConversations);

Wyświetl plik

@ -8,6 +8,7 @@ import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.lifecycle.LifecycleOwner;
import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.ListAdapter; import androidx.recyclerview.widget.ListAdapter;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
@ -39,6 +40,7 @@ class ConversationListAdapter extends ListAdapter<Conversation, RecyclerView.Vie
SELECTION SELECTION
} }
private final LifecycleOwner lifecycleOwner;
private final GlideRequests glideRequests; private final GlideRequests glideRequests;
private final OnConversationClickListener onConversationClickListener; private final OnConversationClickListener onConversationClickListener;
private ConversationSet selectedConversations = new ConversationSet(); private ConversationSet selectedConversations = new ConversationSet();
@ -46,11 +48,13 @@ class ConversationListAdapter extends ListAdapter<Conversation, RecyclerView.Vie
private PagingController pagingController; private PagingController pagingController;
protected ConversationListAdapter(@NonNull GlideRequests glideRequests, protected ConversationListAdapter(@NonNull LifecycleOwner lifecycleOwner,
@NonNull GlideRequests glideRequests,
@NonNull OnConversationClickListener onConversationClickListener) @NonNull OnConversationClickListener onConversationClickListener)
{ {
super(new ConversationDiffCallback()); super(new ConversationDiffCallback());
this.lifecycleOwner = lifecycleOwner;
this.glideRequests = glideRequests; this.glideRequests = glideRequests;
this.onConversationClickListener = onConversationClickListener; this.onConversationClickListener = onConversationClickListener;
} }
@ -127,7 +131,8 @@ class ConversationListAdapter extends ListAdapter<Conversation, RecyclerView.Vie
ConversationViewHolder casted = (ConversationViewHolder) holder; ConversationViewHolder casted = (ConversationViewHolder) holder;
Conversation conversation = Objects.requireNonNull(getItem(position)); Conversation conversation = Objects.requireNonNull(getItem(position));
casted.getConversationListItem().bind(conversation.getThreadRecord(), casted.getConversationListItem().bind(lifecycleOwner,
conversation.getThreadRecord(),
glideRequests, glideRequests,
Locale.getDefault(), Locale.getDefault(),
typingSet, typingSet,

Wyświetl plik

@ -341,6 +341,30 @@ public class ConversationListFragment extends MainFragment implements ActionMode
})); }));
} }
@Override
public void onDestroyView() {
coordinator = null;
list = null;
searchEmptyState = null;
toolbarShadow = null;
bottomActionBar = null;
reminderView = null;
emptyState = null;
megaphoneContainer = null;
paymentNotificationView = null;
voiceNotePlayerViewStub = null;
fab = null;
cameraFab = null;
snapToTopDataObserver = null;
itemAnimator = null;
activeAdapter = null;
defaultAdapter = null;
searchAdapter = null;
super.onDestroyView();
}
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
@ -646,8 +670,8 @@ public class ConversationListFragment extends MainFragment implements ActionMode
private void initializeListAdapters() { private void initializeListAdapters() {
defaultAdapter = new ConversationListAdapter(GlideApp.with(this), this); defaultAdapter = new ConversationListAdapter(getViewLifecycleOwner(), GlideApp.with(this), this);
searchAdapter = new ConversationListSearchAdapter(GlideApp.with(this), this, Locale.getDefault()); searchAdapter = new ConversationListSearchAdapter(getViewLifecycleOwner(), GlideApp.with(this), this, Locale.getDefault());
searchAdapterDecoration = new StickyHeaderDecoration(searchAdapter, false, false, 0); searchAdapterDecoration = new StickyHeaderDecoration(searchAdapter, false, false, 0);
setAdapter(defaultAdapter); setAdapter(defaultAdapter);
@ -1527,7 +1551,6 @@ public class ConversationListFragment extends MainFragment implements ActionMode
float dX, float dY, int actionState, float dX, float dY, int actionState,
boolean isCurrentlyActive) boolean isCurrentlyActive)
{ {
if (viewHolder.itemView instanceof ConversationListItemInboxZero) return;
float absoluteDx = Math.abs(dX); float absoluteDx = Math.abs(dX);
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) { if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {

Wyświetl plik

@ -36,6 +36,7 @@ import androidx.annotation.Nullable;
import androidx.annotation.Px; import androidx.annotation.Px;
import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer; import androidx.lifecycle.Observer;
import androidx.lifecycle.Transformations; import androidx.lifecycle.Transformations;
@ -69,7 +70,6 @@ import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
import org.thoughtcrime.securesms.mms.GlideRequests; import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.recipients.LiveRecipient; import org.thoughtcrime.securesms.recipients.LiveRecipient;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientForeverObserver;
import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.search.MessageResult; import org.thoughtcrime.securesms.search.MessageResult;
import org.thoughtcrime.securesms.util.DateUtils; import org.thoughtcrime.securesms.util.DateUtils;
@ -84,20 +84,17 @@ import java.util.Set;
import static org.thoughtcrime.securesms.database.model.LiveUpdateMessage.recipientToStringAsync; import static org.thoughtcrime.securesms.database.model.LiveUpdateMessage.recipientToStringAsync;
public final class ConversationListItem extends ConstraintLayout public final class ConversationListItem extends ConstraintLayout implements BindableConversationListItem, Unbindable {
implements RecipientForeverObserver,
BindableConversationListItem,
Unbindable,
Observer<SpannableString>
{
@SuppressWarnings("unused") @SuppressWarnings("unused")
private final static String TAG = Log.tag(ConversationListItem.class); private final static String TAG = Log.tag(ConversationListItem.class);
private final static Typeface BOLD_TYPEFACE = Typeface.create("sans-serif-medium", Typeface.NORMAL); private final static Typeface BOLD_TYPEFACE = Typeface.create("sans-serif-medium", Typeface.NORMAL);
private final static Typeface LIGHT_TYPEFACE = Typeface.create("sans-serif", Typeface.NORMAL); private final static Typeface LIGHT_TYPEFACE = Typeface.create("sans-serif", Typeface.NORMAL);
private final Rect conversationAvatarTouchDelegateBounds = new Rect(); private final Rect conversationAvatarTouchDelegateBounds = new Rect();
private final Rect newConversationAvatarTouchDelegateBounds = new Rect(); private final Rect newConversationAvatarTouchDelegateBounds = new Rect();
private final Observer<Recipient> recipientObserver = this::onRecipientChanged;
private final Observer<SpannableString> displayBodyObserver = this::onDisplayBodyChanged;
private Set<Long> typingThreads; private Set<Long> typingThreads;
private LiveRecipient recipient; private LiveRecipient recipient;
@ -174,7 +171,7 @@ public final class ConversationListItem extends ConstraintLayout
newConversationAvatarTouchDelegateBounds.right = right; newConversationAvatarTouchDelegateBounds.right = right;
} }
newConversationAvatarTouchDelegateBounds.top = top; newConversationAvatarTouchDelegateBounds.top = top;
newConversationAvatarTouchDelegateBounds.bottom = bottom; newConversationAvatarTouchDelegateBounds.bottom = bottom;
TouchDelegate currentDelegate = getTouchDelegate(); TouchDelegate currentDelegate = getTouchDelegate();
@ -187,25 +184,24 @@ public final class ConversationListItem extends ConstraintLayout
} }
@Override @Override
public void bind(@NonNull ThreadRecord thread, public void bind(@NonNull LifecycleOwner lifecycleOwner,
@NonNull ThreadRecord thread,
@NonNull GlideRequests glideRequests, @NonNull GlideRequests glideRequests,
@NonNull Locale locale, @NonNull Locale locale,
@NonNull Set<Long> typingThreads, @NonNull Set<Long> typingThreads,
@NonNull ConversationSet selectedConversations) @NonNull ConversationSet selectedConversations)
{ {
bindThread(thread, glideRequests, locale, typingThreads, selectedConversations, null); bindThread(lifecycleOwner, thread, glideRequests, locale, typingThreads, selectedConversations, null);
} }
public void bindThread(@NonNull ThreadRecord thread, public void bindThread(@NonNull LifecycleOwner lifecycleOwner,
@NonNull ThreadRecord thread,
@NonNull GlideRequests glideRequests, @NonNull GlideRequests glideRequests,
@NonNull Locale locale, @NonNull Locale locale,
@NonNull Set<Long> typingThreads, @NonNull Set<Long> typingThreads,
@NonNull ConversationSet selectedConversations, @NonNull ConversationSet selectedConversations,
@Nullable String highlightSubstring) @Nullable String highlightSubstring)
{ {
observeRecipient(thread.getRecipient().live());
observeDisplayBody(null);
this.threadId = thread.getThreadId(); this.threadId = thread.getThreadId();
this.glideRequests = glideRequests; this.glideRequests = glideRequests;
this.unreadCount = thread.getUnreadCount(); this.unreadCount = thread.getUnreadCount();
@ -214,6 +210,9 @@ public final class ConversationListItem extends ConstraintLayout
this.locale = locale; this.locale = locale;
this.highlightSubstring = highlightSubstring; this.highlightSubstring = highlightSubstring;
observeRecipient(lifecycleOwner, thread.getRecipient().live());
observeDisplayBody(null, null);
if (highlightSubstring != null) { if (highlightSubstring != null) {
String name = recipient.get().isSelf() ? getContext().getString(R.string.note_to_self) : recipient.get().getDisplayName(getContext()); String name = recipient.get().isSelf() ? getContext().getString(R.string.note_to_self) : recipient.get().getDisplayName(getContext());
@ -227,7 +226,7 @@ public final class ConversationListItem extends ConstraintLayout
LiveData<SpannableString> displayBody = getThreadDisplayBody(getContext(), thread, glideRequests, thumbSize, thumbTarget); LiveData<SpannableString> displayBody = getThreadDisplayBody(getContext(), thread, glideRequests, thumbSize, thumbTarget);
setSubjectViewText(displayBody.getValue()); setSubjectViewText(displayBody.getValue());
observeDisplayBody(displayBody); observeDisplayBody(lifecycleOwner, displayBody);
if (thread.getDate() > 0) { if (thread.getDate() > 0) {
CharSequence date = DateUtils.getBriefRelativeTimeSpanString(getContext(), locale, thread.getDate()); CharSequence date = DateUtils.getBriefRelativeTimeSpanString(getContext(), locale, thread.getDate());
@ -259,19 +258,20 @@ public final class ConversationListItem extends ConstraintLayout
} }
} }
public void bindContact(@NonNull Recipient contact, public void bindContact(@NonNull LifecycleOwner lifecycleOwner,
@NonNull GlideRequests glideRequests, @NonNull Recipient contact,
@NonNull Locale locale, @NonNull GlideRequests glideRequests,
@Nullable String highlightSubstring) @NonNull Locale locale,
@Nullable String highlightSubstring)
{ {
observeRecipient(contact.live());
observeDisplayBody(null);
setSubjectViewText(null);
this.glideRequests = glideRequests; this.glideRequests = glideRequests;
this.locale = locale; this.locale = locale;
this.highlightSubstring = highlightSubstring; this.highlightSubstring = highlightSubstring;
observeRecipient(lifecycleOwner, contact.live());
observeDisplayBody(null, null);
setSubjectViewText(null);
fromView.setText(contact, SearchUtil.getHighlightedSpan(locale, SpanUtil::getMediumBoldSpan, new SpannableString(contact.getDisplayName(getContext())), highlightSubstring, SearchUtil.MATCH_ALL), true, null); fromView.setText(contact, SearchUtil.getHighlightedSpan(locale, SpanUtil::getMediumBoldSpan, new SpannableString(contact.getDisplayName(getContext())), highlightSubstring, SearchUtil.MATCH_ALL), true, null);
setSubjectViewText(SearchUtil.getHighlightedSpan(locale, SpanUtil::getBoldSpan, contact.getE164().orElse(""), highlightSubstring, SearchUtil.MATCH_ALL)); setSubjectViewText(SearchUtil.getHighlightedSpan(locale, SpanUtil::getBoldSpan, contact.getE164().orElse(""), highlightSubstring, SearchUtil.MATCH_ALL));
dateView.setText(""); dateView.setText("");
@ -285,19 +285,20 @@ public final class ConversationListItem extends ConstraintLayout
contactPhotoImage.setAvatar(glideRequests, recipient.get(), !batchMode); contactPhotoImage.setAvatar(glideRequests, recipient.get(), !batchMode);
} }
public void bindMessage(@NonNull MessageResult messageResult, public void bindMessage(@NonNull LifecycleOwner lifecycleOwner,
@NonNull GlideRequests glideRequests, @NonNull MessageResult messageResult,
@NonNull Locale locale, @NonNull GlideRequests glideRequests,
@Nullable String highlightSubstring) @NonNull Locale locale,
@Nullable String highlightSubstring)
{ {
observeRecipient(messageResult.getConversationRecipient().live());
observeDisplayBody(null);
setSubjectViewText(null);
this.glideRequests = glideRequests; this.glideRequests = glideRequests;
this.locale = locale; this.locale = locale;
this.highlightSubstring = highlightSubstring; this.highlightSubstring = highlightSubstring;
observeRecipient(lifecycleOwner, messageResult.getConversationRecipient().live());
observeDisplayBody(null, null);
setSubjectViewText(null);
fromView.setText(recipient.get(), false); fromView.setText(recipient.get(), false);
setSubjectViewText(SearchUtil.getHighlightedSpan(locale, SpanUtil::getBoldSpan, messageResult.getBodySnippet(), highlightSubstring, SearchUtil.MATCH_ALL)); setSubjectViewText(SearchUtil.getHighlightedSpan(locale, SpanUtil::getBoldSpan, messageResult.getBodySnippet(), highlightSubstring, SearchUtil.MATCH_ALL));
dateView.setText(DateUtils.getBriefRelativeTimeSpanString(getContext(), locale, messageResult.getReceivedTimestampMs())); dateView.setText(DateUtils.getBriefRelativeTimeSpanString(getContext(), locale, messageResult.getReceivedTimestampMs()));
@ -314,12 +315,12 @@ public final class ConversationListItem extends ConstraintLayout
@Override @Override
public void unbind() { public void unbind() {
if (this.recipient != null) { if (this.recipient != null) {
observeRecipient(null); observeRecipient(null, null);
setSelectedConversations(new ConversationSet()); setSelectedConversations(new ConversationSet());
contactPhotoImage.setAvatar(glideRequests, null, !batchMode); contactPhotoImage.setAvatar(glideRequests, null, !batchMode);
} }
observeDisplayBody(null); observeDisplayBody(null, null);
} }
@Override @Override
@ -332,7 +333,7 @@ public final class ConversationListItem extends ConstraintLayout
if (recipient != null) { if (recipient != null) {
contactPhotoImage.setAvatar(glideRequests, recipient.get(), !batchMode); contactPhotoImage.setAvatar(glideRequests, recipient.get(), !batchMode);
} }
if (batchMode && selected) { if (batchMode && selected) {
checkContainer.setVisibility(VISIBLE); checkContainer.setVisibility(VISIBLE);
uncheckedView.setVisibility(GONE); uncheckedView.setVisibility(GONE);
@ -383,31 +384,31 @@ public final class ConversationListItem extends ConstraintLayout
return lastSeen; return lastSeen;
} }
private void observeRecipient(@Nullable LiveRecipient newRecipient) { private void observeRecipient(@Nullable LifecycleOwner lifecycleOwner, @Nullable LiveRecipient newRecipient) {
if (this.recipient != null) { if (this.recipient != null) {
this.recipient.removeForeverObserver(this); this.recipient.getLiveData().removeObserver(recipientObserver);
} }
this.recipient = newRecipient; this.recipient = newRecipient;
if (this.recipient != null) { if (lifecycleOwner != null && this.recipient != null) {
this.recipient.observeForever(this); this.recipient.getLiveData().observe(lifecycleOwner, recipientObserver);
} }
} }
private void observeDisplayBody(@Nullable LiveData<SpannableString> displayBody) { private void observeDisplayBody(@Nullable LifecycleOwner lifecycleOwner, @Nullable LiveData<SpannableString> displayBody) {
if (displayBody == null && glideRequests != null) { if (displayBody == null && glideRequests != null) {
glideRequests.clear(thumbTarget); glideRequests.clear(thumbTarget);
} }
if (this.displayBody != null) { if (this.displayBody != null) {
this.displayBody.removeObserver(this); this.displayBody.removeObserver(displayBodyObserver);
} }
this.displayBody = displayBody; this.displayBody = displayBody;
if (this.displayBody != null) { if (lifecycleOwner != null && this.displayBody != null) {
this.displayBody.observeForever(this); this.displayBody.observe(lifecycleOwner, displayBodyObserver);
} }
} }
@ -424,7 +425,7 @@ public final class ConversationListItem extends ConstraintLayout
if (MmsSmsColumns.Types.isBadDecryptType(thread.getType())) { if (MmsSmsColumns.Types.isBadDecryptType(thread.getType())) {
deliveryStatusIndicator.setNone(); deliveryStatusIndicator.setNone();
alertView.setFailed(); alertView.setFailed();
} else if (!thread.isOutgoing() || } else if (!thread.isOutgoing() ||
thread.isOutgoingAudioCall() || thread.isOutgoingAudioCall() ||
thread.isOutgoingVideoCall() || thread.isOutgoingVideoCall() ||
thread.isVerificationStatusChange()) thread.isVerificationStatusChange())
@ -470,8 +471,7 @@ public final class ConversationListItem extends ConstraintLayout
unreadIndicator.setVisibility(View.VISIBLE); unreadIndicator.setVisibility(View.VISIBLE);
} }
@Override private void onRecipientChanged(@NonNull Recipient recipient) {
public void onRecipientChanged(@NonNull Recipient recipient) {
if (this.recipient == null || !this.recipient.getId().equals(recipient.getId())) { if (this.recipient == null || !this.recipient.getId().equals(recipient.getId())) {
Log.w(TAG, "Bad change! Local recipient doesn't match. Ignoring. Local: " + (this.recipient == null ? "null" : this.recipient.getId()) + ", Changed: " + recipient.getId()); Log.w(TAG, "Bad change! Local recipient doesn't match. Ignoring. Local: " + (this.recipient == null ? "null" : this.recipient.getId()) + ", Changed: " + recipient.getId());
return; return;
@ -531,7 +531,7 @@ public final class ConversationListItem extends ConstraintLayout
} else if (SmsDatabase.Types.isJoinedType(thread.getType())) { } else if (SmsDatabase.Types.isJoinedType(thread.getType())) {
return emphasisAdded(recipientToStringAsync(thread.getRecipient().getId(), r -> new SpannableString(context.getString(R.string.ThreadRecord_s_is_on_signal, r.getDisplayName(context))))); return emphasisAdded(recipientToStringAsync(thread.getRecipient().getId(), r -> new SpannableString(context.getString(R.string.ThreadRecord_s_is_on_signal, r.getDisplayName(context)))));
} else if (SmsDatabase.Types.isExpirationTimerUpdate(thread.getType())) { } else if (SmsDatabase.Types.isExpirationTimerUpdate(thread.getType())) {
int seconds = (int)(thread.getExpiresIn() / 1000); int seconds = (int) (thread.getExpiresIn() / 1000);
if (seconds <= 0) { if (seconds <= 0) {
return emphasisAdded(context, context.getString(R.string.ThreadRecord_disappearing_messages_disabled), R.drawable.ic_update_timer_disabled_16, defaultTint); return emphasisAdded(context, context.getString(R.string.ThreadRecord_disappearing_messages_disabled), R.drawable.ic_update_timer_disabled_16, defaultTint);
} }
@ -649,7 +649,9 @@ public final class ConversationListItem extends ConstraintLayout
return new SpannableString(builder); return new SpannableString(builder);
} }
/** After a short delay, if the main data hasn't shown yet, then a loading message is displayed. */ /**
* After a short delay, if the main data hasn't shown yet, then a loading message is displayed.
*/
private static @NonNull LiveData<SpannableString> whileLoadingShow(@NonNull String loading, @NonNull LiveData<SpannableString> string) { private static @NonNull LiveData<SpannableString> whileLoadingShow(@NonNull String loading, @NonNull LiveData<SpannableString> string) {
return LiveDataUtil.until(string, LiveDataUtil.delay(250, new SpannableString(loading))); return LiveDataUtil.until(string, LiveDataUtil.delay(250, new SpannableString(loading)));
} }
@ -682,9 +684,9 @@ public final class ConversationListItem extends ConstraintLayout
return Transformations.map(description, sequence -> { return Transformations.map(description, sequence -> {
SpannableString spannable = new SpannableString(sequence); SpannableString spannable = new SpannableString(sequence);
spannable.setSpan(new StyleSpan(Typeface.ITALIC), spannable.setSpan(new StyleSpan(Typeface.ITALIC),
0, 0,
sequence.length(), sequence.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return spannable; return spannable;
}); });
} }
@ -699,8 +701,7 @@ public final class ConversationListItem extends ConstraintLayout
} }
} }
@Override private void onDisplayBodyChanged(SpannableString spannableString) {
public void onChanged(SpannableString spannableString) {
setSubjectViewText(spannableString); setSubjectViewText(spannableString);
if (typingThreads != null) { if (typingThreads != null) {

Wyświetl plik

@ -6,6 +6,7 @@ import android.widget.FrameLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.lifecycle.LifecycleOwner;
import org.thoughtcrime.securesms.BindableConversationListItem; import org.thoughtcrime.securesms.BindableConversationListItem;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
@ -39,7 +40,8 @@ public class ConversationListItemAction extends FrameLayout implements BindableC
} }
@Override @Override
public void bind(@NonNull ThreadRecord thread, public void bind(@NonNull LifecycleOwner lifecycleOwner,
@NonNull ThreadRecord thread,
@NonNull GlideRequests glideRequests, @NonNull GlideRequests glideRequests,
@NonNull Locale locale, @NonNull Locale locale,
@NonNull Set<Long> typingThreads, @NonNull Set<Long> typingThreads,

Wyświetl plik

@ -1,63 +0,0 @@
package org.thoughtcrime.securesms.conversationlist;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import org.thoughtcrime.securesms.BindableConversationListItem;
import org.thoughtcrime.securesms.conversationlist.model.ConversationSet;
import org.thoughtcrime.securesms.database.model.ThreadRecord;
import org.thoughtcrime.securesms.mms.GlideRequests;
import java.util.Locale;
import java.util.Set;
public class ConversationListItemInboxZero extends LinearLayout implements BindableConversationListItem {
public ConversationListItemInboxZero(Context context) {
super(context);
}
public ConversationListItemInboxZero(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public ConversationListItemInboxZero(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public ConversationListItemInboxZero(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public void unbind() {
}
@Override
public void bind(@NonNull ThreadRecord thread,
@NonNull GlideRequests glideRequests,
@NonNull Locale locale,
@NonNull Set<Long> typingThreads,
@NonNull ConversationSet selectedConversations)
{
}
@Override
public void setSelectedConversations(@NonNull ConversationSet conversations) {
}
@Override
public void updateTypingIndicator(@NonNull Set<Long> typingThreads) {
}
}

Wyświetl plik

@ -7,6 +7,7 @@ import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.lifecycle.LifecycleOwner;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
@ -28,20 +29,23 @@ class ConversationListSearchAdapter extends RecyclerView.Adapter<Conversation
private static final int TYPE_CONTACTS = 2; private static final int TYPE_CONTACTS = 2;
private static final int TYPE_MESSAGES = 3; private static final int TYPE_MESSAGES = 3;
private final GlideRequests glideRequests; private final LifecycleOwner lifecycleOwner;
private final EventListener eventListener; private final GlideRequests glideRequests;
private final Locale locale; private final EventListener eventListener;
private final Locale locale;
@NonNull @NonNull
private SearchResult searchResult = SearchResult.EMPTY; private SearchResult searchResult = SearchResult.EMPTY;
ConversationListSearchAdapter(@NonNull GlideRequests glideRequests, ConversationListSearchAdapter(@NonNull LifecycleOwner lifecycleOwner,
@NonNull GlideRequests glideRequests,
@NonNull EventListener eventListener, @NonNull EventListener eventListener,
@NonNull Locale locale) @NonNull Locale locale)
{ {
this.glideRequests = glideRequests; this.lifecycleOwner = lifecycleOwner;
this.eventListener = eventListener; this.glideRequests = glideRequests;
this.locale = locale; this.eventListener = eventListener;
this.locale = locale;
} }
@Override @Override
@ -55,21 +59,21 @@ class ConversationListSearchAdapter extends RecyclerView.Adapter<Conversation
ThreadRecord conversationResult = getConversationResult(position); ThreadRecord conversationResult = getConversationResult(position);
if (conversationResult != null) { if (conversationResult != null) {
holder.bind(conversationResult, glideRequests, eventListener, locale, searchResult.getQuery()); holder.bind(lifecycleOwner, conversationResult, glideRequests, eventListener, locale, searchResult.getQuery());
return; return;
} }
Recipient contactResult = getContactResult(position); Recipient contactResult = getContactResult(position);
if (contactResult != null) { if (contactResult != null) {
holder.bind(contactResult, glideRequests, eventListener, locale, searchResult.getQuery()); holder.bind(lifecycleOwner, contactResult, glideRequests, eventListener, locale, searchResult.getQuery());
return; return;
} }
MessageResult messageResult = getMessageResult(position); MessageResult messageResult = getMessageResult(position);
if (messageResult != null) { if (messageResult != null) {
holder.bind(messageResult, glideRequests, eventListener, locale, searchResult.getQuery()); holder.bind(lifecycleOwner, messageResult, glideRequests, eventListener, locale, searchResult.getQuery());
} }
} }
@ -157,33 +161,36 @@ class ConversationListSearchAdapter extends RecyclerView.Adapter<Conversation
root = (ConversationListItem) itemView; root = (ConversationListItem) itemView;
} }
void bind(@NonNull ThreadRecord conversationResult, void bind(@NonNull LifecycleOwner lifecycleOwner,
@NonNull ThreadRecord conversationResult,
@NonNull GlideRequests glideRequests, @NonNull GlideRequests glideRequests,
@NonNull EventListener eventListener, @NonNull EventListener eventListener,
@NonNull Locale locale, @NonNull Locale locale,
@Nullable String query) @Nullable String query)
{ {
root.bindThread(conversationResult, glideRequests, locale, Collections.emptySet(), new ConversationSet(), query); root.bindThread(lifecycleOwner, conversationResult, glideRequests, locale, Collections.emptySet(), new ConversationSet(), query);
root.setOnClickListener(view -> eventListener.onConversationClicked(conversationResult)); root.setOnClickListener(view -> eventListener.onConversationClicked(conversationResult));
} }
void bind(@NonNull Recipient contactResult, void bind(@NonNull LifecycleOwner lifecycleOwner,
@NonNull Recipient contactResult,
@NonNull GlideRequests glideRequests, @NonNull GlideRequests glideRequests,
@NonNull EventListener eventListener, @NonNull EventListener eventListener,
@NonNull Locale locale, @NonNull Locale locale,
@Nullable String query) @Nullable String query)
{ {
root.bindContact(contactResult, glideRequests, locale, query); root.bindContact(lifecycleOwner, contactResult, glideRequests, locale, query);
root.setOnClickListener(view -> eventListener.onContactClicked(contactResult)); root.setOnClickListener(view -> eventListener.onContactClicked(contactResult));
} }
void bind(@NonNull MessageResult messageResult, void bind(@NonNull LifecycleOwner lifecycleOwner,
@NonNull MessageResult messageResult,
@NonNull GlideRequests glideRequests, @NonNull GlideRequests glideRequests,
@NonNull EventListener eventListener, @NonNull EventListener eventListener,
@NonNull Locale locale, @NonNull Locale locale,
@Nullable String query) @Nullable String query)
{ {
root.bindMessage(messageResult, glideRequests, locale, query); root.bindMessage(lifecycleOwner, messageResult, glideRequests, locale, query);
root.setOnClickListener(view -> eventListener.onMessageClicked(messageResult)); root.setOnClickListener(view -> eventListener.onMessageClicked(messageResult));
} }