Loading more comments in ViewPostDetailActivity is back. Display a progress bar when loading more comments. Display an error view when loading more comments failed.

This commit is contained in:
Alex Ning 2019-06-27 15:17:37 +08:00
parent cfe0b357df
commit 08bfa254bc
10 changed files with 199 additions and 86 deletions

View File

@ -10,6 +10,7 @@ import android.net.Uri;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.ProgressBar; import android.widget.ProgressBar;
@ -52,7 +53,9 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
private static final int VIEW_TYPE_FIRST_LOADING_FAILED = 2; private static final int VIEW_TYPE_FIRST_LOADING_FAILED = 2;
private static final int VIEW_TYPE_NO_COMMENT_PLACEHOLDER = 3; private static final int VIEW_TYPE_NO_COMMENT_PLACEHOLDER = 3;
private static final int VIEW_TYPE_COMMENT = 4; private static final int VIEW_TYPE_COMMENT = 4;
private static final int VIEW_TYPE_LOAD_MORE_COMMENT = 5; private static final int VIEW_TYPE_LOAD_MORE_CHILD_COMMENTS = 5;
private static final int VIEW_TYPE_IS_LOADING_MORE_COMMENTS = 6;
private static final int VIEW_TYPE_LOAD_MORE_COMMENTS_FAILED = 7;
private Activity mActivity; private Activity mActivity;
private Retrofit mRetrofit; private Retrofit mRetrofit;
@ -63,19 +66,22 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
private ArrayList<CommentData> mVisibleComments; private ArrayList<CommentData> mVisibleComments;
private String mSubredditNamePrefixed; private String mSubredditNamePrefixed;
private Locale mLocale; private Locale mLocale;
private UpdatePostInPostFragmentCallback mUpdatePostInPostFragmentCallback; private CommentRecyclerViewAdapterCallback mCommentRecyclerViewAdapterCallback;
private LoadSubredditIconAsyncTask mLoadSubredditIconAsyncTask; private LoadSubredditIconAsyncTask mLoadSubredditIconAsyncTask;
private boolean isInitiallyLoading; private boolean isInitiallyLoading;
private boolean isInitiallyLoadingFailed; private boolean isInitiallyLoadingFailed;
private boolean mHasMoreComments;
private boolean loadMoreCommentsFailed;
interface UpdatePostInPostFragmentCallback { interface CommentRecyclerViewAdapterCallback {
void updatePost(Post post); void updatePost(Post post);
void retryFetchingMoreComments();
} }
CommentRecyclerViewAdapter(Activity activity, Retrofit retrofit, Retrofit oauthRetrofit, RequestManager glide, CommentRecyclerViewAdapter(Activity activity, Retrofit retrofit, Retrofit oauthRetrofit, RequestManager glide,
SharedPreferences sharedPreferences, Post post, String subredditNamePrefixed, SharedPreferences sharedPreferences, Post post, String subredditNamePrefixed,
Locale locale, LoadSubredditIconAsyncTask loadSubredditIconAsyncTask, Locale locale, LoadSubredditIconAsyncTask loadSubredditIconAsyncTask,
UpdatePostInPostFragmentCallback updatePostInPostFragmentCallback) { CommentRecyclerViewAdapterCallback commentRecyclerViewAdapterCallback) {
mActivity = activity; mActivity = activity;
mRetrofit = retrofit; mRetrofit = retrofit;
mOauthRetrofit = oauthRetrofit; mOauthRetrofit = oauthRetrofit;
@ -86,9 +92,11 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
mSubredditNamePrefixed = subredditNamePrefixed; mSubredditNamePrefixed = subredditNamePrefixed;
mLocale = locale; mLocale = locale;
mLoadSubredditIconAsyncTask = loadSubredditIconAsyncTask; mLoadSubredditIconAsyncTask = loadSubredditIconAsyncTask;
mUpdatePostInPostFragmentCallback = updatePostInPostFragmentCallback; mCommentRecyclerViewAdapterCallback = commentRecyclerViewAdapterCallback;
isInitiallyLoading = true; isInitiallyLoading = true;
isInitiallyLoadingFailed = false; isInitiallyLoadingFailed = false;
mHasMoreComments = false;
loadMoreCommentsFailed = false;
} }
@Override @Override
@ -109,29 +117,42 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
} }
} }
if(position == mVisibleComments.size() + 1) {
if(mHasMoreComments) {
return VIEW_TYPE_IS_LOADING_MORE_COMMENTS;
} else {
return VIEW_TYPE_LOAD_MORE_COMMENTS_FAILED;
}
}
CommentData comment = mVisibleComments.get(position - 1); CommentData comment = mVisibleComments.get(position - 1);
if(!comment.isPlaceHolder()) { if(!comment.isPlaceHolder()) {
return VIEW_TYPE_COMMENT; return VIEW_TYPE_COMMENT;
} else { } else {
return VIEW_TYPE_LOAD_MORE_COMMENT; return VIEW_TYPE_LOAD_MORE_CHILD_COMMENTS;
} }
} }
@NonNull @NonNull
@Override @Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if(viewType == VIEW_TYPE_POST_DETAIL) { switch (viewType) {
return new PostDetailViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_post_detail, parent, false)); case VIEW_TYPE_POST_DETAIL:
} else if(viewType == VIEW_TYPE_FIRST_LOADING) { return new PostDetailViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_post_detail, parent, false));
return new LoadCommentsViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_load_comments, parent, false)); case VIEW_TYPE_FIRST_LOADING:
} else if(viewType == VIEW_TYPE_FIRST_LOADING_FAILED) { return new LoadCommentsViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_load_comments, parent, false));
return new LoadCommentsFailedViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_load_comments_failed_placeholder, parent, false)); case VIEW_TYPE_FIRST_LOADING_FAILED:
} else if(viewType == VIEW_TYPE_NO_COMMENT_PLACEHOLDER) { return new LoadCommentsFailedViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_load_comments_failed_placeholder, parent, false));
return new NoCommentViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_no_comment_placeholder, parent, false)); case VIEW_TYPE_NO_COMMENT_PLACEHOLDER:
} else if(viewType == VIEW_TYPE_COMMENT) { return new NoCommentViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_no_comment_placeholder, parent, false));
return new CommentViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_comment, parent, false)); case VIEW_TYPE_COMMENT:
} else { return new CommentViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_comment, parent, false));
return new LoadMoreCommentViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_load_more_comments_placeholder, parent, false)); case VIEW_TYPE_LOAD_MORE_CHILD_COMMENTS:
return new LoadMoreChildCommentsViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_load_more_comments_placeholder, parent, false));
case VIEW_TYPE_IS_LOADING_MORE_COMMENTS:
return new IsLoadingMoreCommentsViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_comment_footer_loading, parent, false));
default:
return new LoadMoreCommentsFailedViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_comment_footer_error, parent, false));
} }
} }
@ -372,21 +393,23 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
.setColorFilter(ContextCompat.getColor(mActivity, R.color.minusButtonColor), android.graphics.PorterDuff.Mode.SRC_IN); .setColorFilter(ContextCompat.getColor(mActivity, R.color.minusButtonColor), android.graphics.PorterDuff.Mode.SRC_IN);
break; break;
} }
} else if(holder instanceof LoadMoreCommentViewHolder) { } else if(holder instanceof LoadMoreChildCommentsViewHolder) {
CommentData placeholder; CommentData placeholder;
placeholder = mVisibleComments.get(holder.getAdapterPosition() - 1); placeholder = mVisibleComments.get(holder.getAdapterPosition() - 1);
ViewGroup.LayoutParams params = ((LoadMoreCommentViewHolder) holder).verticalBlock.getLayoutParams(); ViewGroup.LayoutParams params = ((LoadMoreChildCommentsViewHolder) holder).verticalBlock.getLayoutParams();
params.width = placeholder.getDepth() * 16; params.width = placeholder.getDepth() * 16;
((LoadMoreCommentViewHolder) holder).verticalBlock.setLayoutParams(params); ((LoadMoreChildCommentsViewHolder) holder).verticalBlock.setLayoutParams(params);
if(placeholder.isLoadingMoreChildren()) { if(placeholder.isLoadingMoreChildren()) {
((LoadMoreCommentViewHolder) holder).placeholderTextView.setText(R.string.loading); ((LoadMoreChildCommentsViewHolder) holder).placeholderTextView.setText(R.string.loading);
} else if(placeholder.isLoadMoreChildrenFailed()) { } else if(placeholder.isLoadMoreChildrenFailed()) {
((LoadMoreCommentViewHolder) holder).placeholderTextView.setText(R.string.comment_load_more_comments_failed); ((LoadMoreChildCommentsViewHolder) holder).placeholderTextView.setText(R.string.comment_load_more_comments_failed);
} else { } else {
((LoadMoreCommentViewHolder) holder).placeholderTextView.setText(R.string.comment_load_more_comments); ((LoadMoreChildCommentsViewHolder) holder).placeholderTextView.setText(R.string.comment_load_more_comments);
} }
} else if(holder instanceof LoadMoreCommentsFailedViewHolder) {
((LoadMoreCommentsFailedViewHolder) holder).errorTextView.setText(R.string.post_load_comments_failed);
} }
} }
@ -488,7 +511,7 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
notifyItemRangeRemoved(position + 2, allChildrenSize); notifyItemRangeRemoved(position + 2, allChildrenSize);
} }
void addComments(ArrayList<CommentData> comments) { void addComments(ArrayList<CommentData> comments, boolean hasMoreComments) {
if(mVisibleComments.size() == 0) { if(mVisibleComments.size() == 0) {
isInitiallyLoading = false; isInitiallyLoading = false;
isInitiallyLoadingFailed = false; isInitiallyLoadingFailed = false;
@ -502,6 +525,15 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
int sizeBefore = mVisibleComments.size(); int sizeBefore = mVisibleComments.size();
mVisibleComments.addAll(comments); mVisibleComments.addAll(comments);
notifyItemRangeInserted(sizeBefore + 1, comments.size()); notifyItemRangeInserted(sizeBefore + 1, comments.size());
if(mHasMoreComments != hasMoreComments) {
if(hasMoreComments) {
notifyItemInserted(mVisibleComments.size() + 1);
} else {
notifyItemRemoved(mVisibleComments.size() + 1);
}
}
mHasMoreComments = hasMoreComments;
} }
void addComment(CommentData comment) { void addComment(CommentData comment) {
@ -567,10 +599,17 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
notifyItemChanged(1); notifyItemChanged(1);
} }
void loadMoreCommentsFailed() {
loadMoreCommentsFailed = true;
notifyItemChanged(mVisibleComments.size() + 1);
}
@Override @Override
public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) { public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) {
if (holder instanceof CommentViewHolder) { if (holder instanceof CommentViewHolder) {
((CommentViewHolder) holder).expandButton.setVisibility(View.GONE); ((CommentViewHolder) holder).expandButton.setVisibility(View.GONE);
((CommentViewHolder) holder).upvoteButton.clearColorFilter();
((CommentViewHolder) holder).downvoteButton.clearColorFilter();
} }
} }
@ -580,6 +619,10 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
return 2; return 2;
} }
if(mHasMoreComments || loadMoreCommentsFailed) {
return mVisibleComments.size() + 2;
}
return mVisibleComments.size() + 1; return mVisibleComments.size() + 1;
} }
@ -607,7 +650,7 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
@BindView(R.id.minus_button_item_post_detail) ImageView mDownvoteButton; @BindView(R.id.minus_button_item_post_detail) ImageView mDownvoteButton;
@BindView(R.id.share_button_item_post_detail) ImageView mShareButton; @BindView(R.id.share_button_item_post_detail) ImageView mShareButton;
public PostDetailViewHolder(@NonNull View itemView) { PostDetailViewHolder(@NonNull View itemView) {
super(itemView); super(itemView);
ButterKnife.bind(this, itemView); ButterKnife.bind(this, itemView);
@ -648,7 +691,7 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
mScoreTextView.setText(Integer.toString(mPost.getScore() + mPost.getVoteType())); mScoreTextView.setText(Integer.toString(mPost.getScore() + mPost.getVoteType()));
mUpdatePostInPostFragmentCallback.updatePost(mPost); mCommentRecyclerViewAdapterCallback.updatePost(mPost);
VoteThing.voteThing(mOauthRetrofit, mSharedPreferences, new VoteThing.VoteThingWithoutPositionListener() { VoteThing.voteThing(mOauthRetrofit, mSharedPreferences, new VoteThing.VoteThingWithoutPositionListener() {
@Override @Override
@ -664,7 +707,7 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
mDownvoteButton.clearColorFilter(); mDownvoteButton.clearColorFilter();
mScoreTextView.setText(Integer.toString(mPost.getScore() + mPost.getVoteType())); mScoreTextView.setText(Integer.toString(mPost.getScore() + mPost.getVoteType()));
mUpdatePostInPostFragmentCallback.updatePost(mPost); mCommentRecyclerViewAdapterCallback.updatePost(mPost);
} }
@Override @Override
@ -675,7 +718,7 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
mUpvoteButton.setColorFilter(previousUpvoteButtonColorFilter); mUpvoteButton.setColorFilter(previousUpvoteButtonColorFilter);
mDownvoteButton.setColorFilter(previousDownvoteButtonColorFilter); mDownvoteButton.setColorFilter(previousDownvoteButtonColorFilter);
mUpdatePostInPostFragmentCallback.updatePost(mPost); mCommentRecyclerViewAdapterCallback.updatePost(mPost);
} }
}, mPost.getFullName(), newVoteType); }, mPost.getFullName(), newVoteType);
}); });
@ -702,7 +745,7 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
mScoreTextView.setText(Integer.toString(mPost.getScore() + mPost.getVoteType())); mScoreTextView.setText(Integer.toString(mPost.getScore() + mPost.getVoteType()));
mUpdatePostInPostFragmentCallback.updatePost(mPost); mCommentRecyclerViewAdapterCallback.updatePost(mPost);
VoteThing.voteThing(mOauthRetrofit, mSharedPreferences, new VoteThing.VoteThingWithoutPositionListener() { VoteThing.voteThing(mOauthRetrofit, mSharedPreferences, new VoteThing.VoteThingWithoutPositionListener() {
@Override @Override
@ -718,7 +761,7 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
mUpvoteButton.clearColorFilter(); mUpvoteButton.clearColorFilter();
mScoreTextView.setText(Integer.toString(mPost.getScore() + mPost.getVoteType())); mScoreTextView.setText(Integer.toString(mPost.getScore() + mPost.getVoteType()));
mUpdatePostInPostFragmentCallback.updatePost(mPost); mCommentRecyclerViewAdapterCallback.updatePost(mPost);
} }
@Override @Override
@ -729,7 +772,7 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
mUpvoteButton.setColorFilter(previousUpvoteButtonColorFilter); mUpvoteButton.setColorFilter(previousUpvoteButtonColorFilter);
mDownvoteButton.setColorFilter(previousDownvoteButtonColorFilter); mDownvoteButton.setColorFilter(previousDownvoteButtonColorFilter);
mUpdatePostInPostFragmentCallback.updatePost(mPost); mCommentRecyclerViewAdapterCallback.updatePost(mPost);
} }
}, mPost.getFullName(), newVoteType); }, mPost.getFullName(), newVoteType);
}); });
@ -869,11 +912,11 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
} }
} }
class LoadMoreCommentViewHolder extends RecyclerView.ViewHolder { class LoadMoreChildCommentsViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.vertical_block_item_load_more_comments) View verticalBlock; @BindView(R.id.vertical_block_item_load_more_comments) View verticalBlock;
@BindView(R.id.placeholder_text_view_item_load_more_comments) TextView placeholderTextView; @BindView(R.id.placeholder_text_view_item_load_more_comments) TextView placeholderTextView;
LoadMoreCommentViewHolder(View itemView) { LoadMoreChildCommentsViewHolder(View itemView) {
super(itemView); super(itemView);
ButterKnife.bind(this, itemView); ButterKnife.bind(this, itemView);
@ -1055,4 +1098,22 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
super(itemView); super(itemView);
} }
} }
class IsLoadingMoreCommentsViewHolder extends RecyclerView.ViewHolder {
IsLoadingMoreCommentsViewHolder(@NonNull View itemView) {
super(itemView);
}
}
class LoadMoreCommentsFailedViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.error_text_view_item_comment_footer_error) TextView errorTextView;
@BindView(R.id.retry_button_item_comment_footer_error) Button retryButton;
public LoadMoreCommentsFailedViewHolder(@NonNull View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
retryButton.setOnClickListener(view -> mCommentRecyclerViewAdapterCallback.retryFetchingMoreComments());
}
}
} }

