diff --git a/app/src/main/java/eu/faircode/email/AdapterContact.java b/app/src/main/java/eu/faircode/email/AdapterContact.java index 3f205415c3..12d7933abd 100644 --- a/app/src/main/java/eu/faircode/email/AdapterContact.java +++ b/app/src/main/java/eu/faircode/email/AdapterContact.java @@ -42,6 +42,8 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.appcompat.widget.PopupMenu; +import androidx.core.content.pm.ShortcutInfoCompat; +import androidx.core.content.pm.ShortcutManagerCompat; import androidx.fragment.app.Fragment; import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleObserver; @@ -235,7 +237,9 @@ public class AdapterContact extends RecyclerView.Adapter categories = new HashSet<>(Arrays.asList("eu.faircode.email.TEXT_SHARE_TARGET")); - - String id = (name == null ? email : "\"" + name + "\" <" + email + ">"); - ShortcutInfoCompat.Builder builder = new ShortcutInfoCompat.Builder(context, id) - .setIcon(icon) - .setRank(shortcuts.size() + 1) - .setShortLabel(name == null ? email : name) - .setLongLabel(name == null ? email : name) - .setCategories(categories) - .setIntent(intent); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - Person.Builder person = new Person.Builder() - .setIcon(icon) - .setName(name == null ? email : name) - .setImportant(true); - if (avatar != null) - person.setUri(avatar); - builder.setPerson(person.build()); - } - + ShortcutInfoCompat.Builder builder = getShortcut(context, email, name, avatar); + builder.setRank(shortcuts.size() + 1); shortcuts.add(builder.build()); } } @@ -149,4 +117,94 @@ class Shortcuts { } }.execute(context, owner, new Bundle(), "shortcuts:update"); } + + @NotNull + static ShortcutInfoCompat.Builder getShortcut(Context context, InternetAddress address) { + String name = address.getPersonal(); + String email = address.getAddress(); + + Uri lookupUri = null; + boolean contacts = Helper.hasPermission(context, Manifest.permission.READ_CONTACTS); + if (contacts) { + ContentResolver resolver = context.getContentResolver(); + try (Cursor cursor = resolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, + new String[]{ + ContactsContract.CommonDataKinds.Photo.CONTACT_ID, + ContactsContract.Contacts.LOOKUP_KEY, + ContactsContract.Contacts.DISPLAY_NAME + }, + ContactsContract.CommonDataKinds.Email.ADDRESS + " = ?", + new String[]{email}, null)) { + if (cursor != null && cursor.moveToNext()) { + int colContactId = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Photo.CONTACT_ID); + int colLookupKey = cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY); + int colDisplayName = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME); + + long contactId = cursor.getLong(colContactId); + String lookupKey = cursor.getString(colLookupKey); + String displayName = cursor.getString(colDisplayName); + + lookupUri = ContactsContract.Contacts.getLookupUri(contactId, lookupKey); + if (!TextUtils.isEmpty(displayName)) + name = displayName; + } + } + } + + return getShortcut(context, email, name, lookupUri); + } + + @NotNull + static ShortcutInfoCompat.Builder getShortcut(Context context, EntityContact contact) { + return getShortcut(context, contact.email, contact.name, contact.avatar); + } + + @NotNull + private static ShortcutInfoCompat.Builder getShortcut(Context context, String email, String name, String avatar) { + return getShortcut(context, email, name, avatar == null ? null : Uri.parse(avatar)); + } + + @NotNull + private static ShortcutInfoCompat.Builder getShortcut(Context context, String email, String name, Uri avatar) { + Intent intent = new Intent(context, ActivityMain.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + intent.setAction(Intent.ACTION_SEND); + intent.addCategory(Intent.CATEGORY_DEFAULT); + intent.setData(Uri.parse("mailto:" + email)); + + IconCompat icon = null; + if (avatar != null && + Helper.hasPermission(context, Manifest.permission.READ_CONTACTS)) { + // Create icon from bitmap because launcher might not have contacts permission + InputStream is = ContactsContract.Contacts.openContactPhotoInputStream( + context.getContentResolver(), avatar); + Bitmap bitmap = BitmapFactory.decodeStream(is); + if (bitmap != null) + icon = IconCompat.createWithBitmap(bitmap); + } + if (icon == null) + icon = IconCompat.createWithResource(context, R.drawable.ic_shortcut_email); + + Set categories = new HashSet<>(Arrays.asList("eu.faircode.email.TEXT_SHARE_TARGET")); + + String id = (name == null ? email : "\"" + name + "\" <" + email + ">"); + ShortcutInfoCompat.Builder builder = new ShortcutInfoCompat.Builder(context, id) + .setIcon(icon) + .setShortLabel(name == null ? email : name) + .setLongLabel(name == null ? email : name) + .setCategories(categories) + .setIntent(intent); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + Person.Builder person = new Person.Builder() + .setIcon(icon) + .setName(name == null ? email : name) + .setImportant(true); + if (avatar != null) + person.setUri(avatar.toString()); + builder.setPerson(person.build()); + } + + return builder; + } } diff --git a/app/src/main/res/drawable/baseline_person_pin_circle_24.xml b/app/src/main/res/drawable/baseline_person_pin_circle_24.xml new file mode 100644 index 0000000000..89102055e7 --- /dev/null +++ b/app/src/main/res/drawable/baseline_person_pin_circle_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/include_message_addresses.xml b/app/src/main/res/layout/include_message_addresses.xml index 446e5500af..58df02e8d5 100644 --- a/app/src/main/res/layout/include_message_addresses.xml +++ b/app/src/main/res/layout/include_message_addresses.xml @@ -75,10 +75,22 @@ android:background="?android:attr/selectableItemBackgroundBorderless" android:contentDescription="@string/title_legend_notify" android:tooltipText="@string/title_legend_notify" - app:layout_constraintEnd_toStartOf="@+id/ibAddContact" + app:layout_constraintEnd_toStartOf="@+id/ibPinContact" app:layout_constraintTop_toBottomOf="@id/ibExpanderAddress" app:srcCompat="@drawable/baseline_notifications_24" /> + + + app:constraint_referenced_ids="ibSearchContact,ibNotifyContact,ibPinContact,ibAddContact" /> Edit as new Create rule … Share + Add shortcut Print Show headers Save raw message