mirror of https://github.com/M66B/FairEmail.git
Switched to QuoteSpan
There is special processing for QuoteSpans in Android that doesn't work on extended QuoteSpans
This commit is contained in:
parent
f03717a25c
commit
c1eacc2c80
|
@ -1913,7 +1913,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
|||
}
|
||||
|
||||
// Draw images
|
||||
Spanned spanned = HtmlHelper.fromDocument(context, document, new Html.ImageGetter() {
|
||||
SpannableStringBuilder ssb = HtmlHelper.fromDocument(context, document, new Html.ImageGetter() {
|
||||
@Override
|
||||
public Drawable getDrawable(String source) {
|
||||
Drawable drawable = ImageHelper.decodeImage(context, message.id, source, show_images, zoom, tvBody);
|
||||
|
@ -1927,34 +1927,29 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
|||
}
|
||||
}, null);
|
||||
|
||||
if (show_quotes)
|
||||
return ssb;
|
||||
|
||||
// Replace quote spans
|
||||
final int px = Helper.dp2pixels(context, 24 + (zoom) * 8);
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder(spanned);
|
||||
QuoteSpan[] quoteSpans = builder.getSpans(0, builder.length(), QuoteSpan.class);
|
||||
QuoteSpan[] quoteSpans = ssb.getSpans(0, ssb.length(), QuoteSpan.class);
|
||||
for (QuoteSpan quoteSpan : quoteSpans) {
|
||||
int s = builder.getSpanStart(quoteSpan);
|
||||
int e = builder.getSpanEnd(quoteSpan);
|
||||
|
||||
builder.removeSpan(quoteSpan);
|
||||
|
||||
StyledQuoteSpan squote = new StyledQuoteSpan(context, colorPrimary);
|
||||
builder.setSpan(squote, s, e, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
||||
|
||||
if (!show_quotes)
|
||||
builder.setSpan(
|
||||
new DynamicDrawableSpan() {
|
||||
@Override
|
||||
public Drawable getDrawable() {
|
||||
Drawable d = context.getDrawable(R.drawable.baseline_format_quote_24);
|
||||
d.setTint(colorAccent);
|
||||
d.setBounds(0, 0, px, px);
|
||||
return d;
|
||||
}
|
||||
},
|
||||
s, e, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
||||
int s = ssb.getSpanStart(quoteSpan);
|
||||
int e = ssb.getSpanEnd(quoteSpan);
|
||||
ssb.setSpan(
|
||||
new DynamicDrawableSpan() {
|
||||
@Override
|
||||
public Drawable getDrawable() {
|
||||
Drawable d = context.getDrawable(R.drawable.baseline_format_quote_24);
|
||||
d.setTint(colorAccent);
|
||||
d.setBounds(0, 0, px, px);
|
||||
return d;
|
||||
}
|
||||
},
|
||||
s, e, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
||||
}
|
||||
|
||||
return builder;
|
||||
return ssb;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -77,20 +77,27 @@ public class EditTextCompose extends FixedEditText {
|
|||
return false;
|
||||
html = "<div>" + HtmlHelper.formatPre(text.toString()) + "</div>";
|
||||
}
|
||||
|
||||
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();
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue