QuickContactActivity.java revision a0f20f77e1b4f6cde5934d8b3348d93b58fd6362
1edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann/* 2edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Copyright (C) 2009 The Android Open Source Project 3edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * 4edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Licensed under the Apache License, Version 2.0 (the "License"); 5edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * you may not use this file except in compliance with the License. 6edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * You may obtain a copy of the License at 7edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * 8edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * http://www.apache.org/licenses/LICENSE-2.0 9edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * 10edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Unless required by applicable law or agreed to in writing, software 11edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * distributed under the License is distributed on an "AS IS" BASIS, 12edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * See the License for the specific language governing permissions and 14edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * limitations under the License. 15edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 16edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 17edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannpackage com.android.contacts.quickcontact; 18edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 198477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwellimport android.animation.Animator; 208477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwellimport android.animation.Animator.AnimatorListener; 218477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwellimport android.animation.AnimatorListenerAdapter; 228a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwellimport android.animation.ArgbEvaluator; 23b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport android.animation.ObjectAnimator; 24edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.app.Activity; 25d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport android.app.Fragment; 26cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmannimport android.app.LoaderManager.LoaderCallbacks; 27752cccf954bd6070c5fb623875314951c8e9849dBrian Attwellimport android.content.ActivityNotFoundException; 28edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.content.ContentUris; 29edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.content.Intent; 30cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmannimport android.content.Loader; 31edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.content.pm.PackageManager; 3231b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.graphics.Bitmap; 338a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwellimport android.graphics.Color; 347b0b0ce616c6c2fa149918c112128388712f5657Paul Soulosimport android.graphics.ColorFilter; 3531b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.graphics.drawable.BitmapDrawable; 368a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwellimport android.graphics.drawable.ColorDrawable; 3731b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.graphics.drawable.Drawable; 3823889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulosimport android.graphics.PorterDuff; 3923889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulosimport android.graphics.PorterDuffColorFilter; 40edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.net.Uri; 4131b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.os.AsyncTask; 42edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.os.Bundle; 438a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwellimport android.os.Trace; 44752cccf954bd6070c5fb623875314951c8e9849dBrian Attwellimport android.provider.ContactsContract; 45edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Email; 46edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Phone; 47edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.SipAddress; 48edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 49edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Website; 50752cccf954bd6070c5fb623875314951c8e9849dBrian Attwellimport android.provider.ContactsContract.Contacts; 51edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.QuickContact; 52edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.RawContacts; 5331b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.support.v7.graphics.Palette; 54edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.text.TextUtils; 55edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.util.Log; 56d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport android.view.Menu; 57d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport android.view.MenuItem; 58d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport android.view.MenuInflater; 59edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.view.View; 60edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.view.View.OnClickListener; 6110d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawaimport android.view.WindowManager; 62edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.widget.ImageView; 63edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.widget.Toast; 64d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport android.widget.Toolbar; 65edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 6672b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chenimport com.android.contacts.ContactSaveService; 67d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport com.android.contacts.ContactsActivity; 68e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.R; 69d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport com.android.contacts.common.editor.SelectAccountDialogFragment; 7031b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport com.android.contacts.common.lettertiles.LetterTileDrawable; 71752cccf954bd6070c5fb623875314951c8e9849dBrian Attwellimport com.android.contacts.common.list.ShortcutIntentBuilder; 72752cccf954bd6070c5fb623875314951c8e9849dBrian Attwellimport com.android.contacts.common.list.ShortcutIntentBuilder.OnShortcutIntentCreatedListener; 730d5588da244d0992c3ff8f25d0875fdf95a8c644Chiao Chengimport com.android.contacts.common.model.AccountTypeManager; 74cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.Contact; 75cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.ContactLoader; 76cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.RawContact; 77428f008513d1591cc08fcfe2cf0c9237fb313241Chiao Chengimport com.android.contacts.common.model.account.AccountType; 78d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport com.android.contacts.common.model.account.AccountWithDataSet; 79cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.dataitem.DataItem; 80428f008513d1591cc08fcfe2cf0c9237fb313241Chiao Chengimport com.android.contacts.common.model.dataitem.DataKind; 81cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.dataitem.EmailDataItem; 82cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.dataitem.ImDataItem; 83b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport com.android.contacts.common.model.dataitem.PhoneDataItem; 84cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.util.DataStatus; 85d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport com.android.contacts.detail.ContactDetailDisplayUtils; 86899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulosimport com.android.contacts.interactions.CalendarInteractionsLoader; 87ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulosimport com.android.contacts.interactions.CallLogInteractionsLoader; 888a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwellimport com.android.contacts.interactions.ContactDeletionInteraction; 89b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport com.android.contacts.interactions.ContactInteraction; 90b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport com.android.contacts.interactions.SmsInteractionsLoader; 912d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport com.android.contacts.quickcontact.ExpandingEntryCardView.Entry; 92e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwellimport com.android.contacts.quickcontact.ExpandingEntryCardView.ExpandingEntryCardViewListener; 93e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.util.ImageViewDrawableSetter; 94b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport com.android.contacts.util.SchedulingUtils; 95b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport com.android.contacts.widget.MultiShrinkScroller; 96b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport com.android.contacts.widget.MultiShrinkScroller.MultiShrinkScrollerListener; 97e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.google.common.base.Preconditions; 98e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.google.common.collect.Lists; 99e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng 1002d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport java.util.ArrayList; 101899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulosimport java.util.Arrays; 102b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport java.util.Collections; 103b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport java.util.Comparator; 104edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport java.util.HashMap; 105edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport java.util.HashSet; 106edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport java.util.List; 107b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport java.util.Map; 108edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport java.util.Set; 109edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 110edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann/** 111edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Mostly translucent {@link Activity} that shows QuickContact dialog. It loads 112edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * data asynchronously, and then shows a popup with details centered around 113edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * {@link Intent#getSourceBounds()}. 114edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 115d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellpublic class QuickContactActivity extends ContactsActivity { 1168a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 1178a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell /** 1188a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell * QuickContacts immediately takes up the full screen. All possible information is shown. 1198a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell * This value for {@link android.provider.ContactsContract.QuickContact#EXTRA_MODE} 1208a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell * should only be used by the Contacts app. 1218a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell */ 1228a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell public static final int MODE_FULLY_EXPANDED = 4; 1238a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 124edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private static final String TAG = "QuickContact"; 125edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 1269b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell private static final String KEY_THEME_COLOR = "theme_color"; 1279b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell 1288a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private static final int ANIMATION_SLIDE_OPEN_DURATION = 250; 1299b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell private static final int ANIMATION_STATUS_BAR_COLOR_CHANGE_DURATION = 150; 1308a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private static final int REQUEST_CODE_CONTACT_EDITOR_ACTIVITY = 1; 1318a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private static final float SYSTEM_BAR_BRIGHTNESS_FACTOR = 0.7f; 1329b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell private static final int SCRIM_COLOR = Color.argb(0xB2, 0, 0, 0); 133dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 134752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell /** This is the Intent action to install a shortcut in the launcher. */ 135752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell private static final String ACTION_INSTALL_SHORTCUT = 136752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell "com.android.launcher.action.INSTALL_SHORTCUT"; 137edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 138edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann @SuppressWarnings("deprecation") 139edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private static final String LEGACY_AUTHORITY = android.provider.Contacts.AUTHORITY; 140edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 141edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private Uri mLookupUri; 142edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private String[] mExcludeMimes; 1438a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private int mExtraMode; 1448a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private int mStatusBarColor; 1458a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private boolean mHasAlreadyBeenOpened; 146edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 1476219668d0612f7522bd15a9d34c6232cb15b9a6cYorke Lee private ImageView mPhotoView; 1480d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell private View mTransparentView; 1492d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private ExpandingEntryCardView mCommunicationCard; 150b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private ExpandingEntryCardView mRecentCard; 151b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell private MultiShrinkScroller mScroller; 152d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private SelectAccountDialogFragmentListener mSelectAccountFragmentListener; 1538a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private AsyncTask<Void, Void, Void> mEntriesAndActionsTask; 1549b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell private ColorDrawable mWindowScrim; 1558477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell private boolean mIsWaitingForOtherPieceOfExitAnimation; 1568477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell private boolean mIsExitAnimationInProgress; 1578571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell private boolean mHasComputedThemeColor; 158edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 159b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private static final int MIN_NUM_COMMUNICATION_ENTRIES_SHOWN = 3; 160b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private static final int MIN_NUM_COLLAPSED_RECENT_ENTRIES_SHOWN = 3; 161b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1626cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee private Contact mContactData; 1639815d7f98baf80ce51b0cf1f01f48a3dbb9a9db9Daniel Lehmann private ContactLoader mContactLoader; 1649b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell private PorterDuffColorFilter mColorFilter; 1659815d7f98baf80ce51b0cf1f01f48a3dbb9a9db9Daniel Lehmann 1669758a92fac3e9f64892d893c992f6020d7fe3bfdJosh Gargus private final ImageViewDrawableSetter mPhotoSetter = new ImageViewDrawableSetter(); 1679758a92fac3e9f64892d893c992f6020d7fe3bfdJosh Gargus 168edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann /** 169edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Keeps the default action per mimetype. Empty if no default actions are set 170edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 171edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private HashMap<String, Action> mDefaultsMap = new HashMap<String, Action>(); 172edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 173edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann /** 174edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * {@link #LEADING_MIMETYPES} and {@link #TRAILING_MIMETYPES} are used to sort MIME-types. 175edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * 176edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * <p>The MIME-types in {@link #LEADING_MIMETYPES} appear in the front of the dialog, 177edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * in the order specified here.</p> 178edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * 179edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * <p>The ones in {@link #TRAILING_MIMETYPES} appear in the end of the dialog, in the order 180edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * specified here.</p> 181edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * 182edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * <p>The rest go between them, in the order in the array.</p> 183edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 184edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private static final List<String> LEADING_MIMETYPES = Lists.newArrayList( 185edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann Phone.CONTENT_ITEM_TYPE, SipAddress.CONTENT_ITEM_TYPE, Email.CONTENT_ITEM_TYPE); 186edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 187edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann /** See {@link #LEADING_MIMETYPES}. */ 188edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private static final List<String> TRAILING_MIMETYPES = Lists.newArrayList( 189edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann StructuredPostal.CONTENT_ITEM_TYPE, Website.CONTENT_ITEM_TYPE); 190edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 191b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos /** Id for the background contact loader */ 192b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private static final int LOADER_CONTACT_ID = 0; 193b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 194ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos private static final String KEY_LOADER_EXTRA_PHONES = 195ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos QuickContactActivity.class.getCanonicalName() + ".KEY_LOADER_EXTRA_PHONES"; 196ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 197b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos /** Id for the background Sms Loader */ 198b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private static final int LOADER_SMS_ID = 1; 199b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private static final int MAX_SMS_RETRIEVE = 3; 200ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 201ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos /** Id for the back Calendar Loader */ 202899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos private static final int LOADER_CALENDAR_ID = 2; 203ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos private static final String KEY_LOADER_EXTRA_EMAILS = 204ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos QuickContactActivity.class.getCanonicalName() + ".KEY_LOADER_EXTRA_EMAILS"; 205899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos private static final int MAX_PAST_CALENDAR_RETRIEVE = 3; 206899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos private static final int MAX_FUTURE_CALENDAR_RETRIEVE = 3; 207899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos private static final long PAST_MILLISECOND_TO_SEARCH_LOCAL_CALENDAR = 208899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos 180L * 24L * 60L * 60L * 1000L /* 180 days */; 209899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos private static final long FUTURE_MILLISECOND_TO_SEARCH_LOCAL_CALENDAR = 210899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos 36L * 60L * 60L * 1000L /* 36 hours */; 211899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos 212ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos /** Id for the background Call Log Loader */ 213ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos private static final int LOADER_CALL_LOG_ID = 3; 214ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos private static final int MAX_CALL_LOG_RETRIEVE = 3; 215ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 216ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 217ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos private static final int[] mRecentLoaderIds = new int[]{ 218ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos LOADER_SMS_ID, 219ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos LOADER_CALENDAR_ID, 220ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos LOADER_CALL_LOG_ID}; 221b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private Map<Integer, List<ContactInteraction>> mRecentLoaderResults; 222b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 223d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private static final String FRAGMENT_TAG_SELECT_ACCOUNT = "select_account_fragment"; 2246cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee 2252d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos final OnClickListener mEntryClickHandler = new OnClickListener() { 2262d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos @Override 2272d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos public void onClick(View v) { 2282d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos Log.i(TAG, "mEntryClickHandler onClick"); 2292d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos Object intent = v.getTag(); 2302d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos if (intent == null || !(intent instanceof Intent)) { 2312d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos return; 2322d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 2332d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos startActivity((Intent) intent); 2342d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 2352d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos }; 2362d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 237e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell final ExpandingEntryCardViewListener mExpandingEntryCardViewListener 238e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell = new ExpandingEntryCardViewListener() { 239e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell @Override 240e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell public void onCollapse(int heightDelta) { 241e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell mScroller.prepareForShrinkingScrollChild(heightDelta); 242e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell } 243e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell }; 244e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell 245d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell /** 246d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell * Headless fragment used to handle account selection callbacks invoked from 247d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell * {@link DirectoryContactUtil}. 248d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell */ 249d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public static class SelectAccountDialogFragmentListener extends Fragment 250d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell implements SelectAccountDialogFragment.Listener { 251d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 252d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private QuickContactActivity mQuickContactActivity; 253d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 254d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public SelectAccountDialogFragmentListener() {} 255d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 256d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell @Override 257d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public void onAccountChosen(AccountWithDataSet account, Bundle extraArgs) { 258d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell DirectoryContactUtil.createCopy(mQuickContactActivity.mContactData.getContentValues(), 259d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell account, mQuickContactActivity); 260d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 261d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 262d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell @Override 263d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public void onAccountSelectorCancelled() {} 264d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 265d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell /** 266d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell * Set the parent activity. Since rotation can cause this fragment to be used across 267d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell * more than one activity instance, we need to explicitly set this value instead 268d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell * of making this class non-static. 269d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell */ 270d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public void setQuickContactActivity(QuickContactActivity quickContactActivity) { 271d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mQuickContactActivity = quickContactActivity; 272d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 273d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 274d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 275b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell final MultiShrinkScrollerListener mMultiShrinkScrollerListener 276b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell = new MultiShrinkScrollerListener() { 277b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell @Override 278b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell public void onScrolledOffBottom() { 2798477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell if (!mIsWaitingForOtherPieceOfExitAnimation) { 2808477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell finish(); 2818477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell return; 2828477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell } 2838477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell mIsWaitingForOtherPieceOfExitAnimation = false; 284b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 2858a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 2868a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 2878a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell public void onEnterFullscreen() { 2888a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell updateStatusBarColor(); 2898a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 2908a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 2918a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 2928a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell public void onExitFullscreen() { 2938a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell updateStatusBarColor(); 2948a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 2958477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell 2968477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell @Override 2978477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell public void onStartScrollOffBottom() { 2988477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell // Remove the window shim now that we are starting an Activity exit animation. 2998477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell final int duration = getResources().getInteger(android.R.integer.config_shortAnimTime); 3009b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell final ObjectAnimator animator = ObjectAnimator.ofInt(mWindowScrim, "alpha", 0xFF, 0); 3018477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell animator.addListener(mExitWindowShimAnimationListener); 3028477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell animator.setDuration(duration).start(); 3038477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell mIsWaitingForOtherPieceOfExitAnimation = true; 3048477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell mIsExitAnimationInProgress = true; 3058477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell } 3068477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell }; 3078477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell 3088477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell final AnimatorListener mExitWindowShimAnimationListener = new AnimatorListenerAdapter() { 3098477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell @Override 3108477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell public void onAnimationEnd(Animator animation) { 3118477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell if (!mIsWaitingForOtherPieceOfExitAnimation) { 3128477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell finish(); 3138477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell return; 3148477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell } 3158477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell mIsWaitingForOtherPieceOfExitAnimation = false; 3168477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell } 317b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell }; 318b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell 319edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann @Override 3208a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell protected void onCreate(Bundle savedInstanceState) { 3218a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.beginSection("onCreate()"); 3228a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell super.onCreate(savedInstanceState); 323edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 3248a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell getWindow().setStatusBarColor(Color.TRANSPARENT); 3258a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // Since we can't disable Window animations from the Launcher, we can minimize the 3268a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // silliness of the animation by setting the navigation bar transparent. 3278a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell getWindow().setNavigationBarColor(Color.TRANSPARENT); 3282426cb015ba4cb679a525bd1ffe223527375468cDaniel Lehmann 329d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell processIntent(getIntent()); 330dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 33110d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa // Show QuickContact in front of soft input 33210d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, 33310d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); 33410d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa 335edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann setContentView(R.layout.quickcontact_activity); 336edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 3372d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mCommunicationCard = (ExpandingEntryCardView) findViewById(R.id.communication_card); 338b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos mRecentCard = (ExpandingEntryCardView) findViewById(R.id.recent_card); 339b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell mScroller = (MultiShrinkScroller) findViewById(R.id.multiscroller); 340edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 3412d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mCommunicationCard.setOnClickListener(mEntryClickHandler); 342b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos mCommunicationCard.setTitle(getResources().getString(R.string.communication_card_title)); 34323889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos mCommunicationCard.setExpandButtonText( 34423889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos getResources().getString(R.string.expanding_entry_card_view_see_all)); 345b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 346b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos mRecentCard.setOnClickListener(mEntryClickHandler); 347b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos mRecentCard.setTitle(getResources().getString(R.string.recent_card_title)); 348edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 349d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mPhotoView = (ImageView) findViewById(R.id.photo); 3500d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell mTransparentView = findViewById(R.id.transparent_view); 3510d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell if (mScroller != null) { 3520d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell mTransparentView.setOnClickListener(new OnClickListener() { 3530d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell @Override 3540d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell public void onClick(View v) { 3550d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell mScroller.scrollOffBottom(); 3560d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell } 3570d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell }); 3580d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell } 359edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 360d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 361d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell setActionBar(toolbar); 3629b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell getActionBar().setTitle(null); 3639b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell // Put a TextView with a known resource id into the ActionBar. This allows us to easily 3649b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell // find the correct TextView location & size later. 3659b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell toolbar.addView(getLayoutInflater().inflate(R.layout.quickcontact_title_placeholder, null)); 3666219668d0612f7522bd15a9d34c6232cb15b9a6cYorke Lee 3678a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mHasAlreadyBeenOpened = savedInstanceState != null; 3688a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 3699b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell mWindowScrim = new ColorDrawable(SCRIM_COLOR); 3709b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell getWindow().setBackgroundDrawable(mWindowScrim); 3718a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (!mHasAlreadyBeenOpened) { 3728a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell final int duration = getResources().getInteger(android.R.integer.config_shortAnimTime); 3739b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell ObjectAnimator.ofInt(mWindowScrim, "alpha", 0, 0xFF).setDuration(duration).start(); 3748a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 375edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 376ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell mScroller.initialize(mMultiShrinkScrollerListener); 377ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // mScroller needs to perform asynchronous measurements after initalize(), therefore 378ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // we can't mark this as GONE. 379ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell mScroller.setVisibility(View.INVISIBLE); 3808a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 3819b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell setHeaderNameText(R.string.missing_name); 3829b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell 383d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mSelectAccountFragmentListener= (SelectAccountDialogFragmentListener) getFragmentManager() 384d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell .findFragmentByTag(FRAGMENT_TAG_SELECT_ACCOUNT); 385d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (mSelectAccountFragmentListener == null) { 386d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mSelectAccountFragmentListener = new SelectAccountDialogFragmentListener(); 387d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell getFragmentManager().beginTransaction().add(0, mSelectAccountFragmentListener, 388d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell FRAGMENT_TAG_SELECT_ACCOUNT).commit(); 389d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mSelectAccountFragmentListener.setRetainInstance(true); 390d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 391d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mSelectAccountFragmentListener.setQuickContactActivity(this); 39223889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos 3939b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell if (savedInstanceState != null) { 3949b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell final int color = savedInstanceState.getInt(KEY_THEME_COLOR, 0); 395ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell SchedulingUtils.doOnPreDraw(mScroller, /* drawNextFrame = */ false, 396ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell new Runnable() { 397ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell @Override 398ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell public void run() { 399ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // Need to wait for the pre draw before setting the initial scroll 400ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // value. Prior to pre draw all scroll values are invalid. 401ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell if (mHasAlreadyBeenOpened) { 402ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell mScroller.setVisibility(View.VISIBLE); 403ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell mScroller.setScroll(mScroller.getScrollNeededToBeFullScreen()); 404ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell } 405ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // Need to wait for pre draw for setting the theme color. Setting the 406ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // header tint before the MultiShrinkScroller has been measured will 407ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // cause incorrect tinting calculations. 408ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell if (color != 0) { 4099b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell setThemeColor(color); 4109b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 411ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell } 412ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell }); 4139b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 4149b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell 4158a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.endSection(); 4168a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 4178a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 4188a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell protected void onActivityResult(int requestCode, int resultCode, 4198a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Intent data) { 4208a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (requestCode == REQUEST_CODE_CONTACT_EDITOR_ACTIVITY && 4218a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell resultCode == ContactDeletionInteraction.RESULT_CODE_DELETED) { 4228a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // The contact that we were showing has been deleted. 4238a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell finish(); 424b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 4258a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 426dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 4278a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 4288a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell protected void onNewIntent(Intent intent) { 4298a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell super.onNewIntent(intent); 4308a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mHasAlreadyBeenOpened = true; 4318571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell mHasComputedThemeColor = false; 432d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell processIntent(intent); 433d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 434d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 4359b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell @Override 4369b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell public void onSaveInstanceState(Bundle savedInstanceState) { 4379b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell super.onSaveInstanceState(savedInstanceState); 4389b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell if (mColorFilter != null) { 4399b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell savedInstanceState.putInt(KEY_THEME_COLOR, mColorFilter.getColor()); 4409b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 4419b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 4429b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell 443d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private void processIntent(Intent intent) { 444d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell Uri lookupUri = intent.getData(); 445d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 446d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // Check to see whether it comes from the old version. 447d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (lookupUri != null && LEGACY_AUTHORITY.equals(lookupUri.getAuthority())) { 448d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell final long rawContactId = ContentUris.parseId(lookupUri); 449d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell lookupUri = RawContacts.getContactLookupUri(getContentResolver(), 450d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId)); 451d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 452d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mExtraMode = getIntent().getIntExtra(QuickContact.EXTRA_MODE, 453d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell QuickContact.MODE_LARGE); 454d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell final Uri oldLookupUri = mLookupUri; 455d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 456d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mLookupUri = Preconditions.checkNotNull(lookupUri, "missing lookupUri"); 457d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mExcludeMimes = intent.getStringArrayExtra(QuickContact.EXTRA_EXCLUDE_MIMES); 458d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (oldLookupUri == null) { 459d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mContactLoader = (ContactLoader) getLoaderManager().initLoader( 460d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell LOADER_CONTACT_ID, null, mLoaderContactCallbacks); 461d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } else if (oldLookupUri != mLookupUri) { 462d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // After copying a directory contact, the contact URI changes. Therefore, 463d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // we need to restart the loader and reload the new contact. 464d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mContactLoader = (ContactLoader) getLoaderManager().restartLoader( 465d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell LOADER_CONTACT_ID, null, mLoaderContactCallbacks); 466899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos for (int interactionLoaderId : mRecentLoaderIds) { 467899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos getLoaderManager().destroyLoader(interactionLoaderId); 468899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos } 469d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 4702426cb015ba4cb679a525bd1ffe223527375468cDaniel Lehmann } 471edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 472b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell private void runEntranceAnimation() { 4738a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (mHasAlreadyBeenOpened) { 4748a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell return; 4758a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 4768a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mHasAlreadyBeenOpened = true; 477b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell final int bottomScroll = mScroller.getScrollUntilOffBottom() - 1; 478b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell final ObjectAnimator scrollAnimation 4798a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell = ObjectAnimator.ofInt(mScroller, "scroll", -bottomScroll, 4808a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mExtraMode != MODE_FULLY_EXPANDED ? 0 : mScroller.getScrollNeededToBeFullScreen()); 4818a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell scrollAnimation.setDuration(ANIMATION_SLIDE_OPEN_DURATION); 482b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell scrollAnimation.start(); 483b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 484b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell 48581281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan /** Assign this string to the view if it is not empty. */ 486d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private void setHeaderNameText(int resId) { 4879b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell if (mScroller != null) { 488f43f573340fd9de5d30b43d7c96cac1ec9021e58Brian Attwell mScroller.setTitle(getText(resId) == null ? null : getText(resId).toString()); 4899b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 49081281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan } 49181281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan 49281281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan /** Assign this string to the view if it is not empty. */ 493f43f573340fd9de5d30b43d7c96cac1ec9021e58Brian Attwell private void setHeaderNameText(String value) { 494d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (!TextUtils.isEmpty(value)) { 4959b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell if (mScroller != null) { 496f43f573340fd9de5d30b43d7c96cac1ec9021e58Brian Attwell mScroller.setTitle(value); 4979b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 49881281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan } 49981281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan } 50081281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan 50181281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan /** 502edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Check if the given MIME-type appears in the list of excluded MIME-types 503edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * that the most-recent caller requested. 504edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 505edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private boolean isMimeExcluded(String mimeType) { 506edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann if (mExcludeMimes == null) return false; 507edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann for (String excludedMime : mExcludeMimes) { 508edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann if (TextUtils.equals(excludedMime, mimeType)) { 509edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann return true; 510edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 511edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 512edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann return false; 513edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 514edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 515edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann /** 516cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann * Handle the result from the ContactLoader 517edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 5188a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private void bindContactData(final Contact data) { 5198a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.beginSection("bindContactData"); 5206cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee mContactData = data; 521d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell invalidateOptionsMenu(); 522edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 523edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann mDefaultsMap.clear(); 524edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 5258a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.endSection(); 5268a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.beginSection("Set display photo & name"); 527dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 5286219668d0612f7522bd15a9d34c6232cb15b9a6cYorke Lee mPhotoSetter.setupContactPhoto(data, mPhotoView); 52931b2d42fb0889e61515d27314aa5a245147100daBrian Attwell extractAndApplyTintFromPhotoViewAsynchronously(); 5304936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell analyzeWhitenessOfPhotoAsynchronously(); 531d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell setHeaderNameText(data.getDisplayName()); 532edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 5338a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.endSection(); 534dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 535b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos // Maintain a list of phone numbers to pass into SmsInteractionsLoader 536899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos final Set<String> phoneNumbers = new HashSet<>(); 537899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos // Maintain a list of email addresses to pass into CalendarInteractionsLoader 538899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos final Set<String> emailAddresses = new HashSet<>(); 5398a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // List of Entry that makes up the ExpandingEntryCardView 5408a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell final List<Entry> entries = Lists.newArrayList(); 5418a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 5428a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mEntriesAndActionsTask = new AsyncTask<Void, Void, Void>() { 5438a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 5448a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell protected Void doInBackground(Void... params) { 54516339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos computeEntriesAndActions(data, phoneNumbers, emailAddresses, entries); 5468a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell return null; 5478a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 5488a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 5498a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 5508a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell protected void onPostExecute(Void aVoid) { 5518a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell super.onPostExecute(aVoid); 5528a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // Check that original AsyncTask parameters are still valid and the activity 5538a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // is still running before binding to UI. A new intent could invalidate 5548a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // the results, for example. 5558a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (data == mContactData && !isCancelled()) { 55616339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos bindEntriesAndActions(entries, phoneNumbers, emailAddresses); 5578a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell showActivity(); 5588a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 5598a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 5608a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell }; 5618a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mEntriesAndActionsTask.execute(); 5628a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 5638a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 5648a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private void bindEntriesAndActions(List<Entry> entries, 565899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos Set<String> phoneNumbers, 56616339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos Set<String> emailAddresses) { 5678a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.beginSection("start sms loader"); 568ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos final Bundle phonesExtraBundle = new Bundle(); 569ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos phonesExtraBundle.putStringArray(KEY_LOADER_EXTRA_PHONES, 5708a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell phoneNumbers.toArray(new String[phoneNumbers.size()])); 5718a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell getLoaderManager().initLoader( 5728a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell LOADER_SMS_ID, 573ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos phonesExtraBundle, 574ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos mLoaderInteractionsCallbacks); 575ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos Trace.endSection(); 576ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 577ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos Trace.beginSection("start call log loader"); 578ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos getLoaderManager().initLoader( 579ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos LOADER_CALL_LOG_ID, 580ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos phonesExtraBundle, 5818a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mLoaderInteractionsCallbacks); 582899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos Trace.endSection(); 5838a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 584899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos Trace.beginSection("start calendar loader"); 585ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos final Bundle emailsExtraBundle = new Bundle(); 586ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos emailsExtraBundle.putStringArray(KEY_LOADER_EXTRA_EMAILS, 587899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos emailAddresses.toArray(new String[emailAddresses.size()])); 588899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos getLoaderManager().initLoader( 589899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos LOADER_CALENDAR_ID, 590ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos emailsExtraBundle, 591899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos mLoaderInteractionsCallbacks); 5928a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.endSection(); 5938a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 594899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos Trace.beginSection("bind communicate card"); 5958a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (entries.size() > 0) { 5968a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mCommunicationCard.initialize(entries, 5978a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell /* numInitialVisibleEntries = */ MIN_NUM_COMMUNICATION_ENTRIES_SHOWN, 598e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell /* isExpanded = */ false, mExpandingEntryCardViewListener); 5998a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 6008a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 60116339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos final boolean hasData = !entries.isEmpty(); 602d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mCommunicationCard.setVisibility(hasData ? View.VISIBLE : View.GONE); 6038a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 6048a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.endSection(); 6058a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 6068a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 6078a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private void showActivity() { 6088a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (mScroller != null) { 6098a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mScroller.setVisibility(View.VISIBLE); 6108a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell SchedulingUtils.doOnPreDraw(mScroller, /* drawNextFrame = */ false, 6118a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell new Runnable() { 6128a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 6138a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell public void run() { 6148a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell runEntranceAnimation(); 6158a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 6168a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell }); 6178a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 6188a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 6198a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 620899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos private void computeEntriesAndActions(Contact data, Set<String> phoneNumbers, 62116339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos Set<String> emailAddresses, List<Entry> entries) { 6228a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.beginSection("inflate entries and actions"); 6238a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 6248bf96e78497ea9c8c893bcb357fc1e3175fb2e9bBrian Attwell // Map from {@link String} MIME-type to a list of {@link Action}. 6258bf96e78497ea9c8c893bcb357fc1e3175fb2e9bBrian Attwell final ActionMultiMap actions = new ActionMultiMap(); 6268bf96e78497ea9c8c893bcb357fc1e3175fb2e9bBrian Attwell 6278a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell final ResolveCache cache = ResolveCache.getInstance(this); 628851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu for (RawContact rawContact : data.getRawContacts()) { 629851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu for (DataItem dataItem : rawContact.getDataItems()) { 630851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final String mimeType = dataItem.getMimeType(); 63147b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng final AccountType accountType = rawContact.getAccountType(this); 63247b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng final DataKind dataKind = AccountTypeManager.getInstance(this) 63347b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng .getKindOrFallback(accountType, mimeType); 634cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 635b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos if (dataItem instanceof PhoneDataItem) { 636b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos phoneNumbers.add(((PhoneDataItem) dataItem).getNormalizedNumber()); 637b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 638b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 639899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos if (dataItem instanceof EmailDataItem) { 640899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos emailAddresses.add(((EmailDataItem) dataItem).getAddress()); 641899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos } 642899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos 643cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann // Skip this data item if MIME-type excluded 644cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann if (isMimeExcluded(mimeType)) continue; 645cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 646851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final long dataId = dataItem.getId(); 647851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final boolean isPrimary = dataItem.isPrimary(); 648851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final boolean isSuperPrimary = dataItem.isSuperPrimary(); 649cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 65047b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng if (dataKind != null) { 651cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann // Build an action for this data entry, find a mapping to a UI 652cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann // element, build its summary from the cursor, and collect it 653cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann // along with all others of this MIME-type. 6548a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell final Action action = new DataAction(getApplicationContext(), 6558a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell dataItem, dataKind); 6568bf96e78497ea9c8c893bcb357fc1e3175fb2e9bBrian Attwell final boolean wasAdded = considerAdd(action, cache, isSuperPrimary, actions); 657cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann if (wasAdded) { 658cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann // Remember the default 659cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann if (isSuperPrimary || (isPrimary && (mDefaultsMap.get(mimeType) == null))) { 660cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann mDefaultsMap.put(mimeType, action); 661edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 662edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 663edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 664edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 665cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann // Handle Email rows with presence data as Im entry 6669daca14706f3699c9e9d46dfb522132fc566e57eDaniel Lehmann final DataStatus status = data.getStatuses().get(dataId); 667851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu if (status != null && dataItem instanceof EmailDataItem) { 668851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final EmailDataItem email = (EmailDataItem) dataItem; 669851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final ImDataItem im = ImDataItem.createFromEmail(email); 67047b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng if (dataKind != null) { 6718a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell final DataAction action = new DataAction(getApplicationContext(), 6728a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell im, dataKind); 6739daca14706f3699c9e9d46dfb522132fc566e57eDaniel Lehmann action.setPresence(status.getPresence()); 6748bf96e78497ea9c8c893bcb357fc1e3175fb2e9bBrian Attwell considerAdd(action, cache, isSuperPrimary, actions); 675cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 676edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 677edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 678edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 679edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 6808a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.endSection(); 6818a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.beginSection("collapsing action list"); 682dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 6838a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.endSection(); 6848a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.beginSection("sort mimetypes"); 685edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 68616339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos /* 68716339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos * Sorting is a multi part step. The end result is to a have a sorted list of the most 68816339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos * used actions, one per mimetype. Then, within each mimetype, the list of actions for that 68916339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos * type is also sorted, based off of {super primary, primary, times used} in that order. 69016339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos */ 69116339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos final List<Action> topActions = new ArrayList<>(); 69228a239eb826c14f3c49ac64e4e08014ee2096b2fPaul Soulos final List<Action> allActions = new ArrayList<>(); 6938bf96e78497ea9c8c893bcb357fc1e3175fb2e9bBrian Attwell for (List<Action> mimeTypeActions : actions.values()) { 69416339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos Collections.sort(mimeTypeActions, new Comparator<Action>() { 69516339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos @Override 69616339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos public int compare(Action lhs, Action rhs) { 69716339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos /* 69816339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos * Actions are compared to the same mimetype based off of three qualities: 69916339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos * 1. Super primary 70016339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos * 2. Primary 70116339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos * 3. Times used 70216339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos */ 70316339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos if (lhs.isSuperPrimary()) { 70416339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos return -1; 70516339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos } else if (rhs.isSuperPrimary()) { 70616339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos return 1; 70716339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos } else if (lhs.isPrimary() && !rhs.isPrimary()) { 70816339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos return -1; 70916339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos } else if (!lhs.isPrimary() && rhs.isPrimary()) { 71016339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos return 1; 71116339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos } else { 71216339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos int lhsTimesUsed = lhs.getTimesUsed() == null ? 0 : lhs.getTimesUsed(); 71316339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos int rhsTimesUsed = rhs.getTimesUsed() == null ? 0 : rhs.getTimesUsed(); 71416339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos 71516339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos return rhsTimesUsed - lhsTimesUsed; 71616339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos } 71716339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos } 71816339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos }); 71916339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos topActions.add(mimeTypeActions.get(0)); 72028a239eb826c14f3c49ac64e4e08014ee2096b2fPaul Soulos // Add all the other actions and remove the top one 72128a239eb826c14f3c49ac64e4e08014ee2096b2fPaul Soulos allActions.addAll(mimeTypeActions); 72228a239eb826c14f3c49ac64e4e08014ee2096b2fPaul Soulos allActions.remove(mimeTypeActions.get(0)); 723edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 724edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 72516339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos // topActions now contains the top action for each mimetype. This list now needs to be 72616339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos // sorted, based off of {times used, last used, statically defined} in that order. 72716339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos Collections.sort(topActions, new Comparator<Action>() { 72816339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos @Override 72916339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos public int compare(Action lhs, Action rhs) { 73016339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos int lhsTimesUsed = lhs.getTimesUsed() == null ? 0 : lhs.getTimesUsed(); 73116339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos int rhsTimesUsed = rhs.getTimesUsed() == null ? 0 : rhs.getTimesUsed(); 73216339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos int timesUsedDifference = rhsTimesUsed - lhsTimesUsed; 73316339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos if (timesUsedDifference != 0) { 73416339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos return timesUsedDifference; 73516339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos } 73616339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos 73716339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos long lhsLastTimeUsed = lhs.getLastTimeUsed() == null ? 0 : lhs.getLastTimeUsed(); 73816339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos long rhsLastTimeUsed = rhs.getLastTimeUsed() == null ? 0 : rhs.getLastTimeUsed(); 73916339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos long lastTimeUsedDifference = rhsLastTimeUsed - lhsLastTimeUsed; 74016339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos if (lastTimeUsedDifference > 0) { 74116339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos return 1; 74216339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos } else if (lastTimeUsedDifference < 0) { 74316339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos return -1; 74416339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos } 745edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 74616339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos // Times used and last time used are the same. Resort to statically defined. 74716339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos String lhsMimeType = lhs.getMimeType(); 74816339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos String rhsMimeType = rhs.getMimeType(); 74916339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos for (String mimeType : LEADING_MIMETYPES) { 75016339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos if (lhsMimeType.equals(mimeType)) { 75116339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos return -1; 75216339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos } else if (rhsMimeType.equals(mimeType)) { 75316339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos return 1; 75416339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos } 75516339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos } 75616339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos // Trailing types come last, so flip the returns 75716339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos for (String mimeType : TRAILING_MIMETYPES) { 75816339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos if (lhsMimeType.equals(mimeType)) { 75916339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos return 1; 76016339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos } else if (rhsMimeType.equals(mimeType)) { 76116339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos return -1; 76216339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos } 76316339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos } 76416339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos return 0; 765edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 76616339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos }); 767b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 76816339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos entries.addAll(actionsToEntries(topActions)); 76928a239eb826c14f3c49ac64e4e08014ee2096b2fPaul Soulos entries.addAll(actionsToEntries(allActions)); 7708a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.endSection(); 771edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 772edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 773edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann /** 77431b2d42fb0889e61515d27314aa5a245147100daBrian Attwell * Asynchronously extract the most vibrant color from the PhotoView. Once extracted, 77531b2d42fb0889e61515d27314aa5a245147100daBrian Attwell * apply this tint to {@link MultiShrinkScroller}. This operation takes about 20-30ms 77631b2d42fb0889e61515d27314aa5a245147100daBrian Attwell * on a Nexus 5. 77731b2d42fb0889e61515d27314aa5a245147100daBrian Attwell */ 77831b2d42fb0889e61515d27314aa5a245147100daBrian Attwell private void extractAndApplyTintFromPhotoViewAsynchronously() { 77931b2d42fb0889e61515d27314aa5a245147100daBrian Attwell if (mScroller == null) { 78031b2d42fb0889e61515d27314aa5a245147100daBrian Attwell return; 78131b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 78231b2d42fb0889e61515d27314aa5a245147100daBrian Attwell final Drawable imageViewDrawable = mPhotoView.getDrawable(); 78331b2d42fb0889e61515d27314aa5a245147100daBrian Attwell new AsyncTask<Void, Void, Integer>() { 78431b2d42fb0889e61515d27314aa5a245147100daBrian Attwell @Override 78531b2d42fb0889e61515d27314aa5a245147100daBrian Attwell protected Integer doInBackground(Void... params) { 78631b2d42fb0889e61515d27314aa5a245147100daBrian Attwell if (imageViewDrawable instanceof BitmapDrawable) { 7878a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell final Bitmap bitmap = ((BitmapDrawable) imageViewDrawable).getBitmap(); 7888a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell return colorFromBitmap(bitmap); 7898a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 7908a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (imageViewDrawable instanceof LetterTileDrawable) { 7919b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell return ((LetterTileDrawable) imageViewDrawable).getColor(); 79231b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 7938a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell return 0; 79431b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 79531b2d42fb0889e61515d27314aa5a245147100daBrian Attwell 79631b2d42fb0889e61515d27314aa5a245147100daBrian Attwell @Override 79731b2d42fb0889e61515d27314aa5a245147100daBrian Attwell protected void onPostExecute(Integer color) { 79831b2d42fb0889e61515d27314aa5a245147100daBrian Attwell super.onPostExecute(color); 7998571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell if (mHasComputedThemeColor) { 8008571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // If we had previously computed a theme color from the contact photo, 8018571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // then do not update the theme color. Changing the theme color several 8028571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // seconds after QC has started, as a result of an updated/upgraded photo, 8038571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // is a jarring experience. On the other hand, changing the theme color after 8048571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // a rotation or onNewIntent() is perfectly fine. 8058571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell return; 8068571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell } 8078571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // Check that the Photo has not changed. If it has changed, the new tint 8088571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // color needs to be extracted 8098571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell if (imageViewDrawable == mPhotoView.getDrawable()) { 8108571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell mHasComputedThemeColor = true; 8119b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell setThemeColor(color); 81231b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 81331b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 81431b2d42fb0889e61515d27314aa5a245147100daBrian Attwell }.execute(); 81531b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 81631b2d42fb0889e61515d27314aa5a245147100daBrian Attwell 8174936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell /** 8184936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell * Examine how many white pixels are in the bitmap in order to determine whether or not 8194936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell * we need gradient overlays on top of the image. 8204936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell */ 8214936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell private void analyzeWhitenessOfPhotoAsynchronously() { 8224936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell final Drawable imageViewDrawable = mPhotoView.getDrawable(); 8234936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell new AsyncTask<Void, Void, Boolean>() { 8244936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell @Override 8254936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell protected Boolean doInBackground(Void... params) { 8264936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell if (imageViewDrawable instanceof BitmapDrawable) { 8274936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell final Bitmap bitmap = ((BitmapDrawable) imageViewDrawable).getBitmap(); 8284936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell return WhitenessUtils.isBitmapWhiteAtTopOrBottom(bitmap); 8294936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell } 8304936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell return !(imageViewDrawable instanceof LetterTileDrawable); 8314936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell } 8324936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell 8334936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell @Override 8344936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell protected void onPostExecute(Boolean isWhite) { 8354936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell super.onPostExecute(isWhite); 8364936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell mScroller.setUseGradient(isWhite); 8374936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell } 8384936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell }.execute(); 8394936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell } 8404936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell 8419b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell private void setThemeColor(int color) { 8429b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell // If the color is invalid, use the predefined default 8439b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell if (color == 0) { 8449b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell color = getResources().getColor(R.color.actionbar_background_color); 8459b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 8469b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell mScroller.setHeaderTintColor(color); 8479b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell 8489b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell // Create a darker version of the actionbar color. HSV is device dependent 8499b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell // and not perceptually-linear. Therefore, we can't say mStatusBarColor is 8509b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell // 70% as bright as the action bar color. We can only say: it is a bit darker. 8519b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell final float hsvComponents[] = new float[3]; 8529b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell Color.colorToHSV(color, hsvComponents); 8539b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell hsvComponents[2] *= SYSTEM_BAR_BRIGHTNESS_FACTOR; 8549b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell mStatusBarColor = Color.HSVToColor(hsvComponents); 8559b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell updateStatusBarColor(); 8568571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell 8579b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell mColorFilter = 8589b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP); 8599b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell mCommunicationCard.setColorAndFilter(color, mColorFilter); 8609b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell mRecentCard.setColorAndFilter(color, mColorFilter); 8619b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 8629b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell 8638a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private void updateStatusBarColor() { 8648a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (mScroller == null) { 8658a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell return; 8668a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 8678a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell final int desiredStatusBarColor; 8688a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // Only use a custom status bar color if QuickContacts touches the top of the viewport. 8698a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (mScroller.getScrollNeededToBeFullScreen() <= 0) { 8708a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell desiredStatusBarColor = mStatusBarColor; 8718a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } else { 8728a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell desiredStatusBarColor = Color.TRANSPARENT; 8738a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 8748a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // Animate to the new color. 8758a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (desiredStatusBarColor != getWindow().getStatusBarColor()) { 8768a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell final ObjectAnimator animation = ObjectAnimator.ofInt(getWindow(), "statusBarColor", 8778a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell getWindow().getStatusBarColor(), desiredStatusBarColor); 8788a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell animation.setDuration(ANIMATION_STATUS_BAR_COLOR_CHANGE_DURATION); 8798a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell animation.setEvaluator(new ArgbEvaluator()); 8808a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell animation.start(); 8818a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 8828a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 8838a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 8848a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private int colorFromBitmap(Bitmap bitmap) { 8858a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // Author of Palette recommends using 24 colors when analyzing profile photos. 8868a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell final int NUMBER_OF_PALETTE_COLORS = 24; 8878a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell final Palette palette = Palette.generate(bitmap, NUMBER_OF_PALETTE_COLORS); 888a0f20f77e1b4f6cde5934d8b3348d93b58fd6362Brian Attwell if (palette != null && palette.getVibrantSwatch() != null) { 889a0f20f77e1b4f6cde5934d8b3348d93b58fd6362Brian Attwell return palette.getVibrantSwatch().getRgb(); 8908a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 8918a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell return 0; 8928a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 8938a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 89431b2d42fb0889e61515d27314aa5a245147100daBrian Attwell /** 895edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Consider adding the given {@link Action}, which will only happen if 896edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * {@link PackageManager} finds an application to handle 897edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * {@link Action#getIntent()}. 8988a0dd0f08ab11e9c6dad386e4411aeeb4c0cd73fMaurice Chu * @param action the action to handle 8998a0dd0f08ab11e9c6dad386e4411aeeb4c0cd73fMaurice Chu * @param resolveCache cache of applications that can handle actions 9008a0dd0f08ab11e9c6dad386e4411aeeb4c0cd73fMaurice Chu * @param front indicates whether to add the action to the front of the list 9018bf96e78497ea9c8c893bcb357fc1e3175fb2e9bBrian Attwell * @param actions where to put the action. 902edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * @return true if action has been added 903edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 9048bf96e78497ea9c8c893bcb357fc1e3175fb2e9bBrian Attwell private boolean considerAdd(Action action, ResolveCache resolveCache, boolean front, 9058bf96e78497ea9c8c893bcb357fc1e3175fb2e9bBrian Attwell ActionMultiMap actions) { 906edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann if (resolveCache.hasResolve(action)) { 9078bf96e78497ea9c8c893bcb357fc1e3175fb2e9bBrian Attwell actions.put(action.getMimeType(), action, front); 908edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann return true; 909edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 910edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann return false; 911edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 912edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 913edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann /** 9142d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * Converts a list of Action into a list of Entry 9152d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * @param actions The list of Action to convert 9162d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * @return The converted list of Entry 917edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 9182d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private List<Entry> actionsToEntries(List<Action> actions) { 9192d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos List<Entry> entries = new ArrayList<>(); 9202d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos for (Action action : actions) { 921f43f573340fd9de5d30b43d7c96cac1ec9021e58Brian Attwell final String header = action.getBody() == null ? null : action.getBody().toString(); 922f43f573340fd9de5d30b43d7c96cac1ec9021e58Brian Attwell final String footer = action.getBody() == null ? null : action.getBody().toString(); 92323889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos String body = null; 92423889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos Drawable icon = null; 92523889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos switch (action.getMimeType()) { 92623889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos case Phone.CONTENT_ITEM_TYPE: 9277b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos icon = getResources().getDrawable(R.drawable.ic_phone_24dp); 92823889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos break; 92923889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos case Email.CONTENT_ITEM_TYPE: 9307b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos icon = getResources().getDrawable(R.drawable.ic_email_24dp); 93123889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos break; 93223889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos case StructuredPostal.CONTENT_ITEM_TYPE: 9337b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos icon = getResources().getDrawable(R.drawable.ic_place_24dp); 93423889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos break; 93523889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos default: 93623889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos icon = ResolveCache.getInstance(this).getIcon(action); 93723889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos } 93823889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos entries.add(new Entry(icon, header, body, footer, action.getIntent(), 93923889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos /* isEditable= */ false)); 94023889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos 94123889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos // Add SMS in addition to phone calls 94223889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos if (action.getMimeType().equals(Phone.CONTENT_ITEM_TYPE)) { 9437b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos entries.add(new Entry(getResources().getDrawable(R.drawable.ic_message_24dp), 94423889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos getResources().getString(R.string.send_message), null, header, 94523889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos action.getAlternateIntent(), /* isEditable = */ false)); 94623889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos } 9472d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 9482d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos return entries; 949edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 950edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 951b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private List<Entry> contactInteractionsToEntries(List<ContactInteraction> interactions) { 952b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos List<Entry> entries = new ArrayList<>(); 953b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos for (ContactInteraction interaction : interactions) { 9547b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos entries.add(new Entry(interaction.getIcon(this), 955b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos interaction.getViewHeader(this), 956b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos interaction.getViewBody(this), 957b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos interaction.getBodyIcon(this), 958b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos interaction.getViewFooter(this), 959b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos interaction.getFooterIcon(this), 960b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos interaction.getIntent(), 961b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos /* isEditable = */ false)); 962b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 963b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos return entries; 964b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 965b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 966b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private LoaderCallbacks<Contact> mLoaderContactCallbacks = 967851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu new LoaderCallbacks<Contact>() { 968cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann @Override 969851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public void onLoaderReset(Loader<Contact> loader) { 970cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 971cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 972cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann @Override 973851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public void onLoadFinished(Loader<Contact> loader, Contact data) { 9748a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.beginSection("onLoadFinished()"); 9758a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 976cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann if (isFinishing()) { 977cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann return; 978cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 979cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann if (data.isError()) { 980cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann // This shouldn't ever happen, so throw an exception. The {@link ContactLoader} 981cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann // should log the actual exception. 982cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann throw new IllegalStateException("Failed to load contact", data.getException()); 983cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 984cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann if (data.isNotFound()) { 9858a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (mHasAlreadyBeenOpened) { 9868a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell finish(); 9878a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } else { 9888a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Log.i(TAG, "No contact found: " + ((ContactLoader)loader).getLookupUri()); 9898a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Toast.makeText(QuickContactActivity.this, R.string.invalidContactMessage, 9908a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Toast.LENGTH_LONG).show(); 9918a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 992cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann return; 993cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 994cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 995b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos bindContactData(data); 996cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 9978a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.endSection(); 998cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 999cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 1000cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann @Override 1001851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public Loader<Contact> onCreateLoader(int id, Bundle args) { 1002cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann if (mLookupUri == null) { 1003cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann Log.wtf(TAG, "Lookup uri wasn't initialized. Loader was started too early"); 1004cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 1005d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // Load all contact data. We need loadGroupMetaData=true to determine whether the 1006d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // contact is invisible. If it is, we need to display an "Add to Contacts" MenuItem. 1007b2b435a944947fbf1965c3bb7c202a97f0273259Yorke Lee return new ContactLoader(getApplicationContext(), mLookupUri, 1008d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell true /*loadGroupMetaData*/, false /*loadInvitableAccountTypes*/, 10098571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell true /*postViewNotification*/, true /*computeFormattedPhoneNumber*/); 1010cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 1011cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann }; 1012b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1013b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell @Override 1014b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell public void onBackPressed() { 1015b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell if (mScroller != null) { 10168477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell if (!mIsExitAnimationInProgress) { 10178477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell mScroller.scrollOffBottom(); 10188477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell } 1019b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } else { 1020b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell super.onBackPressed(); 1021b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 1022b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 1023b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 10248a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 10258a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell public void finish() { 10268a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell super.finish(); 10278a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 10288a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // override transitions to skip the standard window animations 10298a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell overridePendingTransition(0, 0); 10308a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 10318a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 1032b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private LoaderCallbacks<List<ContactInteraction>> mLoaderInteractionsCallbacks = 1033b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos new LoaderCallbacks<List<ContactInteraction>>() { 1034b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1035b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos @Override 1036b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos public Loader<List<ContactInteraction>> onCreateLoader(int id, Bundle args) { 1037b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos Log.v(TAG, "onCreateLoader"); 1038b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos Loader<List<ContactInteraction>> loader = null; 1039b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos switch (id) { 1040b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos case LOADER_SMS_ID: 1041b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos Log.v(TAG, "LOADER_SMS_ID"); 1042b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos loader = new SmsInteractionsLoader( 1043b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos QuickContactActivity.this, 1044ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos args.getStringArray(KEY_LOADER_EXTRA_PHONES), 1045b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos MAX_SMS_RETRIEVE); 1046b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos break; 1047899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos case LOADER_CALENDAR_ID: 1048899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos Log.v(TAG, "LOADER_CALENDAR_ID"); 1049899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos loader = new CalendarInteractionsLoader( 1050899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos QuickContactActivity.this, 1051ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos Arrays.asList(args.getStringArray(KEY_LOADER_EXTRA_EMAILS)), 1052899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos MAX_FUTURE_CALENDAR_RETRIEVE, 1053899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos MAX_PAST_CALENDAR_RETRIEVE, 1054899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos FUTURE_MILLISECOND_TO_SEARCH_LOCAL_CALENDAR, 1055899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos PAST_MILLISECOND_TO_SEARCH_LOCAL_CALENDAR); 1056899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos break; 1057ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos case LOADER_CALL_LOG_ID: 1058ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos Log.v(TAG, "LOADER_CALL_LOG_ID"); 1059ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos loader = new CallLogInteractionsLoader( 1060ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos QuickContactActivity.this, 1061ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos args.getStringArray(KEY_LOADER_EXTRA_PHONES), 1062ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos MAX_CALL_LOG_RETRIEVE); 1063b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 1064b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos return loader; 1065b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 1066b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1067b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos @Override 1068b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos public void onLoadFinished(Loader<List<ContactInteraction>> loader, 1069b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos List<ContactInteraction> data) { 1070b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos if (mRecentLoaderResults == null) { 1071b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos mRecentLoaderResults = new HashMap<Integer, List<ContactInteraction>>(); 1072b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 1073899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos Log.v(TAG, "onLoadFinished ~ loader.getId() " + loader.getId() + " data.size() " + 1074899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos data.size()); 1075b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos mRecentLoaderResults.put(loader.getId(), data); 1076b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1077b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos if (isAllRecentDataLoaded()) { 1078b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos bindRecentData(); 1079b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 1080b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 1081b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1082b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos @Override 1083b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos public void onLoaderReset(Loader<List<ContactInteraction>> loader) { 1084b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos mRecentLoaderResults.remove(loader.getId()); 1085b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 1086b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1087b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos }; 1088b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1089b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private boolean isAllRecentDataLoaded() { 1090b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos return mRecentLoaderResults.size() == mRecentLoaderIds.length; 1091b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 1092b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1093b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private void bindRecentData() { 1094b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos List<ContactInteraction> allInteractions = new ArrayList<>(); 1095b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos for (List<ContactInteraction> loaderInteractions : mRecentLoaderResults.values()) { 1096b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos allInteractions.addAll(loaderInteractions); 1097b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 1098b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1099b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos // Sort the interactions by most recent 1100b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos Collections.sort(allInteractions, new Comparator<ContactInteraction>() { 1101b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos @Override 1102b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos public int compare(ContactInteraction a, ContactInteraction b) { 1103b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos return a.getInteractionDate() >= b.getInteractionDate() ? -1 : 1; 1104b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 1105b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos }); 1106b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1107b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos if (allInteractions.size() > 0) { 1108b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos mRecentCard.initialize(contactInteractionsToEntries(allInteractions), 1109b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos /* numInitialVisibleEntries = */ MIN_NUM_COLLAPSED_RECENT_ENTRIES_SHOWN, 1110e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell /* isExpanded = */ false, mExpandingEntryCardViewListener); 1111b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos mRecentCard.setVisibility(View.VISIBLE); 1112b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 1113b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 11148a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 11158a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 11168a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell protected void onStop() { 11178a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell super.onStop(); 11188a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 11198a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (mEntriesAndActionsTask != null) { 11208a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // Once the activity is stopped, we will no longer want to bind mEntriesAndActionsTask's 11218a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // results on the UI thread. In some circumstances Activities are killed without 11228a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // onStop() being called. This is not a problem, because in these circumstances 11238a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // the entire process will be killed. 11248a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mEntriesAndActionsTask.cancel(/* mayInterruptIfRunning = */ false); 11258a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 11268a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 112723889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos 112823889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos /** 1129d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell * Returns true if it is possible to edit the current contact. 1130d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell */ 1131d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private boolean isContactEditable() { 1132d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell return mContactData != null && !mContactData.isDirectoryEntry(); 1133d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 1134d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 1135d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private void editContact() { 1136d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell final Intent intent = new Intent(Intent.ACTION_EDIT, mLookupUri); 1137d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mContactLoader.cacheResult(); 1138d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 1139d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell startActivityForResult(intent, REQUEST_CODE_CONTACT_EDITOR_ACTIVITY); 1140d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 1141d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 1142d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private void toggleStar(MenuItem starredMenuItem) { 1143d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // Make sure there is a contact 1144d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (mLookupUri != null) { 1145d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // Read the current starred value from the UI instead of using the last 1146d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // loaded state. This allows rapid tapping without writing the same 1147d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // value several times 1148d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell final boolean isStarred = starredMenuItem.isChecked(); 1149d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 1150d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // To improve responsiveness, swap out the picture (and tag) in the UI already 1151d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell ContactDetailDisplayUtils.configureStarredMenuItem(starredMenuItem, 1152d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mContactData.isDirectoryEntry(), mContactData.isUserProfile(), 1153d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell !isStarred); 1154d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 1155d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // Now perform the real save 1156d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell Intent intent = ContactSaveService.createSetStarredIntent( 1157d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell QuickContactActivity.this, mLookupUri, !isStarred); 1158d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell startService(intent); 1159d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 1160d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 1161d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 1162752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell /** 1163752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell * Calls into the contacts provider to get a pre-authorized version of the given URI. 1164752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell */ 1165752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell private Uri getPreAuthorizedUri(Uri uri) { 1166752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final Bundle uriBundle = new Bundle(); 1167752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell uriBundle.putParcelable(ContactsContract.Authorization.KEY_URI_TO_AUTHORIZE, uri); 1168752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final Bundle authResponse = getContentResolver().call( 1169752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell ContactsContract.AUTHORITY_URI, 1170752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell ContactsContract.Authorization.AUTHORIZATION_METHOD, 1171752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell null, 1172752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell uriBundle); 1173752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell if (authResponse != null) { 1174752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell return (Uri) authResponse.getParcelable( 1175752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell ContactsContract.Authorization.KEY_AUTHORIZED_URI); 1176752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } else { 1177752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell return uri; 1178752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 1179752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 1180752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell private void shareContact() { 1181752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final String lookupKey = mContactData.getLookupKey(); 1182752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell Uri shareUri = Uri.withAppendedPath(Contacts.CONTENT_VCARD_URI, lookupKey); 1183752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell if (mContactData.isUserProfile()) { 1184752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // User is sharing the profile. We don't want to force the receiver to have 1185752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // the highly-privileged READ_PROFILE permission, so we need to request a 1186752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // pre-authorized URI from the provider. 1187752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell shareUri = getPreAuthorizedUri(shareUri); 1188752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 1189752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 1190752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final Intent intent = new Intent(Intent.ACTION_SEND); 1191752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell intent.setType(Contacts.CONTENT_VCARD_TYPE); 1192752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell intent.putExtra(Intent.EXTRA_STREAM, shareUri); 1193752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 1194752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // Launch chooser to share contact via 1195752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final CharSequence chooseTitle = getText(R.string.share_via); 1196752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final Intent chooseIntent = Intent.createChooser(intent, chooseTitle); 1197752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 1198752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell try { 1199752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell this.startActivity(chooseIntent); 1200752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } catch (ActivityNotFoundException ex) { 1201752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell Toast.makeText(this, R.string.share_error, Toast.LENGTH_SHORT).show(); 1202752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 1203752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 1204752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 1205752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell /** 1206752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell * Creates a launcher shortcut with the current contact. 1207752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell */ 1208752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell private void createLauncherShortcutWithContact() { 1209752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final ShortcutIntentBuilder builder = new ShortcutIntentBuilder(this, 1210752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell new OnShortcutIntentCreatedListener() { 1211752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 1212752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell @Override 1213752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell public void onShortcutIntentCreated(Uri uri, Intent shortcutIntent) { 1214752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // Broadcast the shortcutIntent to the launcher to create a 1215752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // shortcut to this contact 1216752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell shortcutIntent.setAction(ACTION_INSTALL_SHORTCUT); 1217752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell QuickContactActivity.this.sendBroadcast(shortcutIntent); 1218752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 1219752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // Send a toast to give feedback to the user that a shortcut to this 1220752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // contact was added to the launcher. 1221752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell Toast.makeText(QuickContactActivity.this, 1222752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell R.string.createContactShortcutSuccessful, 1223752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell Toast.LENGTH_SHORT).show(); 1224752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 1225752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 1226752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell }); 1227752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell builder.createContactShortcutIntent(mLookupUri); 1228752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 1229752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 1230d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell @Override 1231d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public boolean onCreateOptionsMenu(Menu menu) { 1232d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell MenuInflater inflater = getMenuInflater(); 1233d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell inflater.inflate(R.menu.quickcontact, menu); 1234d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell return true; 1235d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 1236d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 1237d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell @Override 1238d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public boolean onPrepareOptionsMenu(Menu menu) { 1239d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (mContactData != null) { 1240d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell final MenuItem starredMenuItem = menu.findItem(R.id.menu_star); 1241d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell ContactDetailDisplayUtils.configureStarredMenuItem(starredMenuItem, 1242d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mContactData.isDirectoryEntry(), mContactData.isUserProfile(), 1243d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mContactData.getStarred()); 1244d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // Configure edit MenuItem 1245d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell final MenuItem editMenuItem = menu.findItem(R.id.menu_edit); 1246d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell editMenuItem.setVisible(true); 1247d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (DirectoryContactUtil.isDirectoryContact(mContactData) || InvisibleContactUtil 1248d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell .isInvisibleAndAddable(mContactData, this)) { 124930cfd121ad8c8adb83cf417ff1d40a8ba1e3761dBrian Attwell editMenuItem.setIcon(R.drawable.ic_person_add_tinted_24dp); 1250d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } else if (isContactEditable()) { 1251d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell editMenuItem.setIcon(R.drawable.ic_create_24dp); 1252d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } else { 1253d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell editMenuItem.setVisible(false); 1254d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 12558a6d0022b07640d4a1fb8b264c8822bbab2981adPaul Soulos return true; 1256d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 12578a6d0022b07640d4a1fb8b264c8822bbab2981adPaul Soulos return false; 1258d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 1259d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 1260d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell @Override 1261d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public boolean onOptionsItemSelected(MenuItem item) { 1262d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell switch (item.getItemId()) { 1263d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell case R.id.menu_star: 1264d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell toggleStar(item); 1265d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell return true; 1266d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell case R.id.menu_edit: 1267d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (DirectoryContactUtil.isDirectoryContact(mContactData)) { 1268d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell DirectoryContactUtil.addToMyContacts(mContactData, this, getFragmentManager(), 1269d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mSelectAccountFragmentListener); 1270d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } else if (InvisibleContactUtil.isInvisibleAndAddable(mContactData, this)) { 1271d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell InvisibleContactUtil.addToDefaultGroup(mContactData, this); 1272d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } else if (isContactEditable()) { 1273d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell editContact(); 1274d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 1275d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell return true; 1276752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell case R.id.menu_share: 1277752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell shareContact(); 1278752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell return true; 1279752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell case R.id.menu_create_contact_shortcut: 1280752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell createLauncherShortcutWithContact(); 1281752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell return true; 1282d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell default: 1283d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell return super.onOptionsItemSelected(item); 1284d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 128523889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos } 1286edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann} 1287