From d38027eabe6addd7ac8566f70840f79639949fa7 Mon Sep 17 00:00:00 2001 From: M66B Date: Thu, 25 Apr 2019 18:47:52 +0200 Subject: [PATCH] Allow subscribing to folders --- FAQ.md | 1 + app/src/main/java/eu/faircode/email/Core.java | 20 ++++++++++-- app/src/main/java/eu/faircode/email/DB.java | 2 +- .../eu/faircode/email/EntityOperation.java | 22 ++++++++++++- .../eu/faircode/email/FragmentFolder.java | 32 +++++++++++++++++++ app/src/main/res/menu/menu_folder.xml | 6 ++++ app/src/main/res/values/strings.xml | 1 + 7 files changed, 79 insertions(+), 5 deletions(-) diff --git a/FAQ.md b/FAQ.md index 9d894f4aa1..a23469d069 100644 --- a/FAQ.md +++ b/FAQ.md @@ -223,6 +223,7 @@ The low priority status bar notification shows the number of pending operations, * *body*: download message text * *attachment*: download attachment * *sync*: synchronize local and remote messages +* *subscribe*: subscribe to remote folder Operations are processed only when there is a connection to the email server or when manually synchronizing. See also [this FAQ](#user-content-faq16). diff --git a/app/src/main/java/eu/faircode/email/Core.java b/app/src/main/java/eu/faircode/email/Core.java index 9d705d0cde..ab6acaa9c5 100644 --- a/app/src/main/java/eu/faircode/email/Core.java +++ b/app/src/main/java/eu/faircode/email/Core.java @@ -132,7 +132,9 @@ class Core { JSONArray jargs = new JSONArray(op.args); try { - if (message == null && !EntityOperation.SYNC.equals(op.name)) + if (message == null && + !EntityOperation.SYNC.equals(op.name) && + !EntityOperation.SUBSCRIBE.equals(op.name)) throw new MessageRemovedException(); db.operation().setOperationError(op.id, null); @@ -144,7 +146,7 @@ class Core { EntityOperation.DELETE.equals(op.name) || EntityOperation.SEND.equals(op.name) || EntityOperation.SYNC.equals(op.name) || - EntityOperation.WAIT.equals(op.name))) + EntityOperation.SUBSCRIBE.equals(op.name))) throw new IllegalArgumentException(op.name + " without uid " + op.args); // Operations should use database transaction when needed @@ -217,7 +219,8 @@ class Core { onSynchronizeMessages(context, jargs, account, folder, (IMAPFolder) ifolder, state); break; - case EntityOperation.WAIT: + case EntityOperation.SUBSCRIBE: + onSubscribeFolder(context, jargs, folder, (IMAPFolder) ifolder); break; default: @@ -792,6 +795,17 @@ class Core { } } + private static void onSubscribeFolder(Context context, JSONArray jargs, EntityFolder folder, IMAPFolder ifolder) + throws JSONException, MessagingException { + boolean subscribe = jargs.getBoolean(0); + ifolder.setSubscribed(subscribe); + + DB db = DB.getInstance(context); + db.folder().setFolderSubscribed(folder.id, subscribe); + + Log.i(folder.name + " subscribed=" + subscribe); + } + private static void onSynchronizeMessages( Context context, JSONArray jargs, EntityAccount account, final EntityFolder folder, diff --git a/app/src/main/java/eu/faircode/email/DB.java b/app/src/main/java/eu/faircode/email/DB.java index 17aad75920..07e847bc4f 100644 --- a/app/src/main/java/eu/faircode/email/DB.java +++ b/app/src/main/java/eu/faircode/email/DB.java @@ -553,7 +553,7 @@ public abstract class DB extends RoomDatabase { @Override public void migrate(SupportSQLiteDatabase db) { Log.i("DB migration from version " + startVersion + " to " + endVersion); - db.execSQL("DELETE FROM operation WHERE name = '" + EntityOperation.WAIT + "'"); + db.execSQL("DELETE FROM operation WHERE name = 'wait'"); } }) .addMigrations(new Migration(51, 52) { diff --git a/app/src/main/java/eu/faircode/email/EntityOperation.java b/app/src/main/java/eu/faircode/email/EntityOperation.java index b256b034c6..6f94640e72 100644 --- a/app/src/main/java/eu/faircode/email/EntityOperation.java +++ b/app/src/main/java/eu/faircode/email/EntityOperation.java @@ -83,7 +83,7 @@ public class EntityOperation { static final String BODY = "body"; static final String ATTACHMENT = "attachment"; static final String SYNC = "sync"; - static final String WAIT = "wait"; + static final String SUBSCRIBE = "subscribe"; static void queue(Context context, DB db, EntityMessage message, String name, Object... values) { JSONArray jargs = new JSONArray(); @@ -256,6 +256,26 @@ public class EntityOperation { ServiceSynchronize.process(context); } + static void subscribe(Context context, long fid, boolean subscribe) { + DB db = DB.getInstance(context); + + EntityFolder folder = db.folder().getFolder(fid); + + JSONArray jargs = new JSONArray(); + jargs.put(subscribe); + + EntityOperation operation = new EntityOperation(); + operation.account = folder.account; + operation.folder = folder.id; + operation.message = null; + operation.name = SUBSCRIBE; + operation.args = jargs.toString(); + operation.created = new Date().getTime(); + operation.id = db.operation().insertOperation(operation); + + Log.i("Queued subscribe=" + subscribe + " folder=" + folder); + } + @Override public boolean equals(Object obj) { if (obj instanceof EntityOperation) { diff --git a/app/src/main/java/eu/faircode/email/FragmentFolder.java b/app/src/main/java/eu/faircode/email/FragmentFolder.java index ff69c0ad77..aebb4c4e53 100644 --- a/app/src/main/java/eu/faircode/email/FragmentFolder.java +++ b/app/src/main/java/eu/faircode/email/FragmentFolder.java @@ -61,6 +61,7 @@ public class FragmentFolder extends FragmentBase { private long id = -1; private long account = -1; + private Boolean subscribed = null; private boolean saving = false; private boolean deletable = false; @@ -289,6 +290,8 @@ public class FragmentFolder extends FragmentBase { @Override public void onPrepareOptionsMenu(Menu menu) { + menu.findItem(R.id.menu_subscribe).setChecked(subscribed != null && subscribed); + menu.findItem(R.id.menu_subscribe).setVisible(id > 0 && subscribed != null); menu.findItem(R.id.menu_delete).setVisible(id > 0 && !saving && deletable); super.onPrepareOptionsMenu(menu); } @@ -296,6 +299,11 @@ public class FragmentFolder extends FragmentBase { @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.menu_subscribe: + subscribed = !item.isChecked(); + item.setChecked(subscribed); + onMenuSubscribe(); + return true; case R.id.menu_delete: onMenuDelete(); return true; @@ -304,6 +312,29 @@ public class FragmentFolder extends FragmentBase { } } + private void onMenuSubscribe() { + Bundle args = new Bundle(); + args.putLong("id", id); + args.putBoolean("subscribed", subscribed); + + new SimpleTask() { + @Override + protected Void onExecute(Context context, Bundle args) { + long id = args.getLong("id"); + boolean subscribed = args.getBoolean("subscribed"); + + EntityOperation.subscribe(context, id, subscribed); + + return null; + } + + @Override + protected void onException(Bundle args, Throwable ex) { + Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex); + } + }.execute(getContext(), getViewLifecycleOwner(), args, "folder:subscribe"); + } + private void onMenuDelete() { new DialogBuilderLifecycle(getContext(), getViewLifecycleOwner()) .setMessage(R.string.title_folder_delete) @@ -399,6 +430,7 @@ public class FragmentFolder extends FragmentBase { cbDownload.setEnabled(cbSynchronize.isChecked()); btnSave.setEnabled(true); + subscribed = (folder == null ? null : folder.subscribed != null && folder.subscribed); deletable = (folder != null && EntityFolder.USER.equals(folder.type)); getActivity().invalidateOptionsMenu(); } diff --git a/app/src/main/res/menu/menu_folder.xml b/app/src/main/res/menu/menu_folder.xml index dc91f82efb..910d5dd959 100644 --- a/app/src/main/res/menu/menu_folder.xml +++ b/app/src/main/res/menu/menu_folder.xml @@ -1,6 +1,12 @@ + + Trash Copy … + Subscribe Delete More Spam