ReImplemented loading more comments. Load more comments of comments by clicking the load more item (Still has a little issue). Minor bugs fixed.

This commit is contained in:
Alex Ning 2019-06-22 11:58:20 +08:00
parent 89e934f5a7
commit 724d3181e2
14 changed files with 606 additions and 353 deletions

View File

@ -22,7 +22,12 @@ class CommentData implements Parcelable {
private boolean scoreHidden; private boolean scoreHidden;
private boolean isExpanded; private boolean isExpanded;
private ArrayList<CommentData> children; private ArrayList<CommentData> children;
private ArrayList<String> moreChildrenIds; private ArrayList<String> moreChildrenFullnames;
private int moreChildrenStartingIndex;
private boolean isPlaceHolder;
private boolean isLoadingMoreChildren;
private boolean loadMoreChildrenFailed;
CommentData(String id, String fullName, String author, String commentTime, String commentContent, CommentData(String id, String fullName, String author, String commentTime, String commentContent,
String parentId, int score, boolean isSubmitter, String permalink, int depth, String parentId, int score, boolean isSubmitter, String permalink, int depth,
@ -41,6 +46,15 @@ class CommentData implements Parcelable {
this.hasReply = hasReply; this.hasReply = hasReply;
this.scoreHidden = scoreHidden; this.scoreHidden = scoreHidden;
this.isExpanded = false; this.isExpanded = false;
moreChildrenStartingIndex = 0;
isPlaceHolder = false;
}
CommentData(int depth) {
this.depth = depth;
isPlaceHolder = true;
isLoadingMoreChildren = false;
loadMoreChildrenFailed = false;
} }
protected CommentData(Parcel in) { protected CommentData(Parcel in) {
@ -60,7 +74,11 @@ class CommentData implements Parcelable {
scoreHidden = in.readByte() != 0; scoreHidden = in.readByte() != 0;
isExpanded = in.readByte() != 0; isExpanded = in.readByte() != 0;
children = in.readArrayList(null); children = in.readArrayList(null);
moreChildrenIds = in.readArrayList(null); moreChildrenFullnames = in.readArrayList(null);
moreChildrenStartingIndex = in.readInt();
isPlaceHolder = in.readByte() != 0;
isLoadingMoreChildren = in.readByte() != 0;
loadMoreChildrenFailed = in.readByte() != 0;
} }
public static final Creator<CommentData> CREATOR = new Creator<CommentData>() { public static final Creator<CommentData> CREATOR = new Creator<CommentData>() {
@ -164,26 +182,70 @@ class CommentData implements Parcelable {
} }
public void addChildren(ArrayList<CommentData> moreChildren) { public void addChildren(ArrayList<CommentData> moreChildren) {
if(children == null) { if(children == null || children.size() == 0) {
setChildren(moreChildren); setChildren(moreChildren);
} else { } else {
children.addAll(moreChildren); if(children.get(children.size() - 1).isPlaceHolder) {
children.addAll(children.size() - 2, moreChildren);
} else {
children.addAll(moreChildren);
}
} }
} }
public void addChild(CommentData comment) { public void addChild(CommentData comment) {
addChild(comment, 0);
}
public void addChild(CommentData comment, int position) {
if(children == null) { if(children == null) {
children = new ArrayList<>(); children = new ArrayList<>();
} }
children.add(0, comment); children.add(position, comment);
} }
public ArrayList<String> getMoreChildrenIds() { public ArrayList<String> getMoreChildrenFullnames() {
return moreChildrenIds; return moreChildrenFullnames;
} }
public void setMoreChildrenIds(ArrayList<String> moreChildrenIds) { public void setMoreChildrenFullnames(ArrayList<String> moreChildrenFullnames) {
this.moreChildrenIds = moreChildrenIds; this.moreChildrenFullnames = moreChildrenFullnames;
}
public boolean hasMoreChildrenFullnames() {
return moreChildrenFullnames != null;
}
public void removeMoreChildrenFullnames() {
moreChildrenFullnames.clear();
}
public int getMoreChildrenStartingIndex() {
return moreChildrenStartingIndex;
}
public void setMoreChildrenStartingIndex(int moreChildrenStartingIndex) {
this.moreChildrenStartingIndex = moreChildrenStartingIndex;
}
public boolean isPlaceHolder() {
return isPlaceHolder;
}
public boolean isLoadingMoreChildren() {
return isLoadingMoreChildren;
}
public void setLoadingMoreChildren(boolean isLoadingMoreChildren) {
this.isLoadingMoreChildren = isLoadingMoreChildren;
}
public boolean isLoadMoreChildrenFailed() {
return loadMoreChildrenFailed;
}
public void setLoadMoreChildrenFailed(boolean loadMoreChildrenFailed) {
this.loadMoreChildrenFailed = loadMoreChildrenFailed;
} }
@Override @Override
@ -209,6 +271,10 @@ class CommentData implements Parcelable {
parcel.writeByte((byte) (scoreHidden ? 1 : 0)); parcel.writeByte((byte) (scoreHidden ? 1 : 0));
parcel.writeByte((byte) (isExpanded ? 1 : 0)); parcel.writeByte((byte) (isExpanded ? 1 : 0));
parcel.writeList(children); parcel.writeList(children);
parcel.writeList(moreChildrenIds); parcel.writeList(moreChildrenFullnames);
parcel.writeInt(moreChildrenStartingIndex);
parcel.writeByte((byte) (isPlaceHolder ? 1 : 0));
parcel.writeByte((byte) (isLoadingMoreChildren ? 1 : 0));
parcel.writeByte((byte) (loadMoreChildrenFailed ? 1 : 0));
} }
} }

View File

@ -1,11 +1,11 @@
package ml.docilealligator.infinityforreddit; package ml.docilealligator.infinityforreddit;
import java.util.Locale;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import androidx.paging.PageKeyedDataSource; import androidx.paging.PageKeyedDataSource;
import retrofit2.Call;
import java.util.Locale;
import retrofit2.Retrofit; import retrofit2.Retrofit;
public class CommentDataSource extends PageKeyedDataSource<String, Post> { public class CommentDataSource extends PageKeyedDataSource<String, Post> {
@ -62,7 +62,7 @@ public class CommentDataSource extends PageKeyedDataSource<String, Post> {
RedditAPI api = retrofit.create(RedditAPI.class); RedditAPI api = retrofit.create(RedditAPI.class);
Call<String> comments = api.getComments(subredditNamePrefixed, article, comment); //Call<String> comments = api.getComments(subredditNamePrefixed, article, comment);
/*comments.enqueue(new Callback<String>() { /*comments.enqueue(new Callback<String>() {
@Override @Override
public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) { public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) {
@ -119,7 +119,7 @@ public class CommentDataSource extends PageKeyedDataSource<String, Post> {
RedditAPI api = retrofit.create(RedditAPI.class); RedditAPI api = retrofit.create(RedditAPI.class);
Call<String> moreChildrenBasicInfo = api.getMoreChildren(mParentId, params.key); //Call<String> moreChildrenBasicInfo = api.getMoreChildren(mParentId, params.key);
/*moreChildrenBasicInfo.enqueue(new Callback<String>() { /*moreChildrenBasicInfo.enqueue(new Callback<String>() {
@Override @Override
public void onResponse(Call<String> call, Response<String> response) { public void onResponse(Call<String> call, Response<String> response) {

View File

@ -29,6 +29,11 @@ import ru.noties.markwon.SpannableConfiguration;
import ru.noties.markwon.view.MarkwonView; import ru.noties.markwon.view.MarkwonView;
class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int VIEW_TYPE_COMMENT = 0;
private static final int VIEW_TYPE_LOAD_MORE_COMMENT = 1;
private static final int VIEW_TYPE_IS_LOADING_MORE_COMMENT = 2;
private static final int VIEW_TYPE_LOAD_MORE_COMMENT_FAILED = 3;
private Activity mActivity; private Activity mActivity;
private Retrofit mRetrofit; private Retrofit mRetrofit;
private Retrofit mOauthRetrofit; private Retrofit mOauthRetrofit;
@ -56,7 +61,6 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
mLocale = locale; mLocale = locale;
mVisibleComments = new ArrayList<>(); mVisibleComments = new ArrayList<>();
new Handler().post(() -> { new Handler().post(() -> {
makeChildrenVisible(commentData, mVisibleComments); makeChildrenVisible(commentData, mVisibleComments);
notifyDataSetChanged(); notifyDataSetChanged();
@ -70,239 +74,387 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
c.setExpanded(true); c.setExpanded(true);
makeChildrenVisible(c.getChildren(), visibleComments); makeChildrenVisible(c.getChildren(), visibleComments);
} }
if(c.hasMoreChildrenFullnames() && c.getMoreChildrenFullnames().size() > c.getMoreChildrenStartingIndex()) {
//Add a load more placeholder
visibleComments.add(new CommentData(c.getDepth() + 1));
c.addChild(new CommentData(c.getDepth() + 1), c.getChildren().size());
}
}
}
@Override
public int getItemViewType(int position) {
CommentData comment = mVisibleComments.get(position);
if(!comment.isPlaceHolder()) {
return VIEW_TYPE_COMMENT;
} else {
if(comment.isLoadMoreChildrenFailed()) {
return VIEW_TYPE_LOAD_MORE_COMMENT_FAILED;
} else if(comment.isLoadingMoreChildren()) {
return VIEW_TYPE_IS_LOADING_MORE_COMMENT;
} else {
return VIEW_TYPE_LOAD_MORE_COMMENT;
}
} }
} }
@NonNull @NonNull
@Override @Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new CommentViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_comment, parent, false)); switch (viewType) {
case VIEW_TYPE_COMMENT:
return new CommentViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_comment, parent, false));
case VIEW_TYPE_LOAD_MORE_COMMENT:
return new LoadMoreCommentViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_load_more_comments, parent, false));
case VIEW_TYPE_IS_LOADING_MORE_COMMENT:
return new IsLoadingMoreCommentViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_is_loading_more_comments, parent, false));
default:
return new LoadMoreCommentFailedViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_load_more_comments_failed, parent, false));
}
} }
@Override @Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
CommentData commentItem = mVisibleComments.get(holder.getAdapterPosition()); if(holder.getItemViewType() == VIEW_TYPE_COMMENT) {
CommentData commentItem = mVisibleComments.get(holder.getAdapterPosition());
String authorPrefixed = "u/" + commentItem.getAuthor(); String authorPrefixed = "u/" + commentItem.getAuthor();
((CommentViewHolder) holder).authorTextView.setText(authorPrefixed); ((CommentViewHolder) holder).authorTextView.setText(authorPrefixed);
((CommentViewHolder) holder).authorTextView.setOnClickListener(view -> { ((CommentViewHolder) holder).authorTextView.setOnClickListener(view -> {
Intent intent = new Intent(mActivity, ViewUserDetailActivity.class);
intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, commentItem.getAuthor());
mActivity.startActivity(intent);
});
((CommentViewHolder) holder).commentTimeTextView.setText(commentItem.getCommentTime());
SpannableConfiguration spannableConfiguration = SpannableConfiguration.builder(mActivity).linkResolver((view, link) -> {
if (link.startsWith("/u/") || link.startsWith("u/")) {
Intent intent = new Intent(mActivity, ViewUserDetailActivity.class); Intent intent = new Intent(mActivity, ViewUserDetailActivity.class);
intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, link.substring(3)); intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, commentItem.getAuthor());
mActivity.startActivity(intent); mActivity.startActivity(intent);
} else if (link.startsWith("/r/") || link.startsWith("r/")) { });
Intent intent = new Intent(mActivity, ViewSubredditDetailActivity.class);
intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY, link.substring(3));
mActivity.startActivity(intent);
} else {
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
// add share action to menu list
builder.addDefaultShareMenuItem();
builder.setToolbarColor(mActivity.getResources().getColor(R.color.colorPrimary));
CustomTabsIntent customTabsIntent = builder.build();
customTabsIntent.launchUrl(mActivity, Uri.parse(link));
}
}).build();
((CommentViewHolder) holder).commentMarkdownView.setMarkdown(spannableConfiguration, commentItem.getCommentContent()); ((CommentViewHolder) holder).commentTimeTextView.setText(commentItem.getCommentTime());
((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(commentItem.getScore()));
((CommentViewHolder) holder).verticalBlock.getLayoutParams().width = commentItem.getDepth() * 16; SpannableConfiguration spannableConfiguration = SpannableConfiguration.builder(mActivity).linkResolver((view, link) -> {
if (link.startsWith("/u/") || link.startsWith("u/")) {
((CommentViewHolder) holder).shareButton.setOnClickListener(view -> { Intent intent = new Intent(mActivity, ViewUserDetailActivity.class);
Intent intent = new Intent(Intent.ACTION_SEND); intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, link.substring(3));
intent.setType("text/plain"); mActivity.startActivity(intent);
String extraText = commentItem.getPermalink(); } else if (link.startsWith("/r/") || link.startsWith("r/")) {
intent.putExtra(Intent.EXTRA_TEXT, extraText); Intent intent = new Intent(mActivity, ViewSubredditDetailActivity.class);
mActivity.startActivity(Intent.createChooser(intent, "Share")); intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY, link.substring(3));
}); mActivity.startActivity(intent);
} else {
if (commentItem.hasReply()) { CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
if(commentItem.isExpanded()) { // add share action to menu list
((CommentViewHolder) holder).expandButton.setImageResource(R.drawable.ic_expand_less_black_20dp); builder.addDefaultShareMenuItem();
} else { builder.setToolbarColor(mActivity.getResources().getColor(R.color.colorPrimary));
((CommentViewHolder) holder).expandButton.setImageResource(R.drawable.ic_expand_more_black_20dp); CustomTabsIntent customTabsIntent = builder.build();
} customTabsIntent.launchUrl(mActivity, Uri.parse(link));
((CommentViewHolder) holder).expandButton.setVisibility(View.VISIBLE);
}
((CommentViewHolder) holder).expandButton.setOnClickListener(view -> {
if(commentItem.isExpanded()) {
collapseChildren(holder.getAdapterPosition());
((CommentViewHolder) holder).expandButton
.setImageResource(R.drawable.ic_expand_more_black_20dp);
} else {
expandChildren(holder.getAdapterPosition());
commentItem.setExpanded(true);
((CommentViewHolder) holder).expandButton
.setImageResource(R.drawable.ic_expand_less_black_20dp);
}
/*if (commentItem.hasReply() && commentItem.getChildren().size() > 0) {
collapseChildren(holder.getAdapterPosition());
((CommentViewHolder) holder).expandButton
.setImageResource(R.drawable.ic_expand_more_black_20dp);
} else {
((CommentViewHolder) holder).loadMoreCommentsProgressBar.setVisibility(View.VISIBLE);
FetchComment.fetchAllComment(mRetrofit, mSubredditNamePrefixed, article, commentItem.getId(),
locale, false, commentItem.getDepth(), new FetchComment.FetchAllCommentListener() {
@Override
public void onFetchAllCommentSuccess(List<?> commentData) {
commentItem.addChildren((ArrayList<CommentData>) commentData);
((CommentViewHolder) holder).loadMoreCommentsProgressBar
.setVisibility(View.GONE);
expandChildren(holder.getAdapterPosition());
((CommentViewHolder) holder).expandButton
.setImageResource(R.drawable.ic_expand_less_black_20dp);
}
@Override
public void onFetchAllCommentFailed() {
((CommentViewHolder) holder).loadMoreCommentsProgressBar
.setVisibility(View.GONE);
}
});
}*/
});
((CommentViewHolder) holder).replyButton.setOnClickListener(view -> {
Intent intent = new Intent(mActivity, CommentActivity.class);
intent.putExtra(CommentActivity.EXTRA_PARENT_DEPTH_KEY, commentItem.getDepth() + 1);
intent.putExtra(CommentActivity.EXTRA_COMMENT_PARENT_TEXT_KEY, commentItem.getCommentContent());
intent.putExtra(CommentActivity.EXTRA_PARENT_FULLNAME_KEY, commentItem.getFullName());
intent.putExtra(CommentActivity.EXTRA_IS_REPLYING_KEY, true);
intent.putExtra(CommentActivity.EXTRA_PARENT_POSITION_KEY, holder.getAdapterPosition());
mActivity.startActivityForResult(intent, CommentActivity.WRITE_COMMENT_REQUEST_CODE);
});
switch (commentItem.getVoteType()) {
case 1:
((CommentViewHolder) holder).upvoteButton
.setColorFilter(ContextCompat.getColor(mActivity, R.color.colorPrimary), android.graphics.PorterDuff.Mode.SRC_IN);
break;
case 2:
((CommentViewHolder) holder).downvoteButton
.setColorFilter(ContextCompat.getColor(mActivity, R.color.minusButtonColor), android.graphics.PorterDuff.Mode.SRC_IN);
break;
}
((CommentViewHolder) holder).upvoteButton.setOnClickListener(view -> {
ColorFilter previousUpvoteButtonColorFilter = ((CommentViewHolder) holder).upvoteButton.getColorFilter();
ColorFilter previousDownvoteButtonColorFilter = ((CommentViewHolder) holder).downvoteButton.getColorFilter();
int previousVoteType = commentItem.getVoteType();
String newVoteType;
((CommentViewHolder) holder).downvoteButton.clearColorFilter();
if(previousUpvoteButtonColorFilter == null) {
//Not upvoted before
commentItem.setVoteType(1);
newVoteType = RedditUtils.DIR_UPVOTE;
((CommentViewHolder) holder).upvoteButton
.setColorFilter(ContextCompat.getColor(mActivity, R.color.backgroundColorPrimaryDark), android.graphics.PorterDuff.Mode.SRC_IN);
} else {
//Upvoted before
commentItem.setVoteType(0);
newVoteType = RedditUtils.DIR_UNVOTE;
((CommentViewHolder) holder).upvoteButton.clearColorFilter();
}
((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(commentItem.getScore() + commentItem.getVoteType()));
VoteThing.voteThing(mOauthRetrofit, mSharedPreferences, new VoteThing.VoteThingListener() {
@Override
public void onVoteThingSuccess(int position1) {
if(newVoteType.equals(RedditUtils.DIR_UPVOTE)) {
commentItem.setVoteType(1);
((CommentViewHolder) holder).upvoteButton
.setColorFilter(ContextCompat.getColor(mActivity, R.color.backgroundColorPrimaryDark), android.graphics.PorterDuff.Mode.SRC_IN);
} else {
commentItem.setVoteType(0);
((CommentViewHolder) holder).upvoteButton.clearColorFilter();
}
((CommentViewHolder) holder).downvoteButton.clearColorFilter();
((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(commentItem.getScore() + commentItem.getVoteType()));
} }
}).build();
@Override ((CommentViewHolder) holder).commentMarkdownView.setMarkdown(spannableConfiguration, commentItem.getCommentContent());
public void onVoteThingFail(int position1) { ((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(commentItem.getScore()));
Toast.makeText(mActivity, R.string.vote_failed, Toast.LENGTH_SHORT).show();
commentItem.setVoteType(previousVoteType); ((CommentViewHolder) holder).verticalBlock.getLayoutParams().width = commentItem.getDepth() * 16;
((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(commentItem.getScore() + previousVoteType));
((CommentViewHolder) holder).upvoteButton.setColorFilter(previousUpvoteButtonColorFilter); ((CommentViewHolder) holder).shareButton.setOnClickListener(view -> {
((CommentViewHolder) holder).downvoteButton.setColorFilter(previousDownvoteButtonColorFilter); Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
String extraText = commentItem.getPermalink();
intent.putExtra(Intent.EXTRA_TEXT, extraText);
mActivity.startActivity(Intent.createChooser(intent, "Share"));
});
if (commentItem.hasReply()) {
if(commentItem.isExpanded()) {
((CommentViewHolder) holder).expandButton.setImageResource(R.drawable.ic_expand_less_black_20dp);
} else {
((CommentViewHolder) holder).expandButton.setImageResource(R.drawable.ic_expand_more_black_20dp);
} }
}, commentItem.getFullName(), newVoteType, holder.getAdapterPosition()); ((CommentViewHolder) holder).expandButton.setVisibility(View.VISIBLE);
}); }
((CommentViewHolder) holder).downvoteButton.setOnClickListener(view -> { ((CommentViewHolder) holder).expandButton.setOnClickListener(view -> {
ColorFilter previousUpvoteButtonColorFilter = ((CommentViewHolder) holder).upvoteButton.getColorFilter(); if(commentItem.isExpanded()) {
ColorFilter previousDownvoteButtonColorFilter = ((CommentViewHolder) holder).downvoteButton.getColorFilter(); collapseChildren(holder.getAdapterPosition());
int previousVoteType = commentItem.getVoteType(); ((CommentViewHolder) holder).expandButton
String newVoteType; .setImageResource(R.drawable.ic_expand_more_black_20dp);
} else {
expandChildren(holder.getAdapterPosition());
commentItem.setExpanded(true);
((CommentViewHolder) holder).expandButton
.setImageResource(R.drawable.ic_expand_less_black_20dp);
}
});
((CommentViewHolder) holder).upvoteButton.clearColorFilter(); ((CommentViewHolder) holder).replyButton.setOnClickListener(view -> {
Intent intent = new Intent(mActivity, CommentActivity.class);
intent.putExtra(CommentActivity.EXTRA_PARENT_DEPTH_KEY, commentItem.getDepth() + 1);
intent.putExtra(CommentActivity.EXTRA_COMMENT_PARENT_TEXT_KEY, commentItem.getCommentContent());
intent.putExtra(CommentActivity.EXTRA_PARENT_FULLNAME_KEY, commentItem.getFullName());
intent.putExtra(CommentActivity.EXTRA_IS_REPLYING_KEY, true);
intent.putExtra(CommentActivity.EXTRA_PARENT_POSITION_KEY, holder.getAdapterPosition());
mActivity.startActivityForResult(intent, CommentActivity.WRITE_COMMENT_REQUEST_CODE);
});
switch (commentItem.getVoteType()) {
case 1:
((CommentViewHolder) holder).upvoteButton
.setColorFilter(ContextCompat.getColor(mActivity, R.color.colorPrimary), android.graphics.PorterDuff.Mode.SRC_IN);
break;
case 2:
((CommentViewHolder) holder).downvoteButton
.setColorFilter(ContextCompat.getColor(mActivity, R.color.minusButtonColor), android.graphics.PorterDuff.Mode.SRC_IN);
break;
}
((CommentViewHolder) holder).upvoteButton.setOnClickListener(view -> {
ColorFilter previousUpvoteButtonColorFilter = ((CommentViewHolder) holder).upvoteButton.getColorFilter();
ColorFilter previousDownvoteButtonColorFilter = ((CommentViewHolder) holder).downvoteButton.getColorFilter();
int previousVoteType = commentItem.getVoteType();
String newVoteType;
if(previousDownvoteButtonColorFilter == null) {
//Not downvoted before
commentItem.setVoteType(-1);
newVoteType = RedditUtils.DIR_DOWNVOTE;
((CommentViewHolder) holder).downvoteButton
.setColorFilter(ContextCompat.getColor(mActivity, R.color.colorAccent), android.graphics.PorterDuff.Mode.SRC_IN);
} else {
//Downvoted before
commentItem.setVoteType(0);
newVoteType = RedditUtils.DIR_UNVOTE;
((CommentViewHolder) holder).downvoteButton.clearColorFilter(); ((CommentViewHolder) holder).downvoteButton.clearColorFilter();
}
((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(commentItem.getScore() + commentItem.getVoteType())); if(previousUpvoteButtonColorFilter == null) {
//Not upvoted before
commentItem.setVoteType(1);
newVoteType = RedditUtils.DIR_UPVOTE;
((CommentViewHolder) holder).upvoteButton
.setColorFilter(ContextCompat.getColor(mActivity, R.color.backgroundColorPrimaryDark), android.graphics.PorterDuff.Mode.SRC_IN);
} else {
//Upvoted before
commentItem.setVoteType(0);
newVoteType = RedditUtils.DIR_UNVOTE;
((CommentViewHolder) holder).upvoteButton.clearColorFilter();
}
((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(commentItem.getScore() + commentItem.getVoteType()));
VoteThing.voteThing(mOauthRetrofit, mSharedPreferences, new VoteThing.VoteThingListener() {
@Override
public void onVoteThingSuccess(int position1) {
if(newVoteType.equals(RedditUtils.DIR_UPVOTE)) {
commentItem.setVoteType(1);
((CommentViewHolder) holder).upvoteButton
.setColorFilter(ContextCompat.getColor(mActivity, R.color.backgroundColorPrimaryDark), android.graphics.PorterDuff.Mode.SRC_IN);
} else {
commentItem.setVoteType(0);
((CommentViewHolder) holder).upvoteButton.clearColorFilter();
}
VoteThing.voteThing(mOauthRetrofit, mSharedPreferences, new VoteThing.VoteThingListener() {
@Override
public void onVoteThingSuccess(int position1) {
if(newVoteType.equals(RedditUtils.DIR_DOWNVOTE)) {
commentItem.setVoteType(-1);
((CommentViewHolder) holder).downvoteButton
.setColorFilter(ContextCompat.getColor(mActivity, R.color.colorAccent), android.graphics.PorterDuff.Mode.SRC_IN);
} else {
commentItem.setVoteType(0);
((CommentViewHolder) holder).downvoteButton.clearColorFilter(); ((CommentViewHolder) holder).downvoteButton.clearColorFilter();
((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(commentItem.getScore() + commentItem.getVoteType()));
} }
((CommentViewHolder) holder).upvoteButton.clearColorFilter(); @Override
((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(commentItem.getScore() + commentItem.getVoteType())); public void onVoteThingFail(int position1) {
Toast.makeText(mActivity, R.string.vote_failed, Toast.LENGTH_SHORT).show();
commentItem.setVoteType(previousVoteType);
((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(commentItem.getScore() + previousVoteType));
((CommentViewHolder) holder).upvoteButton.setColorFilter(previousUpvoteButtonColorFilter);
((CommentViewHolder) holder).downvoteButton.setColorFilter(previousDownvoteButtonColorFilter);
}
}, commentItem.getFullName(), newVoteType, holder.getAdapterPosition());
});
((CommentViewHolder) holder).downvoteButton.setOnClickListener(view -> {
ColorFilter previousUpvoteButtonColorFilter = ((CommentViewHolder) holder).upvoteButton.getColorFilter();
ColorFilter previousDownvoteButtonColorFilter = ((CommentViewHolder) holder).downvoteButton.getColorFilter();
int previousVoteType = commentItem.getVoteType();
String newVoteType;
((CommentViewHolder) holder).upvoteButton.clearColorFilter();
if(previousDownvoteButtonColorFilter == null) {
//Not downvoted before
commentItem.setVoteType(-1);
newVoteType = RedditUtils.DIR_DOWNVOTE;
((CommentViewHolder) holder).downvoteButton
.setColorFilter(ContextCompat.getColor(mActivity, R.color.colorAccent), android.graphics.PorterDuff.Mode.SRC_IN);
} else {
//Downvoted before
commentItem.setVoteType(0);
newVoteType = RedditUtils.DIR_UNVOTE;
((CommentViewHolder) holder).downvoteButton.clearColorFilter();
} }
@Override ((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(commentItem.getScore() + commentItem.getVoteType()));
public void onVoteThingFail(int position1) {
Toast.makeText(mActivity, R.string.vote_failed, Toast.LENGTH_SHORT).show(); VoteThing.voteThing(mOauthRetrofit, mSharedPreferences, new VoteThing.VoteThingListener() {
commentItem.setVoteType(previousVoteType); @Override
((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(commentItem.getScore() + previousVoteType)); public void onVoteThingSuccess(int position1) {
((CommentViewHolder) holder).upvoteButton.setColorFilter(previousUpvoteButtonColorFilter); if(newVoteType.equals(RedditUtils.DIR_DOWNVOTE)) {
((CommentViewHolder) holder).downvoteButton.setColorFilter(previousDownvoteButtonColorFilter); commentItem.setVoteType(-1);
} ((CommentViewHolder) holder).downvoteButton
}, commentItem.getFullName(), newVoteType, holder.getAdapterPosition()); .setColorFilter(ContextCompat.getColor(mActivity, R.color.colorAccent), android.graphics.PorterDuff.Mode.SRC_IN);
}); } else {
commentItem.setVoteType(0);
((CommentViewHolder) holder).downvoteButton.clearColorFilter();
}
((CommentViewHolder) holder).upvoteButton.clearColorFilter();
((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(commentItem.getScore() + commentItem.getVoteType()));
}
@Override
public void onVoteThingFail(int position1) {
Toast.makeText(mActivity, R.string.vote_failed, Toast.LENGTH_SHORT).show();
commentItem.setVoteType(previousVoteType);
((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(commentItem.getScore() + previousVoteType));
((CommentViewHolder) holder).upvoteButton.setColorFilter(previousUpvoteButtonColorFilter);
((CommentViewHolder) holder).downvoteButton.setColorFilter(previousDownvoteButtonColorFilter);
}
}, commentItem.getFullName(), newVoteType, holder.getAdapterPosition());
});
} else if(holder.getItemViewType() == VIEW_TYPE_LOAD_MORE_COMMENT) {
((LoadMoreCommentViewHolder) holder).verticalBlock.getLayoutParams().width = mVisibleComments.get(holder.getAdapterPosition()).getDepth() * 16;
((LoadMoreCommentViewHolder) holder).textView.setOnClickListener(view -> {
loadMoreComments(holder.getAdapterPosition());
});
} else if(holder.getItemViewType() == VIEW_TYPE_IS_LOADING_MORE_COMMENT){
((IsLoadingMoreCommentViewHolder) holder).verticalBlock.getLayoutParams().width = mVisibleComments.get(holder.getAdapterPosition()).getDepth() * 16;
} else if(holder.getItemViewType() == VIEW_TYPE_LOAD_MORE_COMMENT_FAILED) {
((LoadMoreCommentFailedViewHolder) holder).verticalBlock.getLayoutParams().width = mVisibleComments.get(holder.getAdapterPosition()).getDepth() * 16;
((LoadMoreCommentFailedViewHolder) holder).retryTextView.setOnClickListener(view -> {
loadMoreComments(holder.getAdapterPosition());
});
}
}
private void loadMoreComments(int position) {
int parentPosition = getParentPosition(position);
CommentData parentComment = mVisibleComments.get(parentPosition);
mVisibleComments.get(position).setLoadingMoreChildren(true);
mVisibleComments.get(position).setLoadMoreChildrenFailed(false);
notifyItemChanged(position);
FetchComment.fetchMoreComment(mRetrofit, mSubredditNamePrefixed, parentComment.getMoreChildrenFullnames(),
parentComment.getMoreChildrenStartingIndex(), parentComment.getDepth() + 1, mLocale,
new FetchComment.FetchMoreCommentListener() {
@Override
public void onFetchMoreCommentSuccess(ArrayList<CommentData> commentsData, int childrenStartingIndex) {
if(mVisibleComments.size() > parentPosition
&& parentComment.getFullName().equals(mVisibleComments.get(parentPosition).getFullName())) {
if(mVisibleComments.get(parentPosition).isExpanded()) {
if(mVisibleComments.get(parentPosition).getChildren().size() > childrenStartingIndex) {
mVisibleComments.get(position).setLoadingMoreChildren(false);
mVisibleComments.get(position).setLoadMoreChildrenFailed(false);
notifyItemChanged(position);
mVisibleComments.get(parentPosition).setMoreChildrenStartingIndex(childrenStartingIndex);
mVisibleComments.get(parentPosition).getChildren().get(mVisibleComments.get(parentPosition).getChildren().size() - 1)
.setLoadingMoreChildren(false);
mVisibleComments.get(parentPosition).getChildren().get(mVisibleComments.get(parentPosition).getChildren().size() - 1)
.setLoadMoreChildrenFailed(false);
mVisibleComments.addAll(parentPosition
+ mVisibleComments.get(parentPosition).getChildren().size(),
commentsData);
notifyItemRangeInserted(parentPosition + mVisibleComments.get(parentPosition).getChildren().size(),
commentsData.size());
} else {
mVisibleComments.get(parentPosition).getChildren()
.remove(mVisibleComments.get(parentPosition).getChildren().size() - 1);
mVisibleComments.remove(position);
notifyItemRemoved(position);
mVisibleComments.get(parentPosition).removeMoreChildrenFullnames();
mVisibleComments.addAll(parentPosition
+ mVisibleComments.get(parentPosition).getChildren().size() + 1,
commentsData);
notifyItemRangeInserted(parentPosition + mVisibleComments.get(parentPosition).getChildren().size() + 1,
commentsData.size());
}
}
mVisibleComments.get(parentPosition).addChildren(commentsData);
} else {
for(int i = 0; i < mVisibleComments.size(); i++) {
if(mVisibleComments.get(i).getFullName().equals(parentComment.getFullName())) {
mVisibleComments.get(i).setMoreChildrenStartingIndex(childrenStartingIndex);
if(mVisibleComments.get(i).isExpanded()) {
mVisibleComments.get(i + mVisibleComments.get(i).getChildren().size()).setLoadingMoreChildren(false);
mVisibleComments.get(i + mVisibleComments.get(i).getChildren().size()).setLoadMoreChildrenFailed(false);
notifyItemChanged(i + mVisibleComments.get(i).getChildren().size());
mVisibleComments.addAll(i + mVisibleComments.get(i).getChildren().size(),
commentsData);
notifyItemRangeInserted(i + mVisibleComments.get(i).getChildren().size(),
commentsData.size());
}
mVisibleComments.get(i).getChildren().get(mVisibleComments.get(i).getChildren().size() - 1)
.setLoadingMoreChildren(false);
mVisibleComments.get(i).getChildren().get(mVisibleComments.get(i).getChildren().size() - 1)
.setLoadMoreChildrenFailed(false);
mVisibleComments.get(i).addChildren(commentsData);
break;
}
}
}
}
@Override
public void onFetchMoreCommentFailed() {
if(parentPosition < mVisibleComments.size()
&& parentComment.getFullName().equals(mVisibleComments.get(parentPosition).getFullName())) {
if(mVisibleComments.get(parentPosition).isExpanded()) {
mVisibleComments.get(position).setLoadingMoreChildren(false);
mVisibleComments.get(position).setLoadMoreChildrenFailed(true);
notifyItemChanged(position);
}
mVisibleComments.get(parentPosition).getChildren().get(mVisibleComments.get(parentPosition).getChildren().size() - 1)
.setLoadingMoreChildren(false);
mVisibleComments.get(parentPosition).getChildren().get(mVisibleComments.get(parentPosition).getChildren().size() - 1)
.setLoadMoreChildrenFailed(true);
} else {
for(int i = 0; i < mVisibleComments.size(); i++) {
if(mVisibleComments.get(i).getFullName().equals(parentComment.getFullName())) {
if(mVisibleComments.get(i).isExpanded()) {
mVisibleComments.get(i + mVisibleComments.get(i).getChildren().size()).setLoadingMoreChildren(false);
mVisibleComments.get(i + mVisibleComments.get(i).getChildren().size()).setLoadMoreChildrenFailed(true);
notifyItemChanged(i + mVisibleComments.get(i).getChildren().size());
}
mVisibleComments.get(i).getChildren().get(mVisibleComments.get(i).getChildren().size() - 1).setLoadingMoreChildren(false);
mVisibleComments.get(i).getChildren().get(mVisibleComments.get(i).getChildren().size() - 1).setLoadMoreChildrenFailed(true);
break;
}
}
}
}
});
}
private int getParentPosition(int position) {
int childDepth = mVisibleComments.get(position).getDepth();
for(int i = position; i >= 0; i--) {
if(mVisibleComments.get(i).getDepth() < childDepth) {
return i;
}
}
return -1;
} }
private void expandChildren(int position) { private void expandChildren(int position) {
mVisibleComments.get(position).setExpanded(true); CommentData comment = mVisibleComments.get(position);
ArrayList<CommentData> children = mVisibleComments.get(position).getChildren(); if(!comment.isExpanded()) {
if(children != null && children.size() > 0) { comment.setExpanded(true);
mVisibleComments.addAll(position + 1, children); ArrayList<CommentData> children = comment.getChildren();
for(int i = position + 1; i <= position + children.size(); i++) { if(children != null && children.size() > 0) {
mVisibleComments.get(i).setExpanded(false); /*if(comment.hasMoreChildrenFullnames() && comment.getMoreChildrenFullnames().size() > comment.getMoreChildrenStartingIndex()
&& !children.get(children.size() - 1).isPlaceHolder()) {
children.add(children.size(), new CommentData(children.get(0).getDepth()));
}*/
mVisibleComments.addAll(position + 1, children);
for(int i = position + 1; i <= position + children.size(); i++) {
mVisibleComments.get(i).setExpanded(false);
}
notifyItemRangeInserted(position + 1, children.size());
} }
notifyItemRangeInserted(position + 1, children.size());
} }
} }
@ -392,4 +544,33 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
ButterKnife.bind(this, itemView); ButterKnife.bind(this, itemView);
} }
} }
class LoadMoreCommentViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.vertical_block_item_load_more_comments) View verticalBlock;
@BindView(R.id.load_more_comments_text_view_item_load_more_comments) TextView textView;
LoadMoreCommentViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
class IsLoadingMoreCommentViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.vertical_block_item_is_loading_more_comments) View verticalBlock;
IsLoadingMoreCommentViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
class LoadMoreCommentFailedViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.vertical_block_item_load_more_comments_failed) View verticalBlock;
@BindView(R.id.retry_text_view_item_load_more_comments_failed) TextView retryTextView;
LoadMoreCommentFailedViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
} }

