aboutsummaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorAlex Ning <chineseperson5@gmail.com>2019-06-25 01:21:44 +0000
committerAlex Ning <chineseperson5@gmail.com>2019-06-25 01:21:44 +0000
commitc4690a6e38004fa0442e6c15b9637ee209e9c2dd (patch)
tree4434cae708a07cb04eaa597a82312c45c410e780 /app
parent34d49d884c5fc639204d0e464455e0d898a987e4 (diff)
downloadinfinity-for-reddit-c4690a6e38004fa0442e6c15b9637ee209e9c2dd.tar
infinity-for-reddit-c4690a6e38004fa0442e6c15b9637ee209e9c2dd.tar.gz
infinity-for-reddit-c4690a6e38004fa0442e6c15b9637ee209e9c2dd.tar.bz2
infinity-for-reddit-c4690a6e38004fa0442e6c15b9637ee209e9c2dd.tar.lz
infinity-for-reddit-c4690a6e38004fa0442e6c15b9637ee209e9c2dd.tar.xz
infinity-for-reddit-c4690a6e38004fa0442e6c15b9637ee209e9c2dd.tar.zst
infinity-for-reddit-c4690a6e38004fa0442e6c15b9637ee209e9c2dd.zip
Reimplement ViewPostActivity using one recyclerview to display a post and its comments instead of using a recyclerview inside NestedScrollView to prevent onBindViewHolder gets called for all the comments data at once and thus consumes more memory and freezes after the comments are loaded.
Diffstat (limited to 'app')
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/CommentRecyclerViewAdapter.java644
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java2
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/LoadSubredditIconAsyncTask.java4
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java2
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/ViewPostDetailActivity.java499
-rw-r--r--app/src/main/res/drawable/no_comment_placeholder.png (renamed from app/src/main/res/drawable/no_comment_indicator.png)bin60561 -> 60561 bytes
-rw-r--r--app/src/main/res/layout/activity_view_post_detail.xml335
-rw-r--r--app/src/main/res/layout/item_load_comments.xml19
-rw-r--r--app/src/main/res/layout/item_load_comments_failed_placeholder.xml8
-rw-r--r--app/src/main/res/layout/item_no_comment_placeholder.xml8
-rw-r--r--app/src/main/res/layout/item_post_detail.xml252
11 files changed, 927 insertions, 846 deletions
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentRecyclerViewAdapter.java
index d2b34ecd..d987a6b7 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentRecyclerViewAdapter.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentRecyclerViewAdapter.java
@@ -3,55 +3,113 @@ package ml.docilealligator.infinityforreddit;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.graphics.ColorFilter;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ProgressBar;
+import android.widget.RelativeLayout;
import android.widget.TextView;
+import android.widget.Toast;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.browser.customtabs.CustomTabsIntent;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
+import com.bumptech.glide.RequestBuilder;
+import com.bumptech.glide.RequestManager;
+import com.bumptech.glide.load.DataSource;
+import com.bumptech.glide.load.engine.GlideException;
+import com.bumptech.glide.request.RequestListener;
+import com.bumptech.glide.request.RequestOptions;
+import com.bumptech.glide.request.target.Target;
+import com.google.android.material.chip.Chip;
+import com.santalu.aspectratioimageview.AspectRatioImageView;
+
import java.util.ArrayList;
import java.util.Locale;
+import CustomView.AspectRatioGifImageView;
+import SubredditDatabase.SubredditRoomDatabase;
import butterknife.BindView;
import butterknife.ButterKnife;
+import jp.wasabeef.glide.transformations.BlurTransformation;
+import jp.wasabeef.glide.transformations.RoundedCornersTransformation;
import retrofit2.Retrofit;
import ru.noties.markwon.SpannableConfiguration;
import ru.noties.markwon.view.MarkwonView;
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_POST_DETAIL = 0;
+ private static final int VIEW_TYPE_FIRST_LOADING = 1;
+ private static final int VIEW_TYPE_FIRST_LOADING_FAILED = 2;
+ private static final int VIEW_TYPE_NO_COMMENT_PLACEHOLDER = 3;
+ private static final int VIEW_TYPE_COMMENT = 4;
+ private static final int VIEW_TYPE_LOAD_MORE_COMMENT = 5;
private Activity mActivity;
private Retrofit mRetrofit;
private Retrofit mOauthRetrofit;
+ private RequestManager mGlide;
private SharedPreferences mSharedPreferences;
+ private Post mPost;
+ private ArrayList<CommentData> mVisibleComments;
private String mSubredditNamePrefixed;
private Locale mLocale;
+ private UpdatePostInPostFragmentCallback mUpdatePostInPostFragmentCallback;
+ private LoadSubredditIconAsyncTask mLoadSubredditIconAsyncTask;
+ private boolean isInitiallyLoading;
+ private boolean isInitiallyLoadingFailed;
- private ArrayList<CommentData> mVisibleComments;
+ interface UpdatePostInPostFragmentCallback {
+ void updatePost(Post post);
+ }
- CommentRecyclerViewAdapter(Activity activity, Retrofit retrofit, Retrofit oauthRetrofit,
- SharedPreferences sharedPreferences, ArrayList<CommentData> expandedComments,
- String subredditNamePrefixed, Locale locale) {
+ CommentRecyclerViewAdapter(Activity activity, Retrofit retrofit, Retrofit oauthRetrofit, RequestManager glide,
+ SharedPreferences sharedPreferences, Post post, String subredditNamePrefixed,
+ Locale locale, LoadSubredditIconAsyncTask loadSubredditIconAsyncTask,
+ UpdatePostInPostFragmentCallback updatePostInPostFragmentCallback) {
mActivity = activity;
mRetrofit = retrofit;
mOauthRetrofit = oauthRetrofit;
+ mGlide = glide;
mSharedPreferences = sharedPreferences;
+ mPost = post;
+ mVisibleComments = new ArrayList<>();
mSubredditNamePrefixed = subredditNamePrefixed;
mLocale = locale;
- mVisibleComments = expandedComments;
+ mLoadSubredditIconAsyncTask = loadSubredditIconAsyncTask;
+ mUpdatePostInPostFragmentCallback = updatePostInPostFragmentCallback;
+ isInitiallyLoading = true;
+ isInitiallyLoadingFailed = false;
}
@Override
public int getItemViewType(int position) {
- CommentData comment = mVisibleComments.get(position);
+ if(position == 0) {
+ return VIEW_TYPE_POST_DETAIL;
+ }
+
+ if(mVisibleComments.size() == 0) {
+ if(position == 1) {
+ if(isInitiallyLoading) {
+ return VIEW_TYPE_FIRST_LOADING;
+ } else if(isInitiallyLoadingFailed) {
+ return VIEW_TYPE_FIRST_LOADING_FAILED;
+ } else {
+ return VIEW_TYPE_NO_COMMENT_PLACEHOLDER;
+ }
+ }
+ }
+
+ CommentData comment = mVisibleComments.get(position - 1);
if(!comment.isPlaceHolder()) {
return VIEW_TYPE_COMMENT;
} else {
@@ -62,7 +120,15 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
- if(viewType == VIEW_TYPE_COMMENT) {
+ if(viewType == VIEW_TYPE_POST_DETAIL) {
+ return new PostDetailViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_post_detail, parent, false));
+ } else if(viewType == VIEW_TYPE_FIRST_LOADING) {
+ return new LoadCommentsViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_load_comments, parent, false));
+ } else if(viewType == VIEW_TYPE_FIRST_LOADING_FAILED) {
+ return new LoadCommentsFailedViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_load_comments_failed_placeholder, parent, false));
+ } else if(viewType == VIEW_TYPE_NO_COMMENT_PLACEHOLDER) {
+ return new NoCommentViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_no_comment_placeholder, parent, false));
+ } else if(viewType == VIEW_TYPE_COMMENT) {
return new CommentViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_comment, parent, false));
} else {
return new LoadMoreCommentViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_load_more_comments_placeholder, parent, false));
@@ -71,8 +137,196 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
- if(holder.getItemViewType() == VIEW_TYPE_COMMENT) {
- CommentData commentItem = mVisibleComments.get(holder.getAdapterPosition());
+ if(holder.getItemViewType() == VIEW_TYPE_POST_DETAIL) {
+ ((PostDetailViewHolder) holder).mTitleTextView.setText(mPost.getTitle());
+
+ if(mPost.getSubredditIconUrl() == null) {
+ if(mLoadSubredditIconAsyncTask != null) {
+ mLoadSubredditIconAsyncTask.cancel(true);
+ } else {
+ mLoadSubredditIconAsyncTask = new LoadSubredditIconAsyncTask(
+ SubredditRoomDatabase.getDatabase(mActivity).subredditDao(), mPost.getSubredditNamePrefixed().substring(2),
+ iconImageUrl -> {
+ if(!iconImageUrl.equals("")) {
+ mGlide.load(iconImageUrl)
+ .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))
+ .error(mGlide.load(R.drawable.subreddit_default_icon)
+ .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))))
+ .into(((PostDetailViewHolder) holder).mSubredditIconGifImageView);
+ } else {
+ mGlide.load(R.drawable.subreddit_default_icon)
+ .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))
+ .into(((PostDetailViewHolder) holder).mSubredditIconGifImageView);
+ }
+
+ mPost.setSubredditIconUrl(iconImageUrl);
+ });
+ }
+
+ mLoadSubredditIconAsyncTask.execute();
+ } else if(!mPost.getSubredditIconUrl().equals("")) {
+ mGlide.load(mPost.getSubredditIconUrl())
+ .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))
+ .error(mGlide.load(R.drawable.subreddit_default_icon)
+ .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))))
+ .into(((PostDetailViewHolder) holder).mSubredditIconGifImageView);
+ } else {
+ mGlide.load(R.drawable.subreddit_default_icon)
+ .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))
+ .into(((PostDetailViewHolder) holder).mSubredditIconGifImageView);
+ }
+
+ switch (mPost.getVoteType()) {
+ case 1:
+ //Upvote
+ ((PostDetailViewHolder) holder).mUpvoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.backgroundColorPrimaryDark), PorterDuff.Mode.SRC_IN);
+ break;
+ case -1:
+ //Downvote
+ ((PostDetailViewHolder) holder).mDownvoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.minusButtonColor), PorterDuff.Mode.SRC_IN);
+ break;
+ case 0:
+ ((PostDetailViewHolder) holder).mUpvoteButton.clearColorFilter();
+ ((PostDetailViewHolder) holder).mDownvoteButton.clearColorFilter();
+ }
+
+ if(mPost.getPostType() != Post.TEXT_TYPE && mPost.getPostType() != Post.NO_PREVIEW_LINK_TYPE) {
+ ((PostDetailViewHolder) holder).mRelativeLayout.setVisibility(View.VISIBLE);
+ ((PostDetailViewHolder) holder).mImageView.setVisibility(View.VISIBLE);
+ ((PostDetailViewHolder) holder).mImageView.setRatio((float) mPost.getPreviewHeight() / (float) mPost.getPreviewWidth());
+ loadImage((PostDetailViewHolder) holder);
+ } else {
+ ((PostDetailViewHolder) holder).mRelativeLayout.setVisibility(View.GONE);
+ ((PostDetailViewHolder) holder).mImageView.setVisibility(View.GONE);
+ }
+
+ if(mPost.isCrosspost()) {
+ ((PostDetailViewHolder) holder).mCrosspostImageView.setVisibility(View.VISIBLE);
+ }
+
+ ((PostDetailViewHolder) holder).mSubredditTextView.setText(mPost.getSubredditNamePrefixed());
+
+ ((PostDetailViewHolder) holder).mPostTimeTextView.setText(mPost.getPostTime());
+
+ if(mPost.getGilded() > 0) {
+ ((PostDetailViewHolder) holder).mGildedImageView.setVisibility(View.VISIBLE);
+ mGlide.load(R.drawable.gold).into(((PostDetailViewHolder) holder).mGildedImageView);
+ ((PostDetailViewHolder) holder).mGildedNumberTextView.setVisibility(View.VISIBLE);
+ String gildedNumber = mActivity.getResources().getString(R.string.gilded, mPost.getGilded());
+ ((PostDetailViewHolder) holder).mGildedNumberTextView.setText(gildedNumber);
+ }
+
+ if(mPost.isNSFW()) {
+ ((PostDetailViewHolder) holder).mNSFWChip.setVisibility(View.VISIBLE);
+ } else {
+ ((PostDetailViewHolder) holder).mNSFWChip.setVisibility(View.GONE);
+ }
+
+ String scoreWithVote = Integer.toString(mPost.getScore() + mPost.getVoteType());
+ ((PostDetailViewHolder) holder).mScoreTextView.setText(scoreWithVote);
+
+ switch (mPost.getPostType()) {
+ case Post.IMAGE_TYPE:
+ ((PostDetailViewHolder) holder).mTypeChip.setText("IMAGE");
+
+ ((PostDetailViewHolder) holder).mImageView.setOnClickListener(view -> {
+ Intent intent = new Intent(mActivity, ViewImageActivity.class);
+ intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, mPost.getUrl());
+ intent.putExtra(ViewImageActivity.TITLE_KEY, mPost.getTitle());
+ intent.putExtra(ViewImageActivity.FILE_NAME_KEY, mPost.getSubredditNamePrefixed().substring(2)
+ + "-" + mPost.getId().substring(3));
+ mActivity.startActivity(intent);
+ });
+ break;
+ case Post.LINK_TYPE:
+ ((PostDetailViewHolder) holder).mTypeChip.setText("LINK");
+
+ ((PostDetailViewHolder) holder).linkTextView.setVisibility(View.VISIBLE);
+ String domain = Uri.parse(mPost.getUrl()).getHost();
+ ((PostDetailViewHolder) holder).linkTextView.setText(domain);
+
+ ((PostDetailViewHolder) holder).mImageView.setOnClickListener(view -> {
+ 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(mPost.getUrl()));
+ });
+ break;
+ case Post.GIF_VIDEO_TYPE:
+ ((PostDetailViewHolder) holder).mTypeChip.setText("GIF");
+
+ final Uri gifVideoUri = Uri.parse(mPost.getVideoUrl());
+ ((PostDetailViewHolder) holder).mImageView.setOnClickListener(view -> {
+ Intent intent = new Intent(mActivity, ViewVideoActivity.class);
+ intent.setData(gifVideoUri);
+ intent.putExtra(ViewVideoActivity.TITLE_KEY, mPost.getTitle());
+ intent.putExtra(ViewVideoActivity.IS_DASH_VIDEO_KEY, mPost.isDashVideo());
+ intent.putExtra(ViewVideoActivity.IS_DOWNLOADABLE_KEY, mPost.isDownloadableGifOrVideo());
+ if(mPost.isDownloadableGifOrVideo()) {
+ intent.putExtra(ViewVideoActivity.DOWNLOAD_URL_KEY, mPost.getGifOrVideoDownloadUrl());
+ intent.putExtra(ViewVideoActivity.SUBREDDIT_KEY, mPost.getSubredditNamePrefixed());
+ intent.putExtra(ViewVideoActivity.ID_KEY, mPost.getId());
+ }
+ mActivity.startActivity(intent);
+ });
+ break;
+ case Post.VIDEO_TYPE:
+ ((PostDetailViewHolder) holder).mTypeChip.setText("VIDEO");
+
+ final Uri videoUri = Uri.parse(mPost.getVideoUrl());
+ ((PostDetailViewHolder) holder).mImageView.setOnClickListener(view -> {
+ Intent intent = new Intent(mActivity, ViewVideoActivity.class);
+ intent.setData(videoUri);
+ intent.putExtra(ViewVideoActivity.TITLE_KEY, mPost.getTitle());
+ intent.putExtra(ViewVideoActivity.IS_DASH_VIDEO_KEY, mPost.isDashVideo());
+ intent.putExtra(ViewVideoActivity.IS_DOWNLOADABLE_KEY, mPost.isDownloadableGifOrVideo());
+ if(mPost.isDownloadableGifOrVideo()) {
+ intent.putExtra(ViewVideoActivity.DOWNLOAD_URL_KEY, mPost.getGifOrVideoDownloadUrl());
+ intent.putExtra(ViewVideoActivity.SUBREDDIT_KEY, mPost.getSubredditNamePrefixed());
+ intent.putExtra(ViewVideoActivity.ID_KEY, mPost.getId());
+ }
+ mActivity.startActivity(intent);
+ });
+ break;
+ case Post.NO_PREVIEW_LINK_TYPE:
+ ((PostDetailViewHolder) holder).mTypeChip.setText("LINK");
+
+ ((PostDetailViewHolder) holder).linkTextView.setVisibility(View.VISIBLE);
+ String noPreviewLinkDomain = Uri.parse(mPost.getUrl()).getHost();
+ ((PostDetailViewHolder) holder).linkTextView.setText(noPreviewLinkDomain);
+
+ if(!mPost.getSelfText().equals("")) {
+ ((PostDetailViewHolder) holder).mContentMarkdownView.setVisibility(View.VISIBLE);
+ ((PostDetailViewHolder) holder).mContentMarkdownView.setMarkdown(getCustomSpannableConfiguration(), mPost.getSelfText());
+ }
+ ((PostDetailViewHolder) holder).mNoPreviewLinkImageView.setVisibility(View.VISIBLE);
+ ((PostDetailViewHolder) holder).mNoPreviewLinkImageView.setOnClickListener(view -> {
+ 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(mPost.getUrl()));
+ });
+ break;
+ case Post.TEXT_TYPE:
+ ((PostDetailViewHolder) holder).mTypeChip.setText("TEXT");
+
+ if(!mPost.getSelfText().equals("")) {
+ ((PostDetailViewHolder) holder).mContentMarkdownView.setVisibility(View.VISIBLE);
+ ((PostDetailViewHolder) holder).mContentMarkdownView.setMarkdown(getCustomSpannableConfiguration(), mPost.getSelfText());
+ }
+ break;
+ }
+ } else if(holder.getItemViewType() == VIEW_TYPE_COMMENT) {
+ CommentData commentItem;
+ if(isInitiallyLoading || isInitiallyLoadingFailed) {
+ commentItem = mVisibleComments.get(holder.getAdapterPosition() - 2);
+ } else {
+ commentItem = mVisibleComments.get(holder.getAdapterPosition() - 1);
+ }
String authorPrefixed = "u/" + commentItem.getAuthor();
((CommentViewHolder) holder).authorTextView.setText(authorPrefixed);
@@ -122,11 +376,17 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
.setColorFilter(ContextCompat.getColor(mActivity, R.color.minusButtonColor), android.graphics.PorterDuff.Mode.SRC_IN);
break;
}
- } else {
- ((LoadMoreCommentViewHolder) holder).verticalBlock.getLayoutParams().width = mVisibleComments.get(holder.getAdapterPosition()).getDepth() * 16;
- if(mVisibleComments.get(holder.getAdapterPosition()).isLoadingMoreChildren()) {
+ } else if(holder instanceof LoadMoreCommentViewHolder) {
+ CommentData placeholder;
+ if(isInitiallyLoading || isInitiallyLoadingFailed) {
+ placeholder = mVisibleComments.get(holder.getAdapterPosition() - 2);
+ } else {
+ placeholder = mVisibleComments.get(holder.getAdapterPosition() - 1);
+ }
+ ((LoadMoreCommentViewHolder) holder).verticalBlock.getLayoutParams().width = placeholder.getDepth() * 16;
+ if(placeholder.isLoadingMoreChildren()) {
((LoadMoreCommentViewHolder) holder).placeholderTextView.setText(R.string.loading);
- } else if(mVisibleComments.get(holder.getAdapterPosition()).isLoadMoreChildrenFailed()) {
+ } else if(placeholder.isLoadMoreChildrenFailed()) {
((LoadMoreCommentViewHolder) holder).placeholderTextView.setText(R.string.comment_load_more_comments_failed);
} else {
((LoadMoreCommentViewHolder) holder).placeholderTextView.setText(R.string.comment_load_more_comments);
@@ -134,6 +394,63 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
}
}
+ private void loadImage(PostDetailViewHolder holder) {
+ RequestBuilder imageRequestBuilder = mGlide.load(mPost.getPreviewUrl())
+ .apply(new RequestOptions().override(mPost.getPreviewWidth(), mPost.getPreviewHeight()))
+ .listener(new RequestListener<Drawable>() {
+ @Override
+ public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
+ holder.mLoadImageProgressBar.setVisibility(View.GONE);
+ holder.mLoadImageErrorTextView.setVisibility(View.VISIBLE);
+ holder.mLoadImageErrorTextView.setOnClickListener(view -> {
+ holder.mLoadImageProgressBar.setVisibility(View.VISIBLE);
+ holder.mLoadImageErrorTextView.setVisibility(View.GONE);
+ loadImage(holder);
+ });
+ return false;
+ }
+
+ @Override
+ public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
+ holder.mLoadWrapper.setVisibility(View.GONE);
+ return false;
+ }
+ });
+
+ if(mPost.isNSFW()) {
+ imageRequestBuilder.apply(RequestOptions.bitmapTransform(new BlurTransformation(50, 2)))
+ .into(holder.mImageView);
+ } else {
+ imageRequestBuilder.into(holder.mImageView);
+ }
+ }
+
+ private SpannableConfiguration getCustomSpannableConfiguration() {
+ return SpannableConfiguration.builder(mActivity).linkResolver((view, link) -> {
+ if(link.startsWith("/u/") || link.startsWith("u/")) {
+ Intent intent = new Intent(mActivity, ViewUserDetailActivity.class);
+ intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, link.substring(3));
+ 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();
+ }
+
+ void updatePost(Post post) {
+ mPost = post;
+ notifyItemChanged(0);
+ }
+
private int getParentPosition(int position) {
int childDepth = mVisibleComments.get(position).getDepth();
for(int i = position; i >= 0; i--) {
@@ -176,9 +493,19 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
}
void addComments(ArrayList<CommentData> comments) {
+ if(mVisibleComments.size() == 0) {
+ isInitiallyLoading = false;
+ isInitiallyLoadingFailed = false;
+ if(comments.size() == 0) {
+ notifyItemChanged(1);
+ } else {
+ notifyItemRemoved(1);
+ }
+ }
+
int sizeBefore = mVisibleComments.size();
mVisibleComments.addAll(comments);
- notifyItemRangeInserted(sizeBefore, comments.size());
+ notifyItemRangeInserted(sizeBefore + 1, comments.size());
}
void addComment(CommentData comment) {
@@ -207,9 +534,36 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
}
}
- void clearData() {
- mVisibleComments.clear();
- notifyDataSetChanged();
+ void initiallyLoading() {
+ if(mLoadSubredditIconAsyncTask != null) {
+ mLoadSubredditIconAsyncTask.cancel(true);
+ }
+
+ if(isInitiallyLoading || isInitiallyLoadingFailed) {
+ isInitiallyLoading = true;
+ isInitiallyLoadingFailed = false;
+ notifyItemChanged(1);
+ } else {
+ isInitiallyLoading = true;
+ isInitiallyLoadingFailed = false;
+ notifyItemInserted(1);
+ }
+
+ clearComments();
+ }
+
+ void initiallyLoadCommentsFailed() {
+ isInitiallyLoading = false;
+ isInitiallyLoadingFailed = true;
+ notifyItemChanged(1);
+ }
+
+ private void clearComments() {
+ if(mVisibleComments.size() != 0) {
+ int previousSize = mVisibleComments.size();
+ mVisibleComments.clear();
+ notifyItemRangeRemoved(1, previousSize);
+ }
}
@Override
@@ -221,7 +575,164 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
@Override
public int getItemCount() {
- return mVisibleComments.size();
+ if(isInitiallyLoading || isInitiallyLoadingFailed) {
+ return 2;
+ }
+
+ return mVisibleComments.size() + 1;
+ }
+
+ class PostDetailViewHolder extends RecyclerView.ViewHolder {
+ @BindView(R.id.subreddit_icon_name_linear_layout_item_post_detail) LinearLayout mSubredditIconNameLinearLayout;
+ @BindView(R.id.subreddit_icon_circle_image_view_item_post_detail) AspectRatioGifImageView mSubredditIconGifImageView;
+ @BindView(R.id.subreddit_text_view_item_post_detail) TextView mSubredditTextView;
+ @BindView(R.id.post_time_text_view_item_post_detail) TextView mPostTimeTextView;
+ @BindView(R.id.title_text_view_item_post_detail) TextView mTitleTextView;
+ @BindView(R.id.content_markdown_view_item_post_detail) MarkwonView mContentMarkdownView;
+ @BindView(R.id.type_text_view_item_post_detail) Chip mTypeChip;
+ @BindView(R.id.gilded_image_view_item_post_detail) ImageView mGildedImageView;
+ @BindView(R.id.gilded_number_text_view_item_post_detail) TextView mGildedNumberTextView;
+ @BindView(R.id.crosspost_image_view_item_post_detail) ImageView mCrosspostImageView;
+ @BindView(R.id.nsfw_text_view_item_post_detail) Chip mNSFWChip;
+ @BindView(R.id.link_text_view_item_post_detail) TextView linkTextView;
+ @BindView(R.id.image_view_wrapper_item_post_detail) RelativeLayout mRelativeLayout;
+ @BindView(R.id.load_wrapper_item_post_detail) RelativeLayout mLoadWrapper;
+ @BindView(R.id.progress_bar_item_post_detail) ProgressBar mLoadImageProgressBar;
+ @BindView(R.id.load_image_error_text_view_item_post_detail) TextView mLoadImageErrorTextView;
+ @BindView(R.id.image_view_item_post_detail) AspectRatioImageView mImageView;
+ @BindView(R.id.image_view_no_preview_link_item_post_detail) ImageView mNoPreviewLinkImageView;
+ @BindView(R.id.plus_button_item_post_detail) ImageView mUpvoteButton;
+ @BindView(R.id.score_text_view_item_post_detail) TextView mScoreTextView;
+ @BindView(R.id.minus_button_item_post_detail) ImageView mDownvoteButton;
+ @BindView(R.id.share_button_item_post_detail) ImageView mShareButton;
+
+ public PostDetailViewHolder(@NonNull View itemView) {
+ super(itemView);
+ ButterKnife.bind(this, itemView);
+
+ mSubredditIconNameLinearLayout.setOnClickListener(view -> {
+ Intent intent = new Intent(mActivity, ViewSubredditDetailActivity.class);
+ intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY,
+ mPost.getSubredditNamePrefixed().substring(2));
+ mActivity.startActivity(intent);
+ });
+
+ mShareButton.setOnClickListener(view -> {
+ Intent intent = new Intent(Intent.ACTION_SEND);
+ intent.setType("text/plain");
+ String extraText = mPost.getTitle() + "\n" + mPost.getPermalink();
+ intent.putExtra(Intent.EXTRA_TEXT, extraText);
+ mActivity.startActivity(Intent.createChooser(intent, "Share"));
+ });
+
+ mUpvoteButton.setOnClickListener(view -> {
+ ColorFilter previousUpvoteButtonColorFilter = mUpvoteButton.getColorFilter();
+ ColorFilter previousDownvoteButtonColorFilter = mDownvoteButton.getColorFilter();
+ int previousVoteType = mPost.getVoteType();
+ String newVoteType;
+
+ mDownvoteButton.clearColorFilter();
+
+ if(previousUpvoteButtonColorFilter == null) {
+ //Not upvoted before
+ mPost.setVoteType(1);
+ newVoteType = RedditUtils.DIR_UPVOTE;
+ mUpvoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.backgroundColorPrimaryDark), android.graphics.PorterDuff.Mode.SRC_IN);
+ } else {
+ //Upvoted before
+ mPost.setVoteType(0);
+ newVoteType = RedditUtils.DIR_UNVOTE;
+ mUpvoteButton.clearColorFilter();
+ }
+
+ mScoreTextView.setText(Integer.toString(mPost.getScore() + mPost.getVoteType()));
+
+ mUpdatePostInPostFragmentCallback.updatePost(mPost);
+
+ VoteThing.voteThing(mOauthRetrofit, mSharedPreferences, new VoteThing.VoteThingWithoutPositionListener() {
+ @Override
+ public void onVoteThingSuccess() {
+ if(newVoteType.equals(RedditUtils.DIR_UPVOTE)) {
+ mPost.setVoteType(1);
+ mUpvoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.backgroundColorPrimaryDark), android.graphics.PorterDuff.Mode.SRC_IN);
+ } else {
+ mPost.setVoteType(0);
+ mUpvoteButton.clearColorFilter();
+ }
+
+ mDownvoteButton.clearColorFilter();
+ mScoreTextView.setText(Integer.toString(mPost.getScore() + mPost.getVoteType()));
+
+ mUpdatePostInPostFragmentCallback.updatePost(mPost);
+ }
+
+ @Override
+ public void onVoteThingFail() {
+ Toast.makeText(mActivity, R.string.vote_failed, Toast.LENGTH_SHORT).show();
+ mPost.setVoteType(previousVoteType);
+ mScoreTextView.setText(Integer.toString(mPost.getScore() + previousVoteType));
+ mUpvoteButton.setColorFilter(previousUpvoteButtonColorFilter);
+ mDownvoteButton.setColorFilter(previousDownvoteButtonColorFilter);
+
+ mUpdatePostInPostFragmentCallback.updatePost(mPost);
+ }
+ }, mPost.getFullName(), newVoteType);
+ });
+
+ mDownvoteButton.setOnClickListener(view -> {
+ ColorFilter previousUpvoteButtonColorFilter = mUpvoteButton.getColorFilter();
+ ColorFilter previousDownvoteButtonColorFilter = mDownvoteButton.getColorFilter();
+ int previousVoteType = mPost.getVoteType();
+ String newVoteType;
+
+ mUpvoteButton.clearColorFilter();
+
+ if(previousDownvoteButtonColorFilter == null) {
+ //Not upvoted before
+ mPost.setVoteType(-1);
+ newVoteType = RedditUtils.DIR_DOWNVOTE;
+ mDownvoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.colorAccent), android.graphics.PorterDuff.Mode.SRC_IN);
+ } else {
+ //Upvoted before
+ mPost.setVoteType(0);
+ newVoteType = RedditUtils.DIR_UNVOTE;
+ mDownvoteButton.clearColorFilter();
+ }
+
+ mScoreTextView.setText(Integer.toString(mPost.getScore() + mPost.getVoteType()));
+
+ mUpdatePostInPostFragmentCallback.updatePost(mPost);
+
+ VoteThing.voteThing(mOauthRetrofit, mSharedPreferences, new VoteThing.VoteThingWithoutPositionListener() {
+ @Override
+ public void onVoteThingSuccess() {
+ if(newVoteType.equals(RedditUtils.DIR_DOWNVOTE)) {
+ mPost.setVoteType(-1);
+ mDownvoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.colorAccent), android.graphics.PorterDuff.Mode.SRC_IN);
+ } else {
+ mPost.setVoteType(0);
+ mDownvoteButton.clearColorFilter();
+ }
+
+ mUpvoteButton.clearColorFilter();
+ mScoreTextView.setText(Integer.toString(mPost.getScore() + mPost.getVoteType()));
+
+ mUpdatePostInPostFragmentCallback.updatePost(mPost);
+ }
+
+ @Override
+ public void onVoteThingFail() {
+ Toast.makeText(mActivity, R.string.vote_failed, Toast.LENGTH_SHORT).show();
+ mPost.setVoteType(previousVoteType);
+ mScoreTextView.setText(Integer.toString(mPost.getScore() + previousVoteType));
+ mUpvoteButton.setColorFilter(previousUpvoteButtonColorFilter);
+ mDownvoteButton.setColorFilter(previousDownvoteButtonColorFilter);
+
+ mUpdatePostInPostFragmentCallback.updatePost(mPost);
+ }
+ }, mPost.getFullName(), newVoteType);
+ });
+ }
}
class CommentViewHolder extends RecyclerView.ViewHolder {
@@ -242,117 +753,117 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
authorTextView.setOnClickListener(view -> {
Intent intent = new Intent(mActivity, ViewUserDetailActivity.class);
- intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, mVisibleComments.get(getAdapterPosition()).getAuthor());
+ intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, mVisibleComments.get(getAdapterPosition() - 1).getAuthor());
mActivity.startActivity(intent);
});
shareButton.setOnClickListener(view -> {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
- String extraText = mVisibleComments.get(getAdapterPosition()).getPermalink();
+ String extraText = mVisibleComments.get(getAdapterPosition() - 1).getPermalink();
intent.putExtra(Intent.EXTRA_TEXT, extraText);
mActivity.startActivity(Intent.createChooser(intent, "Share"));
});
expandButton.setOnClickListener(view -> {
- if(mVisibleComments.get(getAdapterPosition()).isExpanded()) {
+ if(mVisibleComments.get(getAdapterPosition() - 1).isExpanded()) {
collapseChildren(getAdapterPosition());
expandButton.setImageResource(R.drawable.ic_expand_more_black_20dp);
} else {
expandChildren(getAdapterPosition());
- mVisibleComments.get(getAdapterPosition()).setExpanded(true);
+ mVisibleComments.get(getAdapterPosition() - 1).setExpanded(true);
expandButton.setImageResource(R.drawable.ic_expand_less_black_20dp);
}
});
replyButton.setOnClickListener(view -> {
Intent intent = new Intent(mActivity, CommentActivity.class);
- intent.putExtra(CommentActivity.EXTRA_PARENT_DEPTH_KEY, mVisibleComments.get(getAdapterPosition()).getDepth() + 1);
- intent.putExtra(CommentActivity.EXTRA_COMMENT_PARENT_TEXT_KEY, mVisibleComments.get(getAdapterPosition()).getCommentContent());
- intent.putExtra(CommentActivity.EXTRA_PARENT_FULLNAME_KEY, mVisibleComments.get(getAdapterPosition()).getFullName());
+ intent.putExtra(CommentActivity.EXTRA_PARENT_DEPTH_KEY, mVisibleComments.get(getAdapterPosition() - 1).getDepth() + 1);
+ intent.putExtra(CommentActivity.EXTRA_COMMENT_PARENT_TEXT_KEY, mVisibleComments.get(getAdapterPosition() - 1).getCommentContent());
+ intent.putExtra(CommentActivity.EXTRA_PARENT_FULLNAME_KEY, mVisibleComments.get(getAdapterPosition() - 1).getFullName());
intent.putExtra(CommentActivity.EXTRA_IS_REPLYING_KEY, true);
intent.putExtra(CommentActivity.EXTRA_PARENT_POSITION_KEY, getAdapterPosition());
mActivity.startActivityForResult(intent, CommentActivity.WRITE_COMMENT_REQUEST_CODE);
});
upvoteButton.setOnClickListener(view -> {
- int previousVoteType = mVisibleComments.get(getAdapterPosition()).getVoteType();
+ int previousVoteType = mVisibleComments.get(getAdapterPosition() - 1).getVoteType();
String newVoteType;
downvoteButton.clearColorFilter();
if(previousVoteType != CommentData.VOTE_TYPE_UPVOTE) {
//Not upvoted before
- mVisibleComments.get(getAdapterPosition()).setVoteType(CommentData.VOTE_TYPE_UPVOTE);
+ mVisibleComments.get(getAdapterPosition() - 1).setVoteType(CommentData.VOTE_TYPE_UPVOTE);
newVoteType = RedditUtils.DIR_UPVOTE;
upvoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.backgroundColorPrimaryDark), android.graphics.PorterDuff.Mode.SRC_IN);
} else {
//Upvoted before
- mVisibleComments.get(getAdapterPosition()).setVoteType(CommentData.VOTE_TYPE_NO_VOTE);
+ mVisibleComments.get(getAdapterPosition() - 1).setVoteType(CommentData.VOTE_TYPE_NO_VOTE);
newVoteType = RedditUtils.DIR_UNVOTE;
upvoteButton.clearColorFilter();
}
- scoreTextView.setText(Integer.toString(mVisibleComments.get(getAdapterPosition()).getScore() + mVisibleComments.get(getAdapterPosition()).getVoteType()));
+ scoreTextView.setText(Integer.toString(mVisibleComments.get(getAdapterPosition() - 1).getScore() + mVisibleComments.get(getAdapterPosition() - 1).getVoteType()));
VoteThing.voteThing(mOauthRetrofit, mSharedPreferences, new VoteThing.VoteThingListener() {
@Override
public void onVoteThingSuccess(int position) {
if(newVoteType.equals(RedditUtils.DIR_UPVOTE)) {
- mVisibleComments.get(getAdapterPosition()).setVoteType(CommentData.VOTE_TYPE_UPVOTE);
+ mVisibleComments.get(getAdapterPosition() - 1).setVoteType(CommentData.VOTE_TYPE_UPVOTE);
upvoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.backgroundColorPrimaryDark), android.graphics.PorterDuff.Mode.SRC_IN);
} else {
- mVisibleComments.get(getAdapterPosition()).setVoteType(CommentData.VOTE_TYPE_NO_VOTE);
+ mVisibleComments.get(getAdapterPosition() - 1).setVoteType(CommentData.VOTE_TYPE_NO_VOTE);
upvoteButton.clearColorFilter();
}
downvoteButton.clearColorFilter();
- scoreTextView.setText(Integer.toString(mVisibleComments.get(getAdapterPosition()).getScore() + mVisibleComments.get(getAdapterPosition()).getVoteType()));
+ scoreTextView.setText(Integer.toString(mVisibleComments.get(getAdapterPosition() - 1).getScore() + mVisibleComments.get(getAdapterPosition() - 1).getVoteType()));
}
@Override
public void onVoteThingFail(int position) { }
- }, mVisibleComments.get(getAdapterPosition()).getFullName(), newVoteType, getAdapterPosition());
+ }, mVisibleComments.get(getAdapterPosition() - 1).getFullName(), newVoteType, getAdapterPosition());
});
downvoteButton.setOnClickListener(view -> {
- int previousVoteType = mVisibleComments.get(getAdapterPosition()).getVoteType();
+ int previousVoteType = mVisibleComments.get(getAdapterPosition() - 1).getVoteType();
String newVoteType;
upvoteButton.clearColorFilter();
if(previousVoteType != CommentData.VOTE_TYPE_DOWNVOTE) {
//Not downvoted before
- mVisibleComments.get(getAdapterPosition()).setVoteType(CommentData.VOTE_TYPE_DOWNVOTE);
+ mVisibleComments.get(getAdapterPosition() - 1).setVoteType(CommentData.VOTE_TYPE_DOWNVOTE);
newVoteType = RedditUtils.DIR_DOWNVOTE;
downvoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.colorAccent), android.graphics.PorterDuff.Mode.SRC_IN);
} else {
//Downvoted before
- mVisibleComments.get(getAdapterPosition()).setVoteType(CommentData.VOTE_TYPE_NO_VOTE);
+ mVisibleComments.get(getAdapterPosition() - 1).setVoteType(CommentData.VOTE_TYPE_NO_VOTE);
newVoteType = RedditUtils.DIR_UNVOTE;
downvoteButton.clearColorFilter();
}
- scoreTextView.setText(Integer.toString(mVisibleComments.get(getAdapterPosition()).getScore() + mVisibleComments.get(getAdapterPosition()).getVoteType()));
+ scoreTextView.setText(Integer.toString(mVisibleComments.get(getAdapterPosition() - 1).getScore() + mVisibleComments.get(getAdapterPosition() - 1).getVoteType()));
VoteThing.voteThing(mOauthRetrofit, mSharedPreferences, new VoteThing.VoteThingListener() {
@Override
public void onVoteThingSuccess(int position1) {
if(newVoteType.equals(RedditUtils.DIR_DOWNVOTE)) {
- mVisibleComments.get(getAdapterPosition()).setVoteType(CommentData.VOTE_TYPE_DOWNVOTE);
+ mVisibleComments.get(getAdapterPosition() - 1).setVoteType(CommentData.VOTE_TYPE_DOWNVOTE);
downvoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.colorAccent), android.graphics.PorterDuff.Mode.SRC_IN);
} else {
- mVisibleComments.get(getAdapterPosition()).setVoteType(CommentData.VOTE_TYPE_NO_VOTE);
+ mVisibleComments.get(getAdapterPosition() - 1).setVoteType(CommentData.VOTE_TYPE_NO_VOTE);
downvoteButton.clearColorFilter();
}
upvoteButton.clearColorFilter();
- scoreTextView.setText(Integer.toString(mVisibleComments.get(getAdapterPosition()).getScore() + mVisibleComments.get(getAdapterPosition()).getVoteType()));
+ scoreTextView.setText(Integer.toString(mVisibleComments.get(getAdapterPosition() - 1).getScore() + mVisibleComments.get(getAdapterPosition() - 1).getVoteType()));
}
@Override
public void onVoteThingFail(int position1) { }
- }, mVisibleComments.get(getAdapterPosition()).getFullName(), newVoteType, getAdapterPosition());
+ }, mVisibleComments.get(getAdapterPosition() - 1).getFullName(), newVoteType, getAdapterPosition());
});
}
}
@@ -366,11 +877,11 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
ButterKnife.bind(this, itemView);
placeholderTextView.setOnClickListener(view -> {
- int parentPosition = getParentPosition(getAdapterPosition());
+ int parentPosition = getParentPosition(getAdapterPosition() - 1);
CommentData parentComment = mVisibleComments.get(parentPosition);
- mVisibleComments.get(getAdapterPosition()).setLoadingMoreChildren(true);
- mVisibleComments.get(getAdapterPosition()).setLoadMoreChildrenFailed(false);
+ mVisibleComments.get(getAdapterPosition() - 1).setLoadingMoreChildren(true);
+ mVisibleComments.get(getAdapterPosition() - 1).setLoadMoreChildrenFailed(false);
placeholderTextView.setText(R.string.loading);
FetchComment.fetchMoreComment(mRetrofit, mSubredditNamePrefixed, parentComment.getMoreChildrenFullnames(),
@@ -389,8 +900,8 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
mVisibleComments.get(parentPosition).getChildren().get(mVisibleComments.get(parentPosition).getChildren().size() - 1)
.setLoadMoreChildrenFailed(false);
- int placeholderPosition = getAdapterPosition();
- if(mVisibleComments.get(getAdapterPosition()).getFullName().equals(parentComment.getFullName())) {
+ int placeholderPosition = getAdapterPosition() - 1;
+ if(mVisibleComments.get(getAdapterPosition() - 1).getFullName().equals(parentComment.getFullName())) {
for(int i = parentPosition + 1; i < mVisibleComments.size(); i++) {
if(mVisibleComments.get(i).getFullName().equals(parentComment.getFullName())) {
placeholderPosition = i;
@@ -404,14 +915,14 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
placeholderTextView.setText(R.string.comment_load_more_comments);
mVisibleComments.addAll(placeholderPosition, expandedComments);
- notifyItemRangeInserted(placeholderPosition, expandedComments.size());
+ notifyItemRangeInserted(placeholderPosition + 1, expandedComments.size());
} else {
mVisibleComments.get(parentPosition).getChildren()
.remove(mVisibleComments.get(parentPosition).getChildren().size() - 1);
mVisibleComments.get(parentPosition).removeMoreChildrenFullnames();
- int placeholderPosition = getAdapterPosition();
- if(mVisibleComments.get(getAdapterPosition()).getFullName().equals(parentComment.getFullName())) {
+ int placeholderPosition = getAdapterPosition() - 1;
+ if(mVisibleComments.get(getAdapterPosition() - 1).getFullName().equals(parentComment.getFullName())) {
for(int i = parentPosition + 1; i < mVisibleComments.size(); i++) {
if(mVisibleComments.get(i).getFullName().equals(parentComment.getFullName())) {
placeholderPosition = i;
@@ -421,10 +932,10 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
}
mVisibleComments.remove(placeholderPosition);
- notifyItemRemoved(placeholderPosition);
+ notifyItemRemoved(placeholderPosition + 1);
mVisibleComments.addAll(placeholderPosition, expandedComments);
- notifyItemRangeInserted(placeholderPosition, expandedComments.size());
+ notifyItemRangeInserted(placeholderPosition + 1, expandedComments.size());
}
} else {
if(mVisibleComments.get(parentPosition).hasReply() && mVisibleComments.get(parentPosition).getChildren().size() <= childrenStartingIndex) {
@@ -455,7 +966,7 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
placeholderTextView.setText(R.string.comment_load_more_comments);
mVisibleComments.addAll(placeholderPosition, expandedComments);
- notifyItemRangeInserted(placeholderPosition, expandedComments.size());
+ notifyItemRangeInserted(placeholderPosition + 1, expandedComments.size());
}
mVisibleComments.get(i).getChildren().get(mVisibleComments.get(i).getChildren().size() - 1)
@@ -475,8 +986,8 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
if(parentPosition < mVisibleComments.size()
&& parentComment.getFullName().equals(mVisibleComments.get(parentPosition).getFullName())) {
if(mVisibleComments.get(parentPosition).isExpanded()) {
- int placeholderPosition = getAdapterPosition();
- if(!mVisibleComments.get(getAdapterPosition()).getFullName().equals(parentComment.getFullName())) {
+ int placeholderPosition = getAdapterPosition() - 1;
+ if(!mVisibleComments.get(getAdapterPosition() - 1).getFullName().equals(parentComment.getFullName())) {
for(int i = parentPosition + 1; i < mVisibleComments.size(); i++) {
if(mVisibleComments.get(i).getFullName().equals(parentComment.getFullName())) {
placeholderPosition = i;
@@ -525,4 +1036,25 @@ class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
});
}
}
+
+ class LoadCommentsViewHolder extends RecyclerView.ViewHolder {
+
+ public LoadCommentsViewHolder(@NonNull View itemView) {
+ super(itemView);
+ }
+ }
+
+ class LoadCommentsFailedViewHolder extends RecyclerView.ViewHolder {
+
+ public LoadCommentsFailedViewHolder(@NonNull View itemView) {
+ super(itemView);
+ }
+ }
+
+ class NoCommentViewHolder extends RecyclerView.ViewHolder {
+
+ public NoCommentViewHolder(@NonNull View itemView) {
+ super(itemView);
+ }
+ }
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java
index b2a0db3f..fb1aec1f 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java
@@ -106,7 +106,7 @@ class FetchComment {
}
@Override
- public void onFailure(Call<String> call, Throwable t) {
+ public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) {
Log.i("more comment failed", t.getMessage());
fetchMoreCommentListener.onFetchMoreCommentFailed();
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/LoadSubredditIconAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/LoadSubredditIconAsyncTask.java
index f7f0fdcd..923e657f 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/LoadSubredditIconAsyncTask.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/LoadSubredditIconAsyncTask.java
@@ -34,6 +34,8 @@ class LoadSubredditIconAsyncTask extends AsyncTask<Void, Void, Void> {
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
- loadSubredditIconAsyncTaskListener.loadIconSuccess(iconImageUrl);
+ if(!isCancelled()) {
+ loadSubredditIconAsyncTaskListener.loadIconSuccess(iconImageUrl);
+ }
}
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java
index 72f8c4a3..a10579c1 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java
@@ -16,7 +16,7 @@ public interface RedditAPI {
@POST("api/v1/access_token")
Call<String> getAccessToken(@HeaderMap Map<String, String> headers, @FieldMap Map<String, String> params);
- @GET("{subredditNamePrefixed}/comments/{article}.json?raw_json=1")
+ @GET("{subredditNamePrefixed}/comments/{article}.json?&raw_json=1")
Call<String> getComments(@Path("subredditNamePrefixed") String subredditNamePrefixed,
@Path("article") String article);
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewPostDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewPostDetailActivity.java
index 8ab0b3f5..0eb99830 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewPostDetailActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewPostDetailActivity.java
@@ -3,46 +3,23 @@ package ml.docilealligator.infinityforreddit;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
-import android.graphics.ColorFilter;
-import android.graphics.PorterDuff;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.ProgressBar;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
-import androidx.browser.customtabs.CustomTabsIntent;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
-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;
import com.bumptech.glide.RequestManager;
-import com.bumptech.glide.load.DataSource;
-import com.bumptech.glide.load.engine.GlideException;
-import com.bumptech.glide.request.RequestListener;
-import com.bumptech.glide.request.RequestOptions;
-import com.bumptech.glide.request.target.Target;
-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.santalu.aspectratioimageview.AspectRatioImageView;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -53,15 +30,9 @@ import java.util.Locale;
import javax.inject.Inject;
import javax.inject.Named;
-import CustomView.AspectRatioGifImageView;
-import SubredditDatabase.SubredditRoomDatabase;
import butterknife.BindView;
import butterknife.ButterKnife;
-import jp.wasabeef.glide.transformations.BlurTransformation;
-import jp.wasabeef.glide.transformations.RoundedCornersTransformation;
import retrofit2.Retrofit;
-import ru.noties.markwon.SpannableConfiguration;
-import ru.noties.markwon.view.MarkwonView;
import static ml.docilealligator.infinityforreddit.CommentActivity.EXTRA_COMMENT_DATA_KEY;
import static ml.docilealligator.infinityforreddit.CommentActivity.WRITE_COMMENT_REQUEST_CODE;
@@ -93,34 +64,7 @@ public class ViewPostDetailActivity extends AppCompatActivity {
@BindView(R.id.coordinator_layout_view_post_detail) CoordinatorLayout mCoordinatorLayout;
@BindView(R.id.toolbar_view_post_detail_activity) Toolbar toolbar;
- @BindView(R.id.nested_scroll_view_view_post_detail_activity) NestedScrollView mNestedScrollView;
- @BindView(R.id.subreddit_icon_name_linear_layout_view_post_detail) LinearLayout mSubredditIconNameLinearLayout;
- @BindView(R.id.subreddit_icon_circle_image_view_view_post_detail) AspectRatioGifImageView mSubredditIconGifImageView;
- @BindView(R.id.subreddit_text_view_view_post_detail) TextView mSubredditTextView;
- @BindView(R.id.post_time_text_view_view_post_detail) TextView mPostTimeTextView;
- @BindView(R.id.title_text_view_view_post_detail) TextView mTitleTextView;
- @BindView(R.id.content_markdown_view_view_post_detail) MarkwonView mContentMarkdownView;
- @BindView(R.id.type_text_view_view_post_detail) Chip mTypeChip;
- @BindView(R.id.gilded_image_view_view_post_detail) ImageView mGildedImageView;
- @BindView(R.id.gilded_number_text_view_view_post_detail) TextView mGildedNumberTextView;
- @BindView(R.id.crosspost_image_view_view_post_detail) ImageView mCrosspostImageView;
- @BindView(R.id.nsfw_text_view_view_post_detail) Chip mNSFWChip;
- @BindView(R.id.link_text_view_view_post_detail) TextView linkTextView;
- @BindView(R.id.image_view_wrapper_view_post_detail) RelativeLayout mRelativeLayout;
- @BindView(R.id.load_wrapper_view_post_detail) RelativeLayout mLoadWrapper;
- @BindView(R.id.progress_bar_view_post_detail) ProgressBar mLoadImageProgressBar;
- @BindView(R.id.load_image_error_text_view_view_post_detail) TextView mLoadImageErrorTextView;
- @BindView(R.id.image_view_view_post_detail) AspectRatioImageView mImageView;
- @BindView(R.id.image_view_no_preview_link_view_post_detail) ImageView mNoPreviewLinkImageView;
- @BindView(R.id.plus_button_view_post_detail) ImageView mUpvoteButton;
- @BindView(R.id.score_text_view_view_post_detail) TextView mScoreTextView;
- @BindView(R.id.minus_button_view_post_detail) ImageView mDownvoteButton;
- @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) 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;
@Inject @Named("no_oauth")
Retrofit mRetrofit;
@@ -148,14 +92,26 @@ public class ViewPostDetailActivity extends AppCompatActivity {
mGlide = Glide.with(this);
mLocale = getResources().getConfiguration().locale;
+ mRecyclerView.setNestedScrollingEnabled(false);
+ mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
+ mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
+
if(savedInstanceState == null) {
orientation = getResources().getConfiguration().orientation;
mPost = getIntent().getExtras().getParcelable(EXTRA_POST_DATA);
} else {
orientation = savedInstanceState.getInt(ORIENTATION_STATE);
mPost = savedInstanceState.getParcelable(POST_STATE);
- isRefreshing = savedInstanceState.getBoolean(IS_REFRESHING_STATE);
+ }
+
+ mAdapter = new CommentRecyclerViewAdapter(ViewPostDetailActivity.this, mRetrofit,
+ mOauthRetrofit, mGlide, mSharedPreferences, mPost,
+ mPost.getSubredditNamePrefixed(), mLocale, mLoadSubredditIconAsyncTask,
+ post -> EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition)));
+ mRecyclerView.setAdapter(mAdapter);
+ if(savedInstanceState != null) {
+ isRefreshing = savedInstanceState.getBoolean(IS_REFRESHING_STATE);
if(isRefreshing) {
isRefreshing = false;
refresh();
@@ -166,336 +122,11 @@ public class ViewPostDetailActivity extends AppCompatActivity {
postListPosition = getIntent().getExtras().getInt(EXTRA_POST_LIST_POSITION);
}
- mRecyclerView.setNestedScrollingEnabled(false);
- mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
- mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
-
fetchComment();
- bindView();
- initializeButtonOnClickListener();
- }
-
- private void bindView() {
- mTitleTextView.setText(mPost.getTitle());
-
- if(mPost.getSubredditIconUrl() == null) {
- mLoadSubredditIconAsyncTask = new LoadSubredditIconAsyncTask(
- SubredditRoomDatabase.getDatabase(this).subredditDao(), mPost.getSubredditNamePrefixed().substring(2),
- iconImageUrl -> {
- if(!iconImageUrl.equals("")) {
- mGlide.load(iconImageUrl)
- .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))
- .error(mGlide.load(R.drawable.subreddit_default_icon)
- .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))))
- .into(mSubredditIconGifImageView);
- } else {
- mGlide.load(R.drawable.subreddit_default_icon)
- .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))
- .into(mSubredditIconGifImageView);
- }
-
- mPost.setSubredditIconUrl(iconImageUrl);
- });
- mLoadSubredditIconAsyncTask.execute();
- } else if(!mPost.getSubredditIconUrl().equals("")) {
- mGlide.load(mPost.getSubredditIconUrl())
- .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))
- .error(mGlide.load(R.drawable.subreddit_default_icon)
- .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))))
- .into(mSubredditIconGifImageView);
- } else {
- mGlide.load(R.drawable.subreddit_default_icon)
- .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))
- .into(mSubredditIconGifImageView);
- }
-
- switch (mPost.getVoteType()) {
- case 1:
- //Upvote
- mUpvoteButton.setColorFilter(ContextCompat.getColor(this, R.color.backgroundColorPrimaryDark), PorterDuff.Mode.SRC_IN);
- break;
- case -1:
- //Downvote
- mDownvoteButton.setColorFilter(ContextCompat.getColor(this, R.color.minusButtonColor), PorterDuff.Mode.SRC_IN);
- break;
- case 0:
- mUpvoteButton.clearColorFilter();
- mDownvoteButton.clearColorFilter();
- }
-
- if(mPost.getPostType() != Post.TEXT_TYPE && mPost.getPostType() != Post.NO_PREVIEW_LINK_TYPE) {
- mRelativeLayout.setVisibility(View.VISIBLE);
- mImageView.setVisibility(View.VISIBLE);
- mImageView.setRatio((float) mPost.getPreviewHeight() / (float) mPost.getPreviewWidth());
- loadImage();
- } else {
- mRelativeLayout.setVisibility(View.GONE);
- mImageView.setVisibility(View.GONE);
- }
-
- if(mPost.isCrosspost()) {
- mCrosspostImageView.setVisibility(View.VISIBLE);
- }
-
- mSubredditTextView.setText(mPost.getSubredditNamePrefixed());
-
- mPostTimeTextView.setText(mPost.getPostTime());
-
- if(mPost.getGilded() > 0) {
- mGildedImageView.setVisibility(View.VISIBLE);
- mGlide.load(R.drawable.gold).into(mGildedImageView);
- mGildedNumberTextView.setVisibility(View.VISIBLE);
- String gildedNumber = getResources().getString(R.string.gilded, mPost.getGilded());
- mGildedNumberTextView.setText(gildedNumber);
- }
-
- if(mPost.isNSFW()) {
- mNSFWChip.setVisibility(View.VISIBLE);
- } else {
- mNSFWChip.setVisibility(View.GONE);
- }
-
- String scoreWithVote = Integer.toString(mPost.getScore() + mPost.getVoteType());
- mScoreTextView.setText(scoreWithVote);
-
- switch (mPost.getPostType()) {
- case Post.IMAGE_TYPE:
- mTypeChip.setText("IMAGE");
-
- mImageView.setOnClickListener(view -> {
- Intent intent = new Intent(ViewPostDetailActivity.this, ViewImageActivity.class);
- intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, mPost.getUrl());
- intent.putExtra(ViewImageActivity.TITLE_KEY, mPost.getTitle());
- intent.putExtra(ViewImageActivity.FILE_NAME_KEY, mPost.getSubredditNamePrefixed().substring(2)
- + "-" + mPost.getId().substring(3));
- startActivity(intent);
- });
- break;
- case Post.LINK_TYPE:
- mTypeChip.setText("LINK");
-
- linkTextView.setVisibility(View.VISIBLE);
- String domain = Uri.parse(mPost.getUrl()).getHost();
- linkTextView.setText(domain);
-
- mImageView.setOnClickListener(view -> {
- CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
- // add share action to menu list
- builder.addDefaultShareMenuItem();
- builder.setToolbarColor(getResources().getColor(R.color.colorPrimary));
- CustomTabsIntent customTabsIntent = builder.build();
- customTabsIntent.launchUrl(ViewPostDetailActivity.this, Uri.parse(mPost.getUrl()));
- });
- break;
- case Post.GIF_VIDEO_TYPE:
- mTypeChip.setText("GIF");
-
- final Uri gifVideoUri = Uri.parse(mPost.getVideoUrl());
- mImageView.setOnClickListener(view -> {
- Intent intent = new Intent(ViewPostDetailActivity.this, ViewVideoActivity.class);
- intent.setData(gifVideoUri);
- intent.putExtra(ViewVideoActivity.TITLE_KEY, mPost.getTitle());
- intent.putExtra(ViewVideoActivity.IS_DASH_VIDEO_KEY, mPost.isDashVideo());
- intent.putExtra(ViewVideoActivity.IS_DOWNLOADABLE_KEY, mPost.isDownloadableGifOrVideo());
- if(mPost.isDownloadableGifOrVideo()) {
- intent.putExtra(ViewVideoActivity.DOWNLOAD_URL_KEY, mPost.getGifOrVideoDownloadUrl());
- intent.putExtra(ViewVideoActivity.SUBREDDIT_KEY, mPost.getSubredditNamePrefixed());
- intent.putExtra(ViewVideoActivity.ID_KEY, mPost.getId());
- }
- startActivity(intent);
- });
- break;
- case Post.VIDEO_TYPE:
- mTypeChip.setText("VIDEO");
-
- final Uri videoUri = Uri.parse(mPost.getVideoUrl());
- mImageView.setOnClickListener(view -> {
- Intent intent = new Intent(ViewPostDetailActivity.this, ViewVideoActivity.class);
- intent.setData(videoUri);
- intent.putExtra(ViewVideoActivity.TITLE_KEY, mPost.getTitle());
- intent.putExtra(ViewVideoActivity.IS_DASH_VIDEO_KEY, mPost.isDashVideo());
- intent.putExtra(ViewVideoActivity.IS_DOWNLOADABLE_KEY, mPost.isDownloadableGifOrVideo());
- if(mPost.isDownloadableGifOrVideo()) {
- intent.putExtra(ViewVideoActivity.DOWNLOAD_URL_KEY, mPost.getGifOrVideoDownloadUrl());
- intent.putExtra(ViewVideoActivity.SUBREDDIT_KEY, mPost.getSubredditNamePrefixed());
- intent.putExtra(ViewVideoActivity.ID_KEY, mPost.getId());
- }
- startActivity(intent);
- });
- break;
- case Post.NO_PREVIEW_LINK_TYPE:
- mTypeChip.setText("LINK");
-
- linkTextView.setVisibility(View.VISIBLE);
- String noPreviewLinkDomain = Uri.parse(mPost.getUrl()).getHost();
- linkTextView.setText(noPreviewLinkDomain);
-
- if(!mPost.getSelfText().equals("")) {
- mContentMarkdownView.setVisibility(View.VISIBLE);
- mContentMarkdownView.setMarkdown(getCustomSpannableConfiguration(), mPost.getSelfText());
- }
- mNoPreviewLinkImageView.setVisibility(View.VISIBLE);
- mNoPreviewLinkImageView.setOnClickListener(view -> {
- CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
- // add share action to menu list
- builder.addDefaultShareMenuItem();
- builder.setToolbarColor(getResources().getColor(R.color.colorPrimary));
- CustomTabsIntent customTabsIntent = builder.build();
- customTabsIntent.launchUrl(ViewPostDetailActivity.this, Uri.parse(mPost.getUrl()));
- });
- break;
- case Post.TEXT_TYPE:
- mTypeChip.setText("TEXT");
-
- if(!mPost.getSelfText().equals("")) {
- mContentMarkdownView.setVisibility(View.VISIBLE);
- mContentMarkdownView.setMarkdown(getCustomSpannableConfiguration(), mPost.getSelfText());
- }
- break;
- }
- }
-
- private void initializeButtonOnClickListener() {
- mSubredditIconNameLinearLayout.setOnClickListener(view -> {
- Intent intent = new Intent(ViewPostDetailActivity.this, ViewSubredditDetailActivity.class);
- intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY,
- mPost.getSubredditNamePrefixed().substring(2));
- startActivity(intent);
- });
-
- mShareButton.setOnClickListener(view -> {
- Intent intent = new Intent(Intent.ACTION_SEND);
- intent.setType("text/plain");
- String extraText = mPost.getTitle() + "\n" + mPost.getPermalink();
- intent.putExtra(Intent.EXTRA_TEXT, extraText);
- startActivity(Intent.createChooser(intent, "Share"));
- });
-
- mUpvoteButton.setOnClickListener(view -> {
- ColorFilter previousUpvoteButtonColorFilter = mUpvoteButton.getColorFilter();
- ColorFilter previousDownvoteButtonColorFilter = mDownvoteButton.getColorFilter();
- int previousVoteType = mPost.getVoteType();
- String newVoteType;
-
- mDownvoteButton.clearColorFilter();
-
- if(previousUpvoteButtonColorFilter == null) {
- //Not upvoted before
- mPost.setVoteType(1);
- newVoteType = RedditUtils.DIR_UPVOTE;
- mUpvoteButton.setColorFilter(ContextCompat.getColor(this, R.color.backgroundColorPrimaryDark), android.graphics.PorterDuff.Mode.SRC_IN);
- } else {
- //Upvoted before
- mPost.setVoteType(0);
- newVoteType = RedditUtils.DIR_UNVOTE;
- mUpvoteButton.clearColorFilter();
- }
-
- mScoreTextView.setText(Integer.toString(mPost.getScore() + mPost.getVoteType()));
-
- if(postListPosition != -1) {
- EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition));
- }
-
- VoteThing.voteThing(mOauthRetrofit, mSharedPreferences, new VoteThing.VoteThingWithoutPositionListener() {
- @Override
- public void onVoteThingSuccess() {
- if(newVoteType.equals(RedditUtils.DIR_UPVOTE)) {
- mPost.setVoteType(1);
- mUpvoteButton.setColorFilter(ContextCompat.getColor(ViewPostDetailActivity.this, R.color.backgroundColorPrimaryDark), android.graphics.PorterDuff.Mode.SRC_IN);
- } else {
- mPost.setVoteType(0);
- mUpvoteButton.clearColorFilter();
- }
-
- mDownvoteButton.clearColorFilter();
- mScoreTextView.setText(Integer.toString(mPost.getScore() + mPost.getVoteType()));
-
- if(postListPosition != -1) {
- EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition));
- }
- }
-
- @Override
- public void onVoteThingFail() {
- Toast.makeText(ViewPostDetailActivity.this, R.string.vote_failed, Toast.LENGTH_SHORT).show();
- mPost.setVoteType(previousVoteType);
- mScoreTextView.setText(Integer.toString(mPost.getScore() + previousVoteType));
- mUpvoteButton.setColorFilter(previousUpvoteButtonColorFilter);
- mDownvoteButton.setColorFilter(previousDownvoteButtonColorFilter);
-
- if(postListPosition != -1) {
- EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition));
- }
- }
- }, mPost.getFullName(), newVoteType);
- });
-
- mDownvoteButton.setOnClickListener(view -> {
- ColorFilter previousUpvoteButtonColorFilter = mUpvoteButton.getColorFilter();
- ColorFilter previousDownvoteButtonColorFilter = mDownvoteButton.getColorFilter();
- int previousVoteType = mPost.getVoteType();
- String newVoteType;
-
- mUpvoteButton.clearColorFilter();
-
- if(previousDownvoteButtonColorFilter == null) {
- //Not upvoted before
- mPost.setVoteType(-1);
- newVoteType = RedditUtils.DIR_DOWNVOTE;
- mDownvoteButton.setColorFilter(ContextCompat.getColor(this, R.color.colorAccent), android.graphics.PorterDuff.Mode.SRC_IN);
- } else {
- //Upvoted before
- mPost.setVoteType(0);
- newVoteType = RedditUtils.DIR_UNVOTE;
- mDownvoteButton.clearColorFilter();
- }
-
- mScoreTextView.setText(Integer.toString(mPost.getScore() + mPost.getVoteType()));
-
- if(postListPosition != -1) {
- EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition));
- }
-
- VoteThing.voteThing(mOauthRetrofit, mSharedPreferences, new VoteThing.VoteThingWithoutPositionListener() {
- @Override
- public void onVoteThingSuccess() {
- if(newVoteType.equals(RedditUtils.DIR_DOWNVOTE)) {
- mPost.setVoteType(-1);
- mDownvoteButton.setColorFilter(ContextCompat.getColor(ViewPostDetailActivity.this, R.color.colorAccent), android.graphics.PorterDuff.Mode.SRC_IN);
- } else {
- mPost.setVoteType(0);
- mDownvoteButton.clearColorFilter();
- }
-
- mUpvoteButton.clearColorFilter();
- mScoreTextView.setText(Integer.toString(mPost.getScore() + mPost.getVoteType()));
-
- if(postListPosition != -1) {
- EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition));
- }
- }
-
- @Override
- public void onVoteThingFail() {
- Toast.makeText(ViewPostDetailActivity.this, R.string.vote_failed, Toast.LENGTH_SHORT).show();
- mPost.setVoteType(previousVoteType);
- mScoreTextView.setText(Integer.toString(mPost.getScore() + previousVoteType));
- mUpvoteButton.setColorFilter(previousUpvoteButtonColorFilter);
- mDownvoteButton.setColorFilter(previousDownvoteButtonColorFilter);
-
- if(postListPosition != -1) {
- EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition));
- }
- }
- }, mPost.getFullName(), newVoteType);
- });
}
private void fetchComment() {
- mCommentCardView.setVisibility(View.GONE);
- mCommentProgressbar.setVisibility(View.VISIBLE);
- mNoCommentWrapperLinearLayout.setVisibility(View.GONE);
+ mAdapter.initiallyLoading();
FetchComment.fetchComment(mRetrofit, mPost.getSubredditNamePrefixed(), mPost.getId(),
mLocale, new FetchComment.FetchCommentListener() {
@@ -503,7 +134,19 @@ public class ViewPostDetailActivity extends AppCompatActivity {
public void onFetchCommentSuccess(ArrayList<CommentData> expandedComments,
String parentId, ArrayList<String> children) {
ViewPostDetailActivity.this.children = children;
- mCommentProgressbar.setVisibility(View.GONE);
+
+ mAdapter.addComments(expandedComments);
+
+ mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
+ super.onScrolled(recyclerView, dx, dy);
+
+
+ }
+ });
+
+ /*mCommentProgressbar.setVisibility(View.GONE);
if (expandedComments.size() > 0) {
if(mAdapter == null) {
@@ -520,26 +163,34 @@ public class ViewPostDetailActivity extends AppCompatActivity {
}
mAdapter = new CommentRecyclerViewAdapter(ViewPostDetailActivity.this, mRetrofit,
- mOauthRetrofit, mSharedPreferences, expandedComments,
- mPost.getSubredditNamePrefixed(), mLocale);
+ mOauthRetrofit, mGlide, mSharedPreferences, mPost,
+ mPost.getSubredditNamePrefixed(), mLocale, new CommentRecyclerViewAdapter.UpdatePostInPostFragmentCallback() {
+ @Override
+ public void updatePost(Post post) {
+ EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition));
+ }
+ });
mRecyclerView.setAdapter(mAdapter);
- mCommentCardView.setVisibility(View.VISIBLE);
+ //mCommentCardView.setVisibility(View.VISIBLE);
} else {
mNoCommentWrapperLinearLayout.setVisibility(View.VISIBLE);
- mGlide.load(R.drawable.no_comment_indicator).into(mNoCommentImageView);
- }
+ mGlide.load(R.drawable.no_comment_placeholder).into(mNoCommentImageView);
+ }*/
}
@Override
public void onFetchCommentFailed() {
- mCommentProgressbar.setVisibility(View.GONE);
- showRetrySnackbar();
+ mAdapter.initiallyLoadCommentsFailed();
}
});
}
private void fetchMoreComment(int startingIndex) {
+ if(isLoadingMoreChildren) {
+ return;
+ }
+
isLoadingMoreChildren = true;
FetchComment.fetchMoreComment(mRetrofit, mPost.getSubredditNamePrefixed(), children, startingIndex,
0, mLocale, new FetchComment.FetchMoreCommentListener() {
@@ -560,73 +211,11 @@ public class ViewPostDetailActivity extends AppCompatActivity {
});
}
- private void loadImage() {
- RequestBuilder imageRequestBuilder = mGlide.load(mPost.getPreviewUrl())
- .apply(new RequestOptions().override(mPost.getPreviewWidth(), mPost.getPreviewHeight()))
- .listener(new RequestListener<Drawable>() {
- @Override
- public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
- mLoadImageProgressBar.setVisibility(View.GONE);
- mLoadImageErrorTextView.setVisibility(View.VISIBLE);
- mLoadImageErrorTextView.setOnClickListener(view -> {
- mLoadImageProgressBar.setVisibility(View.VISIBLE);
- mLoadImageErrorTextView.setVisibility(View.GONE);
- loadImage();
- });
- return false;
- }
-
- @Override
- public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
- mLoadWrapper.setVisibility(View.GONE);
- return false;
- }
- });
-
- if(mPost.isNSFW()) {
- imageRequestBuilder.apply(RequestOptions.bitmapTransform(new BlurTransformation(50, 2)))
- .into(mImageView);
- } else {
- imageRequestBuilder.into(mImageView);
- }
- }
-
- private SpannableConfiguration getCustomSpannableConfiguration() {
- return SpannableConfiguration.builder(this).linkResolver((view, link) -> {
- if(link.startsWith("/u/") || link.startsWith("u/")) {
- Intent intent = new Intent(ViewPostDetailActivity.this, ViewUserDetailActivity.class);
- intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, link.substring(3));
- startActivity(intent);
- } else if(link.startsWith("/r/") || link.startsWith("r/")) {
- Intent intent = new Intent(ViewPostDetailActivity.this, ViewSubredditDetailActivity.class);
- intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY, link.substring(3));
- startActivity(intent);
- } else {
- CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
- // add share action to menu list
- builder.addDefaultShareMenuItem();
- builder.setToolbarColor(getResources().getColor(R.color.colorPrimary));
- CustomTabsIntent customTabsIntent = builder.build();
- customTabsIntent.launchUrl(ViewPostDetailActivity.this, Uri.parse(link));
- }
- }).build();
- }
-
- private void showRetrySnackbar() {
- Snackbar snackbar = Snackbar.make(mCoordinatorLayout, R.string.post_load_comments_failed, Snackbar.LENGTH_INDEFINITE);
- snackbar.setAction(R.string.retry, view -> fetchComment());
- snackbar.show();
- }
-
private void refresh() {
if(!isRefreshing) {
isRefreshing = true;
mChildrenStartingIndex = 0;
- if(mAdapter != null) {
- mAdapter.clearData();
- }
-
fetchComment();
String accessToken = getSharedPreferences(SharedPreferencesUtils.AUTH_CODE_FILE_KEY, Context.MODE_PRIVATE)
@@ -636,7 +225,7 @@ public class ViewPostDetailActivity extends AppCompatActivity {
@Override
public void fetchPostSuccess(Post post) {
mPost = post;
- bindView();
+ mAdapter.updatePost(mPost);
EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition));
isRefreshing = false;
}
@@ -654,7 +243,7 @@ public class ViewPostDetailActivity extends AppCompatActivity {
public void onPostUpdateEvent(PostUpdateEventToDetailActivity event) {
if(mPost.getId().equals(event.postId)) {
mPost.setVoteType(event.voteType);
- mScoreTextView.setText(Integer.toString(mPost.getScore() + event.voteType));
+ mAdapter.updatePost(mPost);
}
}
diff --git a/app/src/main/res/drawable/no_comment_indicator.png b/app/src/main/res/drawable/no_comment_placeholder.png
index 62a3668f..62a3668f 100644
--- a/app/src/main/res/drawable/no_comment_indicator.png
+++ b/app/src/main/res/drawable/no_comment_placeholder.png
Binary files differ
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 0c9f6786..7416ed7a 100644
--- a/app/src/main/res/layout/activity_view_post_detail.xml
+++ b/app/src/main/res/layout/activity_view_post_detail.xml
@@ -21,339 +21,10 @@
</com.google.android.material.appbar.AppBarLayout>
- <androidx.core.widget.NestedScrollView
- android:id="@+id/nested_scroll_view_view_post_detail_activity"
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/recycler_view_view_post_detail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- app:layout_behavior="@string/appbar_scrolling_view_behavior">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:descendantFocusability="blocksDescendants">
-
- <com.google.android.material.card.MaterialCardView
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <androidx.constraintlayout.widget.ConstraintLayout
- android:id="@+id/relative_layout_view_post_detail"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <LinearLayout
- android:id="@+id/subreddit_icon_name_linear_layout_view_post_detail"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:padding="16dp"
- app:layout_constrainedWidth="true"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toStartOf="@id/post_time_text_view_view_post_detail"
- app:layout_constraintTop_toTopOf="parent">
-
- <CustomView.AspectRatioGifImageView
- android:id="@+id/subreddit_icon_circle_image_view_view_post_detail"
- android:layout_width="24dp"
- android:layout_height="24dp"
- android:layout_gravity="center"/>
-
- <TextView
- android:id="@+id/subreddit_text_view_view_post_detail"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="16dp"
- android:layout_gravity="center"
- android:textColor="#E91E63" />
-
- </LinearLayout>
-
- <TextView
- android:id="@+id/post_time_text_view_view_post_detail"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:layout_marginEnd="16dp"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toEndOf="@id/subreddit_icon_name_linear_layout_view_post_detail"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintTop_toTopOf="parent"/>
-
- </androidx.constraintlayout.widget.ConstraintLayout>
-
- <TextView
- android:id="@+id/title_text_view_view_post_detail"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingStart="16dp"
- android:paddingEnd="16dp"
- android:textColor="@color/primaryTextColor"
- android:textSize="18sp" />
-
- <ru.noties.markwon.view.MarkwonView
- android:id="@+id/content_markdown_view_view_post_detail"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingStart="16dp"
- android:paddingEnd="16dp"
- android:layout_marginTop="16dp"
- android:visibility="gone" />
-
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingStart="16dp"
- android:paddingEnd="16dp"
- android:paddingTop="16dp">
-
- <com.google.android.material.chip.Chip
- android:id="@+id/type_text_view_view_post_detail"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginEnd="16dp"
- android:textColor="@android:color/white"
- android:layout_centerVertical="true"
- app:chipBackgroundColor="@color/backgroundColorPrimaryDark"/>
-
- <ImageView
- android:id="@+id/gilded_image_view_view_post_detail"
- android:layout_width="24dp"
- android:layout_height="24dp"
- android:layout_toEndOf="@id/type_text_view_view_post_detail"
- android:layout_centerVertical="true"
- android:visibility="gone"/>
-
- <TextView
- android:id="@+id/gilded_number_text_view_view_post_detail"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="4dp"
- android:layout_marginEnd="8dp"
- android:layout_toEndOf="@id/gilded_image_view_view_post_detail"
- android:layout_centerVertical="true"
- android:visibility="gone"
- android:textSize="20sp"
- android:textColor="@color/gold"/>
-
- <ImageView
- android:id="@+id/crosspost_image_view_view_post_detail"
- android:layout_width="24dp"
- android:layout_height="24dp"
- android:layout_marginStart="8dp"
- android:layout_marginEnd="8dp"
- android:layout_toEndOf="@id/gilded_number_text_view_view_post_detail"
- android:layout_centerVertical="true"
- android:src="@drawable/crosspost"
- android:tint="@color/colorAccent"
- android:visibility="gone"/>
-
- <com.google.android.material.chip.Chip
- android:id="@+id/nsfw_text_view_view_post_detail"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/nsfw"
- android:layout_alignParentEnd="true"
- android:layout_marginStart="8dp"
- android:textColor="@android:color/white"
- android:visibility="gone"
- android:layout_centerVertical="true"
- app:chipBackgroundColor="@color/colorAccent"/>
-
- </RelativeLayout>
-
- <TextView
- android:id="@+id/link_text_view_view_post_detail"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingStart="16dp"
- android:paddingEnd="16dp"
- android:textSize="12sp"
- android:visibility="gone"/>
-
- <RelativeLayout
- android:id="@+id/image_view_wrapper_view_post_detail"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="16dp"
- android:visibility="gone">
-
- <com.santalu.aspectratioimageview.AspectRatioImageView
- android:id="@+id/image_view_view_post_detail"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:adjustViewBounds="true"
- android:scaleType="fitStart"/>
-
- <RelativeLayout
- android:id="@+id/load_wrapper_view_post_detail"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true">
-
- <ProgressBar
- android:id="@+id/progress_bar_view_post_detail"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true" />
-
- <TextView
- android:id="@+id/load_image_error_text_view_view_post_detail"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:drawableTop="@drawable/ic_error_outline_black_24dp"
- android:layout_centerInParent="true"
- android:gravity="center"
- android:text="@string/tap_to_retry"
- android:visibility="gone" />
-
- </RelativeLayout>
-
- </RelativeLayout>
-
- <ImageView
- android:id="@+id/image_view_no_preview_link_view_post_detail"
- android:layout_width="match_parent"
- android:layout_height="150dp"
- android:layout_marginTop="16dp"
- android:background="@color/grey"
- android:scaleType="center"
- android:src="@drawable/ic_link"
- android:tint="@android:color/tab_indicator_text"
- android:visibility="gone" />
-
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <ImageView
- android:id="@+id/plus_button_view_post_detail"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentStart="true"
- android:layout_centerVertical="true"
- android:background="?actionBarItemBackground"
- android:clickable="true"
- android:focusable="true"
- android:padding="16dp"
- android:src="@drawable/ic_arrow_upward_black_24dp"
- android:tint="@android:color/tab_indicator_text" />
-
- <TextView
- android:id="@+id/score_text_view_view_post_detail"
- android:layout_width="64dp"
- android:layout_height="wrap_content"
- android:layout_centerVertical="true"
- android:layout_toEndOf="@id/plus_button_view_post_detail"
- android:gravity="center" />
-
- <ImageView
- android:id="@+id/minus_button_view_post_detail"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerVertical="true"
- android:layout_toEndOf="@id/score_text_view_view_post_detail"
- android:background="?actionBarItemBackground"
- android:clickable="true"
- android:focusable="true"
- android:padding="16dp"
- android:src="@drawable/ic_arrow_downward_black_24dp"
- android:tint="@android:color/tab_indicator_text" />
-
- <ImageView
- android:id="@+id/share_button_view_post_detail"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentEnd="true"
- android:layout_centerVertical="true"
- android:background="?actionBarItemBackground"
- android:clickable="true"
- android:focusable="true"
- android:padding="16dp"
- android:src="@drawable/ic_outline_share_24px"
- android:tint="@android:color/tab_indicator_text" />
-
- </RelativeLayout>
-
- </LinearLayout>
-
- </com.google.android.material.card.MaterialCardView>
-
- <com.lsjwzh.widget.materialloadingprogressbar.CircleProgressBar
- android:id="@+id/comment_progress_bar_view_post_detail"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="16dp"
- android:layout_marginBottom="16dp"
- app:mlpb_progress_stoke_width="3dp"
- app:mlpb_progress_color="@color/colorAccent"
- app:mlpb_background_color="@color/circularProgressBarBackground"
- android:layout_gravity="center_horizontal"/>
-
- <com.google.android.material.card.MaterialCardView
- android:id="@+id/comment_card_view_view_post_detail"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="16dp"
- android:visibility="gone">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
-
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingEnd="16dp"
- android:paddingLeft="16dp"
- android:paddingRight="16dp"
- android:paddingStart="16dp"
- android:paddingTop="16dp"
- android:text="@string/comments"
- android:textColor="@color/primaryTextColor"
- android:textSize="18sp" />
-
- <androidx.recyclerview.widget.RecyclerView
- android:id="@+id/recycler_view_view_post_detail"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
- </LinearLayout>
-
- </com.google.android.material.card.MaterialCardView>
-
- <LinearLayout
- android:id="@+id/no_comment_wrapper_linear_layout_view_post_detail"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="48dp"
- android:layout_marginBottom="48dp"
- android:orientation="vertical"
- android:visibility="gone">
-
- <ImageView
- android:id="@+id/no_comment_image_view_view_post_detail"
- android:layout_width="150dp"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal" />
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="16dp"
- android:layout_gravity="center_horizontal"
- android:text="@string/no_comments_yet"/>
-
- </LinearLayout>
-
- </LinearLayout>
-
- </androidx.core.widget.NestedScrollView>
+ app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/item_load_comments.xml b/app/src/main/res/layout/item_load_comments.xml
new file mode 100644
index 00000000..06bc8c38
--- /dev/null
+++ b/app/src/main/res/layout/item_load_comments.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <com.lsjwzh.widget.materialloadingprogressbar.CircleProgressBar
+ android:id="@+id/comment_progress_bar_view_post_detail"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:layout_marginBottom="16dp"
+ app:mlpb_progress_stoke_width="3dp"
+ app:mlpb_progress_color="@color/colorAccent"
+ app:mlpb_background_color="@color/circularProgressBarBackground"
+ android:layout_gravity="center_horizontal"/>
+
+</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/item_load_comments_failed_placeholder.xml b/app/src/main/res/layout/item_load_comments_failed_placeholder.xml
new file mode 100644
index 00000000..476d3d2d
--- /dev/null
+++ b/app/src/main/res/layout/item_load_comments_failed_placeholder.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:padding="36dp"
+ android:text="@string/post_load_comments_failed"
+ android:drawableTop="@drawable/load_post_error_indicator"/> \ No newline at end of file
diff --git a/app/src/main/res/layout/item_no_comment_placeholder.xml b/app/src/main/res/layout/item_no_comment_placeholder.xml
new file mode 100644
index 00000000..becf93d4
--- /dev/null
+++ b/app/src/main/res/layout/item_no_comment_placeholder.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/no_comments_yet"
+ android:gravity="center"
+ android:padding="36dp"
+ android:drawableTop="@drawable/no_comment_placeholder"/> \ No newline at end of file
diff --git a/app/src/main/res/layout/item_post_detail.xml b/app/src/main/res/layout/item_post_detail.xml
new file mode 100644
index 00000000..870d21ef
--- /dev/null
+++ b/app/src/main/res/layout/item_post_detail.xml
@@ -0,0 +1,252 @@
+<?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"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/relative_layout_item_post_detail"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <LinearLayout
+ android:id="@+id/subreddit_icon_name_linear_layout_item_post_detail"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:padding="16dp"
+ app:layout_constrainedWidth="true"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toStartOf="@id/post_time_text_view_item_post_detail"
+ app:layout_constraintTop_toTopOf="parent">
+
+ <CustomView.AspectRatioGifImageView
+ android:id="@+id/subreddit_icon_circle_image_view_item_post_detail"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_gravity="center"/>
+
+ <TextView
+ android:id="@+id/subreddit_text_view_item_post_detail"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="16dp"
+ android:layout_gravity="center"
+ android:textColor="#E91E63" />
+
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/post_time_text_view_item_post_detail"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_marginEnd="16dp"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@id/subreddit_icon_name_linear_layout_item_post_detail"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="parent"/>
+
+ </androidx.constraintlayout.widget.ConstraintLayout>
+
+ <TextView
+ android:id="@+id/title_text_view_item_post_detail"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:textColor="@color/primaryTextColor"
+ android:textSize="18sp" />
+
+ <ru.noties.markwon.view.MarkwonView
+ android:id="@+id/content_markdown_view_item_post_detail"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:layout_marginTop="16dp"
+ android:visibility="gone" />
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:paddingTop="16dp">
+
+ <com.google.android.material.chip.Chip
+ android:id="@+id/type_text_view_item_post_detail"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="16dp"
+ android:textColor="@android:color/white"
+ android:layout_centerVertical="true"
+ app:chipBackgroundColor="@color/backgroundColorPrimaryDark"/>
+
+ <ImageView
+ android:id="@+id/gilded_image_view_item_post_detail"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_toEndOf="@id/type_text_view_item_post_detail"
+ android:layout_centerVertical="true"
+ android:visibility="gone"/>
+
+ <TextView
+ android:id="@+id/gilded_number_text_view_item_post_detail"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="4dp"
+ android:layout_marginEnd="8dp"
+ android:layout_toEndOf="@id/gilded_image_view_item_post_detail"
+ android:layout_centerVertical="true"
+ android:visibility="gone"
+ android:textSize="20sp"
+ android:textColor="@color/gold"/>
+
+ <ImageView
+ android:id="@+id/crosspost_image_view_item_post_detail"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_marginStart="8dp"
+ android:layout_marginEnd="8dp"
+ android:layout_toEndOf="@id/gilded_number_text_view_item_post_detail"
+ android:layout_centerVertical="true"
+ android:src="@drawable/crosspost"
+ android:tint="@color/colorAccent"
+ android:visibility="gone"/>
+
+ <com.google.android.material.chip.Chip
+ android:id="@+id/nsfw_text_view_item_post_detail"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/nsfw"
+ android:layout_alignParentEnd="true"
+ android:layout_marginStart="8dp"
+ android:textColor="@android:color/white"
+ android:visibility="gone"
+ android:layout_centerVertical="true"
+ app:chipBackgroundColor="@color/colorAccent"/>
+
+ </RelativeLayout>
+
+ <TextView
+ android:id="@+id/link_text_view_item_post_detail"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:textSize="12sp"
+ android:visibility="gone"/>
+
+ <RelativeLayout
+ android:id="@+id/image_view_wrapper_item_post_detail"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:visibility="gone">
+
+ <com.santalu.aspectratioimageview.AspectRatioImageView
+ android:id="@+id/image_view_item_post_detail"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:adjustViewBounds="true"
+ android:scaleType="fitStart"/>
+
+ <RelativeLayout
+ android:id="@+id/load_wrapper_item_post_detail"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_centerInParent="true">
+
+ <ProgressBar
+ android:id="@+id/progress_bar_item_post_detail"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerInParent="true" />
+
+ <TextView
+ android:id="@+id/load_image_error_text_view_item_post_detail"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:drawableTop="@drawable/ic_error_outline_black_24dp"
+ android:layout_centerInParent="true"
+ android:gravity="center"
+ android:text="@string/tap_to_retry"
+ android:visibility="gone" />
+
+ </RelativeLayout>
+
+ </RelativeLayout>
+
+ <ImageView
+ android:id="@+id/image_view_no_preview_link_item_post_detail"
+ android:layout_width="match_parent"
+ android:layout_height="150dp"
+ android:layout_marginTop="16dp"
+ android:background="@color/grey"
+ android:scaleType="center"
+ android:src="@drawable/ic_link"
+ android:tint="@android:color/tab_indicator_text"
+ android:visibility="gone" />
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <ImageView
+ android:id="@+id/plus_button_item_post_detail"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentStart="true"
+ android:layout_centerVertical="true"
+ android:background="?actionBarItemBackground"
+ android:clickable="true"
+ android:focusable="true"
+ android:padding="16dp"
+ android:src="@drawable/ic_arrow_upward_black_24dp"
+ android:tint="@android:color/tab_indicator_text" />
+
+ <TextView
+ android:id="@+id/score_text_view_item_post_detail"
+ android:layout_width="64dp"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:layout_toEndOf="@id/plus_button_item_post_detail"
+ android:gravity="center" />
+
+ <ImageView
+ android:id="@+id/minus_button_item_post_detail"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:layout_toEndOf="@id/score_text_view_item_post_detail"
+ android:background="?actionBarItemBackground"
+ android:clickable="true"
+ android:focusable="true"
+ android:padding="16dp"
+ android:src="@drawable/ic_arrow_downward_black_24dp"
+ android:tint="@android:color/tab_indicator_text" />
+
+ <ImageView
+ android:id="@+id/share_button_item_post_detail"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentEnd="true"
+ android:layout_centerVertical="true"
+ android:background="?actionBarItemBackground"
+ android:clickable="true"
+ android:focusable="true"
+ android:padding="16dp"
+ android:src="@drawable/ic_outline_share_24px"
+ android:tint="@android:color/tab_indicator_text" />
+
+ </RelativeLayout>
+
+ </LinearLayout>
+
+</com.google.android.material.card.MaterialCardView> \ No newline at end of file