Select identify from to address, several fixes and improvements

This commit is contained in:
M66B 2018-08-06 11:05:14 +00:00
parent 7052639d48
commit 7b6364b3a2
9 changed files with 113 additions and 50 deletions

View File

@ -328,6 +328,7 @@ public class ActivityView extends ActivityBase implements FragmentManager.OnBack
draft.id = db.message().insertMessage(draft);
EntityOperation.queue(ActivityView.this, draft, EntityOperation.ADD);
EntityOperation.process(ActivityView.this);
startActivity(new Intent(ActivityView.this, ActivityCompose.class)
.putExtra("id", draft.id));

View File

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

View File

@ -102,6 +102,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
message.ui_seen = !message.ui_seen;
DB.getInstance(context).message().updateMessage(message);
EntityOperation.queue(context, message, EntityOperation.SEEN, message.ui_seen);
EntityOperation.process(context);
}
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(context);

View File

@ -93,7 +93,7 @@ public interface DaoMessage {
void deleteMessage(long id);
@Query("DELETE FROM message WHERE folder = :folder AND uid = :uid")
void deleteMessage(long folder, long uid);
int deleteMessage(long folder, long uid);
@Query("DELETE FROM message WHERE folder = :folder")
void deleteMessages(long folder);

View File

@ -31,6 +31,9 @@ import android.util.Log;
import org.json.JSONArray;
import java.util.ArrayList;
import java.util.List;
import static android.arch.persistence.room.ForeignKey.CASCADE;
@Entity(
@ -60,6 +63,8 @@ public class EntityOperation {
public static final String SEND = "send";
public static final String ATTACHMENT = "attachment";
private static List<Intent> queue = new ArrayList<>();
static void queue(Context context, EntityMessage message, String name) {
JSONArray jsonArray = new JSONArray();
queue(context, message, name, jsonArray);
@ -92,16 +97,26 @@ public class EntityOperation {
operation.args = jsonArray.toString();
operation.id = dao.insertOperation(operation);
synchronized (queue) {
queue.add(new Intent(SEND.equals(name)
? ServiceSynchronize.ACTION_PROCESS_OUTBOX
: ServiceSynchronize.ACTION_PROCESS_FOLDER)
.putExtra("folder", message.folder));
}
Log.i(Helper.TAG, "Queued op=" + operation.id + "/" + name +
" args=" + operation.args +
" msg=" + message.folder + "/" + message.id + " uid=" + message.uid +
" purged=" + purged);
}
public static void process(Context context) {
// Processing needs to be done after committing to the database
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(context);
lbm.sendBroadcast(
new Intent(SEND.equals(name)
? ServiceSynchronize.ACTION_PROCESS_OUTBOX
: ServiceSynchronize.ACTION_PROCESS_FOLDER)
.putExtra("folder", message.folder));
synchronized (queue) {
for (Intent intent : queue)
lbm.sendBroadcast(intent);
queue.clear();
}
}
}

View File

@ -24,6 +24,7 @@ import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.provider.ContactsContract;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@ -195,16 +196,18 @@ public class FragmentCompose extends FragmentEx {
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
spFrom.setAdapter(adapter);
// Select primary identity, also for saved drafts
// Select primary identity
for (int pos = 0; pos < identities.size(); pos++)
if (identities.get(pos).primary) {
spFrom.setSelection(pos);
break;
}
// Get might select another identity
getLoaderManager().restartLoader(ActivityCompose.LOADER_COMPOSE_GET, getArguments(), getLoaderCallbacks).forceLoad();
}
});
getLoaderManager().restartLoader(ActivityCompose.LOADER_COMPOSE_GET, getArguments(), getLoaderCallbacks).forceLoad();
return view;
}
@ -369,8 +372,16 @@ public class FragmentCompose extends FragmentEx {
result.putString("from", msg.to);
result.putString("to", to);
} else if ("forward".equals(action)) {
String to = null;
if (msg != null)
try {
Address[] reply = MessageHelper.decodeAddresses(msg.reply);
to = (reply.length == 0 ? msg.from : msg.reply);
} catch (Throwable ex) {
Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex));
}
result.putString("from", msg.to);
result.putString("to", null);
result.putString("to", to);
}
} catch (Throwable ex) {
Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex));
@ -410,19 +421,23 @@ public class FragmentCompose extends FragmentEx {
FragmentCompose.this.rid = rid;
ArrayAdapter adapter = (ArrayAdapter) spFrom.getAdapter();
if (adapter != null)
if (adapter != null) {
InternetAddress[] afrom = MessageHelper.decodeAddresses(from);
for (int pos = 0; pos < adapter.getCount(); pos++) {
EntityIdentity identity = (EntityIdentity) adapter.getItem(pos);
if (iid < 0 ? identity.primary : iid == identity.id) {
if (iid < 0 ? afrom.length > 0 && afrom[0].getAddress().equals(identity.email) : iid == identity.id) {
spFrom.setSelection(pos);
break;
}
}
}
if (!once) {
// Prevent changed fields from being overwritten
once = true;
Handler handler = new Handler();
etCc.setText(TextUtils.join(", ", MessageHelper.decodeAddresses(cc)));
etBcc.setText(TextUtils.join(", ", MessageHelper.decodeAddresses(bcc)));
@ -431,21 +446,34 @@ public class FragmentCompose extends FragmentEx {
etSubject.setText(subject);
if (body != null)
etBody.setText(Html.fromHtml(HtmlHelper.sanitize(getContext(), body, false)));
handler.post(new Runnable() {
@Override
public void run() {
etTo.requestFocus();
}
});
} else if ("reply".equals(action) || "reply_all".equals(action)) {
etTo.setText(TextUtils.join(", ", MessageHelper.decodeAddresses(to)));
String text = String.format("<br><br>%s %s:<br><br>%s",
Html.escapeHtml(new Date().toString()),
Html.escapeHtml(TextUtils.join(", ", MessageHelper.decodeAddresses(from))),
Html.escapeHtml(TextUtils.join(", ", MessageHelper.decodeAddresses(to))),
HtmlHelper.sanitize(getContext(), body, true));
etSubject.setText(getContext().getString(R.string.title_subject_reply, subject));
etBody.setText(Html.fromHtml(text));
handler.postDelayed(new Runnable() {
@Override
public void run() {
etBody.requestFocus();
}
}, 500);
} else if ("forward".equals(action)) {
String text = String.format("<br><br>%s %s:<br><br>%s",
Html.escapeHtml(new Date().toString()),
Html.escapeHtml(TextUtils.join(", ", MessageHelper.decodeAddresses(from))),
Html.escapeHtml(TextUtils.join(", ", MessageHelper.decodeAddresses(to))),
HtmlHelper.sanitize(getContext(), body, true));
etSubject.setText(getContext().getString(R.string.title_subject_forward, subject));
etBody.setText(Html.fromHtml(text));
etTo.requestFocus();
}
}
@ -527,37 +555,47 @@ public class FragmentCompose extends FragmentEx {
draft.id = message.insertMessage(draft);
// Check data
if ("send".equals(action)) {
if (draft.identity == null)
throw new MessagingException(getContext().getString(R.string.title_from_missing));
if (draft.to == null && draft.cc == null && draft.bcc == null)
throw new MessagingException(getContext().getString(R.string.title_to_missing));
try {
db.beginTransaction();
EntityOperation.queue(getContext(), draft, EntityOperation.DELETE);
if ("send".equals(action)) {
if (draft.identity == null)
throw new MessagingException(getContext().getString(R.string.title_from_missing));
if (draft.to == null && draft.cc == null && draft.bcc == null)
throw new MessagingException(getContext().getString(R.string.title_to_missing));
draft.id = null;
draft.folder = folder.getOutbox().id;
draft.ui_hide = false;
draft.id = db.message().insertMessage(draft);
EntityOperation.queue(getContext(), draft, EntityOperation.DELETE);
EntityOperation.queue(getContext(), draft, EntityOperation.SEND);
} else if ("save".equals(action))
EntityOperation.queue(getContext(), draft, EntityOperation.ADD);
else if ("trash".equals(action)) {
EntityOperation.queue(getContext(), draft, EntityOperation.DELETE);
EntityFolder trash = db.folder().getPrimaryFolder(EntityFolder.TYPE_TRASH);
if (trash != null) {
draft.id = null;
draft.folder = trash.id;
draft.folder = folder.getOutbox().id;
draft.ui_hide = false;
draft.id = db.message().insertMessage(draft);
EntityOperation.queue(getContext(), draft, EntityOperation.SEND);
} else if ("save".equals(action))
EntityOperation.queue(getContext(), draft, EntityOperation.ADD);
else if ("trash".equals(action)) {
EntityOperation.queue(getContext(), draft, EntityOperation.DELETE);
EntityFolder trash = db.folder().getPrimaryFolder(EntityFolder.TYPE_TRASH);
if (trash != null) {
draft.id = null;
draft.folder = trash.id;
draft.id = db.message().insertMessage(draft);
EntityOperation.queue(getContext(), draft, EntityOperation.ADD);
}
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
EntityOperation.process(getContext());
return null;
} catch (Throwable ex) {
Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex));

View File

@ -331,6 +331,7 @@ public class FragmentMessage extends FragmentEx {
message.ui_seen = !message.ui_seen;
db.message().updateMessage(message);
EntityOperation.queue(getContext(), message, EntityOperation.SEEN, message.ui_seen);
EntityOperation.process(getContext());
} catch (Throwable ex) {
Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex));
}
@ -381,6 +382,7 @@ public class FragmentMessage extends FragmentEx {
db.message().updateMessage(message);
EntityOperation.queue(getContext(), message, EntityOperation.DELETE);
EntityOperation.process(getContext());
} catch (Throwable ex) {
Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex));
}
@ -401,6 +403,7 @@ public class FragmentMessage extends FragmentEx {
EntityFolder trash = db.folder().getFolderByType(message.account, EntityFolder.TYPE_TRASH);
EntityOperation.queue(getContext(), message, EntityOperation.MOVE, trash.id);
EntityOperation.process(getContext());
} catch (Throwable ex) {
Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex));
}
@ -427,6 +430,7 @@ public class FragmentMessage extends FragmentEx {
EntityFolder spam = db.folder().getFolderByType(message.account, EntityFolder.TYPE_JUNK);
EntityOperation.queue(getContext(), message, EntityOperation.MOVE, spam.id);
EntityOperation.process(getContext());
} catch (Throwable ex) {
Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex));
}
@ -455,6 +459,7 @@ public class FragmentMessage extends FragmentEx {
EntityFolder archive = db.folder().getFolderByType(message.account, EntityFolder.TYPE_ARCHIVE);
EntityOperation.queue(getContext(), message, EntityOperation.MOVE, archive.id);
EntityOperation.process(getContext());
} catch (Throwable ex) {
Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex));
}
@ -546,6 +551,7 @@ public class FragmentMessage extends FragmentEx {
db.message().updateMessage(message);
EntityOperation.queue(getContext(), message, EntityOperation.MOVE, folder);
EntityOperation.process(getContext());
} catch (Throwable ex) {
Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex));
}