View File

@ -24,13 +24,8 @@ class FetchComment {
void onFetchMoreCommentFailed(); void onFetchMoreCommentFailed();
} }
interface FetchAllCommentListener {
void onFetchAllCommentSuccess(ArrayList<CommentData> commentData);
void onFetchAllCommentFailed();
}
static void fetchComment(Retrofit retrofit, String subredditNamePrefixed, String article, static void fetchComment(Retrofit retrofit, String subredditNamePrefixed, String article,
String comment, Locale locale, boolean isPost, int parentDepth, String comment, Locale locale, boolean isPost, int depth,
final FetchCommentListener fetchCommentListener) { final FetchCommentListener fetchCommentListener) {
RedditAPI api = retrofit.create(RedditAPI.class); RedditAPI api = retrofit.create(RedditAPI.class);
Call<String> comments = api.getComments(subredditNamePrefixed, article, comment); Call<String> comments = api.getComments(subredditNamePrefixed, article, comment);
@ -39,13 +34,13 @@ class FetchComment {
public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) { public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) {
if(response.isSuccessful()) { if(response.isSuccessful()) {
ParseComment.parseComment(response.body(), new ArrayList<>(), ParseComment.parseComment(response.body(), new ArrayList<>(),
locale, isPost, parentDepth, locale, isPost, depth,
new ParseComment.ParseCommentListener() { new ParseComment.ParseCommentListener() {
@Override @Override
public void onParseCommentSuccess(ArrayList<CommentData> commentData, public void onParseCommentSuccess(ArrayList<CommentData> commentData,
String parentId, ArrayList<String> moreChildrenIds) { String parentId, ArrayList<String> moreChildrenFullnames) {
fetchCommentListener.onFetchCommentSuccess(commentData, parentId, fetchCommentListener.onFetchCommentSuccess(commentData, parentId,
moreChildrenIds); moreChildrenFullnames);
} }
@Override @Override
@ -68,9 +63,9 @@ class FetchComment {
}); });
} }
static void fetchMoreComment(Retrofit retrofit, String subredditNamePrefixed, String mParentId, static void fetchMoreComment(Retrofit retrofit, String subredditNamePrefixed,
ArrayList<String> allChildren, int startingIndex, Locale locale, ArrayList<String> allChildren, int startingIndex, int depth,
FetchMoreCommentListener fetchMoreCommentListener) { Locale locale, FetchMoreCommentListener fetchMoreCommentListener) {
StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder = new StringBuilder();
for(int i = 0; i < 100; i++) { for(int i = 0; i < 100; i++) {
if(allChildren.size() <= startingIndex + i) { if(allChildren.size() <= startingIndex + i) {
@ -86,101 +81,37 @@ class FetchComment {
stringBuilder.deleteCharAt(stringBuilder.length() - 1); stringBuilder.deleteCharAt(stringBuilder.length() - 1);
RedditAPI api = retrofit.create(RedditAPI.class); RedditAPI api = retrofit.create(RedditAPI.class);
Call<String> moreChildrenBasicInfo = api.getMoreChildren(mParentId, stringBuilder.toString());
moreChildrenBasicInfo.enqueue(new Callback<String>() { Call<String> moreComments = api.getInfo(subredditNamePrefixed, stringBuilder.toString());
moreComments.enqueue(new Callback<String>() {
@Override @Override
public void onResponse(Call<String> call, Response<String> response) { public void onResponse(Call<String> call, Response<String> response) {
if(response.isSuccessful()) { if(response.isSuccessful()) {
ParseComment.parseMoreCommentBasicInfo(response.body(), new ParseComment.ParseMoreCommentBasicInfoListener() { ParseComment.parseMoreComment(response.body(), new ArrayList<>(), locale,
@Override depth, new ParseComment.ParseCommentListener() {
public void onParseMoreCommentBasicInfoSuccess(String commaSeparatedChildrenId) {
Call<String> moreComments = api.getInfo(subredditNamePrefixed, commaSeparatedChildrenId);
moreComments.enqueue(new Callback<String>() {
@Override @Override
public void onResponse(Call<String> call, Response<String> response) { public void onParseCommentSuccess(ArrayList<CommentData> commentData, String parentId,
if(response.isSuccessful()) { ArrayList<String> moreChildrenFullnames) {
ParseComment.parseMoreComment(response.body(), new ArrayList<>(), locale, fetchMoreCommentListener.onFetchMoreCommentSuccess(commentData, startingIndex + 100);
0, new ParseComment.ParseCommentListener() {
@Override
public void onParseCommentSuccess(ArrayList<CommentData> commentData, String parentId,
ArrayList<String> moreChildrenIds) {
fetchMoreCommentListener.onFetchMoreCommentSuccess(commentData, startingIndex + 100);
}
@Override
public void onParseCommentFailed() {
fetchMoreCommentListener.onFetchMoreCommentFailed();
Log.i("comment parse failed", "comment parse failed");
}
});
} else {
Log.i("more comment failed", response.message());
fetchMoreCommentListener.onFetchMoreCommentFailed();
}
} }
@Override @Override
public void onFailure(Call<String> call, Throwable t) { public void onParseCommentFailed() {
Log.i("more comment failed", t.getMessage());
fetchMoreCommentListener.onFetchMoreCommentFailed(); fetchMoreCommentListener.onFetchMoreCommentFailed();
Log.i("comment parse failed", "comment parse failed");
} }
}); });
}
@Override
public void onParseMoreCommentBasicInfoFailed() {
Log.i("comment parse failed", "comment parse failed");
fetchMoreCommentListener.onFetchMoreCommentFailed();
}
});
} else { } else {
Log.i("basic info failed", response.message()); Log.i("more comment failed", response.message());
fetchMoreCommentListener.onFetchMoreCommentFailed(); fetchMoreCommentListener.onFetchMoreCommentFailed();
} }
} }
@Override @Override
public void onFailure(Call<String> call, Throwable t) { public void onFailure(Call<String> call, Throwable t) {
Log.i("basic info failed", t.getMessage()); Log.i("more comment failed", t.getMessage());
fetchMoreCommentListener.onFetchMoreCommentFailed(); fetchMoreCommentListener.onFetchMoreCommentFailed();
} }
}); });
} }
static void fetchAllComment(Retrofit retrofit, String subredditNamePrefixed, String article,
String comment, Locale locale, boolean isPost, int parentDepth,
FetchAllCommentListener fetchAllCommentListener) {
fetchComment(retrofit, subredditNamePrefixed, article, comment, locale, isPost, parentDepth,
new FetchCommentListener() {
@Override
public void onFetchCommentSuccess(ArrayList<CommentData> commentsData, String parentId, ArrayList<String> children) {
if(children.size() != 0) {
fetchMoreComment(retrofit, subredditNamePrefixed, parentId, children,
0, locale, new FetchMoreCommentListener() {
@Override
public void onFetchMoreCommentSuccess(ArrayList<CommentData> commentsData,
int childrenStartingIndex) {
((ArrayList<CommentData>) commentsData).addAll((ArrayList<CommentData>) commentsData);
fetchAllCommentListener.onFetchAllCommentSuccess(commentsData);
}
@Override
public void onFetchMoreCommentFailed() {
Log.i("fetch more comment", "error");
fetchAllCommentListener.onFetchAllCommentFailed();
}
});
} else {
fetchAllCommentListener.onFetchAllCommentSuccess(commentsData);
}
}
@Override
public void onFetchCommentFailed() {
Log.i("fetch comment", "error");
fetchAllCommentListener.onFetchAllCommentFailed();
}
});
}
} }

View File

@ -382,13 +382,10 @@ public class MainActivity extends AppCompatActivity {
if (mFragment instanceof FragmentCommunicator) { if (mFragment instanceof FragmentCommunicator) {
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.action_refresh_main_activity: case R.id.action_refresh_main_activity:
/*((FragmentCommunicator) mFragment).refresh(); ((FragmentCommunicator) mFragment).refresh();
mFetchUserInfoSuccess = false; mFetchUserInfoSuccess = false;
mInsertSuccess = false; mInsertSuccess = false;
loadUserData();*/ loadUserData();
Intent intent = new Intent(this, CommentActivity.class);
intent.putExtra(CommentActivity.EXTRA_COMMENT_DATA_KEY, "asdfasdfas");
startActivity(intent);
return true; return true;
case R.id.action_lazy_mode_main_activity: case R.id.action_lazy_mode_main_activity:
MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_main_activity); MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_main_activity);

View File

@ -16,7 +16,7 @@ import java.util.Locale;
class ParseComment { class ParseComment {
interface ParseCommentListener { interface ParseCommentListener {
void onParseCommentSuccess(ArrayList<CommentData> commentData, String parentId, ArrayList<String> moreChildrenIds); void onParseCommentSuccess(ArrayList<CommentData> commentData, String parentId, ArrayList<String> moreChildrenFullnames);
void onParseCommentFailed(); void onParseCommentFailed();
} }
@ -31,7 +31,7 @@ class ParseComment {
} }
static void parseComment(String response, ArrayList<CommentData> commentData, Locale locale, static void parseComment(String response, ArrayList<CommentData> commentData, Locale locale,
boolean isPost, int parentDepth, ParseCommentListener parseCommentListener) { boolean isPost, int depth, ParseCommentListener parseCommentListener) {
try { try {
JSONArray childrenArray = new JSONArray(response); JSONArray childrenArray = new JSONArray(response);
String parentId = childrenArray.getJSONObject(0).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY) String parentId = childrenArray.getJSONObject(0).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY)
@ -44,7 +44,7 @@ class ParseComment {
.getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY); .getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY);
} }
new ParseCommentAsyncTask(childrenArray, commentData, locale, parentId, parentDepth, parseCommentListener).execute(); new ParseCommentAsyncTask(childrenArray, commentData, locale, parentId, depth, parseCommentListener).execute();
} catch (JSONException e) { } catch (JSONException e) {
e.printStackTrace(); e.printStackTrace();
if(e.getMessage() != null) { if(e.getMessage() != null) {
@ -54,15 +54,11 @@ class ParseComment {
} }
} }
static void parseMoreCommentBasicInfo(String response, ParseMoreCommentBasicInfoListener parseMoreCommentBasicInfoListener) {
new ParseMoreCommentBasicInfoAsyncTask(response, parseMoreCommentBasicInfoListener).execute();
}
static void parseMoreComment(String response, ArrayList<CommentData> commentData, Locale locale, static void parseMoreComment(String response, ArrayList<CommentData> commentData, Locale locale,
int parentDepth, ParseCommentListener parseCommentListener) { int depth, ParseCommentListener parseCommentListener) {
try { try {
JSONArray childrenArray = new JSONObject(response).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY); JSONArray childrenArray = new JSONObject(response).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY);
new ParseCommentAsyncTask(childrenArray, commentData, locale, null, parentDepth, parseCommentListener).execute(); new ParseCommentAsyncTask(childrenArray, commentData, locale, null, depth, parseCommentListener).execute();
} catch (JSONException e) { } catch (JSONException e) {
e.printStackTrace(); e.printStackTrace();
if(e.getMessage() != null) { if(e.getMessage() != null) {
@ -72,31 +68,31 @@ class ParseComment {
} }
} }
static void parseSentComment(String response, int parentDepth, Locale locale, static void parseSentComment(String response, int depth, Locale locale,
ParseSentCommentListener parseSentCommentListener) { ParseSentCommentListener parseSentCommentListener) {
new ParseSentCommentAsyncTask(response, parentDepth, locale, parseSentCommentListener).execute(); new ParseSentCommentAsyncTask(response, depth, locale, parseSentCommentListener).execute();
} }
private static class ParseCommentAsyncTask extends AsyncTask<Void, Void, Void> { private static class ParseCommentAsyncTask extends AsyncTask<Void, Void, Void> {
private JSONArray comments; private JSONArray comments;
private ArrayList<CommentData> commentData; private ArrayList<CommentData> commentData;
private ArrayList<CommentData> newcommentData; private ArrayList<CommentData> newcommentData;
private ArrayList<String> moreChildrenIds; private ArrayList<String> moreChildrenFullnames;
private Locale locale; private Locale locale;
private String parentId; private String parentId;
private int parentDepth; private int depth;
private ParseCommentListener parseCommentListener; private ParseCommentListener parseCommentListener;
private boolean parseFailed; private boolean parseFailed;
ParseCommentAsyncTask(JSONArray comments, ArrayList<CommentData> commentData, Locale locale, ParseCommentAsyncTask(JSONArray comments, ArrayList<CommentData> commentData, Locale locale,
@Nullable String parentId, int parentDepth, ParseCommentListener parseCommentListener){ @Nullable String parentId, int depth, ParseCommentListener parseCommentListener){
this.comments = comments; this.comments = comments;
this.commentData = commentData; this.commentData = commentData;
newcommentData = new ArrayList<>(); newcommentData = new ArrayList<>();
moreChildrenIds = new ArrayList<>(); moreChildrenFullnames = new ArrayList<>();
this.locale = locale; this.locale = locale;
this.parentId = parentId; this.parentId = parentId;
this.parentDepth = parentDepth; this.depth = depth;
parseFailed = false; parseFailed = false;
this.parseCommentListener = parseCommentListener; this.parseCommentListener = parseCommentListener;
} }
@ -104,7 +100,7 @@ class ParseComment {
@Override @Override
protected Void doInBackground(Void... voids) { protected Void doInBackground(Void... voids) {
try { try {
parseCommentRecursion(comments, newcommentData, moreChildrenIds, parentDepth, locale); parseCommentRecursion(comments, newcommentData, moreChildrenFullnames, depth, locale);
} catch (JSONException e) { } catch (JSONException e) {
parseFailed = true; parseFailed = true;
if(e.getMessage() != null) { if(e.getMessage() != null) {
@ -118,7 +114,7 @@ class ParseComment {
protected void onPostExecute(Void aVoid) { protected void onPostExecute(Void aVoid) {
if(!parseFailed) { if(!parseFailed) {
commentData.addAll(newcommentData); commentData.addAll(newcommentData);
parseCommentListener.onParseCommentSuccess(commentData, parentId, moreChildrenIds); parseCommentListener.onParseCommentSuccess(commentData, parentId, moreChildrenFullnames);
} else { } else {
parseCommentListener.onParseCommentFailed(); parseCommentListener.onParseCommentFailed();
} }
@ -126,7 +122,7 @@ class ParseComment {
} }
private static void parseCommentRecursion(JSONArray comments, ArrayList<CommentData> newCommentData, private static void parseCommentRecursion(JSONArray comments, ArrayList<CommentData> newCommentData,
ArrayList<String> moreChildrenIds, int parentDepth, Locale locale) throws JSONException { ArrayList<String> moreChildrenFullnames, int depth, Locale locale) throws JSONException {
int actualCommentLength; int actualCommentLength;
if(comments.length() == 0) { if(comments.length() == 0) {
@ -135,12 +131,12 @@ class ParseComment {
JSONObject more = comments.getJSONObject(comments.length() - 1).getJSONObject(JSONUtils.DATA_KEY); JSONObject more = comments.getJSONObject(comments.length() - 1).getJSONObject(JSONUtils.DATA_KEY);
//Maybe moreChildrenIds contain only comments and no more info //Maybe moreChildrenFullnames contain only comments and no more info
if(more.has(JSONUtils.COUNT_KEY)) { if(more.has(JSONUtils.COUNT_KEY)) {
JSONArray childrenArray = more.getJSONArray(JSONUtils.CHILDREN_KEY); JSONArray childrenArray = more.getJSONArray(JSONUtils.CHILDREN_KEY);
for(int i = 0; i < childrenArray.length(); i++) { for(int i = 0; i < childrenArray.length(); i++) {
moreChildrenIds.add(childrenArray.getString(i)); moreChildrenFullnames.add("t1_" + childrenArray.getString(i));
} }
actualCommentLength = comments.length() - 1; actualCommentLength = comments.length() - 1;
@ -150,17 +146,17 @@ class ParseComment {
for (int i = 0; i < actualCommentLength; i++) { for (int i = 0; i < actualCommentLength; i++) {
JSONObject data = comments.getJSONObject(i).getJSONObject(JSONUtils.DATA_KEY); JSONObject data = comments.getJSONObject(i).getJSONObject(JSONUtils.DATA_KEY);
CommentData singleComment = parseSingleComment(data, parentDepth, locale); CommentData singleComment = parseSingleComment(data, depth, locale);
if(data.get(JSONUtils.REPLIES_KEY) instanceof JSONObject) { if(data.get(JSONUtils.REPLIES_KEY) instanceof JSONObject) {
JSONArray childrenArray = data.getJSONObject(JSONUtils.REPLIES_KEY) JSONArray childrenArray = data.getJSONObject(JSONUtils.REPLIES_KEY)
.getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY); .getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY);
ArrayList<CommentData> children = new ArrayList<>(); ArrayList<CommentData> children = new ArrayList<>();
ArrayList<String> nextMoreChildrenIds = new ArrayList<>(); ArrayList<String> nextMoreChildrenFullnames = new ArrayList<>();
parseCommentRecursion(childrenArray, children, nextMoreChildrenIds, singleComment.getDepth(), parseCommentRecursion(childrenArray, children, nextMoreChildrenFullnames, singleComment.getDepth(),
locale); locale);
singleComment.addChildren(children); singleComment.addChildren(children);
singleComment.setMoreChildrenIds(nextMoreChildrenIds); singleComment.setMoreChildrenFullnames(nextMoreChildrenFullnames);
} }
newCommentData.add(singleComment); newCommentData.add(singleComment);
@ -214,15 +210,15 @@ class ParseComment {
private static class ParseSentCommentAsyncTask extends AsyncTask<Void, Void, Void> { private static class ParseSentCommentAsyncTask extends AsyncTask<Void, Void, Void> {
private String response; private String response;
private int parentDepth; private int depth;
private Locale locale; private Locale locale;
private ParseSentCommentListener parseSentCommentListener; private ParseSentCommentListener parseSentCommentListener;
private boolean parseFailed; private boolean parseFailed;
private CommentData commentData; private CommentData commentData;
ParseSentCommentAsyncTask(String response, int parentDepth, Locale locale, ParseSentCommentListener parseSentCommentListener) { ParseSentCommentAsyncTask(String response, int depth, Locale locale, ParseSentCommentListener parseSentCommentListener) {
this.response = response; this.response = response;
this.parentDepth = parentDepth; this.depth = depth;
this.locale = locale; this.locale = locale;
this.parseSentCommentListener = parseSentCommentListener; this.parseSentCommentListener = parseSentCommentListener;
parseFailed = false; parseFailed = false;
@ -232,7 +228,7 @@ class ParseComment {
protected Void doInBackground(Void... voids) { protected Void doInBackground(Void... voids) {
try { try {
JSONObject sentCommentData = new JSONObject(response); JSONObject sentCommentData = new JSONObject(response);
commentData = parseSingleComment(sentCommentData, parentDepth, locale); commentData = parseSingleComment(sentCommentData, depth, locale);
} catch (JSONException e) { } catch (JSONException e) {
e.printStackTrace(); e.printStackTrace();
parseFailed = true; parseFailed = true;
@ -250,7 +246,7 @@ class ParseComment {
} }
} }
} }
private static CommentData parseSingleComment(JSONObject singleCommentData, int parentDepth, Locale locale) throws JSONException { private static CommentData parseSingleComment(JSONObject singleCommentData, int depth, Locale locale) throws JSONException {
String id = singleCommentData.getString(JSONUtils.ID_KEY); String id = singleCommentData.getString(JSONUtils.ID_KEY);
String fullName = singleCommentData.getString(JSONUtils.NAME_KEY); String fullName = singleCommentData.getString(JSONUtils.NAME_KEY);
String author = singleCommentData.getString(JSONUtils.AUTHOR_KEY); String author = singleCommentData.getString(JSONUtils.AUTHOR_KEY);
@ -270,12 +266,10 @@ class ParseComment {
String formattedSubmitTime = new SimpleDateFormat("MMM d, YYYY, HH:mm", String formattedSubmitTime = new SimpleDateFormat("MMM d, YYYY, HH:mm",
locale).format(submitTimeCalendar.getTime()); locale).format(submitTimeCalendar.getTime());
int depth;
if(singleCommentData.has(JSONUtils.DEPTH_KEY)) { if(singleCommentData.has(JSONUtils.DEPTH_KEY)) {
depth = singleCommentData.getInt(JSONUtils.DEPTH_KEY); depth = singleCommentData.getInt(JSONUtils.DEPTH_KEY);
} else {
depth = parentDepth;
} }
boolean collapsed = singleCommentData.getBoolean(JSONUtils.COLLAPSED_KEY); boolean collapsed = singleCommentData.getBoolean(JSONUtils.COLLAPSED_KEY);
boolean hasReply = !(singleCommentData.get(JSONUtils.REPLIES_KEY) instanceof String); boolean hasReply = !(singleCommentData.get(JSONUtils.REPLIES_KEY) instanceof String);

View File

@ -54,9 +54,6 @@ public interface RedditAPI {
@POST("api/subscribe") @POST("api/subscribe")
Call<String> subredditSubscription(@HeaderMap Map<String, String> headers, @FieldMap Map<String, String> params); Call<String> subredditSubscription(@HeaderMap Map<String, String> headers, @FieldMap Map<String, String> params);
@GET("api/morechildren?api_type=json&raw_json=1")
Call<String> getMoreChildren(@Query("link_id") String linkId, @Query("children") String children);
@GET("{subredditNamePrefixed}/api/info.json?raw_json=1") @GET("{subredditNamePrefixed}/api/info.json?raw_json=1")
Call<String> getInfo(@Path("subredditNamePrefixed") String subredditNamePrefixed, @Query("id") String id); Call<String> getInfo(@Path("subredditNamePrefixed") String subredditNamePrefixed, @Query("id") String id);

View File

@ -209,7 +209,7 @@ public class SubredditListingRecyclerViewAdapter extends PagedListAdapter<Subred
super(itemView); super(itemView);
ButterKnife.bind(this, itemView); ButterKnife.bind(this, itemView);
retryButton.setOnClickListener(view -> retryLoadingMoreCallback.retryLoadingMore()); retryButton.setOnClickListener(view -> retryLoadingMoreCallback.retryLoadingMore());
errorTextView.setText(R.string.load_comment_failed); errorTextView.setText(R.string.post_load_comments_failed);
} }
} }

View File

@ -209,7 +209,7 @@ public class UserListingRecyclerViewAdapter extends PagedListAdapter<UserData, R
super(itemView); super(itemView);
ButterKnife.bind(this, itemView); ButterKnife.bind(this, itemView);
retryButton.setOnClickListener(view -> retryLoadingMoreCallback.retryLoadingMore()); retryButton.setOnClickListener(view -> retryLoadingMoreCallback.retryLoadingMore());
errorTextView.setText(R.string.load_comment_failed); errorTextView.setText(R.string.post_load_comments_failed);
} }
} }

View File

@ -541,8 +541,8 @@ public class ViewPostDetailActivity extends AppCompatActivity {
private void fetchMoreComment(int startingIndex) { private void fetchMoreComment(int startingIndex) {
isLoadingMoreChildren = true; isLoadingMoreChildren = true;
FetchComment.fetchMoreComment(mRetrofit, mPost.getSubredditNamePrefixed(), mPost.getFullName(), FetchComment.fetchMoreComment(mRetrofit, mPost.getSubredditNamePrefixed(), children, startingIndex,
children, startingIndex, mLocale, new FetchComment.FetchMoreCommentListener() { 0, mLocale, new FetchComment.FetchMoreCommentListener() {
@Override @Override
public void onFetchMoreCommentSuccess(ArrayList<CommentData> commentsData, int childrenStartingIndex) { public void onFetchMoreCommentSuccess(ArrayList<CommentData> commentsData, int childrenStartingIndex) {
mAdapter.addComments(commentsData); mAdapter.addComments(commentsData);
@ -553,7 +553,7 @@ public class ViewPostDetailActivity extends AppCompatActivity {
@Override @Override
public void onFetchMoreCommentFailed() { public void onFetchMoreCommentFailed() {
isLoadingMoreChildren = false; isLoadingMoreChildren = false;
Snackbar snackbar = Snackbar.make(mCoordinatorLayout, R.string.load_more_comment_failed, Snackbar.LENGTH_INDEFINITE); Snackbar snackbar = Snackbar.make(mCoordinatorLayout, R.string.post_load_more_comments_failed, Snackbar.LENGTH_INDEFINITE);
snackbar.setAction(R.string.retry, view -> fetchMoreComment(startingIndex)); snackbar.setAction(R.string.retry, view -> fetchMoreComment(startingIndex));
snackbar.show(); snackbar.show();
} }
@ -613,7 +613,7 @@ public class ViewPostDetailActivity extends AppCompatActivity {
} }
private void showRetrySnackbar() { private void showRetrySnackbar() {
Snackbar snackbar = Snackbar.make(mCoordinatorLayout, R.string.load_comment_failed, Snackbar.LENGTH_INDEFINITE); Snackbar snackbar = Snackbar.make(mCoordinatorLayout, R.string.post_load_comments_failed, Snackbar.LENGTH_INDEFINITE);
snackbar.setAction(R.string.retry, view -> fetchComment()); snackbar.setAction(R.string.retry, view -> fetchComment());
snackbar.show(); snackbar.show();
} }

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:id="@+id/vertical_block_item_is_loading_more_comments"
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="@color/textColorPrimaryDark" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="8dp"
android:text="@string/loading"
android:textColor="@color/primaryTextColor" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:id="@+id/vertical_block_item_load_more_comments"
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="@color/textColorPrimaryDark" />
<TextView
android:id="@+id/load_more_comments_text_view_item_load_more_comments"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="8dp"
android:text="@string/comment_load_more_comments"
android:textColor="@color/primaryTextColor" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:id="@+id/vertical_block_item_load_more_comments_failed"
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="@color/textColorPrimaryDark" />
<TextView
android:id="@+id/retry_text_view_item_load_more_comments_failed"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical"
android:gravity="center"
android:padding="8dp"
android:text="@string/comment_load_more_comments_failed"
android:textColor="@color/primaryTextColor" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>

View File

@ -27,8 +27,8 @@
<string name="no_storage_permission">No storage permission to save this file</string> <string name="no_storage_permission">No storage permission to save this file</string>
<string name="load_posts_failed">Error loading posts</string> <string name="load_posts_failed">Error loading posts</string>
<string name="load_comment_failed">Error loading comments</string> <string name="post_load_comments_failed">Error loading comments</string>
<string name="load_more_comment_failed">Error loading more 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>
@ -80,4 +80,9 @@
<string name="download_completed">Download completed</string> <string name="download_completed">Download completed</string>
<string name="download_failed">Download Failed</string> <string name="download_failed">Download Failed</string>
<string name="comment_load_more_comments">Load more comments</string>
<string name="comment_load_more_comments_failed">Load failed. Tap to retry.</string>
<string name="loading">Loading</string>
</resources> </resources>