package cl.monsoon.s1next.view.fragment; import android.content.Context; import android.databinding.DataBindingUtil; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import java.util.List; import cl.monsoon.s1next.R; import cl.monsoon.s1next.data.api.model.Post; import cl.monsoon.s1next.data.api.model.Thread; import cl.monsoon.s1next.data.api.model.collection.Posts; import cl.monsoon.s1next.data.api.model.wrapper.PostsWrapper; import cl.monsoon.s1next.databinding.FragmentBaseCardViewContainerBinding; import cl.monsoon.s1next.view.adapter.PostListRecyclerViewAdapter; import cl.monsoon.s1next.view.internal.LoadingViewModelBindingDelegate; import cl.monsoon.s1next.view.internal.LoadingViewModelBindingDelegateBaseCardViewContainerImpl; import rx.Observable; /** * A Fragment representing one of the pages of posts. * <p> * Activity or Fragment containing this must implement {@link PagerCallback}. */ public final class PostListPagerFragment extends BaseFragment<PostsWrapper> { private static final String ARG_THREAD_ID = "thread_id"; private static final String ARG_PAGE_NUM = "page_num"; /** * Used for quote post redirect. */ private static final String ARG_QUOTE_POST_ID = "quote_post_id"; private String mThreadId; private int mPageNum; private RecyclerView mRecyclerView; private PostListRecyclerViewAdapter mRecyclerAdapter; private PagerCallback mPagerCallback; public static PostListPagerFragment newInstance(String threadId, int page) { return newInstance(threadId, page, null); } public static PostListPagerFragment newInstance(String threadId, int pageNum, String postId) { PostListPagerFragment fragment = new PostListPagerFragment(); Bundle bundle = new Bundle(); bundle.putString(ARG_THREAD_ID, threadId); if (!TextUtils.isEmpty(postId)) { bundle.putString(ARG_QUOTE_POST_ID, postId); } bundle.putInt(ARG_PAGE_NUM, pageNum); fragment.setArguments(bundle); return fragment; } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); mThreadId = getArguments().getString(ARG_THREAD_ID); mPageNum = getArguments().getInt(ARG_PAGE_NUM); mRecyclerView = getRecyclerView(); mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); mRecyclerAdapter = new PostListRecyclerViewAdapter(getActivity()); mRecyclerView.setAdapter(mRecyclerAdapter); // add pull up to refresh to RecyclerView mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { if (!isPullUpToRefresh() && mPageNum == mPagerCallback.getTotalPages() && !isLoading() && mRecyclerAdapter.getItemCount() != 0 && !mRecyclerView.canScrollVertically(1)) { startPullToRefresh(); } } }); } @Override public void onAttach(Context context) { super.onAttach(context); mPagerCallback = (PagerCallback) getFragmentManager().findFragmentByTag(PostListFragment.TAG); } @Override public void onDetach() { super.onDetach(); mPagerCallback = null; } @Override LoadingViewModelBindingDelegate getLoadingViewModelBindingDelegateImpl(LayoutInflater inflater, ViewGroup container) { FragmentBaseCardViewContainerBinding binding = DataBindingUtil.inflate(inflater, R.layout.fragment_base_card_view_container, container, false); return new LoadingViewModelBindingDelegateBaseCardViewContainerImpl(binding); } @Override void startPullToRefresh() { mRecyclerAdapter.showFooterProgress(); super.startPullToRefresh(); } @Override Observable<PostsWrapper> getSourceObservable() { return mS1Service.getPostsWrapper(mThreadId, mPageNum); } @Override void onNext(PostsWrapper data) { boolean pullUpToRefresh = isPullUpToRefresh(); if (pullUpToRefresh) { // mRecyclerAdapter.getItemCount() = 0 // when configuration changes (like orientation changes) if (mRecyclerAdapter.getItemCount() != 0) { mRecyclerAdapter.hideFooterProgress(); } } Posts posts = data.getPosts(); List<Post> postList = posts.getPostList(); // if user has logged out, has no permission to access this thread or this thread is invalid if (postList.isEmpty()) { consumeResult(data.getResult()); } else { super.onNext(data); if (pullUpToRefresh) { final int oldItemCount = mRecyclerAdapter.getItemCount(); // oldItemCount = 0 when configuration changes if (oldItemCount != 0 && mRecyclerAdapter.getItemId(oldItemCount - 1) != Long.parseLong(postList.get(postList.size() - 1).getId())) { // notify data set change if someone deleted their posts mRecyclerAdapter.setDataSet(postList); mRecyclerAdapter.notifyDataSetChanged(); } else { mRecyclerAdapter.setDataSet(postList); int newItemCount = mRecyclerAdapter.getItemCount() - oldItemCount; if (newItemCount > 0) { mRecyclerAdapter.notifyItemRangeInserted(oldItemCount, newItemCount); } } } else { mRecyclerAdapter.setDataSet(postList); mRecyclerAdapter.notifyDataSetChanged(); String quotePostId = getArguments().getString(ARG_QUOTE_POST_ID); if (!TextUtils.isEmpty(quotePostId)) { for (int i = 0, length = postList.size(); i < length; i++) { if (quotePostId.equals(postList.get(i).getId())) { // scroll to quote post mRecyclerView.scrollToPosition(i); break; } } // clear this argument after redirecting getArguments().putString(ARG_QUOTE_POST_ID, null); } } Thread postListInfo = posts.getPostListInfo(); // we have not title if we open a thread link in our app if (TextUtils.isEmpty(getActivity().getTitle())) { mPagerCallback.setThreadTitle(postListInfo.getTitle()); } mPagerCallback.setTotalPageByPosts(postListInfo.getReplies() + 1); if (posts.getThreadAttachment() != null) { mPagerCallback.setupThreadAttachment(posts.getThreadAttachment()); } } } @Override void onError(Throwable throwable) { if (isPullUpToRefresh()) { mRecyclerAdapter.hideFooterProgress(); } super.onError(throwable); } public interface PagerCallback { /** * Gets {@link android.support.v4.view.PagerAdapter#getCount()}. */ int getTotalPages(); /** * A callback to set actual total pages * which used for {@link android.support.v4.view.PagerAdapter}。 */ void setTotalPageByPosts(int threads); void setThreadTitle(CharSequence title); void setupThreadAttachment(Posts.ThreadAttachment threadAttachment); } }