diff --git a/app/src/main/java/eu/faircode/email/ActivityCompose.java b/app/src/main/java/eu/faircode/email/ActivityCompose.java index a597e340..8f64d6b9 100644 --- a/app/src/main/java/eu/faircode/email/ActivityCompose.java +++ b/app/src/main/java/eu/faircode/email/ActivityCompose.java @@ -45,12 +45,8 @@ public class ActivityCompose extends ActivityBase implements FragmentManager.OnB getSupportFragmentManager().addOnBackStackChangedListener(this); if (getSupportFragmentManager().getFragments().size() == 0) { - Bundle args = getIntent().getExtras(); - if (args == null) - args = new Bundle(); - FragmentCompose fragment = new FragmentCompose(); - fragment.setArguments(args); + fragment.setArguments(getIntent().getExtras()); FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); fragmentTransaction.replace(R.id.content_frame, fragment).addToBackStack("compose"); diff --git a/app/src/main/java/eu/faircode/email/ActivityView.java b/app/src/main/java/eu/faircode/email/ActivityView.java index 2d5e77f4..d3e0eeb7 100644 --- a/app/src/main/java/eu/faircode/email/ActivityView.java +++ b/app/src/main/java/eu/faircode/email/ActivityView.java @@ -64,15 +64,16 @@ public class ActivityView extends ActivityBase implements FragmentManager.OnBack static final int LOADER_ACCOUNT_PUT = 2; static final int LOADER_IDENTITY_PUT = 3; static final int LOADER_FOLDER_PUT = 4; - static final int LOADER_MESSAGE_VIEW = 5; - static final int LOADER_MESSAGE_SEEN = 6; - static final int LOADER_MESSAGE_EDIT = 7; - static final int LOADER_MESSAGE_SPAM = 8; - static final int LOADER_MESSAGE_TRASH = 9; - static final int LOADER_MESSAGE_MOVE = 10; - static final int LOADER_MESSAGE_ARCHIVE = 11; - static final int LOADER_SEEN_UNTIL = 12; - static final int LOADER_DEBUG_INFO = 13; + static final int LOADER_MESSAGE_ACCOUNT = 5; + static final int LOADER_MESSAGE_VIEW = 6; + static final int LOADER_MESSAGE_SEEN = 7; + static final int LOADER_MESSAGE_EDIT = 8; + static final int LOADER_MESSAGE_SPAM = 9; + static final int LOADER_MESSAGE_TRASH = 10; + static final int LOADER_MESSAGE_MOVE = 11; + static final int LOADER_MESSAGE_ARCHIVE = 12; + static final int LOADER_SEEN_UNTIL = 13; + static final int LOADER_DEBUG_INFO = 14; static final int REQUEST_VIEW = 1; static final int REQUEST_UNSEEN = 2; diff --git a/app/src/main/java/eu/faircode/email/AdapterMessage.java b/app/src/main/java/eu/faircode/email/AdapterMessage.java index 734387f2..28231ed4 100644 --- a/app/src/main/java/eu/faircode/email/AdapterMessage.java +++ b/app/src/main/java/eu/faircode/email/AdapterMessage.java @@ -45,7 +45,7 @@ public class AdapterMessage extends PagedListAdapter>() { @Override public void onChanged(@Nullable final List identities) { + // Sort identities Collections.sort(identities, new Comparator() { @Override public int compare(EntityIdentity i1, EntityIdentity i2) { @@ -265,6 +248,7 @@ public class FragmentCompose extends FragmentEx { } }); + // Show identities ArrayAdapter adapter = new ArrayAdapter<>(getContext(), R.layout.spinner_item, identities); adapter.setDropDownViewResource(R.layout.spinner_dropdown_item); spFrom.setAdapter(adapter); @@ -279,9 +263,16 @@ public class FragmentCompose extends FragmentEx { spFrom.setVisibility(View.VISIBLE); ivIdentityAdd.setVisibility(View.VISIBLE); - // Get might select another identity - LoaderManager.getInstance(FragmentCompose.this) - .restartLoader(ActivityCompose.LOADER_COMPOSE_GET, getArguments(), getLoaderCallbacks).forceLoad(); + // Get draft + new Handler().post(new Runnable() { + @Override + public void run() { + // Get might select another identity + LoaderManager.getInstance(FragmentCompose.this) + .restartLoader(ActivityCompose.LOADER_COMPOSE_GET, getArguments(), getLoaderCallbacks).forceLoad(); + + } + }); } }); } @@ -292,6 +283,13 @@ public class FragmentCompose extends FragmentEx { super.onCreateOptionsMenu(menu, inflater); } + @Override + public void onPrepareOptionsMenu(Menu menu) { + super.onPrepareOptionsMenu(menu); + menuAttachment = menu.findItem(R.id.menu_attachment); + menuAttachment.setEnabled(false); + } + @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { @@ -421,18 +419,16 @@ public class FragmentCompose extends FragmentEx { } } - private void actionPut(long id, String action) { - Log.i(Helper.TAG, "Put id=" + id + " action=" + action); + private void onAction(int action) { bottom_navigation.getMenu().setGroupEnabled(0, false); + long id = getArguments().getLong("id", -1); EntityIdentity identity = (EntityIdentity) spFrom.getSelectedItem(); Bundle args = new Bundle(); - args.putString("action", action); args.putLong("id", id); - args.putLong("iid", identity == null ? -1 : identity.id); - args.putString("thread", FragmentCompose.this.thread); - args.putLong("rid", FragmentCompose.this.rid); + args.putInt("action", action); + args.putLong("identity", identity == null ? -1 : identity.id); args.putString("to", etTo.getText().toString()); args.putString("cc", etCc.getText().toString()); args.putString("bcc", etBcc.getText().toString()); @@ -443,7 +439,7 @@ public class FragmentCompose extends FragmentEx { .restartLoader(ActivityCompose.LOADER_COMPOSE_PUT, args, putLoaderCallbacks).forceLoad(); } - private static class GetLoader extends AsyncTaskLoader { + private static class GetLoader extends AsyncTaskLoader { private Bundle args; GetLoader(Context context) { @@ -456,167 +452,139 @@ public class FragmentCompose extends FragmentEx { @Nullable @Override - public Bundle loadInBackground() { - Bundle result = new Bundle(); + public EntityMessage loadInBackground() { + EntityMessage draft = null; try { String action = args.getString("action"); long id = args.getLong("id", -1); + long account = args.getLong("account", -1); + long reference = args.getLong("reference", -1); + Log.i(Helper.TAG, "Get action=" + action + " id=" + id + " account=" + account + " reference=" + reference); - result.putString("action", action); - - EntityMessage msg = DB.getInstance(getContext()).message().getMessage(id); - if (msg != null) { - if (msg.identity != null) - result.putLong("iid", msg.identity); - if (msg.replying != null) - result.putLong("rid", msg.replying); - result.putSerializable("cc", msg.cc); - result.putSerializable("bcc", msg.bcc); - result.putString("thread", msg.thread); - result.putString("subject", msg.subject); - result.putString("body", msg.body); - } + DB db = DB.getInstance(getContext()); - if (TextUtils.isEmpty(action)) { - if (msg != null) { - result.putSerializable("from", msg.from); - result.putSerializable("to", msg.to); - } - } else if ("reply".equals(action)) { - Address[] to = null; - if (msg != null) - to = (msg.reply == null || msg.reply.length == 0 ? msg.from : msg.reply); - result.putLong("rid", msg.id); - result.putSerializable("from", msg.to); - result.putSerializable("to", to); - } else if ("reply_all".equals(action)) { - Address[] to = null; - if (msg != null) { - List
addresses = new ArrayList<>(); - if (msg.reply != null) - addresses.addAll(Arrays.asList(msg.reply)); - else if (msg.from != null) - addresses.addAll(Arrays.asList(msg.from)); - if (msg.cc != null) - addresses.addAll(Arrays.asList(msg.cc)); - to = addresses.toArray(new Address[0]); + draft = db.message().getMessage(id); + if (draft == null) { + EntityMessage ref = DB.getInstance(getContext()).message().getMessage(reference); + if (ref != null) + account = ref.account; + + EntityFolder drafts; + drafts = db.folder().getFolderByType(account, EntityFolder.DRAFTS); + if (drafts == null) + drafts = db.folder().getPrimaryDrafts(); + + draft = new EntityMessage(); + draft.account = account; + draft.folder = drafts.id; + + if (ref != null) { + draft.thread = ref.thread; + + if ("reply".equals(action)) { + draft.replying = ref.id; + draft.to = (ref.reply == null || ref.reply.length == 0 ? ref.from : ref.reply); + draft.from = ref.to; + + } else if ("reply_all".equals(action)) { + draft.replying = ref.id; + List
addresses = new ArrayList<>(); + if (draft.reply != null && ref.reply.length > 0) + addresses.addAll(Arrays.asList(ref.reply)); + else if (draft.from != null) + addresses.addAll(Arrays.asList(ref.from)); + if (draft.cc != null) + addresses.addAll(Arrays.asList(ref.cc)); + draft.to = addresses.toArray(new Address[0]); + draft.from = ref.to; + + } else if ("forward".equals(action)) { + //msg.replying = ref.id; + draft.from = ref.to; + } + + if ("reply".equals(action) || "reply_all".equals(action)) { + draft.subject = getContext().getString(R.string.title_subject_reply, ref.subject); + draft.body = String.format("

%s %s:

%s", + Html.escapeHtml(new Date().toString()), + Html.escapeHtml(TextUtils.join(", ", draft.to)), + HtmlHelper.sanitize(getContext(), ref.body, true)); + } else if ("forward".equals(action)) { + draft.subject = getContext().getString(R.string.title_subject_forward, ref.subject); + draft.body = String.format("

%s %s:

%s", + Html.escapeHtml(new Date().toString()), + Html.escapeHtml(TextUtils.join(", ", ref.from)), + HtmlHelper.sanitize(getContext(), ref.body, true)); + } } - result.putLong("rid", msg.id); - result.putSerializable("from", msg.to); - result.putSerializable("to", to); - } else if ("forward".equals(action)) { - Address[] to = null; - if (msg != null) - to = (msg.reply == null || msg.reply.length == 0 ? msg.from : msg.reply); - result.putSerializable("from", msg.to); - result.putSerializable("to", to); + + draft.received = new Date().getTime(); + draft.seen = false; + draft.ui_seen = false; + draft.ui_hide = false; + + draft.id = DB.getInstance(getContext()).message().insertMessage(draft); } } catch (Throwable ex) { Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex)); } - return result; + + return draft; } } - private LoaderManager.LoaderCallbacks getLoaderCallbacks = new LoaderManager.LoaderCallbacks() { + private LoaderManager.LoaderCallbacks getLoaderCallbacks = new LoaderManager.LoaderCallbacks() { @NonNull @Override - public Loader onCreateLoader(int id, @Nullable Bundle args) { + public Loader onCreateLoader(int id, @Nullable Bundle args) { GetLoader loader = new GetLoader(getContext()); loader.setArgs(args); return loader; } @Override - public void onLoadFinished(@NonNull Loader loader, Bundle result) { + public void onLoadFinished(@NonNull Loader loader, EntityMessage msg) { LoaderManager.getInstance(FragmentCompose.this).destroyLoader(loader.getId()); - long iid = result.getLong("iid", -1); - long rid = result.getLong("rid", -1); - String thread = result.getString("thread"); - Address[] from = (Address[]) result.getSerializable("from"); - Address[] to = (Address[]) result.getSerializable("to"); - Address[] cc = (Address[]) result.getSerializable("cc"); - Address[] bcc = (Address[]) result.getSerializable("bcc"); - String subject = result.getString("subject"); - String body = result.getString("body"); - String action = result.getString("action"); + getArguments().putLong("id", msg.id); + String action = getArguments().getString("action"); + menuAttachment.setEnabled(true); pbWait.setVisibility(View.GONE); grpAddresses.setVisibility("reply_all".equals(action) ? View.VISIBLE : View.GONE); grpReady.setVisibility(View.VISIBLE); - FragmentCompose.this.thread = thread; - FragmentCompose.this.rid = rid; - ArrayAdapter adapter = (ArrayAdapter) spFrom.getAdapter(); if (adapter != null) { for (int pos = 0; pos < adapter.getCount(); pos++) { EntityIdentity identity = (EntityIdentity) adapter.getItem(pos); - if (iid < 0 - ? from != null && from.length > 0 && ((InternetAddress) from[0]).getAddress().equals(identity.email) - : iid == identity.id) { + if (msg.identity == null + ? msg.from != null && msg.from.length > 0 && ((InternetAddress) msg.from[0]).getAddress().equals(identity.email) + : msg.identity.equals(identity.id)) { spFrom.setSelection(pos); break; } } } - if (!once) { - // Prevent changed fields from being overwritten - once = true; - - Handler handler = new Handler(); + etTo.setText(msg.to == null ? null : TextUtils.join(", ", msg.to)); + etCc.setText(msg.cc == null ? null : TextUtils.join(", ", msg.cc)); + etBcc.setText(msg.bcc == null ? null : TextUtils.join(", ", msg.bcc)); + etSubject.setText(msg.subject); + etBody.setText(Html.fromHtml(msg.body)); - etCc.setText(cc == null ? null : TextUtils.join(", ", cc)); - etBcc.setText(bcc == null ? null : TextUtils.join(", ", bcc)); - - if (action == null) { - etTo.setText(to == null ? null : TextUtils.join(", ", to)); - 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(to == null ? null : TextUtils.join(", ", to)); - String text = String.format("

%s %s:

%s", - Html.escapeHtml(new Date().toString()), - Html.escapeHtml(to == null ? "" : TextUtils.join(", ", to)), - HtmlHelper.sanitize(getContext(), body, true)); - etSubject.setText(getContext().getString(R.string.title_subject_reply, subject)); - etBody.setText(Html.fromHtml(text)); - handler.post(new Runnable() { - @Override - public void run() { - etBody.requestFocus(); - } - }); - } else if ("forward".equals(action)) { - String text = String.format("

%s %s:

%s", - Html.escapeHtml(new Date().toString()), - Html.escapeHtml(to == null ? "" : TextUtils.join(", ", to)), - HtmlHelper.sanitize(getContext(), body, true)); - etSubject.setText(getContext().getString(R.string.title_subject_forward, subject)); - etBody.setText(Html.fromHtml(text)); - handler.post(new Runnable() { - @Override - public void run() { - etTo.requestFocus(); - } - }); - } - } + if ("edit".equals(action)) + etTo.requestFocus(); + else if ("reply".equals(action) || "reply_all".equals(action)) + etBody.requestFocus(); + else if ("forward".equals(action)) + etTo.requestFocus(); bottom_navigation.getMenu().setGroupEnabled(0, true); } @Override - public void onLoaderReset(@NonNull Loader loader) { + public void onLoaderReset(@NonNull Loader loader) { } }; @@ -634,45 +602,29 @@ public class FragmentCompose extends FragmentEx { @Override public Throwable loadInBackground() { try { - String action = args.getString("action"); - long id = args.getLong("id"); - Log.i(Helper.TAG, "Put load id=" + id + " action=" + action); - - DB db = DB.getInstance(getContext()); - DaoMessage message = db.message(); - DaoIdentity identity = db.identity(); - DaoFolder folder = db.folder(); - // Get data - EntityMessage draft = message.getMessage(id); - EntityIdentity ident = identity.getIdentity(args.getLong("iid")); - if (ident == null) - throw new IllegalArgumentException(getContext().getString(R.string.title_from_missing)); - - EntityFolder drafts = db.folder().getFolderByType(ident.account, EntityFolder.DRAFTS); - - long rid = args.getLong("rid", -1); - String thread = args.getString("thread"); + long id = args.getLong("id"); + int action = args.getInt("action"); + long iid = args.getLong("identity"); String to = args.getString("to"); String cc = args.getString("cc"); String bcc = args.getString("bcc"); - String body = args.getString("body"); String subject = args.getString("subject"); + String body = args.getString("body"); - Address afrom[] = (ident == null ? null : new Address[]{new InternetAddress(ident.email, ident.name)}); + // Get draft & selected identity + DB db = DB.getInstance(getContext()); + EntityMessage draft = db.message().getMessage(id); + EntityIdentity identity = db.identity().getIdentity(iid); + + // Convert data + Address afrom[] = (identity == null ? null : new Address[]{new InternetAddress(identity.email, identity.name)}); Address ato[] = (TextUtils.isEmpty(to) ? null : InternetAddress.parse(to)); Address acc[] = (TextUtils.isEmpty(cc) ? null : InternetAddress.parse(cc)); Address abcc[] = (TextUtils.isEmpty(bcc) ? null : InternetAddress.parse(bcc)); - // Build draft - boolean update = (draft != null); - if (draft == null) - draft = new EntityMessage(); - draft.account = drafts.account; - draft.folder = drafts.id; - draft.identity = (ident == null ? null : ident.id); - draft.replying = (rid < 0 ? null : rid); - draft.thread = thread; + // Update draft + draft.identity = (identity == null ? null : identity.id); draft.from = afrom; draft.to = ato; draft.cc = acc; @@ -680,20 +632,15 @@ public class FragmentCompose extends FragmentEx { draft.subject = subject; draft.body = "
" + body.replaceAll("\\r?\\n", "
") + "
"; draft.received = new Date().getTime(); - draft.seen = false; - draft.ui_seen = false; - draft.ui_hide = false; - // Store draft - if (!update) - draft.id = message.insertMessage(draft); + db.message().updateMessage(draft); // Check data try { db.beginTransaction(); - if ("trash".equals(action)) { - EntityFolder trash = db.folder().getFolderByType(ident.account, EntityFolder.TRASH); + if (action == R.id.action_trash) { + EntityFolder trash = db.folder().getFolderByType(draft.account, EntityFolder.TRASH); boolean move = (draft.uid != null); if (move) @@ -706,7 +653,7 @@ public class FragmentCompose extends FragmentEx { if (!move) EntityOperation.queue(db, draft, EntityOperation.ADD); - } else if ("save".equals(action)) { + } else if (action == R.id.action_save) { // Delete previous draft draft.ui_hide = true; db.message().updateMessage(draft); @@ -719,7 +666,11 @@ public class FragmentCompose extends FragmentEx { draft.id = db.message().insertMessage(draft); EntityOperation.queue(db, draft, EntityOperation.ADD); - } else if ("send".equals(action)) { + } else if (action == R.id.action_send) { + // Check data + if (draft.identity == null) + throw new IllegalArgumentException(getContext().getString(R.string.title_from_missing)); + if (draft.to == null && draft.cc == null && draft.bcc == null) throw new IllegalArgumentException(getContext().getString(R.string.title_to_missing)); @@ -730,7 +681,7 @@ public class FragmentCompose extends FragmentEx { // Copy message to outbox draft.id = null; - draft.folder = folder.getOutbox().id; + draft.folder = db.folder().getOutbox().id; draft.uid = null; draft.ui_hide = false; draft.id = db.message().insertMessage(draft); @@ -766,19 +717,18 @@ public class FragmentCompose extends FragmentEx { public void onLoadFinished(@NonNull Loader loader, Throwable ex) { LoaderManager.getInstance(FragmentCompose.this).destroyLoader(loader.getId()); - Bundle args = ((PutLoader) loader).args; - String action = args.getString("action"); - Log.i(Helper.TAG, "Put finished action=" + action + " ex=" + ex); - bottom_navigation.getMenu().setGroupEnabled(0, true); if (ex == null) { - if ("trash".equals(action)) { + Bundle args = ((PutLoader) loader).args; + int action = args.getInt("action"); + + if (action == R.id.action_trash) { getFragmentManager().popBackStack(); Toast.makeText(getContext(), R.string.title_draft_trashed, Toast.LENGTH_LONG).show(); - } else if ("save".equals(action)) + } else if (action == R.id.action_save) Toast.makeText(getContext(), R.string.title_draft_saved, Toast.LENGTH_LONG).show(); - else if ("send".equals(action)) { + else if (action == R.id.action_send) { getFragmentManager().popBackStack(); Toast.makeText(getContext(), R.string.title_queued, Toast.LENGTH_LONG).show(); } diff --git a/app/src/main/java/eu/faircode/email/FragmentMessage.java b/app/src/main/java/eu/faircode/email/FragmentMessage.java index 574713b7..c2971649 100644 --- a/app/src/main/java/eu/faircode/email/FragmentMessage.java +++ b/app/src/main/java/eu/faircode/email/FragmentMessage.java @@ -460,6 +460,7 @@ public class FragmentMessage extends FragmentEx { if (result.ex == null) getContext().startActivity( new Intent(getContext(), ActivityCompose.class) + .putExtra("action", "edit") .putExtra("id", (long) result.data)); else Toast.makeText(getContext(), result.ex.toString(), Toast.LENGTH_LONG).show(); @@ -469,14 +470,14 @@ public class FragmentMessage extends FragmentEx { private void onActionForward(long id) { startActivity(new Intent(getContext(), ActivityCompose.class) - .putExtra("id", id) - .putExtra("action", "forward")); + .putExtra("action", "forward") + .putExtra("reference", id)); } private void onActionReplyAll(long id) { startActivity(new Intent(getContext(), ActivityCompose.class) - .putExtra("id", id) - .putExtra("action", "reply_all")); + .putExtra("action", "reply_all") + .putExtra("reference", id)); } private void onActionSpam(final long id) { @@ -711,8 +712,8 @@ public class FragmentMessage extends FragmentEx { private void onActionReply(long id) { startActivity(new Intent(getContext(), ActivityCompose.class) - .putExtra("id", id) - .putExtra("action", "reply")); + .putExtra("action", "reply") + .putExtra("reference", id)); } private static class MoveLoader extends AsyncTaskLoader> { diff --git a/app/src/main/java/eu/faircode/email/FragmentMessages.java b/app/src/main/java/eu/faircode/email/FragmentMessages.java index 21932c7b..38aad6f4 100644 --- a/app/src/main/java/eu/faircode/email/FragmentMessages.java +++ b/app/src/main/java/eu/faircode/email/FragmentMessages.java @@ -28,6 +28,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ProgressBar; import android.widget.TextView; +import android.widget.Toast; import com.google.android.material.floatingactionbutton.FloatingActionButton; @@ -83,7 +84,10 @@ public class FragmentMessages extends FragmentEx { fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - startActivity(new Intent(getContext(), ActivityCompose.class)); + startActivity(new Intent(getContext(), ActivityCompose.class) + .putExtra("action", "new") + .putExtra("account", (Long) fab.getTag()) + ); } }); @@ -91,6 +95,7 @@ public class FragmentMessages extends FragmentEx { tvNoEmail.setVisibility(View.GONE); grpReady.setVisibility(View.GONE); pbWait.setVisibility(View.VISIBLE); + fab.setVisibility(View.GONE); return view; } @@ -126,7 +131,6 @@ public class FragmentMessages extends FragmentEx { messages = new LivePagedListBuilder<>(db.message().pagedThread(thread, debug), PAGE_SIZE).build(); } - Log.i(Helper.TAG, "Observing messages"); messages.observe(getViewLifecycleOwner(), new Observer>() { @Override public void onChanged(@Nullable PagedList messages) { @@ -145,5 +149,32 @@ public class FragmentMessages extends FragmentEx { } } }); + + new SimpleLoader() { + @Override + public Object onLoad(Bundle args) throws Throwable { + long folder = (args == null ? -1 : args.getLong("folder", -1)); + long thread = (args == null ? -1 : args.getLong("thread", -1)); // message ID + + DB db = DB.getInstance(getContext()); + + if (thread < 0) + if (folder < 0) + return db.folder().getPrimaryDrafts().account; + else + return db.folder().getFolder(folder).account; + else + return db.message().getMessage(thread).account; + } + + @Override + public void onLoaded(Bundle args, Result result) { + if (result.ex == null) { + fab.setTag(result.data); + fab.setVisibility(View.VISIBLE); + } else + Toast.makeText(getContext(), result.ex.toString(), Toast.LENGTH_LONG).show(); + } + }.load(this, ActivityView.LOADER_MESSAGE_ACCOUNT, getArguments()); } }