From d0cd66eab7429a4ea875ded580ae118b5d31e8d4 Mon Sep 17 00:00:00 2001 From: StoyanDimitrov Date: Fri, 10 Aug 2018 18:21:05 +0000 Subject: [PATCH 1/4] Add GMX to providers Tested in the application. --- app/src/main/res/xml/providers.xml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/xml/providers.xml b/app/src/main/res/xml/providers.xml index c0ebbd5fc5..30d8868c39 100644 --- a/app/src/main/res/xml/providers.xml +++ b/app/src/main/res/xml/providers.xml @@ -92,4 +92,13 @@ port="465" starttls="false" /> - \ No newline at end of file + + + + + From 643b17397af1bd0c98c3c110fc8630e046d9afb0 Mon Sep 17 00:00:00 2001 From: M66B Date: Fri, 10 Aug 2018 19:35:05 +0000 Subject: [PATCH 2/4] Refactored compose to create a draft on get --- .../eu/faircode/email/ActivityCompose.java | 6 +- .../java/eu/faircode/email/ActivityView.java | 19 +- .../eu/faircode/email/AdapterMessage.java | 22 +- .../java/eu/faircode/email/FragmentAbout.java | 1 + .../eu/faircode/email/FragmentCompose.java | 338 ++++++++---------- .../eu/faircode/email/FragmentMessage.java | 13 +- .../eu/faircode/email/FragmentMessages.java | 35 +- 7 files changed, 216 insertions(+), 218 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/ActivityCompose.java b/app/src/main/java/eu/faircode/email/ActivityCompose.java index a597e34097..8f64d6b9ac 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 2d5e77f47a..d3e0eeb710 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 734387f22e..28231ed45b 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 574713b7e4..c29716494d 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 21932c7b57..38aad6f418 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()); } } From 4b5a072ae5d4aa067f7ba23ba8723ed306342d07 Mon Sep 17 00:00:00 2001 From: M66B Date: Fri, 10 Aug 2018 20:07:13 +0000 Subject: [PATCH 3/4] Basic add attachment --- .../java/eu/faircode/email/DaoAttachment.java | 3 + .../eu/faircode/email/FragmentCompose.java | 241 +++++++++++------- 2 files changed, 151 insertions(+), 93 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/DaoAttachment.java b/app/src/main/java/eu/faircode/email/DaoAttachment.java index 01a41503e8..c31326cc74 100644 --- a/app/src/main/java/eu/faircode/email/DaoAttachment.java +++ b/app/src/main/java/eu/faircode/email/DaoAttachment.java @@ -38,6 +38,9 @@ public interface DaoAttachment { @Query("SELECT * FROM attachment WHERE message = :message AND sequence = :sequence") EntityAttachment getAttachment(long message, int sequence); + @Query("SELECT COUNT(attachment.id) FROM attachment WHERE message = :message") + int getAttachmentCount(long message); + @Query("UPDATE attachment SET progress = :progress WHERE id = :id") void setProgress(long id, int progress); diff --git a/app/src/main/java/eu/faircode/email/FragmentCompose.java b/app/src/main/java/eu/faircode/email/FragmentCompose.java index 50d573a499..fa29149782 100644 --- a/app/src/main/java/eu/faircode/email/FragmentCompose.java +++ b/app/src/main/java/eu/faircode/email/FragmentCompose.java @@ -73,6 +73,7 @@ import androidx.lifecycle.Observer; import androidx.loader.app.LoaderManager; import androidx.loader.content.AsyncTaskLoader; import androidx.loader.content.Loader; +import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import static android.app.Activity.RESULT_OK; @@ -96,6 +97,8 @@ public class FragmentCompose extends FragmentEx { private Group grpReady; private MenuItem menuAttachment = null; + private AdapterAttachment adapter; + @Override @Nullable public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { @@ -230,6 +233,13 @@ public class FragmentCompose extends FragmentEx { }); } + rvAttachment.setHasFixedSize(false); + LinearLayoutManager llm = new LinearLayoutManager(getContext()); + rvAttachment.setLayoutManager(llm); + + adapter = new AdapterAttachment(getContext()); + rvAttachment.setAdapter(adapter); + return view; } @@ -319,104 +329,136 @@ public class FragmentCompose extends FragmentEx { public void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == RESULT_OK) { if (requestCode == ActivityCompose.REQUEST_ATTACHMENT) { - if (data != null) { - Bundle args = new Bundle(); - args.putParcelable("uri", data.getData()); - new SimpleLoader() { - @Override - public Object onLoad(Bundle args) throws IOException { - Uri uri = args.getParcelable("uri"); - Cursor cursor = null; - try { - cursor = getActivity().getContentResolver().query(uri, null, null, null, null, null); - if (cursor != null && cursor.moveToFirst()) { - EntityAttachment attachment = new EntityAttachment(); - attachment.name = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); - - String extension = MimeTypeMap.getFileExtensionFromUrl(attachment.name.toLowerCase()); - if (extension != null) - attachment.type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); - if (extension == null) - attachment.type = "application/octet-stream"; - - InputStream is = null; - try { - is = getContext().getContentResolver().openInputStream(uri); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - - int len; - byte[] buffer = new byte[8192]; - while ((len = is.read(buffer)) > 0) - bos.write(buffer, 0, len); - - attachment.size = bos.size(); - attachment.content = bos.toByteArray(); - } finally { - if (is != null) - is.close(); - } - - return attachment; - } - } finally { - if (cursor != null) - cursor.close(); - } + if (data != null) + handleAddAttachment(data); + } else + handlePickContact(requestCode, data); + } + } - return null; - } + private void handlePickContact(int requestCode, Intent data) { + Cursor cursor = null; + try { + cursor = getContext().getContentResolver().query(data.getData(), + new String[]{ + ContactsContract.CommonDataKinds.Email.ADDRESS, + ContactsContract.Contacts.DISPLAY_NAME + }, + null, null, null); + if (cursor != null && cursor.moveToFirst()) { + int colEmail = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.ADDRESS); + int colName = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME); + String email = cursor.getString(colEmail); + String name = cursor.getString(colName); + + String text = null; + if (requestCode == ActivityCompose.REQUEST_CONTACT_TO) + text = etTo.getText().toString(); + else if (requestCode == ActivityCompose.REQUEST_CONTACT_CC) + text = etCc.getText().toString(); + else if (requestCode == ActivityCompose.REQUEST_CONTACT_BCC) + text = etBcc.getText().toString(); + + InternetAddress address = new InternetAddress(email, name); + StringBuilder sb = new StringBuilder(text); + if (sb.length() > 0) + sb.append("; "); + sb.append(address.toString()); + + if (requestCode == ActivityCompose.REQUEST_CONTACT_TO) + etTo.setText(sb.toString()); + else if (requestCode == ActivityCompose.REQUEST_CONTACT_CC) + etCc.setText(sb.toString()); + else if (requestCode == ActivityCompose.REQUEST_CONTACT_BCC) + etBcc.setText(sb.toString()); + } + } catch (Throwable ex) { + Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex)); + Toast.makeText(getContext(), ex.getMessage(), Toast.LENGTH_LONG).show(); + } finally { + if (cursor != null) + cursor.close(); + } + } - @Override - public void onLoaded(Bundle args, Result result) { - EntityAttachment attachment = (EntityAttachment) result.data; - } - }.load(this, ActivityCompose.LOADER_COMPOSE_ATTACHMENT, args); - } - } else { + private void handleAddAttachment(Intent data) { + Bundle args = new Bundle(); + args.putLong("id", getArguments().getLong("id")); + args.putParcelable("uri", data.getData()); + + new SimpleLoader() { + @Override + public Object onLoad(Bundle args) throws IOException { Cursor cursor = null; try { - cursor = getContext().getContentResolver().query(data.getData(), - new String[]{ - ContactsContract.CommonDataKinds.Email.ADDRESS, - ContactsContract.Contacts.DISPLAY_NAME - }, - null, null, null); - if (cursor != null && cursor.moveToFirst()) { - int colEmail = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.ADDRESS); - int colName = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME); - String email = cursor.getString(colEmail); - String name = cursor.getString(colName); - - String text = null; - if (requestCode == ActivityCompose.REQUEST_CONTACT_TO) - text = etTo.getText().toString(); - else if (requestCode == ActivityCompose.REQUEST_CONTACT_CC) - text = etCc.getText().toString(); - else if (requestCode == ActivityCompose.REQUEST_CONTACT_BCC) - text = etBcc.getText().toString(); - - InternetAddress address = new InternetAddress(email, name); - StringBuilder sb = new StringBuilder(text); - if (sb.length() > 0) - sb.append("; "); - sb.append(address.toString()); - - if (requestCode == ActivityCompose.REQUEST_CONTACT_TO) - etTo.setText(sb.toString()); - else if (requestCode == ActivityCompose.REQUEST_CONTACT_CC) - etCc.setText(sb.toString()); - else if (requestCode == ActivityCompose.REQUEST_CONTACT_BCC) - etBcc.setText(sb.toString()); + Uri uri = args.getParcelable("uri"); + cursor = getActivity().getContentResolver().query(uri, null, null, null, null, null); + if (cursor == null || !cursor.moveToFirst()) + return null; + + DB db = DB.getInstance(getContext()); + + long id = args.getLong("id"); + EntityMessage draft = db.message().getMessage(id); + + EntityAttachment attachment = new EntityAttachment(); + attachment.message = draft.id; + attachment.sequence = db.attachment().getAttachmentCount(draft.id); + attachment.name = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); + + String extension = MimeTypeMap.getFileExtensionFromUrl(attachment.name.toLowerCase()); + if (extension != null) + attachment.type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); + if (extension == null) + attachment.type = "application/octet-stream"; + + String size = cursor.getString(cursor.getColumnIndex(OpenableColumns.SIZE)); + + attachment.size = (size == null ? null : Integer.parseInt(size)); + attachment.progress = 0; + + db.attachment().insertAttachment(attachment); + + InputStream is = null; + try { + is = getContext().getContentResolver().openInputStream(uri); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + + int len; + byte[] buffer = new byte[8192]; + while ((len = is.read(buffer)) > 0) { + os.write(buffer, 0, len); + + // Update progress + if (attachment.size != null) { + attachment.progress = os.size() * 100 / attachment.size; + db.attachment().updateAttachment(attachment); + } + } + + attachment.size = os.size(); + attachment.progress = null; + attachment.content = os.toByteArray(); + db.attachment().updateAttachment(attachment); + } finally { + if (is != null) + is.close(); } - } catch (Throwable ex) { - Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex)); - Toast.makeText(getContext(), ex.getMessage(), Toast.LENGTH_LONG).show(); + + + return null; } finally { if (cursor != null) cursor.close(); } } - } + + @Override + public void onLoaded(Bundle args, Result result) { + if (result.ex != null) + Toast.makeText(getContext(), result.ex.toString(), Toast.LENGTH_LONG).show(); + } + }.load(this, ActivityCompose.LOADER_COMPOSE_ATTACHMENT, args); } private void onAction(int action) { @@ -554,10 +596,10 @@ public class FragmentCompose extends FragmentEx { grpAddresses.setVisibility("reply_all".equals(action) ? View.VISIBLE : View.GONE); grpReady.setVisibility(View.VISIBLE); - ArrayAdapter adapter = (ArrayAdapter) spFrom.getAdapter(); - if (adapter != null) { - for (int pos = 0; pos < adapter.getCount(); pos++) { - EntityIdentity identity = (EntityIdentity) adapter.getItem(pos); + ArrayAdapter aa = (ArrayAdapter) spFrom.getAdapter(); + if (aa != null) { + for (int pos = 0; pos < aa.getCount(); pos++) { + EntityIdentity identity = (EntityIdentity) aa.getItem(pos); if (msg.identity == null ? msg.from != null && msg.from.length > 0 && ((InternetAddress) msg.from[0]).getAddress().equals(identity.email) : msg.identity.equals(identity.id)) { @@ -571,7 +613,20 @@ public class FragmentCompose extends FragmentEx { 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)); + + DB db = DB.getInstance(getContext()); + db.attachment().liveAttachments(msg.id).removeObservers(getViewLifecycleOwner()); + db.attachment().liveAttachments(msg.id).observe(getViewLifecycleOwner(), + new Observer>() { + @Override + public void onChanged(@Nullable List attachments) { + adapter.set(attachments); + grpAttachments.setVisibility(attachments.size() > 0 ? View.VISIBLE : View.GONE); + } + }); + + + etBody.setText(TextUtils.isEmpty(msg.body) ? null : Html.fromHtml(msg.body)); if ("edit".equals(action)) etTo.requestFocus(); From 119c54e6643e618cffc4727c2345afd609712343 Mon Sep 17 00:00:00 2001 From: M66B Date: Fri, 10 Aug 2018 20:07:54 +0000 Subject: [PATCH 4/4] Disable STARTTLS for GMX Refs #30 --- app/src/main/res/xml/providers.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/xml/providers.xml b/app/src/main/res/xml/providers.xml index 30d8868c39..ece71bc5fe 100644 --- a/app/src/main/res/xml/providers.xml +++ b/app/src/main/res/xml/providers.xml @@ -99,6 +99,6 @@ + starttls="false" />