From d0b02d85eddda7a52c296f988020d4bc217f4843 Mon Sep 17 00:00:00 2001 From: M66B Date: Tue, 8 Oct 2019 18:49:17 +0200 Subject: [PATCH] Refactoring --- .../eu/faircode/email/AdapterMessage.java | 300 +++++++++--------- .../java/eu/faircode/email/ImageHelper.java | 56 ++-- 2 files changed, 184 insertions(+), 172 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/AdapterMessage.java b/app/src/main/java/eu/faircode/email/AdapterMessage.java index 716727ec2f..00d8aaa0ed 100644 --- a/app/src/main/java/eu/faircode/email/AdapterMessage.java +++ b/app/src/main/java/eu/faircode/email/AdapterMessage.java @@ -1428,178 +1428,172 @@ public class AdapterMessage extends RecyclerView.Adapter() { @Override - public void run() { - new SimpleTask() { - @Override - protected Object onExecute(final Context context, final Bundle args) throws IOException { - TupleMessageEx message = (TupleMessageEx) args.getSerializable("message"); - boolean show_full = args.getBoolean("show_full"); - boolean show_images = args.getBoolean("show_images"); - boolean show_quotes = args.getBoolean("show_quotes"); - int zoom = args.getInt("zoom"); + protected Object onExecute(final Context context, final Bundle args) throws IOException { + TupleMessageEx message = (TupleMessageEx) args.getSerializable("message"); + boolean show_full = args.getBoolean("show_full"); + boolean show_images = args.getBoolean("show_images"); + boolean show_quotes = args.getBoolean("show_quotes"); + int zoom = args.getInt("zoom"); - if (message == null || !message.content) - return null; + if (message == null || !message.content) + return null; - File file = message.getFile(context); - if (!file.exists()) - return null; + File file = message.getFile(context); + if (!file.exists()) + return null; - String body = Helper.readText(file); - Document document = JsoupEx.parse(body); + String body = Helper.readText(file); + Document document = JsoupEx.parse(body); - // Check for inline encryption - int begin = body.indexOf(Helper.PGP_BEGIN_MESSAGE); - int end = body.indexOf(Helper.PGP_END_MESSAGE); - args.putBoolean("iencrypted", begin >= 0 && begin < end); + // Check for inline encryption + int begin = body.indexOf(Helper.PGP_BEGIN_MESSAGE); + int end = body.indexOf(Helper.PGP_END_MESSAGE); + args.putBoolean("iencrypted", begin >= 0 && begin < end); - // Check for images - boolean has_images = false; - for (Element img : document.select("img")) { - if (inline) { - String src = img.attr("src"); - if (!src.startsWith("cid:")) { - has_images = true; - break; - } - } else { - has_images = true; - break; - } + // Check for images + boolean has_images = false; + for (Element img : document.select("img")) { + if (inline) { + String src = img.attr("src"); + if (!src.startsWith("cid:")) { + has_images = true; + break; } - args.putBoolean("has_images", has_images); + } else { + has_images = true; + break; + } + } + args.putBoolean("has_images", has_images); - if (show_full) { - HtmlHelper.removeViewportLimitations(document); - if (inline || show_images) - HtmlHelper.embedInlineImages(context, message.id, document); + if (show_full) { + HtmlHelper.removeViewportLimitations(document); + if (inline || show_images) + HtmlHelper.embedInlineImages(context, message.id, document); - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - boolean disable_tracking = prefs.getBoolean("disable_tracking", true); - if (disable_tracking) - HtmlHelper.removeTrackingPixels(context, document); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + boolean disable_tracking = prefs.getBoolean("disable_tracking", true); + if (disable_tracking) + HtmlHelper.removeTrackingPixels(context, document); - if (debug) { - Document format = JsoupEx.parse(document.html()); - format.outputSettings().prettyPrint(true).outline(true).indentAmount(1); - Element pre = document.createElement("pre"); - pre.text(format.html()); - document.body().appendChild(pre); + if (debug) { + Document format = JsoupEx.parse(document.html()); + format.outputSettings().prettyPrint(true).outline(true).indentAmount(1); + Element pre = document.createElement("pre"); + pre.text(format.html()); + document.body().appendChild(pre); + } + + return document.html(); + } else { + // Collapse quotes + if (!show_quotes) { + for (Element quote : document.select("blockquote")) + quote.html("…"); + body = document.html(); + } + + // Cleanup message + String html = HtmlHelper.sanitize(context, body, show_images); + if (debug) { + Document format = JsoupEx.parse(html); + format.outputSettings().prettyPrint(true).outline(true).indentAmount(1); + String[] lines = format.html().split("\\r?\\n"); + for (int i = 0; i < lines.length; i++) + lines[i] = Html.escapeHtml(lines[i]); + html += "
" + TextUtils.join("
", lines) + "
"; + } + + Spanned spanned = HtmlHelper.fromHtml(html, new Html.ImageGetter() { + @Override + public Drawable getDrawable(String source) { + Drawable drawable = ImageHelper.decodeImage(context, message.id, source, show_images, tvBody); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + if (drawable instanceof AnimatedImageDrawable) + ((AnimatedImageDrawable) drawable).start(); } - return document.html(); - } else { - // Collapse quotes - if (!show_quotes) { - for (Element quote : document.select("blockquote")) - quote.html("…"); - body = document.html(); - } - - // Cleanup message - String html = HtmlHelper.sanitize(context, body, show_images); - if (debug) { - Document format = JsoupEx.parse(html); - format.outputSettings().prettyPrint(true).outline(true).indentAmount(1); - String[] lines = format.html().split("\\r?\\n"); - for (int i = 0; i < lines.length; i++) - lines[i] = Html.escapeHtml(lines[i]); - html += "
" + TextUtils.join("
", lines) + "
"; - } - - Spanned spanned = HtmlHelper.fromHtml(html, new Html.ImageGetter() { - @Override - public Drawable getDrawable(String source) { - Drawable drawable = ImageHelper.decodeImage(context, message.id, source, show_images, tvBody); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - if (drawable instanceof AnimatedImageDrawable) - ((AnimatedImageDrawable) drawable).start(); - } - - return drawable; - } - }, null); - - // Replace quote spans - SpannableStringBuilder builder = new SpannableStringBuilder(spanned); - QuoteSpan[] quoteSpans = builder.getSpans(0, builder.length(), QuoteSpan.class); - for (QuoteSpan quoteSpan : quoteSpans) { - builder.setSpan( - new StyledQuoteSpan(context, colorPrimary), - builder.getSpanStart(quoteSpan), - builder.getSpanEnd(quoteSpan), - builder.getSpanFlags(quoteSpan)); - builder.removeSpan(quoteSpan); - } - - // Make collapsed quotes clickable - if (!show_quotes) { - final int px = Helper.dp2pixels(context, 24 + (zoom) * 8); - - StyledQuoteSpan[] squotes = builder.getSpans(0, builder.length(), StyledQuoteSpan.class); - for (StyledQuoteSpan squote : squotes) - 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; - } - }, - builder.getSpanStart(squote), - builder.getSpanEnd(squote), - builder.getSpanFlags(squote)); - } - - return builder; + return drawable; } + }, null); + + // Replace quote spans + SpannableStringBuilder builder = new SpannableStringBuilder(spanned); + QuoteSpan[] quoteSpans = builder.getSpans(0, builder.length(), QuoteSpan.class); + for (QuoteSpan quoteSpan : quoteSpans) { + builder.setSpan( + new StyledQuoteSpan(context, colorPrimary), + builder.getSpanStart(quoteSpan), + builder.getSpanEnd(quoteSpan), + builder.getSpanFlags(quoteSpan)); + builder.removeSpan(quoteSpan); } - @Override - protected void onExecuted(Bundle args, Object result) { - TupleMessageEx message = (TupleMessageEx) args.getSerializable("message"); - properties.setValue("iencrypted", message.id, args.getBoolean("iencrypted")); + // Make collapsed quotes clickable + if (!show_quotes) { + final int px = Helper.dp2pixels(context, 24 + (zoom) * 8); - TupleMessageEx amessage = getMessage(); - if (amessage == null || !amessage.id.equals(message.id)) - return; - - boolean show_expanded = properties.getValue("expanded", message.id); - if (!show_expanded) - return; - - boolean has_images = args.getBoolean("has_images"); - boolean show_images = properties.getValue("images", message.id); - - if (result instanceof Spanned) { - tvBody.setText((Spanned) result); - tvBody.setTextIsSelectable(false); - tvBody.setTextIsSelectable(true); - tvBody.setMovementMethod(new TouchHandler(message)); - } else if (result instanceof String) - ((WebView) wvBody).loadDataWithBaseURL(null, (String) result, "text/html", "UTF-8", null); - else - throw new IllegalStateException("Result=" + result); - - pbBody.setVisibility(View.GONE); - - // Show attachments/images - cowner.start(); - ibImages.setVisibility(has_images ? View.VISIBLE : View.GONE); + StyledQuoteSpan[] squotes = builder.getSpans(0, builder.length(), StyledQuoteSpan.class); + for (StyledQuoteSpan squote : squotes) + 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; + } + }, + builder.getSpanStart(squote), + builder.getSpanEnd(squote), + builder.getSpanFlags(squote)); } - @Override - protected void onException(Bundle args, Throwable ex) { - Helper.unexpectedError(parentFragment.getFragmentManager(), ex); - } - }.execute(context, owner, args, "message:body"); + return builder; + } } - }); + + @Override + protected void onExecuted(Bundle args, Object result) { + TupleMessageEx message = (TupleMessageEx) args.getSerializable("message"); + properties.setValue("iencrypted", message.id, args.getBoolean("iencrypted")); + + TupleMessageEx amessage = getMessage(); + if (amessage == null || !amessage.id.equals(message.id)) + return; + + boolean show_expanded = properties.getValue("expanded", message.id); + if (!show_expanded) + return; + + boolean has_images = args.getBoolean("has_images"); + boolean show_images = properties.getValue("images", message.id); + + if (result instanceof Spanned) { + tvBody.setText((Spanned) result); + tvBody.setTextIsSelectable(false); + tvBody.setTextIsSelectable(true); + tvBody.setMovementMethod(new TouchHandler(message)); + } else if (result instanceof String) + ((WebView) wvBody).loadDataWithBaseURL(null, (String) result, "text/html", "UTF-8", null); + else + throw new IllegalStateException("Result=" + result); + + pbBody.setVisibility(View.GONE); + + // Show attachments/images + cowner.start(); + ibImages.setVisibility(has_images ? View.VISIBLE : View.GONE); + } + + @Override + protected void onException(Bundle args, Throwable ex) { + Helper.unexpectedError(parentFragment.getFragmentManager(), ex); + } + }.execute(context, owner, args, "message:body"); } private void bindAttachments(final TupleMessageEx message, @Nullable List attachments) { diff --git a/app/src/main/java/eu/faircode/email/ImageHelper.java b/app/src/main/java/eu/faircode/email/ImageHelper.java index 473f9c375d..336bb242fd 100644 --- a/app/src/main/java/eu/faircode/email/ImageHelper.java +++ b/app/src/main/java/eu/faircode/email/ImageHelper.java @@ -58,6 +58,8 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; class ImageHelper { private static final float MIN_LUMINANCE = 0.33f; @@ -369,28 +371,44 @@ class ImageHelper { } } - private static void fitDrawable(final Drawable d, AnnotatedSource a, final View view) { - Rect bounds = d.getBounds(); - int w = bounds.width(); - int h = bounds.height(); + private static void fitDrawable(final Drawable d, final AnnotatedSource a, final View view) { + Semaphore semaphore = new Semaphore(0); - if (a.width == 0 && a.height != 0) - a.width = Math.round(a.height * w / (float) h); - if (a.height == 0 && a.width != 0) - a.height = Math.round(a.width * h / (float) w); + new Handler(view.getContext().getMainLooper()).post(new Runnable() { + @Override + public void run() { + Rect bounds = d.getBounds(); + int w = bounds.width(); + int h = bounds.height(); - if (a.width != 0 && a.height != 0) { - w = Helper.dp2pixels(view.getContext(), a.width); - h = Helper.dp2pixels(view.getContext(), a.height); - d.setBounds(0, 0, w, h); - } + if (a.width == 0 && a.height != 0) + a.width = Math.round(a.height * w / (float) h); + if (a.height == 0 && a.width != 0) + a.height = Math.round(a.width * h / (float) w); - float width = view.getWidth(); - if (w > width) { - float scale = width / w; - w = Math.round(w * scale); - h = Math.round(h * scale); - d.setBounds(0, 0, w, h); + if (a.width != 0 && a.height != 0) { + w = Helper.dp2pixels(view.getContext(), a.width); + h = Helper.dp2pixels(view.getContext(), a.height); + d.setBounds(0, 0, w, h); + } + + float width = view.getWidth(); + if (w > width) { + float scale = width / w; + w = Math.round(w * scale); + h = Math.round(h * scale); + d.setBounds(0, 0, w, h); + } + + semaphore.release(); + } + }); + + try { + if (!semaphore.tryAcquire(1500, TimeUnit.MILLISECONDS)) + Log.e("fitDrawable failed"); + } catch (InterruptedException ex) { + Log.w(ex); } }