From 8511de077a0220e0b95a3b35d048fb6298bb0182 Mon Sep 17 00:00:00 2001 From: M66B Date: Sun, 22 Sep 2019 09:45:37 +0200 Subject: [PATCH] Decouple notifications and widget/badge --- app/src/main/java/eu/faircode/email/Core.java | 32 ------------- .../java/eu/faircode/email/DaoMessage.java | 9 ++++ .../eu/faircode/email/ServiceSynchronize.java | 42 ++++++++++++++++- .../eu/faircode/email/TupleMessageStats.java | 46 +++++++++++++++++++ .../main/java/eu/faircode/email/Widget.java | 6 +-- 5 files changed, 99 insertions(+), 36 deletions(-) create mode 100644 app/src/main/java/eu/faircode/email/TupleMessageStats.java diff --git a/app/src/main/java/eu/faircode/email/Core.java b/app/src/main/java/eu/faircode/email/Core.java index 6771f5b429..98ce13bd48 100644 --- a/app/src/main/java/eu/faircode/email/Core.java +++ b/app/src/main/java/eu/faircode/email/Core.java @@ -108,15 +108,11 @@ import javax.mail.search.OrTerm; import javax.mail.search.ReceivedDateTerm; import javax.mail.search.SearchTerm; -import me.leolin.shortcutbadger.ShortcutBadger; - import static android.os.Process.THREAD_PRIORITY_BACKGROUND; import static androidx.core.app.NotificationCompat.DEFAULT_LIGHTS; import static androidx.core.app.NotificationCompat.DEFAULT_SOUND; class Core { - private static int lastUnseen = -1; - private static final int MAX_NOTIFICATION_COUNT = 100; // per group private static final long AFTER_SEND_DELAY = 10 * 1000L; // milliseconds private static final int SYNC_CHUNCK_SIZE = 200; @@ -2246,16 +2242,6 @@ class Core { } } - static void notifyReset(Context context) { - lastUnseen = -1; - Widget.update(context, -1); - try { - ShortcutBadger.removeCount(context); - } catch (Throwable ex) { - Log.e(ex); - } - } - static void notifyMessages(Context context, List messages, Map> groupNotifying) { if (messages == null) messages = new ArrayList<>(); @@ -2265,21 +2251,14 @@ class Core { if (nm == null) return; - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - boolean badge = prefs.getBoolean("badge", true); - boolean unseen_ignored = prefs.getBoolean("unseen_ignored", false); boolean pro = ActivityBilling.isPro(context); - int unseen = 0; Map> groupMessages = new HashMap<>(); for (long group : groupNotifying.keySet()) groupMessages.put(group, new ArrayList<>()); // Current for (TupleMessageEx message : messages) { - if (!message.ui_seen && (!unseen_ignored || !message.ui_ignored) && message.ui_hide == 0) - unseen++; - // Check if notification channel enabled if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O && message.notifying == 0 && message.from != null && message.from.length > 0) { @@ -2311,17 +2290,6 @@ class Core { } } - // Update widget/badge count - if (lastUnseen < 0 || unseen != lastUnseen) { - lastUnseen = unseen; - Widget.update(context, unseen); - try { - ShortcutBadger.applyCount(context, badge ? unseen : 0); - } catch (Throwable ex) { - Log.e(ex); - } - } - // Difference for (long group : groupMessages.keySet()) { // Difference diff --git a/app/src/main/java/eu/faircode/email/DaoMessage.java b/app/src/main/java/eu/faircode/email/DaoMessage.java index 882645c502..250617ef83 100644 --- a/app/src/main/java/eu/faircode/email/DaoMessage.java +++ b/app/src/main/java/eu/faircode/email/DaoMessage.java @@ -248,6 +248,15 @@ public interface DaoMessage { " WHERE message.id = :id") LiveData liveMessage(long id); + @Query("SELECT COUNT(message.id) AS unseen, SUM(message.ui_ignored) AS ignored" + + " FROM message" + + " JOIN account ON account.id = message.account" + + " JOIN folder ON folder.id = message.folder" + + " WHERE account.`synchronize`" + + " AND folder.notify" + + " AND NOT (message.ui_seen OR message.ui_hide <> 0)") + LiveData liveUnseen(); + @Query("SELECT message.*" + ", account.pop AS accountPop, account.name AS accountName, IFNULL(identity.color, account.color) AS accountColor, account.notify AS accountNotify" + ", folder.name AS folderName, folder.display AS folderDisplay, folder.type AS folderType, folder.read_only AS folderReadOnly" + diff --git a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java index a816689661..3c9c2abba9 100644 --- a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java +++ b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java @@ -78,6 +78,8 @@ import javax.mail.event.MessageCountEvent; import javax.mail.event.StoreEvent; import javax.mail.event.StoreListener; +import me.leolin.shortcutbadger.ShortcutBadger; + import static android.os.Process.THREAD_PRIORITY_BACKGROUND; public class ServiceSynchronize extends ServiceBase { @@ -145,6 +147,28 @@ public class ServiceSynchronize extends ServiceBase { } }); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + + db.message().liveUnseen().observe(this, new Observer() { + private TupleMessageStats lastStats = null; + + @Override + public void onChanged(TupleMessageStats stats) { + if (stats != null) { + boolean unseen_ignored = prefs.getBoolean("unseen_ignored", false); + if (!unseen_ignored || stats.ignored == null) + stats.ignored = 0; + + if (!stats.equals(lastStats)) { + Log.i("Stats " + stats); + lastStats = stats; + + setUnseen(stats.unseen - stats.ignored); + } + } + } + }); + final TwoStateOwner cowner = new TwoStateOwner(this, "liveUnseenNotify"); db.folder().liveSynchronizing().observe(this, new Observer() { @@ -264,7 +288,7 @@ public class ServiceSynchronize extends ServiceBase { ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); cm.unregisterNetworkCallback(onNetworkCallback); - Core.notifyReset(this); + setUnseen(null); try { stopForeground(true); @@ -381,6 +405,22 @@ public class ServiceSynchronize extends ServiceBase { return builder; } + private void setUnseen(Integer unseen) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + boolean badge = prefs.getBoolean("badge", true); + + Widget.update(this, unseen); + + try { + if (unseen == null || !badge) + ShortcutBadger.removeCount(this); + else + ShortcutBadger.applyCount(this, unseen); + } catch (Throwable ex) { + Log.e(ex); + } + } + private void onAlarm() { schedule(this); onReload(true, "alarm"); diff --git a/app/src/main/java/eu/faircode/email/TupleMessageStats.java b/app/src/main/java/eu/faircode/email/TupleMessageStats.java new file mode 100644 index 0000000000..0cd0be2467 --- /dev/null +++ b/app/src/main/java/eu/faircode/email/TupleMessageStats.java @@ -0,0 +1,46 @@ +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-2019 by Marcel Bokhorst (M66B) +*/ + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.Objects; + +public class TupleMessageStats { + public Integer unseen; + public Integer ignored; + + @Override + public boolean equals(@Nullable Object obj) { + if (obj instanceof TupleMessageStats) { + TupleMessageStats other = (TupleMessageStats) obj; + return (Objects.equals(this.unseen, other.unseen) && + Objects.equals(this.ignored, other.ignored)); + } else + return false; + } + + @NonNull + @Override + public String toString() { + return "unseen=" + unseen + " ignored=" + ignored; + } +} diff --git a/app/src/main/java/eu/faircode/email/Widget.java b/app/src/main/java/eu/faircode/email/Widget.java index 57b6373743..28d01a508e 100644 --- a/app/src/main/java/eu/faircode/email/Widget.java +++ b/app/src/main/java/eu/faircode/email/Widget.java @@ -46,13 +46,13 @@ public class Widget extends AppWidgetProvider { }); } - static void update(Context context, int count) { + static void update(Context context, Integer count) { AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); int[] appWidgetIds = AppWidgetManager.getInstance(context).getAppWidgetIds(new ComponentName(context, Widget.class)); update(context, appWidgetManager, appWidgetIds, count); } - private static void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds, int count) { + private static void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds, Integer count) { NumberFormat nf = NumberFormat.getIntegerInstance(); Intent view = new Intent(context, ActivityView.class); @@ -66,7 +66,7 @@ public class Widget extends AppWidgetProvider { views.setOnClickPendingIntent(R.id.widget, pi); - if (count < 0) + if (count == null) views.setTextViewText(R.id.tvCount, "?"); else if (count > 99) views.setTextViewText(R.id.tvCount, "∞");