From b32e32274923a94742a9926ef38785f746d41405 Mon Sep 17 00:00:00 2001 From: sk <sk22@mailbox.org> Date: Fri, 23 Dec 2022 17:51:06 +0100 Subject: [PATCH] implement long-click to copy links closes sk22#84 --- .../displayitems/FooterStatusDisplayItem.java | 2 +- .../ui/text/ClickableLinksDelegate.java | 18 +++++++++++++++--- .../android/ui/text/HtmlParser.java | 6 +++--- .../joinmastodon/android/ui/text/LinkSpan.java | 8 +++++++- 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/FooterStatusDisplayItem.java b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/FooterStatusDisplayItem.java index 25cc444a29..a6a5e79d7c 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/FooterStatusDisplayItem.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/FooterStatusDisplayItem.java @@ -150,7 +150,7 @@ private boolean onButtonTouch(View v, MotionEvent event){ v.removeCallbacks(longClickRunnable); v.animate().scaleX(1).scaleY(1).setInterpolator(CubicBezierInterpolator.DEFAULT).setDuration(150).start(); if (disabled) return true; - if (action == MotionEvent.ACTION_UP && eventDuration < ViewConfiguration.getLongPressTimeout()) v.performClick(); + if (action == MotionEvent.ACTION_UP && eventDuration <= ViewConfiguration.getLongPressTimeout()) v.performClick(); else v.startAnimation(opacityIn); } else if (action == MotionEvent.ACTION_DOWN) { touchingView = v; diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/text/ClickableLinksDelegate.java b/mastodon/src/main/java/org/joinmastodon/android/ui/text/ClickableLinksDelegate.java index 482a7eacf5..e3a1bfc61f 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/text/ClickableLinksDelegate.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/text/ClickableLinksDelegate.java @@ -10,6 +10,8 @@ import android.text.Spanned; import android.view.MotionEvent; import android.view.SoundEffectConstants; +import android.view.View; +import android.view.ViewConfiguration; import android.widget.TextView; import me.grishka.appkit.utils.V; @@ -20,7 +22,11 @@ public class ClickableLinksDelegate { private Path hlPath; private LinkSpan selectedSpan; private TextView view; - + + private final Runnable longClickRunnable = () -> { + if (selectedSpan != null) selectedSpan.onLongClick(view.getContext()); + }; + public ClickableLinksDelegate(TextView view) { this.view=view; hlPaint=new Paint(); @@ -30,6 +36,7 @@ public ClickableLinksDelegate(TextView view) { } public boolean onTouch(MotionEvent event) { + long eventDuration = event.getEventTime() - event.getDownTime(); if(event.getAction()==MotionEvent.ACTION_DOWN){ int line=-1; Rect rect=new Rect(); @@ -63,6 +70,7 @@ public boolean onTouch(MotionEvent event) { } hlPath=new Path(); selectedSpan=span; + view.postDelayed(longClickRunnable, ViewConfiguration.getLongPressTimeout()); hlPaint.setColor((span.getColor() & 0x00FFFFFF) | 0x33000000); //l.getSelectionPath(start, end, hlPath); for(int j=lstart;j<=lend;j++){ @@ -90,8 +98,11 @@ public boolean onTouch(MotionEvent event) { } } if(event.getAction()==MotionEvent.ACTION_UP && selectedSpan!=null){ - view.playSoundEffect(SoundEffectConstants.CLICK); - selectedSpan.onClick(view.getContext()); + if (eventDuration <= ViewConfiguration.getLongPressTimeout()) { + view.playSoundEffect(SoundEffectConstants.CLICK); + selectedSpan.onClick(view.getContext()); + } + view.removeCallbacks(longClickRunnable); hlPath=null; selectedSpan=null; view.invalidate(); @@ -100,6 +111,7 @@ public boolean onTouch(MotionEvent event) { if(event.getAction()==MotionEvent.ACTION_CANCEL){ hlPath=null; selectedSpan=null; + view.removeCallbacks(longClickRunnable); view.invalidate(); return false; } diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/text/HtmlParser.java b/mastodon/src/main/java/org/joinmastodon/android/ui/text/HtmlParser.java index e5841f8d53..2e60018321 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/text/HtmlParser.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/text/HtmlParser.java @@ -117,8 +117,8 @@ public void head(@NonNull Node node, int depth){ case "a" -> { String href=el.attr("href"); LinkSpan.Type linkType; + String text=el.text(); if(el.hasClass("hashtag")){ - String text=el.text(); if(text.startsWith("#")){ linkType=LinkSpan.Type.HASHTAG; href=text.substring(1); @@ -136,7 +136,7 @@ public void head(@NonNull Node node, int depth){ }else{ linkType=LinkSpan.Type.URL; } - openSpans.add(new SpanInfo(new LinkSpan(href, null, linkType, accountID), ssb.length(), el)); + openSpans.add(new SpanInfo(new LinkSpan(href, null, linkType, accountID, text), ssb.length(), el)); } case "br" -> ssb.append('\n'); case "span" -> { @@ -260,7 +260,7 @@ public static CharSequence parseLinks(String text){ String url=matcher.group(3); if(TextUtils.isEmpty(matcher.group(4))) url="http://"+url; - ssb.setSpan(new LinkSpan(url, null, LinkSpan.Type.URL, null), matcher.start(3), matcher.end(3), 0); + ssb.setSpan(new LinkSpan(url, null, LinkSpan.Type.URL, null, url), matcher.start(3), matcher.end(3), 0); }while(matcher.find()); // Find more URLs return ssb; } diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/text/LinkSpan.java b/mastodon/src/main/java/org/joinmastodon/android/ui/text/LinkSpan.java index 34eff30739..9cc570efe6 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/text/LinkSpan.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/text/LinkSpan.java @@ -13,12 +13,14 @@ public class LinkSpan extends CharacterStyle { private String link; private Type type; private String accountID; + private String text; - public LinkSpan(String link, OnLinkClickListener listener, Type type, String accountID){ + public LinkSpan(String link, OnLinkClickListener listener, Type type, String accountID, String text){ this.listener=listener; this.link=link; this.type=type; this.accountID=accountID; + this.text=text; } public int getColor(){ @@ -38,6 +40,10 @@ public void onClick(Context context){ } } + public void onLongClick(Context context) { + UiUtils.copyText(context, getType() == Type.URL ? link : text); + } + public String getLink(){ return link; }