Store copy of message in target folder

pull/147/head
M66B 6 years ago
parent e01728a202
commit 1b5156dfc5

@ -251,7 +251,7 @@ public class AdapterAttachment extends RecyclerView.Adapter<AdapterAttachment.Vi
db.attachment().setProgress(id, 0);
EntityMessage msg = db.message().getMessage(message);
EntityOperation.queue(db, msg, EntityOperation.ATTACHMENT, sequence);
EntityOperation.queue(context, db, msg, EntityOperation.ATTACHMENT, sequence);
db.setTransactionSuccessful();
} finally {

@ -334,7 +334,7 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
for (Long mid : db.message().getMessageByFolder(id)) {
EntityMessage message = db.message().getMessage(mid);
EntityOperation.queue(db, message, EntityOperation.DELETE);
EntityOperation.queue(context, db, message, EntityOperation.DELETE);
}
db.setTransactionSuccessful();

@ -339,6 +339,8 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
pbLoading.setVisibility(View.GONE);
itemView.setAlpha(message.uid == null ? LOW_LIGHT : 1.0f);
if (viewType == ViewType.THREAD) {
ivFlagged.setAlpha(message.duplicate ? LOW_LIGHT : 1.0f);
ivAvatar.setAlpha(message.duplicate ? LOW_LIGHT : 1.0f);
@ -1082,7 +1084,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
return null;
EntityFolder junk = db.folder().getFolderByType(message.account, EntityFolder.JUNK);
EntityOperation.queue(db, message, EntityOperation.MOVE, junk.id);
EntityOperation.queue(context, db, message, EntityOperation.MOVE, junk.id);
db.setTransactionSuccessful();
} finally {
@ -1231,7 +1233,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
if (message == null)
return null;
EntityOperation.queue(db, message, EntityOperation.SEEN, false);
EntityOperation.queue(context, db, message, EntityOperation.SEEN, false);
db.setTransactionSuccessful();
} finally {
@ -1279,7 +1281,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
List<EntityMessage> messages = db.message().getMessageByThread(
message.account, message.thread, threading && thread ? null : id, message.folder);
for (EntityMessage threaded : messages)
EntityOperation.queue(db, threaded, EntityOperation.FLAG, flagged);
EntityOperation.queue(context, db, threaded, EntityOperation.FLAG, flagged);
db.setTransactionSuccessful();
} finally {
@ -1375,7 +1377,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
if (message == null)
return null;
EntityOperation.queue(db, message, EntityOperation.HEADERS);
EntityOperation.queue(context, db, message, EntityOperation.HEADERS);
db.setTransactionSuccessful();
} finally {
@ -1460,7 +1462,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
for (int i = 0; i < selected.length; i++)
if (dirty[i])
EntityOperation.queue(db, message, EntityOperation.KEYWORD, keywords[i], selected[i]);
EntityOperation.queue(context, db, message, EntityOperation.KEYWORD, keywords[i], selected[i]);
db.setTransactionSuccessful();
} finally {
@ -1499,7 +1501,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
String keyword = args.getString("keyword");
DB db = DB.getInstance(context);
EntityOperation.queue(db, message, EntityOperation.KEYWORD, keyword, true);
EntityOperation.queue(context, db, message, EntityOperation.KEYWORD, keyword, true);
return null;
}
@ -1537,23 +1539,25 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
View anchor = bnvActions.findViewById(R.id.action_more);
PopupMenu popupMenu = new PopupMenu(context, anchor);
popupMenu.inflate(R.menu.menu_message);
popupMenu.getMenu().findItem(R.id.menu_junk).setVisible(data.message.uid != null && data.hasJunk);
popupMenu.getMenu().findItem(R.id.menu_junk).setEnabled(data.message.uid != null);
popupMenu.getMenu().findItem(R.id.menu_junk).setVisible(data.hasJunk);
popupMenu.getMenu().findItem(R.id.menu_forward).setEnabled(data.message.content);
popupMenu.getMenu().findItem(R.id.menu_forward_raw).setVisible(data.message.content && data.message.headers != null);
popupMenu.getMenu().findItem(R.id.menu_reply_all).setEnabled(data.message.content);
popupMenu.getMenu().findItem(R.id.menu_answer).setEnabled(data.message.content);
popupMenu.getMenu().findItem(R.id.menu_unseen).setVisible(data.message.uid != null);
popupMenu.getMenu().findItem(R.id.menu_unseen).setEnabled(data.message.uid != null);
popupMenu.getMenu().findItem(R.id.menu_share).setEnabled(data.message.uid != null);
popupMenu.getMenu().findItem(R.id.menu_show_headers).setEnabled(data.message.content);
popupMenu.getMenu().findItem(R.id.menu_show_headers).setChecked(show_headers);
popupMenu.getMenu().findItem(R.id.menu_show_headers).setVisible(data.message.uid != null);
popupMenu.getMenu().findItem(R.id.menu_show_headers).setEnabled(data.message.uid != null);
popupMenu.getMenu().findItem(R.id.menu_manage_keywords).setVisible(data.message.uid != null);
popupMenu.getMenu().findItem(R.id.menu_manage_keywords).setEnabled(data.message.uid != null);
popupMenu.getMenu().findItem(R.id.menu_decrypt).setEnabled(
data.message.content && data.message.to != null && data.message.to.length > 0);
@ -1633,7 +1637,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
nm.cancel("send", message.identity.intValue());
} else
EntityOperation.queue(db, message, EntityOperation.DELETE);
EntityOperation.queue(context, db, message, EntityOperation.DELETE);
db.setTransactionSuccessful();
} finally {

@ -180,12 +180,16 @@ public interface DaoMessage {
" AND NOT ui_hide")
List<EntityMessage> getMessageByThread(long account, String thread, Long id, Long folder);
@Query("SELECT message.* FROM message" +
" JOIN folder ON folder.id = message.folder" +
" WHERE message.account = :account" +
" AND message.msgid = :msgid")
@Query("SELECT * FROM message" +
" WHERE account = :account" +
" AND msgid = :msgid")
List<EntityMessage> getMessageByMsgId(long account, String msgid);
@Query("SELECT COUNT(*) FROM message" +
" WHERE folder = :folder" +
" AND msgid = :msgid")
int countMessageByMsgId(long folder, String msgid);
@Query("SELECT * FROM message" +
" WHERE folder = :folder" +
" AND ui_seen" +

@ -285,7 +285,7 @@ public class EntityMessage implements Serializable {
//(this.identity == null ? other.identity == null : this.identity.equals(other.identity)) &&
//(this.replying == null ? other.replying == null : this.replying.equals(other.replying)) &&
//(this.forwarding == null ? other.forwarding == null : this.forwarding.equals(other.forwarding)) &&
//(this.uid == null ? other.uid == null : this.uid.equals(other.uid)) &&
(this.uid == null ? other.uid == null : this.uid.equals(other.uid)) &&
(this.msgid == null ? other.msgid == null : this.msgid.equals(other.msgid)) && // debug info
//(this.references == null ? other.references == null : this.references.equals(other.references)) &&
//(this.deliveredto == null ? other.deliveredto == null : this.deliveredto.equals(other.deliveredto)) &&
@ -305,7 +305,6 @@ public class EntityMessage implements Serializable {
//(this.sent == null ? other.sent == null : this.sent.equals(other.sent)) &&
this.received.equals(other.received) &&
this.stored.equals(other.stored) && // updated after decryption
//this.stored.equals(other.stored) &&
//this.seen.equals(other.seen) &&
//this.answered.equals(other.answered) &&
//this.flagged.equals(other.flagged) &&

@ -19,10 +19,14 @@ package eu.faircode.email;
Copyright 2018-2019 by Marcel Bokhorst (M66B)
*/
import android.content.Context;
import org.json.JSONArray;
import org.json.JSONException;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.room.Entity;
@ -72,22 +76,22 @@ public class EntityOperation {
static final String ATTACHMENT = "attachment";
static final String SYNC = "sync";
static void queue(DB db, EntityMessage message, String name) {
static void queue(Context context, DB db, EntityMessage message, String name) {
JSONArray jargs = new JSONArray();
queue(db, message, name, jargs);
queue(context, db, message, name, jargs);
}
static void queue(DB db, EntityMessage message, String name, Object value) {
static void queue(Context context, DB db, EntityMessage message, String name, Object value) {
JSONArray jargs = new JSONArray();
jargs.put(value);
queue(db, message, name, jargs);
queue(context, db, message, name, jargs);
}
static void queue(DB db, EntityMessage message, String name, Object value1, Object value2) {
static void queue(Context context, DB db, EntityMessage message, String name, Object value1, Object value2) {
JSONArray jargs = new JSONArray();
jargs.put(value1);
jargs.put(value2);
queue(db, message, name, jargs);
queue(context, db, message, name, jargs);
}
static void sync(DB db, long fid) {
@ -121,7 +125,7 @@ public class EntityOperation {
}
}
private static void queue(DB db, EntityMessage message, String name, JSONArray jargs) {
private static void queue(Context context, DB db, EntityMessage message, String name, JSONArray jargs) {
try {
if (SEEN.equals(name)) {
for (EntityMessage similar : db.message().getMessageByMsgId(message.account, message.msgid)) {
@ -139,9 +143,53 @@ public class EntityOperation {
else if (MOVE.equals(name)) {
EntityFolder source = db.folder().getFolder(message.folder);
if (!EntityFolder.ARCHIVE.equals(source.type))
EntityFolder target = db.folder().getFolder(jargs.getLong(0));
if (!EntityFolder.ARCHIVE.equals(source.type) || EntityFolder.TRASH.equals(target.type))
db.message().setMessageUiHide(message.id, true);
// Create copy without uid in target folder
// Message with same msgid can be in archive and source folder
if (db.message().countMessageByMsgId(target.id, message.msgid) == 0) {
long id = message.id;
long uid = message.uid;
message.id = null;
message.uid = null;
message.folder = target.id;
long newid = db.message().insertMessage(message);
message.id = id;
message.uid = uid;
message.folder = source.id;
if (message.content)
try {
Helper.copy(
EntityMessage.getFile(context, id),
EntityMessage.getFile(context, newid));
} catch (IOException ex) {
Log.e(ex);
db.message().setMessageContent(newid, false, null);
}
List<EntityAttachment> attachments = db.attachment().getAttachments(message.id);
for (EntityAttachment attachment : attachments) {
long aid = attachment.id;
attachment.id = null;
attachment.message = newid;
attachment.progress = null;
attachment.id = db.attachment().insertAttachment(attachment);
if (attachment.available)
try {
Helper.copy(
EntityAttachment.getFile(context, aid),
EntityAttachment.getFile(context, attachment.id));
} catch (IOException ex) {
Log.e(ex);
attachment.available = false;
db.attachment().updateAttachment(attachment);
}
}
}
} else if (DELETE.equals(name))
db.message().setMessageUiHide(message.id, true);
} catch (JSONException ex) {

@ -1470,14 +1470,14 @@ public class FragmentCompose extends FragmentEx {
}
}
EntityOperation.queue(db, result.draft, EntityOperation.ADD);
EntityOperation.queue(context, db, result.draft, EntityOperation.ADD);
} else {
// Existing draft
result.account = db.account().getAccount(result.draft.account);
if (!result.draft.content) {
if (result.draft.uid == null)
throw new IllegalStateException("Draft without uid");
EntityOperation.queue(db, result.draft, EntityOperation.BODY);
EntityOperation.queue(context, db, result.draft, EntityOperation.BODY);
}
}
@ -1723,14 +1723,14 @@ public class FragmentCompose extends FragmentEx {
draft.content = false;
draft.ui_hide = true;
draft.id = db.message().insertMessage(draft);
EntityOperation.queue(db, draft, EntityOperation.DELETE);
EntityOperation.queue(context, db, draft, EntityOperation.DELETE);
draft.id = id;
draft.account = aid;
draft.folder = db.folder().getFolderByType(aid, EntityFolder.DRAFTS).id;
draft.content = true;
draft.ui_hide = false;
EntityOperation.queue(db, draft, EntityOperation.ADD);
EntityOperation.queue(context, db, draft, EntityOperation.ADD);
}
// Convert data
@ -1798,7 +1798,7 @@ public class FragmentCompose extends FragmentEx {
// Execute action
if (action == R.id.action_delete) {
EntityOperation.queue(db, draft, EntityOperation.DELETE);
EntityOperation.queue(context, db, draft, EntityOperation.DELETE);
if (!empty) {
Handler handler = new Handler(context.getMainLooper());
@ -1810,7 +1810,7 @@ public class FragmentCompose extends FragmentEx {
}
} else if (action == R.id.action_save || action == R.id.menu_encrypt) {
if (dirty) {
EntityOperation.queue(db, draft, EntityOperation.ADD);
EntityOperation.queue(context, db, draft, EntityOperation.ADD);
Handler handler = new Handler(context.getMainLooper());
handler.post(new Runnable() {
@ -1835,7 +1835,7 @@ public class FragmentCompose extends FragmentEx {
throw new IllegalArgumentException(context.getString(R.string.title_attachments_missing));
// Delete draft (cannot move to outbox)
EntityOperation.queue(db, draft, EntityOperation.DELETE);
EntityOperation.queue(context, db, draft, EntityOperation.DELETE);
// Copy message to outbox
draft.id = null;
@ -1854,11 +1854,11 @@ public class FragmentCompose extends FragmentEx {
Helper.copy(file, EntityAttachment.getFile(context, attachment.id));
}
EntityOperation.queue(db, draft, EntityOperation.SEND);
EntityOperation.queue(context, db, draft, EntityOperation.SEND);
if (draft.replying != null) {
EntityMessage replying = db.message().getMessage(draft.replying);
EntityOperation.queue(db, replying, EntityOperation.ANSWERED, true);
EntityOperation.queue(context, db, replying, EntityOperation.ANSWERED, true);
}
Handler handler = new Handler(context.getMainLooper());

@ -900,7 +900,7 @@ public class FragmentMessages extends FragmentEx {
List<EntityMessage> messages = db.message().getMessageByThread(
message.account, message.thread, threading ? null : id, message.folder);
for (EntityMessage threaded : messages)
EntityOperation.queue(db, threaded, EntityOperation.SEEN, seen);
EntityOperation.queue(context, db, threaded, EntityOperation.SEEN, seen);
}
}
@ -942,7 +942,7 @@ public class FragmentMessages extends FragmentEx {
List<EntityMessage> messages = db.message().getMessageByThread(
message.account, message.thread, threading ? null : id, message.folder);
for (EntityMessage threaded : messages)
EntityOperation.queue(db, threaded, EntityOperation.FLAG, flagged);
EntityOperation.queue(context, db, threaded, EntityOperation.FLAG, flagged);
}
}
@ -1003,7 +1003,7 @@ public class FragmentMessages extends FragmentEx {
if (threaded.uid == null && !TextUtils.isEmpty(threaded.error)) // outbox
db.message().deleteMessage(threaded.id);
else
EntityOperation.queue(db, threaded, EntityOperation.DELETE);
EntityOperation.queue(context, db, threaded, EntityOperation.DELETE);
}
}
@ -1612,7 +1612,7 @@ public class FragmentMessages extends FragmentEx {
message.uid = null;
db.message().updateMessage(message);
Log.i("Appending sent msgid=" + message.msgid);
EntityOperation.queue(db, message, EntityOperation.ADD); // Could already exist
EntityOperation.queue(context, db, message, EntityOperation.ADD); // Could already exist
}
}
@ -1920,10 +1920,10 @@ public class FragmentMessages extends FragmentEx {
EntityFolder folder = db.folder().getFolder(message.folder);
if (!message.content)
EntityOperation.queue(db, message, EntityOperation.BODY);
EntityOperation.queue(context, db, message, EntityOperation.BODY);
if (!message.ui_seen && !EntityFolder.OUTBOX.equals(folder.type))
EntityOperation.queue(db, message, EntityOperation.SEEN, true);
EntityOperation.queue(context, db, message, EntityOperation.SEEN, true);
db.setTransactionSuccessful();
} finally {
@ -1992,7 +1992,7 @@ public class FragmentMessages extends FragmentEx {
if (message != null) {
Log.i("Move id=" + id + " target=" + result.target.name);
EntityFolder folder = db.folder().getFolderByName(message.account, result.target.name);
EntityOperation.queue(db, message, EntityOperation.MOVE, folder.id);
EntityOperation.queue(context, db, message, EntityOperation.MOVE, folder.id);
}
}
@ -2059,11 +2059,12 @@ public class FragmentMessages extends FragmentEx {
if (snackbar.isShown())
snackbar.dismiss();
final DB db = DB.getInstance(getContext());
final Context context = getContext().getApplicationContext();
new Thread(new Runnable() {
@Override
public void run() {
DB db = DB.getInstance(context);
try {
db.beginTransaction();
@ -2072,7 +2073,7 @@ public class FragmentMessages extends FragmentEx {
if (message != null && message.ui_hide) {
Log.i("Move id=" + id + " target=" + result.target.name);
EntityFolder folder = db.folder().getFolderByName(message.account, result.target.name);
EntityOperation.queue(db, message, EntityOperation.MOVE, folder.id);
EntityOperation.queue(context, db, message, EntityOperation.MOVE, folder.id);
}
}

@ -239,7 +239,7 @@ public class FragmentOptions extends FragmentEx implements SharedPreferences.OnS
Log.e(ex);
db.message().setMessageContent(message.id, false, null);
if (!metered)
EntityOperation.queue(db, message, EntityOperation.BODY);
EntityOperation.queue(context, db, message, EntityOperation.BODY);
}
}

@ -318,7 +318,7 @@ public class Helper {
attachOperations(context, draft.id, 4);
attachLogcat(context, draft.id, 5);
EntityOperation.queue(db, draft, EntityOperation.ADD);
EntityOperation.queue(context, db, draft, EntityOperation.ADD);
db.setTransactionSuccessful();
} finally {

@ -365,7 +365,7 @@ public class ServiceSynchronize extends LifecycleService {
switch (parts[0]) {
case "seen":
EntityOperation.queue(db, message, EntityOperation.SEEN, true);
EntityOperation.queue(ServiceSynchronize.this, db, message, EntityOperation.SEEN, true);
break;
case "archive":
@ -373,13 +373,13 @@ public class ServiceSynchronize extends LifecycleService {
if (archive == null)
archive = db.folder().getFolderByType(message.account, EntityFolder.TRASH);
if (archive != null)
EntityOperation.queue(db, message, EntityOperation.MOVE, archive.id);
EntityOperation.queue(ServiceSynchronize.this, db, message, EntityOperation.MOVE, archive.id);
break;
case "trash":
EntityFolder trash = db.folder().getFolderByType(message.account, EntityFolder.TRASH);
if (trash != null)
EntityOperation.queue(db, message, EntityOperation.MOVE, trash.id);
EntityOperation.queue(ServiceSynchronize.this, db, message, EntityOperation.MOVE, trash.id);
break;
case "ignore":
@ -1699,9 +1699,6 @@ public class ServiceSynchronize extends LifecycleService {
Folder itarget = istore.getFolder(target.name);
itarget.appendMessages(new Message[]{icopy});
}
if (EntityFolder.ARCHIVE.equals(folder.type))
db.message().setMessageUiHide(message.id, false);
}
private void doDelete(EntityFolder folder, IMAPFolder ifolder, EntityMessage message, JSONArray jargs, DB db) throws MessagingException, JSONException {
@ -1816,7 +1813,7 @@ public class ServiceSynchronize extends LifecycleService {
message.uid = null;
db.message().updateMessage(message);
Log.i("Appending sent msgid=" + message.msgid);
EntityOperation.queue(db, message, EntityOperation.ADD); // Could already exist
EntityOperation.queue(ServiceSynchronize.this, db, message, EntityOperation.ADD); // Could already exist
}
}

Loading…
Cancel
Save