diff --git a/app/src/main/java/eu/faircode/email/ActivityEML.java b/app/src/main/java/eu/faircode/email/ActivityEML.java index 0edde24eea..d46f6654f1 100644 --- a/app/src/main/java/eu/faircode/email/ActivityEML.java +++ b/app/src/main/java/eu/faircode/email/ActivityEML.java @@ -349,9 +349,10 @@ public class ActivityEML extends ActivityBase { imessage.setFlag(Flags.Flag.DRAFT, false); ifolder.appendMessages(new Message[]{imessage}); - - EntityOperation.sync(context, inbox.id, true); } + + EntityOperation.sync(context, inbox.id, true); + ServiceSynchronize.eval(context, false, "EML"); } return account.name + "/" + inbox.name; diff --git a/app/src/main/java/eu/faircode/email/AdapterAttachment.java b/app/src/main/java/eu/faircode/email/AdapterAttachment.java index 3c47568eaa..b752a8460d 100644 --- a/app/src/main/java/eu/faircode/email/AdapterAttachment.java +++ b/app/src/main/java/eu/faircode/email/AdapterAttachment.java @@ -282,6 +282,8 @@ public class AdapterAttachment extends RecyclerView.Adapter folders = db.folder().getSynchronizingFolders(aid); - if (folders.size() > 0) - Collections.sort(folders, folders.get(0).getComparator(context)); - for (EntityFolder folder : folders) - EntityOperation.sync(context, folder.id, false); - } } db.setTransactionSuccessful(); @@ -359,6 +348,10 @@ public class FragmentFolders extends FragmentBase { db.endTransaction(); } + ServiceSynchronize.eval(context, aid > 0, "refresh/folders"); + if (outbox) + ServiceSend.start(context); + if (!now) throw new IllegalArgumentException(context.getString(R.string.title_no_connection)); @@ -523,6 +516,8 @@ public class FragmentFolders extends FragmentBase { db.endTransaction(); } + ServiceSynchronize.eval(context, false, "refresh/folder"); + if (!now) throw new IllegalArgumentException(context.getString(R.string.title_no_connection)); @@ -613,6 +608,8 @@ public class FragmentFolders extends FragmentBase { db.endTransaction(); } + ServiceSynchronize.eval(context, false, "delete"); + return null; } diff --git a/app/src/main/java/eu/faircode/email/FragmentMessages.java b/app/src/main/java/eu/faircode/email/FragmentMessages.java index cfd86a9a6a..79ec840517 100644 --- a/app/src/main/java/eu/faircode/email/FragmentMessages.java +++ b/app/src/main/java/eu/faircode/email/FragmentMessages.java @@ -1192,6 +1192,8 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. db.endTransaction(); } + ServiceSynchronize.eval(context, false, "refresh"); + if (!now) throw new IllegalArgumentException(context.getString(R.string.title_no_connection)); @@ -2029,6 +2031,8 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. db.endTransaction(); } + ServiceSynchronize.eval(context, false, "seen"); + return null; } @@ -2162,6 +2166,8 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. db.endTransaction(); } + ServiceSynchronize.eval(context, false, "flag"); + return null; } @@ -3479,6 +3485,8 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. db.endTransaction(); } + ServiceSynchronize.eval(context, false, "expand"); + return null; } @@ -3617,6 +3625,9 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. } finally { db.endTransaction(); } + + ServiceSynchronize.eval(context, false, "move"); + return null; } @@ -3738,6 +3749,8 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. } finally { db.endTransaction(); } + + ServiceSynchronize.eval(context, false, "move"); } }, "messages:movetimeout"); thread.setPriority(THREAD_PRIORITY_BACKGROUND); @@ -4715,6 +4728,8 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. db.endTransaction(); } + ServiceSynchronize.eval(context, false, "delete"); + return null; } @@ -4750,6 +4765,8 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. db.endTransaction(); } + ServiceSynchronize.eval(context, false, "delete"); + return null; } @@ -4785,6 +4802,8 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. db.endTransaction(); } + ServiceSynchronize.eval(context, false, "move"); + return null; } @@ -4843,6 +4862,9 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. EntityOperation.queue(context, message, EntityOperation.FLAG, true, color); } }); + + ServiceSynchronize.eval(context, false, "flag"); + return null; } @@ -4994,6 +5016,8 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. db.endTransaction(); } + ServiceSynchronize.eval(context, false, "copy"); + return result; } @@ -5177,6 +5201,8 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. db.endTransaction(); } + ServiceSynchronize.eval(context, false, "delete"); + return null; } diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsNotifications.java b/app/src/main/java/eu/faircode/email/FragmentOptionsNotifications.java index b2d2e530c8..915f65643d 100644 --- a/app/src/main/java/eu/faircode/email/FragmentOptionsNotifications.java +++ b/app/src/main/java/eu/faircode/email/FragmentOptionsNotifications.java @@ -177,7 +177,6 @@ public class FragmentOptionsNotifications extends FragmentBase implements Shared @Override public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { prefs.edit().putBoolean("badge", checked).apply(); - ServiceSynchronize.restart(getContext(), "badge"); } }); @@ -185,7 +184,6 @@ public class FragmentOptionsNotifications extends FragmentBase implements Shared @Override public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { prefs.edit().putBoolean("unseen_ignored", checked).apply(); - ServiceSynchronize.restart(getContext(), "unseen_ignored"); } }); diff --git a/app/src/main/java/eu/faircode/email/Log.java b/app/src/main/java/eu/faircode/email/Log.java index 12aea11265..3f4d4bfc52 100644 --- a/app/src/main/java/eu/faircode/email/Log.java +++ b/app/src/main/java/eu/faircode/email/Log.java @@ -641,6 +641,8 @@ public class Log { db.endTransaction(); } + ServiceSynchronize.eval(context, false, "debuginfo"); + return draft; } diff --git a/app/src/main/java/eu/faircode/email/ServiceSend.java b/app/src/main/java/eu/faircode/email/ServiceSend.java index 3e8cc1dd19..ef848da1ec 100644 --- a/app/src/main/java/eu/faircode/email/ServiceSend.java +++ b/app/src/main/java/eu/faircode/email/ServiceSend.java @@ -461,14 +461,16 @@ public class ServiceSend extends ServiceBase { EntityOperation.queue(this, orphan, EntityOperation.EXISTS); } + // Reset identity + db.identity().setIdentityConnected(ident.id, new Date().getTime()); + db.identity().setIdentityError(ident.id, null); + db.setTransactionSuccessful(); } finally { db.endTransaction(); } - // Reset identity - db.identity().setIdentityConnected(ident.id, new Date().getTime()); - db.identity().setIdentityError(ident.id, null); + ServiceSynchronize.eval(ServiceSend.this, false, "sent"); NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); nm.cancel("send:" + message.identity, 1); diff --git a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java index 4845178dd2..43a20db6da 100644 --- a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java +++ b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java @@ -104,9 +104,11 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences )); private static final List PREF_RELOAD = Collections.unmodifiableList(Arrays.asList( - "metered", "roaming", "rlah", - "socks_enabled", "socks_proxy", - "subscribed_only", "debug" + "metered", "roaming", "rlah", // force reconnect + "socks_enabled", "socks_proxy", // force reconnect + "subscribed_only", // force folder sync + "badge", "unseen_ignored", // force update badge/widget + "debug" // force reconnect )); static final int PI_ALARM = 1; @@ -153,6 +155,10 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences postValue(result); } } + + private void postDestroy() { + postValue(null); + } } @Override @@ -198,7 +204,8 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences } }); - liveAccountNetworkState.observe(this, new Observer>() { + Log.i("### observe"); + liveAccountNetworkState.observeForever(new Observer>() { boolean running = true; private List accountStates = new ArrayList<>(); private Map serviceStates = new Hashtable<>(); @@ -206,69 +213,81 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences @Override public void onChanged(List accountNetworkStates) { - if (!running) { - Log.i("### not running"); - return; - } + if (accountNetworkStates == null) { + for (TupleAccountNetworkState prev : serviceStates.keySet()) + stop(prev); - boolean runService = false; + quit(); - int connected = 0; - int pending = 0; - for (TupleAccountNetworkState current : accountNetworkStates) { - if (current.accountState.shouldRun(current.enabled)) - runService = true; - if ("connected".equals(current.accountState.state)) - connected++; - pending += current.accountState.operations; - - int index = accountStates.indexOf(current); - if (index < 0) { - if (current.canRun()) { - Log.i("### new " + current); - start(current, current.accountState.isEnabled(current.enabled)); - } - } else { - TupleAccountNetworkState prev = accountStates.get(index); - accountStates.remove(index); - - Core.State state = serviceStates.get(current); - if (state != null) - state.setNetworkState(current.networkState); - - // TODO: reload disconnected account on new network available - // !"connected".equals(current.accountState.state)) - - if (current.reload || - prev.canRun() != current.canRun() || - !prev.accountState.equals(current.accountState)) { - Log.i("### changed " + current + - " reload=" + current.reload + - " run prev=" + prev.canRun() + - " run cur=" + current.canRun() + - " changed=" + !prev.accountState.equals(current.accountState)); - if (prev.canRun()) - stop(prev); - if (current.canRun()) - start(current, current.accountState.isEnabled(current.enabled)); - if (current.accountState.tbd != null) - delete(current); - } + accountStates.clear(); + serviceStates.clear(); + liveAccountNetworkState.removeObserver(this); + } else { + if (!running) { + Log.i("### not running"); + return; } - if (current.accountState.tbd == null) - accountStates.add(current); - } + int connected = 0; + int pending = 0; + boolean runService = false; + for (TupleAccountNetworkState current : accountNetworkStates) { + if (current.accountState.shouldRun(current.enabled)) + runService = true; + if ("connected".equals(current.accountState.state)) + connected++; + pending += current.accountState.operations; - if (accounts != connected || operations != pending) { - accounts = connected; - operations = pending; - NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - nm.notify(Helper.NOTIFICATION_SYNCHRONIZE, getNotificationService(accounts, operations).build()); - } + int index = accountStates.indexOf(current); + if (index < 0) { + if (current.canRun()) { + Log.i("### new " + current); + start(current, current.accountState.isEnabled(current.enabled)); + } + } else { + TupleAccountNetworkState prev = accountStates.get(index); + accountStates.remove(index); - if (!runService) - exit(); + Core.State state = serviceStates.get(current); + if (state != null) + state.setNetworkState(current.networkState); + + // TODO: reload disconnected account on new network available + // !"connected".equals(current.accountState.state)) + + if (current.reload || + prev.canRun() != current.canRun() || + !prev.accountState.equals(current.accountState)) { + Log.i("### changed " + current + + " reload=" + current.reload + + " run prev=" + prev.canRun() + + " run cur=" + current.canRun() + + " changed=" + !prev.accountState.equals(current.accountState)); + if (prev.canRun()) + stop(prev); + if (current.canRun()) + start(current, current.accountState.isEnabled(current.enabled)); + if (current.accountState.tbd != null) + delete(current); + } + } + + if (current.accountState.tbd == null) + accountStates.add(current); + } + + if (runService) { + if (accounts != connected || operations != pending) { + accounts = connected; + operations = pending; + NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + nm.notify(Helper.NOTIFICATION_SYNCHRONIZE, getNotificationService(accounts, operations).build()); + } + } else { + running = false; + stopSelf(); + } + } } private void start(final TupleAccountNetworkState accountNetworkState, boolean sync) { @@ -359,14 +378,13 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences }); } - private void exit() { - EntityLog.log(ServiceSynchronize.this, "Service exit"); + private void quit() { + EntityLog.log(ServiceSynchronize.this, "Service quit"); - running = false; queue.submit(new Runnable() { @Override public void run() { - Log.i("### exit"); + Log.i("### quit"); DB db = DB.getInstance(ServiceSynchronize.this); List ops = db.operation().getOperations(EntityOperation.SYNC); @@ -374,7 +392,7 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences db.folder().setFolderSyncState(op.folder, null); stopSelf(); - Log.i("### exited"); + Log.i("### quited"); } }); } @@ -523,7 +541,7 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); cm.unregisterNetworkCallback(networkCallback); - liveAccountNetworkState.post(new ConnectionHelper.NetworkState()); + liveAccountNetworkState.postDestroy(); setUnseen(null); @@ -1486,9 +1504,4 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences new Intent(context, ServiceSynchronize.class) .setAction("reset")); } - - static void restart(Context context, String reason) { - context.stopService(new Intent(context, ServiceSynchronize.class)); - eval(context, false, reason); - } } diff --git a/app/src/main/java/eu/faircode/email/ServiceUI.java b/app/src/main/java/eu/faircode/email/ServiceUI.java index 6fe1526b78..5d92ce2ca4 100644 --- a/app/src/main/java/eu/faircode/email/ServiceUI.java +++ b/app/src/main/java/eu/faircode/email/ServiceUI.java @@ -194,6 +194,8 @@ public class ServiceUI extends IntentService { } finally { db.endTransaction(); } + + ServiceSynchronize.eval(ServiceUI.this, false, "move"); } private void onMove(long id) { @@ -215,6 +217,8 @@ public class ServiceUI extends IntentService { } finally { db.endTransaction(); } + + ServiceSynchronize.eval(ServiceUI.this, false, "move"); } private void onReplyDirect(long id, Intent intent) throws IOException { @@ -273,11 +277,12 @@ public class ServiceUI extends IntentService { EntityOperation.queue(this, reply, EntityOperation.SEND); db.setTransactionSuccessful(); - - ToastEx.makeText(this, R.string.title_queued, Toast.LENGTH_LONG).show(); } finally { db.endTransaction(); } + + ServiceSend.start(ServiceUI.this); + ToastEx.makeText(this, R.string.title_queued, Toast.LENGTH_LONG).show(); } private void onFlag(long id) { @@ -303,6 +308,8 @@ public class ServiceUI extends IntentService { } finally { db.endTransaction(); } + + ServiceSynchronize.eval(ServiceUI.this, false, "flag"); } private void onSeen(long id) { @@ -320,6 +327,8 @@ public class ServiceUI extends IntentService { } finally { db.endTransaction(); } + + ServiceSynchronize.eval(ServiceUI.this, false, "seen"); } private void onSnooze(long id) { @@ -376,6 +385,8 @@ public class ServiceUI extends IntentService { } private void onWakeup(long id) { + EntityFolder folder; + DB db = DB.getInstance(this); try { db.beginTransaction(); @@ -384,7 +395,10 @@ public class ServiceUI extends IntentService { if (message == null) return; - EntityFolder folder = db.folder().getFolder(message.folder); + folder = db.folder().getFolder(message.folder); + if (folder == null) + return; + if (EntityFolder.OUTBOX.equals(folder.type)) { Log.i("Delayed send id=" + message.id); db.message().setMessageSnoozed(message.id, null); @@ -407,6 +421,11 @@ public class ServiceUI extends IntentService { } finally { db.endTransaction(); } + + if (EntityFolder.OUTBOX.equals(folder.type)) + ServiceSend.start(ServiceUI.this); + else + ServiceSynchronize.eval(ServiceUI.this, false, "wakeup"); } private void onDaily() { diff --git a/app/src/main/java/eu/faircode/email/WorkerPoll.java b/app/src/main/java/eu/faircode/email/WorkerPoll.java index 7723b5a149..720484e1c5 100644 --- a/app/src/main/java/eu/faircode/email/WorkerPoll.java +++ b/app/src/main/java/eu/faircode/email/WorkerPoll.java @@ -63,6 +63,8 @@ public class WorkerPoll extends Worker { db.endTransaction(); } + ServiceSynchronize.eval(getApplicationContext(), false, "refresh/poll"); + return Result.success(); }