From de8fb3e26599bb24b1d2b07be3a0ea410c0695c2 Mon Sep 17 00:00:00 2001 From: Stephen Paul Weber Date: Sun, 8 Sep 2024 13:05:41 -0500 Subject: [PATCH] Don't linkify inside escaped/codeblocks --- .../eu/siacs/conversations/ui/util/MyLinkify.java | 14 +++++++++++++- .../siacs/conversations/utils/StylingHelper.java | 10 +++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/ui/util/MyLinkify.java b/src/main/java/eu/siacs/conversations/ui/util/MyLinkify.java index 1217a6e18a36561f5f02c4205fc0aec43ece7e19..7ebb7666b8b1f2ab83b5bcbd523a7cf8a96dbb8c 100644 --- a/src/main/java/eu/siacs/conversations/ui/util/MyLinkify.java +++ b/src/main/java/eu/siacs/conversations/ui/util/MyLinkify.java @@ -32,6 +32,8 @@ package eu.siacs.conversations.ui.util; import android.net.Uri; import android.os.Build; import android.text.Editable; +import android.text.Spanned; +import android.text.style.TypefaceSpan; import android.text.style.URLSpan; import android.text.util.Linkify; @@ -52,6 +54,7 @@ import eu.siacs.conversations.entities.Roster; import eu.siacs.conversations.ui.text.FixedURLSpan; import eu.siacs.conversations.utils.GeoHelper; import eu.siacs.conversations.utils.Patterns; +import eu.siacs.conversations.utils.StylingHelper; import eu.siacs.conversations.utils.XmppUri; import eu.siacs.conversations.xmpp.Jid; @@ -139,7 +142,16 @@ public class MyLinkify { public static void addLinks(Editable body, Account account, Jid context) { addLinks(body, true); Roster roster = account.getRoster(); + urlspan: for (final URLSpan urlspan : body.getSpans(0, body.length() - 1, URLSpan.class)) { + final var start = body.getSpanStart(urlspan); + for (final var span : body.getSpans(start, start, Object.class)) { + // instanceof TypefaceSpan is to block in XHTML code blocks. Probably a bit heavy-handed but works for now + if ((body.getSpanFlags(span) & Spanned.SPAN_USER) >> Spanned.SPAN_USER_SHIFT == StylingHelper.NOLINKIFY || span instanceof TypefaceSpan) { + body.removeSpan(urlspan); + continue urlspan; + } + } Uri uri = Uri.parse(urlspan.getURL()); if ("xmpp".equals(uri.getScheme())) { try { @@ -153,7 +165,7 @@ public class MyLinkify { String display = xmppUri.toString(); if (jid.asBareJid().equals(context) && xmppUri.isAction("message") && xmppUri.getBody() != null) { display = xmppUri.getBody(); - } else if (jid.asBareJid().equals(context)) { + } else if (jid.asBareJid().equals(context) && xmppUri.parameterString().length() > 0) { display = xmppUri.parameterString(); } else { ListItem item = account.getBookmark(jid); diff --git a/src/main/java/eu/siacs/conversations/utils/StylingHelper.java b/src/main/java/eu/siacs/conversations/utils/StylingHelper.java index 6b0d98d9f1e2cd3c71ff79ba00fed2c13d2b4e3b..46449b76d3ab6fbe0bcbdd428ed450e8ac982685 100644 --- a/src/main/java/eu/siacs/conversations/utils/StylingHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/StylingHelper.java @@ -67,6 +67,7 @@ public class StylingHelper { public static final int XHTML_IGNORE = 1; public static final int XHTML_REMOVE = 2; public static final int XHTML_EMPHASIS = 3; + public static final int NOLINKIFY = 0xf0; private static final List> SPAN_CLASSES = Arrays.asList( StyleSpan.class, @@ -88,7 +89,14 @@ public class StylingHelper { public static void format(final Editable editable, int start, int end, @ColorInt int textColor, final boolean composing) { for (ImStyleParser.Style style : ImStyleParser.parse(editable, start, end)) { final int keywordLength = style.getKeyword().length(); - editable.setSpan(createSpanForStyle(style), style.getStart() + keywordLength, style.getEnd() - keywordLength + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | ("*".equals(style.getKeyword()) || "_".equals(style.getKeyword()) ? XHTML_EMPHASIS << Spanned.SPAN_USER_SHIFT : 0)); + editable.setSpan( + createSpanForStyle(style), + style.getStart() + keywordLength, + style.getEnd() - keywordLength + 1, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | + ("*".equals(style.getKeyword()) || "_".equals(style.getKeyword()) ? XHTML_EMPHASIS << Spanned.SPAN_USER_SHIFT : 0) | + ("`".equals(style.getKeyword()) || "```".equals(style.getKeyword()) ? NOLINKIFY << Spanned.SPAN_USER_SHIFT : 0) + ); makeKeywordOpaque(editable, style.getStart(), style.getStart() + keywordLength + ("```".equals(style.getKeyword()) ? 1 : 0), textColor, composing); makeKeywordOpaque(editable, style.getEnd() - keywordLength + 1, style.getEnd() + 1, textColor, composing); }