From 6065dc84548e2111cabb23565e8789cf091fd75b Mon Sep 17 00:00:00 2001 From: Docile-Alligator <25734209+Docile-Alligator@users.noreply.github.com> Date: Sat, 9 Dec 2023 00:03:29 -0500 Subject: Fix OnClickListener's onlick being called even if it's null. Fix the double haptic feedback issue in markdown text. --- .../activities/ViewSubredditDetailActivity.java | 7 +- .../activities/ViewUserDetailActivity.java | 7 +- .../infinityforreddit/activities/WikiActivity.java | 4 +- .../CommentsListingRecyclerViewAdapter.java | 4 +- .../adapters/CommentsRecyclerViewAdapter.java | 6 +- .../adapters/MessageRecyclerViewAdapter.java | 1 - .../adapters/PostDetailRecyclerViewAdapter.java | 11 +- .../PrivateMessagesDetailRecyclerViewAdapter.java | 1 - .../adapters/RulesRecyclerViewAdapter.java | 6 +- .../customviews/SpoilerOnClickTextView.java | 2 +- .../fragments/SidebarFragment.java | 6 +- .../markdown/CustomMarkwonAdapter.java | 25 +- .../markdown/EvenBetterLinkMovementMethod.java | 450 +++++++++++++++++++++ .../infinityforreddit/markdown/MarkdownUtils.java | 9 +- .../markdown/SpoilerAwareMovementMethod.java | 12 +- .../infinityforreddit/markdown/SpoilerSpan.java | 2 - 16 files changed, 505 insertions(+), 48 deletions(-) create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/markdown/EvenBetterLinkMovementMethod.java (limited to 'app/src/main/java/ml') diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewSubredditDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewSubredditDetailActivity.java index 9101cfbc..80c0b8b5 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewSubredditDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewSubredditDetailActivity.java @@ -71,7 +71,6 @@ import io.noties.markwon.MarkwonConfiguration; import io.noties.markwon.MarkwonPlugin; import io.noties.markwon.core.MarkwonTheme; import jp.wasabeef.glide.transformations.RoundedCornersTransformation; -import me.saket.bettermovementmethod.BetterLinkMovementMethod; import ml.docilealligator.infinityforreddit.ActivityToolbarInterface; import ml.docilealligator.infinityforreddit.AppBarStateChangeListener; import ml.docilealligator.infinityforreddit.Infinity; @@ -103,6 +102,7 @@ import ml.docilealligator.infinityforreddit.events.GoBackToMainPageEvent; import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent; import ml.docilealligator.infinityforreddit.fragments.PostFragment; import ml.docilealligator.infinityforreddit.fragments.SidebarFragment; +import ml.docilealligator.infinityforreddit.markdown.EvenBetterLinkMovementMethod; import ml.docilealligator.infinityforreddit.markdown.MarkdownUtils; import ml.docilealligator.infinityforreddit.message.ReadMessage; import ml.docilealligator.infinityforreddit.multireddit.MultiReddit; @@ -389,7 +389,7 @@ public class ViewSubredditDetailActivity extends BaseActivity implements SortTyp builder.linkColor(mCustomThemeWrapper.getLinkColor()); } }; - BetterLinkMovementMethod.OnLinkLongClickListener onLinkLongClickListener = (textView, url) -> { + EvenBetterLinkMovementMethod.OnLinkLongClickListener onLinkLongClickListener = (textView, url) -> { UrlMenuBottomSheetFragment urlMenuBottomSheetFragment = UrlMenuBottomSheetFragment.newInstance(url); urlMenuBottomSheetFragment.show(getSupportFragmentManager(), null); return true; @@ -400,8 +400,9 @@ public class ViewSubredditDetailActivity extends BaseActivity implements SortTyp descriptionTextView.setOnLongClickListener(view -> { if (description != null && !description.equals("") && descriptionTextView.getSelectionStart() == -1 && descriptionTextView.getSelectionEnd() == -1) { CopyTextBottomSheetFragment.show(getSupportFragmentManager(), description, null); + return true; } - return true; + return false; }); mSubredditViewModel = new ViewModelProvider(this, diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewUserDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewUserDetailActivity.java index 52fedcb7..659d0a4b 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewUserDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewUserDetailActivity.java @@ -67,7 +67,6 @@ import io.noties.markwon.MarkwonConfiguration; import io.noties.markwon.MarkwonPlugin; import io.noties.markwon.core.MarkwonTheme; import jp.wasabeef.glide.transformations.RoundedCornersTransformation; -import me.saket.bettermovementmethod.BetterLinkMovementMethod; import ml.docilealligator.infinityforreddit.ActivityToolbarInterface; import ml.docilealligator.infinityforreddit.AppBarStateChangeListener; import ml.docilealligator.infinityforreddit.DeleteThing; @@ -100,6 +99,7 @@ import ml.docilealligator.infinityforreddit.events.GoBackToMainPageEvent; import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent; import ml.docilealligator.infinityforreddit.fragments.CommentsListingFragment; import ml.docilealligator.infinityforreddit.fragments.PostFragment; +import ml.docilealligator.infinityforreddit.markdown.EvenBetterLinkMovementMethod; import ml.docilealligator.infinityforreddit.markdown.MarkdownUtils; import ml.docilealligator.infinityforreddit.message.ReadMessage; import ml.docilealligator.infinityforreddit.multireddit.MultiReddit; @@ -381,7 +381,7 @@ public class ViewUserDetailActivity extends BaseActivity implements SortTypeSele builder.linkColor(mCustomThemeWrapper.getLinkColor()); } }; - BetterLinkMovementMethod.OnLinkLongClickListener onLinkLongClickListener = (textView, url) -> { + EvenBetterLinkMovementMethod.OnLinkLongClickListener onLinkLongClickListener = (textView, url) -> { UrlMenuBottomSheetFragment urlMenuBottomSheetFragment = UrlMenuBottomSheetFragment.newInstance(url); urlMenuBottomSheetFragment.show(getSupportFragmentManager(), null); return true; @@ -391,8 +391,9 @@ public class ViewUserDetailActivity extends BaseActivity implements SortTypeSele descriptionTextView.setOnLongClickListener(view -> { if (description != null && !description.equals("") && descriptionTextView.getSelectionStart() == -1 && descriptionTextView.getSelectionEnd() == -1) { CopyTextBottomSheetFragment.show(getSupportFragmentManager(), description, null); + return true; } - return true; + return false; }); userViewModel = new ViewModelProvider(this, new UserViewModel.Factory(getApplication(), mRedditDataRoomDatabase, username)) 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 57ec0ff1..6372191f 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/WikiActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/WikiActivity.java @@ -41,7 +41,6 @@ import io.noties.markwon.MarkwonConfiguration; import io.noties.markwon.MarkwonPlugin; import io.noties.markwon.core.MarkwonTheme; import io.noties.markwon.recycler.MarkwonAdapter; -import me.saket.bettermovementmethod.BetterLinkMovementMethod; import ml.docilealligator.infinityforreddit.Infinity; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.apis.RedditAPI; @@ -53,6 +52,7 @@ import ml.docilealligator.infinityforreddit.customviews.SwipeLockLinearLayoutMan import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr; import ml.docilealligator.infinityforreddit.events.ChangeNetworkStatusEvent; import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.markdown.EvenBetterLinkMovementMethod; import ml.docilealligator.infinityforreddit.markdown.EmoteCloseBracketInlineProcessor; import ml.docilealligator.infinityforreddit.markdown.EmotePlugin; import ml.docilealligator.infinityforreddit.markdown.ImageAndGifEntry; @@ -182,7 +182,7 @@ public class WikiActivity extends BaseActivity { builder.linkColor(linkColor); } }; - BetterLinkMovementMethod.OnLinkLongClickListener onLinkLongClickListener = (textView, url) -> { + EvenBetterLinkMovementMethod.OnLinkLongClickListener onLinkLongClickListener = (textView, url) -> { UrlMenuBottomSheetFragment urlMenuBottomSheetFragment = UrlMenuBottomSheetFragment.newInstance(url); urlMenuBottomSheetFragment.show(getSupportFragmentManager(), null); return true; 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 1964f7f7..9fb2b239 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsListingRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsListingRecyclerViewAdapter.java @@ -36,7 +36,6 @@ import io.noties.markwon.Markwon; import io.noties.markwon.MarkwonConfiguration; import io.noties.markwon.MarkwonPlugin; import io.noties.markwon.core.MarkwonTheme; -import me.saket.bettermovementmethod.BetterLinkMovementMethod; import ml.docilealligator.infinityforreddit.NetworkState; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.SaveThing; @@ -56,6 +55,7 @@ import ml.docilealligator.infinityforreddit.customviews.SpoilerOnClickTextView; import ml.docilealligator.infinityforreddit.customviews.SwipeLockInterface; import ml.docilealligator.infinityforreddit.customviews.SwipeLockLinearLayoutManager; import ml.docilealligator.infinityforreddit.databinding.ItemCommentBinding; +import ml.docilealligator.infinityforreddit.markdown.EvenBetterLinkMovementMethod; import ml.docilealligator.infinityforreddit.markdown.CustomMarkwonAdapter; import ml.docilealligator.infinityforreddit.markdown.EmoteCloseBracketInlineProcessor; import ml.docilealligator.infinityforreddit.markdown.EmotePlugin; @@ -173,7 +173,7 @@ public class CommentsListingRecyclerViewAdapter extends PagedListAdapter { + EvenBetterLinkMovementMethod.OnLinkLongClickListener onLinkLongClickListener = (textView, url) -> { if (!activity.isDestroyed() && !activity.isFinishing()) { UrlMenuBottomSheetFragment urlMenuBottomSheetFragment = UrlMenuBottomSheetFragment.newInstance(url); urlMenuBottomSheetFragment.show(activity.getSupportFragmentManager(), urlMenuBottomSheetFragment.getTag()); 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 8aa76ba7..ba0e45c0 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsRecyclerViewAdapter.java @@ -44,7 +44,6 @@ import io.noties.markwon.MarkwonConfiguration; import io.noties.markwon.MarkwonPlugin; import io.noties.markwon.core.MarkwonTheme; 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.SortType; @@ -61,13 +60,14 @@ import ml.docilealligator.infinityforreddit.comment.Comment; import ml.docilealligator.infinityforreddit.comment.FetchComment; import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.customviews.CommentIndentationView; -import ml.docilealligator.infinityforreddit.markdown.CustomMarkwonAdapter; import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFixed; import ml.docilealligator.infinityforreddit.customviews.SpoilerOnClickTextView; import ml.docilealligator.infinityforreddit.customviews.SwipeLockInterface; import ml.docilealligator.infinityforreddit.customviews.SwipeLockLinearLayoutManager; import ml.docilealligator.infinityforreddit.databinding.ItemCommentBinding; import ml.docilealligator.infinityforreddit.fragments.ViewPostDetailFragment; +import ml.docilealligator.infinityforreddit.markdown.EvenBetterLinkMovementMethod; +import ml.docilealligator.infinityforreddit.markdown.CustomMarkwonAdapter; import ml.docilealligator.infinityforreddit.markdown.EmoteCloseBracketInlineProcessor; import ml.docilealligator.infinityforreddit.markdown.EmotePlugin; import ml.docilealligator.infinityforreddit.markdown.ImageAndGifEntry; @@ -207,7 +207,7 @@ public class CommentsRecyclerViewAdapter extends RecyclerView.Adapter { + EvenBetterLinkMovementMethod.OnLinkLongClickListener onLinkLongClickListener = (textView, url) -> { if (!activity.isDestroyed() && !activity.isFinishing()) { UrlMenuBottomSheetFragment urlMenuBottomSheetFragment = UrlMenuBottomSheetFragment.newInstance(url); urlMenuBottomSheetFragment.show(activity.getSupportFragmentManager(), null); 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 1eea5041..f2967d8e 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/MessageRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/MessageRecyclerViewAdapter.java @@ -28,7 +28,6 @@ import io.noties.markwon.Markwon; import io.noties.markwon.MarkwonConfiguration; import io.noties.markwon.core.MarkwonTheme; import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; -import io.noties.markwon.inlineparser.AutolinkInlineProcessor; import io.noties.markwon.inlineparser.BangInlineProcessor; import io.noties.markwon.inlineparser.HtmlInlineProcessor; import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin; 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 a7c36f73..2afce6a5 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostDetailRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostDetailRecyclerViewAdapter.java @@ -61,7 +61,6 @@ import io.noties.markwon.MarkwonPlugin; import io.noties.markwon.core.MarkwonTheme; 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; @@ -102,6 +101,7 @@ import ml.docilealligator.infinityforreddit.databinding.ItemPostDetailVideoAndGi import ml.docilealligator.infinityforreddit.databinding.ItemPostDetailVideoAutoplayBinding; import ml.docilealligator.infinityforreddit.databinding.ItemPostDetailVideoAutoplayLegacyControllerBinding; import ml.docilealligator.infinityforreddit.fragments.ViewPostDetailFragment; +import ml.docilealligator.infinityforreddit.markdown.EvenBetterLinkMovementMethod; import ml.docilealligator.infinityforreddit.markdown.CustomMarkwonAdapter; import ml.docilealligator.infinityforreddit.markdown.EmoteCloseBracketInlineProcessor; import ml.docilealligator.infinityforreddit.markdown.EmotePlugin; @@ -221,7 +221,7 @@ public class PostDetailRecyclerViewAdapter extends RecyclerView.Adapter streamableApiProvider, @@ -356,8 +356,9 @@ public class PostDetailRecyclerViewAdapter extends RecyclerView.Adapter { - if (activity != null && !activity.isDestroyed() && !activity.isFinishing()) { + EvenBetterLinkMovementMethod.OnLinkLongClickListener onLinkLongClickListener = (textView, url) -> { + if (!activity.isDestroyed() && !activity.isFinishing()) { 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/PrivateMessagesDetailRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PrivateMessagesDetailRecyclerViewAdapter.java index e617340f..c4f859d4 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PrivateMessagesDetailRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PrivateMessagesDetailRecyclerViewAdapter.java @@ -32,7 +32,6 @@ import io.noties.markwon.Markwon; import io.noties.markwon.MarkwonConfiguration; import io.noties.markwon.core.MarkwonTheme; import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; -import io.noties.markwon.inlineparser.AutolinkInlineProcessor; import io.noties.markwon.inlineparser.BangInlineProcessor; import io.noties.markwon.inlineparser.HtmlInlineProcessor; import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin; 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 554e3b06..5dc4a82e 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/RulesRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/RulesRecyclerViewAdapter.java @@ -24,7 +24,6 @@ import io.noties.markwon.MarkwonConfiguration; import io.noties.markwon.MarkwonPlugin; import io.noties.markwon.core.MarkwonTheme; import io.noties.markwon.recycler.MarkwonAdapter; -import me.saket.bettermovementmethod.BetterLinkMovementMethod; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.Rule; import ml.docilealligator.infinityforreddit.activities.BaseActivity; @@ -35,6 +34,7 @@ import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.customviews.SwipeLockInterface; import ml.docilealligator.infinityforreddit.customviews.SwipeLockLinearLayoutManager; import ml.docilealligator.infinityforreddit.customviews.slidr.widget.SliderPanel; +import ml.docilealligator.infinityforreddit.markdown.EvenBetterLinkMovementMethod; import ml.docilealligator.infinityforreddit.markdown.EmoteCloseBracketInlineProcessor; import ml.docilealligator.infinityforreddit.markdown.EmotePlugin; import ml.docilealligator.infinityforreddit.markdown.ImageAndGifEntry; @@ -87,8 +87,8 @@ public class RulesRecyclerViewAdapter extends RecyclerView.Adapter { - if (activity != null && !activity.isDestroyed() && !activity.isFinishing()) { + EvenBetterLinkMovementMethod.OnLinkLongClickListener onLinkLongClickListener = (textView, url) -> { + if (!activity.isDestroyed() && !activity.isFinishing()) { UrlMenuBottomSheetFragment urlMenuBottomSheetFragment = UrlMenuBottomSheetFragment.newInstance(url); urlMenuBottomSheetFragment.show(activity.getSupportFragmentManager(), null); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/SpoilerOnClickTextView.java b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/SpoilerOnClickTextView.java index a34f644a..43709bbb 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/SpoilerOnClickTextView.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/SpoilerOnClickTextView.java @@ -24,7 +24,7 @@ public class SpoilerOnClickTextView extends androidx.appcompat.widget.AppCompatT return isSpoilerOnClick; } - public void setSpoilerOnClick(boolean spoilerOnClick) { + public void setSpoilerOnClick(boolean spoilerOnClick) { isSpoilerOnClick = spoilerOnClick; } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/SidebarFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/SidebarFragment.java index a30fe3c1..a8298a92 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/SidebarFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/SidebarFragment.java @@ -35,7 +35,6 @@ import io.noties.markwon.Markwon; import io.noties.markwon.MarkwonConfiguration; import io.noties.markwon.MarkwonPlugin; import io.noties.markwon.core.MarkwonTheme; -import me.saket.bettermovementmethod.BetterLinkMovementMethod; import ml.docilealligator.infinityforreddit.Infinity; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; @@ -46,9 +45,10 @@ import ml.docilealligator.infinityforreddit.asynctasks.InsertSubredditData; import ml.docilealligator.infinityforreddit.bottomsheetfragments.CopyTextBottomSheetFragment; import ml.docilealligator.infinityforreddit.bottomsheetfragments.UrlMenuBottomSheetFragment; import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; +import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFixed; import ml.docilealligator.infinityforreddit.events.ChangeNetworkStatusEvent; +import ml.docilealligator.infinityforreddit.markdown.EvenBetterLinkMovementMethod; import ml.docilealligator.infinityforreddit.markdown.CustomMarkwonAdapter; -import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFixed; import ml.docilealligator.infinityforreddit.markdown.EmoteCloseBracketInlineProcessor; import ml.docilealligator.infinityforreddit.markdown.EmotePlugin; import ml.docilealligator.infinityforreddit.markdown.ImageAndGifEntry; @@ -153,7 +153,7 @@ public class SidebarFragment extends Fragment { }); } }; - BetterLinkMovementMethod.OnLinkLongClickListener onLinkLongClickListener = (textView, url) -> { + EvenBetterLinkMovementMethod.OnLinkLongClickListener onLinkLongClickListener = (textView, url) -> { UrlMenuBottomSheetFragment urlMenuBottomSheetFragment = UrlMenuBottomSheetFragment.newInstance(url); urlMenuBottomSheetFragment.show(getChildFragmentManager(), null); return true; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/CustomMarkwonAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/CustomMarkwonAdapter.java index 25e63d2c..c3c84ee3 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/CustomMarkwonAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/CustomMarkwonAdapter.java @@ -120,8 +120,18 @@ public class CustomMarkwonAdapter extends MarkwonAdapter { entry.bindHolder(markwon, holder, node); if (holder.itemView instanceof SpoilerOnClickTextView) { - holder.itemView.setOnClickListener(onClickListener); - holder.itemView.setOnLongClickListener(onLongClickListener); + SpoilerOnClickTextView textView = (SpoilerOnClickTextView) holder.itemView; + holder.itemView.setOnClickListener(view -> { + if (onClickListener != null && textView.getSelectionStart() == -1 && textView.getSelectionEnd() == -1) { + onClickListener.onClick(view); + } + }); + holder.itemView.setOnLongClickListener(view -> { + if (onLongClickListener != null && textView.getSelectionStart() == -1 && textView.getSelectionEnd() == -1) { + return onLongClickListener.onLongClick(view); + } + return false; + }); } else if (holder.itemView instanceof HorizontalScrollView) { TableLayout tableLayout = holder.itemView.findViewById(R.id.table_layout); if (tableLayout != null) { @@ -132,15 +142,16 @@ public class CustomMarkwonAdapter extends MarkwonAdapter { if (tableRow.getChildAt(j) instanceof TextView) { TextView textView = (TextView) tableRow.getChildAt(j); tableRow.getChildAt(j).setOnClickListener(view -> { - if (textView.getSelectionStart() == -1 && textView.getSelectionEnd() == -1) { + if (onClickListener != null && textView.getSelectionStart() == -1 && textView.getSelectionEnd() == -1) { onClickListener.onClick(view); } }); tableRow.getChildAt(j).setOnLongClickListener(view -> { - if (textView.getSelectionStart() == -1 && textView.getSelectionEnd() == -1) { + if (onLongClickListener != null && textView.getSelectionStart() == -1 && textView.getSelectionEnd() == -1) { onLongClickListener.onLongClick(view); + return true; } - return true; + return false; }); } } @@ -158,12 +169,12 @@ public class CustomMarkwonAdapter extends MarkwonAdapter { if (holder instanceof ImageAndGifEntry.Holder) { if (!((ImageAndGifEntry.Holder) holder).binding.captionTextViewMarkdownImageAndGifBlock.hasOnClickListeners()) { ((ImageAndGifEntry.Holder) holder).binding.captionTextViewMarkdownImageAndGifBlock.setOnClickListener(view -> { - if (((ImageAndGifEntry.Holder) holder).binding.captionTextViewMarkdownImageAndGifBlock.getSelectionStart() == -1 && ((ImageAndGifEntry.Holder) holder).binding.captionTextViewMarkdownImageAndGifBlock.getSelectionEnd() == -1) { + if (onClickListener != null && ((ImageAndGifEntry.Holder) holder).binding.captionTextViewMarkdownImageAndGifBlock.getSelectionStart() == -1 && ((ImageAndGifEntry.Holder) holder).binding.captionTextViewMarkdownImageAndGifBlock.getSelectionEnd() == -1) { onClickListener.onClick(view); } }); ((ImageAndGifEntry.Holder) holder).binding.captionTextViewMarkdownImageAndGifBlock.setOnLongClickListener(view -> { - if (((ImageAndGifEntry.Holder) holder).binding.captionTextViewMarkdownImageAndGifBlock.getSelectionStart() == -1 && ((ImageAndGifEntry.Holder) holder).binding.captionTextViewMarkdownImageAndGifBlock.getSelectionEnd() == -1) { + if (onLongClickListener != null && ((ImageAndGifEntry.Holder) holder).binding.captionTextViewMarkdownImageAndGifBlock.getSelectionStart() == -1 && ((ImageAndGifEntry.Holder) holder).binding.captionTextViewMarkdownImageAndGifBlock.getSelectionEnd() == -1) { return onLongClickListener.onLongClick(view); } return false; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/EvenBetterLinkMovementMethod.java b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/EvenBetterLinkMovementMethod.java new file mode 100644 index 00000000..d3c4909d --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/EvenBetterLinkMovementMethod.java @@ -0,0 +1,450 @@ +package ml.docilealligator.infinityforreddit.markdown; + +import android.app.Activity; +import android.graphics.RectF; +import android.text.Layout; +import android.text.Selection; +import android.text.Spannable; +import android.text.Spanned; +import android.text.method.LinkMovementMethod; +import android.text.style.BackgroundColorSpan; +import android.text.style.ClickableSpan; +import android.text.style.URLSpan; +import android.text.util.Linkify; +import android.view.HapticFeedbackConstants; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.TextView; + +import ml.docilealligator.infinityforreddit.R; + +public class EvenBetterLinkMovementMethod extends LinkMovementMethod { + private static EvenBetterLinkMovementMethod singleInstance; + private static final int LINKIFY_NONE = -2; + + private OnLinkClickListener onLinkClickListener; + private OnLinkLongClickListener onLinkLongClickListener; + private final RectF touchedLineBounds = new RectF(); + private boolean isUrlHighlighted; + private ClickableSpan clickableSpanUnderTouchOnActionDown; + private int activeTextViewHashcode; + private LongPressTimer ongoingLongPressTimer; + private boolean wasLongPressRegistered; + + public interface OnLinkClickListener { + /** + * @param textView The TextView on which a click was registered. + * @param url The clicked URL. + * @return True if this click was handled. False to let Android handle the URL. + */ + boolean onClick(TextView textView, String url); + } + + public interface OnLinkLongClickListener { + /** + * @param textView The TextView on which a long-click was registered. + * @param url The long-clicked URL. + * @return True if this long-click was handled. False to let Android handle the URL (as a short-click). + */ + boolean onLongClick(TextView textView, String url); + } + + /** + * Return a new instance of BetterLinkMovementMethod. + */ + public static EvenBetterLinkMovementMethod newInstance() { + return new EvenBetterLinkMovementMethod(); + } + + /** + * @param linkifyMask One of {@link Linkify#ALL}, {@link Linkify#PHONE_NUMBERS}, {@link Linkify#MAP_ADDRESSES}, + * {@link Linkify#WEB_URLS} and {@link Linkify#EMAIL_ADDRESSES}. + * @param textViews The TextViews on which a {@link EvenBetterLinkMovementMethod} should be registered. + * @return The registered {@link EvenBetterLinkMovementMethod} on the TextViews. + */ + public static EvenBetterLinkMovementMethod linkify(int linkifyMask, TextView... textViews) { + EvenBetterLinkMovementMethod movementMethod = newInstance(); + for (TextView textView : textViews) { + addLinks(linkifyMask, movementMethod, textView); + } + return movementMethod; + } + + /** + * Like {@link #linkify(int, TextView...)}, but can be used for TextViews with HTML links. + * + * @param textViews The TextViews on which a {@link EvenBetterLinkMovementMethod} should be registered. + * @return The registered {@link EvenBetterLinkMovementMethod} on the TextViews. + */ + public static EvenBetterLinkMovementMethod linkifyHtml(TextView... textViews) { + return linkify(LINKIFY_NONE, textViews); + } + + /** + * Recursively register a {@link EvenBetterLinkMovementMethod} on every TextView inside a layout. + * + * @param linkifyMask One of {@link Linkify#ALL}, {@link Linkify#PHONE_NUMBERS}, {@link Linkify#MAP_ADDRESSES}, + * {@link Linkify#WEB_URLS} and {@link Linkify#EMAIL_ADDRESSES}. + * @return The registered {@link EvenBetterLinkMovementMethod} on the TextViews. + */ + public static EvenBetterLinkMovementMethod linkify(int linkifyMask, ViewGroup viewGroup) { + EvenBetterLinkMovementMethod movementMethod = newInstance(); + rAddLinks(linkifyMask, viewGroup, movementMethod); + return movementMethod; + } + + /** + * Like {@link #linkify(int, TextView...)}, but can be used for TextViews with HTML links. + * + * @return The registered {@link EvenBetterLinkMovementMethod} on the TextViews. + */ + @SuppressWarnings("unused") + public static EvenBetterLinkMovementMethod linkifyHtml(ViewGroup viewGroup) { + return linkify(LINKIFY_NONE, viewGroup); + } + + /** + * Recursively register a {@link EvenBetterLinkMovementMethod} on every TextView inside a layout. + * + * @param linkifyMask One of {@link Linkify#ALL}, {@link Linkify#PHONE_NUMBERS}, {@link Linkify#MAP_ADDRESSES}, + * {@link Linkify#WEB_URLS} and {@link Linkify#EMAIL_ADDRESSES}. + * @return The registered {@link EvenBetterLinkMovementMethod} on the TextViews. + */ + public static EvenBetterLinkMovementMethod linkify(int linkifyMask, Activity activity) { + // Find the layout passed to setContentView(). + ViewGroup activityLayout = ((ViewGroup) ((ViewGroup) activity.findViewById(Window.ID_ANDROID_CONTENT)).getChildAt(0)); + + EvenBetterLinkMovementMethod movementMethod = newInstance(); + rAddLinks(linkifyMask, activityLayout, movementMethod); + return movementMethod; + } + + /** + * Like {@link #linkify(int, TextView...)}, but can be used for TextViews with HTML links. + * + * @return The registered {@link EvenBetterLinkMovementMethod} on the TextViews. + */ + @SuppressWarnings("unused") + public static EvenBetterLinkMovementMethod linkifyHtml(Activity activity) { + return linkify(LINKIFY_NONE, activity); + } + + /** + * Get a static instance of BetterLinkMovementMethod. Do note that registering a click listener on the returned + * instance is not supported because it will potentially be shared on multiple TextViews. + */ + @SuppressWarnings("unused") + public static EvenBetterLinkMovementMethod getInstance() { + if (singleInstance == null) { + singleInstance = new EvenBetterLinkMovementMethod(); + } + return singleInstance; + } + + protected EvenBetterLinkMovementMethod() { + } + + /** + * Set a listener that will get called whenever any link is clicked on the TextView. + */ + public EvenBetterLinkMovementMethod setOnLinkClickListener(OnLinkClickListener clickListener) { + if (this == singleInstance) { + throw new UnsupportedOperationException("Setting a click listener on the instance returned by getInstance() is not supported to avoid memory " + + "leaks. Please use newInstance() or any of the linkify() methods instead."); + } + + this.onLinkClickListener = clickListener; + return this; + } + + /** + * Set a listener that will get called whenever any link is clicked on the TextView. + */ + public EvenBetterLinkMovementMethod setOnLinkLongClickListener(OnLinkLongClickListener longClickListener) { + if (this == singleInstance) { + throw new UnsupportedOperationException("Setting a long-click listener on the instance returned by getInstance() is not supported to avoid " + + "memory leaks. Please use newInstance() or any of the linkify() methods instead."); + } + + this.onLinkLongClickListener = longClickListener; + return this; + } + +// ======== PUBLIC APIs END ======== // + + private static void rAddLinks(int linkifyMask, ViewGroup viewGroup, EvenBetterLinkMovementMethod movementMethod) { + for (int i = 0; i < viewGroup.getChildCount(); i++) { + View child = viewGroup.getChildAt(i); + + if (child instanceof ViewGroup) { + // Recursively find child TextViews. + rAddLinks(linkifyMask, ((ViewGroup) child), movementMethod); + + } else if (child instanceof TextView) { + TextView textView = (TextView) child; + addLinks(linkifyMask, movementMethod, textView); + } + } + } + + private static void addLinks(int linkifyMask, EvenBetterLinkMovementMethod movementMethod, TextView textView) { + textView.setMovementMethod(movementMethod); + if (linkifyMask != LINKIFY_NONE) { + Linkify.addLinks(textView, linkifyMask); + } + } + + @Override + public boolean onTouchEvent(final TextView textView, Spannable text, MotionEvent event) { + if (activeTextViewHashcode != textView.hashCode()) { + // Bug workaround: TextView stops calling onTouchEvent() once any URL is highlighted. + // A hacky solution is to reset any "autoLink" property set in XML. But we also want + // to do this once per TextView. + activeTextViewHashcode = textView.hashCode(); + textView.setAutoLinkMask(0); + } + + final ClickableSpan clickableSpanUnderTouch = findClickableSpanUnderTouch(textView, text, event); + if (event.getAction() == MotionEvent.ACTION_DOWN) { + clickableSpanUnderTouchOnActionDown = clickableSpanUnderTouch; + } + final boolean touchStartedOverAClickableSpan = clickableSpanUnderTouchOnActionDown != null; + + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + if (clickableSpanUnderTouch != null) { + highlightUrl(textView, clickableSpanUnderTouch, text); + } + + if (touchStartedOverAClickableSpan && onLinkLongClickListener != null) { + LongPressTimer.OnTimerReachedListener longClickListener = new LongPressTimer.OnTimerReachedListener() { + @Override + public void onTimerReached() { + wasLongPressRegistered = true; + removeUrlHighlightColor(textView); + if (dispatchUrlLongClick(textView, clickableSpanUnderTouch)) { + textView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + } + } + }; + startTimerForRegisteringLongClick(textView, longClickListener); + } + return touchStartedOverAClickableSpan; + + case MotionEvent.ACTION_UP: + // Register a click only if the touch started and ended on the same URL. + if (!wasLongPressRegistered && touchStartedOverAClickableSpan && clickableSpanUnderTouch == clickableSpanUnderTouchOnActionDown) { + dispatchUrlClick(textView, clickableSpanUnderTouch); + } + cleanupOnTouchUp(textView); + + // Consume this event even if we could not find any spans to avoid letting Android handle this event. + // Android's TextView implementation has a bug where links get clicked even when there is no more text + // next to the link and the touch lies outside its bounds in the same direction. + return touchStartedOverAClickableSpan; + + case MotionEvent.ACTION_CANCEL: + cleanupOnTouchUp(textView); + return false; + + case MotionEvent.ACTION_MOVE: + // Stop listening for a long-press as soon as the user wanders off to unknown lands. + if (clickableSpanUnderTouch != clickableSpanUnderTouchOnActionDown) { + removeLongPressCallback(textView); + } + + if (!wasLongPressRegistered) { + // Toggle highlight. + if (clickableSpanUnderTouch != null) { + highlightUrl(textView, clickableSpanUnderTouch, text); + } else { + removeUrlHighlightColor(textView); + } + } + + return touchStartedOverAClickableSpan; + + default: + return false; + } + } + + private void cleanupOnTouchUp(TextView textView) { + wasLongPressRegistered = false; + clickableSpanUnderTouchOnActionDown = null; + removeUrlHighlightColor(textView); + removeLongPressCallback(textView); + } + + /** + * Determines the touched location inside the TextView's text and returns the ClickableSpan found under it (if any). + * + * @return The touched ClickableSpan or null. + */ + protected ClickableSpan findClickableSpanUnderTouch(TextView textView, Spannable text, MotionEvent event) { + // 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); + for (final Object span : spans) { + if (span instanceof ClickableSpan) { + return (ClickableSpan) span; + } + } + // No ClickableSpan found under the touched location. + return null; + + } else { + // Touch lies outside the line's horizontal bounds where no spans should exist. + return null; + } + } + + /** + * Adds a background color span at clickableSpan's location. + */ + protected void highlightUrl(TextView textView, ClickableSpan clickableSpan, Spannable text) { + if (isUrlHighlighted) { + return; + } + isUrlHighlighted = true; + + int spanStart = text.getSpanStart(clickableSpan); + int spanEnd = text.getSpanEnd(clickableSpan); + BackgroundColorSpan highlightSpan = new BackgroundColorSpan(textView.getHighlightColor()); + text.setSpan(highlightSpan, spanStart, spanEnd, Spannable.SPAN_INCLUSIVE_INCLUSIVE); + + textView.setTag(R.id.bettermovementmethod_highlight_background_span, highlightSpan); + + Selection.setSelection(text, spanStart, spanEnd); + } + + /** + * Removes the highlight color under the Url. + */ + protected void removeUrlHighlightColor(TextView textView) { + if (!isUrlHighlighted) { + return; + } + isUrlHighlighted = false; + + Spannable text = (Spannable) textView.getText(); + BackgroundColorSpan highlightSpan = (BackgroundColorSpan) textView.getTag(R.id.bettermovementmethod_highlight_background_span); + text.removeSpan(highlightSpan); + + Selection.removeSelection(text); + } + + protected void startTimerForRegisteringLongClick(TextView textView, LongPressTimer.OnTimerReachedListener longClickListener) { + ongoingLongPressTimer = new LongPressTimer(); + ongoingLongPressTimer.setOnTimerReachedListener(longClickListener); + textView.postDelayed(ongoingLongPressTimer, ViewConfiguration.getLongPressTimeout()); + } + + /** + * Remove the long-press detection timer. + */ + protected void removeLongPressCallback(TextView textView) { + if (ongoingLongPressTimer != null) { + textView.removeCallbacks(ongoingLongPressTimer); + ongoingLongPressTimer = null; + } + } + + protected void dispatchUrlClick(TextView textView, ClickableSpan clickableSpan) { + ClickableSpanWithText clickableSpanWithText = ClickableSpanWithText.ofSpan(textView, clickableSpan); + boolean handled = onLinkClickListener != null && onLinkClickListener.onClick(textView, clickableSpanWithText.text()); + + if (!handled) { + // Let Android handle this click. + clickableSpanWithText.span().onClick(textView); + } + } + + protected boolean dispatchUrlLongClick(TextView textView, ClickableSpan clickableSpan) { + ClickableSpanWithText clickableSpanWithText = ClickableSpanWithText.ofSpan(textView, clickableSpan); + boolean handled = onLinkLongClickListener != null && onLinkLongClickListener.onLongClick(textView, clickableSpanWithText.text()); + + if (!handled) { + // Let Android handle this long click as a short-click. + clickableSpanWithText.span().onClick(textView); + } + + return true; + } + + protected static final class LongPressTimer implements Runnable { + private LongPressTimer.OnTimerReachedListener onTimerReachedListener; + + protected interface OnTimerReachedListener { + void onTimerReached(); + } + + @Override + public void run() { + onTimerReachedListener.onTimerReached(); + } + + public void setOnTimerReachedListener(LongPressTimer.OnTimerReachedListener listener) { + onTimerReachedListener = listener; + } + } + + /** + * A wrapper to support all {@link ClickableSpan}s that may or may not provide URLs. + */ + protected static class ClickableSpanWithText { + private ClickableSpan span; + private String text; + + protected static ClickableSpanWithText ofSpan(TextView textView, ClickableSpan span) { + Spanned s = (Spanned) textView.getText(); + String text; + if (span instanceof URLSpan) { + text = ((URLSpan) span).getURL(); + } else { + int start = s.getSpanStart(span); + int end = s.getSpanEnd(span); + text = s.subSequence(start, end).toString(); + } + return new ClickableSpanWithText(span, text); + } + + protected ClickableSpanWithText(ClickableSpan span, String text) { + this.span = span; + this.text = text; + } + + protected ClickableSpan span() { + return span; + } + + protected String text() { + return text; + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/MarkdownUtils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/MarkdownUtils.java index 45e6f384..b9b906fd 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/MarkdownUtils.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/MarkdownUtils.java @@ -19,7 +19,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.R; public class MarkdownUtils { @@ -35,7 +34,7 @@ public class MarkdownUtils { @NonNull ImageAndGifPlugin imageAndGifPlugin, int markdownColor, int spoilerBackgroundColor, - @Nullable BetterLinkMovementMethod.OnLinkLongClickListener onLinkLongClickListener) { + @Nullable EvenBetterLinkMovementMethod.OnLinkLongClickListener onLinkLongClickListener) { return Markwon.builder(context) .usePlugin(MarkwonInlineParserPlugin.create(plugin -> { plugin.excludeInlineProcessor(HtmlInlineProcessor.class); @@ -60,7 +59,7 @@ public class MarkdownUtils { @NonNull public static Markwon createDescriptionMarkwon(Context context, MarkwonPlugin miscPlugin, - BetterLinkMovementMethod.OnLinkLongClickListener onLinkLongClickListener) { + EvenBetterLinkMovementMethod.OnLinkLongClickListener onLinkLongClickListener) { return Markwon.builder(context) .usePlugin(MarkwonInlineParserPlugin.create(plugin -> { plugin.excludeInlineProcessor(HtmlInlineProcessor.class); @@ -84,14 +83,14 @@ public class MarkdownUtils { @NonNull public static Markwon createLinksOnlyMarkwon(@NonNull Context context, @NonNull MarkwonPlugin miscPlugin, - @Nullable BetterLinkMovementMethod.OnLinkLongClickListener onLinkLongClickListener) { + @Nullable EvenBetterLinkMovementMethod.OnLinkLongClickListener onLinkLongClickListener) { return Markwon.builder(context) .usePlugin(MarkwonInlineParserPlugin.create(plugin -> { plugin.excludeInlineProcessor(HtmlInlineProcessor.class); plugin.excludeInlineProcessor(BangInlineProcessor.class); })) .usePlugin(miscPlugin) - .usePlugin(MovementMethodPlugin.create(BetterLinkMovementMethod.newInstance().setOnLinkLongClickListener(onLinkLongClickListener))) + .usePlugin(MovementMethodPlugin.create(EvenBetterLinkMovementMethod.newInstance().setOnLinkLongClickListener(onLinkLongClickListener))) .usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS)) .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 index 1b343e6a..4ff7dcf9 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerAwareMovementMethod.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerAwareMovementMethod.java @@ -10,12 +10,10 @@ 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 + * Extension of {@link EvenBetterLinkMovementMethod} that handles {@link SpoilerSpan}s */ -public class SpoilerAwareMovementMethod extends BetterLinkMovementMethod { +public class SpoilerAwareMovementMethod extends EvenBetterLinkMovementMethod { private final RectF touchedLineBounds = new RectF(); @Override @@ -85,12 +83,12 @@ public class SpoilerAwareMovementMethod extends BetterLinkMovementMethod { } @Override - protected void dispatchUrlLongClick(TextView textView, ClickableSpan clickableSpan) { + protected boolean dispatchUrlLongClick(TextView textView, ClickableSpan clickableSpan) { if (clickableSpan instanceof SpoilerSpan) { ((SpoilerSpan) clickableSpan).onLongClick(textView); - return; + return false; } - super.dispatchUrlLongClick(textView, clickableSpan); + return super.dispatchUrlLongClick(textView, clickableSpan); } @Override 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 6651867b..9a63ae24 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerSpan.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerSpan.java @@ -8,8 +8,6 @@ import android.view.View; import android.widget.TextView; import androidx.annotation.NonNull; -import androidx.transition.AutoTransition; -import androidx.transition.TransitionManager; import ml.docilealligator.infinityforreddit.customviews.SpoilerOnClickTextView; -- cgit v1.2.3