make RecyclerView unique IDs per thread

Closes #4619
// FREEBIE
This commit is contained in:
Jake McGinty 2015-11-19 18:28:57 -08:00 committed by Moxie Marlinspike
parent dc1b420fef
commit 2e8841c1d6

View File

@ -27,6 +27,7 @@ import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener; import android.view.View.OnLongClickListener;
import android.view.ViewGroup; import android.view.ViewGroup;
import org.thoughtcrime.redphone.util.Conversions;
import org.thoughtcrime.securesms.crypto.MasterCipher; import org.thoughtcrime.securesms.crypto.MasterCipher;
import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter; import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
@ -34,6 +35,8 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.ThreadDatabase; import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.database.model.ThreadRecord; import org.thoughtcrime.securesms.database.model.ThreadRecord;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Locale; import java.util.Locale;
@ -46,19 +49,21 @@ import java.util.Set;
*/ */
public class ConversationListAdapter extends CursorRecyclerViewAdapter<ConversationListAdapter.ViewHolder> { public class ConversationListAdapter extends CursorRecyclerViewAdapter<ConversationListAdapter.ViewHolder> {
private final ThreadDatabase threadDatabase; private final ThreadDatabase threadDatabase;
private final MasterSecret masterSecret; private final MasterSecret masterSecret;
private final MasterCipher masterCipher; private final MasterCipher masterCipher;
private final Locale locale; private final Locale locale;
private final LayoutInflater inflater; private final LayoutInflater inflater;
private final ItemClickListener clickListener; private final ItemClickListener clickListener;
private final @NonNull MessageDigest digest;
private final Set<Long> batchSet = Collections.synchronizedSet(new HashSet<Long>()); private final Set<Long> batchSet = Collections.synchronizedSet(new HashSet<Long>());
private boolean batchMode = false; private boolean batchMode = false;
protected static class ViewHolder extends RecyclerView.ViewHolder { protected static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(final @NonNull ConversationListItem itemView, public ViewHolder(final @NonNull ConversationListItem itemView,
final @Nullable ItemClickListener clickListener) { final @Nullable ItemClickListener clickListener)
{
super(itemView); super(itemView);
itemView.setOnClickListener(new OnClickListener() { itemView.setOnClickListener(new OnClickListener() {
@Override @Override
@ -76,23 +81,39 @@ public class ConversationListAdapter extends CursorRecyclerViewAdapter<Conversat
} }
public ConversationListItem getItem() { public ConversationListItem getItem() {
return (ConversationListItem) itemView; return (ConversationListItem)itemView;
} }
} }
@Override
public long getItemId(@NonNull Cursor cursor) {
ThreadRecord record = getThreadRecord(cursor);
StringBuilder builder = new StringBuilder(""+record.getThreadId());
for (long recipientId : record.getRecipients().getIds()) {
builder.append("::").append(recipientId);
}
return Conversions.byteArrayToLong(digest.digest(builder.toString().getBytes()));
}
public ConversationListAdapter(@NonNull Context context, public ConversationListAdapter(@NonNull Context context,
@NonNull MasterSecret masterSecret, @NonNull MasterSecret masterSecret,
@NonNull Locale locale, @NonNull Locale locale,
@Nullable Cursor cursor, @Nullable Cursor cursor,
@Nullable ItemClickListener clickListener) { @Nullable ItemClickListener clickListener)
{
super(context, cursor); super(context, cursor);
this.masterSecret = masterSecret; try {
this.masterCipher = new MasterCipher(masterSecret); this.masterSecret = masterSecret;
this.threadDatabase = DatabaseFactory.getThreadDatabase(context); this.masterCipher = new MasterCipher(masterSecret);
this.locale = locale; this.threadDatabase = DatabaseFactory.getThreadDatabase(context);
this.inflater = LayoutInflater.from(context); this.locale = locale;
this.clickListener = clickListener; this.inflater = LayoutInflater.from(context);
setHasStableIds(true); this.clickListener = clickListener;
this.digest = MessageDigest.getInstance("SHA1");
setHasStableIds(true);
} catch (NoSuchAlgorithmException nsae) {
throw new AssertionError("SHA-1 missing");
}
} }
@Override @Override
@ -101,16 +122,18 @@ public class ConversationListAdapter extends CursorRecyclerViewAdapter<Conversat
parent, false), clickListener); parent, false), clickListener);
} }
@Override public void onItemViewRecycled(ViewHolder holder) { @Override
public void onItemViewRecycled(ViewHolder holder) {
holder.getItem().unbind(); holder.getItem().unbind();
} }
@Override @Override
public void onBindItemViewHolder(ViewHolder viewHolder, @NonNull Cursor cursor) { public void onBindItemViewHolder(ViewHolder viewHolder, @NonNull Cursor cursor) {
ThreadDatabase.Reader reader = threadDatabase.readerFor(cursor, masterCipher); viewHolder.getItem().set(masterSecret, getThreadRecord(cursor), locale, batchSet, batchMode);
ThreadRecord record = reader.getCurrent(); }
viewHolder.getItem().set(masterSecret, record, locale, batchSet, batchMode); private ThreadRecord getThreadRecord(@NonNull Cursor cursor) {
return threadDatabase.readerFor(cursor, masterCipher).getCurrent();
} }
public void toggleThreadInBatchSet(long threadId) { public void toggleThreadInBatchSet(long threadId) {