Decouple notifications and widget/badge

This commit is contained in:
M66B 2019-09-22 09:45:37 +02:00
parent ebc7c98425
commit 8511de077a
5 changed files with 99 additions and 36 deletions

View File

@ -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<TupleMessageEx> messages, Map<Long, List<Long>> 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<Long, List<TupleMessageEx>> 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

View File

@ -248,6 +248,15 @@ public interface DaoMessage {
" WHERE message.id = :id")
LiveData<TupleMessageEx> 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<TupleMessageStats> 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" +

View File

@ -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<TupleMessageStats>() {
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<Integer>() {
@ -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");

View File

@ -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 <http://www.gnu.org/licenses/>.
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;
}
}

View File

@ -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, "");