From 917c02f46deb9d7eb5ca65e6ba032d8c2911a892 Mon Sep 17 00:00:00 2001 From: M66B Date: Wed, 27 Feb 2019 18:29:58 +0000 Subject: [PATCH] Notify on demand --- FAQ.md | 4 - app/src/main/java/eu/faircode/email/Core.java | 92 ++++++++++++++++++- .../java/eu/faircode/email/DaoMessage.java | 9 +- .../eu/faircode/email/ServiceSynchronize.java | 73 +-------------- .../java/eu/faircode/email/ServiceUI.java | 3 + 5 files changed, 102 insertions(+), 79 deletions(-) diff --git a/FAQ.md b/FAQ.md index 376f6d5b7e..727a31aa56 100644 --- a/FAQ.md +++ b/FAQ.md @@ -1295,10 +1295,6 @@ you can enable on demand synchronization in the account settings. When enabled FairEmail will not keep a connection to the email server anymore, instead you can manually synchronize messages by either using pull-down-to-refresh or by using the folder menu *Synchronize now*. -Note that globally disabling FairEmail with the advanced option *Synchronize*, -by using [a schedule](#user-content-faq78) or by using [a quick settings tile](#user-content-faq30) -will remove the associated [status bar notification](#user-content-faq2), but will also disable new message notifications. -
## Support diff --git a/app/src/main/java/eu/faircode/email/Core.java b/app/src/main/java/eu/faircode/email/Core.java index ed3c12c68c..fc5756bdbc 100644 --- a/app/src/main/java/eu/faircode/email/Core.java +++ b/app/src/main/java/eu/faircode/email/Core.java @@ -13,7 +13,9 @@ import android.os.Build; import android.os.Bundle; import android.os.SystemClock; import android.preference.PreferenceManager; +import android.service.notification.StatusBarNotification; import android.text.TextUtils; +import android.util.LongSparseArray; import com.sun.mail.iap.ConnectionException; import com.sun.mail.iap.Response; @@ -1387,7 +1389,94 @@ class Core { } } - static List getNotificationUnseen(Context context, long account, String accountName, List messages) { + static void notify(Context context, List messages) { + Log.i("Notify messages=" + messages.size()); + + Widget.update(context, messages.size()); + + NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + + LongSparseArray> notifying = new LongSparseArray<>(); + LongSparseArray accountName = new LongSparseArray<>(); + LongSparseArray> accountMessages = new LongSparseArray<>(); + + // Existing + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + for (StatusBarNotification notification : nm.getActiveNotifications()) { + Bundle args = notification.getNotification().extras; + long id = args.getLong("id", 0); + long account = args.getLong("account", 0); + Log.i("Notify showing=" + id); + if (id != 0) { + if (notifying.indexOfKey(account) < 0) { + notifying.put(account, new ArrayList()); + accountMessages.put(account, new ArrayList()); + } + notifying.get(account).add(id); + } + } + } + + // Current + for (TupleMessageEx message : messages) { + long account = (message.accountNotify ? message.account : 0); + accountName.put(account, account > 0 ? message.accountName : null); + if (accountMessages.indexOfKey(account) < 0) { + notifying.put(account, new ArrayList()); + accountMessages.put(account, new ArrayList()); + } + accountMessages.get(account).add(message); + } + + // Difference + for (int i = 0; i < accountMessages.size(); i++) { + long account = accountMessages.keyAt(i); + List notifications = getNotificationUnseen( + context, account, accountName.get(account), accountMessages.get(account)); + + List all = new ArrayList<>(); + List added = new ArrayList<>(); + List removed = notifying.get(account); + for (Notification notification : notifications) { + Long id = notification.extras.getLong("id", 0); + if (id != 0) { + all.add(id); + if (removed.contains(id)) { + removed.remove(id); + Log.i("Notify removing=" + id); + } else { + removed.remove(-id); + added.add(id); + Log.i("Notify adding=" + id); + } + } + } + + int headers = 0; + for (Long id : added) + if (id < 0) + headers++; + + Log.i("Notify account=" + account + + " count=" + notifications.size() + " all=" + all.size() + + " added=" + added.size() + " removed=" + removed.size() + " headers=" + headers); + + if (notifications.size() == 0 || + (Build.VERSION.SDK_INT < Build.VERSION_CODES.O && headers > 0)) + nm.cancel("unseen:" + account + ":0", 1); + + for (Long id : removed) + nm.cancel("unseen:" + account + ":" + Math.abs(id), 1); + + for (Notification notification : notifications) { + long id = notification.extras.getLong("id", 0); + if ((id == 0 && added.size() + removed.size() > 0) || added.contains(id)) + nm.notify("unseen:" + account + ":" + Math.abs(id), 1, notification); + } + } + } + + private static List getNotificationUnseen(Context context, long account, String accountName, List messages) { List notifications = new ArrayList<>(); if (messages.size() == 0) @@ -1496,6 +1585,7 @@ class Core { Bundle args = new Bundle(); args.putLong("id", message.content ? message.id : -message.id); + args.putLong("account", message.accountNotify ? message.account : 0); Intent thread = new Intent(context, ActivityView.class); thread.setAction("thread:" + message.thread); diff --git a/app/src/main/java/eu/faircode/email/DaoMessage.java b/app/src/main/java/eu/faircode/email/DaoMessage.java index 00036a4070..343f04cb1c 100644 --- a/app/src/main/java/eu/faircode/email/DaoMessage.java +++ b/app/src/main/java/eu/faircode/email/DaoMessage.java @@ -207,7 +207,7 @@ public interface DaoMessage { " WHERE message.id = :id") LiveData liveMessage(long id); - @Query("SELECT message.*" + + String notify = "SELECT message.*" + ", 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" + ", identity.name AS identityName, identity.email AS identityEmail, identity.synchronize AS identitySynchronize" + @@ -227,9 +227,14 @@ public interface DaoMessage { " AND NOT message.ui_seen" + " AND NOT message.ui_hide" + " AND NOT message.ui_ignored" + - " ORDER BY message.received") + " ORDER BY message.received"; + + @Query(notify) LiveData> liveUnseenNotify(); + @Query(notify) + List getUnseenNotify(); + @Query("SELECT COUNT(message.id) FROM message" + " JOIN account ON account.id = message.account" + " JOIN folder ON folder.id = message.folder" + diff --git a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java index 88a587d56e..f9a462be42 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.Handler; import android.os.PowerManager; import android.preference.PreferenceManager; -import android.util.LongSparseArray; import com.sun.mail.imap.IMAPFolder; import com.sun.mail.imap.IMAPMessage; @@ -126,79 +125,9 @@ public class ServiceSynchronize extends LifecycleService { }); db.message().liveUnseenNotify().observe(this, new Observer>() { - private LongSparseArray> notifying = new LongSparseArray<>(); - @Override public void onChanged(final List messages) { - Log.i("Notification messages=" + messages.size()); - - Widget.update(ServiceSynchronize.this, messages.size()); - - LongSparseArray accountName = new LongSparseArray<>(); - LongSparseArray> accountMessages = new LongSparseArray<>(); - - for (int i = 0; i < notifying.size(); i++) - accountMessages.put(notifying.keyAt(i), new ArrayList()); - - for (TupleMessageEx message : messages) { - long account = (message.accountNotify ? message.account : 0); - accountName.put(account, account > 0 ? message.accountName : null); - if (accountMessages.indexOfKey(account) < 0) - accountMessages.put(account, new ArrayList()); - accountMessages.get(account).add(message); - if (notifying.indexOfKey(account) < 0) - notifying.put(account, new ArrayList()); - } - - for (int i = 0; i < accountMessages.size(); i++) { - long account = accountMessages.keyAt(i); - List notifications = Core.getNotificationUnseen( - ServiceSynchronize.this, account, accountName.get(account), accountMessages.get(account)); - - List all = new ArrayList<>(); - List added = new ArrayList<>(); - List removed = notifying.get(account); - for (Notification notification : notifications) { - Integer id = (int) notification.extras.getLong("id", 0); - if (id != 0) { - all.add(id); - if (removed.contains(id)) { - removed.remove(id); - Log.i("Notification removing=" + id); - } else { - removed.remove(Integer.valueOf(-id)); - added.add(id); - Log.i("Notification adding=" + id); - } - } - } - - int headers = 0; - for (Integer id : added) - if (id < 0) - headers++; - - Log.i("Notification account=" + account + - " notifications=" + notifications.size() + " all=" + all.size() + - " added=" + added.size() + " removed=" + removed.size() + " headers=" + headers); - - NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - - if (notifications.size() == 0 || - (Build.VERSION.SDK_INT < Build.VERSION_CODES.O && headers > 0)) - nm.cancel("unseen:" + account, 0); - - for (Integer id : removed) - nm.cancel("unseen:" + account, Math.abs(id)); - - for (Notification notification : notifications) { - Integer id = (int) notification.extras.getLong("id", 0); - if ((id == 0 && added.size() + removed.size() > 0) || added.contains(id)) - nm.notify("unseen:" + account, Math.abs(id), notification); - } - - notifying.put(account, all); - } + Core.notify(ServiceSynchronize.this, messages); } }); } diff --git a/app/src/main/java/eu/faircode/email/ServiceUI.java b/app/src/main/java/eu/faircode/email/ServiceUI.java index e8e758f564..f0801ba400 100644 --- a/app/src/main/java/eu/faircode/email/ServiceUI.java +++ b/app/src/main/java/eu/faircode/email/ServiceUI.java @@ -281,6 +281,9 @@ public class ServiceUI extends IntentService { // Synchronize messages Core.onSynchronizeMessages(this, account, folder, (IMAPFolder) ifolder, folder.getSyncArgs(), new Core.State()); + // Notify new messages + Core.notify(this, db.message().getUnseenNotify()); + } catch (Throwable ex) { Log.w(ex); Core.reportError(this, account, folder, ex);