Fix force stop when navigating top-level comments. Fix invisible retry loading more posts button in dark theme. Minor bugs fixed.

This commit is contained in:
Alex Ning 2019-11-26 22:01:34 +08:00
parent a7edd207ad
commit b96552a5ca
7 changed files with 69 additions and 67 deletions

View File

@ -6,8 +6,8 @@ android {
applicationId "ml.docilealligator.infinityforreddit"
minSdkVersion 21
targetSdkVersion 29
versionCode 22
versionName "1.6.0"
versionCode 23
versionName "1.6.1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {

View File

@ -258,7 +258,7 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter<Recy
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if (holder.getItemViewType() == VIEW_TYPE_POST_DETAIL) {
if (holder instanceof PostDetailViewHolder) {
((PostDetailViewHolder) holder).mTitleTextView.setText(mPost.getTitle());
if (mPost.getSubredditNamePrefixed().startsWith("u/")) {
if (mPost.getAuthorIconUrl() == null) {
@ -583,7 +583,7 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter<Recy
});
}
});
} else if (holder.getItemViewType() == VIEW_TYPE_COMMENT) {
} else if (holder instanceof CommentViewHolder) {
CommentData comment;
if (mIsSingleCommentThreadMode) {
comment = mVisibleComments.get(holder.getAdapterPosition() - 2);
@ -763,54 +763,48 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter<Recy
return;
}
int commentPosition = mIsSingleCommentThreadMode ? holder.getAdapterPosition() - 2 : holder.getAdapterPosition() - 1;
int previousVoteType = mVisibleComments.get(commentPosition).getVoteType();
int previousVoteType = comment.getVoteType();
String newVoteType;
((CommentViewHolder) holder).downVoteButton.clearColorFilter();
if (previousVoteType != CommentData.VOTE_TYPE_UPVOTE) {
//Not upvoted before
mVisibleComments.get(commentPosition).setVoteType(CommentData.VOTE_TYPE_UPVOTE);
comment.setVoteType(CommentData.VOTE_TYPE_UPVOTE);
newVoteType = RedditUtils.DIR_UPVOTE;
((CommentViewHolder) holder).upVoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.upvoted), android.graphics.PorterDuff.Mode.SRC_IN);
((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.upvoted));
} else {
//Upvoted before
mVisibleComments.get(commentPosition).setVoteType(CommentData.VOTE_TYPE_NO_VOTE);
comment.setVoteType(CommentData.VOTE_TYPE_NO_VOTE);
newVoteType = RedditUtils.DIR_UNVOTE;
((CommentViewHolder) holder).upVoteButton.clearColorFilter();
((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor));
}
((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(mVisibleComments.get(commentPosition).getScore() + mVisibleComments.get(commentPosition).getVoteType()));
((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(comment.getScore() + comment.getVoteType()));
VoteThing.voteThing(mOauthRetrofit, mAccessToken, new VoteThing.VoteThingListener() {
@Override
public void onVoteThingSuccess(int position) {
if (newVoteType.equals(RedditUtils.DIR_UPVOTE)) {
if (commentPosition < mVisibleComments.size()) {
mVisibleComments.get(commentPosition).setVoteType(CommentData.VOTE_TYPE_UPVOTE);
}
comment.setVoteType(CommentData.VOTE_TYPE_UPVOTE);
((CommentViewHolder) holder).upVoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.upvoted), android.graphics.PorterDuff.Mode.SRC_IN);
((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.upvoted));
} else {
if (commentPosition < mVisibleComments.size()) {
mVisibleComments.get(commentPosition).setVoteType(CommentData.VOTE_TYPE_NO_VOTE);
}
comment.setVoteType(CommentData.VOTE_TYPE_NO_VOTE);
((CommentViewHolder) holder).upVoteButton.clearColorFilter();
((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor));
}
((CommentViewHolder) holder).downVoteButton.clearColorFilter();
((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(mVisibleComments.get(commentPosition).getScore() + mVisibleComments.get(commentPosition).getVoteType()));
((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(comment.getScore() + comment.getVoteType()));
}
@Override
public void onVoteThingFail(int position) {
}
}, mVisibleComments.get(commentPosition).getFullName(), newVoteType, holder.getAdapterPosition());
}, comment.getFullName(), newVoteType, holder.getAdapterPosition());
});
((CommentViewHolder) holder).downVoteButton.setOnClickListener(view -> {
@ -824,50 +818,48 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter<Recy
return;
}
int commentPosition = mIsSingleCommentThreadMode ? holder.getAdapterPosition() - 2 : holder.getAdapterPosition() - 1;
int previousVoteType = mVisibleComments.get(commentPosition).getVoteType();
int previousVoteType = comment.getVoteType();
String newVoteType;
((CommentViewHolder) holder).upVoteButton.clearColorFilter();
if (previousVoteType != CommentData.VOTE_TYPE_DOWNVOTE) {
//Not downvoted before
mVisibleComments.get(commentPosition).setVoteType(CommentData.VOTE_TYPE_DOWNVOTE);
comment.setVoteType(CommentData.VOTE_TYPE_DOWNVOTE);
newVoteType = RedditUtils.DIR_DOWNVOTE;
((CommentViewHolder) holder).downVoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.downvoted), android.graphics.PorterDuff.Mode.SRC_IN);
((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.downvoted));
} else {
//Downvoted before
mVisibleComments.get(commentPosition).setVoteType(CommentData.VOTE_TYPE_NO_VOTE);
comment.setVoteType(CommentData.VOTE_TYPE_NO_VOTE);
newVoteType = RedditUtils.DIR_UNVOTE;
((CommentViewHolder) holder).downVoteButton.clearColorFilter();
((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor));
}
((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(mVisibleComments.get(commentPosition).getScore() + mVisibleComments.get(commentPosition).getVoteType()));
((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(comment.getScore() + comment.getVoteType()));
VoteThing.voteThing(mOauthRetrofit, mAccessToken, new VoteThing.VoteThingListener() {
@Override
public void onVoteThingSuccess(int position1) {
if (newVoteType.equals(RedditUtils.DIR_DOWNVOTE)) {
mVisibleComments.get(commentPosition).setVoteType(CommentData.VOTE_TYPE_DOWNVOTE);
comment.setVoteType(CommentData.VOTE_TYPE_DOWNVOTE);
((CommentViewHolder) holder).downVoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.downvoted), android.graphics.PorterDuff.Mode.SRC_IN);
((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.downvoted));
} else {
mVisibleComments.get(commentPosition).setVoteType(CommentData.VOTE_TYPE_NO_VOTE);
comment.setVoteType(CommentData.VOTE_TYPE_NO_VOTE);
((CommentViewHolder) holder).downVoteButton.clearColorFilter();
((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor));
}
((CommentViewHolder) holder).upVoteButton.clearColorFilter();
((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(mVisibleComments.get(commentPosition).getScore() + mVisibleComments.get(commentPosition).getVoteType()));
((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(comment.getScore() + comment.getVoteType()));
}
@Override
public void onVoteThingFail(int position1) {
}
}, mVisibleComments.get(commentPosition).getFullName(), newVoteType, holder.getAdapterPosition());
}, comment.getFullName(), newVoteType, holder.getAdapterPosition());
});
if (comment.isSaved()) {
@ -916,11 +908,7 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter<Recy
((CommentViewHolder) holder).authorTextView.setOnClickListener(view -> {
Intent intent = new Intent(mActivity, ViewUserDetailActivity.class);
if (mIsSingleCommentThreadMode) {
intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, mVisibleComments.get(holder.getAdapterPosition() - 2).getAuthor());
} else {
intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, mVisibleComments.get(holder.getAdapterPosition() - 1).getAuthor());
}
intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, comment.getAuthor());
mActivity.startActivity(intent);
});
@ -928,8 +916,7 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter<Recy
try {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
String extraText = mIsSingleCommentThreadMode ? mVisibleComments.get(holder.getAdapterPosition() - 2).getPermalink()
: mVisibleComments.get(holder.getAdapterPosition() - 1).getPermalink();
String extraText = comment.getPermalink();
intent.putExtra(Intent.EXTRA_TEXT, extraText);
mActivity.startActivity(Intent.createChooser(intent, mActivity.getString(R.string.share)));
} catch (ActivityNotFoundException e) {
@ -940,7 +927,7 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter<Recy
((CommentViewHolder) holder).expandButton.setOnClickListener(view -> {
if (((CommentViewHolder) holder).expandButton.getVisibility() == View.VISIBLE) {
int commentPosition = mIsSingleCommentThreadMode ? holder.getAdapterPosition() - 2 : holder.getAdapterPosition() - 1;
if(commentPosition < mVisibleComments.size()) {
if(commentPosition >= 0 && commentPosition < mVisibleComments.size()) {
if (mVisibleComments.get(commentPosition).isExpanded()) {
collapseChildren(commentPosition);
((CommentViewHolder) holder).expandButton.setImageResource(R.drawable.ic_expand_more_grey_24dp);
@ -1419,20 +1406,22 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter<Recy
}
public void deleteComment(int position) {
if (mVisibleComments.get(position).hasReply()) {
mVisibleComments.get(position).setAuthor("[deleted]");
mVisibleComments.get(position).setCommentContent("[deleted]");
if (mIsSingleCommentThreadMode) {
notifyItemChanged(position + 2);
if (mVisibleComments != null && position >= 0 && position < mVisibleComments.size()) {
if (mVisibleComments.get(position).hasReply()) {
mVisibleComments.get(position).setAuthor("[deleted]");
mVisibleComments.get(position).setCommentContent("[deleted]");
if (mIsSingleCommentThreadMode) {
notifyItemChanged(position + 2);
} else {
notifyItemChanged(position + 1);
}
} else {
notifyItemChanged(position + 1);
}
} else {
mVisibleComments.remove(position);
if (mIsSingleCommentThreadMode) {
notifyItemRemoved(position + 2);
} else {
notifyItemRemoved(position + 1);
mVisibleComments.remove(position);
if (mIsSingleCommentThreadMode) {
notifyItemRemoved(position + 2);
} else {
notifyItemRemoved(position + 1);
}
}
}
}
@ -1448,7 +1437,7 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter<Recy
public int getNextParentCommentPosition(int currentPosition) {
if (mVisibleComments != null && !mVisibleComments.isEmpty()) {
if (mIsSingleCommentThreadMode) {
for (int i = currentPosition + 1; i - 2 < mVisibleComments.size(); i++) {
for (int i = currentPosition + 1; i - 2 < mVisibleComments.size() && i - 2 >= 0; i++) {
if (mVisibleComments.get(i - 2).getDepth() == 0) {
return i;
}

View File

@ -1372,7 +1372,7 @@ public class PostRecyclerViewAdapter extends PagedListAdapter<Post, RecyclerView
boolean newExtraRow = hasExtraRow();
if (previousExtraRow != newExtraRow) {
if (previousExtraRow) {
notifyItemRemoved(super.getItemCount());
notifyItemRemoved(getItemCount() - 1);
} else {
notifyItemInserted(super.getItemCount());
}
@ -1381,6 +1381,14 @@ public class PostRecyclerViewAdapter extends PagedListAdapter<Post, RecyclerView
}
}
public void removeFooter() {
if (hasExtraRow()) {
notifyItemRemoved(getItemCount() - 1);
}
networkState = null;
}
@Override
public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) {
if (holder instanceof PostViewHolder) {
@ -1609,7 +1617,7 @@ public class PostRecyclerViewAdapter extends PagedListAdapter<Post, RecyclerView
ErrorViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
errorTextView.setText(R.string.load_posts_error);
errorTextView.setText(R.string.load_more_posts_error);
retryButton.setOnClickListener(view -> mCallback.retryLoadingMore());
}
}

View File

@ -476,9 +476,7 @@ public class PostFragment extends Fragment implements FragmentCommunicator {
mPostRecyclerView.setAdapter(mAdapter);
mPostViewModel = new ViewModelProvider(this, factory).get(PostViewModel.class);
mPostViewModel.getPosts().observe(this, posts -> {
mAdapter.submitList(posts);
});
mPostViewModel.getPosts().observe(this, posts -> mAdapter.submitList(posts));
mPostViewModel.hasPost().observe(this, hasPost -> {
this.hasPost = hasPost;
@ -542,14 +540,14 @@ public class PostFragment extends Fragment implements FragmentCommunicator {
@Override
public void refresh() {
mPostViewModel.refresh();
if (isInLazyMode) {
stopLazyMode();
}
mAdapter.setNetworkState(null);
mAdapter.removeFooter();
mFetchPostInfoLinearLayout.setVisibility(View.GONE);
hasPost = false;
mPostViewModel.refresh();
}
private void showErrorView(int stringResId) {

View File

@ -196,9 +196,9 @@ public class PostDataSource extends PageKeyedDataSource<String, Post> {
public void onParsePostSuccess(Post post) {
ArrayList<Post> singlePostList = new ArrayList<>();
singlePostList.add(post);
callback.onResult(singlePostList, null, null);
hasPostLiveData.postValue(true);
initialLoadStateLiveData.postValue(NetworkState.LOADED);
callback.onResult(singlePostList, null, null);
}
@Override
@ -219,16 +219,17 @@ public class PostDataSource extends PageKeyedDataSource<String, Post> {
}
if (newPosts.size() != 0) {
callback.onResult(newPosts, null, nextPageKey);
hasPostLiveData.postValue(true);
} else if (nextPageKey != null) {
loadBestPostsInitial(callback, nextPageKey);
return;
} else {
callback.onResult(newPosts, null, nextPageKey);
hasPostLiveData.postValue(false);
}
initialLoadStateLiveData.postValue(NetworkState.LOADED);
callback.onResult(newPosts, null, nextPageKey);
}
@Override
@ -275,8 +276,8 @@ public class PostDataSource extends PageKeyedDataSource<String, Post> {
if (newPosts.size() == 0 && lastItem != null && !lastItem.equals("") && !lastItem.equals("null")) {
loadBestPostsAfter(params, callback, lastItem);
} else {
paginationNetworkStateLiveData.postValue(NetworkState.LOADED);
callback.onResult(newPosts, lastItem);
paginationNetworkStateLiveData.postValue(NetworkState.LOADED);
}
}
@ -327,9 +328,9 @@ public class PostDataSource extends PageKeyedDataSource<String, Post> {
public void onParsePostSuccess(Post post) {
ArrayList<Post> singlePostList = new ArrayList<>();
singlePostList.add(post);
callback.onResult(singlePostList, null, null);
hasPostLiveData.postValue(true);
initialLoadStateLiveData.postValue(NetworkState.LOADED);
callback.onResult(singlePostList, null, null);
}
@Override
@ -350,16 +351,17 @@ public class PostDataSource extends PageKeyedDataSource<String, Post> {
}
if (newPosts.size() != 0) {
callback.onResult(newPosts, null, nextPageKey);
hasPostLiveData.postValue(true);
} else if (nextPageKey != null) {
loadSubredditPostsInitial(callback, nextPageKey);
return;
} else {
callback.onResult(newPosts, null, nextPageKey);
hasPostLiveData.postValue(false);
}
initialLoadStateLiveData.postValue(NetworkState.LOADED);
callback.onResult(newPosts, null, nextPageKey);
}
@Override
@ -417,8 +419,8 @@ public class PostDataSource extends PageKeyedDataSource<String, Post> {
if (newPosts.size() == 0 && lastItem != null && !lastItem.equals("") && !lastItem.equals("null")) {
loadSubredditPostsAfter(params, callback, lastItem);
} else {
paginationNetworkStateLiveData.postValue(NetworkState.LOADED);
callback.onResult(newPosts, lastItem);
paginationNetworkStateLiveData.postValue(NetworkState.LOADED);
}
}
@ -476,16 +478,17 @@ public class PostDataSource extends PageKeyedDataSource<String, Post> {
}
if (newPosts.size() != 0) {
callback.onResult(newPosts, null, nextPageKey);
hasPostLiveData.postValue(true);
} else if (nextPageKey != null) {
loadUserPostsInitial(callback, nextPageKey);
return;
} else {
callback.onResult(newPosts, null, nextPageKey);
hasPostLiveData.postValue(false);
}
initialLoadStateLiveData.postValue(NetworkState.LOADED);
callback.onResult(newPosts, null, nextPageKey);
}
@Override
@ -539,8 +542,8 @@ public class PostDataSource extends PageKeyedDataSource<String, Post> {
if (newPosts.size() == 0 && lastItem != null && !lastItem.equals("") && !lastItem.equals("null")) {
loadUserPostsAfter(params, callback, lastItem);
} else {
paginationNetworkStateLiveData.postValue(NetworkState.LOADED);
callback.onResult(newPosts, lastItem);
paginationNetworkStateLiveData.postValue(NetworkState.LOADED);
}
}
@ -620,16 +623,17 @@ public class PostDataSource extends PageKeyedDataSource<String, Post> {
}
if (newPosts.size() != 0) {
callback.onResult(newPosts, null, nextPageKey);
hasPostLiveData.postValue(true);
} else if (nextPageKey != null) {
loadSearchPostsInitial(callback, nextPageKey);
return;
} else {
callback.onResult(newPosts, null, nextPageKey);
hasPostLiveData.postValue(false);
}
initialLoadStateLiveData.postValue(NetworkState.LOADED);
callback.onResult(newPosts, null, nextPageKey);
}
@Override
@ -703,8 +707,8 @@ public class PostDataSource extends PageKeyedDataSource<String, Post> {
if (newPosts.size() == 0 && lastItem != null && !lastItem.equals("") && !lastItem.equals("null")) {
loadSearchPostsAfter(params, callback, lastItem);
} else {
paginationNetworkStateLiveData.postValue(NetworkState.LOADED);
callback.onResult(newPosts, lastItem);
paginationNetworkStateLiveData.postValue(NetworkState.LOADED);
}
}

View File

@ -22,6 +22,8 @@
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:backgroundTint="@color/backgroundColorPrimary"
android:textColor="@android:color/white"
android:text="@string/retry"
android:textSize="?attr/font_default" />

View File

@ -51,6 +51,7 @@
<string name="tap_to_retry">Error loading image. Tap to retry.</string>
<string name="load_posts_error">Error loading posts.\nTap to retry.</string>
<string name="load_more_posts_error">Error loading posts.</string>
<string name="load_post_error">Error loading this post.\nTap to retry.</string>
<string name="search_subreddits_error">Error searching subreddits.\nTap to retry.</string>
<string name="search_users_error">Error searching users.\nTap to retry.</string>