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..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 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/FragmentMessages.java b/app/src/main/java/eu/faircode/email/FragmentMessages.java index 72ad81a0d7..bf76cd441f 100644 --- a/app/src/main/java/eu/faircode/email/FragmentMessages.java +++ b/app/src/main/java/eu/faircode/email/FragmentMessages.java @@ -1653,6 +1653,19 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. setValue("expanded", message.id, value); + final int p = adapter.getPositionForKey(message.id); + if (p != NO_POSITION) + rvMessage.post(new Runnable() { + @Override + public void run() { + try { + adapter.notifyItemChanged(p); + } catch (Throwable ex) { + Log.e(ex); + } + } + }); + // Collapse other messages SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); boolean expand_all = prefs.getBoolean("expand_all", false); 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; 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; 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.