From bbc69b45e6f414673906641232cde0f72a641f35 Mon Sep 17 00:00:00 2001 From: Alex Ning Date: Wed, 19 Feb 2020 21:18:08 +0800 Subject: Show image flairs properly. Minor bugs fixed. --- .../Adapter/CommentAndPostRecyclerViewAdapter.java | 12 +- .../infinityforreddit/ParseComment.java | 25 ++-- .../infinityforreddit/Utils/GlideImageGetter.java | 157 +++++++++++++++++++++ .../infinityforreddit/Utils/JSONUtils.java | 7 +- app/src/main/res/layout/activity_main.xml | 1 - 5 files changed, 188 insertions(+), 14 deletions(-) create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Utils/GlideImageGetter.java (limited to 'app/src/main') 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 52372b76..80887700 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentAndPostRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentAndPostRecyclerViewAdapter.java @@ -6,6 +6,8 @@ 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.text.Spanned; import android.text.style.SuperscriptSpan; import android.text.util.Linkify; @@ -81,6 +83,7 @@ import ml.docilealligator.infinityforreddit.Post.PostDataSource; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; import ml.docilealligator.infinityforreddit.SaveThing; +import ml.docilealligator.infinityforreddit.Utils.GlideImageGetter; import ml.docilealligator.infinityforreddit.Utils.RedditUtils; import ml.docilealligator.infinityforreddit.Utils.Utils; import ml.docilealligator.infinityforreddit.VoteThing; @@ -704,7 +707,14 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter= android.os.Build.VERSION_CODES.N) { + flairHTML = (Spannable) Html.fromHtml(comment.getAuthorFlair(), Html.FROM_HTML_MODE_LEGACY, glideImageGetter, null); + } else { + flairHTML = (Spannable) Html.fromHtml(comment.getAuthorFlair(), glideImageGetter, null); + } + ((CommentViewHolder) holder).authorFlairTextView.setText(flairHTML); ((CommentViewHolder) holder).authorFlairTextView.setOnClickListener(view -> ((CommentViewHolder) holder).authorTextView.performClick()); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseComment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseComment.java index 1650b6bc..0891e7f1 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseComment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseComment.java @@ -118,11 +118,18 @@ public class ParseComment { String id = singleCommentData.getString(JSONUtils.ID_KEY); String fullName = singleCommentData.getString(JSONUtils.NAME_KEY); String author = singleCommentData.getString(JSONUtils.AUTHOR_KEY); - String authorFlair; - if (!singleCommentData.has(JSONUtils.AUTHOR_FLAIR_TEXT_KEY) || singleCommentData.isNull(JSONUtils.AUTHOR_FLAIR_TEXT_KEY)) { - authorFlair = ""; - } else { - authorFlair = singleCommentData.getString(JSONUtils.AUTHOR_FLAIR_TEXT_KEY); + StringBuilder authorFlairHTMLBuilder = new StringBuilder(); + if (singleCommentData.has(JSONUtils.AUTHOR_FLAIR_RICHTEXT_KEY)) { + JSONArray flairArray = singleCommentData.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 linkAuthor = singleCommentData.has(JSONUtils.LINK_AUTHOR_KEY) ? singleCommentData.getString(JSONUtils.LINK_AUTHOR_KEY) : null; String linkId = singleCommentData.getString(JSONUtils.LINK_ID_KEY).substring(3); @@ -161,10 +168,10 @@ public class ParseComment { boolean collapsed = singleCommentData.getBoolean(JSONUtils.COLLAPSED_KEY); boolean hasReply = !(singleCommentData.get(JSONUtils.REPLIES_KEY) instanceof String); - return new CommentData(id, fullName, author, authorFlair, linkAuthor, formattedSubmitTime, - submitTime, commentMarkdown, commentRawText, linkId, subredditName, parentId, score, - voteType, isSubmitter, distinguished, permalink, depth, collapsed, hasReply, - scoreHidden, saved); + return new CommentData(id, fullName, author, authorFlairHTMLBuilder.toString(), linkAuthor, + formattedSubmitTime, submitTime, commentMarkdown, commentRawText, linkId, subredditName, + parentId, score, voteType, isSubmitter, distinguished, permalink, depth, collapsed, + hasReply, scoreHidden, saved); } @Nullable diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/GlideImageGetter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/GlideImageGetter.java new file mode 100644 index 00000000..b38f5b52 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/GlideImageGetter.java @@ -0,0 +1,157 @@ +package ml.docilealligator.infinityforreddit.Utils; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.text.Html; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.Request; +import com.bumptech.glide.request.target.SizeReadyCallback; +import com.bumptech.glide.request.target.Target; +import com.bumptech.glide.request.transition.Transition; + +import java.lang.ref.WeakReference; + +public class GlideImageGetter implements Html.ImageGetter { + + private WeakReference container; + private boolean matchParentWidth; + private HtmlImagesHandler imagesHandler; + private float density = 1.0f; + private float textSize; + + public GlideImageGetter(TextView textView) { + this(textView, false, false, null); + } + + public GlideImageGetter(TextView textView, boolean matchParentWidth, HtmlImagesHandler imagesHandler) { + this(textView, matchParentWidth, false, imagesHandler); + } + + public GlideImageGetter(TextView textView, boolean matchParentWidth, boolean densityAware, + @Nullable HtmlImagesHandler imagesHandler) { + this.container = new WeakReference<>(textView); + this.matchParentWidth = matchParentWidth; + this.imagesHandler = imagesHandler; + if (densityAware) { + density = container.get().getResources().getDisplayMetrics().density; + } + textSize = container.get().getTextSize(); + } + + @Override + public Drawable getDrawable(String source) { + if (imagesHandler != null) { + imagesHandler.addImage(source); + } + + BitmapDrawablePlaceholder drawable = new BitmapDrawablePlaceholder(textSize); + + container.get().post(() -> Glide.with(container.get().getContext()) + .asBitmap() + .load(source) + .into(drawable)); + + return drawable; + } + + private class BitmapDrawablePlaceholder extends BitmapDrawable implements Target { + + protected Drawable drawable; + + BitmapDrawablePlaceholder(float textSize) { + super(container.get().getResources(), + Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)); + } + + @Override + public void draw(final Canvas canvas) { + if (drawable != null) { + drawable.draw(canvas); + } + } + + private void setDrawable(Drawable drawable) { + this.drawable = drawable; + int drawableWidth = (int) (drawable.getIntrinsicWidth() * density); + int drawableHeight = (int) (drawable.getIntrinsicHeight() * density); + float ratio = (float) drawableWidth / (float) drawableHeight; + drawableHeight = (int) textSize + 10; + drawableWidth = (int) (drawableHeight * ratio); + int maxWidth = container.get().getMeasuredWidth(); + if ((drawableWidth > maxWidth) || matchParentWidth) { + int calculatedHeight = maxWidth * drawableHeight / drawableWidth; + drawable.setBounds(0, 0, maxWidth, calculatedHeight); + setBounds(0, 0, maxWidth, calculatedHeight); + } else { + drawable.setBounds(0, 0, drawableWidth, drawableHeight); + setBounds(0, 0, drawableWidth, drawableHeight); + } + + container.get().setText(container.get().getText()); + } + + @Override + public void onLoadStarted(@Nullable Drawable placeholderDrawable) { + if(placeholderDrawable != null) { + setDrawable(placeholderDrawable); + } + } + + @Override + public void onLoadFailed(@Nullable Drawable errorDrawable) { + if (errorDrawable != null) { + setDrawable(errorDrawable); + } + } + + @Override + public void onResourceReady(@NonNull Bitmap bitmap, @Nullable Transition transition) { + setDrawable(new BitmapDrawable(container.get().getResources(), bitmap)); + } + + @Override + public void onLoadCleared(@Nullable Drawable placeholderDrawable) { + if(placeholderDrawable != null) { + setDrawable(placeholderDrawable); + } + } + + @Override + public void getSize(@NonNull SizeReadyCallback cb) { + cb.onSizeReady(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL); + } + + @Override + public void removeCallback(@NonNull SizeReadyCallback cb) {} + + @Override + public void setRequest(@Nullable Request request) {} + + @Nullable + @Override + public Request getRequest() { + return null; + } + + @Override + public void onStart() {} + + @Override + public void onStop() {} + + @Override + public void onDestroy() {} + + } + + public interface HtmlImagesHandler { + void addImage(String uri); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/JSONUtils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/JSONUtils.java index 77338813..577b16e0 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/JSONUtils.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/JSONUtils.java @@ -17,6 +17,10 @@ public class JSONUtils { public static final String SELFTEXT_HTML_KEY = "selftext_html"; public static final String AUTHOR_KEY = "author"; public static final String AUTHOR_FLAIR_TEXT_KEY = "author_flair_text"; + public static final String AUTHOR_FLAIR_RICHTEXT_KEY = "author_flair_richtext"; + public static final String E_KEY = "e"; + public static final String T_KEY = "t"; + public static final String U_KEY = "u"; public static final String LINK_AUTHOR_KEY = "link_author"; public static final String LINK_FLAIR_TEXT_KEY = "link_flair_text"; public static final String SCORE_KEY = "score"; @@ -29,9 +33,6 @@ public class JSONUtils { public static final String IMAGES_KEY = "images"; public static final String WIDTH_KEY = "width"; public static final String HEIGHT_KEY = "height"; - public static final String VARIANTS_KEY = "variants"; - public static final String GIF_KEY = "gif"; - public static final String MP4_KEY = "mp4"; public static final String SOURCE_KEY = "source"; public static final String URL_KEY = "url"; public static final String MEDIA_KEY = "media"; diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index cb1ca05f..e9f99b9c 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -14,7 +14,6 @@ android:layout_height="match_parent" />