From c1eacc2c80d7ba4679feea17f403844c7a886abd Mon Sep 17 00:00:00 2001 From: M66B Date: Sun, 3 May 2020 14:11:38 +0200 Subject: [PATCH] Switched to QuoteSpan There is special processing for QuoteSpans in Android that doesn't work on extended QuoteSpans --- .../eu/faircode/email/AdapterMessage.java | 43 ++++++------- .../eu/faircode/email/EditTextCompose.java | 21 ++++--- .../eu/faircode/email/FragmentCompose.java | 41 ++++++------ .../java/eu/faircode/email/HtmlHelper.java | 16 +++-- .../eu/faircode/email/StyledQuoteSpan.java | 62 ------------------- 5 files changed, 66 insertions(+), 117 deletions(-) delete mode 100644 app/src/main/java/eu/faircode/email/StyledQuoteSpan.java diff --git a/app/src/main/java/eu/faircode/email/AdapterMessage.java b/app/src/main/java/eu/faircode/email/AdapterMessage.java index 944e14150b..1ac0727c5a 100644 --- a/app/src/main/java/eu/faircode/email/AdapterMessage.java +++ b/app/src/main/java/eu/faircode/email/AdapterMessage.java @@ -1913,7 +1913,7 @@ public class AdapterMessage extends RecyclerView.Adapter"; } + Document document = HtmlHelper.sanitizeCompose(context, html, false); - Spanned paste = HtmlHelper.fromDocument(context, document); + Spanned paste = HtmlHelper.fromHtml(document.html()); int colorPrimary = Helper.resolveColor(context, R.attr.colorPrimary); + int dp3 = Helper.dp2pixels(context, 3); + int dp6 = Helper.dp2pixels(context, 6); SpannableStringBuilder ssb = new SpannableStringBuilder(paste); QuoteSpan[] spans = ssb.getSpans(0, ssb.length(), QuoteSpan.class); - for (QuoteSpan span : spans) { - ssb.setSpan( - new StyledQuoteSpan(context, colorPrimary), - ssb.getSpanStart(span), - ssb.getSpanEnd(span), + for (QuoteSpan quoteSpan : spans) { + QuoteSpan q; + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) + q = new QuoteSpan(colorPrimary); + else + q = new QuoteSpan(colorPrimary, dp3, dp6); + ssb.setSpan(q, + ssb.getSpanStart(quoteSpan), + ssb.getSpanEnd(quoteSpan), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - ssb.removeSpan(span); + ssb.removeSpan(quoteSpan); } int start = getSelectionStart(); diff --git a/app/src/main/java/eu/faircode/email/FragmentCompose.java b/app/src/main/java/eu/faircode/email/FragmentCompose.java index bf823c258b..c0b747346d 100644 --- a/app/src/main/java/eu/faircode/email/FragmentCompose.java +++ b/app/src/main/java/eu/faircode/email/FragmentCompose.java @@ -47,6 +47,7 @@ import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkRequest; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.OperationCanceledException; @@ -485,8 +486,8 @@ public class FragmentCompose extends FragmentBase { // break block quotes boolean broken = false; SpannableStringBuilder ssb = new SpannableStringBuilder(text); - StyledQuoteSpan[] spans = ssb.getSpans(start + 1, start + 1, StyledQuoteSpan.class); - for (StyledQuoteSpan span : spans) { + QuoteSpan[] spans = ssb.getSpans(start + 1, start + 1, QuoteSpan.class); + for (QuoteSpan span : spans) { int s = ssb.getSpanStart(span); int e = ssb.getSpanEnd(span); int f = ssb.getSpanFlags(span); @@ -497,11 +498,19 @@ public class FragmentCompose extends FragmentBase { ssb.charAt(start) == '\n' && ssb.charAt(e - 1) == '\n') { broken = true; - StyledQuoteSpan q1 = new StyledQuoteSpan(getContext(), span.getColor()); + QuoteSpan q1; + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) + q1 = new QuoteSpan(span.getColor()); + else + q1 = new QuoteSpan(span.getColor(), span.getStripeWidth(), span.getGapWidth()); ssb.setSpan(q1, s, start, f); Log.i("Span " + s + "..." + start); - StyledQuoteSpan q2 = new StyledQuoteSpan(getContext(), span.getColor()); + QuoteSpan q2; + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) + q2 = new QuoteSpan(span.getColor()); + else + q2 = new QuoteSpan(span.getColor(), span.getStripeWidth(), span.getGapWidth()); ssb.setSpan(q2, start + 1, e, f); Log.i("Span " + (start + 1) + "..." + e); @@ -4428,6 +4437,8 @@ public class FragmentCompose extends FragmentBase { final boolean show_images = args.getBoolean("show_images", false); int colorPrimary = Helper.resolveColor(context, R.attr.colorPrimary); + int dp3 = Helper.dp2pixels(context, 3); + int dp6 = Helper.dp2pixels(context, 6); DB db = DB.getInstance(context); EntityMessage draft = db.message().getMessage(id); @@ -4449,8 +4460,12 @@ public class FragmentCompose extends FragmentBase { SpannableStringBuilder bodyBuilder = new SpannableStringBuilder(spannedBody); QuoteSpan[] bodySpans = bodyBuilder.getSpans(0, bodyBuilder.length(), QuoteSpan.class); for (QuoteSpan quoteSpan : bodySpans) { - bodyBuilder.setSpan( - new StyledQuoteSpan(context, colorPrimary), + QuoteSpan q; + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) + q = new QuoteSpan(colorPrimary); + else + q = new QuoteSpan(colorPrimary, dp3, dp6); + bodyBuilder.setSpan(q, bodyBuilder.getSpanStart(quoteSpan), bodyBuilder.getSpanEnd(quoteSpan), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); @@ -4463,7 +4478,7 @@ public class FragmentCompose extends FragmentBase { if (!ref.isEmpty()) { Document dref = JsoupEx.parse(ref.outerHtml()); Document quote = HtmlHelper.sanitizeView(context, dref, show_images); - SpannableStringBuilder ssb = HtmlHelper.fromDocument(context, quote, + spannedRef = HtmlHelper.fromDocument(context, quote, new Html.ImageGetter() { @Override public Drawable getDrawable(String source) { @@ -4471,18 +4486,6 @@ public class FragmentCompose extends FragmentBase { } }, null); - - QuoteSpan[] refSpans = ssb.getSpans(0, ssb.length(), QuoteSpan.class); - for (QuoteSpan quoteSpan : refSpans) { - ssb.setSpan( - new StyledQuoteSpan(context, colorPrimary), - ssb.getSpanStart(quoteSpan), - ssb.getSpanEnd(quoteSpan), - Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - ssb.removeSpan(quoteSpan); - } - - spannedRef = ssb; } args.putBoolean("ref_has_images", spannedRef != null && diff --git a/app/src/main/java/eu/faircode/email/HtmlHelper.java b/app/src/main/java/eu/faircode/email/HtmlHelper.java index 74c8182c1e..adcd0237c8 100644 --- a/app/src/main/java/eu/faircode/email/HtmlHelper.java +++ b/app/src/main/java/eu/faircode/email/HtmlHelper.java @@ -1716,10 +1716,11 @@ public class HtmlHelper { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); boolean debug = prefs.getBoolean("debug", false); - int colorAccent = Helper.resolveColor(context, R.attr.colorAccent); - int dp3 = Helper.dp2pixels(context, 3); - int dp6 = Helper.dp2pixels(context, 6); - int dp24 = Helper.dp2pixels(context, 24); + final int colorPrimary = Helper.resolveColor(context, R.attr.colorPrimary); + final int colorAccent = Helper.resolveColor(context, R.attr.colorAccent); + final int dp3 = Helper.dp2pixels(context, 3); + final int dp6 = Helper.dp2pixels(context, 6); + final int dp24 = Helper.dp2pixels(context, 24); // https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements NodeTraversor.traverse(new NodeVisitor() { @@ -1897,7 +1898,12 @@ public class HtmlHelper { case "blockquote": if (start > 0 && ssb.charAt(start - 1) != '\n') ssb.insert(start++, "\n"); - ssb.setSpan(new QuoteSpan(), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) + ssb.setSpan(new QuoteSpan(colorPrimary), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + else + ssb.setSpan(new QuoteSpan(colorPrimary, dp3, dp6), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + if (ssb.length() > 1 && ssb.charAt(ssb.length() - 1) != '\n') ssb.append("\n"); break; diff --git a/app/src/main/java/eu/faircode/email/StyledQuoteSpan.java b/app/src/main/java/eu/faircode/email/StyledQuoteSpan.java deleted file mode 100644 index 03cdee9f9b..0000000000 --- a/app/src/main/java/eu/faircode/email/StyledQuoteSpan.java +++ /dev/null @@ -1,62 +0,0 @@ -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-2020 by Marcel Bokhorst (M66B) -*/ - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.text.Layout; -import android.text.style.QuoteSpan; - -import androidx.annotation.NonNull; - -public class StyledQuoteSpan extends QuoteSpan { - private int stripeWidth; - private int gapWidth; - - StyledQuoteSpan(Context context, int color) { - super(color); - stripeWidth = Helper.dp2pixels(context, 3); - gapWidth = Helper.dp2pixels(context, 6); - } - - @Override - public int getLeadingMargin(boolean first) { - return stripeWidth + gapWidth; - } - - @Override - public void drawLeadingMargin( - @NonNull Canvas c, @NonNull Paint p, - int x, int dir, int top, int baseline, int bottom, - @NonNull CharSequence text, int start, int end, boolean first, - @NonNull Layout layout) { - Paint.Style style = p.getStyle(); - int color = p.getColor(); - - p.setStyle(Paint.Style.FILL); - p.setColor(getColor()); - - c.drawRect(x, top, x + dir * stripeWidth, bottom, p); - - p.setStyle(style); - p.setColor(color); - } -}