package com.badoo.chateau.example.ui.chat.messages;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import com.badoo.barf.mvp.MvpView;
import com.badoo.barf.mvp.PresenterFactory;
import com.badoo.chateau.data.models.payloads.ImagePayload;
import com.badoo.chateau.data.models.payloads.TextPayload;
import com.badoo.chateau.data.models.payloads.TimestampPayload;
import com.badoo.chateau.example.R;
import com.badoo.chateau.example.data.model.ExampleMessage;
import com.badoo.chateau.example.ui.chat.messages.viewholders.ImageMessageViewHolder;
import com.badoo.chateau.example.ui.chat.messages.viewholders.TextMessageViewHolder;
import com.badoo.chateau.example.ui.chat.messages.viewholders.TimestampViewHolder;
import com.badoo.chateau.example.ui.util.MessageViewHolder;
import com.badoo.chateau.example.ui.util.recycle.LoadingAdapter;
import com.badoo.chateau.extras.ViewFinder;
import java.util.List;
public class ExampleMessageListViewImpl implements ExampleMessageListView, MvpView {
private static final String TAG = ExampleMessageListViewImpl.class.getSimpleName();
private static final boolean DEBUG = true;
private final RecyclerView mChatList;
private final LinearLayoutManager mLayoutManager;
private final MessageListAdapter mMessageListAdapter = new MessageListAdapter();
private final LoadingAdapter<MessageViewHolder> mLoadingAdapter = new LoadingAdapter<>(mMessageListAdapter, Integer.MIN_VALUE);
private ExampleMessageListPresenter mPresenter;
private boolean mHasRequestedMoreMessages;
public ExampleMessageListViewImpl(@NonNull ViewFinder finder,
@NonNull PresenterFactory<ExampleMessageListView, ExampleMessageListPresenter> presenterFactory) {
mPresenter = presenterFactory.init(this);
mChatList = finder.findViewById(R.id.chat_list);
mLayoutManager = new LinearLayoutManager(mChatList.getContext());
mLayoutManager.setStackFromEnd(true);
mChatList.setLayoutManager(mLayoutManager);
mLoadingAdapter.setLoading(false);
mLoadingAdapter.setHasStableIds(true);
mChatList.setAdapter(mLoadingAdapter);
mMessageListAdapter.registerMessageViewHolderFactory(TextPayload.class, parent -> {
final View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_chat_text_message, parent, false);
return new TextMessageViewHolder(v);
}, new BaseItemClickListener(mChatList, mMessageListAdapter));
mMessageListAdapter.registerMessageViewHolderFactory(ImagePayload.class, parent -> {
final View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_chat_image_message, parent, false);
return new ImageMessageViewHolder(v);
}, new BaseItemClickListener(mChatList, mMessageListAdapter) {
@Override
public void onClick(@NonNull ExampleMessage message) {
// TODO: Don't allow click when image is loading?
mPresenter.onImageClicked(Uri.parse(((ImagePayload) message.getPayload()).getImageUrl()));
}
});
mMessageListAdapter.registerMessageViewHolderFactory(TimestampPayload.class, parent -> {
final View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_chat_day, parent, false);
return new TimestampViewHolder(v);
});
mMessageListAdapter.registerPreProcessor(new TimeStampPreProcessor());
mChatList.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
notifyIfReachingTopOfList();
}
});
}
@Override
public void showError(boolean fatal, Throwable throwable) {
if (fatal) {
Snackbar.make(mChatList, R.string.error_generic, Snackbar.LENGTH_INDEFINITE).show();
}
}
private void notifyIfReachingTopOfList() {
if (!mHasRequestedMoreMessages && mLayoutManager.findFirstCompletelyVisibleItemPosition() < 10) {
mPresenter.onMoreMessagesRequired();
mHasRequestedMoreMessages = true;
}
}
@Override
public void showLoadingMoreMessages(boolean show) {
mLoadingAdapter.setLoading(show);
}
@Override
public void showMessages(@NonNull List<ExampleMessage> messages) {
mMessageListAdapter.setMessages(messages);
if (mMessageListAdapter.getItemCount() == 0) {
mChatList.scrollToPosition(mMessageListAdapter.getItemCount() - 1);
}
}
@Override
public void showNewerMessages(@NonNull List<ExampleMessage> messages) {
mMessageListAdapter.addNewMessages(messages);
mChatList.scrollToPosition(mMessageListAdapter.getItemCount() - 1);
}
@Override
public void showOlderMessages(@NonNull List<ExampleMessage> messages) {
mMessageListAdapter.addOldMessages(messages);
}
@Override
public void replaceMessage(@NonNull ExampleMessage oldMessage, @NonNull ExampleMessage newMessage) {
mMessageListAdapter.replaceMessage(oldMessage, newMessage);
}
// @Override
// public void showMessages(@NonNull List<ExampleMessage> messages) {
// // When items are added we either want to scroll to the bottom, or if a block of messages were added to the top then we want
// // to maintain the position (the RecyclerView does not handle this properly even with stable ids enabled)
// final boolean addedToTop = !messages.isEmpty() && !messages.get(0).equals(mMessageListAdapter.getOldestMessage());
// final boolean scrollToEndAfterUpdate = isLastItemDisplayed();
// final int lastVisiblePosition = mLoadingAdapter.getAdjustedPosition(mLayoutManager.findLastCompletelyVisibleItemPosition());
// final ExampleMessage lastVisible = lastVisiblePosition != -1 && mMessageListAdapter.getItemCount() > 0 ? mMessageListAdapter.getMessage(lastVisiblePosition) : null;
// mMessageListAdapter.setMessages(messages);
// if (scrollToEndAfterUpdate) {
// mChatList.scrollToPosition(mMessageListAdapter.getItemCount() - 1);
// }
// else if (addedToTop) {
// int index = mMessageListAdapter.getIndexOfMessage(lastVisible);
// if (index != -1) {
// mChatList.scrollToPosition(index);
// }
// }
// mHasRequestedMoreMessages = false;
// if (DEBUG) {
// Log.d(TAG, "Showing messages, scrollToBottom:" + scrollToEndAfterUpdate + ", maintainPosition:" + addedToTop);
// }
// }
/**
* returns <code>true</code> if the last item in the list is been displayed.
*/
private boolean isLastItemDisplayed() {
return mLoadingAdapter.getItemCount() == 0 || mLayoutManager.findLastVisibleItemPosition() == (mLoadingAdapter.getItemCount() - 1);
}
}