mirror of
https://codeberg.org/Bazsalanszky/Infinity-For-Lemmy.git
synced 2024-12-28 11:58:23 +01:00
Switch loading more comments to /morechildren endpoint (#1186)
* Load more comments from /morechildren endpoint Previous implementation requested comments from /api/info which returned the comments themselves but did not include any information about their children. Also /api/info does not allow to specify sort type. On the other hand /morechildren supports sort type and it will be added in a later commit. I am not proud of this implementation, but I had to fight with both Reddit api response and existing code. The problem with api response is that it is a flat list of comments, not a tree structure. So the tree has to be rebuilt on our end. And the problem with existing code is that it merges "more children" node into its parent but then adds a placeholder anyways. The code relies on the fact that parent comment will be located before any of its children in the response. The code sequentially processes comments, tries to find their parents and either adds them to the tree or puts in a "top-level" array which will be handled by outside code. One possible problem is the removal of `depth` argument from parsing as I couldn't find a way to fit it in the new logic. However I also didn't experience any problems with it during my testing and the response seems to always contain depth key. Moreover current depth handling logic in ParseComment#parseCommentRecursion is broken because it does not increment depth when making a recursive call. * Store moreChildren ids instead of fullnames /morechildren endpoint accepts ids instead of fullnames so there is no point in converting ids to fullnames and back * Send all comment ids to Reddit so it can select what to display itself Sending all ids allows Reddit to sort them properly. Since the number of comments can be very bing, it requires using POST request instead of GET. This commit changes the meaning of Comment#moreChildrenIds field, now it stores only ids of comments that are not yet loaded. This simplifies the code and removes the need for Comment#moreChildrenStartingIndex * Fetch more comments with current sort type
This commit is contained in:
parent
8326e6c4a2
commit
0f1c4d1e11
@ -607,18 +607,17 @@ public class CommentsRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerVi
|
|||||||
((LoadMoreChildCommentsViewHolder) holder).placeholderTextView.setText(R.string.loading);
|
((LoadMoreChildCommentsViewHolder) holder).placeholderTextView.setText(R.string.loading);
|
||||||
|
|
||||||
Retrofit retrofit = mAccessToken == null ? mRetrofit : mOauthRetrofit;
|
Retrofit retrofit = mAccessToken == null ? mRetrofit : mOauthRetrofit;
|
||||||
|
String sortType = mCommentRecyclerViewAdapterCallback.getSortType();
|
||||||
FetchComment.fetchMoreComment(mExecutor, new Handler(), retrofit, mAccessToken,
|
FetchComment.fetchMoreComment(mExecutor, new Handler(), retrofit, mAccessToken,
|
||||||
parentComment.getMoreChildrenFullnames(),
|
parentComment.getMoreChildrenIds(),
|
||||||
parentComment.getMoreChildrenStartingIndex(), parentComment.getDepth() + 1,
|
mExpandChildren, mPost.getFullName(), sortType, new FetchComment.FetchMoreCommentListener() {
|
||||||
mExpandChildren, new FetchComment.FetchMoreCommentListener() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onFetchMoreCommentSuccess(ArrayList<Comment> expandedComments,
|
public void onFetchMoreCommentSuccess(ArrayList<Comment> expandedComments, ArrayList<String> moreChildrenIds) {
|
||||||
int childrenStartingIndex) {
|
|
||||||
if (mVisibleComments.size() > parentPosition
|
if (mVisibleComments.size() > parentPosition
|
||||||
&& parentComment.getFullName().equals(mVisibleComments.get(parentPosition).getFullName())) {
|
&& parentComment.getFullName().equals(mVisibleComments.get(parentPosition).getFullName())) {
|
||||||
if (mVisibleComments.get(parentPosition).isExpanded()) {
|
if (mVisibleComments.get(parentPosition).isExpanded()) {
|
||||||
if (mVisibleComments.get(parentPosition).getChildren().size() > childrenStartingIndex) {
|
if (!moreChildrenIds.isEmpty()) {
|
||||||
mVisibleComments.get(parentPosition).setMoreChildrenStartingIndex(childrenStartingIndex);
|
mVisibleComments.get(parentPosition).setMoreChildrenIds(moreChildrenIds);
|
||||||
mVisibleComments.get(parentPosition).getChildren().get(mVisibleComments.get(parentPosition).getChildren().size() - 1)
|
mVisibleComments.get(parentPosition).getChildren().get(mVisibleComments.get(parentPosition).getChildren().size() - 1)
|
||||||
.setLoadingMoreChildren(false);
|
.setLoadingMoreChildren(false);
|
||||||
mVisibleComments.get(parentPosition).getChildren().get(mVisibleComments.get(parentPosition).getChildren().size() - 1)
|
mVisibleComments.get(parentPosition).getChildren().get(mVisibleComments.get(parentPosition).getChildren().size() - 1)
|
||||||
@ -647,7 +646,7 @@ public class CommentsRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerVi
|
|||||||
} else {
|
} else {
|
||||||
mVisibleComments.get(parentPosition).getChildren()
|
mVisibleComments.get(parentPosition).getChildren()
|
||||||
.remove(mVisibleComments.get(parentPosition).getChildren().size() - 1);
|
.remove(mVisibleComments.get(parentPosition).getChildren().size() - 1);
|
||||||
mVisibleComments.get(parentPosition).removeMoreChildrenFullnames();
|
mVisibleComments.get(parentPosition).removeMoreChildrenIds();
|
||||||
|
|
||||||
int placeholderPosition = commentPosition;
|
int placeholderPosition = commentPosition;
|
||||||
if (mVisibleComments.get(commentPosition).getFullName().equals(parentComment.getFullName())) {
|
if (mVisibleComments.get(commentPosition).getFullName().equals(parentComment.getFullName())) {
|
||||||
@ -674,10 +673,10 @@ public class CommentsRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerVi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (mVisibleComments.get(parentPosition).hasReply() && mVisibleComments.get(parentPosition).getChildren().size() <= childrenStartingIndex) {
|
if (mVisibleComments.get(parentPosition).hasReply() && moreChildrenIds.isEmpty()) {
|
||||||
mVisibleComments.get(parentPosition).getChildren()
|
mVisibleComments.get(parentPosition).getChildren()
|
||||||
.remove(mVisibleComments.get(parentPosition).getChildren().size() - 1);
|
.remove(mVisibleComments.get(parentPosition).getChildren().size() - 1);
|
||||||
mVisibleComments.get(parentPosition).removeMoreChildrenFullnames();
|
mVisibleComments.get(parentPosition).removeMoreChildrenIds();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1157,6 +1156,8 @@ public class CommentsRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerVi
|
|||||||
void retryFetchingComments();
|
void retryFetchingComments();
|
||||||
|
|
||||||
void retryFetchingMoreComments();
|
void retryFetchingMoreComments();
|
||||||
|
|
||||||
|
String getSortType();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CommentViewHolder extends RecyclerView.ViewHolder {
|
public class CommentViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
@ -10,6 +10,7 @@ import retrofit2.Call;
|
|||||||
import retrofit2.Response;
|
import retrofit2.Response;
|
||||||
import retrofit2.http.Body;
|
import retrofit2.http.Body;
|
||||||
import retrofit2.http.DELETE;
|
import retrofit2.http.DELETE;
|
||||||
|
import retrofit2.http.Field;
|
||||||
import retrofit2.http.FieldMap;
|
import retrofit2.http.FieldMap;
|
||||||
import retrofit2.http.FormUrlEncoded;
|
import retrofit2.http.FormUrlEncoded;
|
||||||
import retrofit2.http.GET;
|
import retrofit2.http.GET;
|
||||||
@ -500,4 +501,12 @@ public interface RedditAPI {
|
|||||||
@FormUrlEncoded
|
@FormUrlEncoded
|
||||||
@POST("/api/site_admin")
|
@POST("/api/site_admin")
|
||||||
Call<String> postSiteAdmin(@HeaderMap Map<String, String> headers, @FieldMap Map<String, String> params);
|
Call<String> postSiteAdmin(@HeaderMap Map<String, String> headers, @FieldMap Map<String, String> params);
|
||||||
|
|
||||||
|
@FormUrlEncoded
|
||||||
|
@POST("/api/morechildren.json?raw_json=1&api_type=json")
|
||||||
|
Call<String> moreChildren(@Field("link_id") String linkId, @Field("children") String children, @Field("sort") String sort);
|
||||||
|
|
||||||
|
@FormUrlEncoded
|
||||||
|
@POST("/api/morechildren.json?raw_json=1&api_type=json")
|
||||||
|
Call<String> moreChildrenOauth(@Field("link_id") String linkId, @Field("children") String children, @Field("sort") String sort, @HeaderMap Map<String, String> headers);
|
||||||
}
|
}
|
||||||
|
@ -53,8 +53,7 @@ public class Comment implements Parcelable {
|
|||||||
private boolean isExpanded;
|
private boolean isExpanded;
|
||||||
private boolean hasExpandedBefore;
|
private boolean hasExpandedBefore;
|
||||||
private ArrayList<Comment> children;
|
private ArrayList<Comment> children;
|
||||||
private ArrayList<String> moreChildrenFullnames;
|
private ArrayList<String> moreChildrenIds;
|
||||||
private int moreChildrenStartingIndex;
|
|
||||||
private int placeholderType;
|
private int placeholderType;
|
||||||
private boolean isLoadingMoreChildren;
|
private boolean isLoadingMoreChildren;
|
||||||
private boolean loadMoreChildrenFailed;
|
private boolean loadMoreChildrenFailed;
|
||||||
@ -91,7 +90,6 @@ public class Comment implements Parcelable {
|
|||||||
this.saved = saved;
|
this.saved = saved;
|
||||||
this.isExpanded = false;
|
this.isExpanded = false;
|
||||||
this.hasExpandedBefore = false;
|
this.hasExpandedBefore = false;
|
||||||
moreChildrenStartingIndex = 0;
|
|
||||||
placeholderType = NOT_PLACEHOLDER;
|
placeholderType = NOT_PLACEHOLDER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,9 +139,8 @@ public class Comment implements Parcelable {
|
|||||||
hasExpandedBefore = in.readByte() != 0;
|
hasExpandedBefore = in.readByte() != 0;
|
||||||
children = new ArrayList<>();
|
children = new ArrayList<>();
|
||||||
in.readTypedList(children, Comment.CREATOR);
|
in.readTypedList(children, Comment.CREATOR);
|
||||||
moreChildrenFullnames = new ArrayList<>();
|
moreChildrenIds = new ArrayList<>();
|
||||||
in.readStringList(moreChildrenFullnames);
|
in.readStringList(moreChildrenIds);
|
||||||
moreChildrenStartingIndex = in.readInt();
|
|
||||||
placeholderType = in.readInt();
|
placeholderType = in.readInt();
|
||||||
isLoadingMoreChildren = in.readByte() != 0;
|
isLoadingMoreChildren = in.readByte() != 0;
|
||||||
loadMoreChildrenFailed = in.readByte() != 0;
|
loadMoreChildrenFailed = in.readByte() != 0;
|
||||||
@ -345,28 +342,20 @@ public class Comment implements Parcelable {
|
|||||||
children.add(position, comment);
|
children.add(position, comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<String> getMoreChildrenFullnames() {
|
public ArrayList<String> getMoreChildrenIds() {
|
||||||
return moreChildrenFullnames;
|
return moreChildrenIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMoreChildrenFullnames(ArrayList<String> moreChildrenFullnames) {
|
public void setMoreChildrenIds(ArrayList<String> moreChildrenIds) {
|
||||||
this.moreChildrenFullnames = moreChildrenFullnames;
|
this.moreChildrenIds = moreChildrenIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasMoreChildrenFullnames() {
|
public boolean hasMoreChildrenIds() {
|
||||||
return moreChildrenFullnames != null;
|
return moreChildrenIds != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeMoreChildrenFullnames() {
|
public void removeMoreChildrenIds() {
|
||||||
moreChildrenFullnames.clear();
|
moreChildrenIds.clear();
|
||||||
}
|
|
||||||
|
|
||||||
public int getMoreChildrenStartingIndex() {
|
|
||||||
return moreChildrenStartingIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMoreChildrenStartingIndex(int moreChildrenStartingIndex) {
|
|
||||||
this.moreChildrenStartingIndex = moreChildrenStartingIndex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getPlaceholderType() {
|
public int getPlaceholderType() {
|
||||||
@ -423,8 +412,7 @@ public class Comment implements Parcelable {
|
|||||||
parcel.writeByte((byte) (isExpanded ? 1 : 0));
|
parcel.writeByte((byte) (isExpanded ? 1 : 0));
|
||||||
parcel.writeByte((byte) (hasExpandedBefore ? 1 : 0));
|
parcel.writeByte((byte) (hasExpandedBefore ? 1 : 0));
|
||||||
parcel.writeTypedList(children);
|
parcel.writeTypedList(children);
|
||||||
parcel.writeStringList(moreChildrenFullnames);
|
parcel.writeStringList(moreChildrenIds);
|
||||||
parcel.writeInt(moreChildrenStartingIndex);
|
|
||||||
parcel.writeInt(placeholderType);
|
parcel.writeInt(placeholderType);
|
||||||
parcel.writeByte((byte) (isLoadingMoreChildren ? 1 : 0));
|
parcel.writeByte((byte) (isLoadingMoreChildren ? 1 : 0));
|
||||||
parcel.writeByte((byte) (loadMoreChildrenFailed ? 1 : 0));
|
parcel.writeByte((byte) (loadMoreChildrenFailed ? 1 : 0));
|
||||||
|
@ -46,9 +46,9 @@ public class FetchComment {
|
|||||||
expandChildren, new ParseComment.ParseCommentListener() {
|
expandChildren, new ParseComment.ParseCommentListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onParseCommentSuccess(ArrayList<Comment> expandedComments,
|
public void onParseCommentSuccess(ArrayList<Comment> expandedComments,
|
||||||
String parentId, ArrayList<String> moreChildrenFullnames) {
|
String parentId, ArrayList<String> moreChildrenIds) {
|
||||||
fetchCommentListener.onFetchCommentSuccess(expandedComments, parentId,
|
fetchCommentListener.onFetchCommentSuccess(expandedComments, parentId,
|
||||||
moreChildrenFullnames);
|
moreChildrenIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -70,33 +70,27 @@ public class FetchComment {
|
|||||||
|
|
||||||
public static void fetchMoreComment(Executor executor, Handler handler, Retrofit retrofit,
|
public static void fetchMoreComment(Executor executor, Handler handler, Retrofit retrofit,
|
||||||
@Nullable String accessToken,
|
@Nullable String accessToken,
|
||||||
ArrayList<String> allChildren, int startingIndex,
|
ArrayList<String> allChildren,
|
||||||
int depth, boolean expandChildren,
|
boolean expandChildren, String postFullName,
|
||||||
|
String sortType,
|
||||||
FetchMoreCommentListener fetchMoreCommentListener) {
|
FetchMoreCommentListener fetchMoreCommentListener) {
|
||||||
if (allChildren == null) {
|
if (allChildren == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
String childrenIds = String.join(",", allChildren);
|
||||||
for (int i = 0; i < 100; i++) {
|
|
||||||
if (allChildren.size() <= startingIndex + i) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
stringBuilder.append(allChildren.get(startingIndex + i)).append(",");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stringBuilder.length() == 0) {
|
if (childrenIds.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
|
|
||||||
|
|
||||||
RedditAPI api = retrofit.create(RedditAPI.class);
|
RedditAPI api = retrofit.create(RedditAPI.class);
|
||||||
Call<String> moreComments;
|
Call<String> moreComments;
|
||||||
if (accessToken == null) {
|
if (accessToken == null) {
|
||||||
moreComments = api.getInfo(stringBuilder.toString());
|
moreComments = api.moreChildren(postFullName, childrenIds, sortType);
|
||||||
} else {
|
} else {
|
||||||
moreComments = api.getInfoOauth(stringBuilder.toString(), APIUtils.getOAuthHeader(accessToken));
|
moreComments = api.moreChildrenOauth(postFullName, childrenIds,
|
||||||
|
sortType, APIUtils.getOAuthHeader(accessToken));
|
||||||
}
|
}
|
||||||
|
|
||||||
moreComments.enqueue(new Callback<String>() {
|
moreComments.enqueue(new Callback<String>() {
|
||||||
@ -104,12 +98,11 @@ public 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.parseMoreComment(executor, handler, response.body(), new ArrayList<>(),
|
ParseComment.parseMoreComment(executor, handler, response.body(), new ArrayList<>(),
|
||||||
depth, expandChildren, new ParseComment.ParseCommentListener() {
|
expandChildren, new ParseComment.ParseCommentListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onParseCommentSuccess(ArrayList<Comment> expandedComments,
|
public void onParseCommentSuccess(ArrayList<Comment> expandedComments,
|
||||||
String parentId, ArrayList<String> moreChildrenFullnames) {
|
String parentId, ArrayList<String> moreChildrenIds) {
|
||||||
fetchMoreCommentListener.onFetchMoreCommentSuccess(expandedComments,
|
fetchMoreCommentListener.onFetchMoreCommentSuccess(expandedComments, moreChildrenIds);
|
||||||
startingIndex + 100);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -136,7 +129,7 @@ public class FetchComment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public interface FetchMoreCommentListener {
|
public interface FetchMoreCommentListener {
|
||||||
void onFetchMoreCommentSuccess(ArrayList<Comment> expandedComments, int childrenStartingIndex);
|
void onFetchMoreCommentSuccess(ArrayList<Comment> expandedComments, ArrayList<String> moreChildrenIds);
|
||||||
|
|
||||||
void onFetchMoreCommentFailed();
|
void onFetchMoreCommentFailed();
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,9 @@ import static ml.docilealligator.infinityforreddit.comment.Comment.VOTE_TYPE_UPV
|
|||||||
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
@ -14,6 +16,7 @@ import org.json.JSONException;
|
|||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
import ml.docilealligator.infinityforreddit.utils.JSONUtils;
|
import ml.docilealligator.infinityforreddit.utils.JSONUtils;
|
||||||
@ -31,10 +34,10 @@ public class ParseComment {
|
|||||||
childrenArray = childrenArray.getJSONObject(1).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY);
|
childrenArray = childrenArray.getJSONObject(1).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY);
|
||||||
|
|
||||||
ArrayList<Comment> expandedNewComments = new ArrayList<>();
|
ArrayList<Comment> expandedNewComments = new ArrayList<>();
|
||||||
ArrayList<String> moreChildrenFullnames = new ArrayList<>();
|
ArrayList<String> moreChildrenIds = new ArrayList<>();
|
||||||
ArrayList<Comment> newComments = new ArrayList<>();
|
ArrayList<Comment> newComments = new ArrayList<>();
|
||||||
|
|
||||||
parseCommentRecursion(childrenArray, newComments, moreChildrenFullnames, 0);
|
parseCommentRecursion(childrenArray, newComments, moreChildrenIds, 0);
|
||||||
expandChildren(newComments, expandedNewComments, expandChildren);
|
expandChildren(newComments, expandedNewComments, expandChildren);
|
||||||
|
|
||||||
if (expandChildren) {
|
if (expandChildren) {
|
||||||
@ -43,7 +46,7 @@ public class ParseComment {
|
|||||||
commentData.addAll(newComments);
|
commentData.addAll(newComments);
|
||||||
}
|
}
|
||||||
|
|
||||||
handler.post(() -> parseCommentListener.onParseCommentSuccess(commentData, parentId, moreChildrenFullnames));
|
handler.post(() -> parseCommentListener.onParseCommentSuccess(commentData, parentId, moreChildrenIds));
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
handler.post(parseCommentListener::onParseCommentFailed);
|
handler.post(parseCommentListener::onParseCommentFailed);
|
||||||
@ -52,17 +55,75 @@ public class ParseComment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void parseMoreComment(Executor executor, Handler handler, String response,
|
static void parseMoreComment(Executor executor, Handler handler, String response,
|
||||||
ArrayList<Comment> commentData, int depth, boolean expandChildren,
|
ArrayList<Comment> commentData, boolean expandChildren,
|
||||||
ParseCommentListener parseCommentListener) {
|
ParseCommentListener parseCommentListener) {
|
||||||
executor.execute(() -> {
|
executor.execute(() -> {
|
||||||
try {
|
try {
|
||||||
JSONArray childrenArray = new JSONObject(response).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY);
|
JSONArray childrenArray = new JSONObject(response).getJSONObject(JSONUtils.JSON_KEY)
|
||||||
|
.getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.THINGS_KEY);
|
||||||
|
|
||||||
ArrayList<Comment> newComments = new ArrayList<>();
|
ArrayList<Comment> newComments = new ArrayList<>();
|
||||||
ArrayList<Comment> expandedNewComments = new ArrayList<>();
|
ArrayList<Comment> expandedNewComments = new ArrayList<>();
|
||||||
ArrayList<String> moreChildrenFullnames = new ArrayList<>();
|
ArrayList<String> moreChildrenIds = new ArrayList<>();
|
||||||
|
|
||||||
parseCommentRecursion(childrenArray, newComments, moreChildrenFullnames, depth);
|
// api response is a flat list of comments tree
|
||||||
|
// process it in order and rebuild the tree
|
||||||
|
for (int i = 0; i < childrenArray.length(); i++) {
|
||||||
|
JSONObject child = childrenArray.getJSONObject(i);
|
||||||
|
JSONObject childData = child.getJSONObject(JSONUtils.DATA_KEY);
|
||||||
|
if (child.getString(JSONUtils.KIND_KEY).equals(JSONUtils.KIND_VALUE_MORE)) {
|
||||||
|
String parentFullName = childData.getString(JSONUtils.PARENT_ID_KEY);
|
||||||
|
JSONArray childrenIds = childData.getJSONArray(JSONUtils.CHILDREN_KEY);
|
||||||
|
|
||||||
|
if (childrenIds.length() != 0) {
|
||||||
|
ArrayList<String> localMoreChildrenIds = new ArrayList<>(childrenIds.length());
|
||||||
|
for (int j = 0; j < childrenIds.length(); j++) {
|
||||||
|
localMoreChildrenIds.add(childrenIds.getString(j));
|
||||||
|
}
|
||||||
|
|
||||||
|
Comment parentComment = findCommentByFullName(newComments, parentFullName);
|
||||||
|
if (parentComment != null) {
|
||||||
|
parentComment.setHasReply(true);
|
||||||
|
parentComment.setMoreChildrenIds(localMoreChildrenIds);
|
||||||
|
parentComment.addChildren(new ArrayList<>()); // ensure children list is not null
|
||||||
|
} else {
|
||||||
|
// assume that it is parent of this call
|
||||||
|
moreChildrenIds.addAll(localMoreChildrenIds);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Comment continueThreadPlaceholder = new Comment(
|
||||||
|
parentFullName,
|
||||||
|
childData.getInt(JSONUtils.DEPTH_KEY),
|
||||||
|
Comment.PLACEHOLDER_CONTINUE_THREAD
|
||||||
|
);
|
||||||
|
|
||||||
|
Comment parentComment = findCommentByFullName(newComments, parentFullName);
|
||||||
|
if (parentComment != null) {
|
||||||
|
parentComment.setHasReply(true);
|
||||||
|
parentComment.addChild(continueThreadPlaceholder, parentComment.getChildCount());
|
||||||
|
parentComment.setChildCount(parentComment.getChildCount() + 1);
|
||||||
|
} else {
|
||||||
|
// assume that it is parent of this call
|
||||||
|
newComments.add(continueThreadPlaceholder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Comment comment = parseSingleComment(childData, 0);
|
||||||
|
String parentFullName = comment.getParentId();
|
||||||
|
|
||||||
|
Comment parentComment = findCommentByFullName(newComments, parentFullName);
|
||||||
|
if (parentComment != null) {
|
||||||
|
parentComment.setHasReply(true);
|
||||||
|
parentComment.addChild(comment, parentComment.getChildCount());
|
||||||
|
parentComment.setChildCount(parentComment.getChildCount() + 1);
|
||||||
|
} else {
|
||||||
|
// assume that it is parent of this call
|
||||||
|
newComments.add(comment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateChildrenCount(newComments);
|
||||||
expandChildren(newComments, expandedNewComments, expandChildren);
|
expandChildren(newComments, expandedNewComments, expandChildren);
|
||||||
|
|
||||||
if (expandChildren) {
|
if (expandChildren) {
|
||||||
@ -71,7 +132,7 @@ public class ParseComment {
|
|||||||
commentData.addAll(newComments);
|
commentData.addAll(newComments);
|
||||||
}
|
}
|
||||||
|
|
||||||
handler.post(() -> parseCommentListener.onParseCommentSuccess(commentData, null, moreChildrenFullnames));
|
handler.post(() -> parseCommentListener.onParseCommentSuccess(commentData, null, moreChildrenIds));
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
handler.post(parseCommentListener::onParseCommentFailed);
|
handler.post(parseCommentListener::onParseCommentFailed);
|
||||||
@ -96,7 +157,7 @@ public class ParseComment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void parseCommentRecursion(JSONArray comments, ArrayList<Comment> newCommentData,
|
private static void parseCommentRecursion(JSONArray comments, ArrayList<Comment> newCommentData,
|
||||||
ArrayList<String> moreChildrenFullnames, int depth) throws JSONException {
|
ArrayList<String> moreChildrenIds, int depth) throws JSONException {
|
||||||
int actualCommentLength;
|
int actualCommentLength;
|
||||||
|
|
||||||
if (comments.length() == 0) {
|
if (comments.length() == 0) {
|
||||||
@ -105,17 +166,17 @@ public 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 moreChildrenFullnames contain only commentsJSONArray and no more info
|
//Maybe moreChildrenIds contain only commentsJSONArray 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++) {
|
||||||
moreChildrenFullnames.add("t1_" + childrenArray.getString(i));
|
moreChildrenIds.add(childrenArray.getString(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
actualCommentLength = comments.length() - 1;
|
actualCommentLength = comments.length() - 1;
|
||||||
|
|
||||||
if (moreChildrenFullnames.isEmpty() && comments.getJSONObject(comments.length() - 1).getString(JSONUtils.KIND_KEY).equals(JSONUtils.KIND_VALUE_MORE)) {
|
if (moreChildrenIds.isEmpty() && comments.getJSONObject(comments.length() - 1).getString(JSONUtils.KIND_KEY).equals(JSONUtils.KIND_VALUE_MORE)) {
|
||||||
newCommentData.add(new Comment(more.getString(JSONUtils.PARENT_ID_KEY), more.getInt(JSONUtils.DEPTH_KEY), Comment.PLACEHOLDER_CONTINUE_THREAD));
|
newCommentData.add(new Comment(more.getString(JSONUtils.PARENT_ID_KEY), more.getInt(JSONUtils.DEPTH_KEY), Comment.PLACEHOLDER_CONTINUE_THREAD));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -131,10 +192,10 @@ public class ParseComment {
|
|||||||
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<Comment> children = new ArrayList<>();
|
ArrayList<Comment> children = new ArrayList<>();
|
||||||
ArrayList<String> nextMoreChildrenFullnames = new ArrayList<>();
|
ArrayList<String> nextMoreChildrenIds = new ArrayList<>();
|
||||||
parseCommentRecursion(childrenArray, children, nextMoreChildrenFullnames, singleComment.getDepth());
|
parseCommentRecursion(childrenArray, children, nextMoreChildrenIds, singleComment.getDepth());
|
||||||
singleComment.addChildren(children);
|
singleComment.addChildren(children);
|
||||||
singleComment.setMoreChildrenFullnames(nextMoreChildrenFullnames);
|
singleComment.setMoreChildrenIds(nextMoreChildrenIds);
|
||||||
singleComment.setChildCount(getChildCount(singleComment));
|
singleComment.setChildCount(getChildCount(singleComment));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,7 +226,7 @@ public class ParseComment {
|
|||||||
} else {
|
} else {
|
||||||
c.setExpanded(true);
|
c.setExpanded(true);
|
||||||
}
|
}
|
||||||
if (c.hasMoreChildrenFullnames() && c.getMoreChildrenFullnames().size() > c.getMoreChildrenStartingIndex()) {
|
if (c.hasMoreChildrenIds() && !c.getMoreChildrenIds().isEmpty()) {
|
||||||
//Add a load more placeholder
|
//Add a load more placeholder
|
||||||
Comment placeholder = new Comment(c.getFullName(), c.getDepth() + 1, Comment.PLACEHOLDER_LOAD_MORE_COMMENTS);
|
Comment placeholder = new Comment(c.getFullName(), c.getDepth() + 1, Comment.PLACEHOLDER_LOAD_MORE_COMMENTS);
|
||||||
visibleComments.add(placeholder);
|
visibleComments.add(placeholder);
|
||||||
@ -277,9 +338,35 @@ public class ParseComment {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static Comment findCommentByFullName(@NonNull List<Comment> comments, @NonNull String fullName) {
|
||||||
|
for (Comment comment: comments) {
|
||||||
|
if (comment.getFullName().equals(fullName) &&
|
||||||
|
comment.getPlaceholderType() == Comment.NOT_PLACEHOLDER) {
|
||||||
|
return comment;
|
||||||
|
}
|
||||||
|
if (comment.getChildren() != null) {
|
||||||
|
Comment result = findCommentByFullName(comment.getChildren(), fullName);
|
||||||
|
if (result != null) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void updateChildrenCount(@NonNull List<Comment> comments) {
|
||||||
|
for (Comment comment: comments) {
|
||||||
|
comment.setChildCount(getChildCount(comment));
|
||||||
|
if (comment.getChildren() != null) {
|
||||||
|
updateChildrenCount(comment.getChildren());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public interface ParseCommentListener {
|
public interface ParseCommentListener {
|
||||||
void onParseCommentSuccess(ArrayList<Comment> expandedComments, String parentId,
|
void onParseCommentSuccess(ArrayList<Comment> expandedComments, String parentId,
|
||||||
ArrayList<String> moreChildrenFullnames);
|
ArrayList<String> moreChildrenIds);
|
||||||
|
|
||||||
void onParseCommentFailed();
|
void onParseCommentFailed();
|
||||||
}
|
}
|
||||||
|
@ -202,8 +202,6 @@ public class ViewPostDetailFragment extends Fragment implements FragmentCommunic
|
|||||||
@State
|
@State
|
||||||
ArrayList<String> children;
|
ArrayList<String> children;
|
||||||
@State
|
@State
|
||||||
int mChildrenStartingIndex = 0;
|
|
||||||
@State
|
|
||||||
boolean loadMoreChildrenSuccess = true;
|
boolean loadMoreChildrenSuccess = true;
|
||||||
@State
|
@State
|
||||||
boolean hasMoreChildren;
|
boolean hasMoreChildren;
|
||||||
@ -621,6 +619,11 @@ public class ViewPostDetailFragment extends Fragment implements FragmentCommunic
|
|||||||
|
|
||||||
fetchMoreComments();
|
fetchMoreComments();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSortType() {
|
||||||
|
return sortType;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
if (mCommentsRecyclerView != null) {
|
if (mCommentsRecyclerView != null) {
|
||||||
mRecyclerView.setAdapter(mPostAdapter);
|
mRecyclerView.setAdapter(mPostAdapter);
|
||||||
@ -810,7 +813,6 @@ public class ViewPostDetailFragment extends Fragment implements FragmentCommunic
|
|||||||
public void changeSortType(SortType sortType) {
|
public void changeSortType(SortType sortType) {
|
||||||
mFetchPostInfoLinearLayout.setVisibility(View.GONE);
|
mFetchPostInfoLinearLayout.setVisibility(View.GONE);
|
||||||
mGlide.clear(mFetchPostInfoImageView);
|
mGlide.clear(mFetchPostInfoImageView);
|
||||||
mChildrenStartingIndex = 0;
|
|
||||||
if (children != null) {
|
if (children != null) {
|
||||||
children.clear();
|
children.clear();
|
||||||
}
|
}
|
||||||
@ -1328,6 +1330,11 @@ public class ViewPostDetailFragment extends Fragment implements FragmentCommunic
|
|||||||
|
|
||||||
fetchMoreComments();
|
fetchMoreComments();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSortType() {
|
||||||
|
return sortType;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
if (mCommentsRecyclerView != null) {
|
if (mCommentsRecyclerView != null) {
|
||||||
mRecyclerView.setAdapter(mPostAdapter);
|
mRecyclerView.setAdapter(mPostAdapter);
|
||||||
@ -1343,8 +1350,8 @@ public class ViewPostDetailFragment extends Fragment implements FragmentCommunic
|
|||||||
ParseComment.parseComment(mExecutor, new Handler(), response.body(), new ArrayList<>(),
|
ParseComment.parseComment(mExecutor, new Handler(), response.body(), new ArrayList<>(),
|
||||||
mExpandChildren, new ParseComment.ParseCommentListener() {
|
mExpandChildren, new ParseComment.ParseCommentListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onParseCommentSuccess(ArrayList<Comment> expandedComments, String parentId, ArrayList<String> moreChildrenFullnames) {
|
public void onParseCommentSuccess(ArrayList<Comment> expandedComments, String parentId, ArrayList<String> moreChildrenIds) {
|
||||||
ViewPostDetailFragment.this.children = moreChildrenFullnames;
|
ViewPostDetailFragment.this.children = moreChildrenIds;
|
||||||
|
|
||||||
hasMoreChildren = children.size() != 0;
|
hasMoreChildren = children.size() != 0;
|
||||||
mCommentsAdapter.addComments(expandedComments, hasMoreChildren);
|
mCommentsAdapter.addComments(expandedComments, hasMoreChildren);
|
||||||
@ -1567,13 +1574,13 @@ public class ViewPostDetailFragment extends Fragment implements FragmentCommunic
|
|||||||
isLoadingMoreChildren = true;
|
isLoadingMoreChildren = true;
|
||||||
|
|
||||||
Retrofit retrofit = mAccessToken == null ? mRetrofit : mOauthRetrofit;
|
Retrofit retrofit = mAccessToken == null ? mRetrofit : mOauthRetrofit;
|
||||||
FetchComment.fetchMoreComment(mExecutor, new Handler(), retrofit, mAccessToken, children, mChildrenStartingIndex,
|
FetchComment.fetchMoreComment(mExecutor, new Handler(), retrofit, mAccessToken, children,
|
||||||
0, mExpandChildren, new FetchComment.FetchMoreCommentListener() {
|
mExpandChildren, mPost.getFullName(), sortType, new FetchComment.FetchMoreCommentListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onFetchMoreCommentSuccess(ArrayList<Comment> expandedComments, int childrenStartingIndex) {
|
public void onFetchMoreCommentSuccess(ArrayList<Comment> expandedComments, ArrayList<String> moreChildrenIds) {
|
||||||
hasMoreChildren = childrenStartingIndex < children.size();
|
children = moreChildrenIds;
|
||||||
|
hasMoreChildren = !children.isEmpty();
|
||||||
mCommentsAdapter.addComments(expandedComments, hasMoreChildren);
|
mCommentsAdapter.addComments(expandedComments, hasMoreChildren);
|
||||||
mChildrenStartingIndex = childrenStartingIndex;
|
|
||||||
isLoadingMoreChildren = false;
|
isLoadingMoreChildren = false;
|
||||||
loadMoreChildrenSuccess = true;
|
loadMoreChildrenSuccess = true;
|
||||||
}
|
}
|
||||||
@ -1590,7 +1597,6 @@ public class ViewPostDetailFragment extends Fragment implements FragmentCommunic
|
|||||||
public void refresh(boolean fetchPost, boolean fetchComments) {
|
public void refresh(boolean fetchPost, boolean fetchComments) {
|
||||||
if (mPostAdapter != null && !isRefreshing) {
|
if (mPostAdapter != null && !isRefreshing) {
|
||||||
isRefreshing = true;
|
isRefreshing = true;
|
||||||
mChildrenStartingIndex = 0;
|
|
||||||
|
|
||||||
mFetchPostInfoLinearLayout.setVisibility(View.GONE);
|
mFetchPostInfoLinearLayout.setVisibility(View.GONE);
|
||||||
mGlide.clear(mFetchPostInfoImageView);
|
mGlide.clear(mFetchPostInfoImageView);
|
||||||
|
Loading…
Reference in New Issue
Block a user