diff --git a/FAQ.md b/FAQ.md index 1142fbec12..770b366536 100644 --- a/FAQ.md +++ b/FAQ.md @@ -42,7 +42,6 @@ None at this moment. * Calendar events: opening the attached calendar file should open the related calendar app. * Snooze timer: snoozed emails are not supported by [IMAP](https://en.wikipedia.org/wiki/Internet_Message_Access_Protocol). * Badge count: there is no standard Android API for this and third party solutions might stop working anytime. For example *ShortcutBadger* [has lots of problems](https://github.com/leolin310148/ShortcutBadger/issues). You can use the provided widget instead. -* Shortcut frequently contacted: Android [doesn't support this anymore](https://developer.android.com/guide/topics/providers/contacts-provider#ObsoleteData). * Switch language: although it is possible to change the language of an app, Android is not designed for this. Better fix the translation in your language if needed, see [this FAQ](#user-content-faq26) about how to. * Select identities to show in unified inbox: this would add complexity for something which would hardly be used. * Better design: please let me know what you have in mind [in this forum](https://forum.xda-developers.com/android/apps-games/source-email-t3824168). diff --git a/app/src/main/java/eu/faircode/email/ActivityView.java b/app/src/main/java/eu/faircode/email/ActivityView.java index 863e26e679..8abb7720fd 100644 --- a/app/src/main/java/eu/faircode/email/ActivityView.java +++ b/app/src/main/java/eu/faircode/email/ActivityView.java @@ -28,7 +28,13 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.IntentSender; import android.content.SharedPreferences; +import android.content.pm.ShortcutInfo; +import android.content.pm.ShortcutManager; import android.content.res.Configuration; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.drawable.Icon; import android.net.ConnectivityManager; import android.net.Network; import android.net.NetworkCapabilities; @@ -38,6 +44,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.ParcelFileDescriptor; import android.preference.PreferenceManager; +import android.provider.ContactsContract; import android.text.TextUtils; import android.util.Log; import android.view.LayoutInflater; @@ -86,6 +93,7 @@ import java.util.Properties; import javax.mail.Address; import javax.mail.Session; +import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import javax.net.ssl.HttpsURLConnection; @@ -336,6 +344,8 @@ public class ActivityView extends ActivityBilling implements FragmentManager.OnB pgpService = new OpenPgpServiceConnection(this, "org.sufficientlysecure.keychain"); pgpService.bindToService(); + + updateShortcuts(); } private Runnable checkIntent = new Runnable() { @@ -702,6 +712,78 @@ public class ActivityView extends ActivityBilling implements FragmentManager.OnB }.load(this, new Bundle()); } + private void updateShortcuts() { + if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.N_MR1) + return; + + ShortcutManager sm = (ShortcutManager) getSystemService(Context.SHORTCUT_SERVICE); + + Cursor cursor = null; + List shortcuts = new ArrayList<>(); + try { + cursor = getContentResolver().query( + ContactsContract.CommonDataKinds.Email.CONTENT_URI, + new String[]{ + ContactsContract.RawContacts._ID, + ContactsContract.Contacts.LOOKUP_KEY, + ContactsContract.Contacts.DISPLAY_NAME, + ContactsContract.CommonDataKinds.Email.DATA, + ContactsContract.Contacts.TIMES_CONTACTED, + ContactsContract.Contacts.LAST_TIME_CONTACTED + }, + ContactsContract.CommonDataKinds.Email.DATA + " <> ''", + null, + ContactsContract.Contacts.STARRED + " DESC" + + ", " + ContactsContract.Contacts.TIMES_CONTACTED + " DESC" + + ", " + ContactsContract.Contacts.LAST_TIME_CONTACTED + " DESC"); + while (cursor.moveToNext()) + try { + int times = cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts.TIMES_CONTACTED)); + long last = cursor.getLong(cursor.getColumnIndex(ContactsContract.Contacts.LAST_TIME_CONTACTED)); + if (times == 0 && last == 0) + continue; + + long id = cursor.getLong(cursor.getColumnIndex(ContactsContract.RawContacts._ID)); + String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); + String email = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA)); + InternetAddress address = new InternetAddress(email, name); + Log.i(Helper.TAG, "Shortcut id=" + id + " address=" + address + " times=" + times + " last=" + last); + + Uri uri = ContactsContract.Contacts.getLookupUri( + cursor.getLong(cursor.getColumnIndex(ContactsContract.RawContacts._ID)), + cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY))); + InputStream is = ContactsContract.Contacts.openContactPhotoInputStream( + getContentResolver(), uri); + Bitmap bitmap = BitmapFactory.decodeStream(is); + Icon icon = (bitmap == null + ? Icon.createWithResource(this, R.drawable.ic_shortcut_email) + : Icon.createWithBitmap(bitmap)); + + Intent intent = new Intent(this, ActivityCompose.class); + intent.setAction(Intent.ACTION_SEND); + intent.setData(Uri.parse("mailto:" + address)); + + shortcuts.add( + new ShortcutInfo.Builder(this, Long.toString(id)) + .setIcon(icon) + .setRank(shortcuts.size() + 1) + .setShortLabel(name) + .setIntent(intent) + .build()); + + if (sm.getManifestShortcuts().size() + shortcuts.size() >= sm.getMaxShortcutCountPerActivity()) + break; + } catch (Throwable ex) { + Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex)); + } + } finally { + if (cursor != null) + cursor.close(); + } + + sm.setDynamicShortcuts(shortcuts); + } + private Intent getIntentFAQ() { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("https://github.com/M66B/open-source-email/blob/master/FAQ.md")); diff --git a/app/src/main/res/drawable-hdpi/ic_shortcut_email.png b/app/src/main/res/drawable-hdpi/ic_shortcut_email.png new file mode 100644 index 0000000000..3cfd0dee17 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_shortcut_email.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_shortcut_email.png b/app/src/main/res/drawable-mdpi/ic_shortcut_email.png new file mode 100644 index 0000000000..ae6e417906 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_shortcut_email.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_shortcut_email.png b/app/src/main/res/drawable-xhdpi/ic_shortcut_email.png new file mode 100644 index 0000000000..2f136342e6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_shortcut_email.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_shortcut_email.png b/app/src/main/res/drawable-xxhdpi/ic_shortcut_email.png new file mode 100644 index 0000000000..879e60027a Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_shortcut_email.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_shortcut_email.png b/app/src/main/res/drawable-xxxhdpi/ic_shortcut_email.png new file mode 100644 index 0000000000..b65e40e02f Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_shortcut_email.png differ