Allow long press to copy any link in a message

Stephen Paul Weber created

Change summary

build.gradle                                                        |  1 
src/main/java/eu/siacs/conversations/ui/ConversationFragment.java   | 11 
src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java | 13 
src/main/java/eu/siacs/conversations/ui/util/ShareUtil.java         | 34 
src/main/res/menu/message_context.xml                               |  4 
5 files changed, 30 insertions(+), 33 deletions(-)

Detailed changes

build.gradle 🔗

@@ -110,6 +110,7 @@ dependencies {
     implementation 'androidx.recyclerview:recyclerview:1.1.0'
     implementation 'com.github.ipld:java-cid:v1.3.1'
     implementation 'com.splitwise:tokenautocomplete:3.0.2'
+    implementation 'me.saket:better-link-movement-method:2.2.0'
     implementation urlFile('https://gateway.pinata.cloud/ipfs/QmeqMiLxHi8AAjXobxr3QTfa1bSSLyAu86YviAqQnjxCjM/libwebrtc.aar', 'libwebrtc.aar')
     // INSERT
 }

src/main/java/eu/siacs/conversations/ui/ConversationFragment.java 🔗

@@ -1321,7 +1321,6 @@ public class ConversationFragment extends XmppFragment
             menu.setHeaderTitle(R.string.message_options);
             MenuItem openWith = menu.findItem(R.id.open_with);
             MenuItem copyMessage = menu.findItem(R.id.copy_message);
-            MenuItem copyLink = menu.findItem(R.id.copy_link);
             MenuItem quoteMessage = menu.findItem(R.id.quote_message);
             MenuItem retryDecryption = menu.findItem(R.id.retry_decryption);
             MenuItem correctMessage = menu.findItem(R.id.correct_message);
@@ -1346,13 +1345,6 @@ public class ConversationFragment extends XmppFragment
                     && t == null) {
                 copyMessage.setVisible(true);
                 quoteMessage.setVisible(!showError && MessageUtils.prepareQuote(m).length() > 0);
-                String body = m.getMergedBody().toString();
-                if (ShareUtil.containsXmppUri(body)) {
-                    copyLink.setTitle(R.string.copy_jabber_id);
-                    copyLink.setVisible(true);
-                } else if (Patterns.AUTOLINK_WEB_URL.matcher(body).find()) {
-                    copyLink.setVisible(true);
-                }
             }
             if (m.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED && !deleted) {
                 retryDecryption.setVisible(true);
@@ -1442,9 +1434,6 @@ public class ConversationFragment extends XmppFragment
             case R.id.copy_message:
                 ShareUtil.copyToClipboard(activity, selectedMessage);
                 return true;
-            case R.id.copy_link:
-                ShareUtil.copyLinkToClipboard(activity, selectedMessage);
-                return true;
             case R.id.quote_message:
                 quoteMessage(selectedMessage);
                 return true;

src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java 🔗

@@ -20,6 +20,7 @@ import android.text.style.RelativeSizeSpan;
 import android.text.style.StyleSpan;
 import android.text.style.URLSpan;
 import android.util.DisplayMetrics;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
@@ -51,6 +52,8 @@ import java.util.regex.Pattern;
 
 import io.ipfs.cid.Cid;
 
+import me.saket.bettermovementmethod.BetterLinkMovementMethod;
+
 import eu.siacs.conversations.Config;
 import eu.siacs.conversations.R;
 import eu.siacs.conversations.crypto.axolotl.FingerprintStatus;
@@ -76,9 +79,9 @@ import eu.siacs.conversations.ui.text.QuoteSpan;
 import eu.siacs.conversations.ui.util.AvatarWorkerTask;
 import eu.siacs.conversations.ui.util.MyLinkify;
 import eu.siacs.conversations.ui.util.QuoteHelper;
+import eu.siacs.conversations.ui.util.ShareUtil;
 import eu.siacs.conversations.ui.util.StyledAttributes;
 import eu.siacs.conversations.ui.util.ViewUtil;
-import eu.siacs.conversations.ui.widget.ClickableMovementMethod;
 import eu.siacs.conversations.utils.CryptoHelper;
 import eu.siacs.conversations.utils.Emoticons;
 import eu.siacs.conversations.utils.GeoHelper;
@@ -559,7 +562,13 @@ public class MessageAdapter extends ArrayAdapter<Message> {
             MyLinkify.addLinks(body, message.getConversation().getAccount());
             viewHolder.messageBody.setAutoLinkMask(0);
             viewHolder.messageBody.setText(body);
-            viewHolder.messageBody.setMovementMethod(ClickableMovementMethod.getInstance());
+            BetterLinkMovementMethod method = BetterLinkMovementMethod.newInstance();
+            method.setOnLinkLongClickListener((tv, url) -> {
+                tv.dispatchTouchEvent(MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0f, 0f, 0));
+                ShareUtil.copyLinkToClipboard(activity, url);
+                return true;
+            });
+            viewHolder.messageBody.setMovementMethod(method);
         } else {
             viewHolder.messageBody.setText("");
             viewHolder.messageBody.setTextIsSelectable(false);

src/main/java/eu/siacs/conversations/ui/util/ShareUtil.java 🔗

@@ -108,26 +108,28 @@ public class ShareUtil {
 		}
 	}
 
+	public static void copyLinkToClipboard(final XmppActivity activity, final String url) {
+		final Uri uri = Uri.parse(url);
+		if ("xmpp".equals(uri.getScheme())) {
+			try {
+				final Jid jid = new XmppUri(uri).getJid();
+				if (activity.copyTextToClipboard(jid.asBareJid().toString(), R.string.account_settings_jabber_id)) {
+					Toast.makeText(activity, R.string.jabber_id_copied_to_clipboard, Toast.LENGTH_SHORT).show();
+				}
+			} catch (final Exception e) { }
+		} else {
+			if (activity.copyTextToClipboard(url, R.string.web_address)) {
+				Toast.makeText(activity, R.string.url_copied_to_clipboard, Toast.LENGTH_SHORT).show();
+			}
+		}
+	}
+
 	public static void copyLinkToClipboard(final XmppActivity activity, final Message message) {
 		final SpannableStringBuilder body = message.getMergedBody();
 		MyLinkify.addLinks(body, true);
 		for (final URLSpan urlspan : body.getSpans(0, body.length() - 1, URLSpan.class)) {
-			final Uri uri = Uri.parse(urlspan.getURL());
-			if ("xmpp".equals(uri.getScheme())) {
-				try {
-					final Jid jid = new XmppUri(uri).getJid();
-					if (activity.copyTextToClipboard(jid.asBareJid().toString(), R.string.account_settings_jabber_id)) {
-						Toast.makeText(activity,R.string.jabber_id_copied_to_clipboard, Toast.LENGTH_SHORT).show();
-					}
-					return;
-				} catch (final Exception e) {
-					return;
-				}
-			} else {
-				if (activity.copyTextToClipboard(urlspan.getURL(),R.string.web_address)) {
-					Toast.makeText(activity,R.string.url_copied_to_clipboard, Toast.LENGTH_SHORT).show();
-				}
-			}
+			copyLinkToClipboard(activity, urlspan.getURL());
+			return;
 		}
 	}
 

src/main/res/menu/message_context.xml 🔗

@@ -16,10 +16,6 @@
         android:title="@string/copy_to_clipboard"
         android:visible="false" />
 
-    <item
-        android:id="@+id/copy_link"
-        android:title="@string/copy_link"
-        android:visible="false" />
     <item
         android:id="@+id/quote_message"
         android:title="@string/quote"