mirror of https://github.com/M66B/FairEmail.git
Allow subscribing to folders
This commit is contained in:
parent
ffb64cd8ba
commit
d38027eabe
1
FAQ.md
1
FAQ.md
|
@ -223,6 +223,7 @@ The low priority status bar notification shows the number of pending operations,
|
||||||
* *body*: download message text
|
* *body*: download message text
|
||||||
* *attachment*: download attachment
|
* *attachment*: download attachment
|
||||||
* *sync*: synchronize local and remote messages
|
* *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.
|
Operations are processed only when there is a connection to the email server or when manually synchronizing.
|
||||||
See also [this FAQ](#user-content-faq16).
|
See also [this FAQ](#user-content-faq16).
|
||||||
|
|
|
@ -132,7 +132,9 @@ class Core {
|
||||||
JSONArray jargs = new JSONArray(op.args);
|
JSONArray jargs = new JSONArray(op.args);
|
||||||
|
|
||||||
try {
|
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();
|
throw new MessageRemovedException();
|
||||||
|
|
||||||
db.operation().setOperationError(op.id, null);
|
db.operation().setOperationError(op.id, null);
|
||||||
|
@ -144,7 +146,7 @@ class Core {
|
||||||
EntityOperation.DELETE.equals(op.name) ||
|
EntityOperation.DELETE.equals(op.name) ||
|
||||||
EntityOperation.SEND.equals(op.name) ||
|
EntityOperation.SEND.equals(op.name) ||
|
||||||
EntityOperation.SYNC.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);
|
throw new IllegalArgumentException(op.name + " without uid " + op.args);
|
||||||
|
|
||||||
// Operations should use database transaction when needed
|
// Operations should use database transaction when needed
|
||||||
|
@ -217,7 +219,8 @@ class Core {
|
||||||
onSynchronizeMessages(context, jargs, account, folder, (IMAPFolder) ifolder, state);
|
onSynchronizeMessages(context, jargs, account, folder, (IMAPFolder) ifolder, state);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EntityOperation.WAIT:
|
case EntityOperation.SUBSCRIBE:
|
||||||
|
onSubscribeFolder(context, jargs, folder, (IMAPFolder) ifolder);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
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(
|
private static void onSynchronizeMessages(
|
||||||
Context context, JSONArray jargs,
|
Context context, JSONArray jargs,
|
||||||
EntityAccount account, final EntityFolder folder,
|
EntityAccount account, final EntityFolder folder,
|
||||||
|
|
|
@ -553,7 +553,7 @@ public abstract class DB extends RoomDatabase {
|
||||||
@Override
|
@Override
|
||||||
public void migrate(SupportSQLiteDatabase db) {
|
public void migrate(SupportSQLiteDatabase db) {
|
||||||
Log.i("DB migration from version " + startVersion + " to " + endVersion);
|
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) {
|
.addMigrations(new Migration(51, 52) {
|
||||||
|
|
|
@ -83,7 +83,7 @@ public class EntityOperation {
|
||||||
static final String BODY = "body";
|
static final String BODY = "body";
|
||||||
static final String ATTACHMENT = "attachment";
|
static final String ATTACHMENT = "attachment";
|
||||||
static final String SYNC = "sync";
|
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) {
|
static void queue(Context context, DB db, EntityMessage message, String name, Object... values) {
|
||||||
JSONArray jargs = new JSONArray();
|
JSONArray jargs = new JSONArray();
|
||||||
|
@ -256,6 +256,26 @@ public class EntityOperation {
|
||||||
ServiceSynchronize.process(context);
|
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
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (obj instanceof EntityOperation) {
|
if (obj instanceof EntityOperation) {
|
||||||
|
|
|
@ -61,6 +61,7 @@ public class FragmentFolder extends FragmentBase {
|
||||||
|
|
||||||
private long id = -1;
|
private long id = -1;
|
||||||
private long account = -1;
|
private long account = -1;
|
||||||
|
private Boolean subscribed = null;
|
||||||
private boolean saving = false;
|
private boolean saving = false;
|
||||||
private boolean deletable = false;
|
private boolean deletable = false;
|
||||||
|
|
||||||
|
@ -289,6 +290,8 @@ public class FragmentFolder extends FragmentBase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPrepareOptionsMenu(Menu menu) {
|
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);
|
menu.findItem(R.id.menu_delete).setVisible(id > 0 && !saving && deletable);
|
||||||
super.onPrepareOptionsMenu(menu);
|
super.onPrepareOptionsMenu(menu);
|
||||||
}
|
}
|
||||||
|
@ -296,6 +299,11 @@ public class FragmentFolder extends FragmentBase {
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
|
case R.id.menu_subscribe:
|
||||||
|
subscribed = !item.isChecked();
|
||||||
|
item.setChecked(subscribed);
|
||||||
|
onMenuSubscribe();
|
||||||
|
return true;
|
||||||
case R.id.menu_delete:
|
case R.id.menu_delete:
|
||||||
onMenuDelete();
|
onMenuDelete();
|
||||||
return true;
|
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<Void>() {
|
||||||
|
@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() {
|
private void onMenuDelete() {
|
||||||
new DialogBuilderLifecycle(getContext(), getViewLifecycleOwner())
|
new DialogBuilderLifecycle(getContext(), getViewLifecycleOwner())
|
||||||
.setMessage(R.string.title_folder_delete)
|
.setMessage(R.string.title_folder_delete)
|
||||||
|
@ -399,6 +430,7 @@ public class FragmentFolder extends FragmentBase {
|
||||||
cbDownload.setEnabled(cbSynchronize.isChecked());
|
cbDownload.setEnabled(cbSynchronize.isChecked());
|
||||||
btnSave.setEnabled(true);
|
btnSave.setEnabled(true);
|
||||||
|
|
||||||
|
subscribed = (folder == null ? null : folder.subscribed != null && folder.subscribed);
|
||||||
deletable = (folder != null && EntityFolder.USER.equals(folder.type));
|
deletable = (folder != null && EntityFolder.USER.equals(folder.type));
|
||||||
getActivity().invalidateOptionsMenu();
|
getActivity().invalidateOptionsMenu();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_subscribe"
|
||||||
|
android:checkable="true"
|
||||||
|
android:title="@string/title_subscribe"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/menu_delete"
|
android:id="@+id/menu_delete"
|
||||||
android:title="@string/title_delete"
|
android:title="@string/title_delete"
|
||||||
|
|
|
@ -365,6 +365,7 @@
|
||||||
|
|
||||||
<string name="title_trash">Trash</string>
|
<string name="title_trash">Trash</string>
|
||||||
<string name="title_copy">Copy …</string>
|
<string name="title_copy">Copy …</string>
|
||||||
|
<string name="title_subscribe">Subscribe</string>
|
||||||
<string name="title_delete">Delete</string>
|
<string name="title_delete">Delete</string>
|
||||||
<string name="title_more">More</string>
|
<string name="title_more">More</string>
|
||||||
<string name="title_spam">Spam</string>
|
<string name="title_spam">Spam</string>
|
||||||
|
|
Loading…
Reference in New Issue