diff --git a/src/cheogram/java/com/cheogram/android/SpannedToXHTML.java b/src/cheogram/java/com/cheogram/android/SpannedToXHTML.java index 00d68b10c6d9441a584cd323029acbe6100c5b00..380303744bb10f93f0518c67c2d395efab90571a 100644 --- a/src/cheogram/java/com/cheogram/android/SpannedToXHTML.java +++ b/src/cheogram/java/com/cheogram/android/SpannedToXHTML.java @@ -4,6 +4,7 @@ import android.app.Application; import android.graphics.Typeface; import android.text.Spanned; import android.text.SpannableStringBuilder; +import android.text.ParcelableSpan; import android.text.style.AbsoluteSizeSpan; import android.text.style.AlignmentSpan; import android.text.style.BackgroundColorSpan; @@ -32,9 +33,10 @@ import eu.siacs.conversations.xml.TextNode; public class SpannedToXHTML { private static SpannableStringBuilder cleanSpans(Spanned text) { SpannableStringBuilder newText = new SpannableStringBuilder(text); - SuggestionSpan[] spans = newText.getSpans(0, newText.length(), SuggestionSpan.class); - for (SuggestionSpan span : spans) { - newText.removeSpan(span); + ParcelableSpan[] spans = newText.getSpans(0, newText.length(), ParcelableSpan.class); + for (final var span : spans) { + final var userFlags = (text.getSpanFlags(span) & Spanned.SPAN_USER) >> Spanned.SPAN_USER_SHIFT; + if (span instanceof SuggestionSpan || userFlags == 1) newText.removeSpan(span); } BaseInputConnection.removeComposingSpans(newText); return newText; diff --git a/src/main/java/eu/siacs/conversations/utils/StylingHelper.java b/src/main/java/eu/siacs/conversations/utils/StylingHelper.java index a72010fcbcbc98661eeb8e74a2e00ecb7420ea6d..c5f1693888c90e4c318ca47c8faaf081c337fa4f 100644 --- a/src/main/java/eu/siacs/conversations/utils/StylingHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/StylingHelper.java @@ -77,23 +77,27 @@ public class StylingHelper { } } - public static void format(final Editable editable, int start, int end, @ColorInt int textColor) { + 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); - makeKeywordOpaque(editable, style.getStart(), style.getStart() + keywordLength, textColor); - makeKeywordOpaque(editable, style.getEnd() - keywordLength + 1, style.getEnd() + 1, textColor); + editable.setSpan(createSpanForStyle(style), style.getStart() + keywordLength, style.getEnd() - keywordLength + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | (composing ? 1 << Spanned.SPAN_USER_SHIFT : 0)); + makeKeywordOpaque(editable, style.getStart(), style.getStart() + keywordLength, textColor, composing); + makeKeywordOpaque(editable, style.getEnd() - keywordLength + 1, style.getEnd() + 1, textColor, composing); } } public static void format(final Editable editable, @ColorInt int textColor) { + format(editable, textColor, false); + } + + public static void format(final Editable editable, @ColorInt int textColor, final boolean composing) { int end = 0; Message.MergeSeparator[] spans = editable.getSpans(0, editable.length() - 1, Message.MergeSeparator.class); for (Message.MergeSeparator span : spans) { - format(editable, end, editable.getSpanStart(span), textColor); + format(editable, end, editable.getSpanStart(span), textColor, composing); end = editable.getSpanEnd(span); } - format(editable, end, editable.length() - 1, textColor); + format(editable, end, editable.length() - 1, textColor, composing); } public static void highlight(final TextView view, final Editable editable, final List needles) { @@ -186,11 +190,11 @@ public class StylingHelper { }; } - private static void makeKeywordOpaque(final Editable editable, int start, int end, @ColorInt int fallbackTextColor) { + private static void makeKeywordOpaque(final Editable editable, int start, int end, @ColorInt int fallbackTextColor, final boolean composing) { QuoteSpan[] quoteSpans = editable.getSpans(start, end, QuoteSpan.class); @ColorInt int textColor = quoteSpans.length > 0 ? quoteSpans[0].getColor() : fallbackTextColor; @ColorInt int keywordColor = transformColor(textColor); - editable.setSpan(new ForegroundColorSpan(keywordColor), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + editable.setSpan(new ForegroundColorSpan(keywordColor), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | (composing ? 1 << Spanned.SPAN_USER_SHIFT : 0)); } private static @@ -239,7 +243,7 @@ public class StylingHelper { @Override public void afterTextChanged(Editable editable) { clear(editable); - format(editable, mEditText.getCurrentTextColor()); + format(editable, mEditText.getCurrentTextColor(), true); } } } diff --git a/src/main/java/eu/siacs/conversations/utils/UIHelper.java b/src/main/java/eu/siacs/conversations/utils/UIHelper.java index e9c6290476157f6eeac7fc5e2ef75b671ea7a573..7dab05d6fbd45597d99aa34aabdfc3e267e98dac 100644 --- a/src/main/java/eu/siacs/conversations/utils/UIHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/UIHelper.java @@ -250,7 +250,7 @@ public class UIHelper { fallbackImg.setBounds(0, 0, fallbackImg.getIntrinsicWidth(), fallbackImg.getIntrinsicHeight()); SpannableStringBuilder styledBody = message.getSpannableBody(null, fallbackImg); if (textColor != 0) { - StylingHelper.format(styledBody, 0, styledBody.length() - 1, textColor); + StylingHelper.format(styledBody, 0, styledBody.length() - 1, textColor, false); } MyLinkify.addLinks(styledBody, message.getConversation().getAccount(), message.getConversation().getJid()); SpannableStringBuilder builder = new SpannableStringBuilder();