diff options
author | Alex Ning <chineseperson5@gmail.com> | 2019-06-25 01:21:44 +0000 |
---|---|---|
committer | Alex Ning <chineseperson5@gmail.com> | 2019-06-25 01:21:44 +0000 |
commit | c4690a6e38004fa0442e6c15b9637ee209e9c2dd (patch) | |
tree | 4434cae708a07cb04eaa597a82312c45c410e780 /app/src | |
parent | 34d49d884c5fc639204d0e464455e0d898a987e4 (diff) | |
download | infinity-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 '')
-rw-r--r-- | app/src/main/java/ml/docilealligator/infinityforreddit/CommentRecyclerViewAdapter.java | 644 | ||||
-rw-r--r-- | app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java | 2 | ||||
-rw-r--r-- | app/src/main/java/ml/docilealligator/infinityforreddit/LoadSubredditIconAsyncTask.java | 4 | ||||
-rw-r--r-- | app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java | 2 | ||||
-rw-r--r-- | app/src/main/java/ml/docilealligator/infinityforreddit/ViewPostDetailActivity.java | 499 | ||||
-rw-r--r-- | app/src/main/res/drawable/no_comment_placeholder.png (renamed from app/src/main/res/drawable/no_comment_indicator.png) | bin | 60561 -> 60561 bytes | |||
-rw-r--r-- | app/src/main/res/layout/activity_view_post_detail.xml | 335 | ||||
-rw-r--r-- | app/src/main/res/layout/item_load_comments.xml | 19 | ||||
-rw-r--r-- | app/src/main/res/layout/item_load_comments_failed_placeholder.xml | 8 | ||||
-rw-r--r-- | app/src/main/res/layout/item_no_comment_placeholder.xml | 8 | ||||
-rw-r--r-- | app/src/main/res/layout/item_post_detail.xml | 252 |
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 Binary files differindex 62a3668f..62a3668f 100644 --- a/app/src/main/res/drawable/no_comment_indicator.png +++ b/app/src/main/res/drawable/no_comment_placeholder.png 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 |