diff --git a/build.gradle b/build.gradle index 8b32ebc9d..e118011f5 100644 --- a/build.gradle +++ b/build.gradle @@ -89,6 +89,7 @@ dependencies { implementation 'com.github.AppIntro:AppIntro:6.2.0' implementation 'androidx.browser:browser:1.4.0' implementation 'com.otaliastudios:transcoder:0.9.1' // 0.10.4 seems to be buggy + implementation 'me.saket:better-link-movement-method:2.2.0' implementation project(':libs:AXML') } diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 0d5ce5744..c74a5648d 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -1475,7 +1475,6 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke 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); @@ -1495,13 +1494,6 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke deleteMessage.setVisible(true); if (!m.isFileOrImage() && !encrypted && !m.isGeoUri() && !m.treatAsDownloadable() && !unInitiatedButKnownSize && t == null && !m.isMessageDeleted()) { copyMessage.setVisible(true); - 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 (!encrypted && !unInitiatedButKnownSize && t == null) { quoteMessage.setVisible(!showError && QuoteHelper.isMessageQuoteable(m)); @@ -1593,9 +1585,6 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke 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: if (conversation.getMode() == Conversation.MODE_MULTI) { quoteMessage(selectedMessage, user); diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java index 0b7bcded5..5fcac3f13 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -1,5 +1,7 @@ package eu.siacs.conversations.ui.adapter; +import eu.siacs.conversations.ui.widget.ClickableMovementMethod; +import me.saket.bettermovementmethod.BetterLinkMovementMethod; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static eu.siacs.conversations.entities.Message.DELETED_MESSAGE_BODY; import static eu.siacs.conversations.entities.Message.DELETED_MESSAGE_BODY_OLD; @@ -11,6 +13,7 @@ import static eu.siacs.conversations.ui.SettingsActivity.SHOW_MAPS_INSIDE; import static eu.siacs.conversations.ui.util.MyLinkify.removeTrackingParameter; import static eu.siacs.conversations.ui.util.MyLinkify.removeTrailingBracket; import static eu.siacs.conversations.ui.util.MyLinkify.replaceYoutube; +import eu.siacs.conversations.ui.util.ShareUtil; import android.Manifest; import android.annotation.SuppressLint; @@ -35,6 +38,7 @@ import android.text.style.StyleSpan; import android.util.Base64; import android.util.DisplayMetrics; import android.util.Log; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; @@ -88,7 +92,6 @@ import eu.siacs.conversations.ui.util.MyLinkify; import eu.siacs.conversations.ui.util.QuoteHelper; 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.ui.widget.RichLinkView; import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.utils.Emoticons; @@ -698,7 +701,13 @@ public class MessageAdapter extends ArrayAdapter { MyLinkify.addLinks(body, message.getConversation().getAccount()); viewHolder.messageBody.setText(body); viewHolder.messageBody.setAutoLinkMask(0); - 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); diff --git a/src/main/java/eu/siacs/conversations/ui/util/ShareUtil.java b/src/main/java/eu/siacs/conversations/ui/util/ShareUtil.java index 1cb72940b..0501595ce 100644 --- a/src/main/java/eu/siacs/conversations/ui/util/ShareUtil.java +++ b/src/main/java/eu/siacs/conversations/ui/util/ShareUtil.java @@ -47,6 +47,7 @@ import me.drakeet.support.toast.ToastCompat; import android.net.Uri; import android.text.SpannableStringBuilder; import android.text.style.URLSpan; +import android.widget.Toast; public class ShareUtil { @@ -111,26 +112,29 @@ 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)) { - ToastCompat.makeText(activity, R.string.jabber_id_copied_to_clipboard, ToastCompat.LENGTH_SHORT).show(); - } - return; - } catch (final Exception e) { - return; - } - } else { - if (activity.copyTextToClipboard(urlspan.getURL(), R.string.web_address)) { - ToastCompat.makeText(activity, R.string.url_copied_to_clipboard, ToastCompat.LENGTH_SHORT).show(); - } - } + copyLinkToClipboard(activity, urlspan.getURL()); + return; } } diff --git a/src/main/res/menu/message_context.xml b/src/main/res/menu/message_context.xml index 510cd728b..14e81b698 100644 --- a/src/main/res/menu/message_context.xml +++ b/src/main/res/menu/message_context.xml @@ -13,10 +13,6 @@ android:id="@+id/copy_message" android:title="@string/copy_to_clipboard" android:visible="false" /> -