View File

@ -192,9 +192,9 @@ public class MessageHelper {
return jaddresses.toString();
}
static Address[] decodeAddresses(String json) {
static InternetAddress[] decodeAddresses(String json) {
if (json == null)
return new Address[0];
return new InternetAddress[0];
List<Address> result = new ArrayList<>();
try {
JSONArray jaddresses = new JSONArray(json);
@ -211,7 +211,7 @@ public class MessageHelper {
} catch (Throwable ex) {
Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex));
}
return result.toArray(new Address[0]);
return result.toArray(new InternetAddress[0]);
}
static String getFormattedAddresses(String json) {

View File

@ -242,7 +242,6 @@ public class ServiceSynchronize extends LifecycleService {
return builder;
}
private Notification.Builder getNotification(String action, Throwable ex) {
// Build pending intent
Intent intent = new Intent(this, ActivityView.class);
@ -579,8 +578,8 @@ public class ServiceSynchronize extends LifecycleService {
try {
long uid = ifolder.getUID(imessage);
DB db = DB.getInstance(ServiceSynchronize.this);
db.message().deleteMessage(folder.id, uid);
Log.i(Helper.TAG, "Deleted uid=" + uid);
int count = db.message().deleteMessage(folder.id, uid);
Log.i(Helper.TAG, "Deleted uid=" + uid + " count=" + count);
} catch (MessageRemovedException ex) {
Log.w(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex));
}
@ -694,25 +693,27 @@ public class ServiceSynchronize extends LifecycleService {
imessage.setFlag(Flags.Flag.SEEN, jargs.getBoolean(0));
} else if (EntityOperation.ADD.equals(op.name)) {
if (!folder.synchronize) {
// Local drafts
Log.w(Helper.TAG, "Folder synchronization disabled");
return;
}
// Append message
EntityMessage msg = message.getMessage(op.message);
if (msg == null)
return;
// Disconnect from remote to prevent deletion
Long uid = msg.uid;
if (msg.uid != null) {
msg.uid = null;
message.updateMessage(msg);
}
// Execute append
Properties props = MessageHelper.getSessionProperties();
Session isession = Session.getInstance(props, null);
MimeMessage imessage = MessageHelper.from(msg, isession);
ifolder.appendMessages(new Message[]{imessage});
// Drafts can be appended multiple times
if (msg.uid != null) {
Message previously = ifolder.getMessageByUID(msg.uid);
if (uid != null) {
Message previously = ifolder.getMessageByUID(uid);
if (previously == null)
throw new MessageRemovedException();
@ -972,8 +973,8 @@ public class ServiceSynchronize extends LifecycleService {
// Delete local messages not at remote
Log.i(Helper.TAG, folder.name + " delete=" + uids.size());
for (Long uid : uids) {
Log.i(Helper.TAG, folder.name + " delete local uid=" + uid);
dao.deleteMessage(folder.id, uid);
int count = dao.deleteMessage(folder.id, uid);
Log.i(Helper.TAG, folder.name + " delete local uid=" + uid + " count=" + count);
}
Log.i(Helper.TAG, folder.name + " synced");