From 0149a10fd8c4348300fd77af02a81da4eb7f94fa Mon Sep 17 00:00:00 2001 From: Distopico Vegan Date: Sun, 11 Nov 2018 20:49:02 -0500 Subject: [PATCH] feat: improve new mail notifications per account - add notification groups per account - add notification color account --- .../java/org/dystopia/email/ActivityMain.java | 4 - .../java/org/dystopia/email/DaoMessage.java | 77 +++--- .../org/dystopia/email/FragmentAccount.java | 1 - .../org/dystopia/email/FragmentOptions.java | 2 +- .../main/java/org/dystopia/email/Helper.java | 12 + .../dystopia/email/ServiceSynchronize.java | 230 +++++++++++------- .../org/dystopia/email/TupleMessageEx.java | 1 + .../org/dystopia/email/TupleNotification.java | 41 ++++ 8 files changed, 233 insertions(+), 135 deletions(-) create mode 100644 app/src/main/java/org/dystopia/email/TupleNotification.java diff --git a/app/src/main/java/org/dystopia/email/ActivityMain.java b/app/src/main/java/org/dystopia/email/ActivityMain.java index 0440f4f8..5a7fc5fe 100644 --- a/app/src/main/java/org/dystopia/email/ActivityMain.java +++ b/app/src/main/java/org/dystopia/email/ActivityMain.java @@ -20,17 +20,13 @@ package org.dystopia.email; */ import android.content.Intent; -import android.content.SharedPreferences; import android.os.Bundle; -import android.preference.PreferenceManager; -import android.util.Log; import java.util.List; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.FragmentManager; -import androidx.fragment.app.FragmentTransaction; import androidx.lifecycle.Observer; public class ActivityMain extends AppCompatActivity implements FragmentManager.OnBackStackChangedListener { diff --git a/app/src/main/java/org/dystopia/email/DaoMessage.java b/app/src/main/java/org/dystopia/email/DaoMessage.java index 2b8e97ff..40f41ff4 100644 --- a/app/src/main/java/org/dystopia/email/DaoMessage.java +++ b/app/src/main/java/org/dystopia/email/DaoMessage.java @@ -17,6 +17,7 @@ package org.dystopia.email; along with FairEmail. If not, see . Copyright 2018, Marcel Bokhorst (M66B) + Copyright 2018, Distopico (dystopia project) and contributors */ import java.util.List; @@ -69,34 +70,34 @@ public interface DaoMessage { ", folder.name AS folderName, folder.display AS folderDisplay, folder.type AS folderType" + ", COUNT(message.id) AS count" + ", SUM(CASE WHEN message.ui_seen" + - " OR (folder.id <> :folder AND folder.type = '" + EntityFolder.ARCHIVE + "')" + - " OR (folder.id <> :folder AND folder.type = '" + EntityFolder.OUTBOX + "')" + - " OR (folder.id <> :folder AND folder.type = '" + EntityFolder.DRAFTS + "') THEN 0 ELSE 1 END) AS unseen" + + " OR (folder.id <> :folderId AND folder.type = '" + EntityFolder.ARCHIVE + "')" + + " OR (folder.id <> :folderId AND folder.type = '" + EntityFolder.OUTBOX + "')" + + " OR (folder.id <> :folderId AND folder.type = '" + EntityFolder.DRAFTS + "') THEN 0 ELSE 1 END) AS unseen" + ", SUM(CASE WHEN message.ui_flagged" + - " AND NOT (folder.id <> :folder AND folder.type = '" + EntityFolder.ARCHIVE + "')" + - " AND NOT (folder.id <> :folder AND folder.type = '" + EntityFolder.OUTBOX + "')" + - " AND NOT (folder.id <> :folder AND folder.type = '" + EntityFolder.DRAFTS + "') THEN 0 ELSE 1 END) AS unflagged" + + " AND NOT (folder.id <> :folderId AND folder.type = '" + EntityFolder.ARCHIVE + "')" + + " AND NOT (folder.id <> :folderId AND folder.type = '" + EntityFolder.OUTBOX + "')" + + " AND NOT (folder.id <> :folderId AND folder.type = '" + EntityFolder.DRAFTS + "') THEN 0 ELSE 1 END) AS unflagged" + ", (SELECT COUNT(a.id) FROM attachment a WHERE a.message = message.id) AS attachments" + " FROM message" + " JOIN account ON account.id = message.account" + " JOIN folder ON folder.id = message.folder" + - " JOIN folder f ON f.id = :folder" + + " JOIN folder f ON f.id = :folderId" + " WHERE (message.account = f.account OR folder.type = '" + EntityFolder.OUTBOX + "')" + " AND CASE WHEN (:folderType = '" + EntityFolder.TRASH + "' " + " OR :folderType = '" + EntityFolder.OUTBOX + "') " + " THEN 1" + - " ELSE folder.id = :folder" + + " ELSE folder.id = :folderId" + " END" + " AND (NOT message.ui_hide OR :debug)" + " AND ui_found = :found" + " GROUP BY CASE WHEN message.thread IS NULL THEN message.id ELSE message.thread END" + - " HAVING SUM(CASE WHEN folder.id = :folder THEN 1 ELSE 0 END) > 0" + + " HAVING SUM(CASE WHEN folder.id = :folderId THEN 1 ELSE 0 END) > 0" + " ORDER BY CASE" + " WHEN 'unread' = :sort THEN NOT message.ui_seen" + " WHEN 'starred' = :sort THEN message.ui_flagged" + " ELSE 0" + " END DESC, message.received DESC, message.sent DESC") - DataSource.Factory pagedFolder(long folder, String folderType, String sort, boolean found, boolean debug); + DataSource.Factory pagedFolder(long folderId, String folderType, String sort, boolean found, boolean debug); @Query("SELECT message.*" + ", account.name AS accountName, account.color AS accountColor" + @@ -111,13 +112,13 @@ public interface DaoMessage { " WHERE message.account = :account" + " AND message.thread = :thread" + " AND (NOT message.ui_hide OR :debug)" + - " AND NOT (folder.type = '" + EntityFolder.TRASH + "' AND folder.id <> :folder)" + + " AND NOT (folder.type = '" + EntityFolder.TRASH + "' AND folder.id <> :folderId)" + " ORDER BY CASE" + " WHEN 'unread' = :sort THEN NOT message.ui_seen" + " WHEN 'starred' = :sort THEN message.ui_flagged" + " ELSE 0" + " END DESC, message.received DESC, message.sent DESC") - DataSource.Factory pagedThread(long account, long folder, String thread, String sort, boolean debug); + DataSource.Factory pagedThread(long account, long folderId, String thread, String sort, boolean debug); @Query("SELECT COUNT(id)" + " FROM message" + @@ -131,16 +132,16 @@ public interface DaoMessage { @Query("SELECT *" + " FROM message" + - " WHERE folder = :folder" + + " WHERE folder = :folderId" + " AND uid = :uid" + " AND ui_found = :found") - EntityMessage getMessageByUid(long folder, long uid, boolean found); + EntityMessage getMessageByUid(long folderId, long uid, boolean found); @Query("SELECT *" + " FROM message" + - " WHERE folder = :folder" + + " WHERE folder = :folderId" + " AND NOT ui_found") - List getMessageByFolder(long folder); + List getMessageByFolder(long folderId); @Query("SELECT *" + " FROM message" + @@ -149,19 +150,6 @@ public interface DaoMessage { " AND NOT ui_found") List getMessageByThread(long account, String thread); - @Query("SELECT message.*" + - ", account.name AS accountName, account.color AS accountColor" + - ", folder.name AS folderName, folder.display AS folderDisplay, folder.type AS folderType" + - ", (SELECT COUNT(m1.id) FROM message m1 WHERE m1.account = message.account AND m1.thread = message.thread AND NOT m1.ui_hide) AS count" + - ", CASE WHEN message.ui_seen THEN 0 ELSE 1 END AS unseen" + - ", CASE WHEN message.ui_flagged THEN 0 ELSE 1 END AS unflagged" + - ", (SELECT COUNT(a.id) FROM attachment a WHERE a.message = message.id) AS attachments" + - " FROM message" + - " JOIN account ON account.id = message.account" + - " JOIN folder ON folder.id = message.folder" + - " WHERE message.id = :id") - TupleMessageEx getAccountByMessage(long id); - @Query("SELECT message.* FROM message" + " JOIN folder ON folder.id = message.folder" + " WHERE message.account = :account" + @@ -171,9 +159,9 @@ public interface DaoMessage { List getMessageByMsgId(long account, String msgid, String reference, boolean found); @Query("SELECT * FROM message" + - " WHERE folder = :folder" + + " WHERE folder = :folderId" + " AND ui_seen") - List getMessageSeen(long folder); + List getMessageSeen(long folderId); @Query("SELECT message.*" + ", account.name AS accountName, account.color AS accountColor" + @@ -188,7 +176,10 @@ public interface DaoMessage { " WHERE message.id = :id") LiveData liveMessage(long id); - @Query("SELECT message.* FROM message" + + @Query("SELECT message.*" + + ", account.name AS accountName, account.color AS accountColor" + + ", folder.name AS folderName, folder.display AS folderDisplay, folder.type AS folderType" + + " FROM message" + " JOIN account ON account.id = message.account" + " JOIN folder ON folder.id = message.folder" + " WHERE account.`synchronize`" + @@ -198,14 +189,14 @@ public interface DaoMessage { " AND NOT message.ui_found" + " AND NOT message.ui_ignored" + " ORDER BY message.received") - LiveData> liveUnseenUnified(); + LiveData> liveUnseenUnified(); @Query("SELECT uid FROM message" + - " WHERE folder = :folder" + + " WHERE folder = :folderId" + " AND received >= :received" + " AND NOT uid IS NULL" + " AND NOT ui_found" /* keep found messages */) - List getUids(long folder, long received); + List getUids(long folderId, long received); @Insert long insertMessage(EntityMessage message); @@ -254,17 +245,17 @@ public interface DaoMessage { @Query("DELETE FROM message WHERE id = :id") int deleteMessage(long id); - @Query("DELETE FROM message WHERE folder = :folder AND uid = :uid") - int deleteMessage(long folder, long uid); + @Query("DELETE FROM message WHERE folder = :folderId AND uid = :uid") + int deleteMessage(long folderId, long uid); - @Query("DELETE FROM message WHERE folder = :folder AND NOT uid IS NULL") - int deleteLocalMessages(long folder); + @Query("DELETE FROM message WHERE folder = :folderId AND NOT uid IS NULL") + int deleteLocalMessages(long folderId); - @Query("DELETE FROM message WHERE folder = :folder AND seen") - int deleteSeenMessages(long folder); + @Query("DELETE FROM message WHERE folder = :folderId AND seen") + int deleteSeenMessages(long folderId); - @Query("DELETE FROM message WHERE folder = :folder AND received < :received AND NOT uid IS NULL") - int deleteMessagesBefore(long folder, long received); + @Query("DELETE FROM message WHERE folder = :folderId AND received < :received AND NOT uid IS NULL") + int deleteMessagesBefore(long folderId, long received); @Query("DELETE FROM message WHERE ui_found") int deleteFoundMessages(); diff --git a/app/src/main/java/org/dystopia/email/FragmentAccount.java b/app/src/main/java/org/dystopia/email/FragmentAccount.java index 74a80982..8ca4b3f4 100644 --- a/app/src/main/java/org/dystopia/email/FragmentAccount.java +++ b/app/src/main/java/org/dystopia/email/FragmentAccount.java @@ -87,7 +87,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.constraintlayout.widget.Group; import androidx.core.content.ContextCompat; -import androidx.fragment.app.FragmentTransaction; import androidx.lifecycle.Observer; import static android.accounts.AccountManager.newChooseAccountIntent; diff --git a/app/src/main/java/org/dystopia/email/FragmentOptions.java b/app/src/main/java/org/dystopia/email/FragmentOptions.java index 542f1c53..ae1b8c89 100644 --- a/app/src/main/java/org/dystopia/email/FragmentOptions.java +++ b/app/src/main/java/org/dystopia/email/FragmentOptions.java @@ -26,8 +26,8 @@ import android.preference.PreferenceManager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.Switch; import android.widget.CompoundButton; +import android.widget.Switch; import androidx.annotation.NonNull; import androidx.annotation.Nullable; diff --git a/app/src/main/java/org/dystopia/email/Helper.java b/app/src/main/java/org/dystopia/email/Helper.java index ae828a68..4be488e7 100644 --- a/app/src/main/java/org/dystopia/email/Helper.java +++ b/app/src/main/java/org/dystopia/email/Helper.java @@ -17,16 +17,19 @@ package org.dystopia.email; along with FairEmail. If not, see . Copyright 2018, Marcel Bokhorst (M66B) + Copyright 2018, Distopico (dystopia project) and contributors */ import android.accounts.Account; import android.accounts.AccountManager; +import android.app.Notification; import android.content.Context; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.res.TypedArray; import android.net.Uri; +import android.os.Build; import android.text.TextUtils; import android.util.Log; import android.view.Menu; @@ -204,6 +207,15 @@ public class Helper { } } + static Notification.Builder getNotificationBuilder(Context context, String channelId) { + Notification.Builder pbuilder; + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { + return new Notification.Builder(context); + } else { + return new Notification.Builder(context, channelId); + } + } + static String getExtension(String filename) { if (filename == null) return null; diff --git a/app/src/main/java/org/dystopia/email/ServiceSynchronize.java b/app/src/main/java/org/dystopia/email/ServiceSynchronize.java index c1c396ae..46b3398d 100644 --- a/app/src/main/java/org/dystopia/email/ServiceSynchronize.java +++ b/app/src/main/java/org/dystopia/email/ServiceSynchronize.java @@ -34,7 +34,6 @@ import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.database.Cursor; -import android.graphics.Color; import android.graphics.drawable.Icon; import android.media.RingtoneManager; import android.net.ConnectivityManager; @@ -52,6 +51,7 @@ import android.provider.ContactsContract; import android.text.Html; import android.text.TextUtils; import android.util.Log; +import android.util.Pair; import com.sun.mail.iap.ConnectionException; import com.sun.mail.imap.AppendUID; @@ -170,41 +170,81 @@ public class ServiceSynchronize extends LifecycleService { } }); - db.message().liveUnseenUnified().observe(this, new Observer>() { - private List notifying = new ArrayList<>(); + db.message().liveUnseenUnified().observe(this, new Observer>() { + private Map> notifyingAll = new HashMap<>(); + private Map accounts = new HashMap<>(); @Override - public void onChanged(List messages) { + public void onChanged(List messages) { NotificationManager nm = getSystemService(NotificationManager.class); - List notifications = getNotificationUnseen(messages); - - List all = new ArrayList<>(); - List added = new ArrayList<>(); - List removed = new ArrayList<>(notifying); - 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); - else - added.add(id); + Map> messagesByAccount = new HashMap<>(); + + // Update unseen for all account + setWidgetUnseen(messages); + + // Organize messages per account + for (TupleNotification message : messages) { + + Long accountKey = message.account; + ArrayList newList = new ArrayList<>(); + newList.add(message); + + if (messagesByAccount.containsKey(accountKey)) { + ArrayList msgList = messagesByAccount.get(accountKey); + newList.addAll(msgList); } + + if (!accounts.containsKey(accountKey)) { + String accountName = message.accountName; + Integer accountColor = message.accountColor; + accounts.put(accountKey, new Pair(accountName, accountColor)); + } + messagesByAccount.put(accountKey, newList); } - if (notifications.size() == 0) - nm.cancel("unseen", 0); + // Set and group notification per account + for (Map.Entry> messagesAccount : messagesByAccount.entrySet()) { + Long accountId = messagesAccount.getKey(); + List notifications = getNotificationUnseen(messagesAccount.getValue(), accounts.get(accountId)); + List all = new ArrayList<>(); + List added = new ArrayList<>(); + List removed = new ArrayList<>(); + String tag = "unseen-" + accountId; + + if (notifyingAll.containsKey(accountId)) { + removed = notifyingAll.get(accountId); + } + + 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); + } else { + added.add(id); + } + } + } - for (Integer id : removed) - nm.cancel("unseen", id); + if (notifications.size() == 0) { + nm.cancel(tag, 0); + } - 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", id, notification); - } + for (Integer id : removed) { + nm.cancel(tag, id); + } - notifying = all; + 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(tag, id, notification); + } + } + + notifyingAll.put(accountId, all); + } } }); } @@ -309,11 +349,7 @@ public class ServiceSynchronize extends LifecycleService { this, ActivityView.REQUEST_UNIFIED, intent, PendingIntent.FLAG_UPDATE_CURRENT); // Build notification - Notification.Builder builder; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) - builder = new Notification.Builder(this, "service"); - else - builder = new Notification.Builder(this); + Notification.Builder builder = Helper.getNotificationBuilder(this, "service"); builder .setSmallIcon(R.drawable.baseline_compare_arrows_white_24) @@ -340,17 +376,36 @@ public class ServiceSynchronize extends LifecycleService { return builder; } - private List getNotificationUnseen(List messages) { + /** + * Update widget unseen message for all accounts + * @param messages - list of unseen messages + */ + private void setWidgetUnseen(List messages) { + Widget.update(this, messages.size()); + } + + /** + * Get public/summary and individual notifications per account + * @param messages - list of unseen notifications + * @param account - account information (name, color) + * @return List + */ + private List getNotificationUnseen(List messages, Pair account) { // https://developer.android.com/training/notify-user/group List notifications = new ArrayList<>(); - Widget.update(this, messages.size()); - - if (messages.size() == 0) + if (messages.size() == 0) { return notifications; + } SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + String accountName = (String) account.first; + Integer accountColor = (int) account.second; + Integer groupColor = accountColor != null ? accountColor : ContextCompat.getColor(getBaseContext(), R.color.colorPrimary); + String groupKey = BuildConfig.APPLICATION_ID + accountName; + String channelId = "notification"; + // Build pending intent Intent view = new Intent(this, ActivityView.class); view.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); @@ -361,60 +416,74 @@ public class ServiceSynchronize extends LifecycleService { clear.setAction("clear"); PendingIntent piClear = PendingIntent.getService(this, PI_CLEAR, clear, PendingIntent.FLAG_UPDATE_CURRENT); - // Build notification - Notification.Builder builder; - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) - builder = new Notification.Builder(this); - else - builder = new Notification.Builder(this, "notification"); - - builder + // Public notification + Notification.Builder pbuilder = Helper.getNotificationBuilder(this, channelId); + pbuilder .setSmallIcon(R.drawable.ic_mail_icon) .setContentTitle(getResources().getQuantityString(R.plurals.title_notification_unseen, messages.size(), messages.size())) - .setContentText("") + .setContentText(accountName) .setContentIntent(piView) .setNumber(messages.size()) - .setShowWhen(false) - .setColor(ContextCompat.getColor(getBaseContext(), R.color.colorPrimary)) + .setShowWhen(true) + .setColor(groupColor) + .setDeleteIntent(piClear) + .setPriority(Notification.PRIORITY_DEFAULT) + .setCategory(Notification.CATEGORY_STATUS) + .setVisibility(Notification.VISIBILITY_PUBLIC); + + // Summary notification + Notification.Builder gbuilder = Helper.getNotificationBuilder(this, channelId); + String summaryText = getResources().getQuantityString(R.plurals.title_notification_unseen, messages.size(), messages.size()); + + gbuilder + .setSmallIcon(R.drawable.ic_mail_icon) + .setContentTitle(summaryText) + .setContentIntent(piView) + .setNumber(messages.size()) + .setShowWhen(true) + .setColor(groupColor) .setDeleteIntent(piClear) .setPriority(Notification.PRIORITY_DEFAULT) .setCategory(Notification.CATEGORY_STATUS) .setVisibility(Notification.VISIBILITY_PRIVATE) - .setGroup(BuildConfig.APPLICATION_ID) - .setGroupSummary(true); + .setGroup(groupKey) + .setGroupSummary(true) + .setPublicVersion(pbuilder.build()); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) - builder.setSound(null); - else - builder.setGroupAlertBehavior(Notification.GROUP_ALERT_CHILDREN); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { + gbuilder.setSound(null); + } else { + gbuilder.setGroupAlertBehavior(Notification.GROUP_ALERT_CHILDREN); + } if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.O && prefs.getBoolean("light", false)) { - builder.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_LIGHTS); - builder.setLights(0xff00ff00, 1000, 1000); + gbuilder.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_LIGHTS); + gbuilder.setLights(0xff00ff00, 1000, 1000); } DateFormat df = SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.SHORT, SimpleDateFormat.SHORT); StringBuilder sb = new StringBuilder(); for (EntityMessage message : messages) { sb.append("").append(MessageHelper.getFormattedAddresses(message.from, false)).append(""); - if (!TextUtils.isEmpty(message.subject)) + if (!TextUtils.isEmpty(message.subject)) { sb.append(": ").append(message.subject); + } sb.append(" ").append(df.format(new Date(message.sent == null ? message.received : message.sent))); sb.append("
"); } - builder.setStyle(new Notification.BigTextStyle().bigText(Html.fromHtml(sb.toString()))); + Notification.BigTextStyle gstyle = new Notification.BigTextStyle() + .bigText(Html.fromHtml(sb.toString())).setSummaryText(accountName); + gbuilder.setStyle(gstyle); - notifications.add(builder.build()); + notifications.add(gbuilder.build()); Uri uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); - for (EntityMessage message : messages) { - Bundle args = new Bundle(); - args.putLong("id", message.id); - //final DB db = DB.getInstance(getBaseContext()); - //TupleMessageEx messageEx = db.message().getAccountByMessage(message.id); + for (TupleNotification message : messages) { + Bundle mArgs = new Bundle(); + mArgs.putLong("id", message.id); Intent thread = new Intent(this, ActivityView.class); thread.setAction("thread:" + message.thread); @@ -445,47 +514,40 @@ public class ServiceSynchronize extends LifecycleService { getString(R.string.title_trash), piTrash); - Notification.Builder mbuilder; - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) - mbuilder = new Notification.Builder(this); - else - mbuilder = new Notification.Builder(this, "notification"); + Notification.Builder mbuilder = Helper.getNotificationBuilder(this, channelId); + Notification.InboxStyle mstyle = new Notification.InboxStyle(); mbuilder - .addExtras(args) + .addExtras(mArgs) .setSmallIcon(R.drawable.ic_stat_name) .setContentTitle(MessageHelper.getFormattedAddresses(message.from, true)) .setContentIntent(piContent) + .setDeleteIntent(piDelete) .setSound(uri) + .setColor(groupColor) .setWhen(message.sent == null ? message.received : message.sent) - .setDeleteIntent(piDelete) .setPriority(Notification.PRIORITY_DEFAULT) .setCategory(Notification.CATEGORY_STATUS) - .setVisibility(Notification.VISIBILITY_PRIVATE) - .setGroup(BuildConfig.APPLICATION_ID) + .setVisibility(Notification.VISIBILITY_SECRET) + .setGroup(groupKey) .setGroupSummary(false) - .setSortKey(message.account_name) .addAction(actionSeen.build()) .addAction(actionTrash.build()); - //if (messageEx != null && messageEx.accountColor != null) { - // mbuilder.setColor(ContextCompat.getColor(getBaseContext(), messageEx.accountColor)); - //} - if (messages.size() == 1) { - mbuilder.setColor(ContextCompat.getColor(getBaseContext(), R.color.colorPrimary)); - } - if (!TextUtils.isEmpty(message.subject)) { mbuilder.setContentText(message.subject); + mstyle.addLine(message.subject); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { mbuilder.setGroupAlertBehavior(Notification.GROUP_ALERT_CHILDREN); } + mstyle.setBigContentTitle(MessageHelper.getFormattedAddresses(message.from, false)); + mbuilder.setStyle(mstyle); + notifications.add(mbuilder.build()); } - return notifications; } @@ -497,11 +559,7 @@ public class ServiceSynchronize extends LifecycleService { this, ActivityView.REQUEST_ERROR, intent, PendingIntent.FLAG_UPDATE_CURRENT); // Build notification - Notification.Builder builder; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) - builder = new Notification.Builder(this, "error"); - else - builder = new Notification.Builder(this); + Notification.Builder builder = Helper.getNotificationBuilder(this, "error"); builder .setSmallIcon(android.R.drawable.stat_notify_error) diff --git a/app/src/main/java/org/dystopia/email/TupleMessageEx.java b/app/src/main/java/org/dystopia/email/TupleMessageEx.java index 45d8ae08..bbb6ea99 100644 --- a/app/src/main/java/org/dystopia/email/TupleMessageEx.java +++ b/app/src/main/java/org/dystopia/email/TupleMessageEx.java @@ -17,6 +17,7 @@ package org.dystopia.email; along with FairEmail. If not, see . Copyright 2018, Marcel Bokhorst (M66B) + Copyright 2018, Distopico (dystopia project) and contributors */ public class TupleMessageEx extends EntityMessage { diff --git a/app/src/main/java/org/dystopia/email/TupleNotification.java b/app/src/main/java/org/dystopia/email/TupleNotification.java new file mode 100644 index 00000000..0093c124 --- /dev/null +++ b/app/src/main/java/org/dystopia/email/TupleNotification.java @@ -0,0 +1,41 @@ +package org.dystopia.email; + +/* + This file is part of SimpleEmail. + Copyright 2018, Distopico (dystopia project) and contributors + + This program 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. + + This program 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 . +*/ + +public class TupleNotification extends EntityMessage { + public String accountName; + public Integer accountColor; + public String folderName; + public String folderDisplay; + public String folderType; + + @Override + public boolean equals(Object obj) { + if (obj instanceof TupleMessageEx) { + TupleMessageEx other = (TupleMessageEx) obj; + return (super.equals(obj) && + (this.accountName == null ? other.accountName == null : this.accountName.equals(other.accountName)) && + (this.accountColor == null ? other.accountColor == null : this.accountColor.equals(other.accountColor)) && + this.folderName.equals(other.folderName) && + (this.folderDisplay == null ? other.folderDisplay == null : this.folderDisplay.equals(other.folderDisplay)) && + this.folderType.equals(other.folderType)); + } + return super.equals(obj); + } +}