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);