diff options
author | Alex Ning <chineseperson5@gmail.com> | 2019-06-17 16:01:15 +0000 |
---|---|---|
committer | Alex Ning <chineseperson5@gmail.com> | 2019-06-17 16:01:15 +0000 |
commit | 25f2a35d227b299ff202969f614eab914bf8f6ec (patch) | |
tree | 3bdab2028e4d9245065a9b8c02e536edee838bef /app/src/main | |
parent | 502cbe02ba9ad397d616961bd7cb85ae66aced8e (diff) | |
download | infinity-for-reddit-25f2a35d227b299ff202969f614eab914bf8f6ec.tar infinity-for-reddit-25f2a35d227b299ff202969f614eab914bf8f6ec.tar.gz infinity-for-reddit-25f2a35d227b299ff202969f614eab914bf8f6ec.tar.bz2 infinity-for-reddit-25f2a35d227b299ff202969f614eab914bf8f6ec.tar.lz infinity-for-reddit-25f2a35d227b299ff202969f614eab914bf8f6ec.tar.xz infinity-for-reddit-25f2a35d227b299ff202969f614eab914bf8f6ec.tar.zst infinity-for-reddit-25f2a35d227b299ff202969f614eab914bf8f6ec.zip |
Reimplemented parsing comments using recursion to parse all the child comments. Reimplemented CommentRecyclerView (some methods need proper implementation. Minor bugs fixed.
Diffstat (limited to '')
-rw-r--r-- | app/src/main/java/ml/docilealligator/infinityforreddit/CommentActivity.java | 2 | ||||
-rw-r--r-- | app/src/main/java/ml/docilealligator/infinityforreddit/CommentData.java | 232 | ||||
-rw-r--r-- | app/src/main/java/ml/docilealligator/infinityforreddit/CommentRecyclerViewAdapter.java (renamed from app/src/main/java/ml/docilealligator/infinityforreddit/CommentMultiLevelRecyclerViewAdapter.java) | 163 | ||||
-rw-r--r-- | app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java | 21 | ||||
-rw-r--r-- | app/src/main/java/ml/docilealligator/infinityforreddit/ParseComment.java | 99 | ||||
-rw-r--r-- | app/src/main/java/ml/docilealligator/infinityforreddit/ViewPostDetailActivity.java | 28 | ||||
-rw-r--r-- | app/src/main/res/layout/activity_view_post_detail.xml | 7 | ||||
-rw-r--r-- | app/src/main/res/layout/item_comment.xml | 1 |
8 files changed, 425 insertions, 128 deletions
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentActivity.java index 9bf4ebc7..eef1d810 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentActivity.java @@ -3,7 +3,6 @@ package ml.docilealligator.infinityforreddit; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; -import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.widget.EditText; @@ -70,7 +69,6 @@ public class CommentActivity extends AppCompatActivity { toolbar.setTitle(getString(R.string.comment_activity_label_is_replying)); } - Log.i("fullname", parentFullname); setSupportActionBar(toolbar); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentData.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentData.java index 57e95bae..043c0071 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentData.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentData.java @@ -3,14 +3,15 @@ package ml.docilealligator.infinityforreddit; import android.os.Parcel; import android.os.Parcelable; -import com.multilevelview.models.RecyclerViewItem; +import java.util.ArrayList; -class CommentData extends RecyclerViewItem implements Parcelable { +class CommentData implements Parcelable { private String id; private String fullName; private String author; private String commentTime; private String commentContent; + private String parentId; private int score; private int voteType; private boolean isSubmitter; @@ -19,16 +20,217 @@ class CommentData extends RecyclerViewItem implements Parcelable { private boolean collapsed; private boolean hasReply; private boolean scoreHidden; + private boolean isExpanded; + private ArrayList<CommentData> children; + private ArrayList<String> moreChildrenIds; CommentData(String id, String fullName, String author, String commentTime, String commentContent, - int score, boolean isSubmitter, String permalink, int depth, boolean collapsed, - boolean hasReply, boolean scoreHidden) { + String parentId, int score, boolean isSubmitter, String permalink, int depth, + boolean collapsed, boolean hasReply, boolean scoreHidden) { + this.id = id; + this.fullName = fullName; + this.author = author; + this.commentTime = commentTime; + this.commentContent = commentContent; + this.parentId = parentId; + this.score = score; + this.isSubmitter = isSubmitter; + this.permalink = RedditUtils.API_BASE_URI + permalink; + this.depth = depth; + this.collapsed = collapsed; + this.hasReply = hasReply; + this.scoreHidden = scoreHidden; + this.isExpanded = false; + } + + protected CommentData(Parcel in) { + id = in.readString(); + fullName = in.readString(); + author = in.readString(); + commentTime = in.readString(); + commentContent = in.readString(); + parentId = in.readString(); + score = in.readInt(); + voteType = in.readInt(); + isSubmitter = in.readByte() != 0; + permalink = in.readString(); + depth = in.readInt(); + collapsed = in.readByte() != 0; + hasReply = in.readByte() != 0; + scoreHidden = in.readByte() != 0; + isExpanded = in.readByte() != 0; + in.readStringList(moreChildrenIds); + } + + public static final Creator<CommentData> CREATOR = new Creator<CommentData>() { + @Override + public CommentData createFromParcel(Parcel in) { + return new CommentData(in); + } + + @Override + public CommentData[] newArray(int size) { + return new CommentData[size]; + } + }; + + public String getId() { + return id; + } + + public String getFullName() { + return fullName; + } + + public String getAuthor() { + return author; + } + + public String getCommentTime() { + return commentTime; + } + + public String getCommentContent() { + return commentContent; + } + + public String getParentId() { + return parentId; + } + + public void setParentId(String parentId) { + this.parentId = parentId; + } + + public int getScore() { + return score; + } + + public void setScore(int score) { + this.score = score; + } + + public boolean isSubmitter() { + return isSubmitter; + } + + public String getPermalink() { + return permalink; + } + + public int getDepth() { + return depth; + } + + public boolean isCollapsed() { + return collapsed; + } + + public boolean hasReply() { + return hasReply; + } + + public void setHasReply(boolean hasReply) { + this.hasReply = hasReply; + } + + public boolean isScoreHidden() { + return scoreHidden; + } + + public boolean isExpanded() { + return isExpanded; + } + + public void setExpanded(boolean isExpanded) { + this.isExpanded = isExpanded; + } + + public int getVoteType() { + return voteType; + } + + public void setVoteType(int voteType) { + this.voteType = voteType; + } + + public ArrayList<CommentData> getChildren() { + return children; + } + + public void setChildren(ArrayList<CommentData> children) { + this.children = children; + } + + public void addChildren(ArrayList<CommentData> moreChildren) { + if(children == null) { + setChildren(moreChildren); + } else { + children.addAll(moreChildren); + } + } + + public ArrayList<String> getMoreChildrenIds() { + return moreChildrenIds; + } + + public void setMoreChildrenIds(ArrayList<String> moreChildrenIds) { + this.moreChildrenIds = moreChildrenIds; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int i) { + parcel.writeString(id); + parcel.writeString(fullName); + parcel.writeString(author); + parcel.writeString(commentTime); + parcel.writeString(commentContent); + parcel.writeString(parentId); + parcel.writeInt(score); + parcel.writeInt(voteType); + parcel.writeByte((byte) (isSubmitter ? 1 : 0)); + parcel.writeString(permalink); + parcel.writeInt(depth); + parcel.writeByte((byte) (collapsed ? 1 : 0)); + parcel.writeByte((byte) (hasReply ? 1 : 0)); + parcel.writeByte((byte) (scoreHidden ? 1 : 0)); + parcel.writeByte((byte) (isExpanded ? 1 : 0)); + parcel.writeStringList(moreChildrenIds); + } +} + +/*class CommentData extends RecyclerViewItem implements Parcelable { + private String id; + private String fullName; + private String author; + private String commentTime; + private String commentContent; + private String parentId; + private int score; + private int voteType; + private boolean isSubmitter; + private String permalink; + private int depth; + private boolean collapsed; + private boolean hasReply; + private boolean scoreHidden; + private ArrayList<String> moreChildrenIds; + + CommentData(String id, String fullName, String author, String commentTime, String commentContent, + String parentId, int score, boolean isSubmitter, String permalink, int depth, + boolean collapsed, boolean hasReply, boolean scoreHidden) { super(depth); this.id = id; this.fullName = fullName; this.author = author; this.commentTime = commentTime; this.commentContent = commentContent; + this.parentId = parentId; this.score = score; this.isSubmitter = isSubmitter; this.permalink = RedditUtils.API_BASE_URI + permalink; @@ -45,6 +247,7 @@ class CommentData extends RecyclerViewItem implements Parcelable { author = in.readString(); commentTime = in.readString(); commentContent = in.readString(); + parentId = in.readString(); score = in.readInt(); voteType = in.readInt(); isSubmitter = in.readByte() != 0; @@ -53,6 +256,7 @@ class CommentData extends RecyclerViewItem implements Parcelable { collapsed = in.readByte() != 0; hasReply = in.readByte() != 0; scoreHidden = in.readByte() != 0; + in.readStringList(moreChildrenIds); super.setLevel(depth); } @@ -88,6 +292,14 @@ class CommentData extends RecyclerViewItem implements Parcelable { return commentContent; } + public String getParentId() { + return parentId; + } + + public void setParentId(String parentId) { + this.parentId = parentId; + } + public int getScore() { return score; } @@ -132,6 +344,14 @@ class CommentData extends RecyclerViewItem implements Parcelable { this.voteType = voteType; } + public ArrayList<String> getMoreChildrenIds() { + return moreChildrenIds; + } + + public void setMoreChildrenIds(ArrayList<String> moreChildrenIds) { + this.moreChildrenIds = moreChildrenIds; + } + @Override public int describeContents() { return 0; @@ -144,6 +364,7 @@ class CommentData extends RecyclerViewItem implements Parcelable { parcel.writeString(author); parcel.writeString(commentTime); parcel.writeString(commentContent); + parcel.writeString(parentId); parcel.writeInt(score); parcel.writeInt(voteType); parcel.writeByte((byte) (isSubmitter ? 1 : 0)); @@ -152,5 +373,6 @@ class CommentData extends RecyclerViewItem implements Parcelable { parcel.writeByte((byte) (collapsed ? 1 : 0)); parcel.writeByte((byte) (hasReply ? 1 : 0)); parcel.writeByte((byte) (scoreHidden ? 1 : 0)); + parcel.writeStringList(moreChildrenIds); } -} +}*/ diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentMultiLevelRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentRecyclerViewAdapter.java index 1f5795fe..e9da8bde 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentMultiLevelRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentRecyclerViewAdapter.java @@ -5,6 +5,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.graphics.ColorFilter; import android.net.Uri; +import android.os.Handler; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -18,12 +19,7 @@ import androidx.browser.customtabs.CustomTabsIntent; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; -import com.multilevelview.MultiLevelAdapter; -import com.multilevelview.MultiLevelRecyclerView; -import com.multilevelview.models.RecyclerViewItem; - import java.util.ArrayList; -import java.util.List; import java.util.Locale; import butterknife.BindView; @@ -32,42 +28,59 @@ import retrofit2.Retrofit; import ru.noties.markwon.SpannableConfiguration; import ru.noties.markwon.view.MarkwonView; -class CommentMultiLevelRecyclerViewAdapter extends MultiLevelAdapter { +class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private Activity mActivity; private Retrofit mRetrofit; private Retrofit mOauthRetrofit; private SharedPreferences mSharedPreferences; private ArrayList<CommentData> mCommentData; - private MultiLevelRecyclerView mMultiLevelRecyclerView; - private String subredditNamePrefixed; - private String article; - private Locale locale; + private RecyclerView mRecyclerView; + private String mSubredditNamePrefixed; + private String mArticle; + private Locale mLocale; + + private ArrayList<CommentData> mVisibleComments; - CommentMultiLevelRecyclerViewAdapter(Activity activity, Retrofit retrofit, Retrofit oauthRetrofit, + CommentRecyclerViewAdapter(Activity activity, Retrofit retrofit, Retrofit oauthRetrofit, SharedPreferences sharedPreferences, ArrayList<CommentData> commentData, - MultiLevelRecyclerView multiLevelRecyclerView, + RecyclerView recyclerView, String subredditNamePrefixed, String article, Locale locale) { - super(commentData); mActivity = activity; mRetrofit = retrofit; mOauthRetrofit = oauthRetrofit; mSharedPreferences = sharedPreferences; mCommentData = commentData; - mMultiLevelRecyclerView = multiLevelRecyclerView; - this.subredditNamePrefixed = subredditNamePrefixed; - this.article = article; - this.locale = locale; + mRecyclerView = recyclerView; + mSubredditNamePrefixed = subredditNamePrefixed; + mArticle = article; + mLocale = locale; + mVisibleComments = new ArrayList<>(); + + new Handler().post(() -> { + makeChildrenVisible(commentData, mVisibleComments); + notifyDataSetChanged(); + }); + } + + private void makeChildrenVisible(ArrayList<CommentData> comments, ArrayList<CommentData> visibleComments) { + for(CommentData c : comments) { + visibleComments.add(c); + if(c.hasReply()) { + c.setExpanded(true); + makeChildrenVisible(c.getChildren(), visibleComments); + } + } } @NonNull @Override - public RecyclerView.ViewHolder onCreateViewHolder(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)); } @Override - public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) { - final CommentData commentItem = mCommentData.get(position); + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + final CommentData commentItem = mVisibleComments.get(position); String authorPrefixed = "u/" + commentItem.getAuthor(); ((CommentViewHolder) holder).authorTextView.setText(authorPrefixed); @@ -78,6 +91,7 @@ class CommentMultiLevelRecyclerViewAdapter extends MultiLevelAdapter { }); ((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); @@ -101,35 +115,49 @@ class CommentMultiLevelRecyclerViewAdapter extends MultiLevelAdapter { ((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(commentItem.getScore())); ((CommentViewHolder) holder).verticalBlock.getLayoutParams().width = commentItem.getDepth() * 16; - if (commentItem.hasReply()) { - setExpandButton(((CommentViewHolder) holder).expandButton, commentItem.isExpanded()); - } - ((CommentViewHolder) holder).shareButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - 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")); - } + ((CommentViewHolder) holder).shareButton.setOnClickListener(view -> { + 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); + } + ((CommentViewHolder) holder).expandButton.setVisibility(View.VISIBLE); + } + ((CommentViewHolder) holder).expandButton.setOnClickListener(view -> { - if (commentItem.hasChildren() && commentItem.getChildren().size() > 0) { - mMultiLevelRecyclerView.toggleItemsGroup(holder.getAdapterPosition()); - setExpandButton(((CommentViewHolder) holder).expandButton, commentItem.isExpanded()); + 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, subredditNamePrefixed, article, commentItem.getId(), + FetchComment.fetchAllComment(mRetrofit, mSubredditNamePrefixed, article, commentItem.getId(), locale, false, commentItem.getDepth(), new FetchComment.FetchAllCommentListener() { @Override public void onFetchAllCommentSuccess(List<?> commentData) { - commentItem.addChildren((List<RecyclerViewItem>) commentData); + commentItem.addChildren((ArrayList<CommentData>) commentData); ((CommentViewHolder) holder).loadMoreCommentsProgressBar .setVisibility(View.GONE); - mMultiLevelRecyclerView.toggleItemsGroup(holder.getAdapterPosition()); + expandChildren(holder.getAdapterPosition()); ((CommentViewHolder) holder).expandButton .setImageResource(R.drawable.ic_expand_less_black_20dp); } @@ -140,7 +168,7 @@ class CommentMultiLevelRecyclerViewAdapter extends MultiLevelAdapter { .setVisibility(View.GONE); } }); - } + }*/ }); ((CommentViewHolder) holder).replyButton.setOnClickListener(view -> { @@ -149,6 +177,7 @@ class CommentMultiLevelRecyclerViewAdapter extends MultiLevelAdapter { 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); }); @@ -264,27 +293,49 @@ class CommentMultiLevelRecyclerViewAdapter extends MultiLevelAdapter { }); } - @Override - public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) { - if (holder instanceof CommentViewHolder) { - ((CommentViewHolder) holder).expandButton.setVisibility(View.GONE); - ((CommentViewHolder) holder).loadMoreCommentsProgressBar.setVisibility(View.GONE); + private void expandChildren(int position) { + mVisibleComments.get(position).setExpanded(true); + ArrayList<CommentData> children = mVisibleComments.get(position).getChildren(); + if(children != null && children.size() > 0) { + 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()); + } + } + + private void collapseChildren(int position) { + mVisibleComments.get(position).setExpanded(false); + int depth = mVisibleComments.get(position).getDepth(); + int allChildrenSize = 0; + for(int i = position + 1; i < mVisibleComments.size(); i++) { + if(mVisibleComments.get(i).getDepth() > depth) { + allChildrenSize++; + } else { + break; + } } + + mVisibleComments.subList(position + 1, position + 1 + allChildrenSize).clear(); + notifyItemRangeRemoved(position + 1, allChildrenSize); } void addComments(ArrayList<CommentData> comments) { - int sizeBefore = mCommentData.size(); - mCommentData.addAll(comments); - notifyItemRangeInserted(sizeBefore, mCommentData.size() - sizeBefore); + int sizeBefore = mVisibleComments.size(); + mVisibleComments.addAll(comments); + notifyItemRangeInserted(sizeBefore, comments.size()); } + //Need proper implementation void addComment(CommentData comment) { mCommentData.add(0, comment); notifyItemInserted(0); } + //Need proper implementation void addChildComment(CommentData comment, int parentPosition) { - List<RecyclerViewItem> childComments = mCommentData.get(parentPosition).getChildren(); + ArrayList<CommentData> childComments = mCommentData.get(parentPosition).getChildren(); if(childComments == null) { childComments = new ArrayList<>(); } @@ -292,13 +343,19 @@ class CommentMultiLevelRecyclerViewAdapter extends MultiLevelAdapter { mCommentData.get(parentPosition).addChildren(childComments); mCommentData.get(parentPosition).setHasReply(true); notifyItemChanged(parentPosition); - mMultiLevelRecyclerView.toggleItemsGroup(parentPosition); } - private void setExpandButton(ImageView expandButton, boolean isExpanded) { - // set the icon based on the current state - expandButton.setVisibility(View.VISIBLE); - expandButton.setImageResource(isExpanded ? R.drawable.ic_expand_less_black_20dp : R.drawable.ic_expand_more_black_20dp); + @Override + public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) { + if (holder instanceof CommentViewHolder) { + ((CommentViewHolder) holder).expandButton.setVisibility(View.GONE); + ((CommentViewHolder) holder).loadMoreCommentsProgressBar.setVisibility(View.GONE); + } + } + + @Override + public int getItemCount() { + return mVisibleComments.size(); } class CommentViewHolder extends RecyclerView.ViewHolder { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java index c4b1958e..7f582214 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java @@ -5,7 +5,6 @@ import android.util.Log; import androidx.annotation.NonNull; import java.util.ArrayList; -import java.util.List; import java.util.Locale; import retrofit2.Call; @@ -15,18 +14,18 @@ import retrofit2.Retrofit; class FetchComment { interface FetchCommentListener { - void onFetchCommentSuccess(List<?> commentsData, + void onFetchCommentSuccess(ArrayList<CommentData> commentsData, String parentId, ArrayList<String> children); void onFetchCommentFailed(); } interface FetchMoreCommentListener { - void onFetchMoreCommentSuccess(List<?> commentsData, int childrenStartingIndex); + void onFetchMoreCommentSuccess(ArrayList<CommentData> commentsData, int childrenStartingIndex); void onFetchMoreCommentFailed(); } interface FetchAllCommentListener { - void onFetchAllCommentSuccess(List<?> commentData); + void onFetchAllCommentSuccess(ArrayList<CommentData> commentData); void onFetchAllCommentFailed(); } @@ -43,10 +42,10 @@ class FetchComment { locale, isPost, parentDepth, new ParseComment.ParseCommentListener() { @Override - public void onParseCommentSuccess(List<?> commentData, - String parentId, ArrayList<String> children) { + public void onParseCommentSuccess(ArrayList<CommentData> commentData, + String parentId, ArrayList<String> moreChildrenIds) { fetchCommentListener.onFetchCommentSuccess(commentData, parentId, - children); + moreChildrenIds); } @Override @@ -104,8 +103,8 @@ class FetchComment { ParseComment.parseMoreComment(response.body(), new ArrayList<>(), locale, 0, new ParseComment.ParseCommentListener() { @Override - public void onParseCommentSuccess(List<?> commentData, String parentId, - ArrayList<String> children) { + public void onParseCommentSuccess(ArrayList<CommentData> commentData, String parentId, + ArrayList<String> moreChildrenIds) { fetchMoreCommentListener.onFetchMoreCommentSuccess(commentData, startingIndex + 100); } @@ -155,12 +154,12 @@ class FetchComment { fetchComment(retrofit, subredditNamePrefixed, article, comment, locale, isPost, parentDepth, new FetchCommentListener() { @Override - public void onFetchCommentSuccess(List<?> commentsData, String parentId, ArrayList<String> children) { + 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(List<?> commentsData, + public void onFetchMoreCommentSuccess(ArrayList<CommentData> commentsData, int childrenStartingIndex) { ((ArrayList<CommentData>) commentsData).addAll((ArrayList<CommentData>) commentsData); fetchAllCommentListener.onFetchAllCommentSuccess(commentsData); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseComment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseComment.java index 16aaa609..05b9440a 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseComment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseComment.java @@ -3,6 +3,8 @@ package ml.docilealligator.infinityforreddit; import android.os.AsyncTask; import android.util.Log; +import androidx.annotation.Nullable; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -10,12 +12,11 @@ import org.json.JSONObject; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; -import java.util.List; import java.util.Locale; class ParseComment { interface ParseCommentListener { - void onParseCommentSuccess(List<?> commentData, String parentId, ArrayList<String> children); + void onParseCommentSuccess(ArrayList<CommentData> commentData, String parentId, ArrayList<String> moreChildrenIds); void onParseCommentFailed(); } @@ -33,7 +34,8 @@ class ParseComment { boolean isPost, int parentDepth, ParseCommentListener parseCommentListener) { try { JSONArray childrenArray = new JSONArray(response); - + String parentId = childrenArray.getJSONObject(0).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY) + .getJSONObject(0).getJSONObject(JSONUtils.DATA_KEY).getString(JSONUtils.NAME_KEY); if(isPost) { childrenArray = childrenArray.getJSONObject(1).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY); } else { @@ -41,7 +43,8 @@ class ParseComment { .getJSONObject(0).getJSONObject(JSONUtils.DATA_KEY).getJSONObject(JSONUtils.REPLIES_KEY) .getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY); } - new ParseCommentAsyncTask(childrenArray, commentData, locale, parentDepth, parseCommentListener).execute(); + + new ParseCommentAsyncTask(childrenArray, commentData, locale, parentId, parentDepth, parseCommentListener).execute(); } catch (JSONException e) { e.printStackTrace(); if(e.getMessage() != null) { @@ -59,7 +62,7 @@ class ParseComment { int parentDepth, ParseCommentListener parseCommentListener) { try { JSONArray childrenArray = new JSONObject(response).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY); - new ParseCommentAsyncTask(childrenArray, commentData, locale, parentDepth, parseCommentListener).execute(); + new ParseCommentAsyncTask(childrenArray, commentData, locale, null, parentDepth, parseCommentListener).execute(); } catch (JSONException e) { e.printStackTrace(); if(e.getMessage() != null) { @@ -78,20 +81,21 @@ class ParseComment { private JSONArray comments; private ArrayList<CommentData> commentData; private ArrayList<CommentData> newcommentData; - private ArrayList<String> children; + private ArrayList<String> moreChildrenIds; private Locale locale; + private String parentId; private int parentDepth; private ParseCommentListener parseCommentListener; private boolean parseFailed; - private String parentId; ParseCommentAsyncTask(JSONArray comments, ArrayList<CommentData> commentData, Locale locale, - int parentDepth, ParseCommentListener parseCommentListener){ + @Nullable String parentId, int parentDepth, ParseCommentListener parseCommentListener){ this.comments = comments; this.commentData = commentData; newcommentData = new ArrayList<>(); - children = new ArrayList<>(); + moreChildrenIds = new ArrayList<>(); this.locale = locale; + this.parentId = parentId; this.parentDepth = parentDepth; parseFailed = false; this.parseCommentListener = parseCommentListener; @@ -100,32 +104,7 @@ class ParseComment { @Override protected Void doInBackground(Void... voids) { try { - int actualCommentLength; - - if(comments.length() == 0) { - return null; - } - - JSONObject more = comments.getJSONObject(comments.length() - 1).getJSONObject(JSONUtils.DATA_KEY); - - //Maybe children contain only comments and no more info - if(more.has(JSONUtils.COUNT_KEY)) { - JSONArray childrenArray = more.getJSONArray(JSONUtils.CHILDREN_KEY); - - parentId = more.getString(JSONUtils.PARENT_ID_KEY); - for(int i = 0; i < childrenArray.length(); i++) { - children.add(childrenArray.getString(i)); - } - - actualCommentLength = comments.length() - 1; - } else { - actualCommentLength = comments.length(); - } - - for (int i = 0; i < actualCommentLength; i++) { - JSONObject data = comments.getJSONObject(i).getJSONObject(JSONUtils.DATA_KEY); - newcommentData.add(parseSingleComment(data, parentDepth, locale)); - } + parseCommentRecursion(comments, newcommentData, moreChildrenIds, parentDepth, locale); } catch (JSONException e) { parseFailed = true; if(e.getMessage() != null) { @@ -139,13 +118,55 @@ class ParseComment { protected void onPostExecute(Void aVoid) { if(!parseFailed) { commentData.addAll(newcommentData); - parseCommentListener.onParseCommentSuccess(commentData, parentId, children); + parseCommentListener.onParseCommentSuccess(commentData, parentId, moreChildrenIds); } else { parseCommentListener.onParseCommentFailed(); } } } + private static void parseCommentRecursion(JSONArray comments, ArrayList<CommentData> newCommentData, + ArrayList<String> moreChildrenIds, int parentDepth, Locale locale) throws JSONException { + int actualCommentLength; + + if(comments.length() == 0) { + return; + } + + JSONObject more = comments.getJSONObject(comments.length() - 1).getJSONObject(JSONUtils.DATA_KEY); + + //Maybe moreChildrenIds contain only comments and no more info + if(more.has(JSONUtils.COUNT_KEY)) { + JSONArray childrenArray = more.getJSONArray(JSONUtils.CHILDREN_KEY); + + for(int i = 0; i < childrenArray.length(); i++) { + moreChildrenIds.add(childrenArray.getString(i)); + } + + actualCommentLength = comments.length() - 1; + } else { + actualCommentLength = comments.length(); + } + + for (int i = 0; i < actualCommentLength; i++) { + JSONObject data = comments.getJSONObject(i).getJSONObject(JSONUtils.DATA_KEY); + CommentData singleComment = parseSingleComment(data, parentDepth, locale); + + if(data.get(JSONUtils.REPLIES_KEY) instanceof JSONObject) { + JSONArray childrenArray = data.getJSONObject(JSONUtils.REPLIES_KEY) + .getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY); + ArrayList<CommentData> children = new ArrayList<>(); + ArrayList<String> nextMoreChildrenIds = new ArrayList<>(); + parseCommentRecursion(childrenArray, children, nextMoreChildrenIds, singleComment.getDepth(), + locale); + singleComment.addChildren(children); + singleComment.setMoreChildrenIds(nextMoreChildrenIds); + } + + newCommentData.add(singleComment); + } + } + private static class ParseMoreCommentBasicInfoAsyncTask extends AsyncTask<Void, Void, Void> { private JSONArray children; private StringBuilder commaSeparatedChildren; @@ -229,11 +250,11 @@ class ParseComment { } } } - private static CommentData parseSingleComment(JSONObject singleCommentData, int parentDepth, Locale locale) throws JSONException { String id = singleCommentData.getString(JSONUtils.ID_KEY); String fullName = singleCommentData.getString(JSONUtils.NAME_KEY); String author = singleCommentData.getString(JSONUtils.AUTHOR_KEY); + String parentId = singleCommentData.getString(JSONUtils.PARENT_ID_KEY); boolean isSubmitter = singleCommentData.getBoolean(JSONUtils.IS_SUBMITTER_KEY); String commentContent = ""; if(!singleCommentData.isNull(JSONUtils.BODY_HTML_KEY)) { @@ -251,14 +272,14 @@ class ParseComment { int depth; if(singleCommentData.has(JSONUtils.DEPTH_KEY)) { - depth = singleCommentData.getInt(JSONUtils.DEPTH_KEY) + parentDepth; + depth = singleCommentData.getInt(JSONUtils.DEPTH_KEY); } else { depth = parentDepth; } boolean collapsed = singleCommentData.getBoolean(JSONUtils.COLLAPSED_KEY); boolean hasReply = !(singleCommentData.get(JSONUtils.REPLIES_KEY) instanceof String); - return new CommentData(id, fullName, author, formattedSubmitTime, commentContent, score, + return new CommentData(id, fullName, author, formattedSubmitTime, commentContent, parentId, score, isSubmitter, permalink, depth, collapsed, hasReply, scoreHidden); } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewPostDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewPostDetailActivity.java index 741a3a57..3c3db7b5 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewPostDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewPostDetailActivity.java @@ -28,6 +28,7 @@ import androidx.core.content.ContextCompat; import androidx.core.widget.NestedScrollView; import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import com.bumptech.glide.Glide; import com.bumptech.glide.RequestBuilder; @@ -41,14 +42,12 @@ import com.google.android.material.card.MaterialCardView; import com.google.android.material.chip.Chip; import com.google.android.material.snackbar.Snackbar; import com.lsjwzh.widget.materialloadingprogressbar.CircleProgressBar; -import com.multilevelview.MultiLevelRecyclerView; import com.santalu.aspectratioimageview.AspectRatioImageView; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import java.util.ArrayList; -import java.util.List; import java.util.Locale; import javax.inject.Inject; @@ -90,7 +89,7 @@ public class ViewPostDetailActivity extends AppCompatActivity { private ArrayList<String> children; private int mChildrenStartingIndex = 0; - private CommentMultiLevelRecyclerViewAdapter mAdapter; + private CommentRecyclerViewAdapter mAdapter; private LoadSubredditIconAsyncTask mLoadSubredditIconAsyncTask; @BindView(R.id.coordinator_layout_view_post_detail) CoordinatorLayout mCoordinatorLayout; @@ -120,7 +119,7 @@ public class ViewPostDetailActivity extends AppCompatActivity { @BindView(R.id.share_button_view_post_detail) ImageView mShareButton; @BindView(R.id.comment_progress_bar_view_post_detail) CircleProgressBar mCommentProgressbar; @BindView(R.id.comment_card_view_view_post_detail) MaterialCardView mCommentCardView; - @BindView(R.id.recycler_view_view_post_detail) MultiLevelRecyclerView mRecyclerView; + @BindView(R.id.recycler_view_view_post_detail) RecyclerView mRecyclerView; @BindView(R.id.no_comment_wrapper_linear_layout_view_post_detail) LinearLayout mNoCommentWrapperLinearLayout; @BindView(R.id.no_comment_image_view_view_post_detail) ImageView mNoCommentImageView; @@ -504,23 +503,18 @@ public class ViewPostDetailActivity extends AppCompatActivity { FetchComment.fetchComment(mRetrofit, mPost.getSubredditNamePrefixed(), mPost.getId(), null, mLocale, true, 0, new FetchComment.FetchCommentListener() { @Override - public void onFetchCommentSuccess(List<?> commentsData, + public void onFetchCommentSuccess(ArrayList<CommentData> commentsData, String parentId, ArrayList<String> children) { ViewPostDetailActivity.this.children = children; mCommentProgressbar.setVisibility(View.GONE); - mCommentsData.addAll((ArrayList<CommentData>) commentsData); + mCommentsData.addAll(commentsData); if (mCommentsData.size() > 0) { if(mAdapter == null) { - mAdapter = new CommentMultiLevelRecyclerViewAdapter( - ViewPostDetailActivity.this, mRetrofit, mOauthRetrofit, - mSharedPreferences, mCommentsData, - mRecyclerView, mPost.getSubredditNamePrefixed(), - mPost.getId(), mLocale); + mAdapter = new CommentRecyclerViewAdapter(ViewPostDetailActivity.this, mRetrofit, + mOauthRetrofit, mSharedPreferences, commentsData, mRecyclerView, + mPost.getSubredditNamePrefixed(), mPost.getId(), mLocale); mRecyclerView.setAdapter(mAdapter); - mRecyclerView.removeItemClickListeners(); - mRecyclerView.setToggleItemOnClick(false); - mRecyclerView.setAccordion(false); mNestedScrollView.getViewTreeObserver().addOnScrollChangedListener(() -> { if(!isLoadingMoreChildren) { @@ -556,8 +550,8 @@ public class ViewPostDetailActivity extends AppCompatActivity { FetchComment.fetchMoreComment(mRetrofit, mPost.getSubredditNamePrefixed(), mPost.getFullName(), children, startingIndex, mLocale, new FetchComment.FetchMoreCommentListener() { @Override - public void onFetchMoreCommentSuccess(List<?> commentsData, int childrenStartingIndex) { - mAdapter.addComments((ArrayList<CommentData>) commentsData); + public void onFetchMoreCommentSuccess(ArrayList<CommentData> commentsData, int childrenStartingIndex) { + mAdapter.addComments(commentsData); mChildrenStartingIndex = childrenStartingIndex; isLoadingMoreChildren = false; } @@ -678,7 +672,7 @@ public class ViewPostDetailActivity extends AppCompatActivity { } @Override - public boolean onOptionsItemSelected(MenuItem item) { + public boolean onOptionsItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { case R.id.action_refresh_view_post_detail_activity: refresh(); diff --git a/app/src/main/res/layout/activity_view_post_detail.xml b/app/src/main/res/layout/activity_view_post_detail.xml index 1810f995..99056019 100644 --- a/app/src/main/res/layout/activity_view_post_detail.xml +++ b/app/src/main/res/layout/activity_view_post_detail.xml @@ -319,7 +319,12 @@ android:textColor="@color/primaryTextColor" android:textSize="18sp" /> - <com.multilevelview.MultiLevelRecyclerView + <!--<com.multilevelview.MultiLevelRecyclerView + android:id="@+id/recycler_view_view_post_detail" + android:layout_width="match_parent" + android:layout_height="wrap_content" />--> + + <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler_view_view_post_detail" android:layout_width="match_parent" android:layout_height="wrap_content" /> diff --git a/app/src/main/res/layout/item_comment.xml b/app/src/main/res/layout/item_comment.xml index d04f78b6..a4a3c043 100644 --- a/app/src/main/res/layout/item_comment.xml +++ b/app/src/main/res/layout/item_comment.xml @@ -107,6 +107,7 @@ android:layout_toStartOf="@id/share_button_item_post_comment" android:layout_centerVertical="true" android:layout_marginEnd="16dp" + android:src="@drawable/ic_expand_less_black_20dp" android:tint="@android:color/tab_indicator_text" android:background="?actionBarItemBackground" android:clickable="true" |