diff --git a/app/src/main/java/eu/faircode/email/ActivityEML.java b/app/src/main/java/eu/faircode/email/ActivityEML.java
index 3deff1b2b7..999e5b1092 100644
--- a/app/src/main/java/eu/faircode/email/ActivityEML.java
+++ b/app/src/main/java/eu/faircode/email/ActivityEML.java
@@ -275,7 +275,7 @@ public class ActivityEML extends ActivityBase {
}
int textColorLink = Helper.resolveColor(context, android.R.attr.textColorLink);
- SpannableStringBuilder ssb = new SpannableStringBuilder();
+ SpannableStringBuilder ssb = new SpannableStringBuilderEx();
getStructure(imessage, ssb, 0, textColorLink);
result.structure = ssb;
diff --git a/app/src/main/java/eu/faircode/email/ActivitySignature.java b/app/src/main/java/eu/faircode/email/ActivitySignature.java
index bb2d72c35d..61bdaa8582 100644
--- a/app/src/main/java/eu/faircode/email/ActivitySignature.java
+++ b/app/src/main/java/eu/faircode/email/ActivitySignature.java
@@ -356,7 +356,7 @@ public class ActivitySignature extends ActivityBase {
if (etText.isRaw())
etText.getText().insert(start, "
");
else {
- SpannableStringBuilder ssb = new SpannableStringBuilder(etText.getText());
+ SpannableStringBuilder ssb = new SpannableStringBuilderEx(etText.getText());
ssb.insert(start, " \uFFFC"); // Object replacement character
String source = uri.toString();
Drawable d = ImageHelper.decodeImage(this, -1, source, true, 0, 1.0f, etText);
diff --git a/app/src/main/java/eu/faircode/email/AdapterLog.java b/app/src/main/java/eu/faircode/email/AdapterLog.java
index 2d639fc348..8e0fa10d1f 100644
--- a/app/src/main/java/eu/faircode/email/AdapterLog.java
+++ b/app/src/main/java/eu/faircode/email/AdapterLog.java
@@ -80,7 +80,7 @@ public class AdapterLog extends RecyclerView.Adapter {
private void bindTo(EntityLog log) {
tvTime.setText(TF.format(log.time));
- SpannableStringBuilder ssb = new SpannableStringBuilder(log.data);
+ SpannableStringBuilder ssb = new SpannableStringBuilderEx(log.data);
switch (log.type) {
case General:
break;
diff --git a/app/src/main/java/eu/faircode/email/AdapterMessage.java b/app/src/main/java/eu/faircode/email/AdapterMessage.java
index 3febda8b84..5b9444d2b9 100644
--- a/app/src/main/java/eu/faircode/email/AdapterMessage.java
+++ b/app/src/main/java/eu/faircode/email/AdapterMessage.java
@@ -1996,7 +1996,7 @@ public class AdapterMessage extends RecyclerView.Adapter s.length())
@@ -6118,7 +6118,7 @@ public class FragmentCompose extends FragmentBase {
}
}, null);
- SpannableStringBuilder bodyBuilder = new SpannableStringBuilder(spannedBody);
+ SpannableStringBuilder bodyBuilder = new SpannableStringBuilderEx(spannedBody);
QuoteSpan[] bodySpans = bodyBuilder.getSpans(0, bodyBuilder.length(), QuoteSpan.class);
for (QuoteSpan quoteSpan : bodySpans) {
QuoteSpan q;
diff --git a/app/src/main/java/eu/faircode/email/FragmentDialogOpenLink.java b/app/src/main/java/eu/faircode/email/FragmentDialogOpenLink.java
index 8059b9619c..ea8a071d48 100644
--- a/app/src/main/java/eu/faircode/email/FragmentDialogOpenLink.java
+++ b/app/src/main/java/eu/faircode/email/FragmentDialogOpenLink.java
@@ -641,7 +641,7 @@ public class FragmentDialogOpenLink extends FragmentDialogBase {
String scheme = uri.getScheme();
String host = uri.getHost();
String text = uri.toString();
- SpannableStringBuilder ssb = new SpannableStringBuilder(text);
+ SpannableStringBuilder ssb = new SpannableStringBuilderEx(text);
try {
int textColorLink = Helper.resolveColor(context, android.R.attr.textColorLink);
diff --git a/app/src/main/java/eu/faircode/email/FragmentMessages.java b/app/src/main/java/eu/faircode/email/FragmentMessages.java
index 986ab350b9..adba676ed1 100644
--- a/app/src/main/java/eu/faircode/email/FragmentMessages.java
+++ b/app/src/main/java/eu/faircode/email/FragmentMessages.java
@@ -4640,7 +4640,7 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
PopupMenuLifecycle popupMenu = new PopupMenuLifecycle(getContext(), getViewLifecycleOwner(), vwAnchor);
- SpannableStringBuilder all = new SpannableStringBuilder(getString(R.string.title_language_all));
+ SpannableStringBuilder all = new SpannableStringBuilderEx(getString(R.string.title_language_all));
if (current == null) {
all.setSpan(new StyleSpan(Typeface.BOLD), 0, all.length(), 0);
all.setSpan(new RelativeSizeSpan(HtmlHelper.FONT_LARGE), 0, all.length(), 0);
@@ -4651,7 +4651,7 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
for (int i = 0; i < locales.size(); i++) {
Locale locale = locales.get(i);
String language = locale.getLanguage();
- SpannableStringBuilder title = new SpannableStringBuilder(locale.getDisplayLanguage());
+ SpannableStringBuilder title = new SpannableStringBuilderEx(locale.getDisplayLanguage());
if (language.equals(current)) {
title.setSpan(new StyleSpan(Typeface.BOLD), 0, title.length(), 0);
title.setSpan(new RelativeSizeSpan(HtmlHelper.FONT_LARGE), 0, title.length(), 0);
diff --git a/app/src/main/java/eu/faircode/email/FragmentOptions.java b/app/src/main/java/eu/faircode/email/FragmentOptions.java
index a7df91171d..9de78c315b 100644
--- a/app/src/main/java/eu/faircode/email/FragmentOptions.java
+++ b/app/src/main/java/eu/faircode/email/FragmentOptions.java
@@ -220,7 +220,7 @@ public class FragmentOptions extends FragmentBase {
for (int i = 0; i < tabLayout.getTabCount(); i++) {
Drawable d = context.getDrawable(PAGE_ICONS[i]);
d.setColorFilter(colorAccent, PorterDuff.Mode.SRC_ATOP);
- SpannableStringBuilder title = new SpannableStringBuilder(getString(PAGE_TITLES[i]));
+ SpannableStringBuilder title = new SpannableStringBuilderEx(getString(PAGE_TITLES[i]));
if (i > 0)
title.setSpan(new RelativeSizeSpan(0.85f), 0, title.length(), 0);
tabLayout.getTabAt(i)
diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsEncryption.java b/app/src/main/java/eu/faircode/email/FragmentOptionsEncryption.java
index a89eb1a716..97aacf90e4 100644
--- a/app/src/main/java/eu/faircode/email/FragmentOptionsEncryption.java
+++ b/app/src/main/java/eu/faircode/email/FragmentOptionsEncryption.java
@@ -416,7 +416,7 @@ public class FragmentOptionsEncryption extends FragmentBase implements SharedPre
@Override
protected Spanned onExecute(Context context, Bundle args) {
boolean debug = args.getBoolean("debug");
- SpannableStringBuilder ssb = new SpannableStringBuilder();
+ SpannableStringBuilder ssb = new SpannableStringBuilderEx();
int dp24 = Helper.dp2pixels(context, 24);
diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java b/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java
index 8d0de44c2c..1caf3dc4e5 100644
--- a/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java
+++ b/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java
@@ -1189,7 +1189,7 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc
try {
int start = 0;
int dp24 = Helper.dp2pixels(getContext(), 24);
- SpannableStringBuilder ssb = new SpannableStringBuilder();
+ SpannableStringBuilder ssb = new SpannableStringBuilderEx();
PackageManager pm = getContext().getPackageManager();
PackageInfo pi = pm.getPackageInfo(BuildConfig.APPLICATION_ID, PackageManager.GET_PERMISSIONS);
for (int i = 0; i < pi.requestedPermissions.length; i++) {
diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsSend.java b/app/src/main/java/eu/faircode/email/FragmentOptionsSend.java
index 1d920051cf..ea59e0d5ad 100644
--- a/app/src/main/java/eu/faircode/email/FragmentOptionsSend.java
+++ b/app/src/main/java/eu/faircode/email/FragmentOptionsSend.java
@@ -159,7 +159,7 @@ public class FragmentOptionsSend extends FragmentBase implements SharedPreferenc
List fn = new ArrayList<>();
for (int i = 0; i < fontNameNames.length; i++) {
- SpannableStringBuilder ssb = new SpannableStringBuilder(fontNameNames[i]);
+ SpannableStringBuilder ssb = new SpannableStringBuilderEx(fontNameNames[i]);
ssb.setSpan(new TypefaceSpan(fontNameValues[i]), 0, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
fn.add(ssb);
}
diff --git a/app/src/main/java/eu/faircode/email/HtmlHelper.java b/app/src/main/java/eu/faircode/email/HtmlHelper.java
index e466a82da5..5fe7e596ad 100644
--- a/app/src/main/java/eu/faircode/email/HtmlHelper.java
+++ b/app/src/main/java/eu/faircode/email/HtmlHelper.java
@@ -2260,7 +2260,7 @@ public class HtmlHelper {
}
static Spanned highlightHeaders(Context context, String headers, boolean blocklist) {
- SpannableStringBuilder ssb = new SpannableStringBuilder(headers);
+ SpannableStringBuilder ssb = new SpannableStringBuilderEx(headers);
int textColorLink = Helper.resolveColor(context, android.R.attr.textColorLink);
int index = 0;
@@ -2584,7 +2584,7 @@ public class HtmlHelper {
}, document.body());
// https://developer.android.com/guide/topics/text/spans
- SpannableStringBuilder ssb = new SpannableStringBuilder();
+ SpannableStringBuilder ssb = new SpannableStringBuilderEx();
NodeTraversor.traverse(new NodeVisitor() {
private Element element;
diff --git a/app/src/main/java/eu/faircode/email/PopupMenuLifecycle.java b/app/src/main/java/eu/faircode/email/PopupMenuLifecycle.java
index 6664fdb623..44e232b577 100644
--- a/app/src/main/java/eu/faircode/email/PopupMenuLifecycle.java
+++ b/app/src/main/java/eu/faircode/email/PopupMenuLifecycle.java
@@ -131,7 +131,7 @@ public class PopupMenuLifecycle extends PopupMenu implements LifecycleObserver {
icon.setBounds(0, 0, iconSize, iconSize);
ImageSpan imageSpan = new CenteredImageSpan(icon);
- SpannableStringBuilder ssb = new SpannableStringBuilder(menuItem.getTitle());
+ SpannableStringBuilder ssb = new SpannableStringBuilderEx(menuItem.getTitle());
ssb.insert(0, "\uFFFC\u2002"); // object replacement character, en space
ssb.setSpan(imageSpan, 0, 1, 0);
menuItem.setTitle(ssb);
diff --git a/app/src/main/java/eu/faircode/email/SpannableStringBuilderEx.java b/app/src/main/java/eu/faircode/email/SpannableStringBuilderEx.java
new file mode 100644
index 0000000000..9b3cc6980c
--- /dev/null
+++ b/app/src/main/java/eu/faircode/email/SpannableStringBuilderEx.java
@@ -0,0 +1,70 @@
+package eu.faircode.email;
+
+/*
+ This file is part of FairEmail.
+
+ FairEmail is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ FairEmail is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with FairEmail. If not, see .
+
+ Copyright 2018-2021 by Marcel Bokhorst (M66B)
+*/
+
+import android.text.SpannableStringBuilder;
+
+public class SpannableStringBuilderEx extends SpannableStringBuilder {
+ public SpannableStringBuilderEx() {
+ super();
+ }
+
+ public SpannableStringBuilderEx(CharSequence text) {
+ super(text);
+ }
+
+ public SpannableStringBuilderEx(CharSequence text, int start, int end) {
+ super(text, start, end);
+ }
+
+ @Override
+ public void setSpan(Object what, int start, int end, int flags) {
+ try {
+ super.setSpan(what, start, end, flags);
+ } catch (Throwable ex) {
+ Log.e(ex);
+ /*
+ java.lang.IndexOutOfBoundsException: setSpan (-1 ... -1) starts before 0
+ at android.text.SpannableStringInternal.checkRange(SpannableStringInternal.java:497)
+ at android.text.SpannableStringInternal.setSpan(SpannableStringInternal.java:197)
+ at android.text.SpannableStringInternal.setSpan(SpannableStringInternal.java:184)
+ at android.text.SpannableString.setSpan(SpannableString.java:60)
+ at android.text.Selection.setSelection(Selection.java:96)
+ at android.text.Selection.setSelection(Selection.java:78)
+ at android.widget.Editor$SelectionStartHandleView.updateSelection(Editor.java:7649)
+ at android.widget.Editor$HandleView.positionAtCursorOffset(Editor.java:6886)
+ at android.widget.Editor$HandleView.updatePosition(Editor.java:6920)
+ at android.widget.Editor$PositionListener.onPreDraw(Editor.java:3660)
+ at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:1093)
+ at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3194)
+ at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2046)
+ at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8349)
+ at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1058)
+ at android.view.Choreographer.doCallbacks(Choreographer.java:880)
+ at android.view.Choreographer.doFrame(Choreographer.java:813)
+ at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1043)
+ at android.os.Handler.handleCallback(Handler.java:938)
+ at android.os.Handler.dispatchMessage(Handler.java:99)
+ at android.os.Looper.loop(Looper.java:236)
+ at android.app.ActivityThread.main(ActivityThread.java:7861)
+ */
+ }
+ }
+}
diff --git a/app/src/main/java/eu/faircode/email/StyleHelper.java b/app/src/main/java/eu/faircode/email/StyleHelper.java
index 63925efc13..046e6aa160 100644
--- a/app/src/main/java/eu/faircode/email/StyleHelper.java
+++ b/app/src/main/java/eu/faircode/email/StyleHelper.java
@@ -146,7 +146,7 @@ public class StyleHelper {
int[] titles = new int[]{R.string.title_style_size_small, R.string.title_style_size_medium, R.string.title_style_size_large};
float[] sizes = new float[]{HtmlHelper.FONT_SMALL, 1.0f, HtmlHelper.FONT_LARGE};
for (int i = 0; i < ids.length; i++) {
- SpannableStringBuilder ssb = new SpannableStringBuilder(context.getString(titles[i]));
+ SpannableStringBuilder ssb = new SpannableStringBuilderEx(context.getString(titles[i]));
ssb.setSpan(new RelativeSizeSpan(sizes[i]), 0, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
smenu.add(R.id.group_style_size, ids[i], i, ssb);
}
@@ -156,7 +156,7 @@ public class StyleHelper {
String[] fontNameValues = anchor.getResources().getStringArray(R.array.fontNameValues);
SubMenu smenu = popupMenu.getMenu().findItem(R.id.menu_style_font).getSubMenu();
for (int i = 0; i < fontNameNames.length; i++) {
- SpannableStringBuilder ssb = new SpannableStringBuilder(fontNameNames[i]);
+ SpannableStringBuilder ssb = new SpannableStringBuilderEx(fontNameNames[i]);
ssb.setSpan(getTypefaceSpan(fontNameValues[i], context), 0, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
smenu.add(R.id.group_style_font, i, 0, ssb);
}