Prepare batch move

This commit is contained in:
M66B 2019-09-28 13:49:56 +02:00
parent a36e260ac6
commit af58493eaa
1 changed files with 85 additions and 61 deletions

View File

@ -259,11 +259,11 @@ class Core {
break; break;
case EntityOperation.MOVE: case EntityOperation.MOVE:
onMove(context, jargs, false, folder, message, (IMAPStore) istore, (IMAPFolder) ifolder, state); onMove(context, jargs, false, folder, Arrays.asList(message), (IMAPStore) istore, (IMAPFolder) ifolder, state);
break; break;
case EntityOperation.COPY: case EntityOperation.COPY:
onMove(context, jargs, true, folder, message, (IMAPStore) istore, (IMAPFolder) ifolder, state); onMove(context, jargs, true, folder, Arrays.asList(message), (IMAPStore) istore, (IMAPFolder) ifolder, state);
break; break;
case EntityOperation.FETCH: case EntityOperation.FETCH:
@ -665,7 +665,7 @@ class Core {
} }
} }
private static void onMove(Context context, JSONArray jargs, boolean copy, EntityFolder folder, EntityMessage message, IMAPStore istore, IMAPFolder ifolder, State state) throws JSONException, MessagingException, IOException { private static void onMove(Context context, JSONArray jargs, boolean copy, EntityFolder folder, List<EntityMessage> messages, IMAPStore istore, IMAPFolder ifolder, State state) throws JSONException, MessagingException, IOException {
// Move message // Move message
DB db = DB.getInstance(context); DB db = DB.getInstance(context);
@ -674,96 +674,120 @@ class Core {
boolean autoread = jargs.optBoolean(1, false); boolean autoread = jargs.optBoolean(1, false);
Flags flags = ifolder.getPermanentFlags(); Flags flags = ifolder.getPermanentFlags();
// Get source message
Message imessage = ifolder.getMessageByUID(message.uid);
if (imessage == null)
throw new MessageRemovedException();
// Get target folder // Get target folder
EntityFolder target = db.folder().getFolder(id); EntityFolder target = db.folder().getFolder(id);
if (target == null) if (target == null)
throw new FolderNotFoundException(); throw new FolderNotFoundException();
IMAPFolder itarget = (IMAPFolder) istore.getFolder(target.name); IMAPFolder itarget = (IMAPFolder) istore.getFolder(target.name);
// Some providers do not support copying drafts // Get source messages
Map<Message, EntityMessage> map = new HashMap<>();
for (EntityMessage message : messages)
try {
Message imessage = ifolder.getMessageByUID(message.uid);
if (imessage != null)
map.put(imessage, message);
} catch (MessageRemovedException ex) {
Log.w(ex);
}
// Some providers do not support the COPY operation for drafts
if (EntityFolder.DRAFTS.equals(folder.type) || EntityFolder.DRAFTS.equals(target.type)) { if (EntityFolder.DRAFTS.equals(folder.type) || EntityFolder.DRAFTS.equals(target.type)) {
Log.i(folder.name + " move from " + folder.type + " to " + target.type); Log.i(folder.name + " move from " + folder.type + " to " + target.type);
File file = File.createTempFile("draft", "." + message.id, context.getCacheDir()); List<Message> icopies = new ArrayList<>();
try (OutputStream os = new FileOutputStream(file)) { for (Message imessage : map.keySet()) {
imessage.writeTo(os); EntityMessage message = map.get(imessage);
File file = File.createTempFile("draft", "." + message.id, context.getCacheDir());
try (OutputStream os = new FileOutputStream(file)) {
imessage.writeTo(os);
}
Properties props = MessageHelper.getSessionProperties();
Session isession = Session.getInstance(props, null);
Message icopy;
try (InputStream is = new BufferedInputStream(new FileInputStream(file))) {
icopy = new MimeMessage(isession, is);
}
file.delete();
// Auto read
if (autoread && flags.contains(Flags.Flag.SEEN))
icopy.setFlag(Flags.Flag.SEEN, true);
if (message.ui_answered && flags.contains(Flags.Flag.ANSWERED))
icopy.setFlag(Flags.Flag.ANSWERED, true);
// Set drafts flag
icopy.setFlag(Flags.Flag.DRAFT, EntityFolder.DRAFTS.equals(target.type));
icopies.add(icopy);
} }
Properties props = MessageHelper.getSessionProperties(); itarget.appendMessages(icopies.toArray(new Message[0]));
Session isession = Session.getInstance(props, null);
Message icopy;
try (InputStream is = new BufferedInputStream(new FileInputStream(file))) {
icopy = new MimeMessage(isession, is);
}
file.delete();
// Auto read
if (autoread && flags.contains(Flags.Flag.SEEN))
icopy.setFlag(Flags.Flag.SEEN, true);
if (message.ui_answered && flags.contains(Flags.Flag.ANSWERED))
icopy.setFlag(Flags.Flag.ANSWERED, true);
// Set drafts flag
icopy.setFlag(Flags.Flag.DRAFT, EntityFolder.DRAFTS.equals(target.type));
itarget.appendMessages(new Message[]{icopy});
} else { } else {
// Auto read for (Message imessage : map.keySet()) {
if (autoread && flags.contains(Flags.Flag.SEEN)) EntityMessage message = map.get(imessage);
imessage.setFlag(Flags.Flag.SEEN, true);
if (message.ui_answered && flags.contains(Flags.Flag.ANSWERED)) // Auto read
imessage.setFlag(Flags.Flag.ANSWERED, true); if (autoread && flags.contains(Flags.Flag.SEEN))
imessage.setFlag(Flags.Flag.SEEN, true);
ifolder.copyMessages(new Message[]{imessage}, itarget); if (message.ui_answered && flags.contains(Flags.Flag.ANSWERED))
imessage.setFlag(Flags.Flag.ANSWERED, true);
}
ifolder.copyMessages(map.keySet().toArray(new Message[0]), itarget);
} }
// Delete source // Delete source
if (!copy) { if (!copy) {
try { try {
imessage.setFlag(Flags.Flag.DELETED, true); for (Message imessage : map.keySet())
imessage.setFlag(Flags.Flag.DELETED, true);
} catch (MessageRemovedException ignored) { } catch (MessageRemovedException ignored) {
} }
ifolder.expunge(); ifolder.expunge();
} }
// Fetch appended/copied when needed // Fetch appended/copied when needed
if (!TextUtils.isEmpty(message.msgid) && if (!target.synchronize || !istore.hasCapability("IDLE"))
(!target.synchronize || !istore.hasCapability("IDLE")))
try { try {
itarget.open(READ_WRITE); itarget.open(READ_WRITE);
try {
Long uid = findUid(itarget, message.msgid, false); for (EntityMessage message : map.values())
if (uid != null) { if (!TextUtils.isEmpty(message.msgid))
JSONArray fargs = new JSONArray(); try {
fargs.put(uid); Long uid = findUid(itarget, message.msgid, false);
onFetch(context, fargs, target, itarget, state); if (uid != null) {
} JSONArray fargs = new JSONArray();
} finally { fargs.put(uid);
itarget.close(); onFetch(context, fargs, target, itarget, state);
} }
} catch (Throwable ex) {
Log.w(ex);
}
} catch (Throwable ex) { } catch (Throwable ex) {
Log.w(ex); Log.w(ex);
} finally {
if (itarget.isOpen())
itarget.close();
} }
// Delete junk contacts // Delete junk contacts
if (EntityFolder.JUNK.equals(target.type)) { if (EntityFolder.JUNK.equals(target.type))
Address[] recipients = (message.reply != null ? message.reply : message.from); for (EntityMessage message : map.values()) {
if (recipients != null) Address[] recipients = (message.reply != null ? message.reply : message.from);
for (Address recipient : recipients) { if (recipients != null)
String email = ((InternetAddress) recipient).getAddress(); for (Address recipient : recipients) {
int count = db.contact().deleteContact(target.account, EntityContact.TYPE_FROM, email); String email = ((InternetAddress) recipient).getAddress();
Log.i("Deleted contact email=" + email + " count=" + count); int count = db.contact().deleteContact(target.account, EntityContact.TYPE_FROM, email);
} Log.i("Deleted contact email=" + email + " count=" + count);
} }
}
} }
private static void onFetch(Context context, JSONArray jargs, EntityFolder folder, IMAPFolder ifolder, State state) throws JSONException, MessagingException, IOException { private static void onFetch(Context context, JSONArray jargs, EntityFolder folder, IMAPFolder ifolder, State state) throws JSONException, MessagingException, IOException {