Skip to content

Commit

Permalink
Add placeholder support for ConversationListAdapter.
Browse files Browse the repository at this point in the history
  • Loading branch information
greyson-signal committed Jun 16, 2020
1 parent 49f75d7 commit cf98a22
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 31 deletions.
Expand Up @@ -65,10 +65,6 @@ public void loadInitial(@NonNull LoadInitialParams params, @NonNull LoadInitialC
int totalCount = db.getConversationCount(threadId);
int effectiveCount = params.requestedStartPosition;

if (totalCount == 0 || params.requestedStartPosition > totalCount) {

}

try (MmsSmsDatabase.Reader reader = db.readerFor(db.getConversation(threadId, params.requestedStartPosition, params.requestedLoadSize))) {
MessageRecord record;
while ((record = reader.getNext()) != null && effectiveCount < totalCount && !isInvalid()) {
Expand All @@ -83,7 +79,7 @@ public void loadInitial(@NonNull LoadInitialParams params, @NonNull LoadInitialC
callback.onResult(result.getItems(), params.requestedStartPosition, result.getTotal());
}

Log.d(TAG, "[Initial Load] " + (System.currentTimeMillis() - start) + " ms" + (isInvalid() ? " -- invalidated" : ""));
Log.d(TAG, "[Initial Load] " + (System.currentTimeMillis() - start) + " ms | thread: " + threadId + ", start: " + params.requestedStartPosition + ", size: " + params.requestedLoadSize + (isInvalid() ? " -- invalidated" : ""));
}

@Override
Expand All @@ -102,7 +98,7 @@ public void loadRange(@NonNull LoadRangeParams params, @NonNull LoadRangeCallbac

callback.onResult(records);

Log.d(TAG, "[Update] " + (System.currentTimeMillis() - start) + " ms" + (isInvalid() ? " -- invalidated" : ""));
Log.d(TAG, "[Update] " + (System.currentTimeMillis() - start) + " ms | thread: " + threadId + ", start: " + params.startPosition + ", size: " + params.loadSize + (isInvalid() ? " -- invalidated" : ""));
}

static class Factory extends DataSource.Factory<Integer, MessageRecord> {
Expand Down
Expand Up @@ -3,6 +3,7 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import androidx.annotation.NonNull;
import androidx.paging.PagedListAdapter;
Expand All @@ -16,7 +17,7 @@
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.CachedInflater;
import org.thoughtcrime.securesms.util.Stopwatch;
import org.thoughtcrime.securesms.util.ViewUtil;

import java.util.Collection;
import java.util.Collections;
Expand All @@ -28,7 +29,11 @@
import java.util.Objects;
import java.util.Set;

class ConversationPagedListAdapter extends PagedListAdapter<Conversation, ConversationPagedListAdapter.ConversationViewHolder> {
class ConversationListAdapter extends PagedListAdapter<Conversation, RecyclerView.ViewHolder> {

private static final int TYPE_THREAD = 1;
private static final int TYPE_ACTION = 2;
private static final int TYPE_PLACEHOLDER = 3;

private enum Payload {
TYPING_INDICATOR,
Expand All @@ -42,18 +47,18 @@ private enum Payload {
private final Set<Long> typingSet = new HashSet<>();
private int archived;

protected ConversationPagedListAdapter(@NonNull GlideRequests glideRequests, @NonNull OnConversationClickListener onConversationClickListener) {
protected ConversationListAdapter(@NonNull GlideRequests glideRequests, @NonNull OnConversationClickListener onConversationClickListener) {
super(new ConversationDiffCallback());

this.glideRequests = glideRequests;
this.onConversationClickListener = onConversationClickListener;
}

@Override
public @NonNull ConversationViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (viewType == R.layout.conversation_list_item_action) {
public @NonNull RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (viewType == TYPE_ACTION) {
ConversationViewHolder holder = new ConversationViewHolder(LayoutInflater.from(parent.getContext())
.inflate(viewType, parent, false));
.inflate(R.layout.conversation_list_item_action, parent, false));

holder.itemView.setOnClickListener(v -> {
int position = holder.getAdapterPosition();
Expand All @@ -64,9 +69,9 @@ protected ConversationPagedListAdapter(@NonNull GlideRequests glideRequests, @No
});

return holder;
} else {
} else if (viewType == TYPE_THREAD) {
ConversationViewHolder holder = new ConversationViewHolder(CachedInflater.from(parent.getContext())
.inflate(viewType, parent, false));
.inflate(R.layout.conversation_list_item_view, parent, false));

holder.itemView.setOnClickListener(v -> {
int position = holder.getAdapterPosition();
Expand All @@ -86,11 +91,17 @@ protected ConversationPagedListAdapter(@NonNull GlideRequests glideRequests, @No
return false;
});
return holder;
} else if (viewType == TYPE_PLACEHOLDER) {
View v = new FrameLayout(parent.getContext());
v.setLayoutParams(new FrameLayout.LayoutParams(1, ViewUtil.dpToPx(100)));
return new PlaceholderViewHolder(v);
} else {
throw new IllegalStateException("Unknown type! " + viewType);
}
}

@Override
public void onBindViewHolder(@NonNull ConversationViewHolder holder, int position, @NonNull List<Object> payloads) {
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List<Object> payloads) {
if (payloads.isEmpty()) {
onBindViewHolder(holder, position);
} else {
Expand All @@ -99,19 +110,21 @@ public void onBindViewHolder(@NonNull ConversationViewHolder holder, int positio
Payload payload = (Payload) payloadObject;

if (payload == Payload.SELECTION) {
holder.getConversationListItem().setBatchMode(batchMode);
((ConversationViewHolder) holder).getConversationListItem().setBatchMode(batchMode);
} else {
holder.getConversationListItem().updateTypingIndicator(typingSet);
((ConversationViewHolder) holder).getConversationListItem().updateTypingIndicator(typingSet);
}
}
}
}
}

@Override
public void onBindViewHolder(@NonNull ConversationViewHolder holder, int position) {
if (holder.getItemViewType() == R.layout.conversation_list_item_action) {
holder.getConversationListItem().bind(new ThreadRecord.Builder(100)
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if (holder.getItemViewType() == TYPE_ACTION) {
ConversationViewHolder casted = (ConversationViewHolder) holder;

casted.getConversationListItem().bind(new ThreadRecord.Builder(100)
.setBody("")
.setDate(100)
.setRecipient(Recipient.UNKNOWN)
Expand All @@ -122,10 +135,11 @@ public void onBindViewHolder(@NonNull ConversationViewHolder holder, int positio
typingSet,
getBatchSelectionIds(),
batchMode);
} else {
Conversation conversation = Objects.requireNonNull(getItem(position));
} else if (holder.getItemViewType() == TYPE_THREAD) {
ConversationViewHolder casted = (ConversationViewHolder) holder;
Conversation conversation = Objects.requireNonNull(getItem(position));

holder.getConversationListItem().bind(conversation.getThreadRecord(),
casted.getConversationListItem().bind(conversation.getThreadRecord(),
glideRequests,
conversation.getLocale(),
typingSet,
Expand All @@ -135,8 +149,10 @@ public void onBindViewHolder(@NonNull ConversationViewHolder holder, int positio
}

@Override
public void onViewRecycled(@NonNull ConversationViewHolder holder) {
holder.getConversationListItem().unbind();
public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) {
if (holder instanceof ConversationViewHolder) {
((ConversationViewHolder) holder).getConversationListItem().unbind();
}
}

void setTypingThreads(@NonNull Set<Long> typingThreadSet) {
Expand Down Expand Up @@ -184,9 +200,11 @@ public int getItemCount() {
@Override
public int getItemViewType(int position) {
if (archived > 0 && position == getItemCount() - 1) {
return R.layout.conversation_list_item_action;
return TYPE_ACTION;
} else if (getItem(position) == null) {
return TYPE_PLACEHOLDER;
} else {
return R.layout.conversation_list_item_view;
return TYPE_THREAD;
}
}

Expand Down Expand Up @@ -244,6 +262,12 @@ public boolean areContentsTheSame(@NonNull Conversation oldItem, @NonNull Conver
}
}

private static class PlaceholderViewHolder extends RecyclerView.ViewHolder {
PlaceholderViewHolder(@NonNull View itemView) {
super(itemView);
}
}

interface OnConversationClickListener {
void onConversationClick(Conversation conversation);
boolean onConversationLongClick(Conversation conversation);
Expand Down
Expand Up @@ -137,7 +137,7 @@


public class ConversationListFragment extends MainFragment implements ActionMode.Callback,
ConversationPagedListAdapter.OnConversationClickListener,
ConversationListAdapter.OnConversationClickListener,
ConversationListSearchAdapter.EventListener,
MainNavigator.BackHandler,
MegaphoneActionController
Expand Down Expand Up @@ -167,7 +167,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
private View toolbarShadow;
private ConversationListViewModel viewModel;
private RecyclerView.Adapter activeAdapter;
private ConversationPagedListAdapter defaultAdapter;
private ConversationListAdapter defaultAdapter;
private ConversationListSearchAdapter searchAdapter;
private StickyHeaderDecoration searchAdapterDecoration;
private ViewGroup megaphoneContainer;
Expand Down Expand Up @@ -465,7 +465,7 @@ public void onSearchClosed() {
}

private void initializeListAdapters() {
defaultAdapter = new ConversationPagedListAdapter(GlideApp.with(this), this);
defaultAdapter = new ConversationListAdapter(GlideApp.with(this), this);
searchAdapter = new ConversationListSearchAdapter(GlideApp.with(this), this, Locale.getDefault());
searchAdapterDecoration = new StickyHeaderDecoration(searchAdapter, false, false);

Expand Down
Expand Up @@ -69,7 +69,7 @@ public void onChange(boolean selfChange) {
PagedList.Config config = new PagedList.Config.Builder()
.setPageSize(15)
.setInitialLoadSizeHint(30)
.setEnablePlaceholders(false)
.setEnablePlaceholders(true)
.build();

this.conversationList = new LivePagedListBuilder<>(factory, config).setFetchExecutor(ConversationListDataSource.EXECUTOR)
Expand Down

0 comments on commit cf98a22

Please sign in to comment.