diff options
author | Sergei Kozelko <KozelkoS@yandex.ru> | 2022-09-25 08:13:59 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-25 08:13:59 +0000 |
commit | fad978432e2f8c3a676d137d9683bf1f470da1f0 (patch) | |
tree | 16179322ddae5624d0e7f37ad303996526734776 | |
parent | 85debf62f3807f1b137883169eafe79070355a31 (diff) | |
download | infinity-for-reddit-fad978432e2f8c3a676d137d9683bf1f470da1f0.tar infinity-for-reddit-fad978432e2f8c3a676d137d9683bf1f470da1f0.tar.gz infinity-for-reddit-fad978432e2f8c3a676d137d9683bf1f470da1f0.tar.bz2 infinity-for-reddit-fad978432e2f8c3a676d137d9683bf1f470da1f0.tar.lz infinity-for-reddit-fad978432e2f8c3a676d137d9683bf1f470da1f0.tar.xz infinity-for-reddit-fad978432e2f8c3a676d137d9683bf1f470da1f0.tar.zst infinity-for-reddit-fad978432e2f8c3a676d137d9683bf1f470da1f0.zip |
Fix spoiler interactions with links and long clicks (#1129)
* Prioritize clicks on hidden spoilers over links
Extend BetterLinkMovementMethod to override selection of span that will be
touched and give spoilers and links following priorities:
1. Hidden spoiler
2. Non-spoiler span (i.e. link)
3. Shown spoiler
#609
* Ignore long clicks on spoilers
Ignore long clicks if it is a SpoilerSpan. Also don't apply highlight
because it breaks spoiler effect.
#529
Diffstat (limited to '')
11 files changed, 135 insertions, 10 deletions
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java index 4aac3cbe..07df4287 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java @@ -56,6 +56,7 @@ import io.noties.markwon.inlineparser.BangInlineProcessor; import io.noties.markwon.inlineparser.HtmlInlineProcessor; import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin; import io.noties.markwon.linkify.LinkifyPlugin; +import io.noties.markwon.movement.MovementMethodPlugin; import io.noties.markwon.recycler.MarkwonAdapter; import io.noties.markwon.recycler.table.TableEntry; import io.noties.markwon.recycler.table.TableEntryPlugin; @@ -78,6 +79,7 @@ import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFi import ml.docilealligator.infinityforreddit.databinding.ActivityCommentBinding; import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent; import ml.docilealligator.infinityforreddit.markdown.RedditHeadingPlugin; +import ml.docilealligator.infinityforreddit.markdown.SpoilerAwareMovementMethod; import ml.docilealligator.infinityforreddit.markdown.SpoilerParserPlugin; import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils; @@ -239,6 +241,7 @@ public class CommentActivity extends BaseActivity implements UploadImageEnabledA .usePlugin(SpoilerParserPlugin.create(parentTextColor, parentSpoilerBackgroundColor)) .usePlugin(RedditHeadingPlugin.create()) .usePlugin(StrikethroughPlugin.create()) + .usePlugin(MovementMethodPlugin.create(new SpoilerAwareMovementMethod())) .usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS)) .usePlugin(TableEntryPlugin.create(this)) .build(); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/FullMarkdownActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/FullMarkdownActivity.java index 32f20d82..59e964a3 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/FullMarkdownActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/FullMarkdownActivity.java @@ -45,6 +45,7 @@ import io.noties.markwon.inlineparser.BangInlineProcessor; import io.noties.markwon.inlineparser.HtmlInlineProcessor; import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin; import io.noties.markwon.linkify.LinkifyPlugin; +import io.noties.markwon.movement.MovementMethodPlugin; import io.noties.markwon.recycler.MarkwonAdapter; import io.noties.markwon.recycler.table.TableEntry; import io.noties.markwon.recycler.table.TableEntryPlugin; @@ -55,6 +56,7 @@ import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFi import ml.docilealligator.infinityforreddit.customviews.MarkwonLinearLayoutManager; import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent; import ml.docilealligator.infinityforreddit.markdown.RedditHeadingPlugin; +import ml.docilealligator.infinityforreddit.markdown.SpoilerAwareMovementMethod; import ml.docilealligator.infinityforreddit.markdown.SpoilerParserPlugin; import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils; @@ -172,6 +174,7 @@ public class FullMarkdownActivity extends BaseActivity { .usePlugin(SpoilerParserPlugin.create(markdownColor, spoilerBackgroundColor)) .usePlugin(RedditHeadingPlugin.create()) .usePlugin(StrikethroughPlugin.create()) + .usePlugin(MovementMethodPlugin.create(new SpoilerAwareMovementMethod())) .usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS)) .usePlugin(TableEntryPlugin.create(this)) .build(); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/WikiActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/WikiActivity.java index 7d0e3168..f8ef602b 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/WikiActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/WikiActivity.java @@ -55,7 +55,6 @@ import io.noties.markwon.movement.MovementMethodPlugin; import io.noties.markwon.recycler.MarkwonAdapter; import io.noties.markwon.recycler.table.TableEntry; import io.noties.markwon.recycler.table.TableEntryPlugin; -import me.saket.bettermovementmethod.BetterLinkMovementMethod; import ml.docilealligator.infinityforreddit.Infinity; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.apis.RedditAPI; @@ -65,6 +64,7 @@ import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFi import ml.docilealligator.infinityforreddit.customviews.MarkwonLinearLayoutManager; import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent; import ml.docilealligator.infinityforreddit.markdown.RedditHeadingPlugin; +import ml.docilealligator.infinityforreddit.markdown.SpoilerAwareMovementMethod; import ml.docilealligator.infinityforreddit.markdown.SpoilerParserPlugin; import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; import ml.docilealligator.infinityforreddit.utils.JSONUtils; @@ -201,7 +201,7 @@ public class WikiActivity extends BaseActivity { .usePlugin(SpoilerParserPlugin.create(markdownColor, spoilerBackgroundColor)) .usePlugin(RedditHeadingPlugin.create()) .usePlugin(StrikethroughPlugin.create()) - .usePlugin(MovementMethodPlugin.create(BetterLinkMovementMethod.linkify(Linkify.WEB_URLS).setOnLinkLongClickListener((textView, url) -> { + .usePlugin(MovementMethodPlugin.create(new SpoilerAwareMovementMethod().setOnLinkLongClickListener((textView, url) -> { UrlMenuBottomSheetFragment urlMenuBottomSheetFragment = new UrlMenuBottomSheetFragment(); Bundle bundle = new Bundle(); bundle.putString(UrlMenuBottomSheetFragment.EXTRA_URL, url); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsListingRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsListingRecyclerViewAdapter.java index d199f885..6b8ad84f 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsListingRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsListingRecyclerViewAdapter.java @@ -48,7 +48,6 @@ import io.noties.markwon.linkify.LinkifyPlugin; import io.noties.markwon.movement.MovementMethodPlugin; import io.noties.markwon.recycler.table.TableEntry; import io.noties.markwon.recycler.table.TableEntryPlugin; -import me.saket.bettermovementmethod.BetterLinkMovementMethod; import ml.docilealligator.infinityforreddit.NetworkState; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.SaveThing; @@ -69,6 +68,7 @@ import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFi import ml.docilealligator.infinityforreddit.customviews.MarkwonLinearLayoutManager; import ml.docilealligator.infinityforreddit.customviews.SpoilerOnClickTextView; import ml.docilealligator.infinityforreddit.markdown.RedditHeadingPlugin; +import ml.docilealligator.infinityforreddit.markdown.SpoilerAwareMovementMethod; import ml.docilealligator.infinityforreddit.markdown.SpoilerParserPlugin; import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; import ml.docilealligator.infinityforreddit.utils.APIUtils; @@ -195,7 +195,7 @@ public class CommentsListingRecyclerViewAdapter extends PagedListAdapter<Comment .usePlugin(SpoilerParserPlugin.create(mCommentColor, commentSpoilerBackgroundColor)) .usePlugin(RedditHeadingPlugin.create()) .usePlugin(StrikethroughPlugin.create()) - .usePlugin(MovementMethodPlugin.create(BetterLinkMovementMethod.linkify(Linkify.WEB_URLS).setOnLinkLongClickListener((textView, url) -> { + .usePlugin(MovementMethodPlugin.create(new SpoilerAwareMovementMethod().setOnLinkLongClickListener((textView, url) -> { if (!activity.isDestroyed() && !activity.isFinishing()) { UrlMenuBottomSheetFragment urlMenuBottomSheetFragment = new UrlMenuBottomSheetFragment(); Bundle bundle = new Bundle(); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsRecyclerViewAdapter.java index fe452064..7fc55c01 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsRecyclerViewAdapter.java @@ -58,7 +58,6 @@ import io.noties.markwon.movement.MovementMethodPlugin; import io.noties.markwon.recycler.table.TableEntry; import io.noties.markwon.recycler.table.TableEntryPlugin; import jp.wasabeef.glide.transformations.RoundedCornersTransformation; -import me.saket.bettermovementmethod.BetterLinkMovementMethod; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.SaveThing; import ml.docilealligator.infinityforreddit.VoteThing; @@ -79,6 +78,7 @@ import ml.docilealligator.infinityforreddit.customviews.MarkwonLinearLayoutManag import ml.docilealligator.infinityforreddit.customviews.SpoilerOnClickTextView; import ml.docilealligator.infinityforreddit.fragments.ViewPostDetailFragment; import ml.docilealligator.infinityforreddit.markdown.RedditHeadingPlugin; +import ml.docilealligator.infinityforreddit.markdown.SpoilerAwareMovementMethod; import ml.docilealligator.infinityforreddit.markdown.SpoilerParserPlugin; import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; import ml.docilealligator.infinityforreddit.post.Post; @@ -227,7 +227,7 @@ public class CommentsRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerVi .usePlugin(SpoilerParserPlugin.create(mCommentTextColor, commentSpoilerBackgroundColor)) .usePlugin(RedditHeadingPlugin.create()) .usePlugin(StrikethroughPlugin.create()) - .usePlugin(MovementMethodPlugin.create(BetterLinkMovementMethod.linkify(Linkify.WEB_URLS).setOnLinkLongClickListener((textView, url) -> { + .usePlugin(MovementMethodPlugin.create(new SpoilerAwareMovementMethod().setOnLinkLongClickListener((textView, url) -> { if (!activity.isDestroyed() && !activity.isFinishing()) { UrlMenuBottomSheetFragment urlMenuBottomSheetFragment = new UrlMenuBottomSheetFragment(); Bundle bundle = new Bundle(); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/MessageRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/MessageRecyclerViewAdapter.java index 01408328..8a2aa51d 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/MessageRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/MessageRecyclerViewAdapter.java @@ -35,6 +35,7 @@ import io.noties.markwon.inlineparser.BangInlineProcessor; import io.noties.markwon.inlineparser.HtmlInlineProcessor; import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin; import io.noties.markwon.linkify.LinkifyPlugin; +import io.noties.markwon.movement.MovementMethodPlugin; import ml.docilealligator.infinityforreddit.NetworkState; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.activities.BaseActivity; @@ -44,6 +45,7 @@ import ml.docilealligator.infinityforreddit.activities.ViewUserDetailActivity; import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.events.ChangeInboxCountEvent; import ml.docilealligator.infinityforreddit.markdown.RedditHeadingPlugin; +import ml.docilealligator.infinityforreddit.markdown.SpoilerAwareMovementMethod; import ml.docilealligator.infinityforreddit.markdown.SpoilerParserPlugin; import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; import ml.docilealligator.infinityforreddit.message.FetchMessage; @@ -138,6 +140,7 @@ public class MessageRecyclerViewAdapter extends PagedListAdapter<Message, Recycl .usePlugin(SpoilerParserPlugin.create(mSecondaryTextColor, spoilerBackgroundColor)) .usePlugin(RedditHeadingPlugin.create()) .usePlugin(StrikethroughPlugin.create()) + .usePlugin(MovementMethodPlugin.create(new SpoilerAwareMovementMethod())) .usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS)) .build(); mAccessToken = accessToken; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostDetailRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostDetailRecyclerViewAdapter.java index 3c517171..d332166a 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostDetailRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostDetailRecyclerViewAdapter.java @@ -72,7 +72,6 @@ import io.noties.markwon.recycler.table.TableEntry; import io.noties.markwon.recycler.table.TableEntryPlugin; import jp.wasabeef.glide.transformations.BlurTransformation; import jp.wasabeef.glide.transformations.RoundedCornersTransformation; -import me.saket.bettermovementmethod.BetterLinkMovementMethod; import ml.docilealligator.infinityforreddit.FetchGfycatOrRedgifsVideoLinks; import ml.docilealligator.infinityforreddit.FetchStreamableVideo; import ml.docilealligator.infinityforreddit.R; @@ -104,6 +103,7 @@ import ml.docilealligator.infinityforreddit.customviews.AspectRatioGifImageView; import ml.docilealligator.infinityforreddit.customviews.MarkwonLinearLayoutManager; import ml.docilealligator.infinityforreddit.fragments.ViewPostDetailFragment; import ml.docilealligator.infinityforreddit.markdown.RedditHeadingPlugin; +import ml.docilealligator.infinityforreddit.markdown.SpoilerAwareMovementMethod; import ml.docilealligator.infinityforreddit.markdown.SpoilerParserPlugin; import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; import ml.docilealligator.infinityforreddit.post.Post; @@ -297,7 +297,7 @@ public class PostDetailRecyclerViewAdapter extends RecyclerView.Adapter<Recycler .usePlugin(SpoilerParserPlugin.create(markdownColor, postSpoilerBackgroundColor)) .usePlugin(RedditHeadingPlugin.create()) .usePlugin(StrikethroughPlugin.create()) - .usePlugin(MovementMethodPlugin.create(BetterLinkMovementMethod.linkify(Linkify.WEB_URLS).setOnLinkLongClickListener((textView, url) -> { + .usePlugin(MovementMethodPlugin.create(new SpoilerAwareMovementMethod().setOnLinkLongClickListener((textView, url) -> { if (activity != null && !activity.isDestroyed() && !activity.isFinishing()) { UrlMenuBottomSheetFragment urlMenuBottomSheetFragment = new UrlMenuBottomSheetFragment(); Bundle bundle = new Bundle(); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PrivateMessagesDetailRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PrivateMessagesDetailRecyclerViewAdapter.java index 149eae5b..3dea4478 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PrivateMessagesDetailRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PrivateMessagesDetailRecyclerViewAdapter.java @@ -39,6 +39,7 @@ import io.noties.markwon.inlineparser.BangInlineProcessor; import io.noties.markwon.inlineparser.HtmlInlineProcessor; import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin; import io.noties.markwon.linkify.LinkifyPlugin; +import io.noties.markwon.movement.MovementMethodPlugin; import jp.wasabeef.glide.transformations.RoundedCornersTransformation; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.activities.LinkResolverActivity; @@ -46,6 +47,7 @@ import ml.docilealligator.infinityforreddit.activities.ViewPrivateMessagesActivi import ml.docilealligator.infinityforreddit.activities.ViewUserDetailActivity; import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.markdown.RedditHeadingPlugin; +import ml.docilealligator.infinityforreddit.markdown.SpoilerAwareMovementMethod; import ml.docilealligator.infinityforreddit.markdown.SpoilerParserPlugin; import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; import ml.docilealligator.infinityforreddit.message.Message; @@ -121,6 +123,7 @@ public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapt .usePlugin(StrikethroughPlugin.create()) .usePlugin(SpoilerParserPlugin.create(commentColor, commentColor | 0xFF000000)) .usePlugin(RedditHeadingPlugin.create()) + .usePlugin(MovementMethodPlugin.create(new SpoilerAwareMovementMethod())) .usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS)) .build(); mShowElapsedTime = sharedPreferences.getBoolean(SharedPreferencesUtils.SHOW_ELAPSED_TIME_KEY, false); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/RulesRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/RulesRecyclerViewAdapter.java index 33c3dd81..a1109523 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/RulesRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/RulesRecyclerViewAdapter.java @@ -38,7 +38,6 @@ import io.noties.markwon.movement.MovementMethodPlugin; import io.noties.markwon.recycler.MarkwonAdapter; import io.noties.markwon.recycler.table.TableEntry; import io.noties.markwon.recycler.table.TableEntryPlugin; -import me.saket.bettermovementmethod.BetterLinkMovementMethod; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.Rule; import ml.docilealligator.infinityforreddit.activities.BaseActivity; @@ -48,6 +47,7 @@ import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFixed; import ml.docilealligator.infinityforreddit.customviews.MarkwonLinearLayoutManager; import ml.docilealligator.infinityforreddit.markdown.RedditHeadingPlugin; +import ml.docilealligator.infinityforreddit.markdown.SpoilerAwareMovementMethod; import ml.docilealligator.infinityforreddit.markdown.SpoilerParserPlugin; import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; import ml.docilealligator.infinityforreddit.utils.Utils; @@ -108,7 +108,7 @@ public class RulesRecyclerViewAdapter extends RecyclerView.Adapter<RulesRecycler builder.linkColor(customThemeWrapper.getLinkColor()); } }) - .usePlugin(MovementMethodPlugin.create(BetterLinkMovementMethod.linkify(Linkify.WEB_URLS).setOnLinkLongClickListener((textView, url) -> { + .usePlugin(MovementMethodPlugin.create(new SpoilerAwareMovementMethod().setOnLinkLongClickListener((textView, url) -> { if (activity != null && !activity.isDestroyed() && !activity.isFinishing()) { UrlMenuBottomSheetFragment urlMenuBottomSheetFragment = new UrlMenuBottomSheetFragment(); Bundle bundle = new Bundle(); @@ -122,6 +122,7 @@ public class RulesRecyclerViewAdapter extends RecyclerView.Adapter<RulesRecycler .usePlugin(SpoilerParserPlugin.create(mPrimaryTextColor, spoilerBackgroundColor)) .usePlugin(RedditHeadingPlugin.create()) .usePlugin(StrikethroughPlugin.create()) + .usePlugin(MovementMethodPlugin.create(new SpoilerAwareMovementMethod())) .usePlugin(TableEntryPlugin.create(activity)) .build(); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerAwareMovementMethod.java b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerAwareMovementMethod.java new file mode 100644 index 00000000..19ab96f3 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerAwareMovementMethod.java @@ -0,0 +1,102 @@ +package ml.docilealligator.infinityforreddit.markdown; + +import android.graphics.RectF; +import android.text.Layout; +import android.text.Spannable; +import android.text.style.ClickableSpan; +import android.view.MotionEvent; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import me.saket.bettermovementmethod.BetterLinkMovementMethod; + +/** + * Extension of {@link BetterLinkMovementMethod} that handles {@link SpoilerSpan}s + */ +public class SpoilerAwareMovementMethod extends BetterLinkMovementMethod { + private final RectF touchedLineBounds = new RectF(); + + @Override + protected ClickableSpan findClickableSpanUnderTouch(TextView textView, Spannable text, MotionEvent event) { + // A copy of super method. Logic for selecting correct clickable span was moved to selectClickableSpan + + // So we need to find the location in text where touch was made, regardless of whether the TextView + // has scrollable text. That is, not the entire text is currently visible. + int touchX = (int) event.getX(); + int touchY = (int) event.getY(); + + // Ignore padding. + touchX -= textView.getTotalPaddingLeft(); + touchY -= textView.getTotalPaddingTop(); + + // Account for scrollable text. + touchX += textView.getScrollX(); + touchY += textView.getScrollY(); + + final Layout layout = textView.getLayout(); + final int touchedLine = layout.getLineForVertical(touchY); + final int touchOffset = layout.getOffsetForHorizontal(touchedLine, touchX); + + touchedLineBounds.left = layout.getLineLeft(touchedLine); + touchedLineBounds.top = layout.getLineTop(touchedLine); + touchedLineBounds.right = layout.getLineWidth(touchedLine) + touchedLineBounds.left; + touchedLineBounds.bottom = layout.getLineBottom(touchedLine); + + if (touchedLineBounds.contains(touchX, touchY)) { + // Find a ClickableSpan that lies under the touched area. + final Object[] spans = text.getSpans(touchOffset, touchOffset, ClickableSpan.class); + // BEGIN Infinity changed + return selectClickableSpan(spans); + // END Infinity changed + } else { + // Touch lies outside the line's horizontal bounds where no spans should exist. + return null; + } + } + + /** + * Select a span according to priorities: + * 1. Hidden spoiler + * 2. Non-spoiler span (i.e. link) + * 3. Shown spoiler + */ + @Nullable + private ClickableSpan selectClickableSpan(@NonNull Object[] spans) { + SpoilerSpan spoilerSpan = null; + ClickableSpan nonSpoilerSpan = null; + for (final Object span : spans) { + if (span instanceof SpoilerSpan) { + spoilerSpan = (SpoilerSpan) span; + } else if (span instanceof ClickableSpan) { + nonSpoilerSpan = (ClickableSpan) span; + } + } + + if (spoilerSpan != null && !spoilerSpan.isShowing()) { + return spoilerSpan; + } else if (nonSpoilerSpan != null){ + return nonSpoilerSpan; + } else { + return spoilerSpan; + } + } + + @Override + protected void dispatchUrlLongClick(TextView textView, ClickableSpan clickableSpan) { + if (clickableSpan instanceof SpoilerSpan) { + ((SpoilerSpan) clickableSpan).onLongClick(textView); + return; + } + super.dispatchUrlLongClick(textView, clickableSpan); + } + + @Override + protected void highlightUrl(TextView textView, ClickableSpan clickableSpan, Spannable text) { + if (clickableSpan instanceof SpoilerSpan) { + return; + } + super.highlightUrl(textView, clickableSpan, text); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerSpan.java b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerSpan.java index 2264449c..6651867b 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerSpan.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerSpan.java @@ -50,6 +50,16 @@ public class SpoilerSpan extends ClickableSpan { widget.invalidate(); } + public void onLongClick(@NonNull View widget) { + if (widget instanceof SpoilerOnClickTextView) { + ((SpoilerOnClickTextView) widget).setSpoilerOnClick(true); + } + } + + public boolean isShowing() { + return isShowing; + } + @Override public void updateDrawState(@NonNull TextPaint ds) { if (isShowing) { |