Detailed changes
@@ -98,6 +98,7 @@ import eu.siacs.conversations.ui.widget.EditMessage;
import eu.siacs.conversations.utils.GeoHelper;
import eu.siacs.conversations.utils.MessageUtils;
import eu.siacs.conversations.utils.NickValidityChecker;
+import eu.siacs.conversations.utils.Patterns;
import eu.siacs.conversations.utils.QuickLoader;
import eu.siacs.conversations.utils.StylingHelper;
import eu.siacs.conversations.utils.TimeframeUtils;
@@ -1052,6 +1053,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
activity.getMenuInflater().inflate(R.menu.message_context, menu);
menu.setHeaderTitle(R.string.message_options);
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);
@@ -1065,6 +1067,13 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
if (!m.isFileOrImage() && !encrypted && !m.isGeoUri() && !m.treatAsDownloadable()) {
copyMessage.setVisible(true);
quoteMessage.setVisible(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) {
retryDecryption.setVisible(true);
@@ -1122,6 +1131,9 @@ 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:
quoteMessage(selectedMessage);
return true;
@@ -92,11 +92,6 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
private static final int RECEIVED = 1;
private static final int STATUS = 2;
private static final int DATE_SEPARATOR = 3;
- private static final Pattern XMPP_PATTERN = Pattern
- .compile("xmpp\\:(?:(?:["
- + Patterns.GOOD_IRI_CHAR
- + "\\;\\/\\?\\@\\&\\=\\#\\~\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])"
- + "|(?:\\%[a-fA-F0-9]{2}))+");
private List<String> highlightedTerm = null;
@@ -553,7 +548,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
StylingHelper.highlight(activity, body, highlightedTerm, StylingHelper.isDarkText(viewHolder.messageBody));
}
- Linkify.addLinks(body, XMPP_PATTERN, "xmpp", XMPPURI_MATCH_FILTER, null);
+ Linkify.addLinks(body, Patterns.XMPP_PATTERN, "xmpp", XMPPURI_MATCH_FILTER, null);
Linkify.addLinks(body, Patterns.AUTOLINK_WEB_URL, "http", WEBURL_MATCH_FILTER, WEBURL_TRANSFORM_FILTER);
Linkify.addLinks(body, GeoHelper.GEO_URI, "geo");
FixedURLSpan.fix(body);
@@ -33,13 +33,22 @@ import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.support.v4.content.ContextCompat;
+import android.util.Log;
import android.widget.Toast;
+import java.net.URL;
+import java.util.regex.Matcher;
+
+import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.DownloadableFile;
import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.persistance.FileBackend;
+import eu.siacs.conversations.ui.ConversationsActivity;
import eu.siacs.conversations.ui.XmppActivity;
+import eu.siacs.conversations.utils.Patterns;
+import eu.siacs.conversations.utils.XmppUri;
+import rocks.xmpp.addr.Jid;
public class ShareUtil {
@@ -98,4 +107,40 @@ public class ShareUtil {
Toast.makeText(activity, R.string.url_copied_to_clipboard, Toast.LENGTH_SHORT).show();
}
}
+
+ public static void copyLinkToClipboard(XmppActivity activity, Message message) {
+ String body = message.getMergedBody().toString();
+ Matcher xmppPatternMatcher = Patterns.XMPP_PATTERN.matcher(body);
+ if (xmppPatternMatcher.find()) {
+ try {
+ Jid jid = new XmppUri(body.substring(xmppPatternMatcher.start(), xmppPatternMatcher.end())).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 (Exception e) {
+ e.printStackTrace();
+ return;
+ }
+ }
+ Matcher webUrlPatternMatcher = Patterns.AUTOLINK_WEB_URL.matcher(body);
+ if (webUrlPatternMatcher.find()) {
+ String url = body.substring(webUrlPatternMatcher.start(),webUrlPatternMatcher.end());
+ if (activity.copyTextToClipboard(url,R.string.web_address)) {
+ Toast.makeText(activity,R.string.url_copied_to_clipboard, Toast.LENGTH_SHORT).show();
+ }
+ }
+ }
+
+ public static boolean containsXmppUri(String body) {
+ Matcher xmppPatternMatcher = Patterns.XMPP_PATTERN.matcher(body);
+ if (xmppPatternMatcher.find()) {
+ try {
+ return new XmppUri(body.substring(xmppPatternMatcher.start(), xmppPatternMatcher.end())).isJidValid();
+ } catch (Exception e) {
+ return false;
+ }
+ }
+ return false;
+ }
}
@@ -26,6 +26,13 @@ import java.util.regex.Pattern;
* Commonly used regular expression patterns.
*/
public class Patterns {
+
+ public static final Pattern XMPP_PATTERN = Pattern
+ .compile("xmpp\\:(?:(?:["
+ + Patterns.GOOD_IRI_CHAR
+ + "\\;\\/\\?\\@\\&\\=\\#\\~\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])"
+ + "|(?:\\%[a-fA-F0-9]{2}))+");
+
/**
* Regular expression to match all IANA top-level domains.
* List accurate as of 2011/07/18. List taken from:
@@ -10,6 +10,11 @@
android:id="@+id/copy_message"
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"
@@ -297,6 +297,8 @@
<string name="send_again">Send again</string>
<string name="file_url">File URL</string>
<string name="url_copied_to_clipboard">Copied URL to clipboard</string>
+ <string name="jabber_id_copied_to_clipboard">Copied Jabberd ID to clipboard</string>
+ <string name="web_address">web address</string>
<string name="scan_qr_code">Scan 2D Barcode</string>
<string name="show_qr_code">Show 2D Barcode</string>
<string name="show_block_list">Show block list</string>
@@ -708,4 +710,6 @@
<string name="view_conversation">View conversation</string>
<string name="pref_use_share_location_plugin">Share Location Plugin</string>
<string name="pref_use_share_location_plugin_summary">Use the Share Location Plugin instead of the build in map</string>
+ <string name="copy_link">Copy web address</string>
+ <string name="copy_jabber_id">Copy Jabber ID</string>
</resources>