View File

@ -608,9 +608,8 @@ class PostRecyclerViewAdapter extends PagedListAdapter<Post, RecyclerView.ViewHo
} }
class ErrorViewHolder extends RecyclerView.ViewHolder { class ErrorViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.relative_layout_footer_error_item) RelativeLayout relativeLayout; @BindView(R.id.error_text_view_item_footer_error) TextView errorTextView;
@BindView(R.id.error_text_view_footer_error_item) TextView errorTextView; @BindView(R.id.retry_button_item_footer_error) Button retryButton;
@BindView(R.id.retry_button_footer_error_item) Button retryButton;
ErrorViewHolder(View itemView) { ErrorViewHolder(View itemView) {
super(itemView); super(itemView);
@ -621,8 +620,6 @@ class PostRecyclerViewAdapter extends PagedListAdapter<Post, RecyclerView.ViewHo
} }
class LoadingViewHolder extends RecyclerView.ViewHolder { class LoadingViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.progress_bar_footer_progress_bar_item) ProgressBar progressBar;
LoadingViewHolder(@NonNull View itemView) { LoadingViewHolder(@NonNull View itemView) {
super(itemView); super(itemView);
ButterKnife.bind(this, itemView); ButterKnife.bind(this, itemView);

View File

@ -8,22 +8,22 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.paging.PagedListAdapter;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide; import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestManager; import com.bumptech.glide.RequestManager;
import com.bumptech.glide.request.RequestOptions; import com.bumptech.glide.request.RequestOptions;
import SubredditDatabase.SubredditData; import SubredditDatabase.SubredditData;
import SubscribedSubredditDatabase.SubscribedSubredditDao; import SubscribedSubredditDatabase.SubscribedSubredditDao;
import androidx.annotation.NonNull;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.paging.PagedListAdapter;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView; import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import jp.wasabeef.glide.transformations.RoundedCornersTransformation; import jp.wasabeef.glide.transformations.RoundedCornersTransformation;
@ -201,9 +201,8 @@ public class SubredditListingRecyclerViewAdapter extends PagedListAdapter<Subred
} }
class ErrorViewHolder extends RecyclerView.ViewHolder { class ErrorViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.relative_layout_footer_error_item) RelativeLayout relativeLayout; @BindView(R.id.error_text_view_item_footer_error) TextView errorTextView;
@BindView(R.id.error_text_view_footer_error_item) TextView errorTextView; @BindView(R.id.retry_button_item_footer_error) Button retryButton;
@BindView(R.id.retry_button_footer_error_item) Button retryButton;
ErrorViewHolder(View itemView) { ErrorViewHolder(View itemView) {
super(itemView); super(itemView);
@ -214,8 +213,6 @@ public class SubredditListingRecyclerViewAdapter extends PagedListAdapter<Subred
} }
class LoadingViewHolder extends RecyclerView.ViewHolder { class LoadingViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.progress_bar_footer_progress_bar_item) ProgressBar progressBar;
LoadingViewHolder(@NonNull View itemView) { LoadingViewHolder(@NonNull View itemView) {
super(itemView); super(itemView);
ButterKnife.bind(this, itemView); ButterKnife.bind(this, itemView);

View File

@ -8,22 +8,22 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.paging.PagedListAdapter;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide; import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestManager; import com.bumptech.glide.RequestManager;
import com.bumptech.glide.request.RequestOptions; import com.bumptech.glide.request.RequestOptions;
import SubscribedUserDatabase.SubscribedUserDao; import SubscribedUserDatabase.SubscribedUserDao;
import User.UserData; import User.UserData;
import androidx.annotation.NonNull;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.paging.PagedListAdapter;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView; import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import jp.wasabeef.glide.transformations.RoundedCornersTransformation; import jp.wasabeef.glide.transformations.RoundedCornersTransformation;
@ -201,9 +201,8 @@ public class UserListingRecyclerViewAdapter extends PagedListAdapter<UserData, R
} }
class ErrorViewHolder extends RecyclerView.ViewHolder { class ErrorViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.relative_layout_footer_error_item) RelativeLayout relativeLayout; @BindView(R.id.error_text_view_item_footer_error) TextView errorTextView;
@BindView(R.id.error_text_view_footer_error_item) TextView errorTextView; @BindView(R.id.retry_button_item_footer_error) Button retryButton;
@BindView(R.id.retry_button_footer_error_item) Button retryButton;
ErrorViewHolder(View itemView) { ErrorViewHolder(View itemView) {
super(itemView); super(itemView);
@ -214,8 +213,6 @@ public class UserListingRecyclerViewAdapter extends PagedListAdapter<UserData, R
} }
class LoadingViewHolder extends RecyclerView.ViewHolder { class LoadingViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.progress_bar_footer_progress_bar_item) ProgressBar progressBar;
LoadingViewHolder(@NonNull View itemView) { LoadingViewHolder(@NonNull View itemView) {
super(itemView); super(itemView);
ButterKnife.bind(this, itemView); ButterKnife.bind(this, itemView);

View File

@ -57,7 +57,9 @@ public class ViewPostDetailActivity extends AppCompatActivity {
private boolean isRefreshing = false; private boolean isRefreshing = false;
private ArrayList<String> children; private ArrayList<String> children;
private int mChildrenStartingIndex = 0; private int mChildrenStartingIndex = 0;
private boolean loadMoreChildrenSuccess = true;
private LinearLayoutManager mLinearLayoutManager;
private CommentRecyclerViewAdapter mAdapter; private CommentRecyclerViewAdapter mAdapter;
private LoadSubredditIconAsyncTask mLoadSubredditIconAsyncTask; private LoadSubredditIconAsyncTask mLoadSubredditIconAsyncTask;
@ -91,8 +93,8 @@ public class ViewPostDetailActivity extends AppCompatActivity {
mGlide = Glide.with(this); mGlide = Glide.with(this);
mLocale = getResources().getConfiguration().locale; mLocale = getResources().getConfiguration().locale;
mRecyclerView.setNestedScrollingEnabled(false); mLinearLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); mRecyclerView.setLayoutManager(mLinearLayoutManager);
if(savedInstanceState == null) { if(savedInstanceState == null) {
orientation = getResources().getConfiguration().orientation; orientation = getResources().getConfiguration().orientation;
@ -105,7 +107,20 @@ public class ViewPostDetailActivity extends AppCompatActivity {
mAdapter = new CommentRecyclerViewAdapter(ViewPostDetailActivity.this, mRetrofit, mAdapter = new CommentRecyclerViewAdapter(ViewPostDetailActivity.this, mRetrofit,
mOauthRetrofit, mGlide, mSharedPreferences, mPost, mOauthRetrofit, mGlide, mSharedPreferences, mPost,
mPost.getSubredditNamePrefixed(), mLocale, mLoadSubredditIconAsyncTask, mPost.getSubredditNamePrefixed(), mLocale, mLoadSubredditIconAsyncTask,
post -> EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition))); new CommentRecyclerViewAdapter.CommentRecyclerViewAdapterCallback() {
@Override
public void updatePost(Post post) {
EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition));
}
@Override
public void retryFetchingMoreComments() {
isLoadingMoreChildren = false;
loadMoreChildrenSuccess = true;
fetchMoreComments();
}
});
mRecyclerView.setAdapter(mAdapter); mRecyclerView.setAdapter(mAdapter);
if(savedInstanceState != null) { if(savedInstanceState != null) {
@ -133,16 +148,26 @@ public class ViewPostDetailActivity extends AppCompatActivity {
String parentId, ArrayList<String> children) { String parentId, ArrayList<String> children) {
ViewPostDetailActivity.this.children = children; ViewPostDetailActivity.this.children = children;
mAdapter.addComments(expandedComments); mAdapter.addComments(expandedComments, children.size() != 0);
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { if(children.size() > 0) {
@Override mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { @Override
super.onScrolled(recyclerView, dx, dy); public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if(!isLoadingMoreChildren && loadMoreChildrenSuccess) {
int visibleItemCount = mLinearLayoutManager.getChildCount();
int totalItemCount = mLinearLayoutManager.getItemCount();
int firstVisibleItemPosition = mLinearLayoutManager.findFirstVisibleItemPosition();
} if ((visibleItemCount + firstVisibleItemPosition >= totalItemCount) && firstVisibleItemPosition >= 0) {
}); fetchMoreComments();
}
}
}
});
}
/*mCommentProgressbar.setVisibility(View.GONE); /*mCommentProgressbar.setVisibility(View.GONE);
@ -154,7 +179,7 @@ public class ViewPostDetailActivity extends AppCompatActivity {
int diff = view.getBottom() - (mNestedScrollView.getHeight() + int diff = view.getBottom() - (mNestedScrollView.getHeight() +
mNestedScrollView.getScrollY()); mNestedScrollView.getScrollY());
if(diff == 0) { if(diff == 0) {
fetchMoreComment(mChildrenStartingIndex); fetchMoreComments(mChildrenStartingIndex);
} }
} }
}); });
@ -162,7 +187,7 @@ public class ViewPostDetailActivity extends AppCompatActivity {
mAdapter = new CommentRecyclerViewAdapter(ViewPostDetailActivity.this, mRetrofit, mAdapter = new CommentRecyclerViewAdapter(ViewPostDetailActivity.this, mRetrofit,
mOauthRetrofit, mGlide, mSharedPreferences, mPost, mOauthRetrofit, mGlide, mSharedPreferences, mPost,
mPost.getSubredditNamePrefixed(), mLocale, new CommentRecyclerViewAdapter.UpdatePostInPostFragmentCallback() { mPost.getSubredditNamePrefixed(), mLocale, new CommentRecyclerViewAdapter.CommentRecyclerViewAdapterCallback() {
@Override @Override
public void updatePost(Post post) { public void updatePost(Post post) {
EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition)); EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition));
@ -184,27 +209,27 @@ public class ViewPostDetailActivity extends AppCompatActivity {
}); });
} }
private void fetchMoreComment(int startingIndex) { void fetchMoreComments() {
if(isLoadingMoreChildren) { if(isLoadingMoreChildren || !loadMoreChildrenSuccess) {
return; return;
} }
isLoadingMoreChildren = true; isLoadingMoreChildren = true;
FetchComment.fetchMoreComment(mRetrofit, mPost.getSubredditNamePrefixed(), children, startingIndex, FetchComment.fetchMoreComment(mRetrofit, mPost.getSubredditNamePrefixed(), children, mChildrenStartingIndex,
0, mLocale, new FetchComment.FetchMoreCommentListener() { 0, mLocale, new FetchComment.FetchMoreCommentListener() {
@Override @Override
public void onFetchMoreCommentSuccess(ArrayList<CommentData> expandedComments, int childrenStartingIndex) { public void onFetchMoreCommentSuccess(ArrayList<CommentData> expandedComments, int childrenStartingIndex) {
mAdapter.addComments(expandedComments); mAdapter.addComments(expandedComments, childrenStartingIndex < children.size());
mChildrenStartingIndex = childrenStartingIndex; mChildrenStartingIndex = childrenStartingIndex;
isLoadingMoreChildren = false; isLoadingMoreChildren = false;
loadMoreChildrenSuccess = true;
} }
@Override @Override
public void onFetchMoreCommentFailed() { public void onFetchMoreCommentFailed() {
isLoadingMoreChildren = false; isLoadingMoreChildren = false;
Snackbar snackbar = Snackbar.make(mCoordinatorLayout, R.string.post_load_more_comments_failed, Snackbar.LENGTH_INDEFINITE); loadMoreChildrenSuccess = false;
snackbar.setAction(R.string.retry, view -> fetchMoreComment(startingIndex)); mAdapter.loadMoreCommentsFailed();
snackbar.show();
} }
}); });
} }

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/relative_layout_item_comment_footer_error"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp">
<TextView
android:id="@+id/error_text_view_item_comment_footer_error"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_toStartOf="@id/retry_button_item_comment_footer_error"
android:textSize="18sp" />
<Button
android:id="@+id/retry_button_item_comment_footer_error"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:text="@string/retry" />
</RelativeLayout>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:layout_centerHorizontal="true" />
</RelativeLayout>

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/relative_layout_footer_error_item"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
@ -9,16 +8,16 @@
android:layout_marginBottom="16dp"> android:layout_marginBottom="16dp">
<TextView <TextView
android:id="@+id/error_text_view_footer_error_item" android:id="@+id/error_text_view_item_footer_error"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_toStartOf="@id/retry_button_footer_error_item" android:layout_toStartOf="@id/retry_button_item_footer_error"
android:textSize="18sp" /> android:textSize="18sp" />
<Button <Button
android:id="@+id/retry_button_footer_error_item" android:id="@+id/retry_button_item_footer_error"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"

View File

@ -5,7 +5,6 @@
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<ProgressBar <ProgressBar
android:id="@+id/progress_bar_footer_progress_bar_item"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"

View File

@ -28,7 +28,6 @@
<string name="load_posts_failed">Error loading posts</string> <string name="load_posts_failed">Error loading posts</string>
<string name="post_load_comments_failed">Error loading comments</string> <string name="post_load_comments_failed">Error loading comments</string>
<string name="post_load_more_comments_failed">Error loading more comments</string>
<string name="retry">Retry</string> <string name="retry">Retry</string>
<string name="comments">Comments</string> <string name="comments">Comments</string>
<string name="no_comments_yet">No comments yet. Write a comment?</string> <string name="no_comments_yet">No comments yet. Write a comment?</string>