From 033c8bd24184258904f68bee13b96b6c491fec05 Mon Sep 17 00:00:00 2001 From: Alex Ning Date: Wed, 29 Apr 2020 18:13:28 +0800 Subject: Buggy video and Gif autoplay. --- app/build.gradle | 2 + .../Adapter/PostRecyclerViewAdapter.java | 1395 +++++++++++++++----- .../infinityforreddit/AppModule.java | 19 + .../infinityforreddit/Fragment/PostFragment.java | 33 +- .../exo_player_autoplay_button_background.xml | 9 + .../layout/exo_autoplay_playback_control_view.xml | 70 + app/src/main/res/layout/fragment_post.xml | 8 +- app/src/main/res/layout/item_post_gif_type.xml | 314 +++++ app/src/main/res/layout/item_post_image_type.xml | 314 +++++ app/src/main/res/layout/item_post_link_type.xml | 324 +++++ .../res/layout/item_post_no_preview_link_type.xml | 293 ++++ app/src/main/res/layout/item_post_text_type.xml | 288 ++++ .../res/layout/item_post_video_type_autoplay.xml | 289 ++++ build.gradle | 1 + 14 files changed, 3016 insertions(+), 343 deletions(-) create mode 100644 app/src/main/res/drawable/exo_player_autoplay_button_background.xml create mode 100644 app/src/main/res/layout/exo_autoplay_playback_control_view.xml create mode 100644 app/src/main/res/layout/item_post_gif_type.xml create mode 100644 app/src/main/res/layout/item_post_image_type.xml create mode 100644 app/src/main/res/layout/item_post_link_type.xml create mode 100644 app/src/main/res/layout/item_post_no_preview_link_type.xml create mode 100644 app/src/main/res/layout/item_post_text_type.xml create mode 100644 app/src/main/res/layout/item_post_video_type_autoplay.xml diff --git a/app/build.gradle b/app/build.gradle index 6a76e789..707333bf 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -86,4 +86,6 @@ dependencies { implementation 'com.atlassian.commonmark:commonmark:0.13.1' implementation 'com.google.code.gson:gson:2.8.6' implementation 'me.zhanghai.android.fastscroll:library:1.1.2' + implementation "im.ene.toro3:toro:$rootProject.toroVersion" + implementation "im.ene.toro3:toro-ext-exoplayer:$rootProject.toroVersion" } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java index 38aa8b00..55a75184 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java @@ -1,14 +1,13 @@ package ml.docilealligator.infinityforreddit.Adapter; import android.content.Intent; +import android.content.SharedPreferences; import android.content.res.ColorStateList; import android.graphics.ColorFilter; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; -import android.text.Html; -import android.text.Spannable; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -38,6 +37,8 @@ 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.exoplayer2.ui.AspectRatioFrameLayout; +import com.google.android.exoplayer2.ui.PlayerView; import com.google.android.material.card.MaterialCardView; import com.libRG.CustomTextView; @@ -45,6 +46,13 @@ import org.greenrobot.eventbus.EventBus; import butterknife.BindView; import butterknife.ButterKnife; +import im.ene.toro.CacheManager; +import im.ene.toro.ToroPlayer; +import im.ene.toro.ToroUtil; +import im.ene.toro.exoplayer.ExoCreator; +import im.ene.toro.exoplayer.ExoPlayerViewHelper; +import im.ene.toro.media.PlaybackInfo; +import im.ene.toro.widget.Container; import jp.wasabeef.glide.transformations.BlurTransformation; import jp.wasabeef.glide.transformations.RoundedCornersTransformation; import ml.docilealligator.infinityforreddit.Activity.FilteredThingActivity; @@ -68,7 +76,6 @@ import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; import ml.docilealligator.infinityforreddit.SaveThing; import ml.docilealligator.infinityforreddit.User.UserDao; -import ml.docilealligator.infinityforreddit.Utils.GlideImageGetter; import ml.docilealligator.infinityforreddit.Utils.RedditUtils; import ml.docilealligator.infinityforreddit.Utils.SharedPreferencesUtils; import ml.docilealligator.infinityforreddit.Utils.Utils; @@ -79,10 +86,16 @@ import retrofit2.Retrofit; * Created by alex on 2/25/18. */ -public class PostRecyclerViewAdapter extends PagedListAdapter { - private static final int VIEW_TYPE_DATA = 0; - private static final int VIEW_TYPE_ERROR = 1; - private static final int VIEW_TYPE_LOADING = 2; +public class PostRecyclerViewAdapter extends PagedListAdapter implements CacheManager { + private static final int VIEW_TYPE_POST_CARD_VIDEO_TYPE_AUTOPLAY = 1; + private static final int VIEW_TYPE_POST_CARD_GIF_TYPE = 2; + private static final int VIEW_TYPE_POST_CARD_IMAGE_TYPE = 3; + private static final int VIEW_TYPE_POST_CARD_LINK_TYPE = 4; + private static final int VIEW_TYPE_POST_CARD_NO_PREVIEW_LINK_TYPE = 5; + private static final int VIEW_TYPE_POST_CARD_TEXT_TYPE = 6; + private static final int VIEW_TYPE_POST_COMPACT = 7; + private static final int VIEW_TYPE_ERROR = 8; + private static final int VIEW_TYPE_LOADING = 9; private static final DiffUtil.ItemCallback DIFF_CALLBACK = new DiffUtil.ItemCallback() { @Override public boolean areItemsTheSame(@NonNull Post post, @NonNull Post t1) { @@ -140,12 +153,79 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { + ((PostBaseViewHolder) holder).cardView.setOnClickListener(view -> { if (canStartActivity) { canStartActivity = false; @@ -260,9 +378,9 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { + ((PostBaseViewHolder) holder).subredditTextView.setText(subredditNamePrefixed); + ((PostBaseViewHolder) holder).userTextView.setText(authorPrefixed); + ((PostBaseViewHolder) holder).userTextView.setOnClickListener(view -> { if (canStartActivity) { canStartActivity = false; Intent intent = new Intent(mActivity, ViewUserDetailActivity.class); @@ -279,13 +397,13 @@ public class PostRecyclerViewAdapter extends PagedListAdapter= 0) { @@ -298,11 +416,11 @@ public class PostRecyclerViewAdapter extends PagedListAdapter= 0) { @@ -331,15 +449,15 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { + ((PostBaseViewHolder) holder).subredditTextView.setOnClickListener(view -> { if (canStartActivity) { canStartActivity = false; if (post.getSubredditNamePrefixed().startsWith("u/")) { @@ -356,8 +474,8 @@ public class PostRecyclerViewAdapter extends PagedListAdapter - ((PostViewHolder) holder).subredditTextView.performClick()); + ((PostBaseViewHolder) holder).iconGifImageView.setOnClickListener(view -> + ((PostBaseViewHolder) holder).subredditTextView.performClick()); } else { if (post.getAuthorIconUrl() == null) { String authorName = post.getAuthor().equals("[deleted]") ? post.getSubredditNamePrefixed().substring(2) : post.getAuthor(); @@ -366,13 +484,13 @@ public class PostRecyclerViewAdapter extends PagedListAdapter= 0) { @@ -385,14 +503,14 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { + ((PostBaseViewHolder) holder).subredditTextView.setOnClickListener(view -> { if (canStartActivity) { canStartActivity = false; if (post.getSubredditNamePrefixed().startsWith("u/")) { @@ -408,27 +526,27 @@ public class PostRecyclerViewAdapter extends PagedListAdapter - ((PostViewHolder) holder).userTextView.performClick()); + ((PostBaseViewHolder) holder).iconGifImageView.setOnClickListener(view -> + ((PostBaseViewHolder) holder).userTextView.performClick()); } if (mShowElapsedTime) { - ((PostViewHolder) holder).postTimeTextView.setText( + ((PostBaseViewHolder) holder).postTimeTextView.setText( Utils.getElapsedTime(mActivity, post.getPostTimeMillis())); } else { - ((PostViewHolder) holder).postTimeTextView.setText(postTime); + ((PostBaseViewHolder) holder).postTimeTextView.setText(post.getPostTime()); } - ((PostViewHolder) holder).titleTextView.setText(title); - ((PostViewHolder) holder).scoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, post.getScore() + post.getVoteType())); + ((PostBaseViewHolder) holder).titleTextView.setText(post.getTitle()); + ((PostBaseViewHolder) holder).scoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, post.getScore() + post.getVoteType())); if (post.isLocked()) { - ((PostViewHolder) holder).lockedImageView.setVisibility(View.VISIBLE); + ((PostBaseViewHolder) holder).lockedImageView.setVisibility(View.VISIBLE); } - if (nsfw) { + if (post.isNSFW()) { if (!(mActivity instanceof FilteredThingActivity)) { - ((PostViewHolder) holder).nsfwTextView.setOnClickListener(view -> { + ((PostBaseViewHolder) holder).nsfwTextView.setOnClickListener(view -> { Intent intent = new Intent(mActivity, FilteredThingActivity.class); intent.putExtra(FilteredThingActivity.EXTRA_NAME, post.getSubredditNamePrefixed().substring(2)); intent.putExtra(FilteredThingActivity.EXTRA_POST_TYPE, PostDataSource.TYPE_SUBREDDIT); @@ -436,176 +554,71 @@ public class PostRecyclerViewAdapter extends PagedListAdapter= android.os.Build.VERSION_CODES.N) { - flairHTML = (Spannable) Html.fromHtml(flair, Html.FROM_HTML_MODE_LEGACY, glideImageGetter, null); - } else { - flairHTML = (Spannable) Html.fromHtml(flair, glideImageGetter, null); - } - ((PostViewHolder) holder).flairTextView.setText(flairHTML); + Utils.setHTMLWithImageToTextView(((PostBaseViewHolder) holder).flairTextView, flair); } if (nAwards > 0) { - ((PostViewHolder) holder).awardsTextView.setVisibility(View.VISIBLE); + ((PostBaseViewHolder) holder).awardsTextView.setVisibility(View.VISIBLE); if (nAwards == 1) { - ((PostViewHolder) holder).awardsTextView.setText(mActivity.getString(R.string.one_award)); + ((PostBaseViewHolder) holder).awardsTextView.setText(mActivity.getString(R.string.one_award)); } else { - ((PostViewHolder) holder).awardsTextView.setText(mActivity.getString(R.string.n_awards, nAwards)); + ((PostBaseViewHolder) holder).awardsTextView.setText(mActivity.getString(R.string.n_awards, nAwards)); } } - switch (voteType) { + switch (post.getVoteType()) { case 1: //Upvoted - ((PostViewHolder) holder).upvoteButton.setColorFilter(mUpvotedColor, android.graphics.PorterDuff.Mode.SRC_IN); - ((PostViewHolder) holder).scoreTextView.setTextColor(mUpvotedColor); + ((PostBaseViewHolder) holder).upvoteButton.setColorFilter(mUpvotedColor, android.graphics.PorterDuff.Mode.SRC_IN); + ((PostBaseViewHolder) holder).scoreTextView.setTextColor(mUpvotedColor); break; case -1: //Downvoted - ((PostViewHolder) holder).downvoteButton.setColorFilter(mDownvotedColor, android.graphics.PorterDuff.Mode.SRC_IN); - ((PostViewHolder) holder).scoreTextView.setTextColor(mDownvotedColor); + ((PostBaseViewHolder) holder).downvoteButton.setColorFilter(mDownvotedColor, android.graphics.PorterDuff.Mode.SRC_IN); + ((PostBaseViewHolder) holder).scoreTextView.setTextColor(mDownvotedColor); break; } - if (post.getPostType() != Post.TEXT_TYPE && post.getPostType() != Post.NO_PREVIEW_LINK_TYPE) { - ((PostViewHolder) holder).relativeLayout.setVisibility(View.VISIBLE); - ((PostViewHolder) holder).progressBar.setVisibility(View.VISIBLE); - ((PostViewHolder) holder).imageView.setVisibility(View.VISIBLE); - ((PostViewHolder) holder).imageView - .setRatio((float) post.getPreviewHeight() / post.getPreviewWidth()); - loadImage(holder, post); - } - if (mPostType == PostDataSource.TYPE_SUBREDDIT && !mDisplaySubredditName && post.isStickied()) { - ((PostViewHolder) holder).stickiedPostImageView.setVisibility(View.VISIBLE); - mGlide.load(R.drawable.ic_thumbtack_24dp).into(((PostViewHolder) holder).stickiedPostImageView); + ((PostBaseViewHolder) holder).stickiedPostImageView.setVisibility(View.VISIBLE); + mGlide.load(R.drawable.ic_thumbtack_24dp).into(((PostBaseViewHolder) holder).stickiedPostImageView); } if (isArchived) { - ((PostViewHolder) holder).archivedImageView.setVisibility(View.VISIBLE); + ((PostBaseViewHolder) holder).archivedImageView.setVisibility(View.VISIBLE); - ((PostViewHolder) holder).upvoteButton + ((PostBaseViewHolder) holder).upvoteButton .setColorFilter(mVoteAndReplyUnavailableVoteButtonColor, android.graphics.PorterDuff.Mode.SRC_IN); - ((PostViewHolder) holder).downvoteButton + ((PostBaseViewHolder) holder).downvoteButton .setColorFilter(mVoteAndReplyUnavailableVoteButtonColor, android.graphics.PorterDuff.Mode.SRC_IN); } if (post.isCrosspost()) { - ((PostViewHolder) holder).crosspostImageView.setVisibility(View.VISIBLE); + ((PostBaseViewHolder) holder).crosspostImageView.setVisibility(View.VISIBLE); } if (!(mActivity instanceof FilteredThingActivity)) { - ((PostViewHolder) holder).typeTextView.setOnClickListener(view -> mCallback.typeChipClicked(post.getPostType())); + ((PostBaseViewHolder) holder).typeTextView.setOnClickListener(view -> mCallback.typeChipClicked(post.getPostType())); } switch (post.getPostType()) { - case Post.IMAGE_TYPE: - ((PostViewHolder) holder).typeTextView.setText(R.string.image); - - final String imageUrl = post.getUrl(); - ((PostViewHolder) holder).imageView.setOnClickListener(view -> { - Intent intent = new Intent(mActivity, ViewImageActivity.class); - intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, imageUrl); - intent.putExtra(ViewImageActivity.FILE_NAME_KEY, subredditName - + "-" + id + ".jpg"); - intent.putExtra(ViewImageActivity.POST_TITLE_KEY, post.getTitle()); - mActivity.startActivity(intent); - }); - - if (post.getPreviewWidth() <= 0 || post.getPreviewHeight() <= 0) { - ((PostViewHolder) holder).imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); - ((PostViewHolder) holder).imageView.getLayoutParams().height = (int) (400 * mScale); - } - break; - case Post.LINK_TYPE: - ((PostViewHolder) holder).typeTextView.setText(R.string.link); - - ((PostViewHolder) holder).linkTextView.setVisibility(View.VISIBLE); - String domain = Uri.parse(post.getUrl()).getHost(); - ((PostViewHolder) holder).linkTextView.setText(domain); - - ((PostViewHolder) holder).imageView.setOnClickListener(view -> { - Intent intent = new Intent(mActivity, LinkResolverActivity.class); - Uri uri = Uri.parse(post.getUrl()); - if (uri.getScheme() == null && uri.getHost() == null) { - intent.setData(LinkResolverActivity.getRedditUriByPath(post.getUrl())); - } else { - intent.setData(uri); - } - mActivity.startActivity(intent); - }); - break; case Post.GIF_TYPE: - ((PostViewHolder) holder).typeTextView.setText(R.string.gif); - - final Uri gifVideoUri = Uri.parse(post.getVideoUrl()); - ((PostViewHolder) holder).imageView.setOnClickListener(view -> { - Intent intent = new Intent(mActivity, ViewGIFActivity.class); - intent.setData(gifVideoUri); - intent.putExtra(ViewGIFActivity.FILE_NAME_KEY, subredditName - + "-" + id + ".gif"); - intent.putExtra(ViewGIFActivity.GIF_URL_KEY, post.getVideoUrl()); - intent.putExtra(ViewGIFActivity.POST_TITLE_KEY, post.getTitle()); - mActivity.startActivity(intent); - }); - - ((PostViewHolder) holder).playButtonImageView.setVisibility(View.VISIBLE); + ((PostBaseViewHolder) holder).typeTextView.setText(R.string.gif); break; case Post.VIDEO_TYPE: - ((PostViewHolder) holder).typeTextView.setText(R.string.video); - - final Uri videoUri = Uri.parse(post.getVideoUrl()); - ((PostViewHolder) holder).imageView.setOnClickListener(view -> { - Intent intent = new Intent(mActivity, ViewVideoActivity.class); - intent.setData(videoUri); - intent.putExtra(ViewVideoActivity.EXTRA_VIDEO_DOWNLOAD_URL, post.getVideoDownloadUrl()); - intent.putExtra(ViewVideoActivity.EXTRA_SUBREDDIT, subredditName); - intent.putExtra(ViewVideoActivity.EXTRA_ID, fullName); - intent.putExtra(ViewVideoActivity.EXTRA_POST_TITLE, post.getTitle()); - mActivity.startActivity(intent); - }); - - ((PostViewHolder) holder).playButtonImageView.setVisibility(View.VISIBLE); - break; - case Post.NO_PREVIEW_LINK_TYPE: - ((PostViewHolder) holder).typeTextView.setText(R.string.link); - - String noPreviewLinkUrl = post.getUrl(); - ((PostViewHolder) holder).linkTextView.setVisibility(View.VISIBLE); - String noPreviewLinkDomain = Uri.parse(noPreviewLinkUrl).getHost(); - ((PostViewHolder) holder).linkTextView.setText(noPreviewLinkDomain); - ((PostViewHolder) holder).noPreviewLinkImageView.setVisibility(View.VISIBLE); - ((PostViewHolder) holder).noPreviewLinkImageView.setOnClickListener(view -> { - Intent intent = new Intent(mActivity, LinkResolverActivity.class); - Uri uri = Uri.parse(post.getUrl()); - if (uri.getScheme() == null && uri.getHost() == null) { - intent.setData(LinkResolverActivity.getRedditUriByPath(post.getUrl())); - } else { - intent.setData(uri); - } - mActivity.startActivity(intent); - }); - break; - case Post.TEXT_TYPE: - ((PostViewHolder) holder).typeTextView.setText(R.string.text); - if (post.getSelfTextPlainTrimmed() != null && !post.getSelfTextPlainTrimmed().equals("")) { - ((PostViewHolder) holder).contentTextView.setVisibility(View.VISIBLE); - ((PostViewHolder) holder).contentTextView.setText(post.getSelfTextPlainTrimmed()); - } + ((PostBaseViewHolder) holder).typeTextView.setText(R.string.video); break; } - ((PostViewHolder) holder).upvoteButton.setOnClickListener(view -> { + ((PostBaseViewHolder) holder).upvoteButton.setOnClickListener(view -> { if (mAccessToken == null) { Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); return; @@ -616,48 +629,48 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { + ((PostBaseViewHolder) holder).downvoteButton.setOnClickListener(view -> { if (mAccessToken == null) { Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); return; @@ -687,48 +700,48 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { + ((PostBaseViewHolder) holder).saveButton.setOnClickListener(view -> { if (mAccessToken == null) { Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); return; } if (post.isSaved()) { - ((PostViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_border_grey_24dp); + ((PostBaseViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_border_grey_24dp); SaveThing.unsaveThing(mOauthRetrofit, mAccessToken, post.getFullName(), new SaveThing.SaveThingListener() { @Override public void success() { post.setSaved(false); - ((PostViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_border_grey_24dp); + ((PostBaseViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_border_grey_24dp); Toast.makeText(mActivity, R.string.post_unsaved_success, Toast.LENGTH_SHORT).show(); EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); } @@ -776,19 +789,19 @@ public class PostRecyclerViewAdapter extends PagedListAdapter shareLink(post)); + ((PostBaseViewHolder) holder).shareButton.setOnClickListener(view -> shareLink(post)); + + if (holder instanceof PostVideoAutoplayViewHolder) { + /*final Uri gifVideoUri = Uri.parse(post.getVideoUrl()); + ((PostBaseViewHolder) holder).imageView.setOnClickListener(view -> { + Intent intent = new Intent(mActivity, ViewGIFActivity.class); + intent.setData(gifVideoUri); + intent.putExtra(ViewGIFActivity.FILE_NAME_KEY, subredditName + + "-" + id + ".gif"); + intent.putExtra(ViewGIFActivity.GIF_URL_KEY, post.getVideoUrl()); + intent.putExtra(ViewGIFActivity.POST_TITLE_KEY, post.getTitle()); + mActivity.startActivity(intent); + }); + + ((PostBaseViewHolder) holder).playButtonImageView.setVisibility(View.VISIBLE);*/ + + + /*final Uri videoUri = Uri.parse(post.getVideoUrl()); + ((PostBaseViewHolder) holder).imageView.setOnClickListener(view -> { + Intent intent = new Intent(mActivity, ViewVideoActivity.class); + intent.setData(videoUri); + intent.putExtra(ViewVideoActivity.EXTRA_VIDEO_DOWNLOAD_URL, post.getVideoDownloadUrl()); + intent.putExtra(ViewVideoActivity.EXTRA_SUBREDDIT, subredditName); + intent.putExtra(ViewVideoActivity.EXTRA_ID, fullName); + intent.putExtra(ViewVideoActivity.EXTRA_POST_TITLE, post.getTitle()); + mActivity.startActivity(intent); + }); + + ((PostBaseViewHolder) holder).playButtonImageView.setVisibility(View.VISIBLE);*/ + /*((PostVideoAutoplayViewHolder) holder).videoPlayer.setRatio( + (float) post.getPreviewHeight() / post.getPreviewWidth() + );*/ + ((PostVideoAutoplayViewHolder) holder).aspectRatioFrameLayout.setAspectRatio((float) post.getPreviewWidth() / post.getPreviewHeight()); + ((PostVideoAutoplayViewHolder) holder).bindVideoUri(Uri.parse(post.getVideoUrl())); + } else if (holder instanceof PostGifTypeViewHolder) { + ((PostGifTypeViewHolder) holder).progressBar.setVisibility(View.VISIBLE); + ((PostGifTypeViewHolder) holder).imageView + .setRatio((float) post.getPreviewHeight() / post.getPreviewWidth()); + loadImage(holder, post); + + final String imageUrl = post.getUrl(); + ((PostGifTypeViewHolder) holder).imageView.setOnClickListener(view -> { + Intent intent = new Intent(mActivity, ViewImageActivity.class); + intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, imageUrl); + intent.putExtra(ViewImageActivity.FILE_NAME_KEY, subredditName + + "-" + id + ".jpg"); + intent.putExtra(ViewImageActivity.POST_TITLE_KEY, post.getTitle()); + mActivity.startActivity(intent); + }); + + if (post.getPreviewWidth() <= 0 || post.getPreviewHeight() <= 0) { + ((PostGifTypeViewHolder) holder).imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); + ((PostGifTypeViewHolder) holder).imageView.getLayoutParams().height = (int) (400 * mScale); + } + } else if (holder instanceof PostImageTypeViewHolder) { + ((PostImageTypeViewHolder) holder).progressBar.setVisibility(View.VISIBLE); + ((PostImageTypeViewHolder) holder).imageView + .setRatio((float) post.getPreviewHeight() / post.getPreviewWidth()); + loadImage(holder, post); + + final String imageUrl = post.getUrl(); + ((PostImageTypeViewHolder) holder).imageView.setOnClickListener(view -> { + Intent intent = new Intent(mActivity, ViewImageActivity.class); + intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, imageUrl); + intent.putExtra(ViewImageActivity.FILE_NAME_KEY, subredditName + + "-" + id + ".jpg"); + intent.putExtra(ViewImageActivity.POST_TITLE_KEY, post.getTitle()); + mActivity.startActivity(intent); + }); + + if (post.getPreviewWidth() <= 0 || post.getPreviewHeight() <= 0) { + ((PostImageTypeViewHolder) holder).imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); + ((PostImageTypeViewHolder) holder).imageView.getLayoutParams().height = (int) (400 * mScale); + } + } else if (holder instanceof PostLinkTypeViewHolder) { + ((PostLinkTypeViewHolder) holder).progressBar.setVisibility(View.VISIBLE); + ((PostLinkTypeViewHolder) holder).imageView + .setRatio((float) post.getPreviewHeight() / post.getPreviewWidth()); + loadImage(holder, post); + + ((PostLinkTypeViewHolder) holder).linkTextView.setVisibility(View.VISIBLE); + String domain = Uri.parse(post.getUrl()).getHost(); + ((PostLinkTypeViewHolder) holder).linkTextView.setText(domain); + + ((PostLinkTypeViewHolder) holder).imageView.setOnClickListener(view -> { + Intent intent = new Intent(mActivity, LinkResolverActivity.class); + Uri uri = Uri.parse(post.getUrl()); + if (uri.getScheme() == null && uri.getHost() == null) { + intent.setData(LinkResolverActivity.getRedditUriByPath(post.getUrl())); + } else { + intent.setData(uri); + } + mActivity.startActivity(intent); + }); + } else if (holder instanceof PostNoPreviewLinkTypeViewHolder) { + String noPreviewLinkUrl = post.getUrl(); + ((PostNoPreviewLinkTypeViewHolder) holder).linkTextView.setVisibility(View.VISIBLE); + String noPreviewLinkDomain = Uri.parse(noPreviewLinkUrl).getHost(); + ((PostNoPreviewLinkTypeViewHolder) holder).linkTextView.setText(noPreviewLinkDomain); + ((PostNoPreviewLinkTypeViewHolder) holder).noPreviewLinkImageView.setOnClickListener(view -> { + Intent intent = new Intent(mActivity, LinkResolverActivity.class); + Uri uri = Uri.parse(post.getUrl()); + if (uri.getScheme() == null && uri.getHost() == null) { + intent.setData(LinkResolverActivity.getRedditUriByPath(post.getUrl())); + } else { + intent.setData(uri); + } + mActivity.startActivity(intent); + }); + } else if (holder instanceof PostTextTypeViewHolder) { + if (post.getSelfTextPlainTrimmed() != null && !post.getSelfTextPlainTrimmed().equals("")) { + ((PostTextTypeViewHolder) holder).contentTextView.setVisibility(View.VISIBLE); + ((PostTextTypeViewHolder) holder).contentTextView.setText(post.getSelfTextPlainTrimmed()); + } + } + + + } } else if (holder instanceof PostCompactViewHolder) { Post post = getItem(position); @@ -1359,15 +1489,72 @@ public class PostRecyclerViewAdapter extends PagedListAdapter imageRequestBuilder = mGlide.load(post.getPreviewUrl()).listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { + ((PostImageTypeViewHolder) holder).progressBar.setVisibility(View.GONE); + ((PostImageTypeViewHolder) holder).errorRelativeLayout.setVisibility(View.VISIBLE); + ((PostImageTypeViewHolder) holder).errorRelativeLayout.setOnClickListener(view -> { + ((PostImageTypeViewHolder) holder).progressBar.setVisibility(View.VISIBLE); + ((PostImageTypeViewHolder) holder).errorRelativeLayout.setVisibility(View.GONE); + loadImage(holder, post); + }); + return false; + } + + @Override + public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { + ((PostImageTypeViewHolder) holder).errorRelativeLayout.setVisibility(View.GONE); + ((PostImageTypeViewHolder) holder).progressBar.setVisibility(View.GONE); + return false; + } + }); + + if ((post.isNSFW() && mNeedBlurNSFW) || post.isSpoiler() && mNeedBlurSpoiler) { + imageRequestBuilder.apply(RequestOptions.bitmapTransform(new BlurTransformation(50, 10))) + .into(((PostImageTypeViewHolder) holder).imageView); + } else { + imageRequestBuilder.into(((PostImageTypeViewHolder) holder).imageView); + } + } else if (holder instanceof PostGifTypeViewHolder) { + String url = mAutoplay ? post.getUrl() : post.getPreviewUrl(); + RequestBuilder imageRequestBuilder = mGlide.load(url).listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { + ((PostGifTypeViewHolder) holder).progressBar.setVisibility(View.GONE); + ((PostGifTypeViewHolder) holder).errorRelativeLayout.setVisibility(View.VISIBLE); + ((PostGifTypeViewHolder) holder).errorRelativeLayout.setOnClickListener(view -> { + ((PostGifTypeViewHolder) holder).progressBar.setVisibility(View.VISIBLE); + ((PostGifTypeViewHolder) holder).errorRelativeLayout.setVisibility(View.GONE); + loadImage(holder, post); + }); + return false; + } + + @Override + public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { + ((PostGifTypeViewHolder) holder).errorRelativeLayout.setVisibility(View.GONE); + ((PostGifTypeViewHolder) holder).progressBar.setVisibility(View.GONE); + return false; + } + }); + + if ((post.isNSFW() && mNeedBlurNSFW) || post.isSpoiler() && mNeedBlurSpoiler) { + imageRequestBuilder.apply(RequestOptions.bitmapTransform(new BlurTransformation(50, 10))) + .into(((PostGifTypeViewHolder) holder).imageView); + } else { + imageRequestBuilder.into(((PostGifTypeViewHolder) holder).imageView); + } + } else if (holder instanceof PostLinkTypeViewHolder) { RequestBuilder imageRequestBuilder = mGlide.load(post.getPreviewUrl()).listener(new RequestListener() { @Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { - ((PostViewHolder) holder).progressBar.setVisibility(View.GONE); - ((PostViewHolder) holder).errorRelativeLayout.setVisibility(View.VISIBLE); - ((PostViewHolder) holder).errorRelativeLayout.setOnClickListener(view -> { - ((PostViewHolder) holder).progressBar.setVisibility(View.VISIBLE); - ((PostViewHolder) holder).errorRelativeLayout.setVisibility(View.GONE); + ((PostLinkTypeViewHolder) holder).progressBar.setVisibility(View.GONE); + ((PostLinkTypeViewHolder) holder).errorRelativeLayout.setVisibility(View.VISIBLE); + ((PostLinkTypeViewHolder) holder).errorRelativeLayout.setOnClickListener(view -> { + ((PostLinkTypeViewHolder) holder).progressBar.setVisibility(View.VISIBLE); + ((PostLinkTypeViewHolder) holder).errorRelativeLayout.setVisibility(View.GONE); loadImage(holder, post); }); return false; @@ -1375,17 +1562,17 @@ public class PostRecyclerViewAdapter extends PagedListAdapter target, DataSource dataSource, boolean isFirstResource) { - ((PostViewHolder) holder).errorRelativeLayout.setVisibility(View.GONE); - ((PostViewHolder) holder).progressBar.setVisibility(View.GONE); + ((PostLinkTypeViewHolder) holder).errorRelativeLayout.setVisibility(View.GONE); + ((PostLinkTypeViewHolder) holder).progressBar.setVisibility(View.GONE); return false; } }); if ((post.isNSFW() && mNeedBlurNSFW) || post.isSpoiler() && mNeedBlurSpoiler) { imageRequestBuilder.apply(RequestOptions.bitmapTransform(new BlurTransformation(50, 10))) - .into(((PostViewHolder) holder).imageView); + .into(((PostLinkTypeViewHolder) holder).imageView); } else { - imageRequestBuilder.into(((PostViewHolder) holder).imageView); + imageRequestBuilder.into(((PostLinkTypeViewHolder) holder).imageView); } } else if (holder instanceof PostCompactViewHolder) { String previewUrl = post.getThumbnailPreviewUrl().equals("") ? post.getPreviewUrl() : post.getThumbnailPreviewUrl(); @@ -1434,20 +1621,6 @@ public class PostRecyclerViewAdapter extends PagedListAdapter= super.getItemCount()) { + return null; + } + return getItem(order); + } + + @Nullable + @Override + public Integer getOrderForKey(@NonNull Object key) { + if (getCurrentList() != null && key instanceof Post) { + return getCurrentList().indexOf(key); + } + + return null; + } + public interface Callback { void retryLoadingMore(); void typeChipClicked(int filter); } - class PostViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.card_view_item_post) + class PostBaseViewHolder extends RecyclerView.ViewHolder { MaterialCardView cardView; - @BindView(R.id.icon_gif_image_view_item_post) AspectRatioGifImageView iconGifImageView; - @BindView(R.id.subreddit_name_text_view_item_post) TextView subredditTextView; - @BindView(R.id.user_text_view_item_post) TextView userTextView; - @BindView(R.id.stickied_post_image_view_item_post) ImageView stickiedPostImageView; - @BindView(R.id.post_time_text_view_best_item_post) TextView postTimeTextView; - @BindView(R.id.title_text_view_best_item_post) TextView titleTextView; - @BindView(R.id.type_text_view_item_post) CustomTextView typeTextView; - @BindView(R.id.archived_image_view_item_post) ImageView archivedImageView; - @BindView(R.id.locked_image_view_item_post) ImageView lockedImageView; - @BindView(R.id.crosspost_image_view_item_post) ImageView crosspostImageView; - @BindView(R.id.nsfw_text_view_item_post) CustomTextView nsfwTextView; - @BindView(R.id.spoiler_custom_text_view_item_post) CustomTextView spoilerTextView; - @BindView(R.id.flair_custom_text_view_item_post) CustomTextView flairTextView; - @BindView(R.id.awards_text_view_item_post) CustomTextView awardsTextView; - @BindView(R.id.link_text_view_item_post) - TextView linkTextView; - @BindView(R.id.image_view_wrapper_item_post) - RelativeLayout relativeLayout; - @BindView(R.id.progress_bar_item_post) - ProgressBar progressBar; - @BindView(R.id.image_view_best_post_item) - AspectRatioGifImageView imageView; - @BindView(R.id.play_button_image_view_item_post) - ImageView playButtonImageView; - @BindView(R.id.load_image_error_relative_layout_item_post) - RelativeLayout errorRelativeLayout; - @BindView(R.id.image_view_no_preview_link_item_post) - ImageView noPreviewLinkImageView; - @BindView(R.id.content_text_view_item_post) - TextView contentTextView; - @BindView(R.id.bottom_constraint_layout_item_post) ConstraintLayout bottomConstraintLayout; - @BindView(R.id.plus_button_item_post) ImageView upvoteButton; - @BindView(R.id.score_text_view_item_post) TextView scoreTextView; - @BindView(R.id.minus_button_item_post) ImageView downvoteButton; - @BindView(R.id.comments_count_item_post) TextView commentsCountTextView; - @BindView(R.id.save_button_item_post) ImageView saveButton; - @BindView(R.id.share_button_item_post) ImageView shareButton; - PostViewHolder(View itemView) { + PostBaseViewHolder(@NonNull View itemView) { super(itemView); - ButterKnife.bind(this, itemView); + } + + void setBaseView(MaterialCardView cardView, + AspectRatioGifImageView iconGifImageView, + TextView subredditTextView, + TextView userTextView, + ImageView stickiedPostImageView, + TextView postTimeTextView, + TextView titleTextView, + CustomTextView typeTextView, + ImageView archivedImageView, + ImageView lockedImageView, + ImageView crosspostImageView, + CustomTextView nsfwTextView, + CustomTextView spoilerTextView, + CustomTextView flairTextView, + CustomTextView awardsTextView, + ConstraintLayout bottomConstraintLayout, + ImageView upvoteButton, + TextView scoreTextView, + ImageView downvoteButton, + TextView commentsCountTextView, + ImageView saveButton, + ImageView shareButton) { + this.cardView = cardView; + this.iconGifImageView = iconGifImageView; + this.subredditTextView = subredditTextView; + this.userTextView = userTextView; + this.stickiedPostImageView = stickiedPostImageView; + this.postTimeTextView = postTimeTextView; + this.titleTextView = titleTextView; + this.typeTextView = typeTextView; + this.archivedImageView = archivedImageView; + this.lockedImageView = lockedImageView; + this.crosspostImageView = crosspostImageView; + this.nsfwTextView = nsfwTextView; + this.spoilerTextView = spoilerTextView; + this.flairTextView = flairTextView; + this.awardsTextView = awardsTextView; + this.bottomConstraintLayout = bottomConstraintLayout; + this.upvoteButton = upvoteButton; + this.scoreTextView = scoreTextView; + this.downvoteButton = downvoteButton; + this.commentsCountTextView = commentsCountTextView; + this.saveButton = saveButton; + this.shareButton = shareButton; + scoreTextView.setOnClickListener(view -> { //Do nothing in order to prevent clicking this to start ViewPostDetailActivity }); @@ -1665,7 +1869,6 @@ public class PostRecyclerViewAdapter extends PagedListAdapter= 0.85; + } + + @Override + public int getPlayerOrder() { + return getAdapterPosition(); + } + } + + class PostGifTypeViewHolder extends PostBaseViewHolder { + @BindView(R.id.card_view_item_post_gif_type) + MaterialCardView cardView; + @BindView(R.id.icon_gif_image_view_item_post_gif_type) + AspectRatioGifImageView iconGifImageView; + @BindView(R.id.subreddit_name_text_view_item_post_gif_type) + TextView subredditTextView; + @BindView(R.id.user_text_view_item_post_gif_type) + TextView userTextView; + @BindView(R.id.stickied_post_image_view_item_post_gif_type) + ImageView stickiedPostImageView; + @BindView(R.id.post_time_text_view_best_item_post_gif_type) + TextView postTimeTextView; + @BindView(R.id.title_text_view_best_item_post_gif_type) + TextView titleTextView; + @BindView(R.id.type_text_view_item_post_gif_type) + CustomTextView typeTextView; + @BindView(R.id.archived_image_view_item_post_gif_type) + ImageView archivedImageView; + @BindView(R.id.locked_image_view_item_post_gif_type) + ImageView lockedImageView; + @BindView(R.id.crosspost_image_view_item_post_gif_type) + ImageView crosspostImageView; + @BindView(R.id.nsfw_text_view_item_post_gif_type) + CustomTextView nsfwTextView; + @BindView(R.id.spoiler_custom_text_view_item_post_gif_type) + CustomTextView spoilerTextView; + @BindView(R.id.flair_custom_text_view_item_post_gif_type) + CustomTextView flairTextView; + @BindView(R.id.awards_text_view_item_post_gif_type) + CustomTextView awardsTextView; + @BindView(R.id.image_view_wrapper_item_post_gif_type) + RelativeLayout relativeLayout; + @BindView(R.id.progress_bar_item_post_gif_type) + ProgressBar progressBar; + @BindView(R.id.image_view_best_post_item) + AspectRatioGifImageView imageView; + @BindView(R.id.load_image_error_relative_layout_item_post_gif_type) + RelativeLayout errorRelativeLayout; + @BindView(R.id.bottom_constraint_layout_item_post_gif_type) + ConstraintLayout bottomConstraintLayout; + @BindView(R.id.plus_button_item_post_gif_type) + ImageView upvoteButton; + @BindView(R.id.score_text_view_item_post_gif_type) + TextView scoreTextView; + @BindView(R.id.minus_button_item_post_gif_type) + ImageView downvoteButton; + @BindView(R.id.comments_count_item_post_gif_type) + TextView commentsCountTextView; + @BindView(R.id.save_button_item_post_gif_type) + ImageView saveButton; + @BindView(R.id.share_button_item_post_gif_type) + ImageView shareButton; + + PostGifTypeViewHolder(View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + setBaseView(cardView, + iconGifImageView, + subredditTextView, + userTextView, + stickiedPostImageView, + postTimeTextView, + titleTextView, + typeTextView, + archivedImageView, + lockedImageView, + crosspostImageView, + nsfwTextView, + spoilerTextView, + flairTextView, + awardsTextView, + bottomConstraintLayout, + upvoteButton, + scoreTextView, + downvoteButton, + commentsCountTextView, + saveButton, + shareButton); + + progressBar.setIndeterminateTintList(ColorStateList.valueOf(mColorAccent)); + } + } + + class PostImageTypeViewHolder extends PostBaseViewHolder { + @BindView(R.id.card_view_item_post_image_type) + MaterialCardView cardView; + @BindView(R.id.icon_gif_image_view_item_post_image_type) + AspectRatioGifImageView iconGifImageView; + @BindView(R.id.subreddit_name_text_view_item_post_image_type) + TextView subredditTextView; + @BindView(R.id.user_text_view_item_post_image_type) + TextView userTextView; + @BindView(R.id.stickied_post_image_view_item_post_image_type) + ImageView stickiedPostImageView; + @BindView(R.id.post_time_text_view_best_item_post_image_type) + TextView postTimeTextView; + @BindView(R.id.title_text_view_best_item_post_image_type) + TextView titleTextView; + @BindView(R.id.type_text_view_item_post_image_type) + CustomTextView typeTextView; + @BindView(R.id.archived_image_view_item_post_image_type) + ImageView archivedImageView; + @BindView(R.id.locked_image_view_item_post_image_type) + ImageView lockedImageView; + @BindView(R.id.crosspost_image_view_item_post_image_type) + ImageView crosspostImageView; + @BindView(R.id.nsfw_text_view_item_post_image_type) + CustomTextView nsfwTextView; + @BindView(R.id.spoiler_custom_text_view_item_post_image_type) + CustomTextView spoilerTextView; + @BindView(R.id.flair_custom_text_view_item_post_image_type) + CustomTextView flairTextView; + @BindView(R.id.awards_text_view_item_post_image_type) + CustomTextView awardsTextView; + @BindView(R.id.image_view_wrapper_item_post_image_type) + RelativeLayout relativeLayout; + @BindView(R.id.progress_bar_item_post_image_type) + ProgressBar progressBar; + @BindView(R.id.image_view_best_post_item) + AspectRatioGifImageView imageView; + @BindView(R.id.load_image_error_relative_layout_item_post_image_type) + RelativeLayout errorRelativeLayout; + @BindView(R.id.bottom_constraint_layout_item_post_image_type) + ConstraintLayout bottomConstraintLayout; + @BindView(R.id.plus_button_item_post_image_type) + ImageView upvoteButton; + @BindView(R.id.score_text_view_item_post_image_type) + TextView scoreTextView; + @BindView(R.id.minus_button_item_post_image_type) + ImageView downvoteButton; + @BindView(R.id.comments_count_item_post_image_type) + TextView commentsCountTextView; + @BindView(R.id.save_button_item_post_image_type) + ImageView saveButton; + @BindView(R.id.share_button_item_post_image_type) + ImageView shareButton; + + PostImageTypeViewHolder(View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + setBaseView(cardView, + iconGifImageView, + subredditTextView, + userTextView, + stickiedPostImageView, + postTimeTextView, + titleTextView, + typeTextView, + archivedImageView, + lockedImageView, + crosspostImageView, + nsfwTextView, + spoilerTextView, + flairTextView, + awardsTextView, + bottomConstraintLayout, + upvoteButton, + scoreTextView, + downvoteButton, + commentsCountTextView, + saveButton, + shareButton); + + progressBar.setIndeterminateTintList(ColorStateList.valueOf(mColorAccent)); + } + } + + class PostLinkTypeViewHolder extends PostBaseViewHolder { + @BindView(R.id.card_view_item_post_link_type) + MaterialCardView cardView; + @BindView(R.id.icon_gif_image_view_item_post_link_type) + AspectRatioGifImageView iconGifImageView; + @BindView(R.id.subreddit_name_text_view_item_post_link_type) + TextView subredditTextView; + @BindView(R.id.user_text_view_item_post_link_type) + TextView userTextView; + @BindView(R.id.stickied_post_image_view_item_post_link_type) + ImageView stickiedPostImageView; + @BindView(R.id.post_time_text_view_best_item_post_link_type) + TextView postTimeTextView; + @BindView(R.id.title_text_view_best_item_post_link_type) + TextView titleTextView; + @BindView(R.id.type_text_view_item_post_link_type) + CustomTextView typeTextView; + @BindView(R.id.archived_image_view_item_post_link_type) + ImageView archivedImageView; + @BindView(R.id.locked_image_view_item_post_link_type) + ImageView lockedImageView; + @BindView(R.id.crosspost_image_view_item_post_link_type) + ImageView crosspostImageView; + @BindView(R.id.nsfw_text_view_item_post_link_type) + CustomTextView nsfwTextView; + @BindView(R.id.spoiler_custom_text_view_item_post_link_type) + CustomTextView spoilerTextView; + @BindView(R.id.flair_custom_text_view_item_post_link_type) + CustomTextView flairTextView; + @BindView(R.id.awards_text_view_item_post_link_type) + CustomTextView awardsTextView; + @BindView(R.id.link_text_view_item_post_link_type) + TextView linkTextView; + @BindView(R.id.image_view_wrapper_item_post_link_type) + RelativeLayout relativeLayout; + @BindView(R.id.progress_bar_item_post_link_type) + ProgressBar progressBar; + @BindView(R.id.image_view_best_post_item) + AspectRatioGifImageView imageView; + @BindView(R.id.load_image_error_relative_layout_item_post_link_type) + RelativeLayout errorRelativeLayout; + @BindView(R.id.bottom_constraint_layout_item_post_link_type) + ConstraintLayout bottomConstraintLayout; + @BindView(R.id.plus_button_item_post_link_type) + ImageView upvoteButton; + @BindView(R.id.score_text_view_item_post_link_type) + TextView scoreTextView; + @BindView(R.id.minus_button_item_post_link_type) + ImageView downvoteButton; + @BindView(R.id.comments_count_item_post_link_type) + TextView commentsCountTextView; + @BindView(R.id.save_button_item_post_link_type) + ImageView saveButton; + @BindView(R.id.share_button_item_post_link_type) + ImageView shareButton; + + PostLinkTypeViewHolder(View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + setBaseView(cardView, + iconGifImageView, + subredditTextView, + userTextView, + stickiedPostImageView, + postTimeTextView, + titleTextView, + typeTextView, + archivedImageView, + lockedImageView, + crosspostImageView, + nsfwTextView, + spoilerTextView, + flairTextView, + awardsTextView, + bottomConstraintLayout, + upvoteButton, + scoreTextView, + downvoteButton, + commentsCountTextView, + saveButton, + shareButton); + + linkTextView.setTextColor(mSecondaryTextColor); + progressBar.setIndeterminateTintList(ColorStateList.valueOf(mColorAccent)); + } + } + + class PostNoPreviewLinkTypeViewHolder extends PostBaseViewHolder { + @BindView(R.id.card_view_item_post_no_preview_link_type) + MaterialCardView cardView; + @BindView(R.id.icon_gif_image_view_item_post_no_preview_link_type) + AspectRatioGifImageView iconGifImageView; + @BindView(R.id.subreddit_name_text_view_item_post_no_preview_link_type) + TextView subredditTextView; + @BindView(R.id.user_text_view_item_post_no_preview_link_type) + TextView userTextView; + @BindView(R.id.stickied_post_image_view_item_post_no_preview_link_type) + ImageView stickiedPostImageView; + @BindView(R.id.post_time_text_view_best_item_post_no_preview_link_type) + TextView postTimeTextView; + @BindView(R.id.title_text_view_best_item_post_no_preview_link_type) + TextView titleTextView; + @BindView(R.id.type_text_view_item_post_no_preview_link_type) + CustomTextView typeTextView; + @BindView(R.id.archived_image_view_item_post_no_preview_link_type) + ImageView archivedImageView; + @BindView(R.id.locked_image_view_item_post_no_preview_link_type) + ImageView lockedImageView; + @BindView(R.id.crosspost_image_view_item_post_no_preview_link_type) + ImageView crosspostImageView; + @BindView(R.id.nsfw_text_view_item_post_no_preview_link_type) + CustomTextView nsfwTextView; + @BindView(R.id.spoiler_custom_text_view_item_post_no_preview_link_type) + CustomTextView spoilerTextView; + @BindView(R.id.flair_custom_text_view_item_post_no_preview_link_type) + CustomTextView flairTextView; + @BindView(R.id.awards_text_view_item_post_no_preview_link_type) + CustomTextView awardsTextView; + @BindView(R.id.link_text_view_item_post_no_preview_link_type) + TextView linkTextView; + @BindView(R.id.image_view_no_preview_link_item_post_no_preview_link_type) + ImageView noPreviewLinkImageView; + @BindView(R.id.bottom_constraint_layout_item_post_no_preview_link_type) + ConstraintLayout bottomConstraintLayout; + @BindView(R.id.plus_button_item_post_no_preview_link_type) + ImageView upvoteButton; + @BindView(R.id.score_text_view_item_post_no_preview_link_type) + TextView scoreTextView; + @BindView(R.id.minus_button_item_post_no_preview_link_type) + ImageView downvoteButton; + @BindView(R.id.comments_count_item_post_no_preview_link_type) + TextView commentsCountTextView; + @BindView(R.id.save_button_item_post_no_preview_link_type) + ImageView saveButton; + @BindView(R.id.share_button_item_post_no_preview_link_type) + ImageView shareButton; + + PostNoPreviewLinkTypeViewHolder(View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + setBaseView(cardView, + iconGifImageView, + subredditTextView, + userTextView, + stickiedPostImageView, + postTimeTextView, + titleTextView, + typeTextView, + archivedImageView, + lockedImageView, + crosspostImageView, + nsfwTextView, + spoilerTextView, + flairTextView, + awardsTextView, + bottomConstraintLayout, + upvoteButton, + scoreTextView, + downvoteButton, + commentsCountTextView, + saveButton, + shareButton); + + linkTextView.setTextColor(mSecondaryTextColor); + noPreviewLinkImageView.setBackgroundColor(mNoPreviewLinkBackgroundColor); + } + } + + class PostTextTypeViewHolder extends PostBaseViewHolder { + @BindView(R.id.card_view_item_post_text_type) + MaterialCardView cardView; + @BindView(R.id.icon_gif_image_view_item_post_text_type) + AspectRatioGifImageView iconGifImageView; + @BindView(R.id.subreddit_name_text_view_item_post_text_type) + TextView subredditTextView; + @BindView(R.id.user_text_view_item_post_text_type) + TextView userTextView; + @BindView(R.id.stickied_post_image_view_item_post_text_type) + ImageView stickiedPostImageView; + @BindView(R.id.post_time_text_view_best_item_post_text_type) + TextView postTimeTextView; + @BindView(R.id.title_text_view_best_item_post_text_type) + TextView titleTextView; + @BindView(R.id.type_text_view_item_post_text_type) + CustomTextView typeTextView; + @BindView(R.id.archived_image_view_item_post_text_type) + ImageView archivedImageView; + @BindView(R.id.locked_image_view_item_post_text_type) + ImageView lockedImageView; + @BindView(R.id.crosspost_image_view_item_post_text_type) + ImageView crosspostImageView; + @BindView(R.id.nsfw_text_view_item_post_text_type) + CustomTextView nsfwTextView; + @BindView(R.id.spoiler_custom_text_view_item_post_text_type) + CustomTextView spoilerTextView; + @BindView(R.id.flair_custom_text_view_item_post_text_type) + CustomTextView flairTextView; + @BindView(R.id.awards_text_view_item_post_text_type) + CustomTextView awardsTextView; + @BindView(R.id.content_text_view_item_post_text_type) + TextView contentTextView; + @BindView(R.id.bottom_constraint_layout_item_post_text_type) + ConstraintLayout bottomConstraintLayout; + @BindView(R.id.plus_button_item_post_text_type) + ImageView upvoteButton; + @BindView(R.id.score_text_view_item_post_text_type) + TextView scoreTextView; + @BindView(R.id.minus_button_item_post_text_type) + ImageView downvoteButton; + @BindView(R.id.comments_count_item_post_text_type) + TextView commentsCountTextView; + @BindView(R.id.save_button_item_post_text_type) + ImageView saveButton; + @BindView(R.id.share_button_item_post_text_type) + ImageView shareButton; + + PostTextTypeViewHolder (View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + setBaseView(cardView, + iconGifImageView, + subredditTextView, + userTextView, + stickiedPostImageView, + postTimeTextView, + titleTextView, + typeTextView, + archivedImageView, + lockedImageView, + crosspostImageView, + nsfwTextView, + spoilerTextView, + flairTextView, + awardsTextView, + bottomConstraintLayout, + upvoteButton, + scoreTextView, + downvoteButton, + commentsCountTextView, + saveButton, + shareButton); + + contentTextView.setTextColor(mPostContentColor); + } + } + class PostCompactViewHolder extends RecyclerView.ViewHolder { @BindView(R.id.icon_gif_image_view_item_post_compact) AspectRatioGifImageView iconGifImageView; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AppModule.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AppModule.java index fe483c3c..a15c01ab 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/AppModule.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AppModule.java @@ -6,6 +6,11 @@ import android.content.SharedPreferences; import androidx.preference.PreferenceManager; +import com.google.android.exoplayer2.database.ExoDatabaseProvider; +import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor; +import com.google.android.exoplayer2.upstream.cache.SimpleCache; + +import java.io.File; import java.util.concurrent.TimeUnit; import javax.inject.Named; @@ -13,6 +18,10 @@ import javax.inject.Singleton; import dagger.Module; import dagger.Provides; +import im.ene.toro.exoplayer.Config; +import im.ene.toro.exoplayer.ExoCreator; +import im.ene.toro.exoplayer.MediaSourceBuilder; +import im.ene.toro.exoplayer.ToroExo; import ml.docilealligator.infinityforreddit.CustomTheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.Utils.CustomThemeSharedPreferencesUtils; import ml.docilealligator.infinityforreddit.Utils.RedditUtils; @@ -147,4 +156,14 @@ class AppModule { @Named("amoled_theme") SharedPreferences amoledThemeSharedPreferences) { return new CustomThemeWrapper(lightThemeSharedPreferences, darkThemeSharedPreferences, amoledThemeSharedPreferences); } + + @Provides + @Singleton + ExoCreator provideExoCreator() { + SimpleCache cache = new SimpleCache(new File(mApplication.getCacheDir(), "/toro_cache"), + new LeastRecentlyUsedCacheEvictor(200 * 1024 * 1024), new ExoDatabaseProvider(mApplication)); + Config config = new Config.Builder(mApplication).setMediaSourceBuilder(MediaSourceBuilder.LOOPING).setCache(cache) + .build(); + return ToroExo.with(mApplication).getCreator(config); + } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostFragment.java index 07ef965a..50e622ba 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostFragment.java @@ -46,6 +46,8 @@ import javax.inject.Named; import butterknife.BindView; import butterknife.ButterKnife; +import im.ene.toro.exoplayer.ExoCreator; +import im.ene.toro.widget.Container; import ml.docilealligator.infinityforreddit.Activity.BaseActivity; import ml.docilealligator.infinityforreddit.Activity.FilteredThingActivity; import ml.docilealligator.infinityforreddit.Activity.MainActivity; @@ -94,7 +96,7 @@ public class PostFragment extends Fragment implements FragmentCommunicator { @BindView(R.id.swipe_refresh_layout_post_fragment) SwipeRefreshLayout mSwipeRefreshLayout; @BindView(R.id.recycler_view_post_fragment) - RecyclerView mPostRecyclerView; + Container mPostRecyclerView; @BindView(R.id.fetch_post_info_linear_layout_post_fragment) LinearLayout mFetchPostInfoLinearLayout; @BindView(R.id.fetch_post_info_image_view_post_fragment) @@ -121,6 +123,8 @@ public class PostFragment extends Fragment implements FragmentCommunicator { SharedPreferences mPostLayoutSharedPreferences; @Inject CustomThemeWrapper customThemeWrapper; + @Inject + ExoCreator exoCreator; private RequestManager mGlide; private AppCompatActivity activity; private LinearLayoutManager mLinearLayoutManager; @@ -323,12 +327,6 @@ public class PostFragment extends Fragment implements FragmentCommunicator { int filter = getArguments().getInt(EXTRA_FILTER); String accessToken = getArguments().getString(EXTRA_ACCESS_TOKEN); boolean nsfw = mSharedPreferences.getBoolean(SharedPreferencesUtils.NSFW_KEY, false); - boolean needBlurNsfw = mSharedPreferences.getBoolean(SharedPreferencesUtils.BLUR_NSFW_KEY, true); - boolean needBlurSpoiler = mSharedPreferences.getBoolean(SharedPreferencesUtils.BLUR_SPOILER_KEY, false); - boolean voteButtonsOnTheRight = mSharedPreferences.getBoolean(SharedPreferencesUtils.VOTE_BUTTONS_ON_THE_RIGHT_KEY, false); - boolean showElapsedTime = mSharedPreferences.getBoolean(SharedPreferencesUtils.SHOW_ELAPSED_TIME_KEY, false); - boolean showDividerInCompactLayout = mSharedPreferences.getBoolean(SharedPreferencesUtils.SHOW_DIVIDER_IN_COMPACT_LAYOUT, true); - boolean showAbsoluteNumberOfVotes = mSharedPreferences.getBoolean(SharedPreferencesUtils.SHOW_ABSOLUTE_NUMBER_OF_VOTES, true); int defaultPostLayout = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.DEFAULT_POST_LAYOUT_KEY, "0")); if (postType == PostDataSource.TYPE_SEARCH) { @@ -342,9 +340,7 @@ public class PostFragment extends Fragment implements FragmentCommunicator { mAdapter = new PostRecyclerViewAdapter(activity, mOauthRetrofit, mRetrofit, mRedditDataRoomDatabase, customThemeWrapper, accessToken, postType, postLayout, true, - needBlurNsfw, needBlurSpoiler, voteButtonsOnTheRight, showElapsedTime, - showDividerInCompactLayout, showAbsoluteNumberOfVotes, - new PostRecyclerViewAdapter.Callback() { + mSharedPreferences, exoCreator, new PostRecyclerViewAdapter.Callback() { @Override public void retryLoadingMore() { mPostViewModel.retryLoadingMore(); @@ -407,9 +403,7 @@ public class PostFragment extends Fragment implements FragmentCommunicator { mAdapter = new PostRecyclerViewAdapter(activity, mOauthRetrofit, mRetrofit, mRedditDataRoomDatabase, customThemeWrapper, accessToken, postType, postLayout, displaySubredditName, - needBlurNsfw, needBlurSpoiler, voteButtonsOnTheRight, showElapsedTime, - showDividerInCompactLayout, showAbsoluteNumberOfVotes, - new PostRecyclerViewAdapter.Callback() { + mSharedPreferences, exoCreator, new PostRecyclerViewAdapter.Callback() { @Override public void retryLoadingMore() { mPostViewModel.retryLoadingMore(); @@ -457,9 +451,7 @@ public class PostFragment extends Fragment implements FragmentCommunicator { mAdapter = new PostRecyclerViewAdapter(activity, mOauthRetrofit, mRetrofit, mRedditDataRoomDatabase, customThemeWrapper, accessToken, postType, postLayout, true, - needBlurNsfw, needBlurSpoiler, voteButtonsOnTheRight, showElapsedTime, - showDividerInCompactLayout, showAbsoluteNumberOfVotes, - new PostRecyclerViewAdapter.Callback() { + mSharedPreferences, exoCreator, new PostRecyclerViewAdapter.Callback() { @Override public void retryLoadingMore() { mPostViewModel.retryLoadingMore(); @@ -505,9 +497,7 @@ public class PostFragment extends Fragment implements FragmentCommunicator { mAdapter = new PostRecyclerViewAdapter(activity, mOauthRetrofit, mRetrofit, mRedditDataRoomDatabase, customThemeWrapper, accessToken, postType, postLayout, true, - needBlurNsfw, needBlurSpoiler, voteButtonsOnTheRight, showElapsedTime, - showDividerInCompactLayout, showAbsoluteNumberOfVotes, - new PostRecyclerViewAdapter.Callback() { + mSharedPreferences, exoCreator, new PostRecyclerViewAdapter.Callback() { @Override public void retryLoadingMore() { mPostViewModel.retryLoadingMore(); @@ -546,9 +536,7 @@ public class PostFragment extends Fragment implements FragmentCommunicator { mAdapter = new PostRecyclerViewAdapter(activity, mOauthRetrofit, mRetrofit, mRedditDataRoomDatabase, customThemeWrapper, accessToken, postType, postLayout, true, - needBlurNsfw, needBlurSpoiler, voteButtonsOnTheRight, showElapsedTime, - showDividerInCompactLayout, showAbsoluteNumberOfVotes, - new PostRecyclerViewAdapter.Callback() { + mSharedPreferences, exoCreator, new PostRecyclerViewAdapter.Callback() { @Override public void retryLoadingMore() { mPostViewModel.retryLoadingMore(); @@ -569,6 +557,7 @@ public class PostFragment extends Fragment implements FragmentCommunicator { } mPostRecyclerView.setAdapter(mAdapter); + mPostRecyclerView.setCacheManager(mAdapter); mPostViewModel.getPosts().observe(this, posts -> mAdapter.submitList(posts)); mPostViewModel.hasPost().observe(this, hasPost -> { diff --git a/app/src/main/res/drawable/exo_player_autoplay_button_background.xml b/app/src/main/res/drawable/exo_player_autoplay_button_background.xml new file mode 100644 index 00000000..0ad9af8e --- /dev/null +++ b/app/src/main/res/drawable/exo_player_autoplay_button_background.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/exo_autoplay_playback_control_view.xml b/app/src/main/res/layout/exo_autoplay_playback_control_view.xml new file mode 100644 index 00000000..99cab8e2 --- /dev/null +++ b/app/src/main/res/layout/exo_autoplay_playback_control_view.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_post.xml b/app/src/main/res/layout/fragment_post.xml index 7862ba25..dc3248b5 100644 --- a/app/src/main/res/layout/fragment_post.xml +++ b/app/src/main/res/layout/fragment_post.xml @@ -10,7 +10,13 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - --> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_post_image_type.xml b/app/src/main/res/layout/item_post_image_type.xml new file mode 100644 index 00000000..6ca140d3 --- /dev/null +++ b/app/src/main/res/layout/item_post_image_type.xml @@ -0,0 +1,314 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_post_link_type.xml b/app/src/main/res/layout/item_post_link_type.xml new file mode 100644 index 00000000..43f51b10 --- /dev/null +++ b/app/src/main/res/layout/item_post_link_type.xml @@ -0,0 +1,324 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_post_no_preview_link_type.xml b/app/src/main/res/layout/item_post_no_preview_link_type.xml new file mode 100644 index 00000000..a6ef9eeb --- /dev/null +++ b/app/src/main/res/layout/item_post_no_preview_link_type.xml @@ -0,0 +1,293 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_post_text_type.xml b/app/src/main/res/layout/item_post_text_type.xml new file mode 100644 index 00000000..cc7a3bb9 --- /dev/null +++ b/app/src/main/res/layout/item_post_text_type.xml @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_post_video_type_autoplay.xml b/app/src/main/res/layout/item_post_video_type_autoplay.xml new file mode 100644 index 00000000..2f1c078a --- /dev/null +++ b/app/src/main/res/layout/item_post_video_type_autoplay.xml @@ -0,0 +1,289 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 21615e4c..c71c119b 100644 --- a/build.gradle +++ b/build.gradle @@ -33,4 +33,5 @@ task clean(type: Delete) { ext { roomVersion = '2.2.5' archLifecycleVersion = '2.2.0' + toroVersion = '3.7.0.2010003' } \ No newline at end of file -- cgit v1.2.3 From 5c053501192e0d9da87d7823c910e79d01cddafc Mon Sep 17 00:00:00 2001 From: Alex Ning Date: Thu, 30 Apr 2020 11:24:34 +0800 Subject: Move onClickListeners to ViewHolders in PostRecyclerViewAdapter. Pause video after fragment pause. --- .../Adapter/PostRecyclerViewAdapter.java | 732 ++++++++++----------- .../CustomView/CustomToroContainer.java | 27 + .../infinityforreddit/Fragment/PostFragment.java | 9 +- app/src/main/res/layout/activity_view_gif.xml | 3 +- app/src/main/res/layout/activity_view_video.xml | 2 +- app/src/main/res/layout/fragment_post.xml | 2 +- .../res/layout/item_post_video_type_autoplay.xml | 2 + 7 files changed, 386 insertions(+), 391 deletions(-) create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/CustomView/CustomToroContainer.java diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java index 55a75184..1f3335e6 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java @@ -225,71 +225,6 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { - if (canStartActivity) { - canStartActivity = false; - - Intent intent = new Intent(mActivity, ViewPostDetailActivity.class); - intent.putExtra(ViewPostDetailActivity.EXTRA_POST_DATA, post); - intent.putExtra(ViewPostDetailActivity.EXTRA_POST_LIST_POSITION, position); - mActivity.startActivity(intent); - } - }); ((PostBaseViewHolder) holder).subredditTextView.setText(subredditNamePrefixed); ((PostBaseViewHolder) holder).userTextView.setText(authorPrefixed); - ((PostBaseViewHolder) holder).userTextView.setOnClickListener(view -> { - if (canStartActivity) { - canStartActivity = false; - Intent intent = new Intent(mActivity, ViewUserDetailActivity.class); - intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, post.getAuthor()); - mActivity.startActivity(intent); - } - }); if (mDisplaySubredditName) { if (authorPrefixed.equals(subredditNamePrefixed)) { @@ -456,26 +369,6 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { - if (canStartActivity) { - canStartActivity = false; - if (post.getSubredditNamePrefixed().startsWith("u/")) { - Intent intent = new Intent(mActivity, ViewUserDetailActivity.class); - intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, - post.getSubredditNamePrefixed().substring(2)); - mActivity.startActivity(intent); - } else { - Intent intent = new Intent(mActivity, ViewSubredditDetailActivity.class); - intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY, - post.getSubredditName()); - mActivity.startActivity(intent); - } - } - }); - - ((PostBaseViewHolder) holder).iconGifImageView.setOnClickListener(view -> - ((PostBaseViewHolder) holder).subredditTextView.performClick()); } else { if (post.getAuthorIconUrl() == null) { String authorName = post.getAuthor().equals("[deleted]") ? post.getSubredditNamePrefixed().substring(2) : post.getAuthor(); @@ -509,25 +402,6 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { - if (canStartActivity) { - canStartActivity = false; - if (post.getSubredditNamePrefixed().startsWith("u/")) { - Intent intent = new Intent(mActivity, ViewUserDetailActivity.class); - intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, post.getAuthor()); - mActivity.startActivity(intent); - } else { - Intent intent = new Intent(mActivity, ViewSubredditDetailActivity.class); - intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY, - post.getSubredditName()); - mActivity.startActivity(intent); - } - } - }); - - ((PostBaseViewHolder) holder).iconGifImageView.setOnClickListener(view -> - ((PostBaseViewHolder) holder).userTextView.performClick()); } if (mShowElapsedTime) { @@ -545,15 +419,6 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { - Intent intent = new Intent(mActivity, FilteredThingActivity.class); - intent.putExtra(FilteredThingActivity.EXTRA_NAME, post.getSubredditNamePrefixed().substring(2)); - intent.putExtra(FilteredThingActivity.EXTRA_POST_TYPE, PostDataSource.TYPE_SUBREDDIT); - intent.putExtra(FilteredThingActivity.EXTRA_FILTER, Post.NSFW_TYPE); - mActivity.startActivity(intent); - }); - } ((PostBaseViewHolder) holder).nsfwTextView.setVisibility(View.VISIBLE); } @@ -592,7 +457,7 @@ public class PostRecyclerViewAdapter extends PagedListAdapter mCallback.typeChipClicked(post.getPostType())); - } - - switch (post.getPostType()) { - case Post.GIF_TYPE: - ((PostBaseViewHolder) holder).typeTextView.setText(R.string.gif); - break; - case Post.VIDEO_TYPE: - ((PostBaseViewHolder) holder).typeTextView.setText(R.string.video); - break; - } - - ((PostBaseViewHolder) holder).upvoteButton.setOnClickListener(view -> { - if (mAccessToken == null) { - Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); - return; - } - - if (isArchived) { - Toast.makeText(mActivity, R.string.archived_post_vote_unavailable, Toast.LENGTH_SHORT).show(); - return; - } - - ColorFilter previousUpvoteButtonColorFilter = ((PostBaseViewHolder) holder).upvoteButton.getColorFilter(); - ColorFilter previousDownvoteButtonColorFilter = ((PostBaseViewHolder) holder).downvoteButton.getColorFilter(); - int previousScoreTextViewColor = ((PostBaseViewHolder) holder).scoreTextView.getCurrentTextColor(); - - int previousVoteType = post.getVoteType(); - String newVoteType; - - ((PostBaseViewHolder) holder).downvoteButton.setColorFilter(mPostIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); - - if (previousVoteType != 1) { - //Not upvoted before - post.setVoteType(1); - newVoteType = RedditUtils.DIR_UPVOTE; - ((PostBaseViewHolder) holder).upvoteButton - .setColorFilter(mUpvotedColor, android.graphics.PorterDuff.Mode.SRC_IN); - ((PostBaseViewHolder) holder).scoreTextView.setTextColor(mUpvotedColor); - } else { - //Upvoted before - post.setVoteType(0); - newVoteType = RedditUtils.DIR_UNVOTE; - ((PostBaseViewHolder) holder).upvoteButton.setColorFilter(mPostIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); - ((PostBaseViewHolder) holder).scoreTextView.setTextColor(mPostIconAndInfoColor); - } - - ((PostBaseViewHolder) holder).scoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, post.getScore() + post.getVoteType())); - - VoteThing.voteThing(mActivity, mOauthRetrofit, mAccessToken, new VoteThing.VoteThingListener() { - @Override - public void onVoteThingSuccess(int position1) { - if (newVoteType.equals(RedditUtils.DIR_UPVOTE)) { - post.setVoteType(1); - ((PostBaseViewHolder) holder).upvoteButton - .setColorFilter(mUpvotedColor, android.graphics.PorterDuff.Mode.SRC_IN); - ((PostBaseViewHolder) holder).scoreTextView.setTextColor(mUpvotedColor); - } else { - post.setVoteType(0); - ((PostBaseViewHolder) holder).upvoteButton.setColorFilter(mPostIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); - ((PostBaseViewHolder) holder).scoreTextView.setTextColor(mPostIconAndInfoColor); - } - - ((PostBaseViewHolder) holder).downvoteButton.setColorFilter(mPostIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); - ((PostBaseViewHolder) holder).scoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, post.getScore() + post.getVoteType())); - - EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); - } - - @Override - public void onVoteThingFail(int position1) { - Toast.makeText(mActivity, R.string.vote_failed, Toast.LENGTH_SHORT).show(); - post.setVoteType(previousVoteType); - ((PostBaseViewHolder) holder).scoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, post.getScore() + previousVoteType)); - ((PostBaseViewHolder) holder).upvoteButton.setColorFilter(previousUpvoteButtonColorFilter); - ((PostBaseViewHolder) holder).downvoteButton.setColorFilter(previousDownvoteButtonColorFilter); - ((PostBaseViewHolder) holder).scoreTextView.setTextColor(previousScoreTextViewColor); - - EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); - } - }, fullName, newVoteType, holder.getAdapterPosition()); - }); - - ((PostBaseViewHolder) holder).downvoteButton.setOnClickListener(view -> { - if (mAccessToken == null) { - Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); - return; - } - - if (isArchived) { - Toast.makeText(mActivity, R.string.archived_post_vote_unavailable, Toast.LENGTH_SHORT).show(); - return; - } - - ColorFilter previousUpvoteButtonColorFilter = ((PostBaseViewHolder) holder).upvoteButton.getColorFilter(); - ColorFilter previousDownvoteButtonColorFilter = ((PostBaseViewHolder) holder).downvoteButton.getColorFilter(); - int previousScoreTextViewColor = ((PostBaseViewHolder) holder).scoreTextView.getCurrentTextColor(); - - int previousVoteType = post.getVoteType(); - String newVoteType; - - ((PostBaseViewHolder) holder).upvoteButton.setColorFilter(mPostIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); - - if (previousVoteType != -1) { - //Not downvoted before - post.setVoteType(-1); - newVoteType = RedditUtils.DIR_DOWNVOTE; - ((PostBaseViewHolder) holder).downvoteButton - .setColorFilter(mDownvotedColor, android.graphics.PorterDuff.Mode.SRC_IN); - ((PostBaseViewHolder) holder).scoreTextView.setTextColor(mDownvotedColor); - } else { - //Downvoted before - post.setVoteType(0); - newVoteType = RedditUtils.DIR_UNVOTE; - ((PostBaseViewHolder) holder).downvoteButton.setColorFilter(mPostIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); - ((PostBaseViewHolder) holder).scoreTextView.setTextColor(mPostIconAndInfoColor); - } - - ((PostBaseViewHolder) holder).scoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, post.getScore() + post.getVoteType())); - - VoteThing.voteThing(mActivity, mOauthRetrofit, mAccessToken, new VoteThing.VoteThingListener() { - @Override - public void onVoteThingSuccess(int position1) { - if (newVoteType.equals(RedditUtils.DIR_DOWNVOTE)) { - post.setVoteType(-1); - ((PostBaseViewHolder) holder).downvoteButton - .setColorFilter(mDownvotedColor, android.graphics.PorterDuff.Mode.SRC_IN); - ((PostBaseViewHolder) holder).scoreTextView.setTextColor(mDownvotedColor); - } else { - post.setVoteType(0); - ((PostBaseViewHolder) holder).downvoteButton.setColorFilter(mPostIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); - ((PostBaseViewHolder) holder).scoreTextView.setTextColor(mPostIconAndInfoColor); - } - - ((PostBaseViewHolder) holder).upvoteButton.setColorFilter(mPostIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); - ((PostBaseViewHolder) holder).scoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, post.getScore() + post.getVoteType())); - - EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); - } - - @Override - public void onVoteThingFail(int position1) { - Toast.makeText(mActivity, R.string.vote_failed, Toast.LENGTH_SHORT).show(); - post.setVoteType(previousVoteType); - ((PostBaseViewHolder) holder).scoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, post.getScore() + previousVoteType)); - ((PostBaseViewHolder) holder).upvoteButton.setColorFilter(previousUpvoteButtonColorFilter); - ((PostBaseViewHolder) holder).downvoteButton.setColorFilter(previousDownvoteButtonColorFilter); - ((PostBaseViewHolder) holder).scoreTextView.setTextColor(previousScoreTextViewColor); - - EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); - } - }, fullName, newVoteType, holder.getAdapterPosition()); - }); - ((PostBaseViewHolder) holder).commentsCountTextView.setText(Integer.toString(post.getNComments())); if (post.isSaved()) { @@ -768,57 +478,6 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { - if (mAccessToken == null) { - Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); - return; - } - - if (post.isSaved()) { - ((PostBaseViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_border_grey_24dp); - SaveThing.unsaveThing(mOauthRetrofit, mAccessToken, post.getFullName(), - new SaveThing.SaveThingListener() { - @Override - public void success() { - post.setSaved(false); - ((PostBaseViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_border_grey_24dp); - Toast.makeText(mActivity, R.string.post_unsaved_success, Toast.LENGTH_SHORT).show(); - EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); - } - - @Override - public void failed() { - post.setSaved(true); - ((PostBaseViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_grey_24dp); - Toast.makeText(mActivity, R.string.post_unsaved_failed, Toast.LENGTH_SHORT).show(); - EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); - } - }); - } else { - ((PostBaseViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_grey_24dp); - SaveThing.saveThing(mOauthRetrofit, mAccessToken, post.getFullName(), - new SaveThing.SaveThingListener() { - @Override - public void success() { - post.setSaved(true); - ((PostBaseViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_grey_24dp); - Toast.makeText(mActivity, R.string.post_saved_success, Toast.LENGTH_SHORT).show(); - EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); - } - - @Override - public void failed() { - post.setSaved(false); - ((PostBaseViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_border_grey_24dp); - Toast.makeText(mActivity, R.string.post_saved_failed, Toast.LENGTH_SHORT).show(); - EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); - } - }); - } - }); - - ((PostBaseViewHolder) holder).shareButton.setOnClickListener(view -> shareLink(post)); - if (holder instanceof PostVideoAutoplayViewHolder) { /*final Uri gifVideoUri = Uri.parse(post.getVideoUrl()); ((PostBaseViewHolder) holder).imageView.setOnClickListener(view -> { @@ -857,16 +516,6 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { - Intent intent = new Intent(mActivity, ViewImageActivity.class); - intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, imageUrl); - intent.putExtra(ViewImageActivity.FILE_NAME_KEY, subredditName - + "-" + id + ".jpg"); - intent.putExtra(ViewImageActivity.POST_TITLE_KEY, post.getTitle()); - mActivity.startActivity(intent); - }); - if (post.getPreviewWidth() <= 0 || post.getPreviewHeight() <= 0) { ((PostGifTypeViewHolder) holder).imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); ((PostGifTypeViewHolder) holder).imageView.getLayoutParams().height = (int) (400 * mScale); @@ -877,16 +526,6 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { - Intent intent = new Intent(mActivity, ViewImageActivity.class); - intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, imageUrl); - intent.putExtra(ViewImageActivity.FILE_NAME_KEY, subredditName - + "-" + id + ".jpg"); - intent.putExtra(ViewImageActivity.POST_TITLE_KEY, post.getTitle()); - mActivity.startActivity(intent); - }); - if (post.getPreviewWidth() <= 0 || post.getPreviewHeight() <= 0) { ((PostImageTypeViewHolder) holder).imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); ((PostImageTypeViewHolder) holder).imageView.getLayoutParams().height = (int) (400 * mScale); @@ -900,41 +539,17 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { - Intent intent = new Intent(mActivity, LinkResolverActivity.class); - Uri uri = Uri.parse(post.getUrl()); - if (uri.getScheme() == null && uri.getHost() == null) { - intent.setData(LinkResolverActivity.getRedditUriByPath(post.getUrl())); - } else { - intent.setData(uri); - } - mActivity.startActivity(intent); - }); } else if (holder instanceof PostNoPreviewLinkTypeViewHolder) { String noPreviewLinkUrl = post.getUrl(); ((PostNoPreviewLinkTypeViewHolder) holder).linkTextView.setVisibility(View.VISIBLE); String noPreviewLinkDomain = Uri.parse(noPreviewLinkUrl).getHost(); ((PostNoPreviewLinkTypeViewHolder) holder).linkTextView.setText(noPreviewLinkDomain); - ((PostNoPreviewLinkTypeViewHolder) holder).noPreviewLinkImageView.setOnClickListener(view -> { - Intent intent = new Intent(mActivity, LinkResolverActivity.class); - Uri uri = Uri.parse(post.getUrl()); - if (uri.getScheme() == null && uri.getHost() == null) { - intent.setData(LinkResolverActivity.getRedditUriByPath(post.getUrl())); - } else { - intent.setData(uri); - } - mActivity.startActivity(intent); - }); } else if (holder instanceof PostTextTypeViewHolder) { if (post.getSelfTextPlainTrimmed() != null && !post.getSelfTextPlainTrimmed().equals("")) { ((PostTextTypeViewHolder) holder).contentTextView.setVisibility(View.VISIBLE); ((PostTextTypeViewHolder) holder).contentTextView.setText(post.getSelfTextPlainTrimmed()); } } - - - } } else if (holder instanceof PostCompactViewHolder) { Post post = getItem(position); @@ -1895,6 +1510,297 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { + if (canStartActivity) { + canStartActivity = false; + + Intent intent = new Intent(mActivity, ViewPostDetailActivity.class); + intent.putExtra(ViewPostDetailActivity.EXTRA_POST_DATA, getItem(getAdapterPosition())); + intent.putExtra(ViewPostDetailActivity.EXTRA_POST_LIST_POSITION, getAdapterPosition()); + mActivity.startActivity(intent); + } + }); + + userTextView.setOnClickListener(view -> { + if (canStartActivity) { + canStartActivity = false; + Intent intent = new Intent(mActivity, ViewUserDetailActivity.class); + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, getItem(getAdapterPosition()).getAuthor()); + mActivity.startActivity(intent); + } + }); + + if (mDisplaySubredditName) { + subredditTextView.setOnClickListener(view -> { + Post post = getItem(getAdapterPosition()); + if (post != null) { + if (canStartActivity) { + canStartActivity = false; + if (post.getSubredditNamePrefixed().startsWith("u/")) { + Intent intent = new Intent(mActivity, ViewUserDetailActivity.class); + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, + post.getSubredditNamePrefixed().substring(2)); + mActivity.startActivity(intent); + } else { + Intent intent = new Intent(mActivity, ViewSubredditDetailActivity.class); + intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY, + post.getSubredditName()); + mActivity.startActivity(intent); + } + } + } + }); + + iconGifImageView.setOnClickListener(view -> subredditTextView.performClick()); + } else { + subredditTextView.setOnClickListener(view -> { + Post post = getItem(getAdapterPosition()); + if (post != null) { + if (canStartActivity) { + canStartActivity = false; + if (post.getSubredditNamePrefixed().startsWith("u/")) { + Intent intent = new Intent(mActivity, ViewUserDetailActivity.class); + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, post.getAuthor()); + mActivity.startActivity(intent); + } else { + Intent intent = new Intent(mActivity, ViewSubredditDetailActivity.class); + intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY, + post.getSubredditName()); + mActivity.startActivity(intent); + } + } + } + }); + + iconGifImageView.setOnClickListener(view -> userTextView.performClick()); + } + + if (!(mActivity instanceof FilteredThingActivity)) { + nsfwTextView.setOnClickListener(view -> { + Post post = getItem(getAdapterPosition()); + if (post != null) { + Intent intent = new Intent(mActivity, FilteredThingActivity.class); + intent.putExtra(FilteredThingActivity.EXTRA_NAME, post.getSubredditNamePrefixed().substring(2)); + intent.putExtra(FilteredThingActivity.EXTRA_POST_TYPE, PostDataSource.TYPE_SUBREDDIT); + intent.putExtra(FilteredThingActivity.EXTRA_FILTER, Post.NSFW_TYPE); + mActivity.startActivity(intent); + } + }); + typeTextView.setOnClickListener(view -> { + Post post = getItem(getAdapterPosition()); + if (post != null) { + mCallback.typeChipClicked(post.getPostType()); + } + }); + } + + upvoteButton.setOnClickListener(view -> { + Post post = getItem(getAdapterPosition()); + if (post != null) { + if (mAccessToken == null) { + Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); + return; + } + + if (post.isArchived()) { + Toast.makeText(mActivity, R.string.archived_post_vote_unavailable, Toast.LENGTH_SHORT).show(); + return; + } + + ColorFilter previousUpvoteButtonColorFilter = upvoteButton.getColorFilter(); + ColorFilter previousDownvoteButtonColorFilter = downvoteButton.getColorFilter(); + int previousScoreTextViewColor = scoreTextView.getCurrentTextColor(); + + int previousVoteType = post.getVoteType(); + String newVoteType; + + downvoteButton.setColorFilter(mPostIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); + + if (previousVoteType != 1) { + //Not upvoted before + post.setVoteType(1); + newVoteType = RedditUtils.DIR_UPVOTE; + upvoteButton + .setColorFilter(mUpvotedColor, android.graphics.PorterDuff.Mode.SRC_IN); + scoreTextView.setTextColor(mUpvotedColor); + } else { + //Upvoted before + post.setVoteType(0); + newVoteType = RedditUtils.DIR_UNVOTE; + upvoteButton.setColorFilter(mPostIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); + scoreTextView.setTextColor(mPostIconAndInfoColor); + } + + scoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, post.getScore() + post.getVoteType())); + + VoteThing.voteThing(mActivity, mOauthRetrofit, mAccessToken, new VoteThing.VoteThingListener() { + @Override + public void onVoteThingSuccess(int position1) { + if (newVoteType.equals(RedditUtils.DIR_UPVOTE)) { + post.setVoteType(1); + upvoteButton + .setColorFilter(mUpvotedColor, android.graphics.PorterDuff.Mode.SRC_IN); + scoreTextView.setTextColor(mUpvotedColor); + } else { + post.setVoteType(0); + upvoteButton.setColorFilter(mPostIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); + scoreTextView.setTextColor(mPostIconAndInfoColor); + } + + downvoteButton.setColorFilter(mPostIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); + scoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, post.getScore() + post.getVoteType())); + + EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); + } + + @Override + public void onVoteThingFail(int position1) { + Toast.makeText(mActivity, R.string.vote_failed, Toast.LENGTH_SHORT).show(); + post.setVoteType(previousVoteType); + scoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, post.getScore() + previousVoteType)); + upvoteButton.setColorFilter(previousUpvoteButtonColorFilter); + downvoteButton.setColorFilter(previousDownvoteButtonColorFilter); + scoreTextView.setTextColor(previousScoreTextViewColor); + + EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); + } + }, post.getFullName(), newVoteType, getAdapterPosition()); + } + }); + + downvoteButton.setOnClickListener(view -> { + Post post = getItem(getAdapterPosition()); + if (post != null) { + if (mAccessToken == null) { + Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); + return; + } + + if (post.isArchived()) { + Toast.makeText(mActivity, R.string.archived_post_vote_unavailable, Toast.LENGTH_SHORT).show(); + return; + } + + ColorFilter previousUpvoteButtonColorFilter = upvoteButton.getColorFilter(); + ColorFilter previousDownvoteButtonColorFilter = downvoteButton.getColorFilter(); + int previousScoreTextViewColor = scoreTextView.getCurrentTextColor(); + + int previousVoteType = post.getVoteType(); + String newVoteType; + + upvoteButton.setColorFilter(mPostIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); + + if (previousVoteType != -1) { + //Not downvoted before + post.setVoteType(-1); + newVoteType = RedditUtils.DIR_DOWNVOTE; + downvoteButton + .setColorFilter(mDownvotedColor, android.graphics.PorterDuff.Mode.SRC_IN); + scoreTextView.setTextColor(mDownvotedColor); + } else { + //Downvoted before + post.setVoteType(0); + newVoteType = RedditUtils.DIR_UNVOTE; + downvoteButton.setColorFilter(mPostIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); + scoreTextView.setTextColor(mPostIconAndInfoColor); + } + + scoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, post.getScore() + post.getVoteType())); + + VoteThing.voteThing(mActivity, mOauthRetrofit, mAccessToken, new VoteThing.VoteThingListener() { + @Override + public void onVoteThingSuccess(int position1) { + if (newVoteType.equals(RedditUtils.DIR_DOWNVOTE)) { + post.setVoteType(-1); + downvoteButton + .setColorFilter(mDownvotedColor, android.graphics.PorterDuff.Mode.SRC_IN); + scoreTextView.setTextColor(mDownvotedColor); + } else { + post.setVoteType(0); + downvoteButton.setColorFilter(mPostIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); + scoreTextView.setTextColor(mPostIconAndInfoColor); + } + + upvoteButton.setColorFilter(mPostIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); + scoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, post.getScore() + post.getVoteType())); + + EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); + } + + @Override + public void onVoteThingFail(int position1) { + Toast.makeText(mActivity, R.string.vote_failed, Toast.LENGTH_SHORT).show(); + post.setVoteType(previousVoteType); + scoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, post.getScore() + previousVoteType)); + upvoteButton.setColorFilter(previousUpvoteButtonColorFilter); + downvoteButton.setColorFilter(previousDownvoteButtonColorFilter); + scoreTextView.setTextColor(previousScoreTextViewColor); + + EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); + } + }, post.getFullName(), newVoteType, getAdapterPosition()); + } + }); + + saveButton.setOnClickListener(view -> { + Post post = getItem(getAdapterPosition()); + if (post != null) { + if (mAccessToken == null) { + Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); + return; + } + + if (post.isSaved()) { + saveButton.setImageResource(R.drawable.ic_bookmark_border_grey_24dp); + SaveThing.unsaveThing(mOauthRetrofit, mAccessToken, post.getFullName(), + new SaveThing.SaveThingListener() { + @Override + public void success() { + post.setSaved(false); + saveButton.setImageResource(R.drawable.ic_bookmark_border_grey_24dp); + Toast.makeText(mActivity, R.string.post_unsaved_success, Toast.LENGTH_SHORT).show(); + EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); + } + + @Override + public void failed() { + post.setSaved(true); + saveButton.setImageResource(R.drawable.ic_bookmark_grey_24dp); + Toast.makeText(mActivity, R.string.post_unsaved_failed, Toast.LENGTH_SHORT).show(); + EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); + } + }); + } else { + saveButton.setImageResource(R.drawable.ic_bookmark_grey_24dp); + SaveThing.saveThing(mOauthRetrofit, mAccessToken, post.getFullName(), + new SaveThing.SaveThingListener() { + @Override + public void success() { + post.setSaved(true); + saveButton.setImageResource(R.drawable.ic_bookmark_grey_24dp); + Toast.makeText(mActivity, R.string.post_saved_success, Toast.LENGTH_SHORT).show(); + EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); + } + + @Override + public void failed() { + post.setSaved(false); + saveButton.setImageResource(R.drawable.ic_bookmark_border_grey_24dp); + Toast.makeText(mActivity, R.string.post_saved_failed, Toast.LENGTH_SHORT).show(); + EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); + } + }); + } + } + }); + + shareButton.setOnClickListener(view -> { + Post post = getItem(getAdapterPosition()); + if (post != null) { + shareLink(post); + } + }); } } @@ -2120,6 +2026,18 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { + Post post = getItem(getAdapterPosition()); + if (post != null) { + Intent intent = new Intent(mActivity, ViewImageActivity.class); + intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, post.getUrl()); + intent.putExtra(ViewImageActivity.FILE_NAME_KEY, post.getSubredditName() + + "-" + post.getId() + ".jpg"); + intent.putExtra(ViewImageActivity.POST_TITLE_KEY, post.getTitle()); + mActivity.startActivity(intent); + } + }); } } @@ -2204,6 +2122,18 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { + Post post = getItem(getAdapterPosition()); + if (post != null) { + Intent intent = new Intent(mActivity, ViewImageActivity.class); + intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, post.getUrl()); + intent.putExtra(ViewImageActivity.FILE_NAME_KEY, post.getSubredditName() + + "-" + post.getId() + ".jpg"); + intent.putExtra(ViewImageActivity.POST_TITLE_KEY, post.getTitle()); + mActivity.startActivity(intent); + } + }); } } @@ -2291,6 +2221,20 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { + Post post = getItem(getAdapterPosition()); + if (post != null) { + Intent intent = new Intent(mActivity, LinkResolverActivity.class); + Uri uri = Uri.parse(post.getUrl()); + if (uri.getScheme() == null && uri.getHost() == null) { + intent.setData(LinkResolverActivity.getRedditUriByPath(post.getUrl())); + } else { + intent.setData(uri); + } + mActivity.startActivity(intent); + } + }); } } @@ -2372,6 +2316,20 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { + Post post = getItem(getAdapterPosition()); + if (post != null) { + Intent intent = new Intent(mActivity, LinkResolverActivity.class); + Uri uri = Uri.parse(post.getUrl()); + if (uri.getScheme() == null && uri.getHost() == null) { + intent.setData(LinkResolverActivity.getRedditUriByPath(post.getUrl())); + } else { + intent.setData(uri); + } + mActivity.startActivity(intent); + } + }); } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CustomView/CustomToroContainer.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CustomView/CustomToroContainer.java new file mode 100644 index 00000000..40e3fe3e --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/CustomView/CustomToroContainer.java @@ -0,0 +1,27 @@ +package ml.docilealligator.infinityforreddit.CustomView; + +import android.content.Context; +import android.util.AttributeSet; + +import androidx.annotation.Nullable; + +import im.ene.toro.widget.Container; + +public class CustomToroContainer extends Container { + public CustomToroContainer(Context context) { + super(context); + } + + public CustomToroContainer(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public CustomToroContainer(Context context, @Nullable AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + public void onWindowVisibilityChanged(int visibility) { + super.onWindowVisibilityChanged(visibility); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostFragment.java index 50e622ba..10c1398e 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostFragment.java @@ -54,6 +54,7 @@ import ml.docilealligator.infinityforreddit.Activity.MainActivity; import ml.docilealligator.infinityforreddit.Activity.ViewSubredditDetailActivity; import ml.docilealligator.infinityforreddit.Adapter.PostRecyclerViewAdapter; import ml.docilealligator.infinityforreddit.CustomTheme.CustomThemeWrapper; +import ml.docilealligator.infinityforreddit.CustomView.CustomToroContainer; import ml.docilealligator.infinityforreddit.Event.ChangeDefaultPostLayoutEvent; import ml.docilealligator.infinityforreddit.Event.ChangeNSFWBlurEvent; import ml.docilealligator.infinityforreddit.Event.ChangePostLayoutEvent; @@ -96,7 +97,7 @@ public class PostFragment extends Fragment implements FragmentCommunicator { @BindView(R.id.swipe_refresh_layout_post_fragment) SwipeRefreshLayout mSwipeRefreshLayout; @BindView(R.id.recycler_view_post_fragment) - Container mPostRecyclerView; + CustomToroContainer mPostRecyclerView; @BindView(R.id.fetch_post_info_linear_layout_post_fragment) LinearLayout mFetchPostInfoLinearLayout; @BindView(R.id.fetch_post_info_image_view_post_fragment) @@ -155,6 +156,9 @@ public class PostFragment extends Fragment implements FragmentCommunicator { if (isInLazyMode && isLazyModePaused) { resumeLazyMode(false); } + if (mAdapter != null && mPostRecyclerView != null) { + mPostRecyclerView.onWindowVisibilityChanged(View.VISIBLE); + } } private boolean scrollPostsByCount(int count) { @@ -861,6 +865,9 @@ public class PostFragment extends Fragment implements FragmentCommunicator { if (isInLazyMode) { pauseLazyMode(false); } + if (mAdapter != null && mPostRecyclerView != null) { + mPostRecyclerView.onWindowVisibilityChanged(View.GONE); + } } @Override diff --git a/app/src/main/res/layout/activity_view_gif.xml b/app/src/main/res/layout/activity_view_gif.xml index 8740679c..cce51370 100644 --- a/app/src/main/res/layout/activity_view_gif.xml +++ b/app/src/main/res/layout/activity_view_gif.xml @@ -5,7 +5,8 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/parent_relative_layout_view_gif_activity" - android:background="@android:color/black" + android:background="#000000" + android:keepScreenOn="true" tools:application="ml.docilealligator.infinityforreddit.Activity.ViewGIFActivity"> diff --git a/app/src/main/res/layout/fragment_post.xml b/app/src/main/res/layout/fragment_post.xml index dc3248b5..69652bbc 100644 --- a/app/src/main/res/layout/fragment_post.xml +++ b/app/src/main/res/layout/fragment_post.xml @@ -16,7 +16,7 @@ android:layout_height="match_parent" android:clipToPadding="false" />--> - Date: Thu, 30 Apr 2020 15:29:56 +0800 Subject: Add an option for video autoplay. Rewrite some viewholders in PostRecyclerViewAdapter. --- .../Adapter/PostRecyclerViewAdapter.java | 235 ++++++++------- .../Event/ChangeVideoAutoplayEvent.java | 9 + .../infinityforreddit/Fragment/PostFragment.java | 17 +- .../Settings/MainPreferenceFragment.java | 19 +- .../Utils/SharedPreferencesUtils.java | 12 +- .../infinityforreddit/Utils/Utils.java | 17 ++ .../layout/exo_autoplay_playback_control_view.xml | 2 - app/src/main/res/layout/fragment_post.xml | 6 - app/src/main/res/layout/item_post_gif_type.xml | 314 -------------------- .../item_post_image_and_gif_autoplay_type.xml | 313 ++++++++++++++++++++ app/src/main/res/layout/item_post_image_type.xml | 314 -------------------- .../item_post_video_and_gif_preview_type.xml | 328 +++++++++++++++++++++ app/src/main/res/values/arrays.xml | 12 + app/src/main/res/values/strings.xml | 1 + app/src/main/res/xml/main_preferences.xml | 8 + 15 files changed, 845 insertions(+), 762 deletions(-) create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Event/ChangeVideoAutoplayEvent.java delete mode 100644 app/src/main/res/layout/item_post_gif_type.xml create mode 100644 app/src/main/res/layout/item_post_image_and_gif_autoplay_type.xml delete mode 100644 app/src/main/res/layout/item_post_image_type.xml create mode 100644 app/src/main/res/layout/item_post_video_and_gif_preview_type.xml diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java index 1f3335e6..88175912 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java @@ -88,8 +88,8 @@ import retrofit2.Retrofit; public class PostRecyclerViewAdapter extends PagedListAdapter implements CacheManager { private static final int VIEW_TYPE_POST_CARD_VIDEO_TYPE_AUTOPLAY = 1; - private static final int VIEW_TYPE_POST_CARD_GIF_TYPE = 2; - private static final int VIEW_TYPE_POST_CARD_IMAGE_TYPE = 3; + private static final int VIEW_TYPE_POST_CARD_VIDEO_AND_GIF_PREVIEW_TYPE = 2; + private static final int VIEW_TYPE_POST_CARD_IMAGE_AND_GIF_AUTOPLAY_TYPE = 3; private static final int VIEW_TYPE_POST_CARD_LINK_TYPE = 4; private static final int VIEW_TYPE_POST_CARD_NO_PREVIEW_LINK_TYPE = 5; private static final int VIEW_TYPE_POST_CARD_TEXT_TYPE = 6; @@ -153,7 +153,7 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { - Intent intent = new Intent(mActivity, ViewGIFActivity.class); - intent.setData(gifVideoUri); - intent.putExtra(ViewGIFActivity.FILE_NAME_KEY, subredditName - + "-" + id + ".gif"); - intent.putExtra(ViewGIFActivity.GIF_URL_KEY, post.getVideoUrl()); - intent.putExtra(ViewGIFActivity.POST_TITLE_KEY, post.getTitle()); - mActivity.startActivity(intent); - }); - - ((PostBaseViewHolder) holder).playButtonImageView.setVisibility(View.VISIBLE);*/ - - - /*final Uri videoUri = Uri.parse(post.getVideoUrl()); - ((PostBaseViewHolder) holder).imageView.setOnClickListener(view -> { - Intent intent = new Intent(mActivity, ViewVideoActivity.class); - intent.setData(videoUri); - intent.putExtra(ViewVideoActivity.EXTRA_VIDEO_DOWNLOAD_URL, post.getVideoDownloadUrl()); - intent.putExtra(ViewVideoActivity.EXTRA_SUBREDDIT, subredditName); - intent.putExtra(ViewVideoActivity.EXTRA_ID, fullName); - intent.putExtra(ViewVideoActivity.EXTRA_POST_TITLE, post.getTitle()); - mActivity.startActivity(intent); - }); - - ((PostBaseViewHolder) holder).playButtonImageView.setVisibility(View.VISIBLE);*/ - /*((PostVideoAutoplayViewHolder) holder).videoPlayer.setRatio( - (float) post.getPreviewHeight() / post.getPreviewWidth() - );*/ ((PostVideoAutoplayViewHolder) holder).aspectRatioFrameLayout.setAspectRatio((float) post.getPreviewWidth() / post.getPreviewHeight()); ((PostVideoAutoplayViewHolder) holder).bindVideoUri(Uri.parse(post.getVideoUrl())); - } else if (holder instanceof PostGifTypeViewHolder) { - ((PostGifTypeViewHolder) holder).progressBar.setVisibility(View.VISIBLE); - ((PostGifTypeViewHolder) holder).imageView + } else if (holder instanceof PostGifAndVideoPreviewViewHolder) { + if (post.getPostType() == Post.VIDEO_TYPE) { + ((PostGifAndVideoPreviewViewHolder) holder).typeTextView.setText(mActivity.getString(R.string.video)); + } else { + ((PostGifAndVideoPreviewViewHolder) holder).typeTextView.setText(mActivity.getString(R.string.gif)); + } + ((PostGifAndVideoPreviewViewHolder) holder).progressBar.setVisibility(View.VISIBLE); + ((PostGifAndVideoPreviewViewHolder) holder).imageView .setRatio((float) post.getPreviewHeight() / post.getPreviewWidth()); loadImage(holder, post); if (post.getPreviewWidth() <= 0 || post.getPreviewHeight() <= 0) { - ((PostGifTypeViewHolder) holder).imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); - ((PostGifTypeViewHolder) holder).imageView.getLayoutParams().height = (int) (400 * mScale); + ((PostGifAndVideoPreviewViewHolder) holder).imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); + ((PostGifAndVideoPreviewViewHolder) holder).imageView.getLayoutParams().height = (int) (400 * mScale); } - } else if (holder instanceof PostImageTypeViewHolder) { - ((PostImageTypeViewHolder) holder).progressBar.setVisibility(View.VISIBLE); - ((PostImageTypeViewHolder) holder).imageView + } else if (holder instanceof PostImageAndGifAutoplayTypeViewHolder) { + if (post.getPostType() == Post.GIF_TYPE) { + ((PostImageAndGifAutoplayTypeViewHolder) holder).typeTextView.setText(mActivity.getString(R.string.gif)); + } else { + ((PostImageAndGifAutoplayTypeViewHolder) holder).typeTextView.setText(mActivity.getString(R.string.image)); + } + ((PostImageAndGifAutoplayTypeViewHolder) holder).progressBar.setVisibility(View.VISIBLE); + ((PostImageAndGifAutoplayTypeViewHolder) holder).imageView .setRatio((float) post.getPreviewHeight() / post.getPreviewWidth()); loadImage(holder, post); if (post.getPreviewWidth() <= 0 || post.getPreviewHeight() <= 0) { - ((PostImageTypeViewHolder) holder).imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); - ((PostImageTypeViewHolder) holder).imageView.getLayoutParams().height = (int) (400 * mScale); + ((PostImageAndGifAutoplayTypeViewHolder) holder).imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); + ((PostImageAndGifAutoplayTypeViewHolder) holder).imageView.getLayoutParams().height = (int) (400 * mScale); } } else if (holder instanceof PostLinkTypeViewHolder) { ((PostLinkTypeViewHolder) holder).progressBar.setVisibility(View.VISIBLE); @@ -1104,15 +1097,16 @@ public class PostRecyclerViewAdapter extends PagedListAdapter imageRequestBuilder = mGlide.load(post.getPreviewUrl()).listener(new RequestListener() { + if (holder instanceof PostImageAndGifAutoplayTypeViewHolder) { + String url = mAutoplay && post.getPostType() == Post.GIF_TYPE ? post.getUrl() : post.getPreviewUrl(); + RequestBuilder imageRequestBuilder = mGlide.load(url).listener(new RequestListener() { @Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { - ((PostImageTypeViewHolder) holder).progressBar.setVisibility(View.GONE); - ((PostImageTypeViewHolder) holder).errorRelativeLayout.setVisibility(View.VISIBLE); - ((PostImageTypeViewHolder) holder).errorRelativeLayout.setOnClickListener(view -> { - ((PostImageTypeViewHolder) holder).progressBar.setVisibility(View.VISIBLE); - ((PostImageTypeViewHolder) holder).errorRelativeLayout.setVisibility(View.GONE); + ((PostImageAndGifAutoplayTypeViewHolder) holder).progressBar.setVisibility(View.GONE); + ((PostImageAndGifAutoplayTypeViewHolder) holder).errorRelativeLayout.setVisibility(View.VISIBLE); + ((PostImageAndGifAutoplayTypeViewHolder) holder).errorRelativeLayout.setOnClickListener(view -> { + ((PostImageAndGifAutoplayTypeViewHolder) holder).progressBar.setVisibility(View.VISIBLE); + ((PostImageAndGifAutoplayTypeViewHolder) holder).errorRelativeLayout.setVisibility(View.GONE); loadImage(holder, post); }); return false; @@ -1120,28 +1114,27 @@ public class PostRecyclerViewAdapter extends PagedListAdapter target, DataSource dataSource, boolean isFirstResource) { - ((PostImageTypeViewHolder) holder).errorRelativeLayout.setVisibility(View.GONE); - ((PostImageTypeViewHolder) holder).progressBar.setVisibility(View.GONE); + ((PostImageAndGifAutoplayTypeViewHolder) holder).errorRelativeLayout.setVisibility(View.GONE); + ((PostImageAndGifAutoplayTypeViewHolder) holder).progressBar.setVisibility(View.GONE); return false; } }); if ((post.isNSFW() && mNeedBlurNSFW) || post.isSpoiler() && mNeedBlurSpoiler) { imageRequestBuilder.apply(RequestOptions.bitmapTransform(new BlurTransformation(50, 10))) - .into(((PostImageTypeViewHolder) holder).imageView); + .into(((PostImageAndGifAutoplayTypeViewHolder) holder).imageView); } else { - imageRequestBuilder.into(((PostImageTypeViewHolder) holder).imageView); + imageRequestBuilder.into(((PostImageAndGifAutoplayTypeViewHolder) holder).imageView); } - } else if (holder instanceof PostGifTypeViewHolder) { - String url = mAutoplay ? post.getUrl() : post.getPreviewUrl(); - RequestBuilder imageRequestBuilder = mGlide.load(url).listener(new RequestListener() { + } else if (holder instanceof PostGifAndVideoPreviewViewHolder) { + RequestBuilder imageRequestBuilder = mGlide.load(post.getPreviewUrl()).listener(new RequestListener() { @Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { - ((PostGifTypeViewHolder) holder).progressBar.setVisibility(View.GONE); - ((PostGifTypeViewHolder) holder).errorRelativeLayout.setVisibility(View.VISIBLE); - ((PostGifTypeViewHolder) holder).errorRelativeLayout.setOnClickListener(view -> { - ((PostGifTypeViewHolder) holder).progressBar.setVisibility(View.VISIBLE); - ((PostGifTypeViewHolder) holder).errorRelativeLayout.setVisibility(View.GONE); + ((PostGifAndVideoPreviewViewHolder) holder).progressBar.setVisibility(View.GONE); + ((PostGifAndVideoPreviewViewHolder) holder).errorRelativeLayout.setVisibility(View.VISIBLE); + ((PostGifAndVideoPreviewViewHolder) holder).errorRelativeLayout.setOnClickListener(view -> { + ((PostGifAndVideoPreviewViewHolder) holder).progressBar.setVisibility(View.VISIBLE); + ((PostGifAndVideoPreviewViewHolder) holder).errorRelativeLayout.setVisibility(View.GONE); loadImage(holder, post); }); return false; @@ -1149,17 +1142,17 @@ public class PostRecyclerViewAdapter extends PagedListAdapter target, DataSource dataSource, boolean isFirstResource) { - ((PostGifTypeViewHolder) holder).errorRelativeLayout.setVisibility(View.GONE); - ((PostGifTypeViewHolder) holder).progressBar.setVisibility(View.GONE); + ((PostGifAndVideoPreviewViewHolder) holder).errorRelativeLayout.setVisibility(View.GONE); + ((PostGifAndVideoPreviewViewHolder) holder).progressBar.setVisibility(View.GONE); return false; } }); if ((post.isNSFW() && mNeedBlurNSFW) || post.isSpoiler() && mNeedBlurSpoiler) { imageRequestBuilder.apply(RequestOptions.bitmapTransform(new BlurTransformation(50, 10))) - .into(((PostGifTypeViewHolder) holder).imageView); + .into(((PostGifAndVideoPreviewViewHolder) holder).imageView); } else { - imageRequestBuilder.into(((PostGifTypeViewHolder) holder).imageView); + imageRequestBuilder.into(((PostGifAndVideoPreviewViewHolder) holder).imageView); } } else if (holder instanceof PostLinkTypeViewHolder) { RequestBuilder imageRequestBuilder = mGlide.load(post.getPreviewUrl()).listener(new RequestListener() { @@ -1300,16 +1293,19 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { Post post = getItem(getAdapterPosition()); if (post != null) { - Intent intent = new Intent(mActivity, ViewImageActivity.class); - intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, post.getUrl()); - intent.putExtra(ViewImageActivity.FILE_NAME_KEY, post.getSubredditName() - + "-" + post.getId() + ".jpg"); - intent.putExtra(ViewImageActivity.POST_TITLE_KEY, post.getTitle()); - mActivity.startActivity(intent); + if (post.getPostType() == Post.VIDEO_TYPE) { + Intent intent = new Intent(mActivity, ViewVideoActivity.class); + intent.setData(Uri.parse(post.getVideoUrl())); + intent.putExtra(ViewVideoActivity.EXTRA_VIDEO_DOWNLOAD_URL, post.getVideoDownloadUrl()); + intent.putExtra(ViewVideoActivity.EXTRA_SUBREDDIT, post.getSubredditName()); + intent.putExtra(ViewVideoActivity.EXTRA_ID, post.getFullName()); + intent.putExtra(ViewVideoActivity.EXTRA_POST_TITLE, post.getTitle()); + mActivity.startActivity(intent); + } else if (post.getPostType() == Post.GIF_TYPE) { + Intent intent = new Intent(mActivity, ViewGIFActivity.class); + intent.setData(Uri.parse(post.getVideoUrl())); + intent.putExtra(ViewGIFActivity.FILE_NAME_KEY, post.getSubredditName() + + "-" + post.getId() + ".gif"); + intent.putExtra(ViewGIFActivity.GIF_URL_KEY, post.getVideoUrl()); + intent.putExtra(ViewGIFActivity.POST_TITLE_KEY, post.getTitle()); + mActivity.startActivity(intent); + } } }); } } - class PostImageTypeViewHolder extends PostBaseViewHolder { + class PostImageAndGifAutoplayTypeViewHolder extends PostBaseViewHolder { @BindView(R.id.card_view_item_post_image_type) MaterialCardView cardView; @BindView(R.id.icon_gif_image_view_item_post_image_type) @@ -2095,7 +2102,7 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { + EventBus.getDefault().post(new ChangeVideoAutoplayEvent((String) newValue)); + return true; + }); + } if (confirmToExitSwitch != null) { - confirmToExitSwitch.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - EventBus.getDefault().post(new RecreateActivityEvent()); - return true; - } + confirmToExitSwitch.setOnPreferenceChangeListener((preference, newValue) -> { + EventBus.getDefault().post(new RecreateActivityEvent()); + return true; }); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/SharedPreferencesUtils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/SharedPreferencesUtils.java index ec523487..63ab550e 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/SharedPreferencesUtils.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/SharedPreferencesUtils.java @@ -76,6 +76,10 @@ public class SharedPreferencesUtils { public static final String VOLUME_KEYS_NAVIGATE_POSTS = "volume_keys_navigate_posts"; public static final String MUTE_VIDEO = "mute_video"; public static final String OPEN_LINK_IN_APP = "open_link_in_app"; + public static final String VIDEO_AUTOPLAY = "video_autoplay"; + public static final String VIDEO_AUTOPLAY_VALUE_ALWAYS_ON = "2"; + public static final String VIDEO_AUTOPLAY_VALUE_ON_WIFI = "1"; + public static final String VIDEO_AUTOPLAY_VALUE_NEVER = "0"; public static final String LOCK_JUMP_TO_NEXT_TOP_LEVEL_COMMENT_BUTTON = "lock_jump_to_next_top_level_comment_button"; public static final String SWIPE_UP_TO_HIDE_JUMP_TO_NEXT_TOP_LEVEL_COMMENT_BUTTON = "swipe_up_to_hide_jump_to_next_top_level_comments_button"; public static final String SHOW_TOP_LEVEL_COMMENTS_FIRST = "show_top_level_comments_first"; @@ -89,10 +93,10 @@ public class SharedPreferencesUtils { public static final String CUSTOMIZE_DARK_THEME = "customize_dark_theme"; public static final String CUSTOMIZE_AMOLED_THEME = "customize_amoled_theme"; public static final String MANAGE_THEMES = "manage_themes"; - public static final String DELETE_ALL_SUBREDDITS_DATA_IN_DATABASE= "delete_all_subreddits_data_in_database"; - public static final String DELETE_ALL_USERS_DATA_IN_DATABASE= "delete_all_users_data_in_database"; - public static final String DELETE_ALL_SORT_TYPE_DATA_IN_DATABASE= "delete_all_sort_type_data_in_database"; - public static final String DELETE_ALL_POST_LAYOUT_DATA_IN_DATABASE= "delete_all_post_layout_data_in_database"; + public static final String DELETE_ALL_SUBREDDITS_DATA_IN_DATABASE = "delete_all_subreddits_data_in_database"; + public static final String DELETE_ALL_USERS_DATA_IN_DATABASE = "delete_all_users_data_in_database"; + public static final String DELETE_ALL_SORT_TYPE_DATA_IN_DATABASE = "delete_all_sort_type_data_in_database"; + public static final String DELETE_ALL_POST_LAYOUT_DATA_IN_DATABASE = "delete_all_post_layout_data_in_database"; public static final String DELETE_ALL_THEMES_IN_DATABASE = "delete_all_themes_in_database"; public static final String RESET_ALL_SETTINGS = "reset_all_settings"; } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/Utils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/Utils.java index f3788ff8..e6726cbb 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/Utils.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/Utils.java @@ -1,6 +1,9 @@ package ml.docilealligator.infinityforreddit.Utils; import android.content.Context; +import android.net.ConnectivityManager; +import android.net.Network; +import android.net.NetworkInfo; import android.text.Html; import android.text.Spannable; import android.widget.TextView; @@ -87,4 +90,18 @@ public class Utils { } textView.setText(html); } + + public static boolean isConnectedToWifi(Context context) { + ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + if (connMgr != null) { + for (Network network : connMgr.getAllNetworks()) { + NetworkInfo networkInfo = connMgr.getNetworkInfo(network); + if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI) { + return networkInfo.isConnected(); + } + } + } + + return false; + } } diff --git a/app/src/main/res/layout/exo_autoplay_playback_control_view.xml b/app/src/main/res/layout/exo_autoplay_playback_control_view.xml index 99cab8e2..1adc685e 100644 --- a/app/src/main/res/layout/exo_autoplay_playback_control_view.xml +++ b/app/src/main/res/layout/exo_autoplay_playback_control_view.xml @@ -7,8 +7,6 @@ android:gravity="bottom" android:paddingStart="16dp" android:paddingEnd="16dp" - android:paddingBottom="16dp" - android:background="@color/transparentActionBarAndExoPlayerControllerColor" android:orientation="vertical"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/item_post_image_and_gif_autoplay_type.xml b/app/src/main/res/layout/item_post_image_and_gif_autoplay_type.xml new file mode 100644 index 00000000..b2fdf016 --- /dev/null +++ b/app/src/main/res/layout/item_post_image_and_gif_autoplay_type.xml @@ -0,0 +1,313 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_post_image_type.xml b/app/src/main/res/layout/item_post_image_type.xml deleted file mode 100644 index 6ca140d3..00000000 --- a/app/src/main/res/layout/item_post_image_type.xml +++ /dev/null @@ -1,314 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/item_post_video_and_gif_preview_type.xml b/app/src/main/res/layout/item_post_video_and_gif_preview_type.xml new file mode 100644 index 00000000..c3549df4 --- /dev/null +++ b/app/src/main/res/layout/item_post_video_and_gif_preview_type.xml @@ -0,0 +1,328 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 4adfdff9..b415b0f5 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -47,6 +47,18 @@ 1 + + Always On + Only on Wifi + Never + + + + 2 + 1 + 0 + + 1s 2s diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fb7082dd..35dadb3a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -311,6 +311,7 @@ Interface Gestures & Buttons Open Link In App + Video Autoplay Immersive Interface Ignore Navigation Bar in Immersive Interface Prevent the Bottom Navigation Bar Having Extra Padding diff --git a/app/src/main/res/xml/main_preferences.xml b/app/src/main/res/xml/main_preferences.xml index 8622a87f..1074a90e 100644 --- a/app/src/main/res/xml/main_preferences.xml +++ b/app/src/main/res/xml/main_preferences.xml @@ -28,6 +28,14 @@ app:key="open_link_in_app" app:title="@string/settings_open_link_in_app_title" /> + + Date: Thu, 30 Apr 2020 17:33:52 +0800 Subject: Add a BroadcastReceiver to receive network status change and enable or disable video autoplay. --- .../NetworkWifiStatusReceiver.java | 22 ++++++++++++++++++++++ .../Event/ChangeWifiStatusEvent.java | 8 ++++++++ .../infinityforreddit/Fragment/PostFragment.java | 12 ++++++++++++ .../infinityforreddit/Infinity.java | 13 +++++++++++++ 4 files changed, 55 insertions(+) create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/BroadcastReceiver/NetworkWifiStatusReceiver.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Event/ChangeWifiStatusEvent.java diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/BroadcastReceiver/NetworkWifiStatusReceiver.java b/app/src/main/java/ml/docilealligator/infinityforreddit/BroadcastReceiver/NetworkWifiStatusReceiver.java new file mode 100644 index 00000000..fb8d3ae4 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/BroadcastReceiver/NetworkWifiStatusReceiver.java @@ -0,0 +1,22 @@ +package ml.docilealligator.infinityforreddit.BroadcastReceiver; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +public class NetworkWifiStatusReceiver extends BroadcastReceiver { + private NetworkWifiStatusReceiverListener networkWifiStatusReceiverListener; + + public interface NetworkWifiStatusReceiverListener { + void networkStatusChange(); + } + + public NetworkWifiStatusReceiver(NetworkWifiStatusReceiverListener listener) { + networkWifiStatusReceiverListener = listener; + } + + @Override + public void onReceive(Context context, Intent intent) { + networkWifiStatusReceiverListener.networkStatusChange(); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Event/ChangeWifiStatusEvent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/ChangeWifiStatusEvent.java new file mode 100644 index 00000000..2c25b8c9 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/ChangeWifiStatusEvent.java @@ -0,0 +1,8 @@ +package ml.docilealligator.infinityforreddit.Event; + +public class ChangeWifiStatusEvent { + public boolean isConnectedToWifi; + public ChangeWifiStatusEvent(boolean isConnectedToWifi) { + this.isConnectedToWifi = isConnectedToWifi; + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostFragment.java index 6ce0ac92..5b76d340 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostFragment.java @@ -62,6 +62,7 @@ import ml.docilealligator.infinityforreddit.Event.ChangeShowElapsedTimeEvent; import ml.docilealligator.infinityforreddit.Event.ChangeSpoilerBlurEvent; import ml.docilealligator.infinityforreddit.Event.ChangeVideoAutoplayEvent; import ml.docilealligator.infinityforreddit.Event.ChangeVoteButtonsPositionEvent; +import ml.docilealligator.infinityforreddit.Event.ChangeWifiStatusEvent; import ml.docilealligator.infinityforreddit.Event.PostUpdateEventToPostList; import ml.docilealligator.infinityforreddit.Event.ShowDividerInCompactLayoutPreferenceEvent; import ml.docilealligator.infinityforreddit.FragmentCommunicator; @@ -854,6 +855,17 @@ public class PostFragment extends Fragment implements FragmentCommunicator { } } + @Subscribe + public void onChangeWifiStatusEvent(ChangeWifiStatusEvent changeWifiStatusEvent) { + if (mAdapter != null) { + String autoplay = mSharedPreferences.getString(SharedPreferencesUtils.VIDEO_AUTOPLAY, SharedPreferencesUtils.VIDEO_AUTOPLAY_VALUE_NEVER); + if (autoplay.equals(SharedPreferencesUtils.VIDEO_AUTOPLAY_VALUE_ON_WIFI)) { + mAdapter.setAutoplay(changeWifiStatusEvent.isConnectedToWifi); + refreshAdapter(); + } + } + } + private void refreshAdapter() { int previousPosition = -1; if (mLinearLayoutManager != null) { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Infinity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Infinity.java index df5a1100..90478a08 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Infinity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Infinity.java @@ -1,6 +1,8 @@ package ml.docilealligator.infinityforreddit; import android.app.Application; +import android.content.IntentFilter; +import android.net.ConnectivityManager; import android.os.Bundle; import androidx.annotation.NonNull; @@ -10,8 +12,15 @@ import com.evernote.android.state.StateSaver; import com.livefront.bridge.Bridge; import com.livefront.bridge.SavedStateHandler; +import org.greenrobot.eventbus.EventBus; + +import ml.docilealligator.infinityforreddit.BroadcastReceiver.NetworkWifiStatusReceiver; +import ml.docilealligator.infinityforreddit.Event.ChangeWifiStatusEvent; +import ml.docilealligator.infinityforreddit.Utils.Utils; + public class Infinity extends Application { private AppComponent mAppComponent; + private NetworkWifiStatusReceiver mNetworkWifiStatusReceiver; @Override public void onCreate() { @@ -32,6 +41,10 @@ public class Infinity extends Application { StateSaver.restoreInstanceState(target, state); } }); + + mNetworkWifiStatusReceiver = + new NetworkWifiStatusReceiver(() -> EventBus.getDefault().post(new ChangeWifiStatusEvent(Utils.isConnectedToWifi(getApplicationContext())))); + registerReceiver(mNetworkWifiStatusReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); } public AppComponent getAppComponent() { -- cgit v1.2.3 From c52cf467ac24e92cd1846b9ee10fb6acc2fdabfb Mon Sep 17 00:00:00 2001 From: Alex Ning Date: Thu, 30 Apr 2020 21:33:51 +0800 Subject: Probably fix duplicate posts issues. Move classes related to Post to Package Post. --- .../Activity/ViewPostDetailActivity.java | 6 +- .../infinityforreddit/FetchPost.java | 54 --- .../infinityforreddit/HidePost.java | 62 --- .../infinityforreddit/ParsePost.java | 488 --------------------- .../infinityforreddit/Post/FetchPost.java | 54 +++ .../infinityforreddit/Post/HidePost.java | 63 +++ .../infinityforreddit/Post/ParsePost.java | 487 ++++++++++++++++++++ .../infinityforreddit/Post/Post.java | 10 + .../infinityforreddit/Post/PostDataSource.java | 104 +++-- .../infinityforreddit/Post/SubmitPost.java | 464 ++++++++++++++++++++ .../Service/SubmitPostService.java | 2 +- .../infinityforreddit/SubmitPost.java | 464 -------------------- 12 files changed, 1160 insertions(+), 1098 deletions(-) delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/FetchPost.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/HidePost.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/ParsePost.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Post/FetchPost.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Post/HidePost.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Post/ParsePost.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Post/SubmitPost.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/SubmitPost.java diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewPostDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewPostDetailActivity.java index 92d04927..9d8ea8a9 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewPostDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewPostDetailActivity.java @@ -64,14 +64,14 @@ import ml.docilealligator.infinityforreddit.Event.PostUpdateEventToDetailActivit import ml.docilealligator.infinityforreddit.Event.PostUpdateEventToPostList; import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; import ml.docilealligator.infinityforreddit.FetchComment; -import ml.docilealligator.infinityforreddit.FetchPost; +import ml.docilealligator.infinityforreddit.Post.FetchPost; import ml.docilealligator.infinityforreddit.Flair; import ml.docilealligator.infinityforreddit.Fragment.FlairBottomSheetFragment; import ml.docilealligator.infinityforreddit.Fragment.PostCommentSortTypeBottomSheetFragment; -import ml.docilealligator.infinityforreddit.HidePost; +import ml.docilealligator.infinityforreddit.Post.HidePost; import ml.docilealligator.infinityforreddit.Infinity; import ml.docilealligator.infinityforreddit.ParseComment; -import ml.docilealligator.infinityforreddit.ParsePost; +import ml.docilealligator.infinityforreddit.Post.ParsePost; import ml.docilealligator.infinityforreddit.Post.Post; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.ReadMessage; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchPost.java b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchPost.java deleted file mode 100644 index 9f0c93ba..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchPost.java +++ /dev/null @@ -1,54 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import androidx.annotation.NonNull; - -import java.util.Locale; - -import ml.docilealligator.infinityforreddit.Post.Post; -import ml.docilealligator.infinityforreddit.Utils.RedditUtils; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; -import retrofit2.Retrofit; - -public class FetchPost { - public static void fetchPost(Retrofit retrofit, String id, String accessToken, Locale locale, FetchPostListener fetchPostListener) { - Call postCall; - if (accessToken == null) { - postCall = retrofit.create(RedditAPI.class).getPost(id); - } else { - postCall = retrofit.create(RedditAPI.class).getPostOauth(id, RedditUtils.getOAuthHeader(accessToken)); - } - postCall.enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - if (response.isSuccessful()) { - ParsePost.parsePost(response.body(), locale, new ParsePost.ParsePostListener() { - @Override - public void onParsePostSuccess(Post post) { - fetchPostListener.fetchPostSuccess(post); - } - - @Override - public void onParsePostFail() { - fetchPostListener.fetchPostFailed(); - } - }); - } else { - fetchPostListener.fetchPostFailed(); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - fetchPostListener.fetchPostFailed(); - } - }); - } - - public interface FetchPostListener { - void fetchPostSuccess(Post post); - - void fetchPostFailed(); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/HidePost.java b/app/src/main/java/ml/docilealligator/infinityforreddit/HidePost.java deleted file mode 100644 index 39f6a2fb..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/HidePost.java +++ /dev/null @@ -1,62 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import androidx.annotation.NonNull; - -import java.util.HashMap; -import java.util.Map; - -import ml.docilealligator.infinityforreddit.Utils.RedditUtils; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; -import retrofit2.Retrofit; - -public class HidePost { - public static void hidePost(Retrofit oauthRetrofit, String accessToken, String fullname, - HidePostListener hidePostListener) { - Map params = new HashMap<>(); - params.put(RedditUtils.ID_KEY, fullname); - oauthRetrofit.create(RedditAPI.class).hide(RedditUtils.getOAuthHeader(accessToken), params).enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - if (response.isSuccessful()) { - hidePostListener.success(); - } else { - hidePostListener.failed(); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - hidePostListener.failed(); - } - }); - } - - public static void unhidePost(Retrofit oauthRetrofit, String accessToken, String fullname, - HidePostListener hidePostListener) { - Map params = new HashMap<>(); - params.put(RedditUtils.ID_KEY, fullname); - oauthRetrofit.create(RedditAPI.class).unhide(RedditUtils.getOAuthHeader(accessToken), params).enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - if (response.isSuccessful()) { - hidePostListener.success(); - } else { - hidePostListener.failed(); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - hidePostListener.failed(); - } - }); - } - - public interface HidePostListener { - void success(); - - void failed(); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ParsePost.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ParsePost.java deleted file mode 100644 index 3a4845e1..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ParsePost.java +++ /dev/null @@ -1,488 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.os.AsyncTask; -import android.text.Html; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Locale; - -import ml.docilealligator.infinityforreddit.Fragment.PostFragment; -import ml.docilealligator.infinityforreddit.Post.Post; -import ml.docilealligator.infinityforreddit.Utils.JSONUtils; -import ml.docilealligator.infinityforreddit.Utils.Utils; - -/** - * Created by alex on 3/21/18. - */ - -public class ParsePost { - public static void parsePosts(String response, Locale locale, int nPosts, int filter, boolean nsfw, - ParsePostsListingListener parsePostsListingListener) { - new ParsePostDataAsyncTask(response, locale, nPosts, filter, nsfw, parsePostsListingListener).execute(); - } - - public static void parsePost(String response, Locale locale, ParsePostListener parsePostListener) { - new ParsePostDataAsyncTask(response, locale, true, parsePostListener).execute(); - } - - private static Post parseBasicData(JSONObject data, Locale locale) throws JSONException { - String id = data.getString(JSONUtils.ID_KEY); - String fullName = data.getString(JSONUtils.NAME_KEY); - String subredditName = data.getString(JSONUtils.SUBREDDIT_KEY); - String subredditNamePrefixed = data.getString(JSONUtils.SUBREDDIT_NAME_PREFIX_KEY); - String author = data.getString(JSONUtils.AUTHOR_KEY); - StringBuilder authorFlairHTMLBuilder = new StringBuilder(); - if (data.has(JSONUtils.AUTHOR_FLAIR_RICHTEXT_KEY)) { - JSONArray flairArray = data.getJSONArray(JSONUtils.AUTHOR_FLAIR_RICHTEXT_KEY); - for (int i = 0; i < flairArray.length(); i++) { - JSONObject flairObject = flairArray.getJSONObject(i); - String e = flairObject.getString(JSONUtils.E_KEY); - if (e.equals("text")) { - authorFlairHTMLBuilder.append(flairObject.getString(JSONUtils.T_KEY)); - } else if (e.equals("emoji")) { - authorFlairHTMLBuilder.append(""); - } - } - } - String authorFlair = data.isNull(JSONUtils.AUTHOR_FLAIR_TEXT_KEY) ? "" : data.getString(JSONUtils.AUTHOR_FLAIR_TEXT_KEY); - long postTime = data.getLong(JSONUtils.CREATED_UTC_KEY) * 1000; - String title = data.getString(JSONUtils.TITLE_KEY); - int score = data.getInt(JSONUtils.SCORE_KEY); - int voteType; - int nComments = data.getInt(JSONUtils.NUM_COMMENTS_KEY); - boolean hidden = data.getBoolean(JSONUtils.HIDDEN_KEY); - boolean spoiler = data.getBoolean(JSONUtils.SPOILER_KEY); - boolean nsfw = data.getBoolean(JSONUtils.NSFW_KEY); - boolean stickied = data.getBoolean(JSONUtils.STICKIED_KEY); - boolean archived = data.getBoolean(JSONUtils.ARCHIVED_KEY); - boolean locked = data.getBoolean(JSONUtils.LOCKEC_KEY); - boolean saved = data.getBoolean(JSONUtils.SAVED_KEY); - StringBuilder postFlairHTMLBuilder = new StringBuilder(); - if (data.has(JSONUtils.LINK_FLAIR_RICHTEXT_KEY)) { - JSONArray flairArray = data.getJSONArray(JSONUtils.LINK_FLAIR_RICHTEXT_KEY); - for (int i = 0; i < flairArray.length(); i++) { - JSONObject flairObject = flairArray.getJSONObject(i); - String e = flairObject.getString(JSONUtils.E_KEY); - if (e.equals("text")) { - postFlairHTMLBuilder.append(Html.escapeHtml(flairObject.getString(JSONUtils.T_KEY))); - } else if (e.equals("emoji")) { - postFlairHTMLBuilder.append(""); - } - } - } - String flair = postFlairHTMLBuilder.toString(); - StringBuilder awardingsBuilder = new StringBuilder(); - JSONArray awardingsArray = data.getJSONArray(JSONUtils.ALL_AWARDINGS_KEY); - int nAwards = 0; - for (int i = 0; i < awardingsArray.length(); i++) { - JSONObject award = awardingsArray.getJSONObject(i); - int count = award.getInt(JSONUtils.COUNT_KEY); - nAwards += count; - JSONArray icons = award.getJSONArray(JSONUtils.RESIZED_ICONS_KEY); - if (icons.length() > 4) { - String iconUrl = icons.getJSONObject(3).getString(JSONUtils.URL_KEY); - awardingsBuilder.append(" ").append("x").append(count).append(" "); - } else if (icons.length() > 0) { - String iconUrl = icons.getJSONObject(icons.length() - 1).getString(JSONUtils.URL_KEY); - awardingsBuilder.append(" ").append("x").append(count).append(" "); - } - } - - if (data.isNull(JSONUtils.LIKES_KEY)) { - voteType = 0; - } else { - voteType = data.getBoolean(JSONUtils.LIKES_KEY) ? 1 : -1; - score -= voteType; - } - - Calendar postTimeCalendar = Calendar.getInstance(); - postTimeCalendar.setTimeInMillis(postTime); - String formattedPostTime = new SimpleDateFormat("MMM d, yyyy, HH:mm", - locale).format(postTimeCalendar.getTime()); - String permalink = Html.fromHtml(data.getString(JSONUtils.PERMALINK_KEY)).toString(); - - String previewUrl = ""; - String thumbnailPreviewUrl = ""; - int previewWidth = -1; - int previewHeight = -1; - if (data.has(JSONUtils.PREVIEW_KEY)) { - JSONObject images = data.getJSONObject(JSONUtils.PREVIEW_KEY).getJSONArray(JSONUtils.IMAGES_KEY).getJSONObject(0); - previewUrl = images.getJSONObject(JSONUtils.SOURCE_KEY).getString(JSONUtils.URL_KEY); - JSONArray thumbnailPreviews = images.getJSONArray(JSONUtils.RESOLUTIONS_KEY); - int thumbnailPreviewsLength = thumbnailPreviews.length(); - if (thumbnailPreviewsLength > 0) { - if (thumbnailPreviewsLength >= 3) { - thumbnailPreviewUrl = images.getJSONArray(JSONUtils.RESOLUTIONS_KEY).getJSONObject(2).getString(JSONUtils.URL_KEY); - } else { - thumbnailPreviewUrl = images.getJSONArray(JSONUtils.RESOLUTIONS_KEY).getJSONObject(0).getString(JSONUtils.URL_KEY); - } - } - previewWidth = images.getJSONObject(JSONUtils.SOURCE_KEY).getInt(JSONUtils.WIDTH_KEY); - previewHeight = images.getJSONObject(JSONUtils.SOURCE_KEY).getInt(JSONUtils.HEIGHT_KEY); - } - if (data.has(JSONUtils.CROSSPOST_PARENT_LIST)) { - //Cross post - data = data.getJSONArray(JSONUtils.CROSSPOST_PARENT_LIST).getJSONObject(0); - Post crosspostParent = parseBasicData(data, locale); - Post post = parseData(data, permalink, id, fullName, subredditName, subredditNamePrefixed, - author, authorFlair, authorFlairHTMLBuilder.toString(), formattedPostTime, - postTime, title, previewUrl, thumbnailPreviewUrl, previewWidth, previewHeight, - score, voteType, nComments, flair, awardingsBuilder.toString(), nAwards, hidden, - spoiler, nsfw, stickied, archived, locked, saved, true); - post.setCrosspostParentId(crosspostParent.getId()); - return post; - } else { - return parseData(data, permalink, id, fullName, subredditName, subredditNamePrefixed, - author, authorFlair, authorFlairHTMLBuilder.toString(), formattedPostTime, - postTime, title, previewUrl, thumbnailPreviewUrl, previewWidth, previewHeight, - score, voteType, nComments, flair, awardingsBuilder.toString(), nAwards, hidden, - spoiler, nsfw, stickied, archived, locked, saved, false); - } - } - - private static Post parseData(JSONObject data, String permalink, String id, String fullName, - String subredditName, String subredditNamePrefixed, String author, - String authorFlair, String authorFlairHTML, String formattedPostTime, - long postTimeMillis, String title, String previewUrl, - String thumbnailPreviewUrl, int previewWidth, int previewHeight, - int score, int voteType, int nComments, String flair, - String awards, int nAwards, boolean hidden, boolean spoiler, - boolean nsfw, boolean stickied, boolean archived, boolean locked, - boolean saved, boolean isCrosspost) throws JSONException { - Post post; - - boolean isVideo = data.getBoolean(JSONUtils.IS_VIDEO_KEY); - String url = Html.fromHtml(data.getString(JSONUtils.URL_KEY)).toString(); - - if (!data.has(JSONUtils.PREVIEW_KEY) && previewUrl.equals("")) { - if (url.contains(permalink)) { - //Text post - int postType = Post.TEXT_TYPE; - post = new Post(id, fullName, subredditName, subredditNamePrefixed, author, - authorFlair, authorFlairHTML, formattedPostTime, postTimeMillis, - title, permalink, score, postType, voteType, nComments, flair, awards, nAwards, - hidden, spoiler, nsfw, stickied, archived, locked, saved, isCrosspost); - if (data.isNull(JSONUtils.SELFTEXT_KEY)) { - post.setSelfText(""); - } else { - post.setSelfText(Utils.modifyMarkdown(data.getString(JSONUtils.SELFTEXT_KEY).trim())); - if (data.isNull(JSONUtils.SELFTEXT_HTML_KEY)) { - post.setSelfTextPlainTrimmed(""); - } else { - String selfTextPlain = Utils.trimTrailingWhitespace( - Html.fromHtml(data.getString(JSONUtils.SELFTEXT_HTML_KEY))).toString(); - post.setSelfTextPlain(selfTextPlain); - if (selfTextPlain.length() > 250) { - selfTextPlain = selfTextPlain.substring(0, 250); - } - post.setSelfTextPlainTrimmed(selfTextPlain); - } - } - } else { - if (url.endsWith("jpg") || url.endsWith("png")) { - //Image post - int postType = Post.IMAGE_TYPE; - - post = new Post(id, fullName, subredditName, subredditNamePrefixed, author, - authorFlair, authorFlairHTML, formattedPostTime, postTimeMillis, title, - url, thumbnailPreviewUrl, url, permalink, score, postType, voteType, - nComments, flair, awards, nAwards, hidden, spoiler, nsfw, stickied, archived, - locked, saved, isCrosspost); - - post.setPreviewWidth(previewWidth); - post.setPreviewHeight(previewHeight); - } else { - //No preview link post - int postType = Post.NO_PREVIEW_LINK_TYPE; - post = new Post(id, fullName, subredditName, subredditNamePrefixed, author, - authorFlair, authorFlairHTML, formattedPostTime, postTimeMillis, - title, previewUrl, thumbnailPreviewUrl, url, permalink, score, postType, - voteType, nComments, flair, awards, nAwards, hidden, spoiler, nsfw, stickied, - archived, locked, saved, isCrosspost); - if (data.isNull(JSONUtils.SELFTEXT_KEY)) { - post.setSelfText(""); - } else { - post.setSelfText(Utils.modifyMarkdown(data.getString(JSONUtils.SELFTEXT_KEY).trim())); - } - } - } - } else { - if (previewUrl.equals("")) { - previewUrl = Html.fromHtml(data.getJSONObject(JSONUtils.PREVIEW_KEY).getJSONArray(JSONUtils.IMAGES_KEY).getJSONObject(0) - .getJSONObject(JSONUtils.SOURCE_KEY).getString(JSONUtils.URL_KEY)).toString(); - } - - if (isVideo) { - //Video post - JSONObject redditVideoObject = data.getJSONObject(JSONUtils.MEDIA_KEY).getJSONObject(JSONUtils.REDDIT_VIDEO_KEY); - int postType = Post.VIDEO_TYPE; - String videoUrl = Html.fromHtml(redditVideoObject.getString(JSONUtils.HLS_URL_KEY)).toString(); - String videoDownloadUrl = redditVideoObject.getString(JSONUtils.FALLBACK_URL_KEY); - - post = new Post(id, fullName, subredditName, subredditNamePrefixed, author, - authorFlair, authorFlairHTML, formattedPostTime, postTimeMillis, title, - previewUrl, thumbnailPreviewUrl, permalink, score, postType, voteType, - nComments, flair, awards, nAwards, hidden, spoiler, nsfw, stickied, archived, locked, - saved, isCrosspost); - - post.setPreviewWidth(previewWidth); - post.setPreviewHeight(previewHeight); - post.setVideoUrl(videoUrl); - post.setVideoDownloadUrl(videoDownloadUrl); - } else if (data.has(JSONUtils.PREVIEW_KEY)) { - if (data.getJSONObject(JSONUtils.PREVIEW_KEY).has(JSONUtils.REDDIT_VIDEO_PREVIEW_KEY)) { - //Gif video post (HLS) - int postType = Post.VIDEO_TYPE; - String videoUrl = Html.fromHtml(data.getJSONObject(JSONUtils.PREVIEW_KEY) - .getJSONObject(JSONUtils.REDDIT_VIDEO_PREVIEW_KEY).getString(JSONUtils.HLS_URL_KEY)).toString(); - String videoDownloadUrl = data.getJSONObject(JSONUtils.PREVIEW_KEY) - .getJSONObject(JSONUtils.REDDIT_VIDEO_PREVIEW_KEY).getString(JSONUtils.FALLBACK_URL_KEY); - - post = new Post(id, fullName, subredditName, subredditNamePrefixed, author, - authorFlair, authorFlairHTML, formattedPostTime, postTimeMillis, title, - previewUrl, thumbnailPreviewUrl, permalink, score, postType, voteType, - nComments, flair, awards, nAwards, hidden, spoiler, nsfw, stickied, archived, - locked, saved, isCrosspost); - post.setPreviewWidth(previewWidth); - post.setPreviewHeight(previewHeight); - post.setVideoUrl(videoUrl); - post.setVideoDownloadUrl(videoDownloadUrl); - } else { - if (url.endsWith("jpg") || url.endsWith("png")) { - //Image post - int postType = Post.IMAGE_TYPE; - - post = new Post(id, fullName, subredditName, subredditNamePrefixed, author, - authorFlair, authorFlairHTML, formattedPostTime, postTimeMillis, - title, url, thumbnailPreviewUrl, url, permalink, score, postType, - voteType, nComments, flair, awards, nAwards, hidden, spoiler, nsfw, - stickied, archived, locked, saved, isCrosspost); - - post.setPreviewWidth(previewWidth); - post.setPreviewHeight(previewHeight); - } else if (url.endsWith("gif")){ - //Gif post - int postType = Post.GIF_TYPE; - post = new Post(id, fullName, subredditName, subredditNamePrefixed, author, - authorFlair, authorFlairHTML, formattedPostTime, postTimeMillis, - title, previewUrl, thumbnailPreviewUrl, url, permalink, score, - postType, voteType, nComments, flair, awards, nAwards, hidden, spoiler, - nsfw, stickied, archived, locked, saved, isCrosspost); - - post.setPreviewWidth(previewWidth); - post.setPreviewHeight(previewHeight); - post.setVideoUrl(url); - } else { - if (url.contains(permalink)) { - //Text post but with a preview - int postType = Post.TEXT_TYPE; - - post = new Post(id, fullName, subredditName, subredditNamePrefixed, author, - authorFlair, authorFlairHTML, formattedPostTime, postTimeMillis, - title, permalink, score, postType, voteType, nComments, flair, - awards, nAwards, hidden, spoiler, nsfw, stickied, archived, locked, - saved, isCrosspost); - - post.setPreviewWidth(previewWidth); - post.setPreviewHeight(previewHeight); - - if (data.isNull(JSONUtils.SELFTEXT_KEY)) { - post.setSelfText(""); - } else { - post.setSelfText(Utils.modifyMarkdown(data.getString(JSONUtils.SELFTEXT_KEY).trim())); - if (data.isNull(JSONUtils.SELFTEXT_HTML_KEY)) { - post.setSelfTextPlainTrimmed(""); - } else { - String selfTextPlain = Utils.trimTrailingWhitespace( - Html.fromHtml(data.getString(JSONUtils.SELFTEXT_HTML_KEY))).toString(); - post.setSelfTextPlain(selfTextPlain); - if (selfTextPlain.length() > 250) { - selfTextPlain = selfTextPlain.substring(0, 250); - } - post.setSelfTextPlainTrimmed(selfTextPlain); - } - } - } else { - //Link post - int postType = Post.LINK_TYPE; - - post = new Post(id, fullName, subredditName, subredditNamePrefixed, author, - authorFlair, authorFlairHTML, formattedPostTime, postTimeMillis, - title, previewUrl, thumbnailPreviewUrl, url, permalink, score, - postType, voteType, nComments, flair, awards, nAwards, hidden, spoiler, - nsfw, stickied, archived, locked, saved, isCrosspost); - if (data.isNull(JSONUtils.SELFTEXT_KEY)) { - post.setSelfText(""); - } else { - post.setSelfText(Utils.modifyMarkdown(data.getString(JSONUtils.SELFTEXT_KEY).trim())); - } - - post.setPreviewWidth(previewWidth); - post.setPreviewHeight(previewHeight); - } - } - } - } else { - if (url.endsWith("jpg") || url.endsWith("png")) { - //Image post - int postType = Post.IMAGE_TYPE; - - post = new Post(id, fullName, subredditName, subredditNamePrefixed, author, - authorFlair, authorFlairHTML, formattedPostTime, postTimeMillis, title, - previewUrl, thumbnailPreviewUrl, url, permalink, score, postType, - voteType, nComments, flair, awards, nAwards, hidden, spoiler, nsfw, stickied, - archived, locked, saved, isCrosspost); - post.setPreviewWidth(previewWidth); - post.setPreviewHeight(previewHeight); - } else { - //CP No Preview Link post - int postType = Post.NO_PREVIEW_LINK_TYPE; - - post = new Post(id, fullName, subredditName, subredditNamePrefixed, author, - authorFlair, authorFlairHTML, formattedPostTime, postTimeMillis, title, - url, thumbnailPreviewUrl, url, permalink, score, postType, voteType, - nComments, flair, awards, nAwards, hidden, spoiler, nsfw, stickied, archived, - locked, saved, isCrosspost); - } - } - } - - return post; - } - - public interface ParsePostsListingListener { - void onParsePostsListingSuccess(ArrayList newPostData, String lastItem); - - void onParsePostsListingFail(); - } - - public interface ParsePostListener { - void onParsePostSuccess(Post post); - - void onParsePostFail(); - } - - private static class ParsePostDataAsyncTask extends AsyncTask { - private JSONArray allData; - private Locale locale; - private int nPosts; - private int filter; - private boolean nsfw; - private ParsePostsListingListener parsePostsListingListener; - private ParsePostListener parsePostListener; - private ArrayList newPosts; - private Post post; - private String lastItem; - private boolean parseFailed; - - ParsePostDataAsyncTask(String response, Locale locale, int nPosts, int filter, boolean nsfw, - ParsePostsListingListener parsePostsListingListener) { - this.parsePostsListingListener = parsePostsListingListener; - try { - JSONObject jsonResponse = new JSONObject(response); - allData = jsonResponse.getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY); - lastItem = jsonResponse.getJSONObject(JSONUtils.DATA_KEY).getString(JSONUtils.AFTER_KEY); - this.locale = locale; - this.nPosts = nPosts; - this.filter = filter; - this.nsfw = nsfw; - newPosts = new ArrayList<>(); - parseFailed = false; - } catch (JSONException e) { - e.printStackTrace(); - parseFailed = true; - } - } - - ParsePostDataAsyncTask(String response, Locale locale, boolean nsfw, - ParsePostListener parsePostListener) { - this.parsePostListener = parsePostListener; - try { - allData = new JSONArray(response).getJSONObject(0).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY); - this.locale = locale; - this.nsfw = nsfw; - parseFailed = false; - } catch (JSONException e) { - e.printStackTrace(); - parseFailed = true; - } - } - - @Override - protected Void doInBackground(Void... voids) { - if (parseFailed) { - return null; - } - - if (newPosts == null) { - //Only one post - if (allData.length() == 0) { - parseFailed = true; - return null; - } - - try { - JSONObject data = allData.getJSONObject(0).getJSONObject(JSONUtils.DATA_KEY); - post = parseBasicData(data, locale); - } catch (JSONException e) { - e.printStackTrace(); - parseFailed = true; - } - } else { - //Posts listing - int size; - if (nPosts < 0 || nPosts > allData.length()) { - size = allData.length(); - } else { - size = nPosts; - } - - for (int i = 0; i < size; i++) { - try { - if (allData.getJSONObject(i).getString(JSONUtils.KIND_KEY).equals("t3")) { - JSONObject data = allData.getJSONObject(i).getJSONObject(JSONUtils.DATA_KEY); - Post post = parseBasicData(data, locale); - if (!(!nsfw && post.isNSFW())) { - if (filter == PostFragment.EXTRA_NO_FILTER) { - newPosts.add(post); - } else if (filter == post.getPostType()) { - newPosts.add(post); - } else if (filter == Post.LINK_TYPE && post.getPostType() == Post.NO_PREVIEW_LINK_TYPE) { - newPosts.add(post); - } else if (filter == Post.NSFW_TYPE && post.isNSFW()) { - newPosts.add(post); - } - } - } - } catch (JSONException e) { - e.printStackTrace(); - } - } - } - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - if (!parseFailed) { - if (newPosts != null) { - parsePostsListingListener.onParsePostsListingSuccess(newPosts, lastItem); - } else { - parsePostListener.onParsePostSuccess(post); - } - } else { - if (parsePostsListingListener != null) { - parsePostsListingListener.onParsePostsListingFail(); - } else { - parsePostListener.onParsePostFail(); - } - } - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Post/FetchPost.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Post/FetchPost.java new file mode 100644 index 00000000..ccbec648 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Post/FetchPost.java @@ -0,0 +1,54 @@ +package ml.docilealligator.infinityforreddit.Post; + +import androidx.annotation.NonNull; + +import java.util.Locale; + +import ml.docilealligator.infinityforreddit.RedditAPI; +import ml.docilealligator.infinityforreddit.Utils.RedditUtils; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; + +public class FetchPost { + public static void fetchPost(Retrofit retrofit, String id, String accessToken, Locale locale, FetchPostListener fetchPostListener) { + Call postCall; + if (accessToken == null) { + postCall = retrofit.create(RedditAPI.class).getPost(id); + } else { + postCall = retrofit.create(RedditAPI.class).getPostOauth(id, RedditUtils.getOAuthHeader(accessToken)); + } + postCall.enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if (response.isSuccessful()) { + ParsePost.parsePost(response.body(), locale, new ParsePost.ParsePostListener() { + @Override + public void onParsePostSuccess(Post post) { + fetchPostListener.fetchPostSuccess(post); + } + + @Override + public void onParsePostFail() { + fetchPostListener.fetchPostFailed(); + } + }); + } else { + fetchPostListener.fetchPostFailed(); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + fetchPostListener.fetchPostFailed(); + } + }); + } + + public interface FetchPostListener { + void fetchPostSuccess(Post post); + + void fetchPostFailed(); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Post/HidePost.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Post/HidePost.java new file mode 100644 index 00000000..ab031fa5 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Post/HidePost.java @@ -0,0 +1,63 @@ +package ml.docilealligator.infinityforreddit.Post; + +import androidx.annotation.NonNull; + +import java.util.HashMap; +import java.util.Map; + +import ml.docilealligator.infinityforreddit.RedditAPI; +import ml.docilealligator.infinityforreddit.Utils.RedditUtils; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; + +public class HidePost { + public static void hidePost(Retrofit oauthRetrofit, String accessToken, String fullname, + HidePostListener hidePostListener) { + Map params = new HashMap<>(); + params.put(RedditUtils.ID_KEY, fullname); + oauthRetrofit.create(RedditAPI.class).hide(RedditUtils.getOAuthHeader(accessToken), params).enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if (response.isSuccessful()) { + hidePostListener.success(); + } else { + hidePostListener.failed(); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + hidePostListener.failed(); + } + }); + } + + public static void unhidePost(Retrofit oauthRetrofit, String accessToken, String fullname, + HidePostListener hidePostListener) { + Map params = new HashMap<>(); + params.put(RedditUtils.ID_KEY, fullname); + oauthRetrofit.create(RedditAPI.class).unhide(RedditUtils.getOAuthHeader(accessToken), params).enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if (response.isSuccessful()) { + hidePostListener.success(); + } else { + hidePostListener.failed(); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + hidePostListener.failed(); + } + }); + } + + public interface HidePostListener { + void success(); + + void failed(); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Post/ParsePost.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Post/ParsePost.java new file mode 100644 index 00000000..ba59f855 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Post/ParsePost.java @@ -0,0 +1,487 @@ +package ml.docilealligator.infinityforreddit.Post; + +import android.os.AsyncTask; +import android.text.Html; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.LinkedHashSet; +import java.util.Locale; + +import ml.docilealligator.infinityforreddit.Fragment.PostFragment; +import ml.docilealligator.infinityforreddit.Utils.JSONUtils; +import ml.docilealligator.infinityforreddit.Utils.Utils; + +/** + * Created by alex on 3/21/18. + */ + +public class ParsePost { + public static void parsePosts(String response, Locale locale, int nPosts, int filter, boolean nsfw, + ParsePostsListingListener parsePostsListingListener) { + new ParsePostDataAsyncTask(response, locale, nPosts, filter, nsfw, parsePostsListingListener).execute(); + } + + public static void parsePost(String response, Locale locale, ParsePostListener parsePostListener) { + new ParsePostDataAsyncTask(response, locale, true, parsePostListener).execute(); + } + + private static Post parseBasicData(JSONObject data, Locale locale) throws JSONException { + String id = data.getString(JSONUtils.ID_KEY); + String fullName = data.getString(JSONUtils.NAME_KEY); + String subredditName = data.getString(JSONUtils.SUBREDDIT_KEY); + String subredditNamePrefixed = data.getString(JSONUtils.SUBREDDIT_NAME_PREFIX_KEY); + String author = data.getString(JSONUtils.AUTHOR_KEY); + StringBuilder authorFlairHTMLBuilder = new StringBuilder(); + if (data.has(JSONUtils.AUTHOR_FLAIR_RICHTEXT_KEY)) { + JSONArray flairArray = data.getJSONArray(JSONUtils.AUTHOR_FLAIR_RICHTEXT_KEY); + for (int i = 0; i < flairArray.length(); i++) { + JSONObject flairObject = flairArray.getJSONObject(i); + String e = flairObject.getString(JSONUtils.E_KEY); + if (e.equals("text")) { + authorFlairHTMLBuilder.append(flairObject.getString(JSONUtils.T_KEY)); + } else if (e.equals("emoji")) { + authorFlairHTMLBuilder.append(""); + } + } + } + String authorFlair = data.isNull(JSONUtils.AUTHOR_FLAIR_TEXT_KEY) ? "" : data.getString(JSONUtils.AUTHOR_FLAIR_TEXT_KEY); + long postTime = data.getLong(JSONUtils.CREATED_UTC_KEY) * 1000; + String title = data.getString(JSONUtils.TITLE_KEY); + int score = data.getInt(JSONUtils.SCORE_KEY); + int voteType; + int nComments = data.getInt(JSONUtils.NUM_COMMENTS_KEY); + boolean hidden = data.getBoolean(JSONUtils.HIDDEN_KEY); + boolean spoiler = data.getBoolean(JSONUtils.SPOILER_KEY); + boolean nsfw = data.getBoolean(JSONUtils.NSFW_KEY); + boolean stickied = data.getBoolean(JSONUtils.STICKIED_KEY); + boolean archived = data.getBoolean(JSONUtils.ARCHIVED_KEY); + boolean locked = data.getBoolean(JSONUtils.LOCKEC_KEY); + boolean saved = data.getBoolean(JSONUtils.SAVED_KEY); + StringBuilder postFlairHTMLBuilder = new StringBuilder(); + if (data.has(JSONUtils.LINK_FLAIR_RICHTEXT_KEY)) { + JSONArray flairArray = data.getJSONArray(JSONUtils.LINK_FLAIR_RICHTEXT_KEY); + for (int i = 0; i < flairArray.length(); i++) { + JSONObject flairObject = flairArray.getJSONObject(i); + String e = flairObject.getString(JSONUtils.E_KEY); + if (e.equals("text")) { + postFlairHTMLBuilder.append(Html.escapeHtml(flairObject.getString(JSONUtils.T_KEY))); + } else if (e.equals("emoji")) { + postFlairHTMLBuilder.append(""); + } + } + } + String flair = postFlairHTMLBuilder.toString(); + StringBuilder awardingsBuilder = new StringBuilder(); + JSONArray awardingsArray = data.getJSONArray(JSONUtils.ALL_AWARDINGS_KEY); + int nAwards = 0; + for (int i = 0; i < awardingsArray.length(); i++) { + JSONObject award = awardingsArray.getJSONObject(i); + int count = award.getInt(JSONUtils.COUNT_KEY); + nAwards += count; + JSONArray icons = award.getJSONArray(JSONUtils.RESIZED_ICONS_KEY); + if (icons.length() > 4) { + String iconUrl = icons.getJSONObject(3).getString(JSONUtils.URL_KEY); + awardingsBuilder.append(" ").append("x").append(count).append(" "); + } else if (icons.length() > 0) { + String iconUrl = icons.getJSONObject(icons.length() - 1).getString(JSONUtils.URL_KEY); + awardingsBuilder.append(" ").append("x").append(count).append(" "); + } + } + + if (data.isNull(JSONUtils.LIKES_KEY)) { + voteType = 0; + } else { + voteType = data.getBoolean(JSONUtils.LIKES_KEY) ? 1 : -1; + score -= voteType; + } + + Calendar postTimeCalendar = Calendar.getInstance(); + postTimeCalendar.setTimeInMillis(postTime); + String formattedPostTime = new SimpleDateFormat("MMM d, yyyy, HH:mm", + locale).format(postTimeCalendar.getTime()); + String permalink = Html.fromHtml(data.getString(JSONUtils.PERMALINK_KEY)).toString(); + + String previewUrl = ""; + String thumbnailPreviewUrl = ""; + int previewWidth = -1; + int previewHeight = -1; + if (data.has(JSONUtils.PREVIEW_KEY)) { + JSONObject images = data.getJSONObject(JSONUtils.PREVIEW_KEY).getJSONArray(JSONUtils.IMAGES_KEY).getJSONObject(0); + previewUrl = images.getJSONObject(JSONUtils.SOURCE_KEY).getString(JSONUtils.URL_KEY); + JSONArray thumbnailPreviews = images.getJSONArray(JSONUtils.RESOLUTIONS_KEY); + int thumbnailPreviewsLength = thumbnailPreviews.length(); + if (thumbnailPreviewsLength > 0) { + if (thumbnailPreviewsLength >= 3) { + thumbnailPreviewUrl = images.getJSONArray(JSONUtils.RESOLUTIONS_KEY).getJSONObject(2).getString(JSONUtils.URL_KEY); + } else { + thumbnailPreviewUrl = images.getJSONArray(JSONUtils.RESOLUTIONS_KEY).getJSONObject(0).getString(JSONUtils.URL_KEY); + } + } + previewWidth = images.getJSONObject(JSONUtils.SOURCE_KEY).getInt(JSONUtils.WIDTH_KEY); + previewHeight = images.getJSONObject(JSONUtils.SOURCE_KEY).getInt(JSONUtils.HEIGHT_KEY); + } + if (data.has(JSONUtils.CROSSPOST_PARENT_LIST)) { + //Cross post + data = data.getJSONArray(JSONUtils.CROSSPOST_PARENT_LIST).getJSONObject(0); + Post crosspostParent = parseBasicData(data, locale); + Post post = parseData(data, permalink, id, fullName, subredditName, subredditNamePrefixed, + author, authorFlair, authorFlairHTMLBuilder.toString(), formattedPostTime, + postTime, title, previewUrl, thumbnailPreviewUrl, previewWidth, previewHeight, + score, voteType, nComments, flair, awardingsBuilder.toString(), nAwards, hidden, + spoiler, nsfw, stickied, archived, locked, saved, true); + post.setCrosspostParentId(crosspostParent.getId()); + return post; + } else { + return parseData(data, permalink, id, fullName, subredditName, subredditNamePrefixed, + author, authorFlair, authorFlairHTMLBuilder.toString(), formattedPostTime, + postTime, title, previewUrl, thumbnailPreviewUrl, previewWidth, previewHeight, + score, voteType, nComments, flair, awardingsBuilder.toString(), nAwards, hidden, + spoiler, nsfw, stickied, archived, locked, saved, false); + } + } + + private static Post parseData(JSONObject data, String permalink, String id, String fullName, + String subredditName, String subredditNamePrefixed, String author, + String authorFlair, String authorFlairHTML, String formattedPostTime, + long postTimeMillis, String title, String previewUrl, + String thumbnailPreviewUrl, int previewWidth, int previewHeight, + int score, int voteType, int nComments, String flair, + String awards, int nAwards, boolean hidden, boolean spoiler, + boolean nsfw, boolean stickied, boolean archived, boolean locked, + boolean saved, boolean isCrosspost) throws JSONException { + Post post; + + boolean isVideo = data.getBoolean(JSONUtils.IS_VIDEO_KEY); + String url = Html.fromHtml(data.getString(JSONUtils.URL_KEY)).toString(); + + if (!data.has(JSONUtils.PREVIEW_KEY) && previewUrl.equals("")) { + if (url.contains(permalink)) { + //Text post + int postType = Post.TEXT_TYPE; + post = new Post(id, fullName, subredditName, subredditNamePrefixed, author, + authorFlair, authorFlairHTML, formattedPostTime, postTimeMillis, + title, permalink, score, postType, voteType, nComments, flair, awards, nAwards, + hidden, spoiler, nsfw, stickied, archived, locked, saved, isCrosspost); + if (data.isNull(JSONUtils.SELFTEXT_KEY)) { + post.setSelfText(""); + } else { + post.setSelfText(Utils.modifyMarkdown(data.getString(JSONUtils.SELFTEXT_KEY).trim())); + if (data.isNull(JSONUtils.SELFTEXT_HTML_KEY)) { + post.setSelfTextPlainTrimmed(""); + } else { + String selfTextPlain = Utils.trimTrailingWhitespace( + Html.fromHtml(data.getString(JSONUtils.SELFTEXT_HTML_KEY))).toString(); + post.setSelfTextPlain(selfTextPlain); + if (selfTextPlain.length() > 250) { + selfTextPlain = selfTextPlain.substring(0, 250); + } + post.setSelfTextPlainTrimmed(selfTextPlain); + } + } + } else { + if (url.endsWith("jpg") || url.endsWith("png")) { + //Image post + int postType = Post.IMAGE_TYPE; + + post = new Post(id, fullName, subredditName, subredditNamePrefixed, author, + authorFlair, authorFlairHTML, formattedPostTime, postTimeMillis, title, + url, thumbnailPreviewUrl, url, permalink, score, postType, voteType, + nComments, flair, awards, nAwards, hidden, spoiler, nsfw, stickied, archived, + locked, saved, isCrosspost); + + post.setPreviewWidth(previewWidth); + post.setPreviewHeight(previewHeight); + } else { + //No preview link post + int postType = Post.NO_PREVIEW_LINK_TYPE; + post = new Post(id, fullName, subredditName, subredditNamePrefixed, author, + authorFlair, authorFlairHTML, formattedPostTime, postTimeMillis, + title, previewUrl, thumbnailPreviewUrl, url, permalink, score, postType, + voteType, nComments, flair, awards, nAwards, hidden, spoiler, nsfw, stickied, + archived, locked, saved, isCrosspost); + if (data.isNull(JSONUtils.SELFTEXT_KEY)) { + post.setSelfText(""); + } else { + post.setSelfText(Utils.modifyMarkdown(data.getString(JSONUtils.SELFTEXT_KEY).trim())); + } + } + } + } else { + if (previewUrl.equals("")) { + previewUrl = Html.fromHtml(data.getJSONObject(JSONUtils.PREVIEW_KEY).getJSONArray(JSONUtils.IMAGES_KEY).getJSONObject(0) + .getJSONObject(JSONUtils.SOURCE_KEY).getString(JSONUtils.URL_KEY)).toString(); + } + + if (isVideo) { + //Video post + JSONObject redditVideoObject = data.getJSONObject(JSONUtils.MEDIA_KEY).getJSONObject(JSONUtils.REDDIT_VIDEO_KEY); + int postType = Post.VIDEO_TYPE; + String videoUrl = Html.fromHtml(redditVideoObject.getString(JSONUtils.HLS_URL_KEY)).toString(); + String videoDownloadUrl = redditVideoObject.getString(JSONUtils.FALLBACK_URL_KEY); + + post = new Post(id, fullName, subredditName, subredditNamePrefixed, author, + authorFlair, authorFlairHTML, formattedPostTime, postTimeMillis, title, + previewUrl, thumbnailPreviewUrl, permalink, score, postType, voteType, + nComments, flair, awards, nAwards, hidden, spoiler, nsfw, stickied, archived, locked, + saved, isCrosspost); + + post.setPreviewWidth(previewWidth); + post.setPreviewHeight(previewHeight); + post.setVideoUrl(videoUrl); + post.setVideoDownloadUrl(videoDownloadUrl); + } else if (data.has(JSONUtils.PREVIEW_KEY)) { + if (data.getJSONObject(JSONUtils.PREVIEW_KEY).has(JSONUtils.REDDIT_VIDEO_PREVIEW_KEY)) { + //Gif video post (HLS) + int postType = Post.VIDEO_TYPE; + String videoUrl = Html.fromHtml(data.getJSONObject(JSONUtils.PREVIEW_KEY) + .getJSONObject(JSONUtils.REDDIT_VIDEO_PREVIEW_KEY).getString(JSONUtils.HLS_URL_KEY)).toString(); + String videoDownloadUrl = data.getJSONObject(JSONUtils.PREVIEW_KEY) + .getJSONObject(JSONUtils.REDDIT_VIDEO_PREVIEW_KEY).getString(JSONUtils.FALLBACK_URL_KEY); + + post = new Post(id, fullName, subredditName, subredditNamePrefixed, author, + authorFlair, authorFlairHTML, formattedPostTime, postTimeMillis, title, + previewUrl, thumbnailPreviewUrl, permalink, score, postType, voteType, + nComments, flair, awards, nAwards, hidden, spoiler, nsfw, stickied, archived, + locked, saved, isCrosspost); + post.setPreviewWidth(previewWidth); + post.setPreviewHeight(previewHeight); + post.setVideoUrl(videoUrl); + post.setVideoDownloadUrl(videoDownloadUrl); + } else { + if (url.endsWith("jpg") || url.endsWith("png")) { + //Image post + int postType = Post.IMAGE_TYPE; + + post = new Post(id, fullName, subredditName, subredditNamePrefixed, author, + authorFlair, authorFlairHTML, formattedPostTime, postTimeMillis, + title, url, thumbnailPreviewUrl, url, permalink, score, postType, + voteType, nComments, flair, awards, nAwards, hidden, spoiler, nsfw, + stickied, archived, locked, saved, isCrosspost); + + post.setPreviewWidth(previewWidth); + post.setPreviewHeight(previewHeight); + } else if (url.endsWith("gif")){ + //Gif post + int postType = Post.GIF_TYPE; + post = new Post(id, fullName, subredditName, subredditNamePrefixed, author, + authorFlair, authorFlairHTML, formattedPostTime, postTimeMillis, + title, previewUrl, thumbnailPreviewUrl, url, permalink, score, + postType, voteType, nComments, flair, awards, nAwards, hidden, spoiler, + nsfw, stickied, archived, locked, saved, isCrosspost); + + post.setPreviewWidth(previewWidth); + post.setPreviewHeight(previewHeight); + post.setVideoUrl(url); + } else { + if (url.contains(permalink)) { + //Text post but with a preview + int postType = Post.TEXT_TYPE; + + post = new Post(id, fullName, subredditName, subredditNamePrefixed, author, + authorFlair, authorFlairHTML, formattedPostTime, postTimeMillis, + title, permalink, score, postType, voteType, nComments, flair, + awards, nAwards, hidden, spoiler, nsfw, stickied, archived, locked, + saved, isCrosspost); + + post.setPreviewWidth(previewWidth); + post.setPreviewHeight(previewHeight); + + if (data.isNull(JSONUtils.SELFTEXT_KEY)) { + post.setSelfText(""); + } else { + post.setSelfText(Utils.modifyMarkdown(data.getString(JSONUtils.SELFTEXT_KEY).trim())); + if (data.isNull(JSONUtils.SELFTEXT_HTML_KEY)) { + post.setSelfTextPlainTrimmed(""); + } else { + String selfTextPlain = Utils.trimTrailingWhitespace( + Html.fromHtml(data.getString(JSONUtils.SELFTEXT_HTML_KEY))).toString(); + post.setSelfTextPlain(selfTextPlain); + if (selfTextPlain.length() > 250) { + selfTextPlain = selfTextPlain.substring(0, 250); + } + post.setSelfTextPlainTrimmed(selfTextPlain); + } + } + } else { + //Link post + int postType = Post.LINK_TYPE; + + post = new Post(id, fullName, subredditName, subredditNamePrefixed, author, + authorFlair, authorFlairHTML, formattedPostTime, postTimeMillis, + title, previewUrl, thumbnailPreviewUrl, url, permalink, score, + postType, voteType, nComments, flair, awards, nAwards, hidden, spoiler, + nsfw, stickied, archived, locked, saved, isCrosspost); + if (data.isNull(JSONUtils.SELFTEXT_KEY)) { + post.setSelfText(""); + } else { + post.setSelfText(Utils.modifyMarkdown(data.getString(JSONUtils.SELFTEXT_KEY).trim())); + } + + post.setPreviewWidth(previewWidth); + post.setPreviewHeight(previewHeight); + } + } + } + } else { + if (url.endsWith("jpg") || url.endsWith("png")) { + //Image post + int postType = Post.IMAGE_TYPE; + + post = new Post(id, fullName, subredditName, subredditNamePrefixed, author, + authorFlair, authorFlairHTML, formattedPostTime, postTimeMillis, title, + previewUrl, thumbnailPreviewUrl, url, permalink, score, postType, + voteType, nComments, flair, awards, nAwards, hidden, spoiler, nsfw, stickied, + archived, locked, saved, isCrosspost); + post.setPreviewWidth(previewWidth); + post.setPreviewHeight(previewHeight); + } else { + //CP No Preview Link post + int postType = Post.NO_PREVIEW_LINK_TYPE; + + post = new Post(id, fullName, subredditName, subredditNamePrefixed, author, + authorFlair, authorFlairHTML, formattedPostTime, postTimeMillis, title, + url, thumbnailPreviewUrl, url, permalink, score, postType, voteType, + nComments, flair, awards, nAwards, hidden, spoiler, nsfw, stickied, archived, + locked, saved, isCrosspost); + } + } + } + + return post; + } + + public interface ParsePostsListingListener { + void onParsePostsListingSuccess(LinkedHashSet newPostData, String lastItem); + + void onParsePostsListingFail(); + } + + public interface ParsePostListener { + void onParsePostSuccess(Post post); + + void onParsePostFail(); + } + + private static class ParsePostDataAsyncTask extends AsyncTask { + private JSONArray allData; + private Locale locale; + private int nPosts; + private int filter; + private boolean nsfw; + private ParsePostsListingListener parsePostsListingListener; + private ParsePostListener parsePostListener; + private LinkedHashSet newPosts; + private Post post; + private String lastItem; + private boolean parseFailed; + + ParsePostDataAsyncTask(String response, Locale locale, int nPosts, int filter, boolean nsfw, + ParsePostsListingListener parsePostsListingListener) { + this.parsePostsListingListener = parsePostsListingListener; + try { + JSONObject jsonResponse = new JSONObject(response); + allData = jsonResponse.getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY); + lastItem = jsonResponse.getJSONObject(JSONUtils.DATA_KEY).getString(JSONUtils.AFTER_KEY); + this.locale = locale; + this.nPosts = nPosts; + this.filter = filter; + this.nsfw = nsfw; + newPosts = new LinkedHashSet<>(); + parseFailed = false; + } catch (JSONException e) { + e.printStackTrace(); + parseFailed = true; + } + } + + ParsePostDataAsyncTask(String response, Locale locale, boolean nsfw, + ParsePostListener parsePostListener) { + this.parsePostListener = parsePostListener; + try { + allData = new JSONArray(response).getJSONObject(0).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY); + this.locale = locale; + this.nsfw = nsfw; + parseFailed = false; + } catch (JSONException e) { + e.printStackTrace(); + parseFailed = true; + } + } + + @Override + protected Void doInBackground(Void... voids) { + if (parseFailed) { + return null; + } + + if (newPosts == null) { + //Only one post + if (allData.length() == 0) { + parseFailed = true; + return null; + } + + try { + JSONObject data = allData.getJSONObject(0).getJSONObject(JSONUtils.DATA_KEY); + post = parseBasicData(data, locale); + } catch (JSONException e) { + e.printStackTrace(); + parseFailed = true; + } + } else { + //Posts listing + int size; + if (nPosts < 0 || nPosts > allData.length()) { + size = allData.length(); + } else { + size = nPosts; + } + + for (int i = 0; i < size; i++) { + try { + if (allData.getJSONObject(i).getString(JSONUtils.KIND_KEY).equals("t3")) { + JSONObject data = allData.getJSONObject(i).getJSONObject(JSONUtils.DATA_KEY); + Post post = parseBasicData(data, locale); + if (!(!nsfw && post.isNSFW())) { + if (filter == PostFragment.EXTRA_NO_FILTER) { + newPosts.add(post); + } else if (filter == post.getPostType()) { + newPosts.add(post); + } else if (filter == Post.LINK_TYPE && post.getPostType() == Post.NO_PREVIEW_LINK_TYPE) { + newPosts.add(post); + } else if (filter == Post.NSFW_TYPE && post.isNSFW()) { + newPosts.add(post); + } + } + } + } catch (JSONException e) { + e.printStackTrace(); + } + } + } + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + if (!parseFailed) { + if (newPosts != null) { + parsePostsListingListener.onParsePostsListingSuccess(newPosts, lastItem); + } else { + parsePostListener.onParsePostSuccess(post); + } + } else { + if (parsePostsListingListener != null) { + parsePostsListingListener.onParsePostsListingFail(); + } else { + parsePostListener.onParsePostFail(); + } + } + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Post/Post.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Post/Post.java index d8b98ad8..eccc4388 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Post/Post.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Post/Post.java @@ -3,6 +3,8 @@ package ml.docilealligator.infinityforreddit.Post; import android.os.Parcel; import android.os.Parcelable; +import androidx.annotation.Nullable; + import ml.docilealligator.infinityforreddit.Utils.RedditUtils; /** @@ -506,4 +508,12 @@ public class Post implements Parcelable { parcel.writeByte((byte) (isCrosspost ? 1 : 0)); parcel.writeString(crosspostParentId); } + + @Override + public boolean equals(@Nullable Object obj) { + if (!(obj instanceof Post)) { + return false; + } + return ((Post) obj).getFullName().equals(fullName); + } } \ No newline at end of file diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Post/PostDataSource.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Post/PostDataSource.java index 19536c47..e8e865b1 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Post/PostDataSource.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Post/PostDataSource.java @@ -5,10 +5,11 @@ import androidx.lifecycle.MutableLiveData; import androidx.paging.PageKeyedDataSource; import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; import java.util.Locale; import ml.docilealligator.infinityforreddit.NetworkState; -import ml.docilealligator.infinityforreddit.ParsePost; import ml.docilealligator.infinityforreddit.RedditAPI; import ml.docilealligator.infinityforreddit.SortType; import ml.docilealligator.infinityforreddit.Utils.RedditUtils; @@ -42,6 +43,7 @@ public class PostDataSource extends PageKeyedDataSource { private int filter; private String userWhere; private String multiRedditPath; + private LinkedHashSet postLinkedHashSet; private MutableLiveData paginationNetworkStateLiveData; private MutableLiveData initialLoadStateLiveData; @@ -62,6 +64,7 @@ public class PostDataSource extends PageKeyedDataSource { this.sortType = sortType == null ? new SortType(SortType.Type.BEST) : sortType; this.filter = filter; this.nsfw = nsfw; + postLinkedHashSet = new LinkedHashSet<>(); } PostDataSource(Retrofit retrofit, String accessToken, Locale locale, String path, int postType, @@ -97,6 +100,7 @@ public class PostDataSource extends PageKeyedDataSource { } this.filter = filter; this.nsfw = nsfw; + postLinkedHashSet = new LinkedHashSet<>(); } PostDataSource(Retrofit retrofit, String accessToken, Locale locale, String subredditOrUserName, int postType, @@ -113,6 +117,7 @@ public class PostDataSource extends PageKeyedDataSource { userWhere = where; this.filter = filter; this.nsfw = nsfw; + postLinkedHashSet = new LinkedHashSet<>(); } PostDataSource(Retrofit retrofit, String accessToken, Locale locale, String subredditOrUserName, String query, @@ -129,6 +134,7 @@ public class PostDataSource extends PageKeyedDataSource { this.sortType = sortType == null ? new SortType(SortType.Type.RELEVANCE) : sortType; this.filter = filter; this.nsfw = nsfw; + postLinkedHashSet = new LinkedHashSet<>(); } MutableLiveData getPaginationNetworkStateLiveData() { @@ -234,7 +240,7 @@ public class PostDataSource extends PageKeyedDataSource { ParsePost.parsePosts(response.body(), locale, -1, filter, nsfw, new ParsePost.ParsePostsListingListener() { @Override - public void onParsePostsListingSuccess(ArrayList newPosts, String lastItem) { + public void onParsePostsListingSuccess(LinkedHashSet newPosts, String lastItem) { String nextPageKey; if (lastItem == null || lastItem.equals("") || lastItem.equals("null")) { nextPageKey = null; @@ -242,14 +248,17 @@ public class PostDataSource extends PageKeyedDataSource { nextPageKey = lastItem; } + int currentPostsSize = postLinkedHashSet.size(); if (newPosts.size() != 0) { - callback.onResult(newPosts, null, nextPageKey); + postLinkedHashSet.addAll(newPosts); + callback.onResult(new ArrayList<>(newPosts), null, nextPageKey); hasPostLiveData.postValue(true); } else if (nextPageKey != null) { loadBestPostsInitial(callback, nextPageKey); return; } else { - callback.onResult(newPosts, null, nextPageKey); + postLinkedHashSet.addAll(newPosts); + callback.onResult(new ArrayList<>(newPosts), null, nextPageKey); hasPostLiveData.postValue(false); } @@ -296,11 +305,18 @@ public class PostDataSource extends PageKeyedDataSource { ParsePost.parsePosts(response.body(), locale, -1, filter, nsfw, new ParsePost.ParsePostsListingListener() { @Override - public void onParsePostsListingSuccess(ArrayList newPosts, String lastItem) { + public void onParsePostsListingSuccess(LinkedHashSet newPosts, String lastItem) { if (newPosts.size() == 0 && lastItem != null && !lastItem.equals("") && !lastItem.equals("null")) { loadBestPostsAfter(params, callback, lastItem); } else { - callback.onResult(newPosts, lastItem); + int currentPostsSize = postLinkedHashSet.size(); + postLinkedHashSet.addAll(newPosts); + if (currentPostsSize == postLinkedHashSet.size()) { + callback.onResult(new ArrayList<>(), lastItem); + } else { + List newPostsList = new ArrayList<>(postLinkedHashSet).subList(currentPostsSize, postLinkedHashSet.size()); + callback.onResult(newPostsList, lastItem); + } paginationNetworkStateLiveData.postValue(NetworkState.LOADED); } } @@ -366,7 +382,7 @@ public class PostDataSource extends PageKeyedDataSource { ParsePost.parsePosts(response.body(), locale, -1, filter, nsfw, new ParsePost.ParsePostsListingListener() { @Override - public void onParsePostsListingSuccess(ArrayList newPosts, String lastItem) { + public void onParsePostsListingSuccess(LinkedHashSet newPosts, String lastItem) { String nextPageKey; if (lastItem == null || lastItem.equals("") || lastItem.equals("null")) { nextPageKey = null; @@ -375,13 +391,15 @@ public class PostDataSource extends PageKeyedDataSource { } if (newPosts.size() != 0) { - callback.onResult(newPosts, null, nextPageKey); + postLinkedHashSet.addAll(newPosts); + callback.onResult(new ArrayList<>(newPosts), null, nextPageKey); hasPostLiveData.postValue(true); } else if (nextPageKey != null) { loadSubredditPostsInitial(callback, nextPageKey); return; } else { - callback.onResult(newPosts, null, nextPageKey); + postLinkedHashSet.addAll(newPosts); + callback.onResult(new ArrayList<>(newPosts), null, nextPageKey); hasPostLiveData.postValue(false); } @@ -439,11 +457,18 @@ public class PostDataSource extends PageKeyedDataSource { ParsePost.parsePosts(response.body(), locale, -1, filter, nsfw, new ParsePost.ParsePostsListingListener() { @Override - public void onParsePostsListingSuccess(ArrayList newPosts, String lastItem) { + public void onParsePostsListingSuccess(LinkedHashSet newPosts, String lastItem) { if (newPosts.size() == 0 && lastItem != null && !lastItem.equals("") && !lastItem.equals("null")) { loadSubredditPostsAfter(params, callback, lastItem); } else { - callback.onResult(newPosts, lastItem); + int currentPostsSize = postLinkedHashSet.size(); + postLinkedHashSet.addAll(newPosts); + if (currentPostsSize == postLinkedHashSet.size()) { + callback.onResult(new ArrayList<>(), lastItem); + } else { + List newPostsList = new ArrayList<>(postLinkedHashSet).subList(currentPostsSize, postLinkedHashSet.size()); + callback.onResult(newPostsList, lastItem); + } paginationNetworkStateLiveData.postValue(NetworkState.LOADED); } } @@ -493,7 +518,7 @@ public class PostDataSource extends PageKeyedDataSource { ParsePost.parsePosts(response.body(), locale, -1, filter, nsfw, new ParsePost.ParsePostsListingListener() { @Override - public void onParsePostsListingSuccess(ArrayList newPosts, String lastItem) { + public void onParsePostsListingSuccess(LinkedHashSet newPosts, String lastItem) { String nextPageKey; if (lastItem == null || lastItem.equals("") || lastItem.equals("null")) { nextPageKey = null; @@ -502,13 +527,15 @@ public class PostDataSource extends PageKeyedDataSource { } if (newPosts.size() != 0) { - callback.onResult(newPosts, null, nextPageKey); + postLinkedHashSet.addAll(newPosts); + callback.onResult(new ArrayList<>(newPosts), null, nextPageKey); hasPostLiveData.postValue(true); } else if (nextPageKey != null) { loadUserPostsInitial(callback, nextPageKey); return; } else { - callback.onResult(newPosts, null, nextPageKey); + postLinkedHashSet.addAll(newPosts); + callback.onResult(new ArrayList<>(newPosts), null, nextPageKey); hasPostLiveData.postValue(false); } @@ -562,11 +589,18 @@ public class PostDataSource extends PageKeyedDataSource { ParsePost.parsePosts(response.body(), locale, -1, filter, nsfw, new ParsePost.ParsePostsListingListener() { @Override - public void onParsePostsListingSuccess(ArrayList newPosts, String lastItem) { + public void onParsePostsListingSuccess(LinkedHashSet newPosts, String lastItem) { if (newPosts.size() == 0 && lastItem != null && !lastItem.equals("") && !lastItem.equals("null")) { loadUserPostsAfter(params, callback, lastItem); } else { - callback.onResult(newPosts, lastItem); + int currentPostsSize = postLinkedHashSet.size(); + postLinkedHashSet.addAll(newPosts); + if (currentPostsSize == postLinkedHashSet.size()) { + callback.onResult(new ArrayList<>(), lastItem); + } else { + List newPostsList = new ArrayList<>(postLinkedHashSet).subList(currentPostsSize, postLinkedHashSet.size()); + callback.onResult(newPostsList, lastItem); + } paginationNetworkStateLiveData.postValue(NetworkState.LOADED); } } @@ -638,7 +672,7 @@ public class PostDataSource extends PageKeyedDataSource { ParsePost.parsePosts(response.body(), locale, -1, filter, nsfw, new ParsePost.ParsePostsListingListener() { @Override - public void onParsePostsListingSuccess(ArrayList newPosts, String lastItem) { + public void onParsePostsListingSuccess(LinkedHashSet newPosts, String lastItem) { String nextPageKey; if (lastItem == null || lastItem.equals("") || lastItem.equals("null")) { nextPageKey = null; @@ -647,13 +681,15 @@ public class PostDataSource extends PageKeyedDataSource { } if (newPosts.size() != 0) { - callback.onResult(newPosts, null, nextPageKey); + postLinkedHashSet.addAll(newPosts); + callback.onResult(new ArrayList<>(newPosts), null, nextPageKey); hasPostLiveData.postValue(true); } else if (nextPageKey != null) { loadSearchPostsInitial(callback, nextPageKey); return; } else { - callback.onResult(newPosts, null, nextPageKey); + postLinkedHashSet.addAll(newPosts); + callback.onResult(new ArrayList<>(newPosts), null, nextPageKey); hasPostLiveData.postValue(false); } @@ -727,11 +763,18 @@ public class PostDataSource extends PageKeyedDataSource { ParsePost.parsePosts(response.body(), locale, -1, filter, nsfw, new ParsePost.ParsePostsListingListener() { @Override - public void onParsePostsListingSuccess(ArrayList newPosts, String lastItem) { + public void onParsePostsListingSuccess(LinkedHashSet newPosts, String lastItem) { if (newPosts.size() == 0 && lastItem != null && !lastItem.equals("") && !lastItem.equals("null")) { loadSearchPostsAfter(params, callback, lastItem); } else { - callback.onResult(newPosts, lastItem); + int currentPostsSize = postLinkedHashSet.size(); + postLinkedHashSet.addAll(newPosts); + if (currentPostsSize == postLinkedHashSet.size()) { + callback.onResult(new ArrayList<>(), lastItem); + } else { + List newPostsList = new ArrayList<>(postLinkedHashSet).subList(currentPostsSize, postLinkedHashSet.size()); + callback.onResult(newPostsList, lastItem); + } paginationNetworkStateLiveData.postValue(NetworkState.LOADED); } } @@ -780,7 +823,7 @@ public class PostDataSource extends PageKeyedDataSource { ParsePost.parsePosts(response.body(), locale, -1, filter, nsfw, new ParsePost.ParsePostsListingListener() { @Override - public void onParsePostsListingSuccess(ArrayList newPosts, String lastItem) { + public void onParsePostsListingSuccess(LinkedHashSet newPosts, String lastItem) { String nextPageKey; if (lastItem == null || lastItem.equals("") || lastItem.equals("null")) { nextPageKey = null; @@ -789,13 +832,15 @@ public class PostDataSource extends PageKeyedDataSource { } if (newPosts.size() != 0) { - callback.onResult(newPosts, null, nextPageKey); + postLinkedHashSet.addAll(newPosts); + callback.onResult(new ArrayList<>(newPosts), null, nextPageKey); hasPostLiveData.postValue(true); } else if (nextPageKey != null) { loadMultiRedditPostsInitial(callback, nextPageKey); return; } else { - callback.onResult(newPosts, null, nextPageKey); + postLinkedHashSet.addAll(newPosts); + callback.onResult(new ArrayList<>(newPosts), null, nextPageKey); hasPostLiveData.postValue(false); } @@ -849,11 +894,18 @@ public class PostDataSource extends PageKeyedDataSource { ParsePost.parsePosts(response.body(), locale, -1, filter, nsfw, new ParsePost.ParsePostsListingListener() { @Override - public void onParsePostsListingSuccess(ArrayList newPosts, String lastItem) { + public void onParsePostsListingSuccess(LinkedHashSet newPosts, String lastItem) { if (newPosts.size() == 0 && lastItem != null && !lastItem.equals("") && !lastItem.equals("null")) { loadMultiRedditPostsAfter(params, callback, lastItem); } else { - callback.onResult(newPosts, lastItem); + int currentPostsSize = postLinkedHashSet.size(); + postLinkedHashSet.addAll(newPosts); + if (currentPostsSize == postLinkedHashSet.size()) { + callback.onResult(new ArrayList<>(), lastItem); + } else { + List newPostsList = new ArrayList<>(postLinkedHashSet).subList(currentPostsSize, postLinkedHashSet.size()); + callback.onResult(newPostsList, lastItem); + } paginationNetworkStateLiveData.postValue(NetworkState.LOADED); } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Post/SubmitPost.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Post/SubmitPost.java new file mode 100644 index 00000000..e7479e36 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Post/SubmitPost.java @@ -0,0 +1,464 @@ +package ml.docilealligator.infinityforreddit.Post; + +import android.graphics.Bitmap; +import android.os.AsyncTask; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlPullParserFactory; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.StringReader; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import ml.docilealligator.infinityforreddit.RedditAPI; +import ml.docilealligator.infinityforreddit.Utils.JSONUtils; +import ml.docilealligator.infinityforreddit.Utils.RedditUtils; +import okhttp3.MediaType; +import okhttp3.MultipartBody; +import okhttp3.RequestBody; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; + +public class SubmitPost { + public static void submitTextOrLinkPost(Retrofit oauthRetrofit, String accessToken, + Locale locale, String subredditName, String title, String content, + String flair, boolean isSpoiler, boolean isNSFW, String kind, + SubmitPostListener submitPostListener) { + submitPost(oauthRetrofit, accessToken, locale, subredditName, title, content, + flair, isSpoiler, isNSFW, kind, null, submitPostListener); + } + + public static void submitImagePost(Retrofit oauthRetrofit, Retrofit uploadMediaRetrofit, + String accessToken, Locale locale, + String subredditName, String title, Bitmap image, String flair, + boolean isSpoiler, boolean isNSFW, SubmitPostListener submitPostListener) { + uploadImage(oauthRetrofit, uploadMediaRetrofit, accessToken, image, + new UploadImageListener() { + @Override + public void uploaded(String imageUrl) { + submitPost(oauthRetrofit, accessToken, locale, + subredditName, title, imageUrl, flair, isSpoiler, isNSFW, + RedditUtils.KIND_IMAGE, null, submitPostListener); + } + + @Override + public void uploadFailed(@Nullable String errorMessage) { + submitPostListener.submitFailed(errorMessage); + } + }); + } + + public static void submitVideoPost(Retrofit oauthRetrofit, Retrofit uploadMediaRetrofit, + Retrofit uploadVideoRetrofit, String accessToken, + Locale locale, String subredditName, String title, byte[] buffer, String mimeType, + Bitmap posterBitmap, String flair, boolean isSpoiler, boolean isNSFW, + SubmitPostListener submitPostListener) { + RedditAPI api = oauthRetrofit.create(RedditAPI.class); + + String fileType = mimeType.substring(mimeType.indexOf("/") + 1); + + Map uploadImageParams = new HashMap<>(); + uploadImageParams.put(RedditUtils.FILEPATH_KEY, "post_video." + fileType); + uploadImageParams.put(RedditUtils.MIMETYPE_KEY, mimeType); + + Call uploadImageCall = api.uploadImage(RedditUtils.getOAuthHeader(accessToken), uploadImageParams); + uploadImageCall.enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if (response.isSuccessful()) { + new ParseJSONResponseFromAWSAsyncTask(response.body(), new ParseJSONResponseFromAWSAsyncTask.ParseJSONResponseFromAWSListener() { + @Override + public void parseSuccessful(Map nameValuePairsMap) { + RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), buffer); + MultipartBody.Part fileToUpload = MultipartBody.Part.createFormData("file", "post_video." + fileType, fileBody); + + RedditAPI uploadVideoToAWSApi; + if (fileType.equals("gif")) { + uploadVideoToAWSApi = uploadMediaRetrofit.create(RedditAPI.class); + } else { + uploadVideoToAWSApi = uploadVideoRetrofit.create(RedditAPI.class); + } + Call uploadMediaToAWS = uploadVideoToAWSApi.uploadMediaToAWS(nameValuePairsMap, fileToUpload); + + uploadMediaToAWS.enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if (response.isSuccessful()) { + new ParseXMLReponseFromAWSAsyncTask(response.body(), new ParseXMLReponseFromAWSAsyncTask.ParseXMLResponseFromAWSListener() { + @Override + public void parseSuccessful(String url) { + uploadImage(oauthRetrofit, uploadMediaRetrofit, accessToken, + posterBitmap, new UploadImageListener() { + @Override + public void uploaded(String imageUrl) { + if (fileType.equals("gif")) { + submitPost(oauthRetrofit, accessToken, locale, + subredditName, title, url, flair, isSpoiler, isNSFW, + RedditUtils.KIND_VIDEOGIF, imageUrl, submitPostListener); + } else { + submitPost(oauthRetrofit, accessToken, locale, + subredditName, title, url, flair, isSpoiler, isNSFW, + RedditUtils.KIND_VIDEO, imageUrl, submitPostListener); + } + } + + @Override + public void uploadFailed(@Nullable String errorMessage) { + submitPostListener.submitFailed(errorMessage); + } + }); + } + + @Override + public void parseFailed() { + submitPostListener.submitFailed(null); + } + }).execute(); + } else { + submitPostListener.submitFailed(response.message()); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + submitPostListener.submitFailed(t.getMessage()); + } + }); + } + + @Override + public void parseFailed() { + submitPostListener.submitFailed(null); + } + }).execute(); + } else { + submitPostListener.submitFailed(response.message()); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + submitPostListener.submitFailed(t.getMessage()); + } + }); + } + + private static void submitPost(Retrofit oauthRetrofit, String accessToken, + Locale locale, String subredditName, String title, String content, + String flair, boolean isSpoiler, boolean isNSFW, String kind, + @Nullable String posterUrl, SubmitPostListener submitPostListener) { + RedditAPI api = oauthRetrofit.create(RedditAPI.class); + + Map params = new HashMap<>(); + params.put(RedditUtils.API_TYPE_KEY, RedditUtils.API_TYPE_JSON); + params.put(RedditUtils.SR_KEY, subredditName); + params.put(RedditUtils.TITLE_KEY, title); + params.put(RedditUtils.KIND_KEY, kind); + switch (kind) { + case RedditUtils.KIND_SELF: + params.put(RedditUtils.TEXT_KEY, content); + break; + case RedditUtils.KIND_LINK: + case RedditUtils.KIND_IMAGE: + params.put(RedditUtils.URL_KEY, content); + break; + case RedditUtils.KIND_VIDEOGIF: + params.put(RedditUtils.KIND_KEY, RedditUtils.KIND_IMAGE); + params.put(RedditUtils.URL_KEY, content); + params.put(RedditUtils.VIDEO_POSTER_URL_KEY, posterUrl); + break; + case RedditUtils.KIND_VIDEO: + params.put(RedditUtils.URL_KEY, content); + params.put(RedditUtils.VIDEO_POSTER_URL_KEY, posterUrl); + break; + } + + if (flair != null) { + params.put(RedditUtils.FLAIR_TEXT_KEY, flair); + } + params.put(RedditUtils.SPOILER_KEY, Boolean.toString(isSpoiler)); + params.put(RedditUtils.NSFW_KEY, Boolean.toString(isNSFW)); + + Call submitPostCall = api.submit(RedditUtils.getOAuthHeader(accessToken), params); + submitPostCall.enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull retrofit2.Response response) { + if (response.isSuccessful()) { + try { + getSubmittedPost(response.body(), kind, oauthRetrofit, accessToken, + locale, submitPostListener); + } catch (JSONException e) { + e.printStackTrace(); + submitPostListener.submitFailed(null); + } + } else { + submitPostListener.submitFailed(response.message()); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + submitPostListener.submitFailed(t.getMessage()); + } + }); + } + + private static void uploadImage(Retrofit oauthRetrofit, Retrofit uploadMediaRetrofit, + String accessToken, Bitmap image, + UploadImageListener uploadImageListener) { + RedditAPI api = oauthRetrofit.create(RedditAPI.class); + + Map uploadImageParams = new HashMap<>(); + uploadImageParams.put(RedditUtils.FILEPATH_KEY, "post_image.jpg"); + uploadImageParams.put(RedditUtils.MIMETYPE_KEY, "image/jpeg"); + + Call uploadImageCall = api.uploadImage(RedditUtils.getOAuthHeader(accessToken), uploadImageParams); + uploadImageCall.enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if (response.isSuccessful()) { + new ParseJSONResponseFromAWSAsyncTask(response.body(), new ParseJSONResponseFromAWSAsyncTask.ParseJSONResponseFromAWSListener() { + @Override + public void parseSuccessful(Map nameValuePairsMap) { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + image.compress(Bitmap.CompressFormat.JPEG, 100, stream); + byte[] byteArray = stream.toByteArray(); + + RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), byteArray); + MultipartBody.Part fileToUpload = MultipartBody.Part.createFormData("file", "post_image.jpg", fileBody); + + RedditAPI uploadMediaToAWSApi = uploadMediaRetrofit.create(RedditAPI.class); + Call uploadMediaToAWS = uploadMediaToAWSApi.uploadMediaToAWS(nameValuePairsMap, fileToUpload); + + uploadMediaToAWS.enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if (response.isSuccessful()) { + new ParseXMLReponseFromAWSAsyncTask(response.body(), new ParseXMLReponseFromAWSAsyncTask.ParseXMLResponseFromAWSListener() { + @Override + public void parseSuccessful(String url) { + uploadImageListener.uploaded(url); + } + + @Override + public void parseFailed() { + uploadImageListener.uploadFailed(null); + } + }).execute(); + } else { + uploadImageListener.uploadFailed("Error: " + response.code()); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + uploadImageListener.uploadFailed(t.getMessage()); + } + }); + } + + @Override + public void parseFailed() { + uploadImageListener.uploadFailed(null); + } + }).execute(); + } else { + uploadImageListener.uploadFailed(response.message()); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + uploadImageListener.uploadFailed(t.getMessage()); + } + }); + } + + private static void getSubmittedPost(String response, String kind, Retrofit oauthRetrofit, + String accessToken, Locale locale, + SubmitPostListener submitPostListener) throws JSONException { + JSONObject responseObject = new JSONObject(response).getJSONObject(JSONUtils.JSON_KEY); + if (responseObject.getJSONArray(JSONUtils.ERRORS_KEY).length() != 0) { + JSONArray error = responseObject.getJSONArray(JSONUtils.ERRORS_KEY) + .getJSONArray(responseObject.getJSONArray(JSONUtils.ERRORS_KEY).length() - 1); + if (error.length() != 0) { + String errorString; + if (error.length() >= 2) { + errorString = error.getString(1); + } else { + errorString = error.getString(0); + } + submitPostListener.submitFailed(errorString); + } else { + submitPostListener.submitFailed(null); + } + + return; + } + + if (!kind.equals(RedditUtils.KIND_IMAGE) && !kind.equals(RedditUtils.KIND_VIDEO) && !kind.equals(RedditUtils.KIND_VIDEOGIF)) { + String postId = responseObject.getJSONObject(JSONUtils.DATA_KEY).getString(JSONUtils.ID_KEY); + + RedditAPI api = oauthRetrofit.create(RedditAPI.class); + + Call getPostCall = api.getPostOauth(postId, RedditUtils.getOAuthHeader(accessToken)); + getPostCall.enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull retrofit2.Response response) { + if (response.isSuccessful()) { + ParsePost.parsePost(response.body(), locale, new ParsePost.ParsePostListener() { + @Override + public void onParsePostSuccess(Post post) { + submitPostListener.submitSuccessful(post); + } + + @Override + public void onParsePostFail() { + submitPostListener.submitFailed(null); + } + }); + } else { + submitPostListener.submitFailed(response.message()); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + submitPostListener.submitFailed(t.getMessage()); + } + }); + } else { + submitPostListener.submitSuccessful(null); + } + } + + public interface SubmitPostListener { + void submitSuccessful(Post post); + + void submitFailed(@Nullable String errorMessage); + } + + private interface UploadImageListener { + void uploaded(String imageUrl); + + void uploadFailed(@Nullable String errorMessage); + } + + private static class ParseJSONResponseFromAWSAsyncTask extends AsyncTask { + private String response; + private ParseJSONResponseFromAWSListener parseJSONResponseFromAWSListener; + private Map nameValuePairsMap; + private boolean successful; + ParseJSONResponseFromAWSAsyncTask(String response, ParseJSONResponseFromAWSListener parseJSONResponseFromAWSListener) { + this.response = response; + this.parseJSONResponseFromAWSListener = parseJSONResponseFromAWSListener; + nameValuePairsMap = new HashMap<>(); + successful = false; + } + + @Override + protected Void doInBackground(Void... voids) { + try { + JSONObject responseObject = new JSONObject(response); + JSONArray nameValuePairs = responseObject.getJSONObject(JSONUtils.ARGS_KEY).getJSONArray(JSONUtils.FIELDS_KEY); + + nameValuePairsMap = new HashMap<>(); + for (int i = 0; i < nameValuePairs.length(); i++) { + nameValuePairsMap.put(nameValuePairs.getJSONObject(i).getString(JSONUtils.NAME_KEY), + RedditUtils.getRequestBody(nameValuePairs.getJSONObject(i).getString(JSONUtils.VALUE_KEY))); + } + + successful = true; + } catch (JSONException e) { + e.printStackTrace(); + successful = false; + } + + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + if (successful) { + parseJSONResponseFromAWSListener.parseSuccessful(nameValuePairsMap); + } else { + parseJSONResponseFromAWSListener.parseFailed(); + } + } + + interface ParseJSONResponseFromAWSListener { + void parseSuccessful(Map nameValuePairsMap); + + void parseFailed(); + } + } + + private static class ParseXMLReponseFromAWSAsyncTask extends AsyncTask { + private String response; + private ParseXMLResponseFromAWSListener parseXMLResponseFromAWSListener; + private String imageUrl; + private boolean successful; + ParseXMLReponseFromAWSAsyncTask(String response, ParseXMLResponseFromAWSListener parseXMLResponseFromAWSListener) { + this.response = response; + this.parseXMLResponseFromAWSListener = parseXMLResponseFromAWSListener; + successful = false; + } + + @Override + protected Void doInBackground(Void... voids) { + try { + XmlPullParser xmlPullParser = XmlPullParserFactory.newInstance().newPullParser(); + xmlPullParser.setInput(new StringReader(response)); + + boolean isLocationTag = false; + int eventType = xmlPullParser.getEventType(); + while (eventType != XmlPullParser.END_DOCUMENT) { + if (eventType == XmlPullParser.START_TAG) { + if (xmlPullParser.getName().equals("Location")) { + isLocationTag = true; + } + } else if (eventType == XmlPullParser.TEXT) { + if (isLocationTag) { + imageUrl = xmlPullParser.getText(); + successful = true; + return null; + } + } + eventType = xmlPullParser.next(); + } + } catch (XmlPullParserException | IOException e) { + e.printStackTrace(); + successful = false; + } + + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + if (successful) { + parseXMLResponseFromAWSListener.parseSuccessful(imageUrl); + } else { + parseXMLResponseFromAWSListener.parseFailed(); + } + } + + interface ParseXMLResponseFromAWSListener { + void parseSuccessful(String url); + + void parseFailed(); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Service/SubmitPostService.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Service/SubmitPostService.java index cfce40c8..cedf9730 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Service/SubmitPostService.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Service/SubmitPostService.java @@ -39,7 +39,7 @@ import ml.docilealligator.infinityforreddit.Infinity; import ml.docilealligator.infinityforreddit.NotificationUtils; import ml.docilealligator.infinityforreddit.Post.Post; import ml.docilealligator.infinityforreddit.R; -import ml.docilealligator.infinityforreddit.SubmitPost; +import ml.docilealligator.infinityforreddit.Post.SubmitPost; import retrofit2.Retrofit; public class SubmitPostService extends Service { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SubmitPost.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SubmitPost.java deleted file mode 100644 index 6a93edf1..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SubmitPost.java +++ /dev/null @@ -1,464 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.graphics.Bitmap; -import android.os.AsyncTask; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlPullParserFactory; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.StringReader; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -import ml.docilealligator.infinityforreddit.Post.Post; -import ml.docilealligator.infinityforreddit.Utils.JSONUtils; -import ml.docilealligator.infinityforreddit.Utils.RedditUtils; -import okhttp3.MediaType; -import okhttp3.MultipartBody; -import okhttp3.RequestBody; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; -import retrofit2.Retrofit; - -public class SubmitPost { - public static void submitTextOrLinkPost(Retrofit oauthRetrofit, String accessToken, - Locale locale, String subredditName, String title, String content, - String flair, boolean isSpoiler, boolean isNSFW, String kind, - SubmitPostListener submitPostListener) { - submitPost(oauthRetrofit, accessToken, locale, subredditName, title, content, - flair, isSpoiler, isNSFW, kind, null, submitPostListener); - } - - public static void submitImagePost(Retrofit oauthRetrofit, Retrofit uploadMediaRetrofit, - String accessToken, Locale locale, - String subredditName, String title, Bitmap image, String flair, - boolean isSpoiler, boolean isNSFW, SubmitPostListener submitPostListener) { - uploadImage(oauthRetrofit, uploadMediaRetrofit, accessToken, image, - new UploadImageListener() { - @Override - public void uploaded(String imageUrl) { - submitPost(oauthRetrofit, accessToken, locale, - subredditName, title, imageUrl, flair, isSpoiler, isNSFW, - RedditUtils.KIND_IMAGE, null, submitPostListener); - } - - @Override - public void uploadFailed(@Nullable String errorMessage) { - submitPostListener.submitFailed(errorMessage); - } - }); - } - - public static void submitVideoPost(Retrofit oauthRetrofit, Retrofit uploadMediaRetrofit, - Retrofit uploadVideoRetrofit, String accessToken, - Locale locale, String subredditName, String title, byte[] buffer, String mimeType, - Bitmap posterBitmap, String flair, boolean isSpoiler, boolean isNSFW, - SubmitPostListener submitPostListener) { - RedditAPI api = oauthRetrofit.create(RedditAPI.class); - - String fileType = mimeType.substring(mimeType.indexOf("/") + 1); - - Map uploadImageParams = new HashMap<>(); - uploadImageParams.put(RedditUtils.FILEPATH_KEY, "post_video." + fileType); - uploadImageParams.put(RedditUtils.MIMETYPE_KEY, mimeType); - - Call uploadImageCall = api.uploadImage(RedditUtils.getOAuthHeader(accessToken), uploadImageParams); - uploadImageCall.enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - if (response.isSuccessful()) { - new ParseJSONResponseFromAWSAsyncTask(response.body(), new ParseJSONResponseFromAWSAsyncTask.ParseJSONResponseFromAWSListener() { - @Override - public void parseSuccessful(Map nameValuePairsMap) { - RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), buffer); - MultipartBody.Part fileToUpload = MultipartBody.Part.createFormData("file", "post_video." + fileType, fileBody); - - RedditAPI uploadVideoToAWSApi; - if (fileType.equals("gif")) { - uploadVideoToAWSApi = uploadMediaRetrofit.create(RedditAPI.class); - } else { - uploadVideoToAWSApi = uploadVideoRetrofit.create(RedditAPI.class); - } - Call uploadMediaToAWS = uploadVideoToAWSApi.uploadMediaToAWS(nameValuePairsMap, fileToUpload); - - uploadMediaToAWS.enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - if (response.isSuccessful()) { - new ParseXMLReponseFromAWSAsyncTask(response.body(), new ParseXMLReponseFromAWSAsyncTask.ParseXMLResponseFromAWSListener() { - @Override - public void parseSuccessful(String url) { - uploadImage(oauthRetrofit, uploadMediaRetrofit, accessToken, - posterBitmap, new UploadImageListener() { - @Override - public void uploaded(String imageUrl) { - if (fileType.equals("gif")) { - submitPost(oauthRetrofit, accessToken, locale, - subredditName, title, url, flair, isSpoiler, isNSFW, - RedditUtils.KIND_VIDEOGIF, imageUrl, submitPostListener); - } else { - submitPost(oauthRetrofit, accessToken, locale, - subredditName, title, url, flair, isSpoiler, isNSFW, - RedditUtils.KIND_VIDEO, imageUrl, submitPostListener); - } - } - - @Override - public void uploadFailed(@Nullable String errorMessage) { - submitPostListener.submitFailed(errorMessage); - } - }); - } - - @Override - public void parseFailed() { - submitPostListener.submitFailed(null); - } - }).execute(); - } else { - submitPostListener.submitFailed(response.message()); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - submitPostListener.submitFailed(t.getMessage()); - } - }); - } - - @Override - public void parseFailed() { - submitPostListener.submitFailed(null); - } - }).execute(); - } else { - submitPostListener.submitFailed(response.message()); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - submitPostListener.submitFailed(t.getMessage()); - } - }); - } - - private static void submitPost(Retrofit oauthRetrofit, String accessToken, - Locale locale, String subredditName, String title, String content, - String flair, boolean isSpoiler, boolean isNSFW, String kind, - @Nullable String posterUrl, SubmitPostListener submitPostListener) { - RedditAPI api = oauthRetrofit.create(RedditAPI.class); - - Map params = new HashMap<>(); - params.put(RedditUtils.API_TYPE_KEY, RedditUtils.API_TYPE_JSON); - params.put(RedditUtils.SR_KEY, subredditName); - params.put(RedditUtils.TITLE_KEY, title); - params.put(RedditUtils.KIND_KEY, kind); - switch (kind) { - case RedditUtils.KIND_SELF: - params.put(RedditUtils.TEXT_KEY, content); - break; - case RedditUtils.KIND_LINK: - case RedditUtils.KIND_IMAGE: - params.put(RedditUtils.URL_KEY, content); - break; - case RedditUtils.KIND_VIDEOGIF: - params.put(RedditUtils.KIND_KEY, RedditUtils.KIND_IMAGE); - params.put(RedditUtils.URL_KEY, content); - params.put(RedditUtils.VIDEO_POSTER_URL_KEY, posterUrl); - break; - case RedditUtils.KIND_VIDEO: - params.put(RedditUtils.URL_KEY, content); - params.put(RedditUtils.VIDEO_POSTER_URL_KEY, posterUrl); - break; - } - - if (flair != null) { - params.put(RedditUtils.FLAIR_TEXT_KEY, flair); - } - params.put(RedditUtils.SPOILER_KEY, Boolean.toString(isSpoiler)); - params.put(RedditUtils.NSFW_KEY, Boolean.toString(isNSFW)); - - Call submitPostCall = api.submit(RedditUtils.getOAuthHeader(accessToken), params); - submitPostCall.enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull retrofit2.Response response) { - if (response.isSuccessful()) { - try { - getSubmittedPost(response.body(), kind, oauthRetrofit, accessToken, - locale, submitPostListener); - } catch (JSONException e) { - e.printStackTrace(); - submitPostListener.submitFailed(null); - } - } else { - submitPostListener.submitFailed(response.message()); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - submitPostListener.submitFailed(t.getMessage()); - } - }); - } - - private static void uploadImage(Retrofit oauthRetrofit, Retrofit uploadMediaRetrofit, - String accessToken, Bitmap image, - UploadImageListener uploadImageListener) { - RedditAPI api = oauthRetrofit.create(RedditAPI.class); - - Map uploadImageParams = new HashMap<>(); - uploadImageParams.put(RedditUtils.FILEPATH_KEY, "post_image.jpg"); - uploadImageParams.put(RedditUtils.MIMETYPE_KEY, "image/jpeg"); - - Call uploadImageCall = api.uploadImage(RedditUtils.getOAuthHeader(accessToken), uploadImageParams); - uploadImageCall.enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - if (response.isSuccessful()) { - new ParseJSONResponseFromAWSAsyncTask(response.body(), new ParseJSONResponseFromAWSAsyncTask.ParseJSONResponseFromAWSListener() { - @Override - public void parseSuccessful(Map nameValuePairsMap) { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - image.compress(Bitmap.CompressFormat.JPEG, 100, stream); - byte[] byteArray = stream.toByteArray(); - - RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), byteArray); - MultipartBody.Part fileToUpload = MultipartBody.Part.createFormData("file", "post_image.jpg", fileBody); - - RedditAPI uploadMediaToAWSApi = uploadMediaRetrofit.create(RedditAPI.class); - Call uploadMediaToAWS = uploadMediaToAWSApi.uploadMediaToAWS(nameValuePairsMap, fileToUpload); - - uploadMediaToAWS.enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - if (response.isSuccessful()) { - new ParseXMLReponseFromAWSAsyncTask(response.body(), new ParseXMLReponseFromAWSAsyncTask.ParseXMLResponseFromAWSListener() { - @Override - public void parseSuccessful(String url) { - uploadImageListener.uploaded(url); - } - - @Override - public void parseFailed() { - uploadImageListener.uploadFailed(null); - } - }).execute(); - } else { - uploadImageListener.uploadFailed("Error: " + response.code()); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - uploadImageListener.uploadFailed(t.getMessage()); - } - }); - } - - @Override - public void parseFailed() { - uploadImageListener.uploadFailed(null); - } - }).execute(); - } else { - uploadImageListener.uploadFailed(response.message()); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - uploadImageListener.uploadFailed(t.getMessage()); - } - }); - } - - private static void getSubmittedPost(String response, String kind, Retrofit oauthRetrofit, - String accessToken, Locale locale, - SubmitPostListener submitPostListener) throws JSONException { - JSONObject responseObject = new JSONObject(response).getJSONObject(JSONUtils.JSON_KEY); - if (responseObject.getJSONArray(JSONUtils.ERRORS_KEY).length() != 0) { - JSONArray error = responseObject.getJSONArray(JSONUtils.ERRORS_KEY) - .getJSONArray(responseObject.getJSONArray(JSONUtils.ERRORS_KEY).length() - 1); - if (error.length() != 0) { - String errorString; - if (error.length() >= 2) { - errorString = error.getString(1); - } else { - errorString = error.getString(0); - } - submitPostListener.submitFailed(errorString); - } else { - submitPostListener.submitFailed(null); - } - - return; - } - - if (!kind.equals(RedditUtils.KIND_IMAGE) && !kind.equals(RedditUtils.KIND_VIDEO) && !kind.equals(RedditUtils.KIND_VIDEOGIF)) { - String postId = responseObject.getJSONObject(JSONUtils.DATA_KEY).getString(JSONUtils.ID_KEY); - - RedditAPI api = oauthRetrofit.create(RedditAPI.class); - - Call getPostCall = api.getPostOauth(postId, RedditUtils.getOAuthHeader(accessToken)); - getPostCall.enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull retrofit2.Response response) { - if (response.isSuccessful()) { - ParsePost.parsePost(response.body(), locale, new ParsePost.ParsePostListener() { - @Override - public void onParsePostSuccess(Post post) { - submitPostListener.submitSuccessful(post); - } - - @Override - public void onParsePostFail() { - submitPostListener.submitFailed(null); - } - }); - } else { - submitPostListener.submitFailed(response.message()); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - submitPostListener.submitFailed(t.getMessage()); - } - }); - } else { - submitPostListener.submitSuccessful(null); - } - } - - public interface SubmitPostListener { - void submitSuccessful(Post post); - - void submitFailed(@Nullable String errorMessage); - } - - private interface UploadImageListener { - void uploaded(String imageUrl); - - void uploadFailed(@Nullable String errorMessage); - } - - private static class ParseJSONResponseFromAWSAsyncTask extends AsyncTask { - private String response; - private ParseJSONResponseFromAWSListener parseJSONResponseFromAWSListener; - private Map nameValuePairsMap; - private boolean successful; - ParseJSONResponseFromAWSAsyncTask(String response, ParseJSONResponseFromAWSListener parseJSONResponseFromAWSListener) { - this.response = response; - this.parseJSONResponseFromAWSListener = parseJSONResponseFromAWSListener; - nameValuePairsMap = new HashMap<>(); - successful = false; - } - - @Override - protected Void doInBackground(Void... voids) { - try { - JSONObject responseObject = new JSONObject(response); - JSONArray nameValuePairs = responseObject.getJSONObject(JSONUtils.ARGS_KEY).getJSONArray(JSONUtils.FIELDS_KEY); - - nameValuePairsMap = new HashMap<>(); - for (int i = 0; i < nameValuePairs.length(); i++) { - nameValuePairsMap.put(nameValuePairs.getJSONObject(i).getString(JSONUtils.NAME_KEY), - RedditUtils.getRequestBody(nameValuePairs.getJSONObject(i).getString(JSONUtils.VALUE_KEY))); - } - - successful = true; - } catch (JSONException e) { - e.printStackTrace(); - successful = false; - } - - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - if (successful) { - parseJSONResponseFromAWSListener.parseSuccessful(nameValuePairsMap); - } else { - parseJSONResponseFromAWSListener.parseFailed(); - } - } - - interface ParseJSONResponseFromAWSListener { - void parseSuccessful(Map nameValuePairsMap); - - void parseFailed(); - } - } - - private static class ParseXMLReponseFromAWSAsyncTask extends AsyncTask { - private String response; - private ParseXMLResponseFromAWSListener parseXMLResponseFromAWSListener; - private String imageUrl; - private boolean successful; - ParseXMLReponseFromAWSAsyncTask(String response, ParseXMLResponseFromAWSListener parseXMLResponseFromAWSListener) { - this.response = response; - this.parseXMLResponseFromAWSListener = parseXMLResponseFromAWSListener; - successful = false; - } - - @Override - protected Void doInBackground(Void... voids) { - try { - XmlPullParser xmlPullParser = XmlPullParserFactory.newInstance().newPullParser(); - xmlPullParser.setInput(new StringReader(response)); - - boolean isLocationTag = false; - int eventType = xmlPullParser.getEventType(); - while (eventType != XmlPullParser.END_DOCUMENT) { - if (eventType == XmlPullParser.START_TAG) { - if (xmlPullParser.getName().equals("Location")) { - isLocationTag = true; - } - } else if (eventType == XmlPullParser.TEXT) { - if (isLocationTag) { - imageUrl = xmlPullParser.getText(); - successful = true; - return null; - } - } - eventType = xmlPullParser.next(); - } - } catch (XmlPullParserException | IOException e) { - e.printStackTrace(); - successful = false; - } - - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - if (successful) { - parseXMLResponseFromAWSListener.parseSuccessful(imageUrl); - } else { - parseXMLResponseFromAWSListener.parseFailed(); - } - } - - interface ParseXMLResponseFromAWSListener { - void parseSuccessful(String url); - - void parseFailed(); - } - } -} -- cgit v1.2.3 From 25328e5d18455a5817b39702a7cb389f29037380 Mon Sep 17 00:00:00 2001 From: Alex Ning Date: Fri, 1 May 2020 10:50:40 +0800 Subject: Muting and unmuting audio when autoplaying are available. --- .../Adapter/PostRecyclerViewAdapter.java | 69 +++++++++++++++++++--- .../infinityforreddit/Fragment/PostFragment.java | 11 ++++ .../infinityforreddit/Post/Post.java | 2 +- .../infinityforreddit/Post/PostDataSource.java | 1 - .../layout/exo_autoplay_playback_control_view.xml | 4 +- 5 files changed, 76 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java index 88175912..0e8bd1da 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java @@ -13,6 +13,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.FrameLayout; +import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.RelativeLayout; @@ -37,6 +38,10 @@ 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.exoplayer2.metadata.Metadata; +import com.google.android.exoplayer2.source.TrackGroupArray; +import com.google.android.exoplayer2.text.Cue; +import com.google.android.exoplayer2.trackselection.TrackSelectionArray; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; import com.google.android.exoplayer2.ui.PlayerView; import com.google.android.material.card.MaterialCardView; @@ -44,6 +49,8 @@ import com.libRG.CustomTextView; import org.greenrobot.eventbus.EventBus; +import java.util.List; + import butterknife.BindView; import butterknife.ButterKnife; import im.ene.toro.CacheManager; @@ -51,6 +58,7 @@ import im.ene.toro.ToroPlayer; import im.ene.toro.ToroUtil; import im.ene.toro.exoplayer.ExoCreator; import im.ene.toro.exoplayer.ExoPlayerViewHelper; +import im.ene.toro.exoplayer.Playable; import im.ene.toro.media.PlaybackInfo; import im.ene.toro.widget.Container; import jp.wasabeef.glide.transformations.BlurTransformation; @@ -1301,7 +1309,10 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { - //Do nothing in order to prevent clicking this to start ViewPostDetailActivity - }); + scoreTextView.setOnClickListener(null); if (mVoteButtonsOnTheRight) { ConstraintSet constraintSet = new ConstraintSet(); @@ -1520,10 +1529,13 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { if (canStartActivity) { - canStartActivity = false; - Intent intent = new Intent(mActivity, ViewUserDetailActivity.class); - intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, getItem(getAdapterPosition()).getAuthor()); - mActivity.startActivity(intent); + Post post = getItem(getAdapterPosition()); + if (post != null) { + canStartActivity = false; + Intent intent = new Intent(mActivity, ViewUserDetailActivity.class); + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, post.getAuthor()); + mActivity.startActivity(intent); + } } }); @@ -1835,6 +1847,8 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { + if (helper != null) { + if (helper.getVolume() != 0) { + muteButton.setImageDrawable(mActivity.getDrawable(R.drawable.ic_mute_24dp)); + helper.setVolume(0f); + } else { + muteButton.setImageDrawable(mActivity.getDrawable(R.drawable.ic_unmute_24dp)); + helper.setVolume(1f); + } + } + }); } void bindVideoUri(Uri videoUri) { @@ -1903,6 +1929,33 @@ public class PostRecyclerViewAdapter extends PagedListAdapter cues) { + + } + }); } helper.initialize(container, playbackInfo); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostFragment.java index 5b76d340..9d058e3b 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostFragment.java @@ -47,6 +47,9 @@ import javax.inject.Named; import butterknife.BindView; import butterknife.ButterKnife; import im.ene.toro.exoplayer.ExoCreator; +import im.ene.toro.media.PlaybackInfo; +import im.ene.toro.media.VolumeInfo; +import im.ene.toro.widget.Container; import ml.docilealligator.infinityforreddit.Activity.BaseActivity; import ml.docilealligator.infinityforreddit.Activity.FilteredThingActivity; import ml.docilealligator.infinityforreddit.Activity.MainActivity; @@ -78,6 +81,9 @@ import ml.docilealligator.infinityforreddit.Utils.SharedPreferencesUtils; import ml.docilealligator.infinityforreddit.Utils.Utils; import retrofit2.Retrofit; +import static im.ene.toro.media.PlaybackInfo.INDEX_UNSET; +import static im.ene.toro.media.PlaybackInfo.TIME_UNSET; + /** * A simple {@link Fragment} subclass. @@ -564,6 +570,11 @@ public class PostFragment extends Fragment implements FragmentCommunicator { mPostRecyclerView.setAdapter(mAdapter); mPostRecyclerView.setCacheManager(mAdapter); + mPostRecyclerView.setPlayerInitializer(order -> { + VolumeInfo volumeInfo = new VolumeInfo(true, 0f); + return new PlaybackInfo(INDEX_UNSET, TIME_UNSET, volumeInfo); + }); + mPostViewModel.getPosts().observe(this, posts -> mAdapter.submitList(posts)); mPostViewModel.hasPost().observe(this, hasPost -> { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Post/Post.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Post/Post.java index eccc4388..b5aa1f1c 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Post/Post.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Post/Post.java @@ -514,6 +514,6 @@ public class Post implements Parcelable { if (!(obj instanceof Post)) { return false; } - return ((Post) obj).getFullName().equals(fullName); + return ((Post) obj).id.equals(id); } } \ No newline at end of file diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Post/PostDataSource.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Post/PostDataSource.java index e8e865b1..b26eef79 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Post/PostDataSource.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Post/PostDataSource.java @@ -248,7 +248,6 @@ public class PostDataSource extends PageKeyedDataSource { nextPageKey = lastItem; } - int currentPostsSize = postLinkedHashSet.size(); if (newPosts.size() != 0) { postLinkedHashSet.addAll(newPosts); callback.onResult(new ArrayList<>(newPosts), null, nextPageKey); diff --git a/app/src/main/res/layout/exo_autoplay_playback_control_view.xml b/app/src/main/res/layout/exo_autoplay_playback_control_view.xml index 1adc685e..b12deafe 100644 --- a/app/src/main/res/layout/exo_autoplay_playback_control_view.xml +++ b/app/src/main/res/layout/exo_autoplay_playback_control_view.xml @@ -26,7 +26,9 @@ + android:src="@drawable/ic_mute_24dp" + android:layout_alignParentEnd="true" + android:visibility="gone" /> -- cgit v1.2.3 From a88f43ff38bd441b945110cf3f2f8c5a7883458b Mon Sep 17 00:00:00 2001 From: Alex Ning Date: Fri, 1 May 2020 19:22:18 +0800 Subject: Fix muting audio after video play ends. --- .../infinityforreddit/Adapter/PostRecyclerViewAdapter.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java index 0e8bd1da..26a2522c 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java @@ -1867,6 +1867,7 @@ public class PostRecyclerViewAdapter extends PagedListAdapter Date: Fri, 1 May 2020 22:07:13 +0800 Subject: Beautify player control view for video autoplay. --- .../Adapter/PostRecyclerViewAdapter.java | 10 +- .../res/drawable/ic_mute_white_rounded_18dp.xml | 9 ++ .../res/drawable/ic_pause_white_rounded_18dp.xml | 9 ++ .../drawable/ic_play_arrow_white_rounded_18dp.xml | 9 ++ .../res/drawable/ic_unmute_white_rounded_18dp.xml | 9 ++ .../layout/exo_autoplay_playback_control_view.xml | 108 ++++++++++----------- 6 files changed, 92 insertions(+), 62 deletions(-) create mode 100644 app/src/main/res/drawable/ic_mute_white_rounded_18dp.xml create mode 100644 app/src/main/res/drawable/ic_pause_white_rounded_18dp.xml create mode 100644 app/src/main/res/drawable/ic_play_arrow_white_rounded_18dp.xml create mode 100644 app/src/main/res/drawable/ic_unmute_white_rounded_18dp.xml diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java index 26a2522c..c474a710 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java @@ -1848,7 +1848,7 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { if (helper != null) { if (helper.getVolume() != 0) { - muteButton.setImageDrawable(mActivity.getDrawable(R.drawable.ic_mute_24dp)); + muteButton.setImageDrawable(mActivity.getDrawable(R.drawable.ic_mute_white_rounded_18dp)); helper.setVolume(0f); volume = 0f; } else { - muteButton.setImageDrawable(mActivity.getDrawable(R.drawable.ic_unmute_24dp)); + muteButton.setImageDrawable(mActivity.getDrawable(R.drawable.ic_unmute_white_rounded_18dp)); helper.setVolume(1f); volume = 1f; } @@ -1942,9 +1942,9 @@ public class PostRecyclerViewAdapter extends PagedListAdapter + + diff --git a/app/src/main/res/drawable/ic_pause_white_rounded_18dp.xml b/app/src/main/res/drawable/ic_pause_white_rounded_18dp.xml new file mode 100644 index 00000000..479c57b0 --- /dev/null +++ b/app/src/main/res/drawable/ic_pause_white_rounded_18dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_play_arrow_white_rounded_18dp.xml b/app/src/main/res/drawable/ic_play_arrow_white_rounded_18dp.xml new file mode 100644 index 00000000..3400b3ac --- /dev/null +++ b/app/src/main/res/drawable/ic_play_arrow_white_rounded_18dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_unmute_white_rounded_18dp.xml b/app/src/main/res/drawable/ic_unmute_white_rounded_18dp.xml new file mode 100644 index 00000000..90b8f85d --- /dev/null +++ b/app/src/main/res/drawable/ic_unmute_white_rounded_18dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/exo_autoplay_playback_control_view.xml b/app/src/main/res/layout/exo_autoplay_playback_control_view.xml index b12deafe..826f6870 100644 --- a/app/src/main/res/layout/exo_autoplay_playback_control_view.xml +++ b/app/src/main/res/layout/exo_autoplay_playback_control_view.xml @@ -1,70 +1,64 @@ - + android:paddingStart="8dp" + android:paddingEnd="8dp" + android:layout_gravity="bottom"> - + android:layout_alignParentStart="true" + android:layout_centerVertical="true" + android:includeFontPadding="false" + android:textColor="#FFFFFF" + android:textSize="12sp" + android:textStyle="bold" /> - - - - - - - - - + android:layout_toEndOf="@id/exo_position" + android:layout_centerVertical="true" + android:text="/" + android:textColor="#FFFFFF" + android:textSize="12sp" + android:textStyle="bold" /> - + - + - + - + - \ No newline at end of file + \ No newline at end of file -- cgit v1.2.3 From 360051a302ce2f3e917f42f431727ce43a7cb528 Mon Sep 17 00:00:00 2001 From: Alex Ning Date: Sat, 2 May 2020 08:22:13 +0800 Subject: Fix the color of award cannot be changed. Prepare to show user comment karma, description, cakeday and subreddit creation day. --- .../infinityforreddit/Activity/MainActivity.java | 10 +- .../Activity/ThemePreviewActivity.java | 10 +- .../Activity/ViewSubredditDetailActivity.java | 10 +- .../infinityforreddit/CustomTheme/CustomTheme.java | 105 +++++++++++---------- .../CustomTheme/CustomThemeSettingsItem.java | 4 + .../CustomTheme/CustomThemeWrapper.java | 16 ++++ .../infinityforreddit/ParseSubredditData.java | 3 +- .../infinityforreddit/ParseSubscribedThing.java | 3 +- .../infinityforreddit/ParseUserData.java | 6 +- .../infinityforreddit/RedditDataRoomDatabase.java | 25 ++++- .../SubredditDatabase/SubredditData.java | 9 +- .../infinityforreddit/User/UserData.java | 36 ++++++- .../Utils/CustomThemeSharedPreferencesUtils.java | 4 + app/src/main/res/values/strings.xml | 4 +- 14 files changed, 166 insertions(+), 79 deletions(-) diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/MainActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/MainActivity.java index 434eaa87..ca7e42d2 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/MainActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/MainActivity.java @@ -302,11 +302,11 @@ public class MainActivity extends BaseActivity implements SortTypeSelectionCallb int backgroundColor = mCustomThemeWrapper.getBackgroundColor(); drawer.setBackgroundColor(backgroundColor); drawer.setStatusBarBackgroundColor(mCustomThemeWrapper.getColorPrimaryDark()); - int primaryIconColor = mCustomThemeWrapper.getPrimaryIconColor(); - subscriptionsBottomAppBar.setColorFilter(primaryIconColor, android.graphics.PorterDuff.Mode.SRC_IN); - multiRedditBottomAppBar.setColorFilter(primaryIconColor, android.graphics.PorterDuff.Mode.SRC_IN); - messageBottomAppBar.setColorFilter(primaryIconColor, android.graphics.PorterDuff.Mode.SRC_IN); - profileBottomAppBar.setColorFilter(primaryIconColor, android.graphics.PorterDuff.Mode.SRC_IN); + int bottomAppBarIconColor = mCustomThemeWrapper.getBottomAppBarIconColor(); + subscriptionsBottomAppBar.setColorFilter(bottomAppBarIconColor, android.graphics.PorterDuff.Mode.SRC_IN); + multiRedditBottomAppBar.setColorFilter(bottomAppBarIconColor, android.graphics.PorterDuff.Mode.SRC_IN); + messageBottomAppBar.setColorFilter(bottomAppBarIconColor, android.graphics.PorterDuff.Mode.SRC_IN); + profileBottomAppBar.setColorFilter(bottomAppBarIconColor, android.graphics.PorterDuff.Mode.SRC_IN); navigationView.setBackgroundColor(backgroundColor); applyAppBarLayoutAndToolbarTheme(appBarLayout, toolbar); applyTabLayoutTheme(tabLayout); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ThemePreviewActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ThemePreviewActivity.java index 83478a2f..f8275d66 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ThemePreviewActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ThemePreviewActivity.java @@ -323,11 +323,11 @@ public class ThemePreviewActivity extends AppCompatActivity { primaryTextView.setTextColor(customTheme.primaryTextColor); secondaryTextView.setTextColor(customTheme.secondaryTextColor); bottomNavigationView.setBackgroundTint(ColorStateList.valueOf(customTheme.bottomAppBarBackgroundColor)); - int primaryIconColor = customTheme.primaryIconColor; - subscriptionsBottomAppBar.setColorFilter(primaryIconColor, android.graphics.PorterDuff.Mode.SRC_IN); - multiRedditBottomAppBar.setColorFilter(primaryIconColor, android.graphics.PorterDuff.Mode.SRC_IN); - messageBottomAppBar.setColorFilter(primaryIconColor, android.graphics.PorterDuff.Mode.SRC_IN); - profileBottomAppBar.setColorFilter(primaryIconColor, android.graphics.PorterDuff.Mode.SRC_IN); + int bottomAppBarIconColor = customTheme.bottomAppBarIconColor; + subscriptionsBottomAppBar.setColorFilter(bottomAppBarIconColor, android.graphics.PorterDuff.Mode.SRC_IN); + multiRedditBottomAppBar.setColorFilter(bottomAppBarIconColor, android.graphics.PorterDuff.Mode.SRC_IN); + messageBottomAppBar.setColorFilter(bottomAppBarIconColor, android.graphics.PorterDuff.Mode.SRC_IN); + profileBottomAppBar.setColorFilter(bottomAppBarIconColor, android.graphics.PorterDuff.Mode.SRC_IN); applyTabLayoutTheme(tabLayout); applyFABTheme(fab); unsubscribedColor = customTheme.unsubscribed; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewSubredditDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewSubredditDetailActivity.java index 419a5e08..b0148cdd 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewSubredditDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewSubredditDetailActivity.java @@ -418,11 +418,11 @@ public class ViewSubredditDetailActivity extends BaseActivity implements SortTyp nOnlineSubscribersTextView.setTextColor(primaryTextColor); descriptionTextView.setTextColor(primaryTextColor); bottomNavigationView.setBackgroundTint(ColorStateList.valueOf(mCustomThemeWrapper.getBottomAppBarBackgroundColor())); - int primaryIconColor = mCustomThemeWrapper.getPrimaryIconColor(); - subscriptionsBottomAppBar.setColorFilter(primaryIconColor, android.graphics.PorterDuff.Mode.SRC_IN); - multiRedditBottomAppBar.setColorFilter(primaryIconColor, android.graphics.PorterDuff.Mode.SRC_IN); - messageBottomAppBar.setColorFilter(primaryIconColor, android.graphics.PorterDuff.Mode.SRC_IN); - profileBottomAppBar.setColorFilter(primaryIconColor, android.graphics.PorterDuff.Mode.SRC_IN); + int bottomAppBarIconColor = mCustomThemeWrapper.getBottomAppBarIconColor(); + subscriptionsBottomAppBar.setColorFilter(bottomAppBarIconColor, android.graphics.PorterDuff.Mode.SRC_IN); + multiRedditBottomAppBar.setColorFilter(bottomAppBarIconColor, android.graphics.PorterDuff.Mode.SRC_IN); + messageBottomAppBar.setColorFilter(bottomAppBarIconColor, android.graphics.PorterDuff.Mode.SRC_IN); + profileBottomAppBar.setColorFilter(bottomAppBarIconColor, android.graphics.PorterDuff.Mode.SRC_IN); applyTabLayoutTheme(tabLayout); applyFABTheme(fab); unsubscribedColor = mCustomThemeWrapper.getUnsubscribed(); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CustomTheme/CustomTheme.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CustomTheme/CustomTheme.java index 1c105ad3..7fbd3359 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/CustomTheme/CustomTheme.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/CustomTheme/CustomTheme.java @@ -51,6 +51,8 @@ public class CustomTheme { public int bottomAppBarBackgroundColor; @ColumnInfo(name = "primary_icon_color") public int primaryIconColor; + @ColumnInfo(name = "bottom_app_bar_icon_color") + public int bottomAppBarIconColor; @ColumnInfo(name = "post_icon_and_info_color") public int postIconAndInfoColor; @ColumnInfo(name = "comment_icon_and_info_color") @@ -193,57 +195,58 @@ public class CustomTheme { customTheme.commentBackgroundColor = customThemeSettingsItems.get(16).colorValue; customTheme.bottomAppBarBackgroundColor = customThemeSettingsItems.get(17).colorValue; customTheme.primaryIconColor = customThemeSettingsItems.get(18).colorValue; - customTheme.postIconAndInfoColor = customThemeSettingsItems.get(19).colorValue; - customTheme.commentIconAndInfoColor = customThemeSettingsItems.get(20).colorValue; - customTheme.fabIconColor = customThemeSettingsItems.get(21).colorValue; - customTheme.toolbarPrimaryTextAndIconColor = customThemeSettingsItems.get(22).colorValue; - customTheme.toolbarSecondaryTextColor = customThemeSettingsItems.get(23).colorValue; - customTheme.circularProgressBarBackground = customThemeSettingsItems.get(24).colorValue; - customTheme.tabLayoutWithExpandedCollapsingToolbarTabBackground = customThemeSettingsItems.get(25).colorValue; - customTheme.tabLayoutWithExpandedCollapsingToolbarTextColor = customThemeSettingsItems.get(26).colorValue; - customTheme.tabLayoutWithExpandedCollapsingToolbarTabIndicator = customThemeSettingsItems.get(27).colorValue; - customTheme.tabLayoutWithCollapsedCollapsingToolbarTabBackground = customThemeSettingsItems.get(28).colorValue; - customTheme.tabLayoutWithCollapsedCollapsingToolbarTextColor = customThemeSettingsItems.get(29).colorValue; - customTheme.tabLayoutWithCollapsedCollapsingToolbarTabIndicator = customThemeSettingsItems.get(30).colorValue; - customTheme.upvoted = customThemeSettingsItems.get(31).colorValue; - customTheme.downvoted = customThemeSettingsItems.get(32).colorValue; - customTheme.postTypeBackgroundColor = customThemeSettingsItems.get(33).colorValue; - customTheme.postTypeTextColor = customThemeSettingsItems.get(34).colorValue; - customTheme.spoilerBackgroundColor = customThemeSettingsItems.get(35).colorValue; - customTheme.spoilerTextColor = customThemeSettingsItems.get(36).colorValue; - customTheme.nsfwBackgroundColor = customThemeSettingsItems.get(37).colorValue; - customTheme.nsfwTextColor = customThemeSettingsItems.get(38).colorValue; - customTheme.flairBackgroundColor = customThemeSettingsItems.get(39).colorValue; - customTheme.flairTextColor = customThemeSettingsItems.get(40).colorValue; - customTheme.awardsBackgroundColor = customThemeSettingsItems.get(41).colorValue; - customTheme.awardsTextColor = customThemeSettingsItems.get(42).colorValue; - customTheme.archivedTint = customThemeSettingsItems.get(43).colorValue; - customTheme.lockedIconTint = customThemeSettingsItems.get(44).colorValue; - customTheme.crosspostIconTint = customThemeSettingsItems.get(45).colorValue; - customTheme.stickiedPostIconTint = customThemeSettingsItems.get(46).colorValue; - customTheme.subscribed = customThemeSettingsItems.get(47).colorValue; - customTheme.unsubscribed = customThemeSettingsItems.get(48).colorValue; - customTheme.username = customThemeSettingsItems.get(49).colorValue; - customTheme.subreddit = customThemeSettingsItems.get(50).colorValue; - customTheme.authorFlairTextColor = customThemeSettingsItems.get(51).colorValue; - customTheme.submitter = customThemeSettingsItems.get(52).colorValue; - customTheme.moderator = customThemeSettingsItems.get(53).colorValue; - customTheme.singleCommentThreadBackgroundColor = customThemeSettingsItems.get(54).colorValue; - customTheme.unreadMessageBackgroundColor = customThemeSettingsItems.get(55).colorValue; - customTheme.dividerColor = customThemeSettingsItems.get(56).colorValue; - customTheme.noPreviewLinkBackgroundColor = customThemeSettingsItems.get(57).colorValue; - customTheme.voteAndReplyUnavailableButtonColor = customThemeSettingsItems.get(58).colorValue; - customTheme.commentVerticalBarColor1 = customThemeSettingsItems.get(59).colorValue; - customTheme.commentVerticalBarColor2 = customThemeSettingsItems.get(60).colorValue; - customTheme.commentVerticalBarColor3 = customThemeSettingsItems.get(61).colorValue; - customTheme.commentVerticalBarColor4 = customThemeSettingsItems.get(62).colorValue; - customTheme.commentVerticalBarColor5 = customThemeSettingsItems.get(63).colorValue; - customTheme.commentVerticalBarColor6 = customThemeSettingsItems.get(64).colorValue; - customTheme.commentVerticalBarColor7 = customThemeSettingsItems.get(65).colorValue; - customTheme.navBarColor = customThemeSettingsItems.get(66).colorValue; - customTheme.isLightStatusBar = customThemeSettingsItems.get(67).isEnabled; - customTheme.isLightNavBar = customThemeSettingsItems.get(68).isEnabled; - customTheme.isChangeStatusBarIconColorAfterToolbarCollapsedInImmersiveInterface = customThemeSettingsItems.get(69).isEnabled; + customTheme.bottomAppBarIconColor = customThemeSettingsItems.get(19).colorValue; + customTheme.postIconAndInfoColor = customThemeSettingsItems.get(20).colorValue; + customTheme.commentIconAndInfoColor = customThemeSettingsItems.get(21).colorValue; + customTheme.fabIconColor = customThemeSettingsItems.get(22).colorValue; + customTheme.toolbarPrimaryTextAndIconColor = customThemeSettingsItems.get(23).colorValue; + customTheme.toolbarSecondaryTextColor = customThemeSettingsItems.get(24).colorValue; + customTheme.circularProgressBarBackground = customThemeSettingsItems.get(25).colorValue; + customTheme.tabLayoutWithExpandedCollapsingToolbarTabBackground = customThemeSettingsItems.get(26).colorValue; + customTheme.tabLayoutWithExpandedCollapsingToolbarTextColor = customThemeSettingsItems.get(27).colorValue; + customTheme.tabLayoutWithExpandedCollapsingToolbarTabIndicator = customThemeSettingsItems.get(28).colorValue; + customTheme.tabLayoutWithCollapsedCollapsingToolbarTabBackground = customThemeSettingsItems.get(29).colorValue; + customTheme.tabLayoutWithCollapsedCollapsingToolbarTextColor = customThemeSettingsItems.get(30).colorValue; + customTheme.tabLayoutWithCollapsedCollapsingToolbarTabIndicator = customThemeSettingsItems.get(31).colorValue; + customTheme.upvoted = customThemeSettingsItems.get(32).colorValue; + customTheme.downvoted = customThemeSettingsItems.get(33).colorValue; + customTheme.postTypeBackgroundColor = customThemeSettingsItems.get(34).colorValue; + customTheme.postTypeTextColor = customThemeSettingsItems.get(35).colorValue; + customTheme.spoilerBackgroundColor = customThemeSettingsItems.get(36).colorValue; + customTheme.spoilerTextColor = customThemeSettingsItems.get(37).colorValue; + customTheme.nsfwBackgroundColor = customThemeSettingsItems.get(38).colorValue; + customTheme.nsfwTextColor = customThemeSettingsItems.get(39).colorValue; + customTheme.flairBackgroundColor = customThemeSettingsItems.get(40).colorValue; + customTheme.flairTextColor = customThemeSettingsItems.get(41).colorValue; + customTheme.awardsBackgroundColor = customThemeSettingsItems.get(42).colorValue; + customTheme.awardsTextColor = customThemeSettingsItems.get(43).colorValue; + customTheme.archivedTint = customThemeSettingsItems.get(44).colorValue; + customTheme.lockedIconTint = customThemeSettingsItems.get(45).colorValue; + customTheme.crosspostIconTint = customThemeSettingsItems.get(46).colorValue; + customTheme.stickiedPostIconTint = customThemeSettingsItems.get(47).colorValue; + customTheme.subscribed = customThemeSettingsItems.get(48).colorValue; + customTheme.unsubscribed = customThemeSettingsItems.get(49).colorValue; + customTheme.username = customThemeSettingsItems.get(50).colorValue; + customTheme.subreddit = customThemeSettingsItems.get(51).colorValue; + customTheme.authorFlairTextColor = customThemeSettingsItems.get(52).colorValue; + customTheme.submitter = customThemeSettingsItems.get(53).colorValue; + customTheme.moderator = customThemeSettingsItems.get(54).colorValue; + customTheme.singleCommentThreadBackgroundColor = customThemeSettingsItems.get(55).colorValue; + customTheme.unreadMessageBackgroundColor = customThemeSettingsItems.get(56).colorValue; + customTheme.dividerColor = customThemeSettingsItems.get(57).colorValue; + customTheme.noPreviewLinkBackgroundColor = customThemeSettingsItems.get(58).colorValue; + customTheme.voteAndReplyUnavailableButtonColor = customThemeSettingsItems.get(59).colorValue; + customTheme.commentVerticalBarColor1 = customThemeSettingsItems.get(60).colorValue; + customTheme.commentVerticalBarColor2 = customThemeSettingsItems.get(61).colorValue; + customTheme.commentVerticalBarColor3 = customThemeSettingsItems.get(62).colorValue; + customTheme.commentVerticalBarColor4 = customThemeSettingsItems.get(63).colorValue; + customTheme.commentVerticalBarColor5 = customThemeSettingsItems.get(64).colorValue; + customTheme.commentVerticalBarColor6 = customThemeSettingsItems.get(65).colorValue; + customTheme.commentVerticalBarColor7 = customThemeSettingsItems.get(66).colorValue; + customTheme.navBarColor = customThemeSettingsItems.get(67).colorValue; + customTheme.isLightStatusBar = customThemeSettingsItems.get(68).isEnabled; + customTheme.isLightNavBar = customThemeSettingsItems.get(69).isEnabled; + customTheme.isChangeStatusBarIconColorAfterToolbarCollapsedInImmersiveInterface = customThemeSettingsItems.get(70).isEnabled; return customTheme; } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CustomTheme/CustomThemeSettingsItem.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CustomTheme/CustomThemeSettingsItem.java index 531f6e8d..b32fcf1a 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/CustomTheme/CustomThemeSettingsItem.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/CustomTheme/CustomThemeSettingsItem.java @@ -130,6 +130,10 @@ public class CustomThemeSettingsItem implements Parcelable { context.getString(R.string.theme_item_primary_icon_color), context.getString(R.string.theme_item_primary_icon_color_detail), customTheme.primaryIconColor)); + customThemeSettingsItems.add(new CustomThemeSettingsItem( + context.getString(R.string.theme_item_bottom_app_bar_icon_color), + context.getString(R.string.theme_item_bottom_app_bar_icon_color_detail), + customTheme.bottomAppBarIconColor)); customThemeSettingsItems.add(new CustomThemeSettingsItem( context.getString(R.string.theme_item_post_icon_and_info_color), context.getString(R.string.theme_item_post_icon_and_info_color_detail), diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CustomTheme/CustomThemeWrapper.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CustomTheme/CustomThemeWrapper.java index ff30966d..aef072c9 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/CustomTheme/CustomThemeWrapper.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/CustomTheme/CustomThemeWrapper.java @@ -127,6 +127,11 @@ public class CustomThemeWrapper { getDefaultColor("#000000", "#FFFFFF", "#FFFFFF")); } + public int getBottomAppBarIconColor() { + return getThemeSharedPreferences().getInt(CustomThemeSharedPreferencesUtils.BOTTOM_APP_BAR_ICON_COLOR, + getDefaultColor("#000000", "#FFFFFF", "#FFFFFF")); + } + public int getPostIconAndInfoColor() { return getThemeSharedPreferences().getInt(CustomThemeSharedPreferencesUtils.POST_ICON_AND_INFO_COLOR, getDefaultColor("#8A000000", "#B3FFFFFF", "#B3FFFFFF")); @@ -449,6 +454,7 @@ public class CustomThemeWrapper { customTheme.commentBackgroundColor = Color.parseColor("#FFFFFF"); customTheme.bottomAppBarBackgroundColor = Color.parseColor("#FFFFFF"); customTheme.primaryIconColor = Color.parseColor("#000000"); + customTheme.bottomAppBarIconColor = Color.parseColor("#000000"); customTheme.postIconAndInfoColor = Color.parseColor("#8A000000"); customTheme.commentIconAndInfoColor = Color.parseColor("#8A000000"); customTheme.toolbarPrimaryTextAndIconColor = Color.parseColor("#FFFFFF"); @@ -525,6 +531,7 @@ public class CustomThemeWrapper { customTheme.commentBackgroundColor = Color.parseColor("#242424"); customTheme.bottomAppBarBackgroundColor = Color.parseColor("#121212"); customTheme.primaryIconColor = Color.parseColor("#FFFFFF"); + customTheme.bottomAppBarIconColor = Color.parseColor("#FFFFFF"); customTheme.postIconAndInfoColor = Color.parseColor("#B3FFFFFF"); customTheme.commentIconAndInfoColor = Color.parseColor("#B3FFFFFF"); customTheme.toolbarPrimaryTextAndIconColor = Color.parseColor("#FFFFFF"); @@ -601,6 +608,7 @@ public class CustomThemeWrapper { customTheme.commentBackgroundColor = Color.parseColor("#000000"); customTheme.bottomAppBarBackgroundColor = Color.parseColor("#000000"); customTheme.primaryIconColor = Color.parseColor("#FFFFFF"); + customTheme.bottomAppBarIconColor = Color.parseColor("#FFFFFF"); customTheme.postIconAndInfoColor = Color.parseColor("#B3FFFFFF"); customTheme.commentIconAndInfoColor = Color.parseColor("#B3FFFFFF"); customTheme.toolbarPrimaryTextAndIconColor = Color.parseColor("#FFFFFF"); @@ -677,6 +685,7 @@ public class CustomThemeWrapper { customTheme.commentBackgroundColor = Color.parseColor("#FFFFFF"); customTheme.bottomAppBarBackgroundColor = Color.parseColor("#FFFFFF"); customTheme.primaryIconColor = Color.parseColor("#000000"); + customTheme.bottomAppBarIconColor = Color.parseColor("#000000"); customTheme.postIconAndInfoColor = Color.parseColor("#3C4043"); customTheme.commentIconAndInfoColor = Color.parseColor("#3C4043"); customTheme.toolbarPrimaryTextAndIconColor = Color.parseColor("#3C4043"); @@ -753,6 +762,7 @@ public class CustomThemeWrapper { customTheme.commentBackgroundColor = Color.parseColor("#242424"); customTheme.bottomAppBarBackgroundColor = Color.parseColor("#121212"); customTheme.primaryIconColor = Color.parseColor("#FFFFFF"); + customTheme.bottomAppBarIconColor = Color.parseColor("#FFFFFF"); customTheme.postIconAndInfoColor = Color.parseColor("#B3FFFFFF"); customTheme.commentIconAndInfoColor = Color.parseColor("#B3FFFFFF"); customTheme.toolbarPrimaryTextAndIconColor = Color.parseColor("#FFFFFF"); @@ -829,6 +839,7 @@ public class CustomThemeWrapper { customTheme.commentBackgroundColor = Color.parseColor("#000000"); customTheme.bottomAppBarBackgroundColor = Color.parseColor("#000000"); customTheme.primaryIconColor = Color.parseColor("#FFFFFF"); + customTheme.bottomAppBarIconColor = Color.parseColor("#FFFFFF"); customTheme.postIconAndInfoColor = Color.parseColor("#B3FFFFFF"); customTheme.commentIconAndInfoColor = Color.parseColor("#B3FFFFFF"); customTheme.toolbarPrimaryTextAndIconColor = Color.parseColor("#FFFFFF"); @@ -905,6 +916,7 @@ public class CustomThemeWrapper { customTheme.commentBackgroundColor = Color.parseColor("#FFFFFF"); customTheme.bottomAppBarBackgroundColor = Color.parseColor("#FFFFFF"); customTheme.primaryIconColor = Color.parseColor("#000000"); + customTheme.bottomAppBarIconColor = Color.parseColor("#000000"); customTheme.postIconAndInfoColor = Color.parseColor("#8A000000"); customTheme.commentIconAndInfoColor = Color.parseColor("#8A000000"); customTheme.toolbarPrimaryTextAndIconColor = Color.parseColor("#FFFFFF"); @@ -981,6 +993,7 @@ public class CustomThemeWrapper { customTheme.commentBackgroundColor = Color.parseColor("#242424"); customTheme.bottomAppBarBackgroundColor = Color.parseColor("#121212"); customTheme.primaryIconColor = Color.parseColor("#FFFFFF"); + customTheme.bottomAppBarIconColor = Color.parseColor("#FFFFFF"); customTheme.postIconAndInfoColor = Color.parseColor("#B3FFFFFF"); customTheme.commentIconAndInfoColor = Color.parseColor("#B3FFFFFF"); customTheme.toolbarPrimaryTextAndIconColor = Color.parseColor("#FFFFFF"); @@ -1057,6 +1070,7 @@ public class CustomThemeWrapper { customTheme.commentBackgroundColor = Color.parseColor("#000000"); customTheme.bottomAppBarBackgroundColor = Color.parseColor("#000000"); customTheme.primaryIconColor = Color.parseColor("#FFFFFF"); + customTheme.bottomAppBarIconColor = Color.parseColor("#FFFFFF"); customTheme.postIconAndInfoColor = Color.parseColor("#B3FFFFFF"); customTheme.commentIconAndInfoColor = Color.parseColor("#B3FFFFFF"); customTheme.toolbarPrimaryTextAndIconColor = Color.parseColor("#FFFFFF"); @@ -1133,6 +1147,7 @@ public class CustomThemeWrapper { customTheme.commentBackgroundColor = Color.parseColor("#393A59"); customTheme.bottomAppBarBackgroundColor = Color.parseColor("#393A59"); customTheme.primaryIconColor = Color.parseColor("#FFFFFF"); + customTheme.bottomAppBarIconColor = Color.parseColor("#FFFFFF"); customTheme.postIconAndInfoColor = Color.parseColor("#FFFFFF"); customTheme.commentIconAndInfoColor = Color.parseColor("#FFFFFF"); customTheme.toolbarPrimaryTextAndIconColor = Color.parseColor("#FFFFFF"); @@ -1209,6 +1224,7 @@ public class CustomThemeWrapper { customTheme.commentBackgroundColor = Color.parseColor("#C0F0F4"); customTheme.bottomAppBarBackgroundColor = Color.parseColor("#D48AE0"); customTheme.primaryIconColor = Color.parseColor("#000000"); + customTheme.bottomAppBarIconColor = Color.parseColor("#000000"); customTheme.postIconAndInfoColor = Color.parseColor("#000000"); customTheme.commentIconAndInfoColor = Color.parseColor("#000000"); customTheme.toolbarPrimaryTextAndIconColor = Color.parseColor("#3C4043"); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseSubredditData.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseSubredditData.java index bb64d7df..73854808 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseSubredditData.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseSubredditData.java @@ -25,6 +25,7 @@ class ParseSubredditData { String subredditFullName = subredditDataJsonObject.getString(JSONUtils.DISPLAY_NAME_KEY); String description = subredditDataJsonObject.getString(JSONUtils.PUBLIC_DESCRIPTION_KEY).trim(); String sidebarDescription = subredditDataJsonObject.getString(JSONUtils.DESCRIPTION_KEY).trim(); + long createdUTC = subredditDataJsonObject.getLong(JSONUtils.CREATED_UTC_KEY) * 1000; String bannerImageUrl; if (subredditDataJsonObject.isNull(JSONUtils.BANNER_BACKGROUND_IMAGE_KEY)) { @@ -52,7 +53,7 @@ class ParseSubredditData { } return new SubredditData(id, subredditFullName, iconUrl, bannerImageUrl, description, - sidebarDescription, nSubscribers); + sidebarDescription, nSubscribers, createdUTC); } interface ParseSubredditDataListener { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseSubscribedThing.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseSubscribedThing.java index 97827fc2..97da7db6 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseSubscribedThing.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseSubscribedThing.java @@ -99,9 +99,10 @@ class ParseSubscribedThing { String description = data.getString(JSONUtils.PUBLIC_DESCRIPTION_KEY).trim(); String sidebarDescription = data.getString(JSONUtils.DESCRIPTION_KEY); int nSubscribers = data.getInt(JSONUtils.SUBSCRIBERS_KEY); + long createdUTC = data.getLong(JSONUtils.CREATED_UTC_KEY); newSubscribedSubredditData.add(new SubscribedSubredditData(id, name, iconUrl, accountName, isFavorite)); newSubredditData.add(new SubredditData(id, subredditFullName, iconUrl, - bannerImageUrl, description, sidebarDescription, nSubscribers)); + bannerImageUrl, description, sidebarDescription, nSubscribers, createdUTC)); } } lastItem = jsonResponse.getJSONObject(JSONUtils.DATA_KEY).getString(JSONUtils.AFTER_KEY); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseUserData.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseUserData.java index 73932c34..87334324 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseUserData.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseUserData.java @@ -38,11 +38,13 @@ public class ParseUserData { } int linkKarma = userDataJson.getInt(JSONUtils.LINK_KARMA_KEY); int commentKarma = userDataJson.getInt(JSONUtils.COMMENT_KARMA_KEY); - int karma = linkKarma + commentKarma; + long cakeday = userDataJson.getLong(JSONUtils.CREATED_UTC_KEY) * 1000; boolean isGold = userDataJson.getBoolean(JSONUtils.IS_GOLD_KEY); boolean isFriend = userDataJson.getBoolean(JSONUtils.IS_FRIEND_KEY); + String description = userDataJson.getString(JSONUtils.PUBLIC_DESCRIPTION_KEY); - return new UserData(userName, iconImageUrl, bannerImageUrl, karma, isGold, isFriend, canBeFollowed); + return new UserData(userName, iconImageUrl, bannerImageUrl, linkKarma, commentKarma, cakeday, + isGold, isFriend, canBeFollowed, description); } interface ParseUserDataListener { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditDataRoomDatabase.java b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditDataRoomDatabase.java index 539bd20e..8743c4c9 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditDataRoomDatabase.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditDataRoomDatabase.java @@ -26,7 +26,7 @@ import ml.docilealligator.infinityforreddit.User.UserDao; import ml.docilealligator.infinityforreddit.User.UserData; @Database(entities = {Account.class, SubredditData.class, SubscribedSubredditData.class, UserData.class, - SubscribedUserData.class, MultiReddit.class, CustomTheme.class}, version = 7) + SubscribedUserData.class, MultiReddit.class, CustomTheme.class}, version = 8) public abstract class RedditDataRoomDatabase extends RoomDatabase { private static RedditDataRoomDatabase INSTANCE; @@ -37,7 +37,7 @@ public abstract class RedditDataRoomDatabase extends RoomDatabase { INSTANCE = Room.databaseBuilder(context.getApplicationContext(), RedditDataRoomDatabase.class, "reddit_data") .addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5, - MIGRATION_5_6, MIGRATION_6_7) + MIGRATION_5_6, MIGRATION_6_7, MIGRATION_7_8) .build(); } } @@ -165,4 +165,25 @@ public abstract class RedditDataRoomDatabase extends RoomDatabase { database.execSQL("ALTER TABLE custom_themes ADD COLUMN awards_text_color INTEGER DEFAULT " + Color.parseColor("#FFFFFF") + " NOT NULL"); } }; + + private static final Migration MIGRATION_7_8 = new Migration(7, 8) { + @Override + public void migrate(@NonNull SupportSQLiteDatabase database) { + database.execSQL("CREATE TABLE users_temp " + + "(name TEXT NOT NULL PRIMARY KEY, icon TEXT, banner TEXT, " + + "link_karma INTEGER NOT NULL, comment_karma INTEGER DEFAULT 0 NOT NULL, created_utc INTEGER DEFAULT 0 NOT NULL," + + "is_gold INTEGER NOT NULL, is_friend INTEGER NOT NULL, can_be_followed INTEGER NOT NULL," + + "description TEXT)"); + database.execSQL( + "INSERT INTO users_temp(name, icon, banner, link_karma, is_gold, is_friend, can_be_followed) SELECT * FROM users"); + database.execSQL("DROP TABLE users"); + database.execSQL("ALTER TABLE users_temp RENAME TO users"); + + database.execSQL("ALTER TABLE subreddits" + + " ADD COLUMN created_utc INTEGER DEFAULT 0 NOT NULL"); + + database.execSQL("ALTER TABLE custom_themes" + + " ADD COLUMN bottom_app_bar_icon_color INTEGER DEFAULT " + Color.parseColor("#000000") + " NOT NULL"); + } + }; } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditDatabase/SubredditData.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditDatabase/SubredditData.java index 486bd0a7..6c73f459 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditDatabase/SubredditData.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditDatabase/SubredditData.java @@ -23,9 +23,11 @@ public class SubredditData { private String sidebarDescription; @ColumnInfo(name = "subscribers_count") private int nSubscribers; + @ColumnInfo(name = "created_utc") + private long createdUTC; public SubredditData(@NonNull String id, String name, String iconUrl, String bannerUrl, - String description, String sidebarDescription, int nSubscribers) { + String description, String sidebarDescription, int nSubscribers, long createdUTC) { this.id = id; this.name = name; this.iconUrl = iconUrl; @@ -33,6 +35,7 @@ public class SubredditData { this.description = description; this.sidebarDescription = sidebarDescription; this.nSubscribers = nSubscribers; + this.createdUTC = createdUTC; } @NonNull @@ -63,4 +66,8 @@ public class SubredditData { public int getNSubscribers() { return nSubscribers; } + + public long getCreatedUTC() { + return createdUTC; + } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/User/UserData.java b/app/src/main/java/ml/docilealligator/infinityforreddit/User/UserData.java index f207685e..8ad00b49 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/User/UserData.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/User/UserData.java @@ -15,23 +15,33 @@ public class UserData { private String iconUrl; @ColumnInfo(name = "banner") private String banner; - @ColumnInfo(name = "karma") - private int karma; + @ColumnInfo(name = "link_karma") + private int linkKarma; + @ColumnInfo(name = "comment_karma") + private int commentKarma; + @ColumnInfo(name = "created_utc") + private long cakeday; @ColumnInfo(name = "is_gold") private boolean isGold; @ColumnInfo(name = "is_friend") private boolean isFriend; @ColumnInfo(name = "can_be_followed") private boolean canBeFollowed; + @ColumnInfo(name = "description") + private String description; - public UserData(@NonNull String name, String iconUrl, String banner, int karma, boolean isGold, boolean isFriend, boolean canBeFollowed) { + public UserData(@NonNull String name, String iconUrl, String banner, int linkKarma, int commentKarma, + long cakeday, boolean isGold, boolean isFriend, boolean canBeFollowed, String description) { this.name = name; this.iconUrl = iconUrl; this.banner = banner; - this.karma = karma; + this.commentKarma = commentKarma; + this.linkKarma = linkKarma; + this.cakeday = cakeday; this.isGold = isGold; this.isFriend = isFriend; this.canBeFollowed = canBeFollowed; + this.description = description; } @NonNull @@ -47,8 +57,20 @@ public class UserData { return banner; } + public int getLinkKarma() { + return linkKarma; + } + + public int getCommentKarma() { + return commentKarma; + } + public int getKarma() { - return karma; + return linkKarma + commentKarma; + } + + public long getCakeday() { + return cakeday; } public boolean isGold() { @@ -62,4 +84,8 @@ public class UserData { public boolean isCanBeFollowed() { return canBeFollowed; } + + public String getDescription() { + return description; + } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/CustomThemeSharedPreferencesUtils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/CustomThemeSharedPreferencesUtils.java index 6e08559b..295013f1 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/CustomThemeSharedPreferencesUtils.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/CustomThemeSharedPreferencesUtils.java @@ -29,6 +29,7 @@ public class CustomThemeSharedPreferencesUtils { public static final String COMMENT_BACKGROUND_COLOR = "commentBackgroundColor"; public static final String BOTTOM_APP_BAR_BACKGROUND_COLOR = "bottomAppBarBackgroundColor"; public static final String PRIMARY_ICON_COLOR = "primaryIconColor"; + public static final String BOTTOM_APP_BAR_ICON_COLOR = "bottomAppBarIconColor"; public static final String POST_ICON_AND_INFO_COLOR = "postIconAndInfoColor"; public static final String COMMENT_ICON_AND_INFO_COLOR = "commentIconAndInfoColor"; public static final String TOOLBAR_PRIMARY_TEXT_AND_ICON_COLOR = "toolbarPrimaryTextAndIconColor"; @@ -96,6 +97,7 @@ public class CustomThemeSharedPreferencesUtils { editor.putInt(COMMENT_BACKGROUND_COLOR, customTheme.commentBackgroundColor); editor.putInt(BOTTOM_APP_BAR_BACKGROUND_COLOR, customTheme.bottomAppBarBackgroundColor); editor.putInt(PRIMARY_ICON_COLOR, customTheme.primaryIconColor); + editor.putInt(BOTTOM_APP_BAR_ICON_COLOR, customTheme.bottomAppBarIconColor); editor.putInt(POST_ICON_AND_INFO_COLOR, customTheme.postIconAndInfoColor); editor.putInt(COMMENT_ICON_AND_INFO_COLOR, customTheme.commentIconAndInfoColor); editor.putInt(TOOLBAR_PRIMARY_TEXT_AND_ICON_COLOR, customTheme.toolbarPrimaryTextAndIconColor); @@ -118,6 +120,8 @@ public class CustomThemeSharedPreferencesUtils { editor.putInt(NSFW_TEXT_COLOR, customTheme.nsfwTextColor); editor.putInt(FLAIR_BACKGROUND_COLOR, customTheme.flairBackgroundColor); editor.putInt(FLAIR_TEXT_COLOR, customTheme.flairTextColor); + editor.putInt(AWARDS_BACKGROUND_COLOR, customTheme.awardsBackgroundColor); + editor.putInt(AWARDS_TEXT_COLOR, customTheme.awardsTextColor); editor.putInt(ARCHIVED_ICON_TINT, customTheme.archivedTint); editor.putInt(LOCKED_ICON_TINT, customTheme.lockedIconTint); editor.putInt(CROSSPOST_ICON_TINT, customTheme.crosspostIconTint); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 35dadb3a..945805f1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -525,7 +525,9 @@ Bottom Navigation Bar Color Applied to: Bottom navigation bar Primary Icon Color - Applied to: Icons in the bottom navigation bar and the navigation drawer. + Applied to: Icons in the navigation drawer. + Bottom Navigation Bar Icon Color + Applied to: Icons in the bottom navigation bar Post Icon and Info Color Applied to: Icons, score and the number of comments in posts Comment Icon and Info Color -- cgit v1.2.3 From ae98fd8a08d2f65415403b3159f3303bdd350978 Mon Sep 17 00:00:00 2001 From: Alex Ning Date: Sat, 2 May 2020 08:34:56 +0800 Subject: Fix JSON parsing error when parsing user data. --- .../main/java/ml/docilealligator/infinityforreddit/ParseUserData.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseUserData.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseUserData.java index 87334324..f3766d05 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseUserData.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseUserData.java @@ -41,7 +41,7 @@ public class ParseUserData { long cakeday = userDataJson.getLong(JSONUtils.CREATED_UTC_KEY) * 1000; boolean isGold = userDataJson.getBoolean(JSONUtils.IS_GOLD_KEY); boolean isFriend = userDataJson.getBoolean(JSONUtils.IS_FRIEND_KEY); - String description = userDataJson.getString(JSONUtils.PUBLIC_DESCRIPTION_KEY); + String description = userDataJson.getJSONObject(JSONUtils.SUBREDDIT_KEY).getString(JSONUtils.PUBLIC_DESCRIPTION_KEY); return new UserData(userName, iconImageUrl, bannerImageUrl, linkKarma, commentKarma, cakeday, isGold, isFriend, canBeFollowed, description); -- cgit v1.2.3 From 93af286d553084a8b85ae8b8baa5fc7463729f5f Mon Sep 17 00:00:00 2001 From: Alex Ning Date: Sat, 2 May 2020 22:26:45 +0800 Subject: Sharing user and subreddit is now available. --- .../Activity/ViewSubredditDetailActivity.java | 10 ++++++++++ .../Activity/ViewUserDetailActivity.java | 18 ++++++++++++------ .../main/res/menu/view_subreddit_detail_activity.xml | 6 ++++++ app/src/main/res/menu/view_user_detail_activity.xml | 6 ++++++ 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewSubredditDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewSubredditDetailActivity.java index b0148cdd..d83ba1ee 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewSubredditDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewSubredditDetailActivity.java @@ -706,6 +706,16 @@ public class ViewSubredditDetailActivity extends BaseActivity implements SortTyp sidebarIntent.putExtra(ViewSidebarActivity.EXTRA_SUBREDDIT_NAME, subredditName); startActivity(sidebarIntent); return true; + case R.id.action_share_view_subreddit_detail_activity: + Intent shareIntent = new Intent(Intent.ACTION_SEND); + shareIntent.setType("text/plain"); + shareIntent.putExtra(Intent.EXTRA_TEXT, "https://www.reddit.com/r/" + subredditName); + if (shareIntent.resolveActivity(getPackageManager()) != null) { + startActivity(Intent.createChooser(shareIntent, getString(R.string.share))); + } else { + Toast.makeText(this, R.string.no_app, Toast.LENGTH_SHORT).show(); + } + return true; } return false; } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewUserDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewUserDetailActivity.java index 8af8944c..82acead4 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewUserDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewUserDetailActivity.java @@ -280,9 +280,7 @@ public class ViewUserDetailActivity extends BaseActivity implements SortTypeSele userViewModel.getUserLiveData().observe(this, userData -> { if (userData != null) { if (userData.getBanner().equals("")) { - bannerImageView.setOnClickListener(view -> { - //Do nothing since the user has no banner image - }); + bannerImageView.setOnClickListener(null); } else { glide.load(userData.getBanner()).into(bannerImageView); bannerImageView.setOnClickListener(view -> { @@ -297,9 +295,7 @@ public class ViewUserDetailActivity extends BaseActivity implements SortTypeSele glide.load(getDrawable(R.drawable.subreddit_default_icon)) .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(216, 0))) .into(iconGifImageView); - iconGifImageView.setOnClickListener(view -> { - //Do nothing since the user has no icon image - }); + iconGifImageView.setOnClickListener(null); } else { glide.load(userData.getIconUrl()) .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(216, 0))) @@ -621,6 +617,16 @@ public class ViewUserDetailActivity extends BaseActivity implements SortTypeSele case R.id.action_change_post_layout_view_user_detail_activity: postLayoutBottomSheetFragment.show(getSupportFragmentManager(), postLayoutBottomSheetFragment.getTag()); return true; + case R.id.action_share_view_user_detail_activity: + Intent shareIntent = new Intent(Intent.ACTION_SEND); + shareIntent.setType("text/plain"); + shareIntent.putExtra(Intent.EXTRA_TEXT, "https://www.reddit.com/user/" + username); + if (shareIntent.resolveActivity(getPackageManager()) != null) { + startActivity(Intent.createChooser(shareIntent, getString(R.string.share))); + } else { + Toast.makeText(this, R.string.no_app, Toast.LENGTH_SHORT).show(); + } + return true; } return false; } diff --git a/app/src/main/res/menu/view_subreddit_detail_activity.xml b/app/src/main/res/menu/view_subreddit_detail_activity.xml index eeef2439..9365ed2e 100644 --- a/app/src/main/res/menu/view_subreddit_detail_activity.xml +++ b/app/src/main/res/menu/view_subreddit_detail_activity.xml @@ -39,4 +39,10 @@ android:orderInCategory="6" android:title="@string/action_view_side_bar" app:showAsAction="never" /> + + \ No newline at end of file diff --git a/app/src/main/res/menu/view_user_detail_activity.xml b/app/src/main/res/menu/view_user_detail_activity.xml index fe991f16..18c3ef16 100644 --- a/app/src/main/res/menu/view_user_detail_activity.xml +++ b/app/src/main/res/menu/view_user_detail_activity.xml @@ -31,4 +31,10 @@ android:orderInCategory="5" android:title="@string/action_change_post_layout" app:showAsAction="never" /> + + -- cgit v1.2.3 From 45cdc6d3a61ad15eeed5e9f70f4c8f36f7a22230 Mon Sep 17 00:00:00 2001 From: Alex Ning Date: Sun, 3 May 2020 09:16:07 +0800 Subject: Show cakeday of users and subreddits, user description and post and comment karma. --- .../Activity/ViewSubredditDetailActivity.java | 12 ++++++ .../Activity/ViewUserDetailActivity.java | 21 +++++++++- .../res/layout/activity_view_subreddit_detail.xml | 47 ++++++++++++++++++---- .../main/res/layout/activity_view_user_detail.xml | 42 ++++++++++++++----- app/src/main/res/values/strings.xml | 3 ++ 5 files changed, 106 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewSubredditDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewSubredditDetailActivity.java index d83ba1ee..f22b6361 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewSubredditDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewSubredditDetailActivity.java @@ -41,6 +41,9 @@ import com.google.android.material.tabs.TabLayout; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; +import java.text.SimpleDateFormat; +import java.util.Locale; + import javax.inject.Inject; import javax.inject.Named; @@ -119,6 +122,10 @@ public class ViewSubredditDetailActivity extends BaseActivity implements SortTyp TextView nSubscribersTextView; @BindView(R.id.online_subscriber_count_text_view_view_subreddit_detail_activity) TextView nOnlineSubscribersTextView; + @BindView(R.id.since_text_view_view_subreddit_detail_activity) + TextView sinceTextView; + @BindView(R.id.creation_time_text_view_view_subreddit_detail_activity) + TextView creationTimeTextView; @BindView(R.id.description_text_view_view_subreddit_detail_activity) TextView descriptionTextView; @BindView(R.id.bottom_navigation_view_subreddit_detail_activity) @@ -322,6 +329,7 @@ public class ViewSubredditDetailActivity extends BaseActivity implements SortTyp setSupportActionBar(toolbar); glide = Glide.with(this); + Locale locale = getResources().getConfiguration().locale; mSubredditViewModel = new ViewModelProvider(this, new SubredditViewModel.Factory(getApplication(), mRedditDataRoomDatabase, subredditName)) @@ -370,6 +378,8 @@ public class ViewSubredditDetailActivity extends BaseActivity implements SortTyp subredditNameTextView.setText(subredditFullName); String nSubscribers = getString(R.string.subscribers_number_detail, subredditData.getNSubscribers()); nSubscribersTextView.setText(nSubscribers); + creationTimeTextView.setText(new SimpleDateFormat("MMM d, yyyy", + locale).format(subredditData.getCreatedUTC())); if (subredditData.getDescription().equals("")) { descriptionTextView.setVisibility(View.GONE); } else { @@ -416,6 +426,8 @@ public class ViewSubredditDetailActivity extends BaseActivity implements SortTyp int primaryTextColor = mCustomThemeWrapper.getPrimaryTextColor(); nSubscribersTextView.setTextColor(primaryTextColor); nOnlineSubscribersTextView.setTextColor(primaryTextColor); + sinceTextView.setTextColor(primaryTextColor); + creationTimeTextView.setTextColor(primaryTextColor); descriptionTextView.setTextColor(primaryTextColor); bottomNavigationView.setBackgroundTint(ColorStateList.valueOf(mCustomThemeWrapper.getBottomAppBarBackgroundColor())); int bottomAppBarIconColor = mCustomThemeWrapper.getBottomAppBarIconColor(); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewUserDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewUserDetailActivity.java index 82acead4..c6bda8bd 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewUserDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewUserDetailActivity.java @@ -40,6 +40,9 @@ import com.google.android.material.tabs.TabLayout; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; +import java.text.SimpleDateFormat; +import java.util.Locale; + import javax.inject.Inject; import javax.inject.Named; @@ -116,6 +119,10 @@ public class ViewUserDetailActivity extends BaseActivity implements SortTypeSele Chip subscribeUserChip; @BindView(R.id.karma_text_view_view_user_detail_activity) TextView karmaTextView; + @BindView(R.id.cakeday_text_view_view_user_detail_activity) + TextView cakedayTextView; + @BindView(R.id.description_text_view_view_user_detail_activity) + TextView descriptionTextView; @Inject @Named("no_oauth") Retrofit mRetrofit; @@ -274,6 +281,7 @@ public class ViewUserDetailActivity extends BaseActivity implements SortTypeSele subscribedUserDao = mRedditDataRoomDatabase.subscribedUserDao(); glide = Glide.with(this); + Locale locale = getResources().getConfiguration().locale; userViewModel = new ViewModelProvider(this, new UserViewModel.Factory(getApplication(), mRedditDataRoomDatabase, username)) .get(UserViewModel.class); @@ -383,8 +391,17 @@ public class ViewUserDetailActivity extends BaseActivity implements SortTypeSele if (!title.equals(userFullName)) { getSupportActionBar().setTitle(userFullName); } - String karma = getString(R.string.karma_info, userData.getKarma()); + String karma = getString(R.string.karma_info_user_detail, userData.getKarma(), userData.getLinkKarma(), userData.getCommentKarma()); karmaTextView.setText(karma); + cakedayTextView.setText(getString(R.string.cakeday_info, new SimpleDateFormat("MMM d, yyyy", + locale).format(userData.getCakeday()))); + + if (userData.getDescription() == null || userData.getDescription().equals("")) { + descriptionTextView.setVisibility(View.GONE); + } else { + descriptionTextView.setVisibility(View.VISIBLE); + descriptionTextView.setText(userData.getDescription()); + } } }); @@ -428,6 +445,8 @@ public class ViewUserDetailActivity extends BaseActivity implements SortTypeSele subscribedColor = mCustomThemeWrapper.getSubscribed(); userNameTextView.setTextColor(mCustomThemeWrapper.getUsername()); karmaTextView.setTextColor(mCustomThemeWrapper.getPrimaryTextColor()); + cakedayTextView.setTextColor(mCustomThemeWrapper.getPrimaryTextColor()); + descriptionTextView.setTextColor(mCustomThemeWrapper.getPrimaryTextColor()); subscribeUserChip.setTextColor(mCustomThemeWrapper.getChipTextColor()); applyTabLayoutTheme(tabLayout); } diff --git a/app/src/main/res/layout/activity_view_subreddit_detail.xml b/app/src/main/res/layout/activity_view_subreddit_detail.xml index da17e978..ee3f0357 100644 --- a/app/src/main/res/layout/activity_view_subreddit_detail.xml +++ b/app/src/main/res/layout/activity_view_subreddit_detail.xml @@ -74,7 +74,7 @@ android:textColor="@android:color/white" android:layout_gravity="center_horizontal"/> - + app:layout_constraintBottom_toTopOf="@id/online_subscriber_count_text_view_view_subreddit_detail_activity" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toStartOf="@id/barrier" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintHorizontal_bias="0" /> + android:textSize="?attr/font_default" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toStartOf="@id/barrier" + app:layout_constraintTop_toBottomOf="@id/subscriber_count_text_view_view_subreddit_detail_activity" + app:layout_constraintHorizontal_bias="0" /> + + + + + + - + - - + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 945805f1..2bd237f9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -90,6 +90,9 @@ NSFW Karma: %1$d + Karma:\n%1$d (%2$d + %3$d) + Cakeday:\n%1$s + Since: Profile Following -- cgit v1.2.3 From 9d451d65dd13c07286641e3fca69914e098a5eb0 Mon Sep 17 00:00:00 2001 From: Alex Ning Date: Sun, 3 May 2020 16:47:33 +0800 Subject: Prepare to add report feature. --- app/src/main/AndroidManifest.xml | 12 +- .../infinityforreddit/Activity/ReportActivity.java | 172 +++++++++++++++++++++ .../Activity/ViewPostDetailActivity.java | 13 ++ .../Adapter/PostRecyclerViewAdapter.java | 16 +- .../Adapter/ReportReasonRecyclerViewAdapter.java | 121 +++++++++++++++ .../infinityforreddit/AppComponent.java | 3 + .../infinityforreddit/RedditAPI.java | 4 + .../infinityforreddit/ReportReason.java | 77 +++++++++ .../infinityforreddit/ReportThing.java | 46 ++++++ .../drawable/ic_fullscreen_white_rounded_18dp.xml | 9 ++ app/src/main/res/layout/activity_report.xml | 31 ++++ .../layout/exo_autoplay_playback_control_view.xml | 10 +- app/src/main/res/layout/item_report_reason.xml | 29 ++++ app/src/main/res/menu/report_activity.xml | 10 ++ .../main/res/menu/view_post_detail_activity.xml | 7 + app/src/main/res/values/strings.xml | 11 ++ 16 files changed, 566 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ReportActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/ReportReasonRecyclerViewAdapter.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/ReportReason.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/ReportThing.java create mode 100644 app/src/main/res/drawable/ic_fullscreen_white_rounded_18dp.xml create mode 100644 app/src/main/res/layout/activity_report.xml create mode 100644 app/src/main/res/layout/item_report_reason.xml create mode 100644 app/src/main/res/menu/report_activity.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b665b78b..08f83a69 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -21,14 +21,20 @@ android:theme="@style/AppTheme" android:usesCleartextTraffic="true" tools:replace="android:label"> - + - + android:theme="@style/AppTheme.NoActionBar" /> = Build.VERSION_CODES.M && isChangeStatusBarIconColor()) { + addOnOffsetChangedListener(appBarLayout); + } + + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + mFullname = getIntent().getStringExtra(EXTRA_THING_FULLNAME); + mSubredditName = getIntent().getStringExtra(EXTRA_SUBREDDIT_NAME); + mAdapter = new ReportReasonRecyclerViewAdapter(mCustomThemeWrapper, ReportReason.getGeneralReasons(this)); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + recyclerView.setAdapter(mAdapter); + + if (savedInstanceState != null) { + mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); + mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); + + if (!mNullAccessToken && mAccessToken == null) { + getCurrentAccount(); + } + } else { + getCurrentAccount(); + } + } + + private void getCurrentAccount() { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if (account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + } + }).execute(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.report_activity, menu); + applyMenuItemTheme(menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + finish(); + return true; + case R.id.action_send_report_activity: + ReportReason reportReason = mAdapter.getSelectedReason(); + if (reportReason != null) { + ReportThing.reportThing(mOauthRetrofit, mAccessToken, mFullname, mSubredditName, + reportReason.getReasonType(), reportReason.getReportReason(), new ReportThing.ReportThingListener() { + @Override + public void success() { + Toast.makeText(ReportActivity.this, R.string.report_successful, Toast.LENGTH_SHORT).show(); + finish(); + } + + @Override + public void failed() { + Toast.makeText(ReportActivity.this, R.string.report_failed, Toast.LENGTH_SHORT).show(); + } + }); + } else { + Toast.makeText(ReportActivity.this, R.string.report_reason_not_selected, Toast.LENGTH_SHORT).show(); + } + return true; + } + + return false; + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); + outState.putString(ACCESS_TOKEN_STATE, mAccessToken); + } + + @Override + protected SharedPreferences getSharedPreferences() { + return mSharedPreferences; + } + + @Override + protected CustomThemeWrapper getCustomThemeWrapper() { + return mCustomThemeWrapper; + } + + @Override + protected void applyCustomTheme() { + coordinatorLayout.setBackgroundColor(mCustomThemeWrapper.getBackgroundColor()); + applyAppBarLayoutAndToolbarTheme(appBarLayout, toolbar); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewPostDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewPostDetailActivity.java index 9d8ea8a9..f3e4d0aa 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewPostDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewPostDetailActivity.java @@ -473,6 +473,8 @@ public class ViewPostDetailActivity extends BaseActivity implements FlairBottomS hideItem.setVisible(true); hideItem.setTitle(R.string.action_hide_post); } + + mMenu.findItem(R.id.action_report_view_post_detail_activity).setVisible(true); } else { saveItem.setVisible(false); hideItem.setVisible(false); @@ -622,6 +624,8 @@ public class ViewPostDetailActivity extends BaseActivity implements FlairBottomS hideItem.setVisible(true); hideItem.setTitle(R.string.action_hide_post); } + + mMenu.findItem(R.id.action_report_view_post_detail_activity).setVisible(true); } else { saveItem.setVisible(false); hideItem.setVisible(false); @@ -931,6 +935,8 @@ public class ViewPostDetailActivity extends BaseActivity implements FlairBottomS hideItem.setVisible(true); hideItem.setTitle(R.string.action_hide_post); } + + mMenu.findItem(R.id.action_report_view_post_detail_activity).setVisible(true); } else { saveItem.setVisible(false); hideItem.setVisible(false); @@ -1264,6 +1270,8 @@ public class ViewPostDetailActivity extends BaseActivity implements FlairBottomS hideItem.setVisible(true); hideItem.setTitle(R.string.action_hide_post); } + + mMenu.findItem(R.id.action_report_view_post_detail_activity).setVisible(true); } else { saveItem.setVisible(false); hideItem.setVisible(false); @@ -1481,6 +1489,11 @@ public class ViewPostDetailActivity extends BaseActivity implements FlairBottomS flairBottomSheetFragment.setArguments(bundle); flairBottomSheetFragment.show(getSupportFragmentManager(), flairBottomSheetFragment.getTag()); return true; + case R.id.action_report_view_post_detail_activity: + Intent intent = new Intent(this, ReportActivity.class); + intent.putExtra(ReportActivity.EXTRA_SUBREDDIT_NAME, mPost.getSubredditName()); + intent.putExtra(ReportActivity.EXTRA_THING_FULLNAME, mPost.getFullName()); + startActivity(intent); case android.R.id.home: onBackPressed(); return true; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java index c474a710..3623fb54 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java @@ -13,7 +13,6 @@ import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.FrameLayout; -import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.RelativeLayout; @@ -1849,6 +1848,8 @@ public class PostRecyclerViewAdapter extends PagedListAdapter { + Post post = getItem(getAdapterPosition()); + if (post != null) { + Intent intent = new Intent(mActivity, ViewVideoActivity.class); + intent.setData(Uri.parse(post.getVideoUrl())); + intent.putExtra(ViewVideoActivity.EXTRA_VIDEO_DOWNLOAD_URL, post.getVideoDownloadUrl()); + intent.putExtra(ViewVideoActivity.EXTRA_SUBREDDIT, post.getSubredditName()); + intent.putExtra(ViewVideoActivity.EXTRA_ID, post.getId()); + intent.putExtra(ViewVideoActivity.EXTRA_POST_TITLE, post.getTitle()); + mActivity.startActivity(intent); + } + }); } void bindVideoUri(Uri videoUri) { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/ReportReasonRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/ReportReasonRecyclerViewAdapter.java new file mode 100644 index 00000000..98db7e3c --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/ReportReasonRecyclerViewAdapter.java @@ -0,0 +1,121 @@ +package ml.docilealligator.infinityforreddit.Adapter; + +import android.content.res.ColorStateList; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CheckBox; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import java.util.ArrayList; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.CustomTheme.CustomThemeWrapper; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.ReportReason; + +public class ReportReasonRecyclerViewAdapter extends RecyclerView.Adapter { + + private ArrayList generalReasons; + private ArrayList rules; + private int primaryTextColor; + private int colorAccent; + + public ReportReasonRecyclerViewAdapter(CustomThemeWrapper customThemeWrapper, ArrayList generalReasons) { + this.generalReasons = generalReasons; + rules = new ArrayList<>(); + primaryTextColor = customThemeWrapper.getPrimaryTextColor(); + colorAccent = customThemeWrapper.getColorAccent(); + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + return new ReasonViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_report_reason, parent, false)); + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + if (holder instanceof ReasonViewHolder) { + ReportReason reportReason; + if (position >= generalReasons.size()) { + reportReason = rules.get(holder.getAdapterPosition() - generalReasons.size()); + } else { + reportReason = generalReasons.get(holder.getAdapterPosition()); + } + ((ReasonViewHolder) holder).reasonTextView.setText(reportReason.getReportReason()); + ((ReasonViewHolder) holder).checkBox.setChecked(reportReason.isSelected()); + } + } + + @Override + public int getItemCount() { + return rules.size() + generalReasons.size(); + } + + public void setRules(ArrayList reportReasons) { + this.rules = reportReasons; + notifyDataSetChanged(); + } + + public ReportReason getSelectedReason() { + for (ReportReason reportReason : rules) { + if (reportReason.isSelected()) { + return reportReason; + } + } + + for (ReportReason reportReason : generalReasons) { + if (reportReason.isSelected()) { + return reportReason; + } + } + + return null; + } + + class ReasonViewHolder extends RecyclerView.ViewHolder { + + @BindView(R.id.reason_text_view_item_report_reason) + TextView reasonTextView; + @BindView(R.id.check_box_item_report_reason) + CheckBox checkBox; + + ReasonViewHolder(@NonNull View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + + reasonTextView.setTextColor(primaryTextColor); + checkBox.setButtonTintList(ColorStateList.valueOf(colorAccent)); + + checkBox.setOnClickListener(view -> { + for (int i = 0; i < generalReasons.size(); i++) { + if (generalReasons.get(i).isSelected()) { + generalReasons.get(i).setSelected(false); + notifyItemChanged(i); + + } + } + + for (int i = 0; i < rules.size(); i++) { + if (rules.get(i).isSelected()) { + rules.get(i).setSelected(false); + notifyItemChanged(i + generalReasons.size()); + } + } + + if (getAdapterPosition() >= generalReasons.size()) { + rules.get(getAdapterPosition() - generalReasons.size()).setSelected(checkBox.isChecked()); + } else { + generalReasons.get(getAdapterPosition()).setSelected(checkBox.isChecked()); + } + }); + + itemView.setOnClickListener(view -> checkBox.performClick()); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java index d8dcc56e..351ab8f8 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java @@ -21,6 +21,7 @@ import ml.docilealligator.infinityforreddit.Activity.PostImageActivity; import ml.docilealligator.infinityforreddit.Activity.PostLinkActivity; import ml.docilealligator.infinityforreddit.Activity.PostTextActivity; import ml.docilealligator.infinityforreddit.Activity.PostVideoActivity; +import ml.docilealligator.infinityforreddit.Activity.ReportActivity; import ml.docilealligator.infinityforreddit.Activity.RulesActivity; import ml.docilealligator.infinityforreddit.Activity.SearchActivity; import ml.docilealligator.infinityforreddit.Activity.SearchResultActivity; @@ -161,4 +162,6 @@ public interface AppComponent { void inject(EditMultiRedditActivity editMultiRedditActivity); void inject(SelectedSubredditsActivity selectedSubredditsActivity); + + void inject(ReportActivity reportActivity); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java index 371e31e9..113e1604 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java @@ -304,4 +304,8 @@ public interface RedditAPI { @GET("/api/multi/multipath/") Call getMultiRedditInfo(@HeaderMap Map headers, @Query("multipath") String multipath); + + @FormUrlEncoded + @POST("/api/report") + Call report(@HeaderMap Map headers, @FieldMap Map params); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ReportReason.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ReportReason.java new file mode 100644 index 00000000..a132a17f --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ReportReason.java @@ -0,0 +1,77 @@ +package ml.docilealligator.infinityforreddit; + +import android.content.Context; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.ArrayList; + +public class ReportReason implements Parcelable { + public static final String REASON_TYPE_RULE_REASON = "rule_reason"; + public static final String REASON_TYPE_REASON = "reason"; + + private String reportReason; + private String reasonType; + private boolean isSelected; + + public ReportReason(String reportReason, String reasonType) { + this.reportReason = reportReason; + this.reasonType = reasonType; + this.isSelected = false; + } + + protected ReportReason(Parcel in) { + reportReason = in.readString(); + reasonType = in.readString(); + isSelected = in.readByte() != 0; + } + + public static final Creator CREATOR = new Creator() { + @Override + public ReportReason createFromParcel(Parcel in) { + return new ReportReason(in); + } + + @Override + public ReportReason[] newArray(int size) { + return new ReportReason[size]; + } + }; + + public String getReportReason() { + return reportReason; + } + + public String getReasonType() { + return reasonType; + } + + public boolean isSelected() { + return isSelected; + } + + public void setSelected(boolean selected) { + isSelected = selected; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int i) { + parcel.writeString(reportReason); + parcel.writeString(reasonType); + parcel.writeByte((byte) (isSelected ? 1 : 0)); + } + + public static ArrayList getGeneralReasons(Context context) { + ArrayList reportReasons = new ArrayList<>(); + reportReasons.add(new ReportReason(context.getString(R.string.report_reason_general_spam), REASON_TYPE_REASON)); + reportReasons.add(new ReportReason(context.getString(R.string.report_reason_general_copyright_issue), REASON_TYPE_REASON)); + reportReasons.add(new ReportReason(context.getString(R.string.report_reason_general_child_pornography), REASON_TYPE_REASON)); + reportReasons.add(new ReportReason(context.getString(R.string.report_reason_general_abusive_content), REASON_TYPE_REASON)); + return reportReasons; + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ReportThing.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ReportThing.java new file mode 100644 index 00000000..3d7febfb --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ReportThing.java @@ -0,0 +1,46 @@ +package ml.docilealligator.infinityforreddit; + +import androidx.annotation.NonNull; + +import java.util.HashMap; +import java.util.Map; + +import ml.docilealligator.infinityforreddit.Utils.RedditUtils; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; + +public class ReportThing { + + public interface ReportThingListener { + void success(); + void failed(); + } + + public static void reportThing(Retrofit oauthRetrofit, String accessToken, String thingFullname, + String subredditName, String reasonType, String reason, + ReportThingListener reportThingListener) { + Map header = RedditUtils.getOAuthHeader(accessToken); + Map params = new HashMap<>(); + params.put(RedditUtils.THING_ID_KEY, thingFullname); + params.put(RedditUtils.SR_NAME_KEY, subredditName); + params.put(reasonType, reason); + + oauthRetrofit.create(RedditAPI.class).report(header, params).enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if (response.isSuccessful()) { + reportThingListener.success(); + } else { + reportThingListener.failed(); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + reportThingListener.failed(); + } + }); + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_fullscreen_white_rounded_18dp.xml b/app/src/main/res/drawable/ic_fullscreen_white_rounded_18dp.xml new file mode 100644 index 00000000..9977b60f --- /dev/null +++ b/app/src/main/res/drawable/ic_fullscreen_white_rounded_18dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/activity_report.xml b/app/src/main/res/layout/activity_report.xml new file mode 100644 index 00000000..845c9ecc --- /dev/null +++ b/app/src/main/res/layout/activity_report.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/exo_autoplay_playback_control_view.xml b/app/src/main/res/layout/exo_autoplay_playback_control_view.xml index 826f6870..a5e128ae 100644 --- a/app/src/main/res/layout/exo_autoplay_playback_control_view.xml +++ b/app/src/main/res/layout/exo_autoplay_playback_control_view.xml @@ -57,8 +57,16 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="8dp" - android:layout_alignParentEnd="true" + android:layout_toStartOf="@id/fullscreen_exo_playback_control_view" android:src="@drawable/ic_mute_white_rounded_18dp" android:visibility="gone" /> + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_report_reason.xml b/app/src/main/res/layout/item_report_reason.xml new file mode 100644 index 00000000..08d6900b --- /dev/null +++ b/app/src/main/res/layout/item_report_reason.xml @@ -0,0 +1,29 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/report_activity.xml b/app/src/main/res/menu/report_activity.xml new file mode 100644 index 00000000..8445d412 --- /dev/null +++ b/app/src/main/res/menu/report_activity.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/view_post_detail_activity.xml b/app/src/main/res/menu/view_post_detail_activity.xml index a9871051..32f83c41 100644 --- a/app/src/main/res/menu/view_post_detail_activity.xml +++ b/app/src/main/res/menu/view_post_detail_activity.xml @@ -74,4 +74,11 @@ android:title="@string/action_edit_flair" app:showAsAction="never" android:visible="false" /> + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2bd237f9..3a8dbdd1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -25,6 +25,7 @@ Theme Preview Edit Multireddit Selected Subreddits + Report Open navigation drawer Close navigation drawer @@ -57,6 +58,7 @@ Delete Multireddit Share Preview + Report Error occurred when parsing the JSON response Error Retrieving the token @@ -702,4 +704,13 @@ %1$d Awards 1 Award + Reported + Report failed + You haven\'t selected a reason + + Spam + Copyright Issue + Child Pornography + Abusive Content + -- cgit v1.2.3 From d444a3a084d82b65e41e15282c11694e7cde7d7a Mon Sep 17 00:00:00 2001 From: Alex Ning Date: Tue, 5 May 2020 13:48:42 +0800 Subject: Reporting posts is now available. --- .../infinityforreddit/Activity/ReportActivity.java | 46 +++++++++- .../infinityforreddit/Activity/RulesActivity.java | 63 +++++++++---- .../Adapter/ReportReasonRecyclerViewAdapter.java | 21 +++-- .../infinityforreddit/FetchRules.java | 101 +++++++++++++++++++++ .../infinityforreddit/ReportReason.java | 23 ++++- .../infinityforreddit/ReportThing.java | 8 ++ .../infinityforreddit/Utils/RedditUtils.java | 2 + .../layout/exo_autoplay_playback_control_view.xml | 2 +- app/src/main/res/values/strings.xml | 9 +- 9 files changed, 240 insertions(+), 35 deletions(-) create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/FetchRules.java diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ReportActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ReportActivity.java index 526be6ef..3092b8c7 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ReportActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ReportActivity.java @@ -14,6 +14,9 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.google.android.material.appbar.AppBarLayout; +import com.google.android.material.snackbar.Snackbar; + +import java.util.ArrayList; import javax.inject.Inject; import javax.inject.Named; @@ -23,11 +26,13 @@ import butterknife.ButterKnife; import ml.docilealligator.infinityforreddit.Adapter.ReportReasonRecyclerViewAdapter; import ml.docilealligator.infinityforreddit.AsyncTask.GetCurrentAccountAsyncTask; import ml.docilealligator.infinityforreddit.CustomTheme.CustomThemeWrapper; +import ml.docilealligator.infinityforreddit.FetchRules; import ml.docilealligator.infinityforreddit.Infinity; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; import ml.docilealligator.infinityforreddit.ReportReason; import ml.docilealligator.infinityforreddit.ReportThing; +import ml.docilealligator.infinityforreddit.Rule; import retrofit2.Retrofit; public class ReportActivity extends BaseActivity { @@ -36,6 +41,8 @@ public class ReportActivity extends BaseActivity { public static final String EXTRA_THING_FULLNAME = "ETF"; private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; private static final String ACCESS_TOKEN_STATE = "ATS"; + private static final String GENERAL_REASONS_STATE = "GRS"; + private static final String RULES_REASON_STATE = "RRS"; @BindView(R.id.coordinator_layout_report_activity) CoordinatorLayout coordinatorLayout; @@ -49,6 +56,9 @@ public class ReportActivity extends BaseActivity { @Named("oauth") Retrofit mOauthRetrofit; @Inject + @Named("no_oauth") + Retrofit mRetrofit; + @Inject @Named("default") SharedPreferences mSharedPreferences; @Inject @@ -59,6 +69,8 @@ public class ReportActivity extends BaseActivity { private String mAccessToken; private String mFullname; private String mSubredditName; + private ArrayList generalReasons; + private ArrayList rulesReasons; private ReportReasonRecyclerViewAdapter mAdapter; @Override @@ -83,9 +95,6 @@ public class ReportActivity extends BaseActivity { mFullname = getIntent().getStringExtra(EXTRA_THING_FULLNAME); mSubredditName = getIntent().getStringExtra(EXTRA_SUBREDDIT_NAME); - mAdapter = new ReportReasonRecyclerViewAdapter(mCustomThemeWrapper, ReportReason.getGeneralReasons(this)); - recyclerView.setLayoutManager(new LinearLayoutManager(this)); - recyclerView.setAdapter(mAdapter); if (savedInstanceState != null) { mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); @@ -94,9 +103,36 @@ public class ReportActivity extends BaseActivity { if (!mNullAccessToken && mAccessToken == null) { getCurrentAccount(); } + + generalReasons = savedInstanceState.getParcelableArrayList(GENERAL_REASONS_STATE); + rulesReasons = savedInstanceState.getParcelableArrayList(RULES_REASON_STATE); } else { getCurrentAccount(); } + + if (generalReasons != null) { + mAdapter = new ReportReasonRecyclerViewAdapter(mCustomThemeWrapper, generalReasons); + } else { + mAdapter = new ReportReasonRecyclerViewAdapter(mCustomThemeWrapper, ReportReason.getGeneralReasons(this)); + } + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + recyclerView.setAdapter(mAdapter); + + if (rulesReasons == null) { + FetchRules.fetchRules(mRetrofit, mSubredditName, new FetchRules.FetchRulesListener() { + @Override + public void success(ArrayList rules) { + mAdapter.setRules(ReportReason.convertRulesToReasons(rules)); + } + + @Override + public void failed() { + Snackbar.make(coordinatorLayout, R.string.error_loading_rules_without_retry, Snackbar.LENGTH_SHORT).show(); + } + }); + } else { + mAdapter.setRules(rulesReasons); + } } private void getCurrentAccount() { @@ -152,6 +188,10 @@ public class ReportActivity extends BaseActivity { super.onSaveInstanceState(outState); outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); outState.putString(ACCESS_TOKEN_STATE, mAccessToken); + if (mAdapter != null) { + outState.putParcelableArrayList(GENERAL_REASONS_STATE, mAdapter.getGeneralReasons()); + outState.putParcelableArrayList(RULES_REASON_STATE, mAdapter.getRules()); + } } @Override diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/RulesActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/RulesActivity.java index 925efd0e..2c5cb05c 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/RulesActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/RulesActivity.java @@ -2,7 +2,6 @@ package ml.docilealligator.infinityforreddit.Activity; import android.content.SharedPreferences; import android.content.res.ColorStateList; -import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.view.MenuItem; @@ -22,9 +21,6 @@ import com.google.android.material.appbar.AppBarLayout; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; import java.util.ArrayList; @@ -36,15 +32,10 @@ import butterknife.ButterKnife; import ml.docilealligator.infinityforreddit.Adapter.RulesRecyclerViewAdapter; import ml.docilealligator.infinityforreddit.CustomTheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.FetchRules; import ml.docilealligator.infinityforreddit.Infinity; import ml.docilealligator.infinityforreddit.R; -import ml.docilealligator.infinityforreddit.RedditAPI; import ml.docilealligator.infinityforreddit.Rule; -import ml.docilealligator.infinityforreddit.Utils.JSONUtils; -import ml.docilealligator.infinityforreddit.Utils.Utils; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; import retrofit2.Retrofit; public class RulesActivity extends BaseActivity { @@ -116,7 +107,26 @@ public class RulesActivity extends BaseActivity { mAdapter = new RulesRecyclerViewAdapter(this, mCustomThemeWrapper); recyclerView.setAdapter(mAdapter); - fetchRules(); + //fetchRules(); + + FetchRules.fetchRules(mRetrofit, mSubredditName, new FetchRules.FetchRulesListener() { + @Override + public void success(ArrayList rules) { + progressBar.setVisibility(View.GONE); + if (rules == null || rules.size() == 0) { + errorTextView.setVisibility(View.VISIBLE); + errorTextView.setText(R.string.no_rule); + errorTextView.setOnClickListener(view -> { + }); + } + mAdapter.changeDataset(rules); + } + + @Override + public void failed() { + displayError(); + } + }); } @Override @@ -137,7 +147,7 @@ public class RulesActivity extends BaseActivity { errorTextView.setTextColor(mCustomThemeWrapper.getSecondaryTextColor()); } - private void fetchRules() { + /*private void fetchRules() { progressBar.setVisibility(View.VISIBLE); errorTextView.setVisibility(View.GONE); @@ -175,13 +185,34 @@ public class RulesActivity extends BaseActivity { displayError(); } }); - } + }*/ private void displayError() { progressBar.setVisibility(View.GONE); errorTextView.setVisibility(View.VISIBLE); errorTextView.setText(R.string.error_loading_rules); - errorTextView.setOnClickListener(view -> fetchRules()); + errorTextView.setOnClickListener(view -> { + progressBar.setVisibility(View.VISIBLE); + errorTextView.setVisibility(View.GONE); + FetchRules.fetchRules(mRetrofit, mSubredditName, new FetchRules.FetchRulesListener() { + @Override + public void success(ArrayList rules) { + progressBar.setVisibility(View.GONE); + if (rules == null || rules.size() == 0) { + errorTextView.setVisibility(View.VISIBLE); + errorTextView.setText(R.string.no_rule); + errorTextView.setOnClickListener(view -> { + }); + } + mAdapter.changeDataset(rules); + } + + @Override + public void failed() { + displayError(); + } + }); + }); } @Override @@ -205,7 +236,7 @@ public class RulesActivity extends BaseActivity { finish(); } - private static class ParseRulesAsyncTask extends AsyncTask, ArrayList> { + /*private static class ParseRulesAsyncTask extends AsyncTask, ArrayList> { private String response; private ParseRulesAsyncTaskListener parseRulesAsyncTaskListener; @@ -248,5 +279,5 @@ public class RulesActivity extends BaseActivity { void parseFailed(); } - } + }*/ } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/ReportReasonRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/ReportReasonRecyclerViewAdapter.java index 98db7e3c..8bbc3991 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/ReportReasonRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/ReportReasonRecyclerViewAdapter.java @@ -27,7 +27,6 @@ public class ReportReasonRecyclerViewAdapter extends RecyclerView.Adapter generalReasons) { this.generalReasons = generalReasons; - rules = new ArrayList<>(); primaryTextColor = customThemeWrapper.getPrimaryTextColor(); colorAccent = customThemeWrapper.getColorAccent(); } @@ -54,7 +53,7 @@ public class ReportReasonRecyclerViewAdapter extends RecyclerView.Adapter reportReasons) { @@ -78,6 +77,14 @@ public class ReportReasonRecyclerViewAdapter extends RecyclerView.Adapter getGeneralReasons() { + return generalReasons; + } + + public ArrayList getRules() { + return rules; + } + class ReasonViewHolder extends RecyclerView.ViewHolder { @BindView(R.id.reason_text_view_item_report_reason) @@ -101,10 +108,12 @@ public class ReportReasonRecyclerViewAdapter extends RecyclerView.Adapter rules); + void failed(); + } + + public static void fetchRules(Retrofit retrofit, String subredditName, FetchRulesListener fetchRulesListener) { + + RedditAPI api = retrofit.create(RedditAPI.class); + Call rulesCall = api.getRules(subredditName); + rulesCall.enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if (response.isSuccessful()) { + new ParseRulesAsyncTask(response.body(), new ParseRulesAsyncTask.ParseRulesAsyncTaskListener() { + @Override + public void parseSuccessful(ArrayList rules) { + fetchRulesListener.success(rules); + } + + @Override + public void parseFailed() { + fetchRulesListener.failed(); + } + }).execute(); + } else { + fetchRulesListener.failed(); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + fetchRulesListener.failed(); + } + }); + } + + private static class ParseRulesAsyncTask extends AsyncTask, ArrayList> { + private String response; + private ParseRulesAsyncTask.ParseRulesAsyncTaskListener parseRulesAsyncTaskListener; + + ParseRulesAsyncTask(String response, ParseRulesAsyncTask.ParseRulesAsyncTaskListener parseRulesAsyncTaskListener) { + this.response = response; + this.parseRulesAsyncTaskListener = parseRulesAsyncTaskListener; + } + + @Override + protected ArrayList doInBackground(Void... voids) { + try { + JSONArray rulesArray = new JSONObject(response).getJSONArray(JSONUtils.RULES_KEY); + ArrayList rules = new ArrayList<>(); + for (int i = 0; i < rulesArray.length(); i++) { + String shortName = rulesArray.getJSONObject(i).getString(JSONUtils.SHORT_NAME_KEY); + String description = null; + if (rulesArray.getJSONObject(i).has(JSONUtils.DESCRIPTION_KEY)) { + description = Utils.modifyMarkdown(rulesArray.getJSONObject(i).getString(JSONUtils.DESCRIPTION_KEY)); + } + rules.add(new Rule(shortName, description)); + } + return rules; + } catch (JSONException e) { + e.printStackTrace(); + } + return null; + } + + @Override + protected void onPostExecute(ArrayList rules) { + if (rules != null) { + parseRulesAsyncTaskListener.parseSuccessful(rules); + } else { + parseRulesAsyncTaskListener.parseFailed(); + } + } + + interface ParseRulesAsyncTaskListener { + void parseSuccessful(ArrayList rules); + + void parseFailed(); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ReportReason.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ReportReason.java index a132a17f..cedda1d8 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ReportReason.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ReportReason.java @@ -7,8 +7,12 @@ import android.os.Parcelable; import java.util.ArrayList; public class ReportReason implements Parcelable { + public static final String REASON_TYPE_SITE_REASON = "site_reason"; public static final String REASON_TYPE_RULE_REASON = "rule_reason"; - public static final String REASON_TYPE_REASON = "reason"; + public static final String REASON_TYPE_OTHER_REASON = "other_reason"; + public static final String REASON_SITE_REASON_SELECTED = "site_reason_selected"; + public static final String REASON_RULE_REASON_SELECTED = "rule_reason_selected"; + public static final String REASON_OTHER = "other"; private String reportReason; private String reasonType; @@ -68,10 +72,19 @@ public class ReportReason implements Parcelable { public static ArrayList getGeneralReasons(Context context) { ArrayList reportReasons = new ArrayList<>(); - reportReasons.add(new ReportReason(context.getString(R.string.report_reason_general_spam), REASON_TYPE_REASON)); - reportReasons.add(new ReportReason(context.getString(R.string.report_reason_general_copyright_issue), REASON_TYPE_REASON)); - reportReasons.add(new ReportReason(context.getString(R.string.report_reason_general_child_pornography), REASON_TYPE_REASON)); - reportReasons.add(new ReportReason(context.getString(R.string.report_reason_general_abusive_content), REASON_TYPE_REASON)); + reportReasons.add(new ReportReason(context.getString(R.string.report_reason_general_spam), REASON_TYPE_SITE_REASON)); + reportReasons.add(new ReportReason(context.getString(R.string.report_reason_general_copyright_issue), REASON_TYPE_SITE_REASON)); + reportReasons.add(new ReportReason(context.getString(R.string.report_reason_general_child_pornography), REASON_TYPE_SITE_REASON)); + reportReasons.add(new ReportReason(context.getString(R.string.report_reason_general_abusive_content), REASON_TYPE_SITE_REASON)); + return reportReasons; + } + + public static ArrayList convertRulesToReasons(ArrayList rules) { + ArrayList reportReasons = new ArrayList<>(); + for (Rule r : rules) { + reportReasons.add(new ReportReason(r.getShortName(), REASON_TYPE_RULE_REASON)); + } + return reportReasons; } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ReportThing.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ReportThing.java index 3d7febfb..8a617179 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ReportThing.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ReportThing.java @@ -26,6 +26,14 @@ public class ReportThing { params.put(RedditUtils.THING_ID_KEY, thingFullname); params.put(RedditUtils.SR_NAME_KEY, subredditName); params.put(reasonType, reason); + if (reasonType.equals(ReportReason.REASON_TYPE_SITE_REASON)) { + params.put(RedditUtils.REASON_KEY, ReportReason.REASON_SITE_REASON_SELECTED); + } else if (reasonType.equals(ReportReason.REASON_TYPE_RULE_REASON)) { + params.put(RedditUtils.REASON_KEY, ReportReason.REASON_RULE_REASON_SELECTED); + } else { + params.put(RedditUtils.REASON_KEY, ReportReason.REASON_OTHER); + } + params.put(RedditUtils.API_TYPE_KEY, RedditUtils.API_TYPE_JSON); oauthRetrofit.create(RedditAPI.class).report(header, params).enqueue(new Callback() { @Override diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/RedditUtils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/RedditUtils.java index 2e7c93c8..b42cbff1 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/RedditUtils.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/RedditUtils.java @@ -84,6 +84,8 @@ public class RedditUtils { public static final String MULTIPATH_KEY = "multipath"; public static final String MODEL_KEY = "model"; + public static final String REASON_KEY = "reason"; + public static Map getHttpBasicAuthHeader() { Map params = new HashMap<>(); String credentials = String.format("%s:%s", RedditUtils.CLIENT_ID, ""); diff --git a/app/src/main/res/layout/exo_autoplay_playback_control_view.xml b/app/src/main/res/layout/exo_autoplay_playback_control_view.xml index a5e128ae..7280717b 100644 --- a/app/src/main/res/layout/exo_autoplay_playback_control_view.xml +++ b/app/src/main/res/layout/exo_autoplay_playback_control_view.xml @@ -3,7 +3,7 @@ android:id="@+id/linear_layout_exo_playback_control_view" android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingStart="8dp" + android:paddingStart="16dp" android:paddingEnd="8dp" android:layout_gravity="bottom"> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3a8dbdd1..e39cd2cf 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -198,6 +198,7 @@ No rule Error loading rules.\nTap to retry. + Error Loading Rules Search in All subreddits @@ -708,9 +709,9 @@ Report failed You haven\'t selected a reason - Spam - Copyright Issue - Child Pornography - Abusive Content + It Is Spam + It Contains Copyright Issue + It Contains Child Pornography + It Contains Abusive Content -- cgit v1.2.3 From 893c8a20769684e2d4493945aa69059e10a5f7e2 Mon Sep 17 00:00:00 2001 From: Alex Ning Date: Tue, 5 May 2020 14:30:46 +0800 Subject: Reporting comments is now available. --- .../infinityforreddit/Activity/ReportActivity.java | 1 + .../Fragment/CommentMoreBottomSheetFragment.java | 12 ++++++++++++ app/src/main/res/drawable/ic_report_black_24dp.xml | 15 +++++++++++++++ .../res/layout/fragment_comment_more_bottom_sheet.xml | 18 ++++++++++++++++++ app/src/main/res/values/strings.xml | 2 ++ 5 files changed, 48 insertions(+) create mode 100644 app/src/main/res/drawable/ic_report_black_24dp.xml diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ReportActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ReportActivity.java index 3092b8c7..4e3a0738 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ReportActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ReportActivity.java @@ -161,6 +161,7 @@ public class ReportActivity extends BaseActivity { case R.id.action_send_report_activity: ReportReason reportReason = mAdapter.getSelectedReason(); if (reportReason != null) { + Toast.makeText(ReportActivity.this, R.string.reporting, Toast.LENGTH_SHORT).show(); ReportThing.reportThing(mOauthRetrofit, mAccessToken, mFullname, mSubredditName, reportReason.getReasonType(), reportReason.getReportReason(), new ReportThing.ReportThingListener() { @Override diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/CommentMoreBottomSheetFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/CommentMoreBottomSheetFragment.java index d339b5f6..fd97f1d4 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/CommentMoreBottomSheetFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/CommentMoreBottomSheetFragment.java @@ -22,6 +22,7 @@ import com.deishelon.roundedbottomsheet.RoundedBottomSheetDialogFragment; import butterknife.BindView; import butterknife.ButterKnife; import ml.docilealligator.infinityforreddit.Activity.EditCommentActivity; +import ml.docilealligator.infinityforreddit.Activity.ReportActivity; import ml.docilealligator.infinityforreddit.Activity.ViewPostDetailActivity; import ml.docilealligator.infinityforreddit.Activity.ViewUserDetailActivity; import ml.docilealligator.infinityforreddit.CommentData; @@ -44,6 +45,8 @@ public class CommentMoreBottomSheetFragment extends RoundedBottomSheetDialogFrag TextView shareTextView; @BindView(R.id.copy_text_view_comment_more_bottom_sheet_fragment) TextView copyTextView; + @BindView(R.id.report_view_comment_more_bottom_sheet_fragment) + TextView reportTextView; private AppCompatActivity activity; public CommentMoreBottomSheetFragment() { // Required empty public constructor @@ -119,6 +122,15 @@ public class CommentMoreBottomSheetFragment extends RoundedBottomSheetDialogFrag copyTextBottomSheetFragment.show(activity.getSupportFragmentManager(), copyTextBottomSheetFragment.getTag()); }); + reportTextView.setOnClickListener(view -> { + Intent intent = new Intent(activity, ReportActivity.class); + intent.putExtra(ReportActivity.EXTRA_SUBREDDIT_NAME, commentData.getSubredditName()); + intent.putExtra(ReportActivity.EXTRA_THING_FULLNAME, commentData.getFullName()); + activity.startActivity(intent); + + dismiss(); + }); + return rootView; } diff --git a/app/src/main/res/drawable/ic_report_black_24dp.xml b/app/src/main/res/drawable/ic_report_black_24dp.xml new file mode 100644 index 00000000..6e07b06d --- /dev/null +++ b/app/src/main/res/drawable/ic_report_black_24dp.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/layout/fragment_comment_more_bottom_sheet.xml b/app/src/main/res/layout/fragment_comment_more_bottom_sheet.xml index d60fe273..ddd3e572 100644 --- a/app/src/main/res/layout/fragment_comment_more_bottom_sheet.xml +++ b/app/src/main/res/layout/fragment_comment_more_bottom_sheet.xml @@ -81,6 +81,24 @@ android:textColor="?attr/primaryTextColor" android:textSize="?attr/font_default" /> + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e39cd2cf..c12d7105 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -705,6 +705,8 @@ %1$d Awards 1 Award + Report + Reporting Reported Report failed You haven\'t selected a reason -- cgit v1.2.3 From eefc8e869d74721ffd41bd7295ae88228a7cca1e Mon Sep 17 00:00:00 2001 From: Alex Ning Date: Tue, 5 May 2020 15:59:59 +0800 Subject: Optimize CommentAndPostRecyclerViewAdapter. --- .../Adapter/CommentAndPostRecyclerViewAdapter.java | 543 +++++++++++---------- 1 file changed, 281 insertions(+), 262 deletions(-) diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentAndPostRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentAndPostRecyclerViewAdapter.java index c29f0940..eb2ba7ae 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentAndPostRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentAndPostRecyclerViewAdapter.java @@ -834,7 +834,6 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter ((CommentViewHolder) holder).authorTextView.performClick()); } else if (comment.getAuthorFlair() != null && !comment.getAuthorFlair().equals("")) { ((CommentViewHolder) holder).authorFlairTextView.setVisibility(View.VISIBLE); ((CommentViewHolder) holder).authorFlairTextView.setText(comment.getAuthorFlair()); @@ -924,39 +923,6 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter { - if (((CommentViewHolder) holder).bottomConstraintLayout.getLayoutParams().height == 0) { - ((CommentViewHolder) holder).bottomConstraintLayout.getLayoutParams().height = LinearLayout.LayoutParams.WRAP_CONTENT; - ((CommentViewHolder) holder).topScoreTextView.setVisibility(View.GONE); - ((ViewPostDetailActivity) mActivity).delayTransition(); - } else { - ((ViewPostDetailActivity) mActivity).delayTransition(); - ((CommentViewHolder) holder).bottomConstraintLayout.getLayoutParams().height = 0; - ((CommentViewHolder) holder).topScoreTextView.setVisibility(View.VISIBLE); - } - }; - ((CommentViewHolder) holder).linearLayout.setOnClickListener(hideToolbarOnClickListener); - ((CommentViewHolder) holder).commentMarkdownView.setOnClickListener(hideToolbarOnClickListener); - ((CommentViewHolder) holder).commentTimeTextView.setOnClickListener(hideToolbarOnClickListener); - } - - ((CommentViewHolder) holder).moreButton.setOnClickListener(view -> { - Bundle bundle = new Bundle(); - if (!mPost.isArchived() && !mPost.isLocked() && comment.getAuthor().equals(mAccountName)) { - bundle.putString(CommentMoreBottomSheetFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - } - bundle.putParcelable(CommentMoreBottomSheetFragment.EXTRA_COMMENT, comment); - if (mIsSingleCommentThreadMode) { - bundle.putInt(CommentMoreBottomSheetFragment.EXTRA_POSITION, holder.getAdapterPosition() - 2); - } else { - bundle.putInt(CommentMoreBottomSheetFragment.EXTRA_POSITION, holder.getAdapterPosition() - 1); - } - CommentMoreBottomSheetFragment commentMoreBottomSheetFragment = new CommentMoreBottomSheetFragment(); - commentMoreBottomSheetFragment.setArguments(bundle); - commentMoreBottomSheetFragment.show(mActivity.getSupportFragmentManager(), commentMoreBottomSheetFragment.getTag()); - }); - if (comment.hasReply()) { if (comment.isExpanded()) { ((CommentViewHolder) holder).expandButton.setImageResource(R.drawable.ic_expand_less_grey_24dp); @@ -997,239 +963,11 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter { - if (mAccessToken == null) { - Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); - return; - } - - if (mPost.isArchived()) { - Toast.makeText(mActivity, R.string.archived_post_reply_unavailable, Toast.LENGTH_SHORT).show(); - return; - } - - if (mPost.isLocked()) { - Toast.makeText(mActivity, R.string.locked_post_reply_unavailable, Toast.LENGTH_SHORT).show(); - return; - } - - Intent intent = new Intent(mActivity, CommentActivity.class); - intent.putExtra(CommentActivity.EXTRA_PARENT_DEPTH_KEY, comment.getDepth() + 1); - intent.putExtra(CommentActivity.EXTRA_COMMENT_PARENT_TEXT_KEY, comment.getCommentMarkdown()); - intent.putExtra(CommentActivity.EXTRA_PARENT_FULLNAME_KEY, comment.getFullName()); - intent.putExtra(CommentActivity.EXTRA_IS_REPLYING_KEY, true); - - int parentPosition = mIsSingleCommentThreadMode ? holder.getAdapterPosition() - 2 : holder.getAdapterPosition() - 1; - intent.putExtra(CommentActivity.EXTRA_PARENT_POSITION_KEY, parentPosition); - mActivity.startActivityForResult(intent, CommentActivity.WRITE_COMMENT_REQUEST_CODE); - }); - - ((CommentViewHolder) holder).upvoteButton.setOnClickListener(view -> { - if (mPost.isArchived()) { - Toast.makeText(mActivity, R.string.archived_post_vote_unavailable, Toast.LENGTH_SHORT).show(); - return; - } - - if (mAccessToken == null) { - Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); - return; - } - - int previousVoteType = comment.getVoteType(); - String newVoteType; - - ((CommentViewHolder) holder).downvoteButton.setColorFilter(mCommentIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); - - if (previousVoteType != CommentData.VOTE_TYPE_UPVOTE) { - //Not upvoted before - comment.setVoteType(CommentData.VOTE_TYPE_UPVOTE); - newVoteType = RedditUtils.DIR_UPVOTE; - ((CommentViewHolder) holder).upvoteButton.setColorFilter(mUpvotedColor, android.graphics.PorterDuff.Mode.SRC_IN); - ((CommentViewHolder) holder).scoreTextView.setTextColor(mUpvotedColor); - } else { - //Upvoted before - comment.setVoteType(CommentData.VOTE_TYPE_NO_VOTE); - newVoteType = RedditUtils.DIR_UNVOTE; - ((CommentViewHolder) holder).upvoteButton.setColorFilter(mCommentIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); - ((CommentViewHolder) holder).scoreTextView.setTextColor(mCommentIconAndInfoColor); - } - - ((CommentViewHolder) holder).scoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, - comment.getScore() + comment.getVoteType())); - ((CommentViewHolder) holder).topScoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, - comment.getScore() + comment.getVoteType()) + " pts"); - - VoteThing.voteThing(mActivity, mOauthRetrofit, mAccessToken, new VoteThing.VoteThingListener() { - @Override - public void onVoteThingSuccess(int position) { - if (newVoteType.equals(RedditUtils.DIR_UPVOTE)) { - comment.setVoteType(CommentData.VOTE_TYPE_UPVOTE); - ((CommentViewHolder) holder).upvoteButton.setColorFilter(mUpvotedColor, android.graphics.PorterDuff.Mode.SRC_IN); - ((CommentViewHolder) holder).scoreTextView.setTextColor(mUpvotedColor); - } else { - comment.setVoteType(CommentData.VOTE_TYPE_NO_VOTE); - ((CommentViewHolder) holder).upvoteButton.setColorFilter(mCommentIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); - ((CommentViewHolder) holder).scoreTextView.setTextColor(mCommentIconAndInfoColor); - } - - ((CommentViewHolder) holder).downvoteButton.setColorFilter(mCommentIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); - ((CommentViewHolder) holder).scoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, - comment.getScore() + comment.getVoteType())); - ((CommentViewHolder) holder).topScoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, - comment.getScore() + comment.getVoteType()) + " pts"); - } - - @Override - public void onVoteThingFail(int position) { - } - }, comment.getFullName(), newVoteType, holder.getAdapterPosition()); - }); - - ((CommentViewHolder) holder).downvoteButton.setOnClickListener(view -> { - if (mPost.isArchived()) { - Toast.makeText(mActivity, R.string.archived_post_vote_unavailable, Toast.LENGTH_SHORT).show(); - return; - } - - if (mAccessToken == null) { - Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); - return; - } - - int previousVoteType = comment.getVoteType(); - String newVoteType; - - ((CommentViewHolder) holder).upvoteButton.setColorFilter(mCommentIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); - - if (previousVoteType != CommentData.VOTE_TYPE_DOWNVOTE) { - //Not downvoted before - comment.setVoteType(CommentData.VOTE_TYPE_DOWNVOTE); - newVoteType = RedditUtils.DIR_DOWNVOTE; - ((CommentViewHolder) holder).downvoteButton.setColorFilter(mDownvotedColor, android.graphics.PorterDuff.Mode.SRC_IN); - ((CommentViewHolder) holder).scoreTextView.setTextColor(mDownvotedColor); - } else { - //Downvoted before - comment.setVoteType(CommentData.VOTE_TYPE_NO_VOTE); - newVoteType = RedditUtils.DIR_UNVOTE; - ((CommentViewHolder) holder).downvoteButton.setColorFilter(mCommentIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); - ((CommentViewHolder) holder).scoreTextView.setTextColor(mCommentIconAndInfoColor); - } - - ((CommentViewHolder) holder).scoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, - comment.getScore() + comment.getVoteType())); - ((CommentViewHolder) holder).topScoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, - comment.getScore() + comment.getVoteType()) + " pts"); - - VoteThing.voteThing(mActivity, mOauthRetrofit, mAccessToken, new VoteThing.VoteThingListener() { - @Override - public void onVoteThingSuccess(int position1) { - if (newVoteType.equals(RedditUtils.DIR_DOWNVOTE)) { - comment.setVoteType(CommentData.VOTE_TYPE_DOWNVOTE); - ((CommentViewHolder) holder).downvoteButton.setColorFilter(mDownvotedColor, android.graphics.PorterDuff.Mode.SRC_IN); - ((CommentViewHolder) holder).scoreTextView.setTextColor(mDownvotedColor); - } else { - comment.setVoteType(CommentData.VOTE_TYPE_NO_VOTE); - ((CommentViewHolder) holder).downvoteButton.setColorFilter(mCommentIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); - ((CommentViewHolder) holder).scoreTextView.setTextColor(mCommentIconAndInfoColor); - } - - ((CommentViewHolder) holder).upvoteButton.setColorFilter(mCommentIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); - ((CommentViewHolder) holder).scoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, - comment.getScore() + comment.getVoteType())); - ((CommentViewHolder) holder).topScoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, - comment.getScore() + comment.getVoteType()) + " pts"); - } - - @Override - public void onVoteThingFail(int position1) { - } - }, comment.getFullName(), newVoteType, holder.getAdapterPosition()); - }); - if (comment.isSaved()) { ((CommentViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_grey_24dp); } else { ((CommentViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_border_grey_24dp); } - - ((CommentViewHolder) holder).saveButton.setOnClickListener(view -> { - if (comment.isSaved()) { - comment.setSaved(false); - SaveThing.unsaveThing(mOauthRetrofit, mAccessToken, comment.getFullName(), new SaveThing.SaveThingListener() { - @Override - public void success() { - comment.setSaved(false); - ((CommentViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_border_grey_24dp); - Toast.makeText(mActivity, R.string.comment_unsaved_success, Toast.LENGTH_SHORT).show(); - } - - @Override - public void failed() { - comment.setSaved(true); - ((CommentViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_grey_24dp); - Toast.makeText(mActivity, R.string.comment_unsaved_failed, Toast.LENGTH_SHORT).show(); - } - }); - } else { - comment.setSaved(true); - SaveThing.saveThing(mOauthRetrofit, mAccessToken, comment.getFullName(), new SaveThing.SaveThingListener() { - @Override - public void success() { - comment.setSaved(true); - ((CommentViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_grey_24dp); - Toast.makeText(mActivity, R.string.comment_saved_success, Toast.LENGTH_SHORT).show(); - } - - @Override - public void failed() { - comment.setSaved(false); - ((CommentViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_border_grey_24dp); - Toast.makeText(mActivity, R.string.comment_saved_failed, Toast.LENGTH_SHORT).show(); - } - }); - } - }); - - ((CommentViewHolder) holder).authorTextView.setOnClickListener(view -> { - Intent intent = new Intent(mActivity, ViewUserDetailActivity.class); - intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, comment.getAuthor()); - mActivity.startActivity(intent); - }); - - ((CommentViewHolder) holder).expandButton.setOnClickListener(view -> { - if (((CommentViewHolder) holder).expandButton.getVisibility() == View.VISIBLE) { - int commentPosition = mIsSingleCommentThreadMode ? holder.getAdapterPosition() - 2 : holder.getAdapterPosition() - 1; - if(commentPosition >= 0 && commentPosition < mVisibleComments.size()) { - if (mVisibleComments.get(commentPosition).isExpanded()) { - collapseChildren(commentPosition); - ((CommentViewHolder) holder).expandButton.setImageResource(R.drawable.ic_expand_more_grey_24dp); - } else { - comment.setExpanded(true); - ArrayList newList = new ArrayList<>(); - expandChildren(mVisibleComments.get(commentPosition).getChildren(), newList, 0); - mVisibleComments.get(commentPosition).setExpanded(true); - mVisibleComments.addAll(commentPosition + 1, newList); - - if (mIsSingleCommentThreadMode) { - notifyItemRangeInserted(commentPosition + 3, newList.size()); - } else { - notifyItemRangeInserted(commentPosition + 2, newList.size()); - } - ((CommentViewHolder) holder).expandButton.setImageResource(R.drawable.ic_expand_less_grey_24dp); - } - } - } - }); - - ((CommentViewHolder) holder).commentMarkdownView.setOnLongClickListener(view -> { - ((CommentViewHolder) holder).expandButton.performClick(); - return true; - }); - - ((CommentViewHolder) holder).itemView.setOnLongClickListener(view -> { - ((CommentViewHolder) holder).expandButton.performClick(); - return true; - }); } else if (holder instanceof LoadMoreChildCommentsViewHolder) { CommentData placeholder; placeholder = mIsSingleCommentThreadMode ? mVisibleComments.get(holder.getAdapterPosition() - 2) @@ -2208,6 +1946,287 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter authorTextView.performClick()); + + View.OnClickListener hideToolbarOnClickListener = view -> { + if (mCommentToolbarHideOnClick) { + if (bottomConstraintLayout.getLayoutParams().height == 0) { + bottomConstraintLayout.getLayoutParams().height = LinearLayout.LayoutParams.WRAP_CONTENT; + topScoreTextView.setVisibility(View.GONE); + ((ViewPostDetailActivity) mActivity).delayTransition(); + } else { + ((ViewPostDetailActivity) mActivity).delayTransition(); + bottomConstraintLayout.getLayoutParams().height = 0; + topScoreTextView.setVisibility(View.VISIBLE); + } + } + }; + linearLayout.setOnClickListener(hideToolbarOnClickListener); + commentMarkdownView.setOnClickListener(hideToolbarOnClickListener); + commentTimeTextView.setOnClickListener(hideToolbarOnClickListener); + + moreButton.setOnClickListener(view -> { + CommentData comment = getCurrentComment(); + Bundle bundle = new Bundle(); + if (!mPost.isArchived() && !mPost.isLocked() && comment.getAuthor().equals(mAccountName)) { + bundle.putString(CommentMoreBottomSheetFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + } + bundle.putParcelable(CommentMoreBottomSheetFragment.EXTRA_COMMENT, comment); + if (mIsSingleCommentThreadMode) { + bundle.putInt(CommentMoreBottomSheetFragment.EXTRA_POSITION, getAdapterPosition() - 2); + } else { + bundle.putInt(CommentMoreBottomSheetFragment.EXTRA_POSITION, getAdapterPosition() - 1); + } + CommentMoreBottomSheetFragment commentMoreBottomSheetFragment = new CommentMoreBottomSheetFragment(); + commentMoreBottomSheetFragment.setArguments(bundle); + commentMoreBottomSheetFragment.show(mActivity.getSupportFragmentManager(), commentMoreBottomSheetFragment.getTag()); + }); + + replyButton.setOnClickListener(view -> { + if (mAccessToken == null) { + Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); + return; + } + + if (mPost.isArchived()) { + Toast.makeText(mActivity, R.string.archived_post_reply_unavailable, Toast.LENGTH_SHORT).show(); + return; + } + + if (mPost.isLocked()) { + Toast.makeText(mActivity, R.string.locked_post_reply_unavailable, Toast.LENGTH_SHORT).show(); + return; + } + + CommentData comment = getCurrentComment(); + + Intent intent = new Intent(mActivity, CommentActivity.class); + intent.putExtra(CommentActivity.EXTRA_PARENT_DEPTH_KEY, comment.getDepth() + 1); + intent.putExtra(CommentActivity.EXTRA_COMMENT_PARENT_TEXT_KEY, comment.getCommentMarkdown()); + intent.putExtra(CommentActivity.EXTRA_PARENT_FULLNAME_KEY, comment.getFullName()); + intent.putExtra(CommentActivity.EXTRA_IS_REPLYING_KEY, true); + + int parentPosition = mIsSingleCommentThreadMode ? getAdapterPosition() - 2 : getAdapterPosition() - 1; + intent.putExtra(CommentActivity.EXTRA_PARENT_POSITION_KEY, parentPosition); + mActivity.startActivityForResult(intent, CommentActivity.WRITE_COMMENT_REQUEST_CODE); + }); + + upvoteButton.setOnClickListener(view -> { + if (mPost.isArchived()) { + Toast.makeText(mActivity, R.string.archived_post_vote_unavailable, Toast.LENGTH_SHORT).show(); + return; + } + + if (mAccessToken == null) { + Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); + return; + } + + CommentData comment = getCurrentComment(); + int previousVoteType = comment.getVoteType(); + String newVoteType; + + downvoteButton.setColorFilter(mCommentIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); + + if (previousVoteType != CommentData.VOTE_TYPE_UPVOTE) { + //Not upvoted before + comment.setVoteType(CommentData.VOTE_TYPE_UPVOTE); + newVoteType = RedditUtils.DIR_UPVOTE; + upvoteButton.setColorFilter(mUpvotedColor, android.graphics.PorterDuff.Mode.SRC_IN); + scoreTextView.setTextColor(mUpvotedColor); + } else { + //Upvoted before + comment.setVoteType(CommentData.VOTE_TYPE_NO_VOTE); + newVoteType = RedditUtils.DIR_UNVOTE; + upvoteButton.setColorFilter(mCommentIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); + scoreTextView.setTextColor(mCommentIconAndInfoColor); + } + + scoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, + comment.getScore() + comment.getVoteType())); + topScoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, + comment.getScore() + comment.getVoteType()) + " pts"); + + VoteThing.voteThing(mActivity, mOauthRetrofit, mAccessToken, new VoteThing.VoteThingListener() { + @Override + public void onVoteThingSuccess(int position) { + if (newVoteType.equals(RedditUtils.DIR_UPVOTE)) { + comment.setVoteType(CommentData.VOTE_TYPE_UPVOTE); + upvoteButton.setColorFilter(mUpvotedColor, android.graphics.PorterDuff.Mode.SRC_IN); + scoreTextView.setTextColor(mUpvotedColor); + } else { + comment.setVoteType(CommentData.VOTE_TYPE_NO_VOTE); + upvoteButton.setColorFilter(mCommentIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); + scoreTextView.setTextColor(mCommentIconAndInfoColor); + } + + downvoteButton.setColorFilter(mCommentIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); + scoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, + comment.getScore() + comment.getVoteType())); + topScoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, + comment.getScore() + comment.getVoteType()) + " pts"); + } + + @Override + public void onVoteThingFail(int position) { + } + }, comment.getFullName(), newVoteType, getAdapterPosition()); + }); + + downvoteButton.setOnClickListener(view -> { + if (mPost.isArchived()) { + Toast.makeText(mActivity, R.string.archived_post_vote_unavailable, Toast.LENGTH_SHORT).show(); + return; + } + + if (mAccessToken == null) { + Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); + return; + } + + CommentData comment = getCurrentComment(); + int previousVoteType = comment.getVoteType(); + String newVoteType; + + upvoteButton.setColorFilter(mCommentIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); + + if (previousVoteType != CommentData.VOTE_TYPE_DOWNVOTE) { + //Not downvoted before + comment.setVoteType(CommentData.VOTE_TYPE_DOWNVOTE); + newVoteType = RedditUtils.DIR_DOWNVOTE; + downvoteButton.setColorFilter(mDownvotedColor, android.graphics.PorterDuff.Mode.SRC_IN); + scoreTextView.setTextColor(mDownvotedColor); + } else { + //Downvoted before + comment.setVoteType(CommentData.VOTE_TYPE_NO_VOTE); + newVoteType = RedditUtils.DIR_UNVOTE; + downvoteButton.setColorFilter(mCommentIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); + scoreTextView.setTextColor(mCommentIconAndInfoColor); + } + + scoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, + comment.getScore() + comment.getVoteType())); + topScoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, + comment.getScore() + comment.getVoteType()) + " pts"); + + VoteThing.voteThing(mActivity, mOauthRetrofit, mAccessToken, new VoteThing.VoteThingListener() { + @Override + public void onVoteThingSuccess(int position1) { + if (newVoteType.equals(RedditUtils.DIR_DOWNVOTE)) { + comment.setVoteType(CommentData.VOTE_TYPE_DOWNVOTE); + downvoteButton.setColorFilter(mDownvotedColor, android.graphics.PorterDuff.Mode.SRC_IN); + scoreTextView.setTextColor(mDownvotedColor); + } else { + comment.setVoteType(CommentData.VOTE_TYPE_NO_VOTE); + downvoteButton.setColorFilter(mCommentIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); + scoreTextView.setTextColor(mCommentIconAndInfoColor); + } + + upvoteButton.setColorFilter(mCommentIconAndInfoColor, android.graphics.PorterDuff.Mode.SRC_IN); + scoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, + comment.getScore() + comment.getVoteType())); + topScoreTextView.setText(Utils.getNVotes(mShowAbsoluteNumberOfVotes, + comment.getScore() + comment.getVoteType()) + " pts"); + } + + @Override + public void onVoteThingFail(int position1) { + } + }, comment.getFullName(), newVoteType, getAdapterPosition()); + }); + + saveButton.setOnClickListener(view -> { + CommentData comment = getCurrentComment(); + if (comment.isSaved()) { + comment.setSaved(false); + SaveThing.unsaveThing(mOauthRetrofit, mAccessToken, comment.getFullName(), new SaveThing.SaveThingListener() { + @Override + public void success() { + comment.setSaved(false); + saveButton.setImageResource(R.drawable.ic_bookmark_border_grey_24dp); + Toast.makeText(mActivity, R.string.comment_unsaved_success, Toast.LENGTH_SHORT).show(); + } + + @Override + public void failed() { + comment.setSaved(true); + saveButton.setImageResource(R.drawable.ic_bookmark_grey_24dp); + Toast.makeText(mActivity, R.string.comment_unsaved_failed, Toast.LENGTH_SHORT).show(); + } + }); + } else { + comment.setSaved(true); + SaveThing.saveThing(mOauthRetrofit, mAccessToken, comment.getFullName(), new SaveThing.SaveThingListener() { + @Override + public void success() { + comment.setSaved(true); + saveButton.setImageResource(R.drawable.ic_bookmark_grey_24dp); + Toast.makeText(mActivity, R.string.comment_saved_success, Toast.LENGTH_SHORT).show(); + } + + @Override + public void failed() { + comment.setSaved(false); + saveButton.setImageResource(R.drawable.ic_bookmark_border_grey_24dp); + Toast.makeText(mActivity, R.string.comment_saved_failed, Toast.LENGTH_SHORT).show(); + } + }); + } + }); + + authorTextView.setOnClickListener(view -> { + Intent intent = new Intent(mActivity, ViewUserDetailActivity.class); + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, getCurrentComment().getAuthor()); + mActivity.startActivity(intent); + }); + + expandButton.setOnClickListener(view -> { + if (expandButton.getVisibility() == View.VISIBLE) { + int commentPosition = mIsSingleCommentThreadMode ? getAdapterPosition() - 2 : getAdapterPosition() - 1; + if(commentPosition >= 0 && commentPosition < mVisibleComments.size()) { + CommentData comment = getCurrentComment(); + if (mVisibleComments.get(commentPosition).isExpanded()) { + collapseChildren(commentPosition); + expandButton.setImageResource(R.drawable.ic_expand_more_grey_24dp); + } else { + comment.setExpanded(true); + ArrayList newList = new ArrayList<>(); + expandChildren(mVisibleComments.get(commentPosition).getChildren(), newList, 0); + mVisibleComments.get(commentPosition).setExpanded(true); + mVisibleComments.addAll(commentPosition + 1, newList); + + if (mIsSingleCommentThreadMode) { + notifyItemRangeInserted(commentPosition + 3, newList.size()); + } else { + notifyItemRangeInserted(commentPosition + 2, newList.size()); + } + expandButton.setImageResource(R.drawable.ic_expand_less_grey_24dp); + } + } + } + }); + + commentMarkdownView.setOnLongClickListener(view -> { + expandButton.performClick(); + return true; + }); + + itemView.setOnLongClickListener(view -> { + expandButton.performClick(); + return true; + }); + } + + private CommentData getCurrentComment() { + CommentData comment; + if (mIsSingleCommentThreadMode) { + comment = mVisibleComments.get(getAdapterPosition() - 2); + } else { + comment = mVisibleComments.get(getAdapterPosition() - 1); + } + + return comment; } } -- cgit v1.2.3