blob: c07b94ebefc5f1f207dcd5b4063fd0b3f38fccb4 [file] [log] [blame]
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -08001/*
Dmitri Plotnikovfcfdffb2010-07-15 18:00:55 -07002 * Copyright (C) 2010 The Android Open Source Project
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Dmitri Plotnikov27834b22010-07-01 14:10:08 -070017package com.android.contacts.activities;
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080018
Chiao Chenge0b2f1e2012-06-12 13:07:56 -070019import android.app.Fragment;
20import android.app.FragmentManager;
21import android.app.FragmentTransaction;
Jay Shraunerd391f842014-11-26 11:14:24 -080022import android.content.ActivityNotFoundException;
Brian Attwell20510ec2015-02-27 16:10:45 -080023import android.content.ContentUris;
Brian Attwell73a67642014-12-18 20:40:58 -080024import android.content.Context;
Chiao Chenge0b2f1e2012-06-12 13:07:56 -070025import android.content.Intent;
Wenyi Wang2f09e602015-10-28 11:34:23 -070026import android.content.pm.PackageManager;
27import android.content.pm.ResolveInfo;
Chiao Chenge0b2f1e2012-06-12 13:07:56 -070028import android.graphics.Rect;
29import android.net.Uri;
Wenyi Wang1fc3ef42016-01-14 18:21:40 -080030import android.os.Build;
Chiao Chenge0b2f1e2012-06-12 13:07:56 -070031import android.os.Bundle;
Chiao Chenge0b2f1e2012-06-12 13:07:56 -070032import android.os.Parcelable;
Chiao Cheng9f0a1c72013-04-19 10:57:26 -070033import android.os.UserManager;
Chiao Chenge0b2f1e2012-06-12 13:07:56 -070034import android.preference.PreferenceActivity;
35import android.provider.ContactsContract;
36import android.provider.ContactsContract.Contacts;
37import android.provider.ContactsContract.ProviderStatus;
Ricky Waied5202a2015-11-17 18:06:33 +000038import android.provider.ContactsContract.QuickContact;
Chiao Chenge0b2f1e2012-06-12 13:07:56 -070039import android.provider.Settings;
40import android.support.v13.app.FragmentPagerAdapter;
41import android.support.v4.view.PagerAdapter;
42import android.support.v4.view.ViewPager;
Wenyi Wange7fd1ad2016-01-06 14:12:10 -080043import android.support.v7.widget.Toolbar;
Fabrice Di Meglio7d3b9152013-04-04 19:49:34 -070044import android.text.TextUtils;
Chiao Chenge0b2f1e2012-06-12 13:07:56 -070045import android.util.Log;
46import android.view.KeyCharacterMap;
47import android.view.KeyEvent;
48import android.view.Menu;
49import android.view.MenuInflater;
50import android.view.MenuItem;
Chiao Chenge0b2f1e2012-06-12 13:07:56 -070051import android.view.View;
52import android.view.ViewGroup;
Paul Soulos2b9563d2014-05-27 16:21:23 -070053import android.widget.ImageButton;
Jay Shraunerd391f842014-11-26 11:14:24 -080054import android.widget.Toast;
Chiao Chenge0b2f1e2012-06-12 13:07:56 -070055
Wenyi Wange7fd1ad2016-01-06 14:12:10 -080056import com.android.contacts.AppCompatContactsActivity;
Dmitri Plotnikov27834b22010-07-01 14:10:08 -070057import com.android.contacts.R;
Makoto Onuki4d788fc2011-07-12 10:00:10 -070058import com.android.contacts.activities.ActionBarAdapter.TabState;
Yorke Leecd321f62013-10-28 15:20:15 -070059import com.android.contacts.common.ContactsUtils;
Brian Attwellbdd32642015-05-08 17:03:15 -070060import com.android.contacts.common.activity.RequestPermissionsActivity;
Chiao Chengc8dd78c2012-10-31 15:31:33 -070061import com.android.contacts.common.dialog.ClearFrequentsDialog;
Chiao Cheng051f41d2012-12-04 15:42:42 -080062import com.android.contacts.common.interactions.ImportExportDialogFragment;
Chiao Cheng821a6572012-12-04 17:42:52 -080063import com.android.contacts.common.list.ContactEntryListFragment;
Chiao Chenga0233a02012-11-01 16:41:08 -070064import com.android.contacts.common.list.ContactListFilter;
Chiao Cheng0d5588d2012-11-26 15:34:14 -080065import com.android.contacts.common.list.ContactListFilterController;
Chiao Chenge776d032012-11-05 16:28:36 -080066import com.android.contacts.common.list.ContactTileAdapter.DisplayType;
Chiao Chenga0233a02012-11-01 16:41:08 -070067import com.android.contacts.common.list.DirectoryListLoader;
Brian Attwell3c763b32014-07-21 14:25:28 -070068import com.android.contacts.common.list.ViewPagerTabs;
Walter Janga84fe612016-01-13 16:49:04 -080069import com.android.contacts.common.logging.Logger;
70import com.android.contacts.common.logging.ScreenEvent;
Wenyi Wang86f2a862015-12-30 16:54:51 -080071import com.android.contacts.common.preference.ContactsPreferenceActivity;
guanxiongliuf597ec62016-01-25 19:49:42 -080072import com.android.contacts.common.preference.DisplayOptionsPreferenceFragment;
Chiao Cheng30868d42012-11-28 17:45:57 -080073import com.android.contacts.common.util.AccountFilterUtil;
guanxiongliuf597ec62016-01-25 19:49:42 -080074import com.android.contacts.common.util.Constants;
guanxiongliu5d7bb262016-01-29 16:43:45 -080075import com.android.contacts.common.util.ImplicitIntentsUtil;
Paul Soulos2b9563d2014-05-27 16:21:23 -070076import com.android.contacts.common.util.ViewUtil;
guanxiongliu5d7bb262016-01-29 16:43:45 -080077import com.android.contacts.common.widget.FloatingActionButtonController;
guanxiongliuf597ec62016-01-25 19:49:42 -080078import com.android.contacts.editor.EditorIntents;
79import com.android.contacts.interactions.ContactDeletionInteraction;
80import com.android.contacts.interactions.ContactMultiDeletionInteraction;
81import com.android.contacts.interactions.ContactMultiDeletionInteraction.MultiContactDeleteListener;
82import com.android.contacts.interactions.JoinContactsDialogFragment;
83import com.android.contacts.interactions.JoinContactsDialogFragment.JoinContactsListener;
84import com.android.contacts.list.ContactTileListFragment;
85import com.android.contacts.list.ContactsIntentResolver;
86import com.android.contacts.list.ContactsRequest;
87import com.android.contacts.list.ContactsUnavailableFragment;
88import com.android.contacts.list.MultiSelectContactsListFragment;
89import com.android.contacts.list.MultiSelectContactsListFragment.OnCheckBoxListActionListener;
90import com.android.contacts.list.OnContactBrowserActionListener;
91import com.android.contacts.list.OnContactsUnavailableActionListener;
92import com.android.contacts.list.ProviderStatusWatcher;
93import com.android.contacts.list.ProviderStatusWatcher.ProviderStatusListener;
Brian Attwell8a6f4ad2014-06-06 21:54:53 -070094import com.android.contacts.quickcontact.QuickContactActivity;
Daniel Lehmann3391dbe2010-07-12 09:50:22 -070095import com.android.contacts.util.DialogManager;
guanxiongliuf597ec62016-01-25 19:49:42 -080096import com.android.contacts.util.PhoneCapabilityTester;
Brian Attwell56bcc2f2015-02-12 23:45:27 +000097import com.android.contactsbind.HelpUtils;
Tadashi G. Takaoka57cf30f2009-09-21 19:54:39 +090098
Brian Attwell20510ec2015-02-27 16:10:45 -080099import java.util.List;
Fabrice Di Meglio7d3b9152013-04-04 19:49:34 -0700100import java.util.Locale;
Makoto Onuki6d9befe2011-07-17 11:00:12 -0700101import java.util.concurrent.atomic.AtomicInteger;
Dmitri Plotnikovcaf0bc72010-09-03 15:16:21 -0700102
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800103/**
Brian Attwell2c1bfd02014-06-04 18:18:35 -0700104 * Displays a list to browse contacts.
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800105 */
Wenyi Wange7fd1ad2016-01-06 14:12:10 -0800106public class PeopleActivity extends AppCompatContactsActivity implements
Paul Soulos2b9563d2014-05-27 16:21:23 -0700107 View.OnCreateContextMenuListener,
108 View.OnClickListener,
109 ActionBarAdapter.Listener,
Dmitri Plotnikov6e850a02010-10-28 10:46:21 -0700110 DialogManager.DialogShowingViewActivity,
Paul Soulos2b9563d2014-05-27 16:21:23 -0700111 ContactListFilterController.ContactListFilterListener,
Brian Attwelld2962a32015-03-02 14:48:50 -0800112 ProviderStatusListener,
Brian Attwelld3946ca2015-03-03 11:13:49 -0800113 MultiContactDeleteListener,
114 JoinContactsListener {
Dmitri Plotnikov57d27da2009-09-28 18:06:11 -0700115
Dave Santoro5e684a42011-06-10 13:23:35 -0700116 private static final String TAG = "PeopleActivity";
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800117
Makoto Onuki9ae60412012-07-19 15:56:41 -0700118 private static final String ENABLE_DEBUG_OPTIONS_HIDDEN_CODE = "debug debug!";
119
Katherine Kuan5c3a0a12011-11-07 15:43:04 -0800120 // These values needs to start at 2. See {@link ContactEntryListFragment}.
Brian Attwell2c1bfd02014-06-04 18:18:35 -0700121 private static final int SUBACTIVITY_ACCOUNT_FILTER = 2;
Katherine Kuanc6b8afe2011-06-22 19:03:50 -0700122
Daisuke Miyakawa34b901c2011-10-18 14:33:41 -0700123 private final DialogManager mDialogManager = new DialogManager(this);
Daniel Lehmann3391dbe2010-07-12 09:50:22 -0700124
Dmitri Plotnikovac0f7832010-04-22 13:26:52 -0700125 private ContactsIntentResolver mIntentResolver;
Dmitri Plotnikovfcfdffb2010-07-15 18:00:55 -0700126 private ContactsRequest mRequest;
127
Dmitri Plotnikovfcfdffb2010-07-15 18:00:55 -0700128 private ActionBarAdapter mActionBarAdapter;
Brian Attwell865847b2015-04-20 14:40:17 -0700129 private FloatingActionButtonController mFloatingActionButtonController;
130 private View mFloatingActionButtonContainer;
131 private boolean wasLastFabAnimationScaleIn = false;
Dmitri Plotnikovfcfdffb2010-07-15 18:00:55 -0700132
Frank Sposaro7979ea22011-07-14 16:46:07 -0700133 private ContactTileListFragment.Listener mFavoritesFragmentListener =
Daisuke Miyakawaee179472011-06-25 11:23:01 -0700134 new StrequentContactListFragmentListener();
135
Dmitri Plotnikov15ccbb42010-10-05 17:29:07 -0700136 private ContactListFilterController mContactListFilterController;
Dmitri Plotnikov3c69e212010-09-27 11:43:39 -0700137
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800138 private ContactsUnavailableFragment mContactsUnavailableFragment;
Makoto Onukic2bd6132012-04-27 16:14:51 -0700139 private ProviderStatusWatcher mProviderStatusWatcher;
Brian Attwellc3d202c2015-01-08 15:01:03 -0800140 private Integer mProviderStatus;
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800141
Dmitri Plotnikov0cd01302010-12-17 18:41:57 -0800142 private boolean mOptionsMenuContactsAvailable;
Dmitri Plotnikov0cd01302010-12-17 18:41:57 -0800143
Daisuke Miyakawa95c5c2a2011-07-08 10:33:21 -0700144 /**
145 * Showing a list of Contacts. Also used for showing search results in search mode.
146 */
Brian Attwell20510ec2015-02-27 16:10:45 -0800147 private MultiSelectContactsListFragment mAllFragment;
Frank Sposaro7979ea22011-07-14 16:46:07 -0700148 private ContactTileListFragment mFavoritesFragment;
Katherine Kuanb5760b92011-06-01 16:19:40 -0700149
Brian Attwell2c1bfd02014-06-04 18:18:35 -0700150 /** ViewPager for swipe */
Makoto Onuki250ce432011-07-12 18:26:45 -0700151 private ViewPager mTabPager;
Brian Attwell3c763b32014-07-21 14:25:28 -0700152 private ViewPagerTabs mViewPagerTabs;
Makoto Onuki250ce432011-07-12 18:26:45 -0700153 private TabPagerAdapter mTabPagerAdapter;
Brian Attwell3c763b32014-07-21 14:25:28 -0700154 private String[] mTabTitles;
Makoto Onuki2e177302011-08-15 14:06:55 -0700155 private final TabPagerListener mTabPagerListener = new TabPagerListener();
Katherine Kuan58fc5772011-07-04 10:08:32 -0700156
Makoto Onuki9ae60412012-07-19 15:56:41 -0700157 private boolean mEnableDebugMenuOptions;
158
Makoto Onuki417ca492011-07-14 19:06:35 -0700159 /**
160 * True if this activity instance is a re-created one. i.e. set true after orientation change.
161 * This is set in {@link #onCreate} for later use in {@link #onStart}.
162 */
163 private boolean mIsRecreatedInstance;
164
165 /**
166 * If {@link #configureFragments(boolean)} is already called. Used to avoid calling it twice
167 * in {@link #onStart}.
168 * (This initialization only needs to be done once in onStart() when the Activity was just
169 * created from scratch -- i.e. onCreate() was just called)
170 */
171 private boolean mFragmentInitialized;
172
Katherine Kuanbe79b8f2011-11-09 20:54:43 -0800173 /**
Paul Sliwowski32791d42013-09-11 15:25:43 -0700174 * This is to disable {@link #onOptionsItemSelected} when we trying to stop the activity.
175 */
176 private boolean mDisableOptionItemSelected;
177
Makoto Onuki6d9befe2011-07-17 11:00:12 -0700178 /** Sequential ID assigned to each instance; used for logging */
179 private final int mInstanceId;
180 private static final AtomicInteger sNextInstanceId = new AtomicInteger();
181
Katherine Kuan9856fce2011-06-01 10:24:09 -0700182 public PeopleActivity() {
Makoto Onuki6d9befe2011-07-17 11:00:12 -0700183 mInstanceId = sNextInstanceId.getAndIncrement();
Dmitri Plotnikov15406742010-05-07 09:22:49 -0700184 mIntentResolver = new ContactsIntentResolver(this);
Makoto Onukic2bd6132012-04-27 16:14:51 -0700185 mProviderStatusWatcher = ProviderStatusWatcher.getInstance(this);
Dmitri Plotnikov6178cb42010-04-20 11:26:05 -0700186 }
187
Makoto Onuki6d9befe2011-07-17 11:00:12 -0700188 @Override
189 public String toString() {
190 // Shown on logcat
191 return String.format("%s@%d", getClass().getSimpleName(), mInstanceId);
192 }
193
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800194 public boolean areContactsAvailable() {
Wenyi Wang2f09e602015-10-28 11:34:23 -0700195 return (mProviderStatus != null) && mProviderStatus.equals(ProviderStatus.STATUS_NORMAL);
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800196 }
197
Makoto Onuki6f74c0f2011-09-27 13:47:15 -0700198 private boolean areGroupWritableAccountsAvailable() {
199 return ContactsUtils.areGroupWritableAccountsAvailable(this);
200 }
Isaac Katzenelson49917b32011-07-19 17:02:30 -0700201
Makoto Onuki50445e92011-07-12 10:28:12 -0700202 /**
203 * Initialize fragments that are (or may not be) in the layout.
204 *
205 * For the fragments that are in the layout, we initialize them in
Makoto Onuki417ca492011-07-14 19:06:35 -0700206 * {@link #createViewsAndFragments(Bundle)} after inflating the layout.
Makoto Onuki50445e92011-07-12 10:28:12 -0700207 *
Brian Attwell2c1bfd02014-06-04 18:18:35 -0700208 * However, the {@link ContactsUnavailableFragment} is a special fragment which may not
209 * be in the layout, so we have to do the initialization here.
210 *
211 * The ContactsUnavailableFragment is always created at runtime.
Makoto Onuki50445e92011-07-12 10:28:12 -0700212 */
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800213 @Override
Dmitri Plotnikov92a6fdf2010-07-09 13:19:33 -0700214 public void onAttachFragment(Fragment fragment) {
Brian Attwell2c1bfd02014-06-04 18:18:35 -0700215 if (fragment instanceof ContactsUnavailableFragment) {
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800216 mContactsUnavailableFragment = (ContactsUnavailableFragment)fragment;
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800217 mContactsUnavailableFragment.setOnContactsUnavailableActionListener(
218 new ContactsUnavailableFragmentListener());
Dmitri Plotnikov92a6fdf2010-07-09 13:19:33 -0700219 }
220 }
221
222 @Override
Dmitri Plotnikov08e1c4e2010-07-02 17:57:51 -0700223 protected void onCreate(Bundle savedState) {
Makoto Onuki49627cc2011-08-28 13:56:48 -0700224 if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) {
225 Log.d(Constants.PERFORMANCE_TAG, "PeopleActivity.onCreate start");
226 }
Dmitri Plotnikov08e1c4e2010-07-02 17:57:51 -0700227 super.onCreate(savedState);
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800228
Brian Attwellbdd32642015-05-08 17:03:15 -0700229 if (RequestPermissionsActivity.startPermissionActivity(this)) {
230 return;
231 }
232
Makoto Onuki6d9befe2011-07-17 11:00:12 -0700233 if (!processIntent(false)) {
Makoto Onuki417ca492011-07-14 19:06:35 -0700234 finish();
235 return;
236 }
Daisuke Miyakawaa012aec2011-10-16 10:24:43 -0700237 mContactListFilterController = ContactListFilterController.getInstance(this);
Katherine Kuanbe79b8f2011-11-09 20:54:43 -0800238 mContactListFilterController.checkFilterValidity(false);
Daisuke Miyakawaa012aec2011-10-16 10:24:43 -0700239 mContactListFilterController.addListener(this);
240
Makoto Onukic2bd6132012-04-27 16:14:51 -0700241 mProviderStatusWatcher.addListener(this);
242
Makoto Onuki417ca492011-07-14 19:06:35 -0700243 mIsRecreatedInstance = (savedState != null);
244 createViewsAndFragments(savedState);
Andrew Lee4b1af3f2014-04-23 10:23:55 -0700245
Makoto Onuki49627cc2011-08-28 13:56:48 -0700246 if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) {
247 Log.d(Constants.PERFORMANCE_TAG, "PeopleActivity.onCreate finish");
248 }
Sai Cheemalapati5b221082014-06-27 14:45:43 -0700249 getWindow().setBackgroundDrawable(null);
Dmitri Plotnikovfa49a662011-01-13 11:04:56 -0800250 }
251
252 @Override
253 protected void onNewIntent(Intent intent) {
254 setIntent(intent);
Makoto Onuki6d9befe2011-07-17 11:00:12 -0700255 if (!processIntent(true)) {
Makoto Onuki417ca492011-07-14 19:06:35 -0700256 finish();
257 return;
258 }
259 mActionBarAdapter.initialize(null, mRequest);
260
Katherine Kuanbe79b8f2011-11-09 20:54:43 -0800261 mContactListFilterController.checkFilterValidity(false);
Katherine Kuanbe79b8f2011-11-09 20:54:43 -0800262
Makoto Onuki417ca492011-07-14 19:06:35 -0700263 // Re-configure fragments.
264 configureFragments(true /* from request */);
Brian Attwell9cfa24c2015-05-04 12:31:37 -0700265 initializeFabVisibility();
Makoto Onuki417ca492011-07-14 19:06:35 -0700266 invalidateOptionsMenuIfNeeded();
Dmitri Plotnikovfa49a662011-01-13 11:04:56 -0800267 }
268
Makoto Onuki417ca492011-07-14 19:06:35 -0700269 /**
270 * Resolve the intent and initialize {@link #mRequest}, and launch another activity if redirect
271 * is needed.
272 *
Makoto Onuki6d9befe2011-07-17 11:00:12 -0700273 * @param forNewIntent set true if it's called from {@link #onNewIntent(Intent)}.
Makoto Onuki417ca492011-07-14 19:06:35 -0700274 * @return {@code true} if {@link PeopleActivity} should continue running. {@code false}
275 * if it shouldn't, in which case the caller should finish() itself and shouldn't do
276 * farther initialization.
277 */
Makoto Onuki6d9befe2011-07-17 11:00:12 -0700278 private boolean processIntent(boolean forNewIntent) {
Dmitri Plotnikov1ce1e7c2010-05-13 16:41:00 -0700279 // Extract relevant information from the intent
280 mRequest = mIntentResolver.resolveIntent(getIntent());
Makoto Onukiea146052011-07-25 10:34:15 -0700281 if (Log.isLoggable(TAG, Log.DEBUG)) {
Makoto Onuki6d9befe2011-07-17 11:00:12 -0700282 Log.d(TAG, this + " processIntent: forNewIntent=" + forNewIntent
283 + " intent=" + getIntent() + " request=" + mRequest);
284 }
Dmitri Plotnikov1ce1e7c2010-05-13 16:41:00 -0700285 if (!mRequest.isValid()) {
286 setResult(RESULT_CANCELED);
Makoto Onuki417ca492011-07-14 19:06:35 -0700287 return false;
Dmitri Plotnikov59fb48e2010-04-26 17:09:19 -0700288 }
289
Brian Attwell2c1bfd02014-06-04 18:18:35 -0700290 if (mRequest.getActionCode() == ContactsRequest.ACTION_VIEW_CONTACT) {
Brian Attwellc6100ff2015-02-19 21:35:36 -0800291 final Intent intent = ImplicitIntentsUtil.composeQuickContactIntent(
292 mRequest.getContactUri(), QuickContactActivity.MODE_FULLY_EXPANDED);
293 ImplicitIntentsUtil.startActivityInApp(this, intent);
Makoto Onuki417ca492011-07-14 19:06:35 -0700294 return false;
Dmitri Plotnikov27b97bc2010-10-07 18:06:09 -0700295 }
Makoto Onuki417ca492011-07-14 19:06:35 -0700296 return true;
297 }
298
299 private void createViewsAndFragments(Bundle savedState) {
300 setContentView(R.layout.people_activity);
301
302 final FragmentManager fragmentManager = getFragmentManager();
303
304 // Hide all tabs (the current tab will later be reshown once a tab is selected)
305 final FragmentTransaction transaction = fragmentManager.beginTransaction();
306
Brian Attwell3c763b32014-07-21 14:25:28 -0700307 mTabTitles = new String[TabState.COUNT];
308 mTabTitles[TabState.FAVORITES] = getString(R.string.favorites_tab_label);
309 mTabTitles[TabState.ALL] = getString(R.string.all_contacts_tab_label);
Brian Attwell2c1bfd02014-06-04 18:18:35 -0700310 mTabPager = getView(R.id.tab_pager);
311 mTabPagerAdapter = new TabPagerAdapter();
312 mTabPager.setAdapter(mTabPagerAdapter);
313 mTabPager.setOnPageChangeListener(mTabPagerListener);
Makoto Onuki417ca492011-07-14 19:06:35 -0700314
Wenyi Wange7fd1ad2016-01-06 14:12:10 -0800315 // Configure toolbar and toolbar tabs. If in landscape mode, we configure tabs differently.
Brian Attwell3c763b32014-07-21 14:25:28 -0700316 final Toolbar toolbar = getView(R.id.toolbar);
Wenyi Wange7fd1ad2016-01-06 14:12:10 -0800317 setSupportActionBar(toolbar);
Brian Attwell3c763b32014-07-21 14:25:28 -0700318 final ViewPagerTabs portraitViewPagerTabs
319 = (ViewPagerTabs) findViewById(R.id.lists_pager_header);
320 ViewPagerTabs landscapeViewPagerTabs = null;
321 if (portraitViewPagerTabs == null) {
322 landscapeViewPagerTabs = (ViewPagerTabs) getLayoutInflater().inflate(
323 R.layout.people_activity_tabs_lands, toolbar, /* attachToRoot = */ false);
324 mViewPagerTabs = landscapeViewPagerTabs;
325 } else {
326 mViewPagerTabs = portraitViewPagerTabs;
327 }
328 mViewPagerTabs.setViewPager(mTabPager);
329
Brian Attwell2c1bfd02014-06-04 18:18:35 -0700330 final String FAVORITE_TAG = "tab-pager-favorite";
331 final String ALL_TAG = "tab-pager-all";
Makoto Onuki417ca492011-07-14 19:06:35 -0700332
Brian Attwell2c1bfd02014-06-04 18:18:35 -0700333 // Create the fragments and add as children of the view pager.
334 // The pager adapter will only change the visibility; it'll never create/destroy
335 // fragments.
336 // However, if it's after screen rotation, the fragments have been re-created by
337 // the fragment manager, so first see if there're already the target fragments
338 // existing.
339 mFavoritesFragment = (ContactTileListFragment)
340 fragmentManager.findFragmentByTag(FAVORITE_TAG);
Brian Attwell20510ec2015-02-27 16:10:45 -0800341 mAllFragment = (MultiSelectContactsListFragment)
Brian Attwell2c1bfd02014-06-04 18:18:35 -0700342 fragmentManager.findFragmentByTag(ALL_TAG);
Makoto Onuki417ca492011-07-14 19:06:35 -0700343
Brian Attwell2c1bfd02014-06-04 18:18:35 -0700344 if (mFavoritesFragment == null) {
345 mFavoritesFragment = new ContactTileListFragment();
Brian Attwell20510ec2015-02-27 16:10:45 -0800346 mAllFragment = new MultiSelectContactsListFragment();
Makoto Onuki417ca492011-07-14 19:06:35 -0700347
Brian Attwell2c1bfd02014-06-04 18:18:35 -0700348 transaction.add(R.id.tab_pager, mFavoritesFragment, FAVORITE_TAG);
349 transaction.add(R.id.tab_pager, mAllFragment, ALL_TAG);
Makoto Onuki4d788fc2011-07-12 10:00:10 -0700350 }
Makoto Onuki417ca492011-07-14 19:06:35 -0700351
352 mFavoritesFragment.setListener(mFavoritesFragmentListener);
353
354 mAllFragment.setOnContactListActionListener(new ContactBrowserActionListener());
Brian Attwell20510ec2015-02-27 16:10:45 -0800355 mAllFragment.setCheckBoxListListener(new CheckBoxListListener());
Makoto Onuki417ca492011-07-14 19:06:35 -0700356
Makoto Onuki417ca492011-07-14 19:06:35 -0700357 // Hide all fragments for now. We adjust visibility when we get onSelectedTabChanged()
358 // from ActionBarAdapter.
359 transaction.hide(mFavoritesFragment);
360 transaction.hide(mAllFragment);
Makoto Onuki417ca492011-07-14 19:06:35 -0700361
Minh Pham4b25da72011-08-25 13:50:38 -0700362 transaction.commitAllowingStateLoss();
Makoto Onuki417ca492011-07-14 19:06:35 -0700363 fragmentManager.executePendingTransactions();
364
Frank Sposaro0c079352011-07-19 13:09:04 -0700365 // Setting Properties after fragment is created
Brian Attwell2c1bfd02014-06-04 18:18:35 -0700366 mFavoritesFragment.setDisplayType(DisplayType.STREQUENT);
Frank Sposaro0c079352011-07-19 13:09:04 -0700367
Wenyi Wange7fd1ad2016-01-06 14:12:10 -0800368 mActionBarAdapter = new ActionBarAdapter(this, this, getSupportActionBar(),
Brian Attwell3c763b32014-07-21 14:25:28 -0700369 portraitViewPagerTabs, landscapeViewPagerTabs, toolbar);
Makoto Onuki4d788fc2011-07-12 10:00:10 -0700370 mActionBarAdapter.initialize(savedState, mRequest);
371
Brian Attwelld41ab8a2014-08-07 11:08:55 -0700372 // Add shadow under toolbar
373 ViewUtil.addRectangularOutlineProvider(findViewById(R.id.toolbar_parent), getResources());
374
Brian Attwell865847b2015-04-20 14:40:17 -0700375 // Configure floating action button
376 mFloatingActionButtonContainer = findViewById(R.id.floating_action_button_container);
377 final ImageButton floatingActionButton
378 = (ImageButton) findViewById(R.id.floating_action_button);
Brian Attwell2c1bfd02014-06-04 18:18:35 -0700379 floatingActionButton.setOnClickListener(this);
Brian Attwell865847b2015-04-20 14:40:17 -0700380 mFloatingActionButtonController = new FloatingActionButtonController(this,
381 mFloatingActionButtonContainer, floatingActionButton);
Brian Attwell9cfa24c2015-05-04 12:31:37 -0700382 initializeFabVisibility();
Paul Soulos2b9563d2014-05-27 16:21:23 -0700383
Makoto Onuki417ca492011-07-14 19:06:35 -0700384 invalidateOptionsMenuIfNeeded();
385 }
Dmitri Plotnikovfa49a662011-01-13 11:04:56 -0800386
Makoto Onuki417ca492011-07-14 19:06:35 -0700387 @Override
388 protected void onStart() {
389 if (!mFragmentInitialized) {
390 mFragmentInitialized = true;
391 /* Configure fragments if we haven't.
392 *
393 * Note it's a one-shot initialization, so we want to do this in {@link #onCreate}.
394 *
395 * However, because this method may indirectly touch views in fragments but fragments
396 * created in {@link #configureContentView} using a {@link FragmentTransaction} will NOT
397 * have views until {@link Activity#onCreate} finishes (they would if they were inflated
398 * from a layout), we need to do it here in {@link #onStart()}.
399 *
400 * (When {@link Fragment#onCreateView} is called is different in the former case and
401 * in the latter case, unfortunately.)
402 *
403 * Also, we skip most of the work in it if the activity is a re-created one.
404 * (so the argument.)
405 */
406 configureFragments(!mIsRecreatedInstance);
Dmitri Plotnikovfe42e552010-05-14 14:50:32 -0700407 }
Makoto Onuki417ca492011-07-14 19:06:35 -0700408 super.onStart();
Dmitri Plotnikovcaf0bc72010-09-03 15:16:21 -0700409 }
410
Dmitri Plotnikov6e850a02010-10-28 10:46:21 -0700411 @Override
Dmitri Plotnikov174fdc22010-10-29 13:55:01 -0700412 protected void onPause() {
Dmitri Plotnikovfa49a662011-01-13 11:04:56 -0800413 mOptionsMenuContactsAvailable = false;
Makoto Onukic2bd6132012-04-27 16:14:51 -0700414 mProviderStatusWatcher.stop();
Dmitri Plotnikov174fdc22010-10-29 13:55:01 -0700415 super.onPause();
416 }
417
418 @Override
419 protected void onResume() {
420 super.onResume();
Josh Gargus697ab262012-05-04 11:11:34 -0700421
Makoto Onukic2bd6132012-04-27 16:14:51 -0700422 mProviderStatusWatcher.start();
Josh Gargus697ab262012-05-04 11:11:34 -0700423 updateViewConfiguration(true);
Makoto Onuki4d788fc2011-07-12 10:00:10 -0700424
425 // Re-register the listener, which may have been cleared when onSaveInstanceState was
426 // called. See also: onSaveInstanceState
427 mActionBarAdapter.setListener(this);
Paul Sliwowski32791d42013-09-11 15:25:43 -0700428 mDisableOptionItemSelected = false;
Makoto Onuki2e177302011-08-15 14:06:55 -0700429 if (mTabPager != null) {
430 mTabPager.setOnPageChangeListener(mTabPagerListener);
431 }
Makoto Onukia4505fc2011-07-15 12:22:24 -0700432 // Current tab may have changed since the last onSaveInstanceState(). Make sure
433 // the actual contents match the tab.
434 updateFragmentsVisibility();
Dmitri Plotnikov174fdc22010-10-29 13:55:01 -0700435 }
436
437 @Override
Makoto Onuki4d788fc2011-07-12 10:00:10 -0700438 protected void onDestroy() {
Makoto Onukic2bd6132012-04-27 16:14:51 -0700439 mProviderStatusWatcher.removeListener(this);
440
Daisuke Miyakawab2a23182011-11-02 12:40:42 -0700441 // Some of variables will be null if this Activity redirects Intent.
442 // See also onCreate() or other methods called during the Activity's initialization.
Makoto Onukic1eed6d2011-07-14 12:24:02 -0700443 if (mActionBarAdapter != null) {
444 mActionBarAdapter.setListener(null);
445 }
Daisuke Miyakawab2a23182011-11-02 12:40:42 -0700446 if (mContactListFilterController != null) {
447 mContactListFilterController.removeListener(this);
448 }
449
Makoto Onuki4d788fc2011-07-12 10:00:10 -0700450 super.onDestroy();
451 }
452
Dmitri Plotnikov955846e2010-11-11 22:31:28 -0800453 private void configureFragments(boolean fromRequest) {
Dmitri Plotnikov009676f2010-10-08 12:13:57 -0700454 if (fromRequest) {
Dmitri Plotnikov91ab5b42010-10-08 15:26:31 -0700455 ContactListFilter filter = null;
456 int actionCode = mRequest.getActionCode();
Makoto Onuki53b427b2011-07-17 11:42:32 -0700457 boolean searchMode = mRequest.isSearchMode();
Daniel Lehmann52aa32d2012-03-08 17:29:27 -0800458 final int tabToOpen;
Dmitri Plotnikov91ab5b42010-10-08 15:26:31 -0700459 switch (actionCode) {
460 case ContactsRequest.ACTION_ALL_CONTACTS:
Katherine Kuanbe18de02011-06-07 12:38:29 -0700461 filter = ContactListFilter.createFilterWithType(
462 ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS);
Makoto Onukiea146052011-07-25 10:34:15 -0700463 tabToOpen = TabState.ALL;
Dmitri Plotnikov91ab5b42010-10-08 15:26:31 -0700464 break;
465 case ContactsRequest.ACTION_CONTACTS_WITH_PHONES:
Katherine Kuanbe18de02011-06-07 12:38:29 -0700466 filter = ContactListFilter.createFilterWithType(
Dmitri Plotnikov91ab5b42010-10-08 15:26:31 -0700467 ContactListFilter.FILTER_TYPE_WITH_PHONE_NUMBERS_ONLY);
Makoto Onukiea146052011-07-25 10:34:15 -0700468 tabToOpen = TabState.ALL;
Dmitri Plotnikov91ab5b42010-10-08 15:26:31 -0700469 break;
470
Dmitri Plotnikov91ab5b42010-10-08 15:26:31 -0700471 case ContactsRequest.ACTION_FREQUENT:
472 case ContactsRequest.ACTION_STREQUENT:
Dmitri Plotnikov91ab5b42010-10-08 15:26:31 -0700473 case ContactsRequest.ACTION_STARRED:
Makoto Onukiea146052011-07-25 10:34:15 -0700474 tabToOpen = TabState.FAVORITES;
Dmitri Plotnikov91ab5b42010-10-08 15:26:31 -0700475 break;
Frank Sposaro9e095d22011-07-07 15:18:38 -0700476 case ContactsRequest.ACTION_VIEW_CONTACT:
Makoto Onukiea146052011-07-25 10:34:15 -0700477 tabToOpen = TabState.ALL;
478 break;
Daniel Lehmann52aa32d2012-03-08 17:29:27 -0800479 default:
480 tabToOpen = -1;
481 break;
Makoto Onukiea146052011-07-25 10:34:15 -0700482 }
Daniel Lehmann52aa32d2012-03-08 17:29:27 -0800483 if (tabToOpen != -1) {
Makoto Onukiea146052011-07-25 10:34:15 -0700484 mActionBarAdapter.setCurrentTab(tabToOpen);
Dmitri Plotnikov91ab5b42010-10-08 15:26:31 -0700485 }
486
487 if (filter != null) {
488 mContactListFilterController.setContactListFilter(filter, false);
Makoto Onuki53b427b2011-07-17 11:42:32 -0700489 searchMode = false;
Dmitri Plotnikov009676f2010-10-08 12:13:57 -0700490 }
Dmitri Plotnikovd9591042010-11-23 09:25:03 -0800491
492 if (mRequest.getContactUri() != null) {
Makoto Onuki53b427b2011-07-17 11:42:32 -0700493 searchMode = false;
Dmitri Plotnikovd9591042010-11-23 09:25:03 -0800494 }
495
Makoto Onuki53b427b2011-07-17 11:42:32 -0700496 mActionBarAdapter.setSearchMode(searchMode);
Katherine Kuan0ff0e312011-06-08 17:43:51 -0700497 configureContactListFragmentForRequest();
Dmitri Plotnikov08e1c4e2010-07-02 17:57:51 -0700498 }
499
Katherine Kuan0ff0e312011-06-08 17:43:51 -0700500 configureContactListFragment();
Dmitri Plotnikovfa49a662011-01-13 11:04:56 -0800501
Katherine Kuan8268bbe2011-06-10 17:48:21 -0700502 invalidateOptionsMenuIfNeeded();
Dmitri Plotnikov92a6fdf2010-07-09 13:19:33 -0700503 }
504
Brian Attwell865847b2015-04-20 14:40:17 -0700505 private void initializeFabVisibility() {
506 final boolean hideFab = mActionBarAdapter.isSearchMode()
507 || mActionBarAdapter.isSelectionMode();
508 mFloatingActionButtonContainer.setVisibility(hideFab ? View.GONE : View.VISIBLE);
Brian Attwell9cfa24c2015-05-04 12:31:37 -0700509 mFloatingActionButtonController.resetIn();
Brian Attwell865847b2015-04-20 14:40:17 -0700510 wasLastFabAnimationScaleIn = !hideFab;
511 }
512
513 private void showFabWithAnimation(boolean showFab) {
514 if (mFloatingActionButtonContainer == null) {
515 return;
516 }
517 if (showFab) {
518 if (!wasLastFabAnimationScaleIn) {
519 mFloatingActionButtonContainer.setVisibility(View.VISIBLE);
520 mFloatingActionButtonController.scaleIn(0);
521 }
522 wasLastFabAnimationScaleIn = true;
523
524 } else {
525 if (wasLastFabAnimationScaleIn) {
526 mFloatingActionButtonContainer.setVisibility(View.VISIBLE);
527 mFloatingActionButtonController.scaleOut();
528 }
529 wasLastFabAnimationScaleIn = false;
530 }
531 }
532
Dmitri Plotnikov6e850a02010-10-28 10:46:21 -0700533 @Override
Dmitri Plotnikov6e850a02010-10-28 10:46:21 -0700534 public void onContactListFilterChanged() {
Daisuke Miyakawa95c5c2a2011-07-08 10:33:21 -0700535 if (mAllFragment == null || !mAllFragment.isAdded()) {
Dmitri Plotnikov955846e2010-11-11 22:31:28 -0800536 return;
537 }
538
Daisuke Miyakawa95c5c2a2011-07-08 10:33:21 -0700539 mAllFragment.setFilter(mContactListFilterController.getFilter());
Dmitri Plotnikove898a9f2010-11-18 16:58:25 -0800540
Katherine Kuan8268bbe2011-06-10 17:48:21 -0700541 invalidateOptionsMenuIfNeeded();
Dmitri Plotnikov6e850a02010-10-28 10:46:21 -0700542 }
543
Dmitri Plotnikovfcfdffb2010-07-15 18:00:55 -0700544 /**
545 * Handler for action bar actions.
546 */
Dmitri Plotnikovfe42e552010-05-14 14:50:32 -0700547 @Override
Daniel Lehmann311882a2012-04-27 22:31:38 -0700548 public void onAction(int action) {
Katherine Kuanb5760b92011-06-01 16:19:40 -0700549 switch (action) {
Brian Attwell20510ec2015-02-27 16:10:45 -0800550 case ActionBarAdapter.Listener.Action.START_SELECTION_MODE:
551 mAllFragment.displayCheckBoxes(true);
Walter Janga84fe612016-01-13 16:49:04 -0800552 startSearchOrSelectionMode();
553 break;
Daniel Lehmann311882a2012-04-27 22:31:38 -0700554 case ActionBarAdapter.Listener.Action.START_SEARCH_MODE:
Walter Janga84fe612016-01-13 16:49:04 -0800555 if (!mIsRecreatedInstance) {
556 Logger.getInstance().logScreenView(
557 ScreenEvent.SEARCH, this, ScreenEvent.TAG_SEARCH);
558 }
559 startSearchOrSelectionMode();
Brian Attwell865847b2015-04-20 14:40:17 -0700560 break;
561 case ActionBarAdapter.Listener.Action.BEGIN_STOPPING_SEARCH_AND_SELECTION_MODE:
562 showFabWithAnimation(/* showFabWithAnimation = */ true);
Katherine Kuanb5760b92011-06-01 16:19:40 -0700563 break;
Brian Attwell20510ec2015-02-27 16:10:45 -0800564 case ActionBarAdapter.Listener.Action.STOP_SEARCH_AND_SELECTION_MODE:
Makoto Onuki1db00f62011-10-19 12:40:12 -0700565 setQueryTextToFragment("");
Makoto Onuki4d788fc2011-07-12 10:00:10 -0700566 updateFragmentsVisibility();
Makoto Onuki8811b7c2011-07-13 15:43:03 -0700567 invalidateOptionsMenu();
Brian Attwell865847b2015-04-20 14:40:17 -0700568 showFabWithAnimation(/* showFabWithAnimation = */ true);
Katherine Kuan8268bbe2011-06-10 17:48:21 -0700569 break;
Daniel Lehmann311882a2012-04-27 22:31:38 -0700570 case ActionBarAdapter.Listener.Action.CHANGE_SEARCH_QUERY:
Makoto Onuki9ae60412012-07-19 15:56:41 -0700571 final String queryString = mActionBarAdapter.getQueryString();
572 setQueryTextToFragment(queryString);
573 updateDebugOptionsVisibility(
574 ENABLE_DEBUG_OPTIONS_HIDDEN_CODE.equals(queryString));
Katherine Kuanb5760b92011-06-01 16:19:40 -0700575 break;
576 default:
577 throw new IllegalStateException("Unkonwn ActionBarAdapter action: " + action);
578 }
Dmitri Plotnikovfe42e552010-05-14 14:50:32 -0700579 }
580
Walter Janga84fe612016-01-13 16:49:04 -0800581 private void startSearchOrSelectionMode() {
582 configureFragments(false /* from request */);
583 updateFragmentsVisibility();
584 invalidateOptionsMenu();
585 showFabWithAnimation(/* showFabWithAnimation = */ false);
586 }
587
Makoto Onuki4d788fc2011-07-12 10:00:10 -0700588 @Override
589 public void onSelectedTabChanged() {
590 updateFragmentsVisibility();
591 }
592
Brian Attwell6adbf1e2014-05-30 16:44:51 -0700593 @Override
594 public void onUpButtonPressed() {
595 onBackPressed();
596 }
597
Makoto Onuki9ae60412012-07-19 15:56:41 -0700598 private void updateDebugOptionsVisibility(boolean visible) {
599 if (mEnableDebugMenuOptions != visible) {
600 mEnableDebugMenuOptions = visible;
601 invalidateOptionsMenu();
602 }
603 }
604
Makoto Onuki4d788fc2011-07-12 10:00:10 -0700605 /**
606 * Updates the fragment/view visibility according to the current mode, such as
607 * {@link ActionBarAdapter#isSearchMode()} and {@link ActionBarAdapter#getCurrentTab()}.
608 */
609 private void updateFragmentsVisibility() {
Daniel Lehmann52aa32d2012-03-08 17:29:27 -0800610 int tab = mActionBarAdapter.getCurrentTab();
Makoto Onuki4d788fc2011-07-12 10:00:10 -0700611
Brian Attwell20510ec2015-02-27 16:10:45 -0800612 if (mActionBarAdapter.isSearchMode() || mActionBarAdapter.isSelectionMode()) {
613 mTabPagerAdapter.setTabsHidden(true);
Brian Attwell2c1bfd02014-06-04 18:18:35 -0700614 } else {
Brian Attwell20510ec2015-02-27 16:10:45 -0800615 // No smooth scrolling if quitting from the search/selection mode.
616 final boolean wereTabsHidden = mTabPagerAdapter.areTabsHidden()
617 || mActionBarAdapter.isSelectionMode();
618 mTabPagerAdapter.setTabsHidden(false);
Brian Attwell2c1bfd02014-06-04 18:18:35 -0700619 if (mTabPager.getCurrentItem() != tab) {
Brian Attwell20510ec2015-02-27 16:10:45 -0800620 mTabPager.setCurrentItem(tab, !wereTabsHidden);
Brian Attwell2c1bfd02014-06-04 18:18:35 -0700621 }
Makoto Onuki4d788fc2011-07-12 10:00:10 -0700622 }
Brian Attwelld2962a32015-03-02 14:48:50 -0800623 if (!mActionBarAdapter.isSelectionMode()) {
624 mAllFragment.displayCheckBoxes(false);
625 }
Brian Attwell2c1bfd02014-06-04 18:18:35 -0700626 invalidateOptionsMenu();
Isaac Katzenelson66606b62011-07-22 18:47:45 -0700627 showEmptyStateForTab(tab);
628 }
629
Daniel Lehmann52aa32d2012-03-08 17:29:27 -0800630 private void showEmptyStateForTab(int tab) {
Isaac Katzenelson66606b62011-07-22 18:47:45 -0700631 if (mContactsUnavailableFragment != null) {
Brian Attwell92037882014-10-16 18:24:44 -0700632 switch (getTabPositionForTextDirection(tab)) {
Daniel Lehmann52aa32d2012-03-08 17:29:27 -0800633 case TabState.FAVORITES:
Wenyi Wangb0cfae52015-09-28 17:17:40 -0700634 mContactsUnavailableFragment.setTabInfo(
635 R.string.listTotalAllContactsZeroStarred, TabState.FAVORITES);
Isaac Katzenelson66606b62011-07-22 18:47:45 -0700636 break;
Daniel Lehmann52aa32d2012-03-08 17:29:27 -0800637 case TabState.ALL:
Wenyi Wangb0cfae52015-09-28 17:17:40 -0700638 mContactsUnavailableFragment.setTabInfo(R.string.noContacts, TabState.ALL);
Isaac Katzenelson66606b62011-07-22 18:47:45 -0700639 break;
640 }
Brian Attwell8d71f112014-07-23 18:13:27 -0700641 // When using the mContactsUnavailableFragment the ViewPager doesn't contain two views.
642 // Therefore, we have to trick the ViewPagerTabs into thinking we have changed tabs
643 // when the mContactsUnavailableFragment changes. Otherwise the tab strip won't move.
644 mViewPagerTabs.onPageScrolled(tab, 0, 0);
Isaac Katzenelson66606b62011-07-22 18:47:45 -0700645 }
Makoto Onuki4d788fc2011-07-12 10:00:10 -0700646 }
647
Makoto Onuki250ce432011-07-12 18:26:45 -0700648 private class TabPagerListener implements ViewPager.OnPageChangeListener {
Chiao Cheng70f77ea2012-05-31 13:33:58 -0700649
650 // This package-protected constructor is here because of a possible compiler bug.
651 // PeopleActivity$1.class should be generated due to the private outer/inner class access
652 // needed here. But for some reason, PeopleActivity$1.class is missing.
653 // Since $1 class is needed as a jvm work around to get access to the inner class,
654 // changing the constructor to package-protected or public will solve the problem.
655 // To verify whether $1 class is needed, javap PeopleActivity$TabPagerListener and look for
656 // references to PeopleActivity$1.
657 //
658 // When the constructor is private and PeopleActivity$1.class is missing, proguard will
659 // correctly catch this and throw warnings and error out the build on user/userdebug builds.
660 //
661 // All private inner classes below also need this fix.
662 TabPagerListener() {}
663
Makoto Onuki250ce432011-07-12 18:26:45 -0700664 @Override
665 public void onPageScrollStateChanged(int state) {
Brian Attwell20510ec2015-02-27 16:10:45 -0800666 if (!mTabPagerAdapter.areTabsHidden()) {
Brian Attwell3c763b32014-07-21 14:25:28 -0700667 mViewPagerTabs.onPageScrollStateChanged(state);
668 }
Makoto Onuki250ce432011-07-12 18:26:45 -0700669 }
670
671 @Override
672 public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
Brian Attwell20510ec2015-02-27 16:10:45 -0800673 if (!mTabPagerAdapter.areTabsHidden()) {
Brian Attwell3c763b32014-07-21 14:25:28 -0700674 mViewPagerTabs.onPageScrolled(position, positionOffset, positionOffsetPixels);
675 }
Makoto Onuki250ce432011-07-12 18:26:45 -0700676 }
677
678 @Override
679 public void onPageSelected(int position) {
680 // Make sure not in the search mode, in which case position != TabState.ordinal().
Brian Attwell20510ec2015-02-27 16:10:45 -0800681 if (!mTabPagerAdapter.areTabsHidden()) {
Daniel Lehmann52aa32d2012-03-08 17:29:27 -0800682 mActionBarAdapter.setCurrentTab(position, false);
Brian Attwell3c763b32014-07-21 14:25:28 -0700683 mViewPagerTabs.onPageSelected(position);
Daniel Lehmann52aa32d2012-03-08 17:29:27 -0800684 showEmptyStateForTab(position);
Makoto Onuki8811b7c2011-07-13 15:43:03 -0700685 invalidateOptionsMenu();
Makoto Onuki250ce432011-07-12 18:26:45 -0700686 }
687 }
688 }
689
690 /**
691 * Adapter for the {@link ViewPager}. Unlike {@link FragmentPagerAdapter},
692 * {@link #instantiateItem} returns existing fragments, and {@link #instantiateItem}/
693 * {@link #destroyItem} show/hide fragments instead of attaching/detaching.
694 *
695 * In search mode, we always show the "all" fragment, and disable the swipe. We change the
696 * number of items to 1 to disable the swipe.
697 *
698 * TODO figure out a more straight way to disable swipe.
699 */
700 private class TabPagerAdapter extends PagerAdapter {
701 private final FragmentManager mFragmentManager;
702 private FragmentTransaction mCurTransaction = null;
703
Brian Attwell20510ec2015-02-27 16:10:45 -0800704 private boolean mAreTabsHiddenInTabPager;
Makoto Onuki250ce432011-07-12 18:26:45 -0700705
Makoto Onuki746316a2011-10-31 14:32:39 -0700706 private Fragment mCurrentPrimaryItem;
707
Makoto Onuki250ce432011-07-12 18:26:45 -0700708 public TabPagerAdapter() {
709 mFragmentManager = getFragmentManager();
710 }
711
Brian Attwell20510ec2015-02-27 16:10:45 -0800712 public boolean areTabsHidden() {
713 return mAreTabsHiddenInTabPager;
Makoto Onuki250ce432011-07-12 18:26:45 -0700714 }
715
Brian Attwell20510ec2015-02-27 16:10:45 -0800716 public void setTabsHidden(boolean hideTabs) {
717 if (hideTabs == mAreTabsHiddenInTabPager) {
Makoto Onuki250ce432011-07-12 18:26:45 -0700718 return;
719 }
Brian Attwell20510ec2015-02-27 16:10:45 -0800720 mAreTabsHiddenInTabPager = hideTabs;
Makoto Onuki250ce432011-07-12 18:26:45 -0700721 notifyDataSetChanged();
722 }
723
724 @Override
725 public int getCount() {
Brian Attwell20510ec2015-02-27 16:10:45 -0800726 return mAreTabsHiddenInTabPager ? 1 : TabState.COUNT;
Makoto Onuki250ce432011-07-12 18:26:45 -0700727 }
728
729 /** Gets called when the number of items changes. */
730 @Override
731 public int getItemPosition(Object object) {
Brian Attwell20510ec2015-02-27 16:10:45 -0800732 if (mAreTabsHiddenInTabPager) {
Makoto Onuki250ce432011-07-12 18:26:45 -0700733 if (object == mAllFragment) {
734 return 0; // Only 1 page in search mode
735 }
736 } else {
737 if (object == mFavoritesFragment) {
Brian Attwell962677f2014-09-26 12:29:07 -0700738 return getTabPositionForTextDirection(TabState.FAVORITES);
Makoto Onuki250ce432011-07-12 18:26:45 -0700739 }
740 if (object == mAllFragment) {
Brian Attwell962677f2014-09-26 12:29:07 -0700741 return getTabPositionForTextDirection(TabState.ALL);
Makoto Onuki250ce432011-07-12 18:26:45 -0700742 }
Makoto Onuki250ce432011-07-12 18:26:45 -0700743 }
744 return POSITION_NONE;
745 }
746
747 @Override
Katherine Kuan97045442011-11-28 10:47:58 -0800748 public void startUpdate(ViewGroup container) {
Makoto Onuki250ce432011-07-12 18:26:45 -0700749 }
750
751 private Fragment getFragment(int position) {
Brian Attwell962677f2014-09-26 12:29:07 -0700752 position = getTabPositionForTextDirection(position);
Brian Attwell20510ec2015-02-27 16:10:45 -0800753 if (mAreTabsHiddenInTabPager) {
Daniel Lehmann8d9ca012012-05-03 18:33:56 -0700754 if (position != 0) {
755 // This has only been observed in monkey tests.
756 // Let's log this issue, but not crash
757 Log.w(TAG, "Request fragment at position=" + position + ", eventhough we " +
758 "are in search mode");
Makoto Onuki250ce432011-07-12 18:26:45 -0700759 }
Daniel Lehmann8d9ca012012-05-03 18:33:56 -0700760 return mAllFragment;
Makoto Onuki250ce432011-07-12 18:26:45 -0700761 } else {
Daniel Lehmann52aa32d2012-03-08 17:29:27 -0800762 if (position == TabState.FAVORITES) {
Makoto Onuki250ce432011-07-12 18:26:45 -0700763 return mFavoritesFragment;
Daniel Lehmann52aa32d2012-03-08 17:29:27 -0800764 } else if (position == TabState.ALL) {
Makoto Onuki250ce432011-07-12 18:26:45 -0700765 return mAllFragment;
Makoto Onuki250ce432011-07-12 18:26:45 -0700766 }
767 }
768 throw new IllegalArgumentException("position: " + position);
769 }
770
771 @Override
Katherine Kuan97045442011-11-28 10:47:58 -0800772 public Object instantiateItem(ViewGroup container, int position) {
Makoto Onuki250ce432011-07-12 18:26:45 -0700773 if (mCurTransaction == null) {
774 mCurTransaction = mFragmentManager.beginTransaction();
775 }
776 Fragment f = getFragment(position);
777 mCurTransaction.show(f);
Makoto Onuki746316a2011-10-31 14:32:39 -0700778
Adam Powell9bd59f22011-11-07 14:02:10 -0800779 // Non primary pages are not visible.
780 f.setUserVisibleHint(f == mCurrentPrimaryItem);
Makoto Onuki250ce432011-07-12 18:26:45 -0700781 return f;
782 }
783
784 @Override
Katherine Kuan97045442011-11-28 10:47:58 -0800785 public void destroyItem(ViewGroup container, int position, Object object) {
Makoto Onuki250ce432011-07-12 18:26:45 -0700786 if (mCurTransaction == null) {
787 mCurTransaction = mFragmentManager.beginTransaction();
788 }
789 mCurTransaction.hide((Fragment) object);
790 }
791
792 @Override
Katherine Kuan97045442011-11-28 10:47:58 -0800793 public void finishUpdate(ViewGroup container) {
Makoto Onuki250ce432011-07-12 18:26:45 -0700794 if (mCurTransaction != null) {
Minh Pham4b25da72011-08-25 13:50:38 -0700795 mCurTransaction.commitAllowingStateLoss();
Makoto Onuki250ce432011-07-12 18:26:45 -0700796 mCurTransaction = null;
797 mFragmentManager.executePendingTransactions();
798 }
799 }
800
801 @Override
802 public boolean isViewFromObject(View view, Object object) {
803 return ((Fragment) object).getView() == view;
804 }
805
806 @Override
Katherine Kuan97045442011-11-28 10:47:58 -0800807 public void setPrimaryItem(ViewGroup container, int position, Object object) {
Makoto Onuki746316a2011-10-31 14:32:39 -0700808 Fragment fragment = (Fragment) object;
809 if (mCurrentPrimaryItem != fragment) {
810 if (mCurrentPrimaryItem != null) {
Adam Powell9bd59f22011-11-07 14:02:10 -0800811 mCurrentPrimaryItem.setUserVisibleHint(false);
Makoto Onuki746316a2011-10-31 14:32:39 -0700812 }
813 if (fragment != null) {
Adam Powell9bd59f22011-11-07 14:02:10 -0800814 fragment.setUserVisibleHint(true);
Makoto Onuki746316a2011-10-31 14:32:39 -0700815 }
816 mCurrentPrimaryItem = fragment;
817 }
818 }
819
820 @Override
Makoto Onuki250ce432011-07-12 18:26:45 -0700821 public Parcelable saveState() {
822 return null;
823 }
824
825 @Override
826 public void restoreState(Parcelable state, ClassLoader loader) {
827 }
Brian Attwell3c763b32014-07-21 14:25:28 -0700828
829 @Override
830 public CharSequence getPageTitle(int position) {
831 return mTabTitles[position];
832 }
Makoto Onuki250ce432011-07-12 18:26:45 -0700833 }
834
Makoto Onuki1db00f62011-10-19 12:40:12 -0700835 private void setQueryTextToFragment(String query) {
Daisuke Miyakawa95c5c2a2011-07-08 10:33:21 -0700836 mAllFragment.setQueryString(query, true);
Makoto Onuki1db00f62011-10-19 12:40:12 -0700837 mAllFragment.setVisibleScrollbarEnabled(!mAllFragment.isSearchMode());
Katherine Kuan8268bbe2011-06-10 17:48:21 -0700838 }
839
Katherine Kuan0ff0e312011-06-08 17:43:51 -0700840 private void configureContactListFragmentForRequest() {
Dmitri Plotnikovfa49a662011-01-13 11:04:56 -0800841 Uri contactUri = mRequest.getContactUri();
842 if (contactUri != null) {
Daisuke Miyakawa95c5c2a2011-07-08 10:33:21 -0700843 mAllFragment.setSelectedContactUri(contactUri);
Dmitri Plotnikovfa49a662011-01-13 11:04:56 -0800844 }
Dmitri Plotnikov1ce1e7c2010-05-13 16:41:00 -0700845
Daisuke Miyakawaa012aec2011-10-16 10:24:43 -0700846 mAllFragment.setFilter(mContactListFilterController.getFilter());
Makoto Onuki1db00f62011-10-19 12:40:12 -0700847 setQueryTextToFragment(mActionBarAdapter.getQueryString());
Dmitri Plotnikov1ce1e7c2010-05-13 16:41:00 -0700848
Dmitri Plotnikovfa49a662011-01-13 11:04:56 -0800849 if (mRequest.isDirectorySearchEnabled()) {
Daisuke Miyakawa95c5c2a2011-07-08 10:33:21 -0700850 mAllFragment.setDirectorySearchMode(DirectoryListLoader.SEARCH_MODE_DEFAULT);
Dmitri Plotnikovfa49a662011-01-13 11:04:56 -0800851 } else {
Daisuke Miyakawa95c5c2a2011-07-08 10:33:21 -0700852 mAllFragment.setDirectorySearchMode(DirectoryListLoader.SEARCH_MODE_NONE);
Dmitri Plotnikovfa49a662011-01-13 11:04:56 -0800853 }
Dmitri Plotnikov08e1c4e2010-07-02 17:57:51 -0700854 }
855
Katherine Kuan0ff0e312011-06-08 17:43:51 -0700856 private void configureContactListFragment() {
Daisuke Miyakawaa012aec2011-10-16 10:24:43 -0700857 // Filter may be changed when this Activity is in background.
858 mAllFragment.setFilter(mContactListFilterController.getFilter());
859
Brian Attwell2c1bfd02014-06-04 18:18:35 -0700860 mAllFragment.setVerticalScrollbarPosition(getScrollBarPosition());
861 mAllFragment.setSelectionVisible(false);
Dmitri Plotnikov1ce1e7c2010-05-13 16:41:00 -0700862 }
863
Brian Attwell2c1bfd02014-06-04 18:18:35 -0700864 private int getScrollBarPosition() {
865 return isRTL() ? View.SCROLLBAR_POSITION_LEFT : View.SCROLLBAR_POSITION_RIGHT;
Chiao Chenge9078382013-06-17 16:35:10 -0700866 }
867
868 private boolean isRTL() {
869 final Locale locale = Locale.getDefault();
870 return TextUtils.getLayoutDirectionFromLocale(locale) == View.LAYOUT_DIRECTION_RTL;
871 }
872
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800873 @Override
874 public void onProviderStatusChange() {
Josh Gargus697ab262012-05-04 11:11:34 -0700875 updateViewConfiguration(false);
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800876 }
877
Josh Gargus697ab262012-05-04 11:11:34 -0700878 private void updateViewConfiguration(boolean forceUpdate) {
Brian Attwellc3d202c2015-01-08 15:01:03 -0800879 int providerStatus = mProviderStatusWatcher.getProviderStatus();
Makoto Onukid8fa7162012-05-16 13:45:48 -0700880 if (!forceUpdate && (mProviderStatus != null)
Brian Attwellc3d202c2015-01-08 15:01:03 -0800881 && (mProviderStatus.equals(providerStatus))) return;
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800882 mProviderStatus = providerStatus;
883
884 View contactsUnavailableView = findViewById(R.id.contacts_unavailable_view);
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800885
Brian Attwellc3d202c2015-01-08 15:01:03 -0800886 if (mProviderStatus.equals(ProviderStatus.STATUS_NORMAL)) {
Josh Gargusb8f11b92011-11-17 18:32:44 -0800887 // Ensure that the mTabPager is visible; we may have made it invisible below.
Dmitri Plotnikovc3f2a522010-11-17 18:36:17 -0800888 contactsUnavailableView.setVisibility(View.GONE);
Josh Gargusb8f11b92011-11-17 18:32:44 -0800889 if (mTabPager != null) {
890 mTabPager.setVisibility(View.VISIBLE);
891 }
892
Daisuke Miyakawa95c5c2a2011-07-08 10:33:21 -0700893 if (mAllFragment != null) {
894 mAllFragment.setEnabled(true);
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800895 }
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800896 } else {
guanxiongliu5d7bb262016-01-29 16:43:45 -0800897 // Setting up the page so that the user can still use the app
898 // even without an account.
Daisuke Miyakawa95c5c2a2011-07-08 10:33:21 -0700899 if (mAllFragment != null) {
900 mAllFragment.setEnabled(false);
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800901 }
902 if (mContactsUnavailableFragment == null) {
903 mContactsUnavailableFragment = new ContactsUnavailableFragment();
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800904 mContactsUnavailableFragment.setOnContactsUnavailableActionListener(
905 new ContactsUnavailableFragmentListener());
Dianne Hackborn3ed426c2011-01-17 12:30:32 -0800906 getFragmentManager().beginTransaction()
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800907 .replace(R.id.contacts_unavailable_container, mContactsUnavailableFragment)
Minh Pham4b25da72011-08-25 13:50:38 -0700908 .commitAllowingStateLoss();
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800909 }
Makoto Onukid8fa7162012-05-16 13:45:48 -0700910 mContactsUnavailableFragment.updateStatus(mProviderStatus);
Josh Gargusb8f11b92011-11-17 18:32:44 -0800911
912 // Show the contactsUnavailableView, and hide the mTabPager so that we don't
913 // see it sliding in underneath the contactsUnavailableView at the edges.
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800914 contactsUnavailableView.setVisibility(View.VISIBLE);
Josh Gargusb8f11b92011-11-17 18:32:44 -0800915 if (mTabPager != null) {
916 mTabPager.setVisibility(View.GONE);
917 }
918
Daniel Lehmann52aa32d2012-03-08 17:29:27 -0800919 showEmptyStateForTab(mActionBarAdapter.getCurrentTab());
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800920 }
921
Katherine Kuan8268bbe2011-06-10 17:48:21 -0700922 invalidateOptionsMenuIfNeeded();
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800923 }
924
Dmitri Plotnikov1ce1e7c2010-05-13 16:41:00 -0700925 private final class ContactBrowserActionListener implements OnContactBrowserActionListener {
Chiao Cheng70f77ea2012-05-31 13:33:58 -0700926 ContactBrowserActionListener() {}
Dmitri Plotnikovd9591042010-11-23 09:25:03 -0800927
928 @Override
929 public void onSelectionChange() {
Brian Attwell2c1bfd02014-06-04 18:18:35 -0700930
Dmitri Plotnikovd9591042010-11-23 09:25:03 -0800931 }
932
Daniel Lehmanne20d3432010-10-10 18:37:51 -0700933 @Override
Ricky Waied5202a2015-11-17 18:06:33 +0000934 public void onViewContactAction(Uri contactLookupUri, boolean isEnterpriseContact) {
935 if (isEnterpriseContact) {
936 // No implicit intent as user may have a different contacts app in work profile.
937 QuickContact.showQuickContact(PeopleActivity.this, new Rect(), contactLookupUri,
938 QuickContactActivity.MODE_FULLY_EXPANDED, null);
939 } else {
940 final Intent intent = ImplicitIntentsUtil.composeQuickContactIntent(
941 contactLookupUri,
942 QuickContactActivity.MODE_FULLY_EXPANDED);
943 ImplicitIntentsUtil.startActivityInApp(PeopleActivity.this, intent);
944 }
Dmitri Plotnikov1ce1e7c2010-05-13 16:41:00 -0700945 }
946
Daniel Lehmanne20d3432010-10-10 18:37:51 -0700947 @Override
Dmitri Plotnikov1ce1e7c2010-05-13 16:41:00 -0700948 public void onDeleteContactAction(Uri contactUri) {
Katherine Kuan9856fce2011-06-01 10:24:09 -0700949 ContactDeletionInteraction.start(PeopleActivity.this, contactUri, false);
Dmitri Plotnikov1ce1e7c2010-05-13 16:41:00 -0700950 }
951
Daniel Lehmanne20d3432010-10-10 18:37:51 -0700952 @Override
Dmitri Plotnikov1ce1e7c2010-05-13 16:41:00 -0700953 public void onFinishAction() {
954 onBackPressed();
955 }
Dmitri Plotnikov6e850a02010-10-28 10:46:21 -0700956
957 @Override
958 public void onInvalidSelection() {
Daisuke Miyakawab9225e32011-08-22 14:02:43 -0700959 ContactListFilter filter;
960 ContactListFilter currentFilter = mAllFragment.getFilter();
961 if (currentFilter != null
962 && currentFilter.filterType == ContactListFilter.FILTER_TYPE_SINGLE_CONTACT) {
963 filter = ContactListFilter.createFilterWithType(
964 ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS);
965 mAllFragment.setFilter(filter);
966 } else {
967 filter = ContactListFilter.createFilterWithType(
968 ContactListFilter.FILTER_TYPE_SINGLE_CONTACT);
969 mAllFragment.setFilter(filter, false);
970 }
Dmitri Plotnikovd9591042010-11-23 09:25:03 -0800971 mContactListFilterController.setContactListFilter(filter, true);
Dmitri Plotnikov6e850a02010-10-28 10:46:21 -0700972 }
Dmitri Plotnikov1ce1e7c2010-05-13 16:41:00 -0700973 }
974
Brian Attwell20510ec2015-02-27 16:10:45 -0800975 private final class CheckBoxListListener implements OnCheckBoxListActionListener {
976 @Override
977 public void onStartDisplayingCheckBoxes() {
Brian Attwell865847b2015-04-20 14:40:17 -0700978 mActionBarAdapter.setSelectionMode(true);
979 invalidateOptionsMenu();
Brian Attwell20510ec2015-02-27 16:10:45 -0800980 }
981
982 @Override
983 public void onSelectedContactIdsChanged() {
984 mActionBarAdapter.setSelectionCount(mAllFragment.getSelectedContactIds().size());
985 invalidateOptionsMenu();
986 }
Brian Attwell8f8937f2015-03-05 14:07:43 -0800987
988 @Override
989 public void onStopDisplayingCheckBoxes() {
990 mActionBarAdapter.setSelectionMode(false);
991 }
Brian Attwell20510ec2015-02-27 16:10:45 -0800992 }
993
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800994 private class ContactsUnavailableFragmentListener
995 implements OnContactsUnavailableActionListener {
Chiao Cheng70f77ea2012-05-31 13:33:58 -0700996 ContactsUnavailableFragmentListener() {}
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800997
998 @Override
999 public void onCreateNewContactAction() {
Brian Attwellc6100ff2015-02-19 21:35:36 -08001000 ImplicitIntentsUtil.startActivityInApp(PeopleActivity.this,
Walter Jang5a7a23b2015-03-06 10:54:26 -08001001 EditorIntents.createCompactInsertContactIntent());
Dmitri Plotnikov8b826462010-11-17 14:52:24 -08001002 }
1003
1004 @Override
1005 public void onAddAccountAction() {
guanxiongliu5d7bb262016-01-29 16:43:45 -08001006 final Intent intent = ImplicitIntentsUtil.getIntentForAddingAccount();
Brian Attwellc6100ff2015-02-19 21:35:36 -08001007 ImplicitIntentsUtil.startActivityOutsideApp(PeopleActivity.this, intent);
Dmitri Plotnikov8b826462010-11-17 14:52:24 -08001008 }
1009
1010 @Override
1011 public void onImportContactsFromFileAction() {
Wenyi Wang9379f4a2015-09-25 10:30:19 -07001012 showImportExportDialogFragment();
Dmitri Plotnikov8b826462010-11-17 14:52:24 -08001013 }
Dmitri Plotnikov8b826462010-11-17 14:52:24 -08001014 }
1015
Daisuke Miyakawaee179472011-06-25 11:23:01 -07001016 private final class StrequentContactListFragmentListener
Frank Sposaro7979ea22011-07-14 16:46:07 -07001017 implements ContactTileListFragment.Listener {
Chiao Cheng70f77ea2012-05-31 13:33:58 -07001018 StrequentContactListFragmentListener() {}
1019
Daisuke Miyakawaee179472011-06-25 11:23:01 -07001020 @Override
Katherine Kuan7a700cf2011-10-27 15:49:18 -07001021 public void onContactSelected(Uri contactUri, Rect targetRect) {
Brian Attwellc6100ff2015-02-19 21:35:36 -08001022 final Intent intent = ImplicitIntentsUtil.composeQuickContactIntent(contactUri,
1023 QuickContactActivity.MODE_FULLY_EXPANDED);
1024 ImplicitIntentsUtil.startActivityInApp(PeopleActivity.this, intent);
Daisuke Miyakawaee179472011-06-25 11:23:01 -07001025 }
Josh Gargus4e05a292012-01-03 15:49:08 -08001026
1027 @Override
1028 public void onCallNumberDirectly(String phoneNumber) {
1029 // No need to call phone number directly from People app.
1030 Log.w(TAG, "unexpected invocation of onCallNumberDirectly()");
1031 }
Daisuke Miyakawaee179472011-06-25 11:23:01 -07001032 }
1033
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -08001034 @Override
1035 public boolean onCreateOptionsMenu(Menu menu) {
Makoto Onuki946070f2011-08-09 18:15:33 -07001036 if (!areContactsAvailable()) {
1037 // If contacts aren't available, hide all menu items.
1038 return false;
1039 }
Jeff Sharkeyd9798ae2009-08-24 20:46:23 -07001040 super.onCreateOptionsMenu(menu);
1041
Dmitri Plotnikovd3758b02010-06-17 11:34:59 -07001042 MenuInflater inflater = getMenuInflater();
Daisuke Miyakawa18e0cab2011-11-21 13:06:10 -08001043 inflater.inflate(R.menu.people_options, menu);
Katherine Kuan971116e2011-07-04 15:14:35 -07001044
Katherine Kuanb5760b92011-06-01 16:19:40 -07001045 return true;
Jeff Sharkeyd9798ae2009-08-24 20:46:23 -07001046 }
Jeff Sharkey3f0b7b82009-08-12 11:28:53 -07001047
Katherine Kuan8268bbe2011-06-10 17:48:21 -07001048 private void invalidateOptionsMenuIfNeeded() {
Dmitri Plotnikov0cd01302010-12-17 18:41:57 -08001049 if (isOptionsMenuChanged()) {
Katherine Kuan8268bbe2011-06-10 17:48:21 -07001050 invalidateOptionsMenu();
Dmitri Plotnikov0cd01302010-12-17 18:41:57 -08001051 }
1052 }
1053
1054 public boolean isOptionsMenuChanged() {
1055 if (mOptionsMenuContactsAvailable != areContactsAvailable()) {
1056 return true;
1057 }
1058
Daisuke Miyakawa95c5c2a2011-07-08 10:33:21 -07001059 if (mAllFragment != null && mAllFragment.isOptionsMenuChanged()) {
Dmitri Plotnikov0cd01302010-12-17 18:41:57 -08001060 return true;
1061 }
1062
Dmitri Plotnikov0cd01302010-12-17 18:41:57 -08001063 return false;
1064 }
1065
1066 @Override
Jeff Sharkeyd9798ae2009-08-24 20:46:23 -07001067 public boolean onPrepareOptionsMenu(Menu menu) {
Dmitri Plotnikov0cd01302010-12-17 18:41:57 -08001068 mOptionsMenuContactsAvailable = areContactsAvailable();
1069 if (!mOptionsMenuContactsAvailable) {
Dmitri Plotnikov8b826462010-11-17 14:52:24 -08001070 return false;
1071 }
1072
Maurice Chu2fc4de32012-04-23 17:05:45 -07001073 // Get references to individual menu items in the menu
Isaac Katzenelson789bc592011-07-20 16:00:21 -07001074 final MenuItem contactsFilterMenu = menu.findItem(R.id.menu_contacts_filter);
Maurice Chu2fc4de32012-04-23 17:05:45 -07001075 final MenuItem clearFrequentsMenu = menu.findItem(R.id.menu_clear_frequents);
Brian Attwell8bb3d1e2014-05-15 21:55:02 +00001076 final MenuItem helpMenu = menu.findItem(R.id.menu_help);
Maurice Chu2fc4de32012-04-23 17:05:45 -07001077
Brian Attwell20510ec2015-02-27 16:10:45 -08001078 final boolean isSearchOrSelectionMode = mActionBarAdapter.isSearchMode()
1079 || mActionBarAdapter.isSelectionMode();
1080 if (isSearchOrSelectionMode) {
Isaac Katzenelson683b57e2011-07-20 17:06:11 -07001081 contactsFilterMenu.setVisible(false);
Maurice Chu2fc4de32012-04-23 17:05:45 -07001082 clearFrequentsMenu.setVisible(false);
Brian Attwell8bb3d1e2014-05-15 21:55:02 +00001083 helpMenu.setVisible(false);
Katherine Kuan8268bbe2011-06-10 17:48:21 -07001084 } else {
Brian Attwell92037882014-10-16 18:24:44 -07001085 switch (getTabPositionForTextDirection(mActionBarAdapter.getCurrentTab())) {
Daniel Lehmann52aa32d2012-03-08 17:29:27 -08001086 case TabState.FAVORITES:
Isaac Katzenelson683b57e2011-07-20 17:06:11 -07001087 contactsFilterMenu.setVisible(false);
Maurice Chu2fc4de32012-04-23 17:05:45 -07001088 clearFrequentsMenu.setVisible(hasFrequents());
Isaac Katzenelson683b57e2011-07-20 17:06:11 -07001089 break;
Daniel Lehmann52aa32d2012-03-08 17:29:27 -08001090 case TabState.ALL:
Isaac Katzenelson683b57e2011-07-20 17:06:11 -07001091 contactsFilterMenu.setVisible(true);
Maurice Chu2fc4de32012-04-23 17:05:45 -07001092 clearFrequentsMenu.setVisible(false);
Katherine Kuan8268bbe2011-06-10 17:48:21 -07001093 break;
Katherine Kuan8268bbe2011-06-10 17:48:21 -07001094 }
Brian Attwell56bcc2f2015-02-12 23:45:27 +00001095 helpMenu.setVisible(HelpUtils.isHelpAndFeedbackAvailable());
Katherine Kuan8268bbe2011-06-10 17:48:21 -07001096 }
Brian Attwell20510ec2015-02-27 16:10:45 -08001097 final boolean showMiscOptions = !isSearchOrSelectionMode;
Makoto Onukiaf0a9d42011-08-09 17:58:41 -07001098 makeMenuItemVisible(menu, R.id.menu_search, showMiscOptions);
1099 makeMenuItemVisible(menu, R.id.menu_import_export, showMiscOptions);
1100 makeMenuItemVisible(menu, R.id.menu_accounts, showMiscOptions);
Wenyi Wang5fe95572016-02-10 16:20:40 -08001101 // TODO make menu_blocked_numbers visible by using UI in framework
1102 makeMenuItemVisible(menu, R.id.menu_blocked_numbers, false);
Makoto Onukiaf0a9d42011-08-09 17:58:41 -07001103 makeMenuItemVisible(menu, R.id.menu_settings,
1104 showMiscOptions && !ContactsPreferenceActivity.isEmpty(this));
Dmitri Plotnikova053d612010-11-23 13:31:10 -08001105
Brian Attwell20510ec2015-02-27 16:10:45 -08001106 final boolean showSelectedContactOptions = mActionBarAdapter.isSelectionMode()
1107 && mAllFragment.getSelectedContactIds().size() != 0;
1108 makeMenuItemVisible(menu, R.id.menu_share, showSelectedContactOptions);
1109 makeMenuItemVisible(menu, R.id.menu_delete, showSelectedContactOptions);
Wenyi Wang687d2182015-10-28 17:03:18 -07001110 final boolean showLinkContactsOptions = mActionBarAdapter.isSelectionMode()
1111 && mAllFragment.getSelectedContactIds().size() > 1;
1112 makeMenuItemVisible(menu, R.id.menu_join, showLinkContactsOptions);
Brian Attwell20510ec2015-02-27 16:10:45 -08001113
Makoto Onuki9ae60412012-07-19 15:56:41 -07001114 // Debug options need to be visible even in search mode.
Wenyi Wang2f09e602015-10-28 11:34:23 -07001115 makeMenuItemVisible(menu, R.id.export_database, mEnableDebugMenuOptions &&
1116 hasExportIntentHandler());
Makoto Onuki9ae60412012-07-19 15:56:41 -07001117
Dmitri Plotnikov0cd01302010-12-17 18:41:57 -08001118 return true;
1119 }
1120
Wenyi Wang2f09e602015-10-28 11:34:23 -07001121 private boolean hasExportIntentHandler() {
1122 final Intent intent = new Intent();
1123 intent.setAction("com.android.providers.contacts.DUMP_DATABASE");
1124 final List<ResolveInfo> receivers = getPackageManager().queryIntentActivities(intent,
1125 PackageManager.MATCH_DEFAULT_ONLY);
1126 return receivers != null && receivers.size() > 0;
1127 }
1128
Maurice Chu2fc4de32012-04-23 17:05:45 -07001129 /**
1130 * Returns whether there are any frequently contacted people being displayed
1131 * @return
1132 */
1133 private boolean hasFrequents() {
Brian Attwell2c1bfd02014-06-04 18:18:35 -07001134 return mFavoritesFragment.hasFrequents();
Maurice Chu2fc4de32012-04-23 17:05:45 -07001135 }
1136
Makoto Onukiaf0a9d42011-08-09 17:58:41 -07001137 private void makeMenuItemVisible(Menu menu, int itemId, boolean visible) {
Brian Attwelld3946ca2015-03-03 11:13:49 -08001138 final MenuItem item = menu.findItem(itemId);
Makoto Onukiaf0a9d42011-08-09 17:58:41 -07001139 if (item != null) {
1140 item.setVisible(visible);
1141 }
1142 }
1143
Brian Attwelld3946ca2015-03-03 11:13:49 -08001144 private void makeMenuItemEnabled(Menu menu, int itemId, boolean visible) {
1145 final MenuItem item = menu.findItem(itemId);
1146 if (item != null) {
1147 item.setEnabled(visible);
1148 }
1149 }
1150
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -08001151 @Override
1152 public boolean onOptionsItemSelected(MenuItem item) {
Paul Sliwowski32791d42013-09-11 15:25:43 -07001153 if (mDisableOptionItemSelected) {
1154 return false;
1155 }
1156
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -08001157 switch (item.getItemId()) {
Makoto Onukie0c66af2011-07-13 14:24:03 -07001158 case android.R.id.home: {
1159 // The home icon on the action bar is pressed
1160 if (mActionBarAdapter.isUpShowing()) {
1161 // "UP" icon press -- should be treated as "back".
1162 onBackPressed();
1163 }
1164 return true;
1165 }
Dmitri Plotnikovc85ad182010-09-17 18:12:49 -07001166 case R.id.menu_settings: {
Wenyi Wang86f2a862015-12-30 16:54:51 -08001167 startActivity(new Intent(this, ContactsPreferenceActivity.class));
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -08001168 return true;
Jeff Sharkeyd9798ae2009-08-24 20:46:23 -07001169 }
Katherine Kuanb5760b92011-06-01 16:19:40 -07001170 case R.id.menu_contacts_filter: {
Josh Gargusb6553452012-01-04 14:50:56 -08001171 AccountFilterUtil.startAccountFilterActivityForResult(
1172 this, SUBACTIVITY_ACCOUNT_FILTER,
1173 mContactListFilterController.getFilter());
Katherine Kuanb5760b92011-06-01 16:19:40 -07001174 return true;
1175 }
Jeff Sharkeyd9798ae2009-08-24 20:46:23 -07001176 case R.id.menu_search: {
Dmitri Plotnikov8e86b752010-02-22 17:47:57 -08001177 onSearchRequested();
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -08001178 return true;
Jeff Sharkeyd9798ae2009-08-24 20:46:23 -07001179 }
Brian Attwell20510ec2015-02-27 16:10:45 -08001180 case R.id.menu_share:
1181 shareSelectedContacts();
1182 return true;
Brian Attwelld3946ca2015-03-03 11:13:49 -08001183 case R.id.menu_join:
1184 joinSelectedContacts();
1185 return true;
Brian Attwelld2962a32015-03-02 14:48:50 -08001186 case R.id.menu_delete:
1187 deleteSelectedContacts();
1188 return true;
Jeff Sharkey49d17b32009-09-07 02:14:21 -07001189 case R.id.menu_import_export: {
Wenyi Wang9379f4a2015-09-25 10:30:19 -07001190 showImportExportDialogFragment();
Jeff Sharkeyd9798ae2009-08-24 20:46:23 -07001191 return true;
1192 }
Maurice Chu2fc4de32012-04-23 17:05:45 -07001193 case R.id.menu_clear_frequents: {
1194 ClearFrequentsDialog.show(getFragmentManager());
1195 return true;
1196 }
Brian Attwell56bcc2f2015-02-12 23:45:27 +00001197 case R.id.menu_help:
1198 HelpUtils.launchHelpAndFeedbackForMainScreen(this);
1199 return true;
Jeff Sharkeyd9798ae2009-08-24 20:46:23 -07001200 case R.id.menu_accounts: {
1201 final Intent intent = new Intent(Settings.ACTION_SYNC_SETTINGS);
Dmitri Plotnikovfe42e552010-05-14 14:50:32 -07001202 intent.putExtra(Settings.EXTRA_AUTHORITIES, new String[] {
Jeff Sharkeyd9798ae2009-08-24 20:46:23 -07001203 ContactsContract.AUTHORITY
1204 });
Dmitri Plotnikov1fbcbd12011-01-16 18:09:09 -08001205 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
Brian Attwellc6100ff2015-02-19 21:35:36 -08001206 ImplicitIntentsUtil.startActivityInAppIfPossible(this, intent);
Jeff Sharkeyd9798ae2009-08-24 20:46:23 -07001207 return true;
1208 }
Wenyi Wang1fc3ef42016-01-14 18:21:40 -08001209 case R.id.menu_blocked_numbers: {
Wenyi Wang1fc3ef42016-01-14 18:21:40 -08001210 return true;
1211 }
Makoto Onuki9ae60412012-07-19 15:56:41 -07001212 case R.id.export_database: {
1213 final Intent intent = new Intent("com.android.providers.contacts.DUMP_DATABASE");
1214 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
Brian Attwellc6100ff2015-02-19 21:35:36 -08001215 ImplicitIntentsUtil.startActivityOutsideApp(this, intent);
Makoto Onuki9ae60412012-07-19 15:56:41 -07001216 return true;
1217 }
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -08001218 }
1219 return false;
1220 }
1221
Wenyi Wang9379f4a2015-09-25 10:30:19 -07001222 private void showImportExportDialogFragment(){
1223 final boolean isOnFavoriteTab = mTabPagerAdapter.mCurrentPrimaryItem == mFavoritesFragment;
1224 if (isOnFavoriteTab) {
1225 ImportExportDialogFragment.show(getFragmentManager(), areContactsAvailable(),
1226 PeopleActivity.class, ImportExportDialogFragment.EXPORT_MODE_FAVORITES);
1227 } else {
1228 ImportExportDialogFragment.show(getFragmentManager(), areContactsAvailable(),
1229 PeopleActivity.class, ImportExportDialogFragment.EXPORT_MODE_ALL_CONTACTS);
1230 }
1231 }
1232
Dmitri Plotnikov8e86b752010-02-22 17:47:57 -08001233 @Override
Makoto Onuki53b427b2011-07-17 11:42:32 -07001234 public boolean onSearchRequested() { // Search key pressed.
Brian Attwell20510ec2015-02-27 16:10:45 -08001235 if (!mActionBarAdapter.isSelectionMode()) {
1236 mActionBarAdapter.setSearchMode(true);
1237 }
Makoto Onuki53b427b2011-07-17 11:42:32 -07001238 return true;
Dmitri Plotnikovdb3d1432010-02-09 17:45:47 -08001239 }
1240
Brian Attwell20510ec2015-02-27 16:10:45 -08001241 /**
1242 * Share all contacts that are currently selected in mAllFragment. This method is pretty
1243 * inefficient for handling large numbers of contacts. I don't expect this to be a problem.
1244 */
1245 private void shareSelectedContacts() {
1246 final StringBuilder uriListBuilder = new StringBuilder();
Brian Attwell20510ec2015-02-27 16:10:45 -08001247 for (Long contactId : mAllFragment.getSelectedContactIds()) {
Brian Attwell20510ec2015-02-27 16:10:45 -08001248 final Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
1249 final Uri lookupUri = Contacts.getLookupUri(getContentResolver(), contactUri);
Jay Shrauner5b691252015-08-24 16:26:39 -07001250 if (lookupUri == null) {
1251 continue;
1252 }
1253 final List<String> pathSegments = lookupUri.getPathSegments();
1254 if (pathSegments.size() < 2) {
1255 continue;
1256 }
1257 final String lookupKey = pathSegments.get(pathSegments.size() - 2);
1258 if (uriListBuilder.length() > 0) {
1259 uriListBuilder.append(':');
1260 }
1261 uriListBuilder.append(Uri.encode(lookupKey));
1262 }
1263 if (uriListBuilder.length() == 0) {
1264 return;
Brian Attwell20510ec2015-02-27 16:10:45 -08001265 }
1266 final Uri uri = Uri.withAppendedPath(
1267 Contacts.CONTENT_MULTI_VCARD_URI,
1268 Uri.encode(uriListBuilder.toString()));
1269 final Intent intent = new Intent(Intent.ACTION_SEND);
1270 intent.setType(Contacts.CONTENT_VCARD_TYPE);
1271 intent.putExtra(Intent.EXTRA_STREAM, uri);
1272 ImplicitIntentsUtil.startActivityOutsideApp(this, intent);
1273 }
Walter Janga84fe612016-01-13 16:49:04 -08001274
Brian Attwelld3946ca2015-03-03 11:13:49 -08001275 private void joinSelectedContacts() {
1276 JoinContactsDialogFragment.start(this, mAllFragment.getSelectedContactIds());
1277 }
1278
1279 @Override
1280 public void onContactsJoined() {
Brian Attwell1154bba2015-03-03 14:59:05 -08001281 mActionBarAdapter.setSelectionMode(false);
Brian Attwelld3946ca2015-03-03 11:13:49 -08001282 }
1283
Brian Attwelld2962a32015-03-02 14:48:50 -08001284 private void deleteSelectedContacts() {
1285 ContactMultiDeletionInteraction.start(PeopleActivity.this,
1286 mAllFragment.getSelectedContactIds());
1287 }
1288
1289 @Override
1290 public void onDeletionFinished() {
Brian Attwell1154bba2015-03-03 14:59:05 -08001291 mActionBarAdapter.setSelectionMode(false);
Brian Attwelld2962a32015-03-02 14:48:50 -08001292 }
1293
Jeff Sharkey49d17b32009-09-07 02:14:21 -07001294 @Override
Dmitri Plotnikovd3758b02010-06-17 11:34:59 -07001295 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
1296 switch (requestCode) {
Daisuke Miyakawa34b901c2011-10-18 14:33:41 -07001297 case SUBACTIVITY_ACCOUNT_FILTER: {
1298 AccountFilterUtil.handleAccountFilterResult(
1299 mContactListFilterController, resultCode, data);
Katherine Kuan495db432011-07-06 18:58:46 -07001300 break;
1301 }
Dmitri Plotnikovd3758b02010-06-17 11:34:59 -07001302
Daniel Lehmann7aa9b282010-07-27 20:33:27 -07001303 // TODO: Using the new startActivityWithResultFromFragment API this should not be needed
1304 // anymore
Dmitri Plotnikove8a95172010-06-23 16:18:10 -07001305 case ContactEntryListFragment.ACTIVITY_REQUEST_CODE_PICKER:
Dmitri Plotnikovd3758b02010-06-17 11:34:59 -07001306 if (resultCode == RESULT_OK) {
Daisuke Miyakawa95c5c2a2011-07-08 10:33:21 -07001307 mAllFragment.onPickerResult(data);
Dmitri Plotnikovd3758b02010-06-17 11:34:59 -07001308 }
1309
1310// TODO fix or remove multipicker code
1311// else if (resultCode == RESULT_CANCELED && mMode == MODE_PICK_MULTIPLE_PHONES) {
Dmitri Plotnikov1ce1e7c2010-05-13 16:41:00 -07001312// // Finish the activity if the sub activity was canceled as back key is used
1313// // to confirm user selection in MODE_PICK_MULTIPLE_PHONES.
1314// finish();
1315// }
1316// break;
Dmitri Plotnikovd3758b02010-06-17 11:34:59 -07001317 }
1318 }
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -08001319
1320 @Override
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -08001321 public boolean onKeyDown(int keyCode, KeyEvent event) {
Dmitri Plotnikov1ce1e7c2010-05-13 16:41:00 -07001322 // TODO move to the fragment
Dmitri Plotnikovdb3d1432010-02-09 17:45:47 -08001323
Brian Attwell20510ec2015-02-27 16:10:45 -08001324 // Bring up the search UI if the user starts typing
1325 final int unicodeChar = event.getUnicodeChar();
1326 if ((unicodeChar != 0)
1327 // If COMBINING_ACCENT is set, it's not a unicode character.
1328 && ((unicodeChar & KeyCharacterMap.COMBINING_ACCENT) == 0)
1329 && !Character.isWhitespace(unicodeChar)) {
1330 if (mActionBarAdapter.isSelectionMode()) {
1331 // Ignore keyboard input when in selection mode.
1332 return true;
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -08001333 }
Brian Attwell20510ec2015-02-27 16:10:45 -08001334 String query = new String(new int[]{unicodeChar}, 0, 1);
1335 if (!mActionBarAdapter.isSearchMode()) {
1336 mActionBarAdapter.setSearchMode(true);
1337 mActionBarAdapter.setQueryString(query);
1338 return true;
Daniel Lehmann7bb2add2010-07-14 21:15:17 -07001339 }
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -08001340 }
1341
1342 return super.onKeyDown(keyCode, event);
1343 }
1344
Dmitri Plotnikovab4d29f2010-10-28 12:43:54 -07001345 @Override
1346 public void onBackPressed() {
Jay Shrauner7712aef2015-09-25 14:14:28 -07001347 if (!isSafeToCommitTransactions()) {
Jay Shraunerc3fdc8f2015-09-16 10:29:52 -07001348 return;
1349 }
1350
Brian Attwell20510ec2015-02-27 16:10:45 -08001351 if (mActionBarAdapter.isSelectionMode()) {
1352 mActionBarAdapter.setSelectionMode(false);
1353 mAllFragment.displayCheckBoxes(false);
1354 } else if (mActionBarAdapter.isSearchMode()) {
Dmitri Plotnikovab4d29f2010-10-28 12:43:54 -07001355 mActionBarAdapter.setSearchMode(false);
Walter Janga84fe612016-01-13 16:49:04 -08001356
1357 if (mAllFragment.wasSearchResultClicked()) {
1358 mAllFragment.resetSearchResultClicked();
1359 } else {
1360 Logger.getInstance().logScreenView(
1361 ScreenEvent.SEARCH_EXIT, this, ScreenEvent.TAG_SEARCH_EXIT);
1362 Logger.getInstance().logSearchEventImpl(mAllFragment.createSearchState());
1363 }
Dmitri Plotnikovab4d29f2010-10-28 12:43:54 -07001364 } else {
1365 super.onBackPressed();
1366 }
1367 }
1368
Dmitri Plotnikov08e1c4e2010-07-02 17:57:51 -07001369 @Override
1370 protected void onSaveInstanceState(Bundle outState) {
1371 super.onSaveInstanceState(outState);
Makoto Onuki4d788fc2011-07-12 10:00:10 -07001372 mActionBarAdapter.onSaveInstanceState(outState);
Makoto Onuki4d788fc2011-07-12 10:00:10 -07001373
1374 // Clear the listener to make sure we don't get callbacks after onSaveInstanceState,
1375 // in order to avoid doing fragment transactions after it.
1376 // TODO Figure out a better way to deal with the issue.
Paul Sliwowski32791d42013-09-11 15:25:43 -07001377 mDisableOptionItemSelected = true;
Makoto Onuki4d788fc2011-07-12 10:00:10 -07001378 mActionBarAdapter.setListener(null);
Makoto Onuki2e177302011-08-15 14:06:55 -07001379 if (mTabPager != null) {
1380 mTabPager.setOnPageChangeListener(null);
1381 }
Dmitri Plotnikov08e1c4e2010-07-02 17:57:51 -07001382 }
1383
Dmitri Plotnikovfa49a662011-01-13 11:04:56 -08001384 @Override
Daniel Lehmann09d66a32012-04-13 19:14:39 -07001385 protected void onRestoreInstanceState(Bundle savedInstanceState) {
1386 super.onRestoreInstanceState(savedInstanceState);
1387 // In our own lifecycle, the focus is saved and restore but later taken away by the
1388 // ViewPager. As a hack, we force focus on the SearchView if we know that we are searching.
1389 // This fixes the keyboard going away on screen rotation
1390 if (mActionBarAdapter.isSearchMode()) {
1391 mActionBarAdapter.setFocusOnSearchView();
1392 }
1393 }
1394
1395 @Override
Daniel Lehmann3391dbe2010-07-12 09:50:22 -07001396 public DialogManager getDialogManager() {
1397 return mDialogManager;
1398 }
Dmitri Plotnikovab75f822011-01-10 11:21:59 -08001399
Paul Soulos2b9563d2014-05-27 16:21:23 -07001400 @Override
1401 public void onClick(View view) {
1402 switch (view.getId()) {
1403 case R.id.floating_action_button:
1404 Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
1405 Bundle extras = getIntent().getExtras();
1406 if (extras != null) {
1407 intent.putExtras(extras);
1408 }
Jay Shraunerd391f842014-11-26 11:14:24 -08001409 try {
Brian Attwellc6100ff2015-02-19 21:35:36 -08001410 ImplicitIntentsUtil.startActivityInApp(PeopleActivity.this, intent);
Jay Shraunerd391f842014-11-26 11:14:24 -08001411 } catch (ActivityNotFoundException ex) {
1412 Toast.makeText(PeopleActivity.this, R.string.missing_app,
1413 Toast.LENGTH_SHORT).show();
1414 }
Paul Soulos2b9563d2014-05-27 16:21:23 -07001415 break;
1416 default:
1417 Log.wtf(TAG, "Unexpected onClick event from " + view);
1418 }
1419 }
Brian Attwell962677f2014-09-26 12:29:07 -07001420
1421 /**
1422 * Returns the tab position adjusted for the text direction.
1423 */
1424 private int getTabPositionForTextDirection(int position) {
1425 if (isRTL()) {
1426 return TabState.COUNT - 1 - position;
1427 }
1428 return position;
1429 }
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -08001430}