diff --git a/src/org/thoughtcrime/securesms/ConversationActivity.java b/src/org/thoughtcrime/securesms/ConversationActivity.java index a36789e37..8312097c0 100644 --- a/src/org/thoughtcrime/securesms/ConversationActivity.java +++ b/src/org/thoughtcrime/securesms/ConversationActivity.java @@ -550,6 +550,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults); } + public void setDraftText(String txt) { + composeText.setText(txt); + composeText.setSelection(composeText.getText().length()); + } + //////// Event Handlers private void handleEphemeralMessages() { diff --git a/src/org/thoughtcrime/securesms/ConversationItem.java b/src/org/thoughtcrime/securesms/ConversationItem.java index 8ab2fb178..9e125e2b4 100644 --- a/src/org/thoughtcrime/securesms/ConversationItem.java +++ b/src/org/thoughtcrime/securesms/ConversationItem.java @@ -32,6 +32,7 @@ import android.text.style.URLSpan; import android.text.util.Linkify; import android.util.AttributeSet; import android.util.TypedValue; +import android.util.Patterns; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; @@ -66,6 +67,8 @@ import org.thoughtcrime.securesms.util.views.Stub; import java.util.HashSet; import java.util.Locale; import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * A view that displays an individual conversation item within a conversation @@ -500,15 +503,44 @@ public class ConversationItem extends LinearLayout } private SpannableString linkifyMessageBody(SpannableString messageBody, boolean shouldLinkifyAllLinks) { - boolean hasLinks = Linkify.addLinks(messageBody, - shouldLinkifyAllLinks ? Linkify.EMAIL_ADDRESSES|Linkify.WEB_URLS|Linkify.PHONE_NUMBERS : 0); + if (!shouldLinkifyAllLinks) { + return messageBody; + } + boolean hasLinks = false; + + Pattern cmdPattern = Pattern.compile("(?<=^|\\s)/[a-zA-Z][a-zA-Z@\\d_/.-]{0,254}"); + hasLinks = Linkify.addLinks(messageBody, cmdPattern, "cmd:", null, null) || hasLinks; + + Linkify.TransformFilter urlFilter = (match, url) -> { + if (url.startsWith("http://") || url.startsWith("https://")) { + return url; + } else { + return "https://" + url; + } + }; + + Linkify.MatchFilter matcher = (s, start, end) -> { + URLSpan[] urlSpans = messageBody.getSpans(start, end, URLSpan.class); + for (URLSpan urlSpan : urlSpans) { + int start2 = messageBody.getSpanStart(urlSpan); + int end2 = messageBody.getSpanEnd(urlSpan); + if ((start >= start2 && start < end2) || (end >= start2 && end < end2)) { + return false; + } + } + return true; + }; + + hasLinks = Linkify.addLinks(messageBody, Patterns.EMAIL_ADDRESS, "mailto:", matcher, null) || hasLinks; + hasLinks = Linkify.addLinks(messageBody, Patterns.WEB_URL, "", matcher, urlFilter) || hasLinks; + hasLinks = Linkify.addLinks(messageBody, Patterns.PHONE, "tel:", matcher, null) || hasLinks; if (hasLinks) { URLSpan[] urlSpans = messageBody.getSpans(0, messageBody.length(), URLSpan.class); for (URLSpan urlSpan : urlSpans) { int start = messageBody.getSpanStart(urlSpan); int end = messageBody.getSpanEnd(urlSpan); - messageBody.setSpan(new LongClickCopySpan(urlSpan.getURL()), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + messageBody.setSpan(new LongClickCopySpan(urlSpan.getURL(), this.dcChat.getId()), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } } return messageBody; diff --git a/src/org/thoughtcrime/securesms/util/LongClickCopySpan.java b/src/org/thoughtcrime/securesms/util/LongClickCopySpan.java index 523cd47ad..278ae1e7d 100644 --- a/src/org/thoughtcrime/securesms/util/LongClickCopySpan.java +++ b/src/org/thoughtcrime/securesms/util/LongClickCopySpan.java @@ -14,6 +14,7 @@ import android.widget.Toast; import com.b44t.messenger.DcContact; import com.b44t.messenger.DcContext; +import com.b44t.messenger.DcMsg; import org.thoughtcrime.securesms.ConversationActivity; import org.thoughtcrime.securesms.R; @@ -22,13 +23,16 @@ import org.thoughtcrime.securesms.connect.DcHelper; public class LongClickCopySpan extends URLSpan { private static final String PREFIX_MAILTO = "mailto:"; private static final String PREFIX_TEL = "tel:"; + private static final String PREFIX_CMD = "cmd:"; private boolean isHighlighted; @ColorInt private int highlightColor; + private int chatId; - public LongClickCopySpan(String url) { + public LongClickCopySpan(String url, int chatId) { super(url); + this.chatId = chatId; } private void openChat(Activity activity, DcContact contact) { @@ -44,13 +48,21 @@ public class LongClickCopySpan extends URLSpan { @Override public void onClick(View widget) { String url = getURL(); - if (url.startsWith(PREFIX_MAILTO)) { + if (url.startsWith(PREFIX_CMD)) { + try { + String cmd = url.substring(PREFIX_CMD.length()); + ConversationActivity activity = (ConversationActivity) widget.getContext(); + activity.setDraftText(cmd + " "); + } catch (Exception e) { + e.printStackTrace(); + } + } else if (url.startsWith(PREFIX_MAILTO)) { try { String addr = prepareUrl(url); Activity activity = (Activity) widget.getContext(); DcContext dcContext = DcHelper.getContext(activity); DcContact contact = dcContext.getContact(dcContext.createContact(null, addr)); - if (contact.getId()!=0 && dcContext.getChatIdByContactId(contact.getId())!=0) { + if (contact.getId() != 0 && dcContext.getChatIdByContactId(contact.getId()) != 0) { openChat(activity, contact); } else { new AlertDialog.Builder(activity) @@ -61,31 +73,35 @@ public class LongClickCopySpan extends URLSpan { .setNegativeButton(R.string.cancel, null) .show(); } - } - catch(Exception e) { + } catch (Exception e) { e.printStackTrace(); } - } - else { + } else { super.onClick(widget); } } void onLongClick(View widget) { Context context = widget.getContext(); - String preparedUrl = prepareUrl(getURL()); + String url = getURL(); - new AlertDialog.Builder(context) - .setTitle(preparedUrl) - .setItems(new CharSequence[]{ - context.getString(R.string.menu_copy_to_clipboard) - }, - (dialogInterface, i) -> { - copyUrl(context, preparedUrl); - Toast.makeText(context, context.getString(R.string.copied_to_clipboard), Toast.LENGTH_SHORT).show(); - }) - .setNegativeButton(R.string.cancel, null) - .show(); + if (url.startsWith(PREFIX_CMD)) { + copyUrl(context, url.substring(PREFIX_CMD.length())); + Toast.makeText(context, context.getString(R.string.copied_to_clipboard), Toast.LENGTH_SHORT).show(); + } else { + String preparedUrl = prepareUrl(url); + new AlertDialog.Builder(context) + .setTitle(preparedUrl) + .setItems(new CharSequence[]{ + context.getString(R.string.menu_copy_to_clipboard) + }, + (dialogInterface, i) -> { + copyUrl(context, preparedUrl); + Toast.makeText(context, context.getString(R.string.copied_to_clipboard), Toast.LENGTH_SHORT).show(); + }) + .setNegativeButton(R.string.cancel, null) + .show(); + } } @Override