From a3947a9b221a2a04d5498887f1b1a9d682d31715 Mon Sep 17 00:00:00 2001 From: M66B Date: Mon, 15 Feb 2021 10:47:03 +0100 Subject: [PATCH] Record number of new messages per group --- app/src/main/java/eu/faircode/email/Core.java | 95 ++++++++++++++----- .../eu/faircode/email/ServiceSynchronize.java | 38 +------- 2 files changed, 74 insertions(+), 59 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/Core.java b/app/src/main/java/eu/faircode/email/Core.java index ba6f4d7340..0046cf814b 100644 --- a/app/src/main/java/eu/faircode/email/Core.java +++ b/app/src/main/java/eu/faircode/email/Core.java @@ -32,6 +32,7 @@ import android.os.Build; import android.os.Bundle; import android.os.OperationCanceledException; import android.os.SystemClock; +import android.service.notification.StatusBarNotification; import android.text.Html; import android.text.TextUtils; import android.util.Pair; @@ -3634,7 +3635,7 @@ class Core { } } - static void notifyMessages(Context context, List messages, Map> groupNotifying, boolean foreground) { + static void notifyMessages(Context context, List messages, NotificationData data, boolean foreground) { if (messages == null) messages = new ArrayList<>(); @@ -3663,8 +3664,10 @@ class Core { " biometrics=" + biometrics + "/" + biometric_notify + " summary=" + notify_summary); + Map newMessages = new HashMap<>(); + Map> groupMessages = new HashMap<>(); - for (long group : groupNotifying.keySet()) + for (long group : data.groupNotifying.keySet()) groupMessages.put(group, new ArrayList<>()); // Current @@ -3699,28 +3702,29 @@ class Core { long group = (pro && message.accountNotify ? message.account : 0); if (!message.folderUnified) group = -message.folder; - if (!groupNotifying.containsKey(group)) - groupNotifying.put(group, new ArrayList()); + if (!data.groupNotifying.containsKey(group)) + data.groupNotifying.put(group, new ArrayList()); if (!groupMessages.containsKey(group)) groupMessages.put(group, new ArrayList()); if (message.notifying != 0) { long id = message.id * message.notifying; - if (!groupNotifying.get(group).contains(id) && - !groupNotifying.get(group).contains(-id)) { + if (!data.groupNotifying.get(group).contains(id) && + !data.groupNotifying.get(group).contains(-id)) { Log.i("Notify database=" + id); - groupNotifying.get(group).add(id); + data.groupNotifying.get(group).add(id); } } - if (!(message.ui_seen || message.ui_ignored || message.ui_hide)) { + if (!message.ui_seen && !message.ui_ignored && !message.ui_hide) { // This assumes the messages are properly ordered + Integer current = newMessages.get(group); + newMessages.put(group, current == null ? 1 : current + 1); + if (groupMessages.get(group).size() < MAX_NOTIFICATION_COUNT) groupMessages.get(group).add(message); - else { - if (!message.ui_ignored) - db.message().setMessageUiIgnored(message.id, true); - } + else + db.message().setMessageUiIgnored(message.id, true); } } @@ -3728,7 +3732,7 @@ class Core { for (long group : groupMessages.keySet()) { List add = new ArrayList<>(); List update = new ArrayList<>(); - List remove = new ArrayList<>(groupNotifying.get(group)); + List remove = new ArrayList<>(data.groupNotifying.get(group)); for (int m = 0; m < groupMessages.get(group).size(); m++) { TupleMessageEx message = groupMessages.get(group).get(m); if (m >= MAX_NOTIFICATION_DISPLAY) { @@ -3755,11 +3759,16 @@ class Core { } } - int new_messages = add.size() - update.size(); + Integer prev = data.newMessages.get(group); + if (prev == null) + prev = 0; + Integer current = newMessages.get(group); + if (current == null) + current = 0; + data.newMessages.put(group, current); - if (notify_summary - ? remove.size() + new_messages == 0 - : remove.size() + add.size() == 0) { + if (prev.equals(current) && + remove.size() + add.size() == 0) { Log.i("Notify unchanged"); continue; } @@ -3767,7 +3776,7 @@ class Core { // Build notifications List notifications = getNotificationUnseen(context, group, groupMessages.get(group), - notify_summary, new_messages, + notify_summary, current - prev, redacted); Log.i("Notify group=" + group + " count=" + notifications.size() + @@ -3784,19 +3793,19 @@ class Core { Log.i("Notify cancel tag=" + tag + " id=" + id); nm.cancel(tag, 1); - groupNotifying.get(group).remove(id); + data.groupNotifying.get(group).remove(id); db.message().setMessageNotifying(Math.abs(id), 0); } for (Long id : add) { - groupNotifying.get(group).add(id); - groupNotifying.get(group).remove(-id); + data.groupNotifying.get(group).add(id); + data.groupNotifying.get(group).remove(-id); db.message().setMessageNotifying(Math.abs(id), (int) Math.signum(id)); } for (NotificationCompat.Builder builder : notifications) { long id = builder.getExtras().getLong("id", 0); - if ((id == 0 && add.size() + remove.size() > 0) || add.contains(id)) { + if ((id == 0 && prev != current) || add.contains(id)) { // https://developer.android.com/training/wearables/notifications/creating if (id == 0) { if (!notify_summary) @@ -3939,7 +3948,7 @@ class Core { .setAllowSystemGeneratedContextualActions(false); if (notify_summary) { - builder.setOnlyAlertOnce(new_messages == 0); + builder.setOnlyAlertOnce(new_messages <= 0); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) if (new_messages > 0) @@ -4744,4 +4753,44 @@ class Core { " total=" + total + " ms"; } } + + static class NotificationData { + private Map newMessages = new HashMap<>(); + private Map> groupNotifying = new HashMap<>(); + + NotificationData(Context context) { + // Get existing notifications + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) + try { + NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + for (StatusBarNotification sbn : nm.getActiveNotifications()) { + String tag = sbn.getTag(); + if (tag != null && tag.startsWith("unseen.")) { + String[] p = tag.split(("\\.")); + long group = Long.parseLong(p[1]); + long id = sbn.getNotification().extras.getLong("id", 0); + + if (!groupNotifying.containsKey(group)) + groupNotifying.put(group, new ArrayList<>()); + + if (id > 0) { + Log.i("Notify restore " + tag + " id=" + id); + groupNotifying.get(group).add(id); + } + } + } + } catch (Throwable ex) { + Log.w(ex); + /* + java.lang.RuntimeException: Unable to create service eu.faircode.email.ServiceSynchronize: java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.List android.content.pm.ParceledListSlice.getList()' on a null object reference + at android.app.ActivityThread.handleCreateService(ActivityThread.java:2944) + at android.app.ActivityThread.access$1900(ActivityThread.java:154) + at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1474) + at android.os.Handler.dispatchMessage(Handler.java:102) + at android.os.Looper.loop(Looper.java:234) + at android.app.ActivityThread.main(ActivityThread.java:5526) + */ + } + } + } } diff --git a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java index 91595aa3b0..ec034f9a65 100644 --- a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java +++ b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java @@ -36,7 +36,6 @@ import android.os.Build; import android.os.Bundle; import android.os.OperationCanceledException; import android.os.PowerManager; -import android.service.notification.StatusBarNotification; import android.text.TextUtils; import androidx.annotation.NonNull; @@ -582,40 +581,7 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences } }); - Map> groupNotifying = new HashMap<>(); - - // Get existing notifications - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) - try { - NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - for (StatusBarNotification sbn : nm.getActiveNotifications()) { - String tag = sbn.getTag(); - if (tag != null && tag.startsWith("unseen.")) { - String[] p = tag.split(("\\.")); - long group = Long.parseLong(p[1]); - long id = sbn.getNotification().extras.getLong("id", 0); - - if (!groupNotifying.containsKey(group)) - groupNotifying.put(group, new ArrayList<>()); - - if (id > 0) { - Log.i("Notify restore " + tag + " id=" + id); - groupNotifying.get(group).add(id); - } - } - } - } catch (Throwable ex) { - Log.w(ex); - /* - java.lang.RuntimeException: Unable to create service eu.faircode.email.ServiceSynchronize: java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.List android.content.pm.ParceledListSlice.getList()' on a null object reference - at android.app.ActivityThread.handleCreateService(ActivityThread.java:2944) - at android.app.ActivityThread.access$1900(ActivityThread.java:154) - at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1474) - at android.os.Handler.dispatchMessage(Handler.java:102) - at android.os.Looper.loop(Looper.java:234) - at android.app.ActivityThread.main(ActivityThread.java:5526) - */ - } + Core.NotificationData notificationData = new Core.NotificationData(this); db.message().liveUnseenNotify().observe(cowner, new Observer>() { private ExecutorService executor = @@ -627,7 +593,7 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences @Override public void run() { try { - Core.notifyMessages(ServiceSynchronize.this, messages, groupNotifying, foreground); + Core.notifyMessages(ServiceSynchronize.this, messages, notificationData, foreground); } catch (SecurityException ex) { Log.w(ex); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSynchronize.this);