From d4c926988684feab6bf509d4b8912427b1c527d4 Mon Sep 17 00:00:00 2001 From: M66B Date: Mon, 19 Oct 2020 12:12:04 +0200 Subject: [PATCH 1/5] Updated F-Droid description --- metadata/en-US/full_description.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/metadata/en-US/full_description.txt b/metadata/en-US/full_description.txt index 5a80128e25..65282a870b 100644 --- a/metadata/en-US/full_description.txt +++ b/metadata/en-US/full_description.txt @@ -1,5 +1,7 @@ FairEmail is easy to setup and works with virtually all email providers, including Gmail, Outlook and Yahoo! +Note that OAuth was not approved for the F-Droid build. For this you'll need to use the Play store version or the GitHub release. + FairEmail might be for you if you value your privacy. FairEmail is an email client only, so you need to bring your own email address. From a12f3068cbf47879d2d200dfed34dadf0a24e0ab Mon Sep 17 00:00:00 2001 From: M66B Date: Mon, 19 Oct 2020 12:47:51 +0200 Subject: [PATCH 2/5] Cleanup favicons --- .../main/java/eu/faircode/email/ContactInfo.java | 16 ++++++++++++++++ .../java/eu/faircode/email/WorkerCleanup.java | 4 ++++ 2 files changed, 20 insertions(+) diff --git a/app/src/main/java/eu/faircode/email/ContactInfo.java b/app/src/main/java/eu/faircode/email/ContactInfo.java index c85b9c9e47..07a4b310e2 100644 --- a/app/src/main/java/eu/faircode/email/ContactInfo.java +++ b/app/src/main/java/eu/faircode/email/ContactInfo.java @@ -101,6 +101,7 @@ public class ContactInfo { private static final int FAVICON_READ_BYTES = 2048; private static final long CACHE_CONTACT_DURATION = 2 * 60 * 1000L; // milliseconds private static final long CACHE_GRAVATAR_DURATION = 2 * 60 * 60 * 1000L; // milliseconds + private static final long CACHE_FAVICON_DURATION = 2 * 7 * 24 * 60 * 60 * 1000L; // milliseconds private ContactInfo() { } @@ -137,6 +138,21 @@ public class ContactInfo { return (new Date().getTime() - time > CACHE_CONTACT_DURATION); } + static void cleanup(Context context) { + long now = new Date().getTime(); + + // Favicons + Log.i("Cleanup favicons"); + File[] favicons = new File(context.getCacheDir(), "favicons").listFiles(); + if (favicons != null) + for (File file : favicons) + if (file.lastModified() + CACHE_FAVICON_DURATION < now) { + Log.i("Deleting " + file); + if (!file.delete()) + Log.w("Error deleting " + file); + } + } + static void clearCache(Context context) { clearCache(context, true); } diff --git a/app/src/main/java/eu/faircode/email/WorkerCleanup.java b/app/src/main/java/eu/faircode/email/WorkerCleanup.java index f09b44ee72..bbd5045201 100644 --- a/app/src/main/java/eu/faircode/email/WorkerCleanup.java +++ b/app/src/main/java/eu/faircode/email/WorkerCleanup.java @@ -248,6 +248,10 @@ public class WorkerCleanup extends Worker { } } + // Cleanup contact info + if (!manual) + ContactInfo.cleanup(context); + Log.i("Cleanup FTS=" + fts); if (fts) { int deleted = 0; From bcb9f8963d33fbe7765d044722efd34c9dc444cb Mon Sep 17 00:00:00 2001 From: M66B Date: Mon, 19 Oct 2020 14:21:48 +0200 Subject: [PATCH 3/5] Allow setting simple task executor --- .../java/eu/faircode/email/SimpleTask.java | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/SimpleTask.java b/app/src/main/java/eu/faircode/email/SimpleTask.java index 727f04fd46..150a3761fd 100644 --- a/app/src/main/java/eu/faircode/email/SimpleTask.java +++ b/app/src/main/java/eu/faircode/email/SimpleTask.java @@ -54,8 +54,9 @@ public abstract class SimpleTask implements LifecycleObserver { private String name; private Future future; + private ExecutorService localExecutor; - private static ExecutorService executor = null; + private static ExecutorService globalExecutor = null; private static final List tasks = new ArrayList<>(); static final String ACTION_TASK_COUNT = BuildConfig.APPLICATION_ID + ".ACTION_TASK_COUNT"; @@ -70,6 +71,25 @@ public abstract class SimpleTask implements LifecycleObserver { return this; } + public SimpleTask setExecutor(ExecutorService executor) { + this.localExecutor = executor; + return this; + } + + private ExecutorService getExecutor(Context context) { + if (localExecutor != null) + return localExecutor; + + if (globalExecutor == null) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + int threads = prefs.getInt("query_threads", Runtime.getRuntime().availableProcessors()); + Log.i("Task threads=" + threads); + globalExecutor = Helper.getBackgroundExecutor(threads, "task"); + } + + return globalExecutor; + } + public void execute(Context context, LifecycleOwner owner, @NonNull Bundle args, @NonNull String name) { run(context, owner, args, name); } @@ -114,14 +134,7 @@ public abstract class SimpleTask implements LifecycleObserver { onException(args, ex); } - if (executor == null) { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - int threads = prefs.getInt("query_threads", Runtime.getRuntime().availableProcessors()); - Log.i("Task threads=" + threads); - executor = Helper.getBackgroundExecutor(threads, "task"); - } - - future = executor.submit(new Runnable() { + future = getExecutor(context).submit(new Runnable() { private Object data; private long elapsed; private Throwable ex; From 42999a270b3d8e9e16fb1a267b50d7ccaabbb5ec Mon Sep 17 00:00:00 2001 From: M66B Date: Mon, 19 Oct 2020 14:47:09 +0200 Subject: [PATCH 4/5] Fixed race condition --- FAQ.md | 1 - .../main/java/eu/faircode/email/AdapterMessage.java | 13 +------------ .../java/eu/faircode/email/FragmentMessages.java | 13 +++++++++++++ 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/FAQ.md b/FAQ.md index b742b2bd12..71eb2e27f0 100644 --- a/FAQ.md +++ b/FAQ.md @@ -82,7 +82,6 @@ Related questions: * A preview of a message text doesn't (always) appear on Samsung watches because [setLocalOnly](https://developer.android.com/reference/androidx/core/app/NotificationCompat.Builder.html#setLocalOnly(boolean)) seem to be ignored. Message preview texts are known to be displayed correctly on Pebble 2, Fitbit Charge 3, and Mi band 3 wearables. See also [this FAQ](#user-content-faq126). * A [bug in Android 6.0](https://issuetracker.google.com/issues/37068143) causes a crash with *... Invalid offset: ... Valid range is ...* when text is selected and tapping outside of the selected text. This bug has been fixed in Android 6.0.1. * Internal (anchor) links will not work because original messages are shown in an embedded WebView in a scrolling view (the conversation list). This is an Android limitation which cannot be fixed or worked around. -* The expanded/collapsed state and the visibility of the message body are sometimes not in sync. This seems to be caused by a bug in the AndroidX ConstraintLayout. ## Planned features diff --git a/app/src/main/java/eu/faircode/email/AdapterMessage.java b/app/src/main/java/eu/faircode/email/AdapterMessage.java index 70fd8b4a9f..a94652366a 100644 --- a/app/src/main/java/eu/faircode/email/AdapterMessage.java +++ b/app/src/main/java/eu/faircode/email/AdapterMessage.java @@ -3529,16 +3529,6 @@ public class AdapterMessage extends RecyclerView.Adapter Date: Mon, 19 Oct 2020 15:12:01 +0200 Subject: [PATCH 5/5] Factor out bind seen --- .../eu/faircode/email/AdapterMessage.java | 78 ++++++++++--------- 1 file changed, 42 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/AdapterMessage.java b/app/src/main/java/eu/faircode/email/AdapterMessage.java index a94652366a..c1efb15807 100644 --- a/app/src/main/java/eu/faircode/email/AdapterMessage.java +++ b/app/src/main/java/eu/faircode/email/AdapterMessage.java @@ -901,24 +901,10 @@ public class AdapterMessage extends RecyclerView.Adapter 0 ? 1.1f : 1f); - float fz_subject = (font_size_subject == null ? textSize : font_size_subject) * 0.9f; - tvFrom.setTextSize(TypedValue.COMPLEX_UNIT_PX, fz_sender); - tvSubject.setTextSize(TypedValue.COMPLEX_UNIT_PX, fz_subject); tvKeywords.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize * 0.9f); tvFolder.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize * 0.9f); tvLabels.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize * 0.9f); tvPreview.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize * 0.9f); - - if (avatars) { - int px = Math.round(fz_sender + fz_subject + (compact ? 0 : textSize * 0.9f)); - ViewGroup.LayoutParams lparams = ibAvatar.getLayoutParams(); - if (lparams.width != px || lparams.height != px) { - lparams.width = px; - lparams.height = px; - ibAvatar.requestLayout(); - } - } } // Selected / disabled @@ -959,27 +945,7 @@ public class AdapterMessage extends RecyclerView.Adapter 0 ? Typeface.DEFAULT_BOLD : Typeface.DEFAULT); - tvFrom.setTypeface(typeface); - tvSize.setTypeface(typeface); - tvTime.setTypeface(typeface); - if (subject_italic) - if (message.unseen > 0) - tvSubject.setTypeface(null, Typeface.BOLD_ITALIC); - else - tvSubject.setTypeface(null, Typeface.ITALIC); - else - tvSubject.setTypeface(typeface); - tvCount.setTypeface(typeface); - - int colorUnseen = (message.unseen > 0 ? colorUnread : colorRead); - if (!Objects.equals(tvFrom.getTag(), colorUnseen)) { - tvFrom.setTag(colorUnseen); - tvFrom.setTextColor(colorUnseen); - tvSize.setTextColor(colorUnseen); - tvTime.setTextColor(colorUnseen); - } + bindSeen(message); // Account color int colorBackground = @@ -1382,6 +1348,46 @@ public class AdapterMessage extends RecyclerView.Adapter 0 ? 1.1f : 1f); + float fz_subject = (font_size_subject == null ? textSize : font_size_subject) * 0.9f; + tvFrom.setTextSize(TypedValue.COMPLEX_UNIT_PX, fz_sender); + tvSubject.setTextSize(TypedValue.COMPLEX_UNIT_PX, fz_subject); + + if (avatars) { + int px = Math.round(fz_sender + fz_subject + (compact ? 0 : textSize * 0.9f)); + ViewGroup.LayoutParams lparams = ibAvatar.getLayoutParams(); + if (lparams.width != px || lparams.height != px) { + lparams.width = px; + lparams.height = px; + ibAvatar.requestLayout(); + } + } + } + + Typeface typeface = (message.unseen > 0 ? Typeface.DEFAULT_BOLD : Typeface.DEFAULT); + tvFrom.setTypeface(typeface); + tvSize.setTypeface(typeface); + tvTime.setTypeface(typeface); + if (subject_italic) + if (message.unseen > 0) + tvSubject.setTypeface(null, Typeface.BOLD_ITALIC); + else + tvSubject.setTypeface(null, Typeface.ITALIC); + else + tvSubject.setTypeface(typeface); + tvCount.setTypeface(typeface); + + int colorUnseen = (message.unseen > 0 ? colorUnread : colorRead); + if (!Objects.equals(tvFrom.getTag(), colorUnseen)) { + tvFrom.setTag(colorUnseen); + tvFrom.setTextColor(colorUnseen); + tvSize.setTextColor(colorUnseen); + tvTime.setTextColor(colorUnseen); + } + } + private void bindFlagged(TupleMessageEx message, boolean expanded) { boolean pro = ActivityBilling.isPro(context); boolean flagged = (message.count - message.unflagged) > 0; @@ -3048,7 +3054,7 @@ public class AdapterMessage extends RecyclerView.Adapter