From b48d54f98faefeb27ba6c9918f73e588dcaac519 Mon Sep 17 00:00:00 2001 From: M66B Date: Fri, 10 Aug 2018 17:13:42 +0000 Subject: [PATCH] Prepare for adding attachments --- .../eu/faircode/email/ActivityCompose.java | 2 + .../eu/faircode/email/FragmentCompose.java | 176 +++++++++++++----- .../eu/faircode/email/FragmentMessage.java | 16 +- app/src/main/res/layout/fragment_compose.xml | 34 +++- app/src/main/res/layout/fragment_message.xml | 2 +- app/src/main/res/menu/menu_compose.xml | 16 ++ .../menu/{menu_message.xml => menu_view.xml} | 4 +- app/src/main/res/values/strings.xml | 3 + 8 files changed, 191 insertions(+), 62 deletions(-) create mode 100644 app/src/main/res/menu/menu_compose.xml rename app/src/main/res/menu/{menu_message.xml => menu_view.xml} (74%) diff --git a/app/src/main/java/eu/faircode/email/ActivityCompose.java b/app/src/main/java/eu/faircode/email/ActivityCompose.java index 3cbe33e3..a597e340 100644 --- a/app/src/main/java/eu/faircode/email/ActivityCompose.java +++ b/app/src/main/java/eu/faircode/email/ActivityCompose.java @@ -28,10 +28,12 @@ import androidx.fragment.app.FragmentTransaction; public class ActivityCompose extends ActivityBase implements FragmentManager.OnBackStackChangedListener { static final int LOADER_COMPOSE_GET = 1; static final int LOADER_COMPOSE_PUT = 2; + static final int LOADER_COMPOSE_ATTACHMENT = 3; static final int REQUEST_CONTACT_TO = 1; static final int REQUEST_CONTACT_CC = 2; static final int REQUEST_CONTACT_BCC = 3; + static final int REQUEST_ATTACHMENT = 4; @Override protected void onCreate(Bundle savedInstanceState) { diff --git a/app/src/main/java/eu/faircode/email/FragmentCompose.java b/app/src/main/java/eu/faircode/email/FragmentCompose.java index 1dc6ec36..16d8a310 100644 --- a/app/src/main/java/eu/faircode/email/FragmentCompose.java +++ b/app/src/main/java/eu/faircode/email/FragmentCompose.java @@ -24,9 +24,11 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.database.Cursor; +import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.provider.ContactsContract; +import android.provider.OpenableColumns; import android.text.Html; import android.text.TextUtils; import android.util.Log; @@ -36,6 +38,7 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.webkit.MimeTypeMap; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.EditText; @@ -47,6 +50,9 @@ import android.widget.Toast; import com.google.android.material.bottomnavigation.BottomNavigationView; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -67,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.RecyclerView; import static android.app.Activity.RESULT_OK; @@ -84,10 +91,12 @@ public class FragmentCompose extends FragmentEx { private AutoCompleteTextView etBcc; private ImageView ivBccAdd; private EditText etSubject; + private RecyclerView rvAttachment; private EditText etBody; private BottomNavigationView bottom_navigation; private ProgressBar pbWait; - private Group grpCc; + private Group grpAddresses; + private Group grpAttachments; private Group grpReady; @Override @@ -112,10 +121,12 @@ public class FragmentCompose extends FragmentEx { etBcc = view.findViewById(R.id.etBcc); ivBccAdd = view.findViewById(R.id.ivBccAdd); etSubject = view.findViewById(R.id.etSubject); + rvAttachment = view.findViewById(R.id.rvAttachment); etBody = view.findViewById(R.id.etBody); bottom_navigation = view.findViewById(R.id.bottom_navigation); pbWait = view.findViewById(R.id.pbWait); - grpCc = view.findViewById(R.id.grpCc); + grpAddresses = view.findViewById(R.id.grpAddresses); + grpAttachments = view.findViewById(R.id.grpAttachments); grpReady = view.findViewById(R.id.grpReady); // Wire controls @@ -183,7 +194,8 @@ public class FragmentCompose extends FragmentEx { // Initialize spFrom.setVisibility(View.GONE); ivIdentityAdd.setVisibility(View.GONE); - grpCc.setVisibility(View.GONE); + grpAddresses.setVisibility(View.GONE); + grpAttachments.setVisibility(View.GONE); grpReady.setVisibility(View.GONE); pbWait.setVisibility(View.VISIBLE); bottom_navigation.getMenu().setGroupEnabled(0, false); @@ -276,69 +288,135 @@ public class FragmentCompose extends FragmentEx { @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - inflater.inflate(R.menu.menu_message, menu); + inflater.inflate(R.menu.menu_compose, menu); super.onCreateOptionsMenu(menu, inflater); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { - case R.id.menu_address: - onMenuCc(); + case R.id.menu_attachment: + onMenuAttachment(); + return true; + case R.id.menu_addresses: + onMenuAddresses(); return true; default: return super.onOptionsItemSelected(item); } } - private void onMenuCc() { - grpCc.setVisibility(grpCc.getVisibility() == View.GONE ? View.VISIBLE : View.GONE); + private void onMenuAttachment() { + Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.setType("*/*"); + startActivityForResult(intent, ActivityCompose.REQUEST_ATTACHMENT); + } + + private void onMenuAddresses() { + grpAddresses.setVisibility(grpAddresses.getVisibility() == View.GONE ? View.VISIBLE : View.GONE); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == RESULT_OK) { - 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()); + 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(); + } + + return null; + } + + @Override + public void onLoaded(Bundle args, Result result) { + EntityAttachment attachment = (EntityAttachment) result.data; + } + }.load(this, ActivityCompose.LOADER_COMPOSE_ATTACHMENT, args); + } + } else { + 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(); } - } 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(); } } } @@ -465,7 +543,7 @@ public class FragmentCompose extends FragmentEx { String action = result.getString("action"); pbWait.setVisibility(View.GONE); - grpCc.setVisibility("reply_all".equals(action) ? View.VISIBLE : View.GONE); + grpAddresses.setVisibility("reply_all".equals(action) ? View.VISIBLE : View.GONE); grpReady.setVisibility(View.VISIBLE); FragmentCompose.this.thread = thread; diff --git a/app/src/main/java/eu/faircode/email/FragmentMessage.java b/app/src/main/java/eu/faircode/email/FragmentMessage.java index a15c3d02..574713b7 100644 --- a/app/src/main/java/eu/faircode/email/FragmentMessage.java +++ b/app/src/main/java/eu/faircode/email/FragmentMessage.java @@ -82,7 +82,7 @@ public class FragmentMessage extends FragmentEx { private TextView tvBody; private BottomNavigationView bottom_navigation; private ProgressBar pbWait; - private Group grpAddress; + private Group grpAddresses; private Group grpAttachments; private Group grpReady; @@ -114,7 +114,7 @@ public class FragmentMessage extends FragmentEx { tvBody = view.findViewById(R.id.tvBody); bottom_navigation = view.findViewById(R.id.bottom_navigation); pbWait = view.findViewById(R.id.pbWait); - grpAddress = view.findViewById(R.id.grpAddress); + grpAddresses = view.findViewById(R.id.grpAddresses); grpAttachments = view.findViewById(R.id.grpAttachments); grpReady = view.findViewById(R.id.grpReady); @@ -216,7 +216,7 @@ public class FragmentMessage extends FragmentEx { }); // Initialize - grpAddress.setVisibility(View.GONE); + grpAddresses.setVisibility(View.GONE); grpAttachments.setVisibility(View.GONE); top_navigation.setVisibility(View.GONE); bottom_navigation.setVisibility(View.GONE); @@ -350,24 +350,24 @@ public class FragmentMessage extends FragmentEx { @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - inflater.inflate(R.menu.menu_message, menu); + inflater.inflate(R.menu.menu_view, menu); super.onCreateOptionsMenu(menu, inflater); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { - case R.id.menu_address: - onMenuAddress(); + case R.id.menu_addresses: + onMenuAddresses(); return true; default: return super.onOptionsItemSelected(item); } } - private void onMenuAddress() { + private void onMenuAddresses() { if (grpReady.getVisibility() == View.VISIBLE) - grpAddress.setVisibility(grpAddress.getVisibility() == View.GONE ? View.VISIBLE : View.GONE); + grpAddresses.setVisibility(grpAddresses.getVisibility() == View.GONE ? View.VISIBLE : View.GONE); } private void onActionThread(long id) { diff --git a/app/src/main/res/layout/fragment_compose.xml b/app/src/main/res/layout/fragment_compose.xml index 71894b66..a5fb993b 100644 --- a/app/src/main/res/layout/fragment_compose.xml +++ b/app/src/main/res/layout/fragment_compose.xml @@ -113,6 +113,30 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/etBcc" /> + + + + + app:layout_constraintTop_toBottomOf="@+id/rvAttachment" /> + + diff --git a/app/src/main/res/menu/menu_compose.xml b/app/src/main/res/menu/menu_compose.xml new file mode 100644 index 00000000..93526243 --- /dev/null +++ b/app/src/main/res/menu/menu_compose.xml @@ -0,0 +1,16 @@ + + + + + + + diff --git a/app/src/main/res/menu/menu_message.xml b/app/src/main/res/menu/menu_view.xml similarity index 74% rename from app/src/main/res/menu/menu_message.xml rename to app/src/main/res/menu/menu_view.xml index 82f8f786..c1714cb8 100644 --- a/app/src/main/res/menu/menu_message.xml +++ b/app/src/main/res/menu/menu_view.xml @@ -3,8 +3,8 @@ xmlns:app="http://schemas.android.com/apk/res-auto"> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 307c8a77..81df3faf 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -136,6 +136,9 @@ Save Send + Show CC/BCC + Add attachment + Sender missing Recipient missing Draft trashed