diff --git a/app/src/main/java/eu/faircode/email/FragmentCompose.java b/app/src/main/java/eu/faircode/email/FragmentCompose.java index e2d974fd60..713082bd98 100644 --- a/app/src/main/java/eu/faircode/email/FragmentCompose.java +++ b/app/src/main/java/eu/faircode/email/FragmentCompose.java @@ -79,6 +79,7 @@ import android.widget.EditText; import android.widget.FilterQueryProvider; import android.widget.ImageButton; import android.widget.ImageView; +import android.widget.ListView; import android.widget.MultiAutoCompleteTextView; import android.widget.Spinner; import android.widget.TextView; @@ -86,6 +87,7 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; import androidx.constraintlayout.widget.Group; import androidx.cursoradapter.widget.SimpleCursorAdapter; import androidx.exifinterface.media.ExifInterface; @@ -752,6 +754,7 @@ public class FragmentCompose extends FragmentBase { menu.findItem(R.id.menu_image).setVisible(state == State.LOADED && !style); menu.findItem(R.id.menu_attachment).setVisible(state == State.LOADED && !style); menu.findItem(R.id.menu_clear).setVisible(state == State.LOADED); + menu.findItem(R.id.menu_contact_group).setVisible(state == State.LOADED); menu.findItem(R.id.menu_encrypt).setVisible(state == State.LOADED); menu.findItem(R.id.menu_send_after).setVisible(state == State.LOADED); @@ -759,6 +762,7 @@ public class FragmentCompose extends FragmentBase { menu.findItem(R.id.menu_image).setEnabled(!busy); menu.findItem(R.id.menu_attachment).setEnabled(!busy); menu.findItem(R.id.menu_clear).setEnabled(!busy); + menu.findItem(R.id.menu_contact_group).setEnabled(!busy); menu.findItem(R.id.menu_encrypt).setEnabled(!busy); menu.findItem(R.id.menu_send_after).setEnabled(!busy); @@ -794,6 +798,9 @@ public class FragmentCompose extends FragmentBase { case R.id.menu_clear: onMenuStyle(item.getItemId()); return true; + case R.id.menu_contact_group: + onMenuContactGroup(); + return true; case R.id.menu_encrypt: onMenuEncrypt(); return true; @@ -943,6 +950,148 @@ public class FragmentCompose extends FragmentBase { etBody.setSelection(end); } + private void onMenuContactGroup() { + View dview = LayoutInflater.from(getContext()).inflate(R.layout.dialog_contact_group, null); + final ListView lvGroup = dview.findViewById(R.id.lvGroup); + final Spinner spTarget = dview.findViewById(R.id.spTarget); + + Cursor groups = resolver.query( + ContactsContract.Groups.CONTENT_URI, + new String[]{ + ContactsContract.Groups._ID, + ContactsContract.Groups.TITLE + }, + null, null, ContactsContract.Groups.TITLE + ); + + final SimpleCursorAdapter adapter = new SimpleCursorAdapter( + getContext(), + R.layout.spinner_item1_dropdown, + groups, + new String[]{ContactsContract.Groups.TITLE}, + new int[]{android.R.id.text1}, + 0); + + lvGroup.setAdapter(adapter); + + final AlertDialog dialog = new DialogBuilderLifecycle(getContext(), getViewLifecycleOwner()) + .setTitle(R.string.title_insert_contact_group) + .setView(dview) + .create(); + + lvGroup.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + dialog.dismiss(); + + int target = spTarget.getSelectedItemPosition(); + Cursor cursor = (Cursor) adapter.getItem(position); + long group = cursor.getLong(0); + + if (target > 0) + grpAddresses.setVisibility(View.VISIBLE); + + Bundle args = new Bundle(); + args.putLong("id", working); + args.putInt("target", target); + args.putLong("group", group); + + new SimpleTask() { + @Override + protected EntityMessage onExecute(Context context, Bundle args) throws Throwable { + long id = args.getLong("id"); + int target = args.getInt("target"); + long group = args.getLong("group"); + + List
selected = new ArrayList<>(); + + try (Cursor cursor = context.getContentResolver().query( + ContactsContract.Data.CONTENT_URI, + new String[]{ContactsContract.Data.CONTACT_ID}, + ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID + "= ?" + " AND " + + ContactsContract.CommonDataKinds.GroupMembership.MIMETYPE + "='" + + ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE + "'", + new String[]{String.valueOf(group)}, null)) { + while (cursor != null && cursor.moveToNext()) { + try (Cursor contact = resolver.query( + ContactsContract.CommonDataKinds.Email.CONTENT_URI, + new String[]{ + ContactsContract.Contacts.DISPLAY_NAME, + ContactsContract.CommonDataKinds.Email.DATA + }, + ContactsContract.Data.CONTACT_ID + " = ?", + new String[]{cursor.getString(0)}, + null)) { + if (contact != null && contact.moveToNext()) { + String name = contact.getString(0); + String email = contact.getString(1); + selected.add(new InternetAddress(email, name)); + } + } + } + } + + EntityMessage draft; + DB db = DB.getInstance(context); + + try { + db.beginTransaction(); + + draft = db.message().getMessage(id); + if (draft == null) + return null; + + Address[] address = null; + if (target == 0) + address = draft.to; + else if (target == 1) + address = draft.cc; + else if (target == 2) + address = draft.bcc; + + List
list = new ArrayList<>(); + if (address != null) + list.addAll(Arrays.asList(address)); + + list.addAll(selected); + + if (target == 0) + draft.to = list.toArray(new Address[0]); + else if (target == 1) + draft.cc = list.toArray(new Address[0]); + else if (target == 2) + draft.bcc = list.toArray(new Address[0]); + + db.message().updateMessage(draft); + + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + + return draft; + } + + @Override + protected void onExecuted(Bundle args, EntityMessage draft) { + if (draft != null) { + etTo.setText(MessageHelper.formatAddressesCompose(draft.to)); + etCc.setText(MessageHelper.formatAddressesCompose(draft.cc)); + etBcc.setText(MessageHelper.formatAddressesCompose(draft.bcc)); + } + } + + @Override + protected void onException(Bundle args, Throwable ex) { + Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex); + } + }.execute(getContext(), getViewLifecycleOwner(), args, "compose:picked"); + } + }); + + dialog.show(); + } + private void onMenuEncrypt() { encrypt = !encrypt; getActivity().invalidateOptionsMenu(); diff --git a/app/src/main/res/layout/dialog_contact_group.xml b/app/src/main/res/layout/dialog_contact_group.xml new file mode 100644 index 0000000000..5178f13d5f --- /dev/null +++ b/app/src/main/res/layout/dialog_contact_group.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_compose.xml b/app/src/main/res/menu/menu_compose.xml index 7f1bff2d9a..5c04736650 100644 --- a/app/src/main/res/menu/menu_compose.xml +++ b/app/src/main/res/menu/menu_compose.xml @@ -34,6 +34,11 @@ android:title="@string/title_style_clear" app:showAsAction="never" /> + + Style toolbar Add attachment Show CC/BCC + Insert contact group Sender missing Recipient missing @@ -698,6 +699,12 @@ 1920 + + To + Cc + Bcc + + @color/red @color/pink