blob: 112fa1b931511d4f5611d504d8b4fff3b7dd7b84 [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
Wenyi Wang917cb4a2016-12-13 17:42:18 -080019import android.accounts.Account;
Chiao Chenge0b2f1e2012-06-12 13:07:56 -070020import android.app.Fragment;
21import android.app.FragmentManager;
22import android.app.FragmentTransaction;
Marcus Hagerottbea2b852016-08-11 14:55:52 -070023import android.content.BroadcastReceiver;
John Shao52dd5d72016-10-06 15:16:14 -070024import android.content.ContentResolver;
Marcus Hagerottd6d5ad52016-10-25 19:25:38 -070025import android.content.ContentUris;
Marcus Hagerottbea2b852016-08-11 14:55:52 -070026import android.content.Context;
Chiao Chenge0b2f1e2012-06-12 13:07:56 -070027import android.content.Intent;
Marcus Hagerottbea2b852016-08-11 14:55:52 -070028import android.content.IntentFilter;
John Shao52dd5d72016-10-06 15:16:14 -070029import android.content.SyncStatusObserver;
Wenyi Wang917cb4a2016-12-13 17:42:18 -080030import android.content.res.Configuration;
31import android.graphics.Color;
Chiao Chenge0b2f1e2012-06-12 13:07:56 -070032import android.net.Uri;
33import android.os.Bundle;
Xi Chen4a7a9ea2016-07-20 11:23:30 -070034import android.os.Handler;
Marcus Hagerottd6d5ad52016-10-25 19:25:38 -070035import android.provider.ContactsContract;
Wenyi Wang917cb4a2016-12-13 17:42:18 -080036import android.provider.ContactsContract.Intents;
Chiao Chenge0b2f1e2012-06-12 13:07:56 -070037import android.provider.ContactsContract.ProviderStatus;
Aravind Sreekumar71212852018-04-06 15:47:45 -070038import androidx.annotation.LayoutRes;
39import androidx.coordinatorlayout.widget.CoordinatorLayout;
Aurimas Liutikas1f8811c2019-01-30 21:39:48 -080040import com.google.android.material.snackbar.Snackbar;
Aravind Sreekumar71212852018-04-06 15:47:45 -070041import androidx.core.content.ContextCompat;
42import androidx.localbroadcastmanager.content.LocalBroadcastManager;
43import androidx.core.view.GravityCompat;
44import androidx.drawerlayout.widget.DrawerLayout;
45import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
46import androidx.appcompat.app.ActionBarDrawerToggle;
47import androidx.appcompat.app.AppCompatActivity;
48import androidx.appcompat.widget.Toolbar;
Chiao Chenge0b2f1e2012-06-12 13:07:56 -070049import android.util.Log;
50import android.view.KeyCharacterMap;
51import android.view.KeyEvent;
Wenyi Wang917cb4a2016-12-13 17:42:18 -080052import android.view.LayoutInflater;
Chiao Chenge0b2f1e2012-06-12 13:07:56 -070053import android.view.View;
Wenyi Wang917cb4a2016-12-13 17:42:18 -080054import android.view.ViewGroup;
Wenyi Wang32912eb2016-09-29 17:17:07 -070055import android.view.accessibility.AccessibilityEvent;
James Laskey6b712bc2016-11-22 11:02:09 -080056import android.view.accessibility.AccessibilityManager;
Paul Soulos2b9563d2014-05-27 16:21:23 -070057import android.widget.ImageButton;
Jay Shraunerd391f842014-11-26 11:14:24 -080058import android.widget.Toast;
Chiao Chenge0b2f1e2012-06-12 13:07:56 -070059
Wenyi Wang917cb4a2016-12-13 17:42:18 -080060import com.android.contacts.AppCompatContactsActivity;
Cody Thomasf32dc992016-05-11 10:56:04 -070061import com.android.contacts.ContactSaveService;
Dmitri Plotnikov27834b22010-07-01 14:10:08 -070062import com.android.contacts.R;
Gary Mai69c182a2016-12-05 13:07:03 -080063import com.android.contacts.compat.CompatUtils;
Wenyi Wang2829deb2017-01-04 14:05:13 -080064import com.android.contacts.drawer.DrawerFragment;
65import com.android.contacts.drawer.DrawerFragment.DrawerFragmentListener;
Wenyi Wang917cb4a2016-12-13 17:42:18 -080066import com.android.contacts.editor.ContactEditorFragment;
67import com.android.contacts.editor.SelectAccountDialogFragment;
68import com.android.contacts.group.GroupListItem;
Gary Mai0a49afa2016-12-05 15:53:58 -080069import com.android.contacts.group.GroupMembersFragment;
Wenyi Wang917cb4a2016-12-13 17:42:18 -080070import com.android.contacts.group.GroupNameEditDialogFragment;
Gary Mai0a49afa2016-12-05 15:53:58 -080071import com.android.contacts.group.GroupUtil;
Wenyi Wang917cb4a2016-12-13 17:42:18 -080072import com.android.contacts.list.AccountFilterActivity;
Gary Mai69c182a2016-12-05 13:07:03 -080073import com.android.contacts.list.ContactListFilter;
Wenyi Wang917cb4a2016-12-13 17:42:18 -080074import com.android.contacts.list.ContactListFilterController;
Gary Mai69c182a2016-12-05 13:07:03 -080075import com.android.contacts.list.ContactListFilterController.ContactListFilterListener;
Gary Mai0a49afa2016-12-05 15:53:58 -080076import com.android.contacts.list.ContactsIntentResolver;
77import com.android.contacts.list.ContactsRequest;
78import com.android.contacts.list.ContactsUnavailableFragment;
79import com.android.contacts.list.DefaultContactBrowseListFragment;
Wenyi Wang917cb4a2016-12-13 17:42:18 -080080import com.android.contacts.list.MultiSelectContactsListFragment;
Gary Mai69c182a2016-12-05 13:07:03 -080081import com.android.contacts.list.ProviderStatusWatcher;
82import com.android.contacts.list.ProviderStatusWatcher.ProviderStatusListener;
83import com.android.contacts.logging.Logger;
84import com.android.contacts.logging.ScreenEvent.ScreenType;
85import com.android.contacts.model.AccountTypeManager;
Marcus Hagerott75895e72016-12-12 17:21:57 -080086import com.android.contacts.model.account.AccountInfo;
Gary Mai69c182a2016-12-05 13:07:03 -080087import com.android.contacts.model.account.AccountWithDataSet;
Wenyi Wang917cb4a2016-12-13 17:42:18 -080088import com.android.contacts.preference.ContactsPreferenceActivity;
Gary Mai69c182a2016-12-05 13:07:03 -080089import com.android.contacts.util.AccountFilterUtil;
90import com.android.contacts.util.Constants;
91import com.android.contacts.util.ImplicitIntentsUtil;
Wenyi Wang917cb4a2016-12-13 17:42:18 -080092import com.android.contacts.util.MaterialColorMapUtils;
93import com.android.contacts.util.SharedPreferenceUtil;
Xi Chen4a7a9ea2016-07-20 11:23:30 -070094import com.android.contacts.util.SyncUtil;
Wenyi Wang917cb4a2016-12-13 17:42:18 -080095import com.android.contacts.util.ViewUtil;
Gary Mai0a49afa2016-12-05 15:53:58 -080096import com.android.contacts.widget.FloatingActionButtonController;
Wenyi Wangf9905062016-09-14 10:07:59 -070097import com.android.contactsbind.FeatureHighlightHelper;
Wenyi Wang917cb4a2016-12-13 17:42:18 -080098import com.android.contactsbind.HelpUtils;
Wenyi Wang79675452016-08-17 10:43:28 -070099import com.android.contactsbind.ObjectFactory;
Gary Maif6b50e82017-01-26 15:32:49 -0800100
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800101import com.google.common.util.concurrent.Futures;
Tadashi G. Takaoka57cf30f2009-09-21 19:54:39 +0900102
Marcus Hagerott396aab72016-12-12 12:00:21 -0800103import java.util.Collections;
Brian Attwell20510ec2015-02-27 16:10:45 -0800104import java.util.List;
Makoto Onuki6d9befe2011-07-17 11:00:12 -0700105import java.util.concurrent.atomic.AtomicInteger;
Dmitri Plotnikovcaf0bc72010-09-03 15:16:21 -0700106
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800107/**
Brian Attwell2c1bfd02014-06-04 18:18:35 -0700108 * Displays a list to browse contacts.
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800109 */
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800110public class PeopleActivity extends AppCompatContactsActivity implements
Wenyi Wang2829deb2017-01-04 14:05:13 -0800111 DrawerFragmentListener,
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800112 SelectAccountDialogFragment.Listener {
113
114 /** Possible views of Contacts app. */
115 public enum ContactsView {
116 NONE,
117 ALL_CONTACTS,
118 ASSISTANT,
119 GROUP_VIEW,
120 ACCOUNT_VIEW,
121 }
Dmitri Plotnikov57d27da2009-09-28 18:06:11 -0700122
Dave Santoro5e684a42011-06-10 13:23:35 -0700123 private static final String TAG = "PeopleActivity";
Wenyi Wangca6018d2016-08-18 17:23:13 -0700124 private static final String TAG_ALL = "contacts-all";
Wenyi Wang79675452016-08-17 10:43:28 -0700125 private static final String TAG_UNAVAILABLE = "contacts-unavailable";
Wenyi Wangcc8f2722016-09-07 14:52:32 -0700126 private static final String TAG_GROUP_VIEW = "contacts-groups";
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800127 private static final String TAG_SELECT_ACCOUNT_DIALOG = "selectAccountDialog";
128 private static final String TAG_GROUP_NAME_EDIT_DIALOG = "groupNameEditDialog";
129
John Shao52dd5d72016-10-06 15:16:14 -0700130 public static final String TAG_ASSISTANT = "contacts-assistant";
131 public static final String TAG_SECOND_LEVEL = "second-level";
132 public static final String TAG_THIRD_LEVEL = "third-level";
Gary Maif6b50e82017-01-26 15:32:49 -0800133 public static final String TAG_ASSISTANT_HELPER = "assistant-helper";
John Shao52dd5d72016-10-06 15:16:14 -0700134 public static final String TAG_DUPLICATES = "DuplicatesFragment";
Wenyi Wang79675452016-08-17 10:43:28 -0700135 public static final String TAG_DUPLICATES_UTIL = "DuplicatesUtilFragment";
136
137 private static final String KEY_GROUP_URI = "groupUri";
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800138 private static final String KEY_CONTACTS_VIEW = "contactsView";
139 private static final String KEY_NEW_GROUP_ACCOUNT = "newGroupAccount";
140
141 private static final long DRAWER_CLOSE_DELAY = 300L;
Wenyi Wangca6018d2016-08-18 17:23:13 -0700142
Dmitri Plotnikovac0f7832010-04-22 13:26:52 -0700143 private ContactsIntentResolver mIntentResolver;
Dmitri Plotnikovfcfdffb2010-07-15 18:00:55 -0700144 private ContactsRequest mRequest;
Marcus Hagerott396aab72016-12-12 12:00:21 -0800145 private AccountTypeManager mAccountTypeManager;
Dmitri Plotnikovfcfdffb2010-07-15 18:00:55 -0700146
Brian Attwell865847b2015-04-20 14:40:17 -0700147 private FloatingActionButtonController mFloatingActionButtonController;
148 private View mFloatingActionButtonContainer;
149 private boolean wasLastFabAnimationScaleIn = false;
Dmitri Plotnikovfcfdffb2010-07-15 18:00:55 -0700150
Makoto Onukic2bd6132012-04-27 16:14:51 -0700151 private ProviderStatusWatcher mProviderStatusWatcher;
Brian Attwellc3d202c2015-01-08 15:01:03 -0800152 private Integer mProviderStatus;
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800153
Marcus Hagerottbea2b852016-08-11 14:55:52 -0700154 private BroadcastReceiver mSaveServiceListener;
155
Wenyi Wang79675452016-08-17 10:43:28 -0700156 private boolean mShouldSwitchToGroupView;
157
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800158 private ContactsView mCurrentView;
159
Marcus Hagerottbea2b852016-08-11 14:55:52 -0700160 private CoordinatorLayout mLayoutRoot;
161
Daisuke Miyakawa95c5c2a2011-07-08 10:33:21 -0700162 /**
163 * Showing a list of Contacts. Also used for showing search results in search mode.
164 */
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800165 private DefaultContactBrowseListFragment mContactsListFragment;
Katherine Kuanb5760b92011-06-01 16:19:40 -0700166
Wenyi Wang79675452016-08-17 10:43:28 -0700167 private GroupMembersFragment mMembersFragment;
168 private Uri mGroupUri;
Katherine Kuan58fc5772011-07-04 10:08:32 -0700169
Makoto Onuki417ca492011-07-14 19:06:35 -0700170 /**
171 * True if this activity instance is a re-created one. i.e. set true after orientation change.
Makoto Onuki417ca492011-07-14 19:06:35 -0700172 */
173 private boolean mIsRecreatedInstance;
174
Wenyi Wang32912eb2016-09-29 17:17:07 -0700175 private boolean mShouldSwitchToAllContacts;
176
Makoto Onuki6d9befe2011-07-17 11:00:12 -0700177 /** Sequential ID assigned to each instance; used for logging */
178 private final int mInstanceId;
179 private static final AtomicInteger sNextInstanceId = new AtomicInteger();
180
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800181 private ContactListFilterController mContactListFilterController;
Wenyi Wang2829deb2017-01-04 14:05:13 -0800182
183 /** Navigation drawer related */
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800184 private DrawerLayout mDrawerLayout;
Wenyi Wang2829deb2017-01-04 14:05:13 -0800185 private DrawerFragment mDrawerFragment;
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800186 private ContactsActionBarDrawerToggle mToggle;
187 private Toolbar mToolbar;
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800188
189 // The account the new group will be created under.
190 private AccountWithDataSet mNewGroupAccount;
191
Xi Chen4a7a9ea2016-07-20 11:23:30 -0700192 private Object mStatusChangeListenerHandle;
193
194 private final Handler mHandler = new Handler();
195
196 private SyncStatusObserver mSyncStatusObserver = new SyncStatusObserver() {
197 public void onStatusChanged(int which) {
198 mHandler.post(new Runnable() {
199 public void run() {
200 onSyncStateUpdated();
201 }
202 });
203 }
204 };
205
206 // Update sync status for accounts in current ContactListFilter
207 private void onSyncStateUpdated() {
Wenyi Wangde61df72017-01-04 18:00:49 -0800208 if (isListFragmentInSearchMode() || isListFragmentInSelectionMode()) {
Xi Chen4a7a9ea2016-07-20 11:23:30 -0700209 return;
210 }
211
Wenyi Wang32912eb2016-09-29 17:17:07 -0700212 final ContactListFilter filter = mContactListFilterController.getFilter();
Xi Chen4a7a9ea2016-07-20 11:23:30 -0700213 if (filter != null) {
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800214 final SwipeRefreshLayout swipeRefreshLayout =
215 mContactsListFragment.getSwipeRefreshLayout();
Xi Chen4a7a9ea2016-07-20 11:23:30 -0700216 if (swipeRefreshLayout == null) {
217 if (Log.isLoggable(TAG, Log.DEBUG)) {
218 Log.d(TAG, "Can not load swipeRefreshLayout, swipeRefreshLayout is null");
219 }
220 return;
221 }
222
Marcus Hagerott396aab72016-12-12 12:00:21 -0800223 final List<AccountWithDataSet> accounts;
224 if (filter.filterType == ContactListFilter.FILTER_TYPE_ACCOUNT &&
225 filter.isGoogleAccountType()) {
226 accounts = Collections.singletonList(new AccountWithDataSet(filter.accountName,
227 filter.accountType, null));
228 } else if (filter.shouldShowSyncState()) {
Marcus Hagerott75895e72016-12-12 17:21:57 -0800229 accounts = AccountInfo.extractAccounts(
230 mAccountTypeManager.getWritableGoogleAccounts());
Marcus Hagerott396aab72016-12-12 12:00:21 -0800231 } else {
232 accounts = Collections.emptyList();
233 }
234 if (SyncUtil.isAnySyncing(accounts)) {
235 return;
Xi Chen4a7a9ea2016-07-20 11:23:30 -0700236 }
237 swipeRefreshLayout.setRefreshing(false);
238 }
239 }
240
yaolu395c3f82016-10-18 11:13:39 -0700241 public void showConnectionErrorMsg() {
242 Snackbar.make(mLayoutRoot, R.string.connection_error_message, Snackbar.LENGTH_LONG).show();
243 }
244
Wenyi Wang32912eb2016-09-29 17:17:07 -0700245 private final ContactListFilterListener mFilterListener = new ContactListFilterListener() {
246 @Override
247 public void onContactListFilterChanged() {
248 final ContactListFilter filter = mContactListFilterController.getFilter();
249 handleFilterChangeForFragment(filter);
250 handleFilterChangeForActivity(filter);
251 }
252 };
253
254 private final ProviderStatusListener mProviderStatusListener = new ProviderStatusListener() {
255 @Override
256 public void onProviderStatusChange() {
Wenyi Wang2829deb2017-01-04 14:05:13 -0800257 // TODO see if it works with drawer fragment.
Wenyi Wang32912eb2016-09-29 17:17:07 -0700258 updateViewConfiguration(false);
259 }
260 };
261
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800262 private class ContactsActionBarDrawerToggle extends ActionBarDrawerToggle {
263 private boolean mMenuClickedBefore = SharedPreferenceUtil.getHamburgerMenuClickedBefore(
264 PeopleActivity.this);
265
266 public ContactsActionBarDrawerToggle(AppCompatActivity activity, DrawerLayout drawerLayout,
267 Toolbar toolbar, int openDrawerContentDescRes, int closeDrawerContentDescRes) {
268 super(activity, drawerLayout, toolbar, openDrawerContentDescRes,
269 closeDrawerContentDescRes);
270 }
271
272 @Override
273 public void onDrawerOpened(View drawerView) {
274 super.onDrawerOpened(drawerView);
275 if (!mMenuClickedBefore) {
276 SharedPreferenceUtil.setHamburgerMenuClickedBefore(PeopleActivity.this);
277 mMenuClickedBefore = true;
278 }
Wenyi Wanga007a0d2017-03-20 10:41:01 -0700279 drawerView.requestFocus();
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800280 invalidateOptionsMenu();
281 // Stop search and selection mode like Gmail and Keep. Otherwise, if user switches to
282 // another fragment in navigation drawer, the current search/selection mode will be
283 // overlaid by the action bar of the newly-created fragment.
284 stopSearchAndSelection();
285 updateStatusBarBackground();
286 }
287
288 private void stopSearchAndSelection() {
289 final MultiSelectContactsListFragment listFragment;
290 if (isAllContactsView() || isAccountView()) {
Wenyi Wangde61df72017-01-04 18:00:49 -0800291 listFragment = getListFragment();
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800292 } else if (isGroupView()) {
293 listFragment = getGroupFragment();
294 } else {
295 listFragment = null;
296 }
297 if (listFragment == null) {
298 return;
299 }
300 final ActionBarAdapter actionBarAdapter = listFragment.getActionBarAdapter();
301 if (actionBarAdapter == null) {
302 return;
303 }
304 if (actionBarAdapter.isSearchMode()) {
305 actionBarAdapter.setSearchMode(false);
306 } else if (actionBarAdapter.isSelectionMode()) {
307 actionBarAdapter.setSelectionMode(false);
308 }
309 }
310
311 @Override
312 public void onDrawerClosed(View view) {
313 super.onDrawerClosed(view);
314 invalidateOptionsMenu();
315 }
316
317 @Override
318 public void onDrawerStateChanged(int newState) {
319 super.onDrawerStateChanged(newState);
320 // Set transparent status bar when drawer starts to move.
321 if (newState != DrawerLayout.STATE_IDLE) {
322 updateStatusBarBackground();
323 }
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800324 }
325 }
326
327
Katherine Kuan9856fce2011-06-01 10:24:09 -0700328 public PeopleActivity() {
Makoto Onuki6d9befe2011-07-17 11:00:12 -0700329 mInstanceId = sNextInstanceId.getAndIncrement();
Dmitri Plotnikov15406742010-05-07 09:22:49 -0700330 mIntentResolver = new ContactsIntentResolver(this);
Makoto Onukic2bd6132012-04-27 16:14:51 -0700331 mProviderStatusWatcher = ProviderStatusWatcher.getInstance(this);
Dmitri Plotnikov6178cb42010-04-20 11:26:05 -0700332 }
333
Makoto Onuki6d9befe2011-07-17 11:00:12 -0700334 @Override
335 public String toString() {
336 // Shown on logcat
337 return String.format("%s@%d", getClass().getSimpleName(), mInstanceId);
338 }
339
Wenyi Wangcc8f2722016-09-07 14:52:32 -0700340 private boolean areContactsAvailable() {
Wenyi Wang2f09e602015-10-28 11:34:23 -0700341 return (mProviderStatus != null) && mProviderStatus.equals(ProviderStatus.STATUS_NORMAL);
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800342 }
343
Dmitri Plotnikov92a6fdf2010-07-09 13:19:33 -0700344 @Override
Dmitri Plotnikov08e1c4e2010-07-02 17:57:51 -0700345 protected void onCreate(Bundle savedState) {
Makoto Onuki49627cc2011-08-28 13:56:48 -0700346 if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) {
347 Log.d(Constants.PERFORMANCE_TAG, "PeopleActivity.onCreate start");
348 }
yaoluf31d6972017-02-20 23:03:00 -0800349
350 // Make sure this is *before* calling super.onCreate
351 setTheme(R.style.PeopleActivityTheme);
Dmitri Plotnikov08e1c4e2010-07-02 17:57:51 -0700352 super.onCreate(savedState);
yaoluf31d6972017-02-20 23:03:00 -0800353
Marcus Hagerott396aab72016-12-12 12:00:21 -0800354 mAccountTypeManager = AccountTypeManager.getInstance(this);
Gary Mai5a924f32017-01-18 14:32:59 -0800355 mContactListFilterController = ContactListFilterController.getInstance(this);
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800356
Gary Mai1e899dc2017-02-07 15:08:53 -0800357 RequestPermissionsActivity.startPermissionActivityIfNeeded(this);
Brian Attwellbdd32642015-05-08 17:03:15 -0700358
Makoto Onuki6d9befe2011-07-17 11:00:12 -0700359 if (!processIntent(false)) {
Makoto Onuki417ca492011-07-14 19:06:35 -0700360 finish();
361 return;
362 }
Daisuke Miyakawaa012aec2011-10-16 10:24:43 -0700363
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800364 mContactListFilterController.checkFilterValidity(false);
365
366 super.setContentView(R.layout.contacts_drawer_activity);
367
368 // Set up the action bar.
369 mToolbar = getView(R.id.toolbar);
370 setSupportActionBar(mToolbar);
371
372 // Add shadow under toolbar.
373 ViewUtil.addRectangularOutlineProvider(findViewById(R.id.toolbar_parent), getResources());
374
375 // Set up hamburger button.
376 mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
Wenyi Wang2829deb2017-01-04 14:05:13 -0800377 mDrawerFragment = (DrawerFragment) getFragmentManager().findFragmentById(R.id.drawer);
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800378 mToggle = new ContactsActionBarDrawerToggle(this, mDrawerLayout, mToolbar,
379 R.string.navigation_drawer_open, R.string.navigation_drawer_close);
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800380 mDrawerLayout.setDrawerListener(mToggle);
381 // Set fallback handler for when drawer is disabled.
382 mToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
383 @Override
384 public void onClick(View v) {
385 onBackPressed();
386 }
387 });
388
389 // Set up navigation mode.
390 if (savedState != null) {
391 mCurrentView = ContactsView.values()[savedState.getInt(KEY_CONTACTS_VIEW)];
392 } else {
393 mCurrentView = ContactsView.ALL_CONTACTS;
394 }
395
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800396 if (savedState != null && savedState.containsKey(KEY_NEW_GROUP_ACCOUNT)) {
397 mNewGroupAccount = AccountWithDataSet.unstringify(
398 savedState.getString(KEY_NEW_GROUP_ACCOUNT));
399 }
400
Wenyi Wang32912eb2016-09-29 17:17:07 -0700401 mContactListFilterController.addListener(mFilterListener);
402 mProviderStatusWatcher.addListener(mProviderStatusListener);
Makoto Onukic2bd6132012-04-27 16:14:51 -0700403
Makoto Onuki417ca492011-07-14 19:06:35 -0700404 mIsRecreatedInstance = (savedState != null);
Wenyi Wang40e79102016-06-01 20:43:56 -0700405
Wenyi Wang79675452016-08-17 10:43:28 -0700406 if (mIsRecreatedInstance) {
407 mGroupUri = savedState.getParcelable(KEY_GROUP_URI);
408 }
409
Wenyi Wang587b8f22016-08-17 17:40:45 -0700410 createViewsAndFragments();
Andrew Lee4b1af3f2014-04-23 10:23:55 -0700411
Makoto Onuki49627cc2011-08-28 13:56:48 -0700412 if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) {
413 Log.d(Constants.PERFORMANCE_TAG, "PeopleActivity.onCreate finish");
414 }
Sai Cheemalapati5b221082014-06-27 14:45:43 -0700415 getWindow().setBackgroundDrawable(null);
Tingting Wangac9596e2016-08-02 22:24:24 -0700416 }
Tingting Wangdce1e682016-07-28 10:06:29 -0700417
Dmitri Plotnikovfa49a662011-01-13 11:04:56 -0800418 @Override
419 protected void onNewIntent(Intent intent) {
Gary Mai4ac56292016-10-31 10:41:11 -0700420 final String action = intent.getAction();
421 if (GroupUtil.ACTION_CREATE_GROUP.equals(action)) {
Wenyi Wang79675452016-08-17 10:43:28 -0700422 mGroupUri = intent.getData();
423 if (mGroupUri == null) {
424 toast(R.string.groupSavedErrorToast);
425 return;
426 }
427 if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "Received group URI " + mGroupUri);
yaolu9b6159c2016-10-24 23:31:49 -0700428 switchView(ContactsView.GROUP_VIEW);
Gary Mai4ac56292016-10-31 10:41:11 -0700429 mMembersFragment.toastForSaveAction(action);
Walter Jang13710d52016-07-08 14:36:20 -0700430 return;
431 }
432
Gary Mai4ac56292016-10-31 10:41:11 -0700433 if (isGroupSaveAction(action)) {
Wenyi Wangcc8f2722016-09-07 14:52:32 -0700434 mGroupUri = intent.getData();
435 if (mGroupUri == null) {
436 popSecondLevel();
Wenyi Wang79675452016-08-17 10:43:28 -0700437 toast(R.string.groupSavedErrorToast);
438 return;
439 }
Wenyi Wangcc8f2722016-09-07 14:52:32 -0700440 if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "Received group URI " + mGroupUri);
Gary Mai4ac56292016-10-31 10:41:11 -0700441 // ACTION_REMOVE_FROM_GROUP doesn't reload data, so it shouldn't cause b/32223934
442 // but it's necessary to use the previous fragment since
443 // GroupMembersFragment#mIsEditMode needs to be persisted between remove actions.
444 if (GroupUtil.ACTION_REMOVE_FROM_GROUP.equals(action)) {
445 switchToOrUpdateGroupView(action);
446 } else {
447 switchView(ContactsView.GROUP_VIEW);
448 }
449 mMembersFragment.toastForSaveAction(action);
Wenyi Wang79675452016-08-17 10:43:28 -0700450 }
451
Dmitri Plotnikovfa49a662011-01-13 11:04:56 -0800452 setIntent(intent);
Wenyi Wang79675452016-08-17 10:43:28 -0700453
Makoto Onuki6d9befe2011-07-17 11:00:12 -0700454 if (!processIntent(true)) {
Makoto Onuki417ca492011-07-14 19:06:35 -0700455 finish();
456 return;
457 }
Makoto Onuki417ca492011-07-14 19:06:35 -0700458
Wenyi Wang79675452016-08-17 10:43:28 -0700459 mContactListFilterController.checkFilterValidity(false);
460
461 if (!isInSecondLevel()) {
462 // Re-initialize ActionBarAdapter because {@link #onNewIntent(Intent)} doesn't invoke
463 // {@link Fragment#onActivityCreated(Bundle)} where we initialize ActionBarAdapter
464 // initially.
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800465 mContactsListFragment.setParameters(/* ContactsRequest */ mRequest,
466 /* fromOnNewIntent */ true);
467 mContactsListFragment.initializeActionBarAdapter(null);
Wenyi Wang79675452016-08-17 10:43:28 -0700468 }
Katherine Kuanbe79b8f2011-11-09 20:54:43 -0800469
Brian Attwell9cfa24c2015-05-04 12:31:37 -0700470 initializeFabVisibility();
Makoto Onuki417ca492011-07-14 19:06:35 -0700471 invalidateOptionsMenuIfNeeded();
Dmitri Plotnikovfa49a662011-01-13 11:04:56 -0800472 }
473
Wenyi Wangcc8f2722016-09-07 14:52:32 -0700474 private static boolean isGroupSaveAction(String action) {
Wenyi Wang79675452016-08-17 10:43:28 -0700475 return GroupUtil.ACTION_UPDATE_GROUP.equals(action)
476 || GroupUtil.ACTION_ADD_TO_GROUP.equals(action)
477 || GroupUtil.ACTION_REMOVE_FROM_GROUP.equals(action);
478 }
479
Wenyi Wang79675452016-08-17 10:43:28 -0700480 private void toast(int resId) {
481 if (resId >= 0) {
482 Toast.makeText(this, resId, Toast.LENGTH_SHORT).show();
483 }
484 }
485
Makoto Onuki417ca492011-07-14 19:06:35 -0700486 /**
487 * Resolve the intent and initialize {@link #mRequest}, and launch another activity if redirect
488 * is needed.
489 *
Makoto Onuki6d9befe2011-07-17 11:00:12 -0700490 * @param forNewIntent set true if it's called from {@link #onNewIntent(Intent)}.
Makoto Onuki417ca492011-07-14 19:06:35 -0700491 * @return {@code true} if {@link PeopleActivity} should continue running. {@code false}
492 * if it shouldn't, in which case the caller should finish() itself and shouldn't do
493 * farther initialization.
494 */
Makoto Onuki6d9befe2011-07-17 11:00:12 -0700495 private boolean processIntent(boolean forNewIntent) {
Dmitri Plotnikov1ce1e7c2010-05-13 16:41:00 -0700496 // Extract relevant information from the intent
497 mRequest = mIntentResolver.resolveIntent(getIntent());
Makoto Onukiea146052011-07-25 10:34:15 -0700498 if (Log.isLoggable(TAG, Log.DEBUG)) {
Makoto Onuki6d9befe2011-07-17 11:00:12 -0700499 Log.d(TAG, this + " processIntent: forNewIntent=" + forNewIntent
500 + " intent=" + getIntent() + " request=" + mRequest);
501 }
Dmitri Plotnikov1ce1e7c2010-05-13 16:41:00 -0700502 if (!mRequest.isValid()) {
503 setResult(RESULT_CANCELED);
Makoto Onuki417ca492011-07-14 19:06:35 -0700504 return false;
Dmitri Plotnikov59fb48e2010-04-26 17:09:19 -0700505 }
506
Walter Jang1110d672016-07-25 17:55:12 +0000507 switch (mRequest.getActionCode()) {
508 case ContactsRequest.ACTION_VIEW_CONTACT: {
Walter Jang0396cf72016-09-21 13:23:29 -0700509 ImplicitIntentsUtil.startQuickContact(
510 this, mRequest.getContactUri(), ScreenType.UNKNOWN);
Walter Jang1110d672016-07-25 17:55:12 +0000511 return false;
512 }
513 case ContactsRequest.ACTION_INSERT_GROUP: {
514 onCreateGroupMenuItemClicked();
515 return true;
516 }
Wenyi Wang79675452016-08-17 10:43:28 -0700517 case ContactsRequest.ACTION_VIEW_GROUP:
518 case ContactsRequest.ACTION_EDIT_GROUP: {
519 mShouldSwitchToGroupView = true;
520 return true;
521 }
Dmitri Plotnikov27b97bc2010-10-07 18:06:09 -0700522 }
Makoto Onuki417ca492011-07-14 19:06:35 -0700523 return true;
524 }
525
Wenyi Wang587b8f22016-08-17 17:40:45 -0700526 private void createViewsAndFragments() {
Makoto Onuki417ca492011-07-14 19:06:35 -0700527 setContentView(R.layout.people_activity);
528
529 final FragmentManager fragmentManager = getFragmentManager();
530
Wenyi Wangde61df72017-01-04 18:00:49 -0800531 setUpListFragment(fragmentManager);
Makoto Onuki417ca492011-07-14 19:06:35 -0700532
Wenyi Wang17fe7982016-10-05 13:54:09 -0700533 mMembersFragment = (GroupMembersFragment) fragmentManager.findFragmentByTag(TAG_GROUP_VIEW);
Makoto Onuki417ca492011-07-14 19:06:35 -0700534
Brian Attwell865847b2015-04-20 14:40:17 -0700535 // Configure floating action button
536 mFloatingActionButtonContainer = findViewById(R.id.floating_action_button_container);
537 final ImageButton floatingActionButton
538 = (ImageButton) findViewById(R.id.floating_action_button);
Wenyi Wang587b8f22016-08-17 17:40:45 -0700539 floatingActionButton.setOnClickListener(new View.OnClickListener() {
540 @Override
541 public void onClick(View v) {
Wenyi Wang79675452016-08-17 10:43:28 -0700542 AccountFilterUtil.startEditorIntent(PeopleActivity.this, getIntent(),
543 mContactListFilterController.getFilter());
Wenyi Wang587b8f22016-08-17 17:40:45 -0700544 }
545 });
Brian Attwell865847b2015-04-20 14:40:17 -0700546 mFloatingActionButtonController = new FloatingActionButtonController(this,
547 mFloatingActionButtonContainer, floatingActionButton);
Paul Soulos2b9563d2014-05-27 16:21:23 -0700548
Makoto Onuki417ca492011-07-14 19:06:35 -0700549 invalidateOptionsMenuIfNeeded();
Marcus Hagerottbea2b852016-08-11 14:55:52 -0700550
551 mLayoutRoot = (CoordinatorLayout) findViewById(R.id.root);
552
Wenyi Wang79675452016-08-17 10:43:28 -0700553 if (mShouldSwitchToGroupView && !mIsRecreatedInstance) {
554 mGroupUri = mRequest.getContactUri();
Wenyi Wangcc8f2722016-09-07 14:52:32 -0700555 switchToOrUpdateGroupView(GroupUtil.ACTION_SWITCH_GROUP);
Wenyi Wang79675452016-08-17 10:43:28 -0700556 mShouldSwitchToGroupView = false;
557 }
558 }
559
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800560 @Override
561 public void setContentView(@LayoutRes int layoutResID) {
562 final ViewGroup parent = (ViewGroup) findViewById(R.id.content_frame);
563 if (parent != null) {
564 parent.removeAllViews();
565 }
566 LayoutInflater.from(this).inflate(layoutResID, parent);
567 }
568
Wenyi Wangde61df72017-01-04 18:00:49 -0800569 private void setUpListFragment(FragmentManager fragmentManager) {
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800570 mContactsListFragment = (DefaultContactBrowseListFragment)
Wenyi Wang79675452016-08-17 10:43:28 -0700571 fragmentManager.findFragmentByTag(TAG_ALL);
572
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800573 if (mContactsListFragment == null) {
574 mContactsListFragment = new DefaultContactBrowseListFragment();
575 mContactsListFragment.setAnimateOnLoad(true);
Wenyi Wang79675452016-08-17 10:43:28 -0700576 fragmentManager.beginTransaction()
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800577 .add(R.id.contacts_list_container, mContactsListFragment, TAG_ALL)
Wenyi Wang79675452016-08-17 10:43:28 -0700578 .commit();
579 fragmentManager.executePendingTransactions();
580 }
581
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800582 mContactsListFragment.setContactsAvailable(areContactsAvailable());
583 mContactsListFragment.setListType(mContactListFilterController.getFilterListType());
584 mContactsListFragment.setParameters(/* ContactsRequest */ mRequest,
585 /* fromOnNewIntent */ false);
Dmitri Plotnikovcaf0bc72010-09-03 15:16:21 -0700586 }
587
Dmitri Plotnikov6e850a02010-10-28 10:46:21 -0700588 @Override
Dmitri Plotnikov174fdc22010-10-29 13:55:01 -0700589 protected void onPause() {
Makoto Onukic2bd6132012-04-27 16:14:51 -0700590 mProviderStatusWatcher.stop();
Marcus Hagerottbea2b852016-08-11 14:55:52 -0700591
592 LocalBroadcastManager.getInstance(this).unregisterReceiver(mSaveServiceListener);
593
Dmitri Plotnikov174fdc22010-10-29 13:55:01 -0700594 super.onPause();
Xi Chen4a7a9ea2016-07-20 11:23:30 -0700595
Walter Jang9adc9ef2016-11-02 18:50:38 -0700596 ContentResolver.removeStatusChangeListener(mStatusChangeListenerHandle);
597 onSyncStateUpdated();
Dmitri Plotnikov174fdc22010-10-29 13:55:01 -0700598 }
599
600 @Override
Sean Midfordfc4f6922016-10-20 13:55:58 -0700601 public void onMultiWindowModeChanged(boolean entering) {
602 initializeHomeVisibility();
603 }
604
605 @Override
Dmitri Plotnikov174fdc22010-10-29 13:55:01 -0700606 protected void onResume() {
607 super.onResume();
Josh Gargus697ab262012-05-04 11:11:34 -0700608
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800609 if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
610 updateStatusBarBackground();
611 }
612
Wenyi Wang32912eb2016-09-29 17:17:07 -0700613 if (mShouldSwitchToAllContacts) {
614 switchToAllContacts();
615 }
616
Makoto Onukic2bd6132012-04-27 16:14:51 -0700617 mProviderStatusWatcher.start();
Josh Gargus697ab262012-05-04 11:11:34 -0700618 updateViewConfiguration(true);
Makoto Onuki4d788fc2011-07-12 10:00:10 -0700619
Walter Jang9adc9ef2016-11-02 18:50:38 -0700620 mStatusChangeListenerHandle = ContentResolver.addStatusChangeListener(
621 ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE
622 | ContentResolver.SYNC_OBSERVER_TYPE_PENDING
623 | ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS,
624 mSyncStatusObserver);
625 onSyncStateUpdated();
626
Wenyi Wang587b8f22016-08-17 17:40:45 -0700627 initializeFabVisibility();
Sean Midfordfc4f6922016-10-20 13:55:58 -0700628 initializeHomeVisibility();
Marcus Hagerottbea2b852016-08-11 14:55:52 -0700629
630 mSaveServiceListener = new SaveServiceListener();
631 LocalBroadcastManager.getInstance(this).registerReceiver(mSaveServiceListener,
Marcus Hagerott819214d2016-09-29 14:58:27 -0700632 new IntentFilter(ContactSaveService.BROADCAST_GROUP_DELETED));
Dmitri Plotnikov174fdc22010-10-29 13:55:01 -0700633 }
634
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800635 public void updateStatusBarBackground() {
636 updateStatusBarBackground(/* color */ -1);
637 }
638
639 public void updateStatusBarBackground(int color) {
640 if (!CompatUtils.isLollipopCompatible()) return;
641 if (color == -1) {
642 mDrawerLayout.setStatusBarBackgroundColor(
643 MaterialColorMapUtils.getStatusBarColor(this));
644 } else {
645 mDrawerLayout.setStatusBarBackgroundColor(color);
646 }
647 mDrawerLayout.invalidate();
648 getWindow().setStatusBarColor(Color.TRANSPARENT);
649 }
650
Dmitri Plotnikov174fdc22010-10-29 13:55:01 -0700651 @Override
Makoto Onuki4d788fc2011-07-12 10:00:10 -0700652 protected void onDestroy() {
Wenyi Wang32912eb2016-09-29 17:17:07 -0700653 mProviderStatusWatcher.removeListener(mProviderStatusListener);
654 mContactListFilterController.removeListener(mFilterListener);
Makoto Onuki4d788fc2011-07-12 10:00:10 -0700655 super.onDestroy();
656 }
657
Brian Attwell865847b2015-04-20 14:40:17 -0700658 private void initializeFabVisibility() {
Wenyi Wang587b8f22016-08-17 17:40:45 -0700659 mFloatingActionButtonContainer.setVisibility(shouldHideFab() ? View.GONE : View.VISIBLE);
Brian Attwell9cfa24c2015-05-04 12:31:37 -0700660 mFloatingActionButtonController.resetIn();
Wenyi Wang587b8f22016-08-17 17:40:45 -0700661 wasLastFabAnimationScaleIn = !shouldHideFab();
Brian Attwell865847b2015-04-20 14:40:17 -0700662 }
663
Sean Midfordfc4f6922016-10-20 13:55:58 -0700664 private void initializeHomeVisibility() {
665 // Remove the navigation icon if we return to the fragment in a search or select state
Wenyi Wangde61df72017-01-04 18:00:49 -0800666 if (getToolbar() != null && (isListFragmentInSelectionMode()
667 || isListFragmentInSearchMode() || isGroupsFragmentInSelectionMode()
Sean Midfordfc4f6922016-10-20 13:55:58 -0700668 || isGroupsFragmentInSearchMode())) {
669 getToolbar().setNavigationIcon(null);
670 }
671 }
672
Wenyi Wang587b8f22016-08-17 17:40:45 -0700673 private boolean shouldHideFab() {
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800674 if (mContactsListFragment != null && mContactsListFragment.getActionBarAdapter() == null
Wenyi Wang79675452016-08-17 10:43:28 -0700675 || isInSecondLevel()) {
676 return true;
677 }
Wenyi Wangde61df72017-01-04 18:00:49 -0800678 return isListFragmentInSearchMode()
679 || isListFragmentInSelectionMode();
Wenyi Wangbf693302016-06-14 12:49:03 -0700680 }
681
Wenyi Wang587b8f22016-08-17 17:40:45 -0700682 public void showFabWithAnimation(boolean showFab) {
Brian Attwell865847b2015-04-20 14:40:17 -0700683 if (mFloatingActionButtonContainer == null) {
684 return;
685 }
686 if (showFab) {
687 if (!wasLastFabAnimationScaleIn) {
688 mFloatingActionButtonContainer.setVisibility(View.VISIBLE);
689 mFloatingActionButtonController.scaleIn(0);
690 }
691 wasLastFabAnimationScaleIn = true;
692
693 } else {
694 if (wasLastFabAnimationScaleIn) {
695 mFloatingActionButtonContainer.setVisibility(View.VISIBLE);
696 mFloatingActionButtonController.scaleOut();
697 }
698 wasLastFabAnimationScaleIn = false;
699 }
700 }
701
Josh Gargus697ab262012-05-04 11:11:34 -0700702 private void updateViewConfiguration(boolean forceUpdate) {
Brian Attwellc3d202c2015-01-08 15:01:03 -0800703 int providerStatus = mProviderStatusWatcher.getProviderStatus();
Makoto Onukid8fa7162012-05-16 13:45:48 -0700704 if (!forceUpdate && (mProviderStatus != null)
Brian Attwellc3d202c2015-01-08 15:01:03 -0800705 && (mProviderStatus.equals(providerStatus))) return;
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800706 mProviderStatus = providerStatus;
707
Wenyi Wang79675452016-08-17 10:43:28 -0700708 final FragmentManager fragmentManager= getFragmentManager();
709 final FragmentTransaction transaction = fragmentManager.beginTransaction();
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800710
Wenyi Wangf128ea82016-07-25 11:56:40 -0700711 // Change in CP2's provider status may not take effect immediately, see b/30566908.
712 // So we need to handle the case where provider status is STATUS_EMPTY and there is
713 // actually at least one real account (not "local" account) on device.
Wenyi Wang79675452016-08-17 10:43:28 -0700714 if (shouldShowList()) {
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800715 if (mContactsListFragment != null) {
Marcus Hagerott89c51292016-11-08 15:05:38 -0800716 final Fragment unavailableFragment = fragmentManager
717 .findFragmentByTag(TAG_UNAVAILABLE);
718 if (unavailableFragment != null) {
719 transaction.remove(unavailableFragment);
720 }
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800721 if (mContactsListFragment.isHidden()) {
722 transaction.show(mContactsListFragment);
Marcus Hagerott89c51292016-11-08 15:05:38 -0800723 }
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800724 mContactsListFragment.setContactsAvailable(areContactsAvailable());
725 mContactsListFragment.setEnabled(true);
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800726 }
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800727 } else {
guanxiongliu5d7bb262016-01-29 16:43:45 -0800728 // Setting up the page so that the user can still use the app
729 // even without an account.
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800730 if (mContactsListFragment != null) {
731 mContactsListFragment.setEnabled(false);
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800732 }
Marcus Hagerott89c51292016-11-08 15:05:38 -0800733 final ContactsUnavailableFragment fragment = new ContactsUnavailableFragment();
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800734 transaction.hide(mContactsListFragment);
Marcus Hagerott89c51292016-11-08 15:05:38 -0800735 transaction.replace(R.id.contacts_unavailable_container, fragment, TAG_UNAVAILABLE);
736 fragment.updateStatus(mProviderStatus);
Wenyi Wang79675452016-08-17 10:43:28 -0700737 }
738 if (!transaction.isEmpty()) {
yingrenwaa21e962018-01-23 15:54:49 +0800739 transaction.commitAllowingStateLoss();
Wenyi Wang79675452016-08-17 10:43:28 -0700740 fragmentManager.executePendingTransactions();
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800741 }
742
Katherine Kuan8268bbe2011-06-10 17:48:21 -0700743 invalidateOptionsMenuIfNeeded();
Dmitri Plotnikov8b826462010-11-17 14:52:24 -0800744 }
745
Wenyi Wang79675452016-08-17 10:43:28 -0700746 private boolean shouldShowList() {
747 return mProviderStatus != null
Marcus Hagerott396aab72016-12-12 12:00:21 -0800748 && ((mProviderStatus.equals(ProviderStatus.STATUS_EMPTY)
749 && mAccountTypeManager.hasNonLocalAccount())
750 || mProviderStatus.equals(ProviderStatus.STATUS_NORMAL));
Wenyi Wangf128ea82016-07-25 11:56:40 -0700751 }
752
Katherine Kuan8268bbe2011-06-10 17:48:21 -0700753 private void invalidateOptionsMenuIfNeeded() {
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800754 if (mContactsListFragment != null
755 && mContactsListFragment.getOptionsMenuContactsAvailable()
756 != areContactsAvailable()) {
Katherine Kuan8268bbe2011-06-10 17:48:21 -0700757 invalidateOptionsMenu();
Dmitri Plotnikov0cd01302010-12-17 18:41:57 -0800758 }
759 }
760
Dmitri Plotnikov8e86b752010-02-22 17:47:57 -0800761 @Override
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800762 public boolean onKeyDown(int keyCode, KeyEvent event) {
Wenyi Wangff3f1192017-03-22 18:22:32 -0700763 // If the drawer is open, consume KEYCODE_BACK event only.
Wenyi Wangcc5ea442017-03-20 18:16:58 -0700764 if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
Wenyi Wangff3f1192017-03-22 18:22:32 -0700765 if (keyCode == KeyEvent.KEYCODE_BACK) {
766 // Should eventually go to onBackPressed().
767 return super.onKeyDown(keyCode, event);
768 }
Wenyi Wangcc5ea442017-03-20 18:16:58 -0700769 return false;
770 }
Brian Attwell20510ec2015-02-27 16:10:45 -0800771 // Bring up the search UI if the user starts typing
772 final int unicodeChar = event.getUnicodeChar();
773 if ((unicodeChar != 0)
774 // If COMBINING_ACCENT is set, it's not a unicode character.
775 && ((unicodeChar & KeyCharacterMap.COMBINING_ACCENT) == 0)
776 && !Character.isWhitespace(unicodeChar)) {
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800777 if (mContactsListFragment.onKeyDown(unicodeChar)) {
Brian Attwell20510ec2015-02-27 16:10:45 -0800778 return true;
Daniel Lehmann7bb2add2010-07-14 21:15:17 -0700779 }
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800780 }
781
782 return super.onKeyDown(keyCode, event);
783 }
784
Dmitri Plotnikovab4d29f2010-10-28 12:43:54 -0700785 @Override
786 public void onBackPressed() {
Jay Shrauner7712aef2015-09-25 14:14:28 -0700787 if (!isSafeToCommitTransactions()) {
Jay Shraunerc3fdc8f2015-09-16 10:29:52 -0700788 return;
789 }
790
Wenyi Wangf9905062016-09-14 10:07:59 -0700791 // Handle the back event in drawer first.
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800792 if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
Wenyi Wang2829deb2017-01-04 14:05:13 -0800793 closeDrawer();
Wenyi Wang51819e82016-09-12 11:57:51 -0700794 return;
Wenyi Wangf9905062016-09-14 10:07:59 -0700795 }
796
797 // Handle the back event in "second level".
798 if (isGroupView()) {
799 onBackPressedGroupView();
800 return;
801 }
802
John Shao52dd5d72016-10-06 15:16:14 -0700803 if (isAssistantView()) {
804 onBackPressedAssistantView();
Wenyi Wangf9905062016-09-14 10:07:59 -0700805 return;
806 }
807
Wenyi Wangde61df72017-01-04 18:00:49 -0800808 // If feature highlight is present, let it handle the back event before
809 // mContactsListFragment.
Wenyi Wangf9905062016-09-14 10:07:59 -0700810 if (FeatureHighlightHelper.tryRemoveHighlight(this)) {
811 return;
812 }
813
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800814 // Handle the back event in "first level" - mContactsListFragment.
Wenyi Wangde61df72017-01-04 18:00:49 -0800815 if (maybeHandleInListFragment()) {
Wenyi Wangf9905062016-09-14 10:07:59 -0700816 return;
817 }
818
819 super.onBackPressed();
820 }
821
822 private void onBackPressedGroupView() {
823 if (mMembersFragment.isEditMode()) {
824 mMembersFragment.exitEditMode();
825 } else if (mMembersFragment.getActionBarAdapter().isSelectionMode()) {
826 mMembersFragment.getActionBarAdapter().setSelectionMode(false);
827 mMembersFragment.displayCheckBoxes(false);
828 } else if (mMembersFragment.getActionBarAdapter().isSearchMode()) {
829 mMembersFragment.getActionBarAdapter().setSearchMode(false);
830 } else {
831 switchToAllContacts();
832 }
833 }
834
John Shao52dd5d72016-10-06 15:16:14 -0700835 private void onBackPressedAssistantView() {
Gary Maif6b50e82017-01-26 15:32:49 -0800836 if (!isInThirdLevel()) {
John Shao52dd5d72016-10-06 15:16:14 -0700837 switchToAllContacts();
838 } else {
839 setDrawerLockMode(/* enabled */ true);
Gary Maif6b50e82017-01-26 15:32:49 -0800840 super.onBackPressed();
John Shao52dd5d72016-10-06 15:16:14 -0700841 }
842 }
843
Wenyi Wangf9905062016-09-14 10:07:59 -0700844 // Returns true if back event is handled in this method.
Wenyi Wangde61df72017-01-04 18:00:49 -0800845 private boolean maybeHandleInListFragment() {
846 if (isListFragmentInSelectionMode()) {
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800847 mContactsListFragment.getActionBarAdapter().setSelectionMode(false);
Wenyi Wangf9905062016-09-14 10:07:59 -0700848 return true;
849 }
850
Wenyi Wangde61df72017-01-04 18:00:49 -0800851 if (isListFragmentInSearchMode()) {
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800852 mContactsListFragment.getActionBarAdapter().setSearchMode(false);
853 if (mContactsListFragment.wasSearchResultClicked()) {
854 mContactsListFragment.resetSearchResultClicked();
Walter Janga84fe612016-01-13 16:49:04 -0800855 } else {
Walter Jang62a20742016-02-24 17:04:12 -0800856 Logger.logScreenView(this, ScreenType.SEARCH_EXIT);
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800857 Logger.logSearchEvent(mContactsListFragment.createSearchState());
Walter Janga84fe612016-01-13 16:49:04 -0800858 }
Wenyi Wangf9905062016-09-14 10:07:59 -0700859 return true;
860 }
861
Wenyi Wang32912eb2016-09-29 17:17:07 -0700862 if (!AccountFilterUtil.isAllContactsFilter(mContactListFilterController.getFilter())
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800863 && !mContactsListFragment.isHidden()) {
864 // If mContactsListFragment is hidden, then mContactsUnavailableFragment is visible so we
Wenyi Wang79675452016-08-17 10:43:28 -0700865 // don't need to switch to all contacts.
Wenyi Wang40e79102016-06-01 20:43:56 -0700866 switchToAllContacts();
Wenyi Wangf9905062016-09-14 10:07:59 -0700867 return true;
Dmitri Plotnikovab4d29f2010-10-28 12:43:54 -0700868 }
Wenyi Wangf9905062016-09-14 10:07:59 -0700869
870 return false;
Dmitri Plotnikovab4d29f2010-10-28 12:43:54 -0700871 }
872
Wenyi Wangde61df72017-01-04 18:00:49 -0800873 private boolean isListFragmentInSelectionMode() {
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800874 return mContactsListFragment != null && mContactsListFragment.getActionBarAdapter() != null
875 && mContactsListFragment.getActionBarAdapter().isSelectionMode();
Wenyi Wanged9f9742016-09-08 13:50:39 -0700876 }
877
Wenyi Wangde61df72017-01-04 18:00:49 -0800878 private boolean isListFragmentInSearchMode() {
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800879 return mContactsListFragment != null && mContactsListFragment.getActionBarAdapter() != null
880 && mContactsListFragment.getActionBarAdapter().isSearchMode();
Wenyi Wanged9f9742016-09-08 13:50:39 -0700881 }
882
Sean Midfordfc4f6922016-10-20 13:55:58 -0700883 private boolean isGroupsFragmentInSelectionMode() {
884 return mMembersFragment != null && mMembersFragment.getActionBarAdapter() != null
885 && mMembersFragment.getActionBarAdapter().isSelectionMode();
886 }
887
888 private boolean isGroupsFragmentInSearchMode() {
889 return mMembersFragment != null && mMembersFragment.getActionBarAdapter() != null
890 && mMembersFragment.getActionBarAdapter().isSearchMode();
891 }
892
Wenyi Wang79675452016-08-17 10:43:28 -0700893 @Override
894 protected void onSaveInstanceState(Bundle outState) {
895 super.onSaveInstanceState(outState);
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800896 if (mNewGroupAccount != null) {
897 outState.putString(KEY_NEW_GROUP_ACCOUNT, mNewGroupAccount.stringify());
898 }
899 outState.putInt(KEY_CONTACTS_VIEW, mCurrentView.ordinal());
Wenyi Wang79675452016-08-17 10:43:28 -0700900 outState.putParcelable(KEY_GROUP_URI, mGroupUri);
Tingting Wang2dc340c2016-07-05 22:31:58 -0700901 }
902
Wenyi Wangbb229242016-05-25 16:04:13 -0700903 @Override
Wenyi Wang79675452016-08-17 10:43:28 -0700904 protected void onRestoreInstanceState(Bundle savedInstanceState) {
905 super.onRestoreInstanceState(savedInstanceState);
906 mGroupUri = savedInstanceState.getParcelable(KEY_GROUP_URI);
Tingting Wang1243cb42016-08-05 16:42:21 -0700907 }
Marcus Hagerottbea2b852016-08-11 14:55:52 -0700908
Gary Mai4ac56292016-10-31 10:41:11 -0700909 private void onGroupDeleted(final Intent intent) {
Marcus Hagerott3c1153f2016-09-07 09:15:14 -0700910 if (!ContactSaveService.canUndo(intent)) return;
911
James Laskey6b712bc2016-11-22 11:02:09 -0800912 final AccessibilityManager am =
913 (AccessibilityManager) getSystemService(Context.ACCESSIBILITY_SERVICE);
James Laskey692c9612016-11-30 10:13:01 -0800914 //TODO set to INDEFINITE and track user interaction to dismiss b/33208886
915 final int accessibilityLength = 15000;
916 final int length = am.isEnabled() ? accessibilityLength : Snackbar.LENGTH_LONG;
James Laskey6b712bc2016-11-22 11:02:09 -0800917 final String message = getString(R.string.groupDeletedToast);
918
919 final Snackbar snackbar = Snackbar.make(mLayoutRoot, message, length)
Marcus Hagerottbea2b852016-08-11 14:55:52 -0700920 .setAction(R.string.undo, new View.OnClickListener() {
921 @Override
922 public void onClick(View v) {
923 ContactSaveService.startService(PeopleActivity.this,
924 ContactSaveService.createUndoIntent(PeopleActivity.this, intent));
925 }
James Laskey6b712bc2016-11-22 11:02:09 -0800926 }).setActionTextColor(ContextCompat.getColor(this, R.color.snackbar_action_text));
927
928 // Announce for a11y talkback
929 mLayoutRoot.announceForAccessibility(message);
930 mLayoutRoot.announceForAccessibility(getString(R.string.undo));
931
932 snackbar.show();
Marcus Hagerottbea2b852016-08-11 14:55:52 -0700933 }
934
Marcus Hagerottbea2b852016-08-11 14:55:52 -0700935 private class SaveServiceListener extends BroadcastReceiver {
936 @Override
937 public void onReceive(Context context, Intent intent) {
938 switch (intent.getAction()) {
Marcus Hagerott819214d2016-09-29 14:58:27 -0700939 case ContactSaveService.BROADCAST_GROUP_DELETED:
Marcus Hagerottbea2b852016-08-11 14:55:52 -0700940 onGroupDeleted(intent);
941 break;
942 }
943 }
944 }
Wenyi Wang79675452016-08-17 10:43:28 -0700945
Wenyi Wang2829deb2017-01-04 14:05:13 -0800946 private void onGroupMenuItemClicked(long groupId) {
Wenyi Wang79675452016-08-17 10:43:28 -0700947 if (isGroupView() && mMembersFragment != null
Marcus Hagerottd6d5ad52016-10-25 19:25:38 -0700948 && mMembersFragment.isCurrentGroup(groupId)) {
Wenyi Wang79675452016-08-17 10:43:28 -0700949 return;
950 }
Marcus Hagerottd6d5ad52016-10-25 19:25:38 -0700951 mGroupUri = ContentUris.withAppendedId(ContactsContract.Groups.CONTENT_URI, groupId);
Wenyi Wangcc8f2722016-09-07 14:52:32 -0700952 switchToOrUpdateGroupView(GroupUtil.ACTION_SWITCH_GROUP);
Wenyi Wang79675452016-08-17 10:43:28 -0700953 }
954
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800955 private void onFilterMenuItemClicked(Intent intent) {
956 // We must pop second level first to "restart" mContactsListFragment before changing filter.
Wenyi Wang79675452016-08-17 10:43:28 -0700957 if (isInSecondLevel()) {
Wenyi Wangcc8f2722016-09-07 14:52:32 -0700958 popSecondLevel();
Wenyi Wang79675452016-08-17 10:43:28 -0700959 showFabWithAnimation(/* showFab */ true);
Marcus Hagerott45451ea2016-10-25 20:05:26 -0700960 // HACK: swap the current filter to force listeners to update because the group
961 // member view no longer changes the filter. Fix for b/32223767
962 final ContactListFilter current = mContactListFilterController.getFilter();
963 mContactListFilterController.setContactListFilter(
964 AccountFilterUtil.createContactsFilter(this), false);
965 mContactListFilterController.setContactListFilter(current, false);
Wenyi Wang79675452016-08-17 10:43:28 -0700966 }
967 mCurrentView = ContactsView.ACCOUNT_VIEW;
Wenyi Wang917cb4a2016-12-13 17:42:18 -0800968 AccountFilterUtil.handleAccountFilterResult(mContactListFilterController,
969 AppCompatActivity.RESULT_OK, intent);
Wenyi Wang79675452016-08-17 10:43:28 -0700970 }
971
Wenyi Wangcc8f2722016-09-07 14:52:32 -0700972 private void switchToOrUpdateGroupView(String action) {
Wenyi Wang17fe7982016-10-05 13:54:09 -0700973 // If group fragment is active and visible, we simply update it.
974 if (mMembersFragment != null && !mMembersFragment.isInactive()) {
Wenyi Wangf6606072016-10-03 17:34:53 -0700975 mMembersFragment.updateExistingGroupFragment(mGroupUri, action);
Wenyi Wang17fe7982016-10-05 13:54:09 -0700976 } else {
977 switchView(ContactsView.GROUP_VIEW);
Wenyi Wangcc8f2722016-09-07 14:52:32 -0700978 }
Wenyi Wang79675452016-08-17 10:43:28 -0700979 }
980
John Shao52dd5d72016-10-06 15:16:14 -0700981 protected void launchAssistant() {
982 switchView(ContactsView.ASSISTANT);
Wenyi Wang79675452016-08-17 10:43:28 -0700983 }
984
985 private void switchView(ContactsView contactsView) {
Wenyi Wang79675452016-08-17 10:43:28 -0700986 mCurrentView = contactsView;
Wenyi Wang79675452016-08-17 10:43:28 -0700987
Wenyi Wang79675452016-08-17 10:43:28 -0700988 final FragmentManager fragmentManager = getFragmentManager();
989 final FragmentTransaction transaction = fragmentManager.beginTransaction();
Gary Maif6b50e82017-01-26 15:32:49 -0800990 popSecondLevel();
Wenyi Wang79675452016-08-17 10:43:28 -0700991 if (isGroupView()) {
yaolu4c075092016-10-19 22:23:00 -0700992 mMembersFragment = GroupMembersFragment.newInstance(mGroupUri);
Wenyi Wangcc8f2722016-09-07 14:52:32 -0700993 transaction.replace(
994 R.id.contacts_list_container, mMembersFragment, TAG_GROUP_VIEW);
Gary Mai4ac56292016-10-31 10:41:11 -0700995 } else if (isAssistantView()) {
John Shao5b1ffdc2016-11-08 13:51:00 -0800996 Fragment uiFragment = fragmentManager.findFragmentByTag(TAG_ASSISTANT);
Sean Midfordb96df942016-11-11 17:54:49 -0800997 Fragment unavailableFragment = fragmentManager.findFragmentByTag(TAG_UNAVAILABLE);
John Shaoa3ce3c72016-10-11 14:58:57 -0700998 if (uiFragment == null) {
John Shao5b1ffdc2016-11-08 13:51:00 -0800999 uiFragment = ObjectFactory.getAssistantFragment();
John Shaoa3ce3c72016-10-11 14:58:57 -07001000 }
Sean Midfordb96df942016-11-11 17:54:49 -08001001 if (unavailableFragment != null) {
1002 transaction.remove(unavailableFragment);
1003 }
John Shao5b1ffdc2016-11-08 13:51:00 -08001004 transaction.replace(R.id.contacts_list_container, uiFragment, TAG_ASSISTANT);
Wenyi Wang17fe7982016-10-05 13:54:09 -07001005 resetToolBarStatusBarColor();
Wenyi Wang79675452016-08-17 10:43:28 -07001006 }
Wenyi Wangcc8f2722016-09-07 14:52:32 -07001007 transaction.addToBackStack(TAG_SECOND_LEVEL);
Wenyi Wang79675452016-08-17 10:43:28 -07001008 transaction.commit();
1009 fragmentManager.executePendingTransactions();
1010
1011 showFabWithAnimation(/* showFab */ false);
1012 }
1013
Wenyi Wang79675452016-08-17 10:43:28 -07001014 public void switchToAllContacts() {
Gary Maif6b50e82017-01-26 15:32:49 -08001015 popSecondLevel();
Wenyi Wang32912eb2016-09-29 17:17:07 -07001016 mShouldSwitchToAllContacts = false;
Wenyi Wang79675452016-08-17 10:43:28 -07001017 mCurrentView = ContactsView.ALL_CONTACTS;
Wenyi Wang2829deb2017-01-04 14:05:13 -08001018 mDrawerFragment.setNavigationItemChecked(ContactsView.ALL_CONTACTS);
Wenyi Wang79675452016-08-17 10:43:28 -07001019 showFabWithAnimation(/* showFab */ true);
Wenyi Wang917cb4a2016-12-13 17:42:18 -08001020 mContactsListFragment.scrollToTop();
Wenyi Wang917cb4a2016-12-13 17:42:18 -08001021 resetFilter();
Wenyi Wang917cb4a2016-12-13 17:42:18 -08001022 setTitle(getString(R.string.contactsList));
1023 }
1024
1025 private void resetFilter() {
1026 final Intent intent = new Intent();
1027 final ContactListFilter filter = AccountFilterUtil.createContactsFilter(this);
1028 intent.putExtra(AccountFilterActivity.EXTRA_CONTACT_LIST_FILTER, filter);
1029 AccountFilterUtil.handleAccountFilterResult(
1030 mContactListFilterController, AppCompatActivity.RESULT_OK, intent);
Wenyi Wang79675452016-08-17 10:43:28 -07001031 }
1032
Wenyi Wang92d7e512016-10-03 14:57:19 -07001033 // Reset toolbar and status bar color to Contacts theme color.
1034 private void resetToolBarStatusBarColor() {
1035 findViewById(R.id.toolbar_frame).setBackgroundColor(
1036 ContextCompat.getColor(this, R.color.primary_color));
1037 updateStatusBarBackground(ContextCompat.getColor(this, R.color.primary_color_dark));
Wenyi Wangcc8f2722016-09-07 14:52:32 -07001038 }
1039
Wenyi Wangde61df72017-01-04 18:00:49 -08001040 protected DefaultContactBrowseListFragment getListFragment() {
Wenyi Wang917cb4a2016-12-13 17:42:18 -08001041 return mContactsListFragment;
Wenyi Wang79675452016-08-17 10:43:28 -07001042 }
1043
Wenyi Wang79675452016-08-17 10:43:28 -07001044 protected GroupMembersFragment getGroupFragment() {
1045 return mMembersFragment;
1046 }
1047
Wenyi Wang32912eb2016-09-29 17:17:07 -07001048 private void handleFilterChangeForFragment(ContactListFilter filter) {
Wenyi Wang917cb4a2016-12-13 17:42:18 -08001049 if (mContactsListFragment.canSetActionBar()) {
1050 mContactsListFragment.setFilterAndUpdateTitle(filter);
James Laskey1842bb22016-10-20 14:38:04 -07001051 // Scroll to top after filter is changed.
Wenyi Wang917cb4a2016-12-13 17:42:18 -08001052 mContactsListFragment.scrollToTop();
James Laskey1842bb22016-10-20 14:38:04 -07001053 }
Wenyi Wang32912eb2016-09-29 17:17:07 -07001054 }
1055
1056 private void handleFilterChangeForActivity(ContactListFilter filter) {
Marcus Hagerott74295d32016-10-26 10:46:28 -07001057 // The filter was changed while this activity was in the background. If we're in the
1058 // assistant view Switch to the main contacts list when we resume to prevent
1059 // b/31838582 and b/31829161
1060 // TODO: this is a hack; we need to do some cleanup of the contact list filter stuff
1061 if (isAssistantView() && filter.isContactsFilterType()) {
Wenyi Wang32912eb2016-09-29 17:17:07 -07001062 mShouldSwitchToAllContacts = true;
1063 }
1064
Wenyi Wang32912eb2016-09-29 17:17:07 -07001065 if (CompatUtils.isNCompatible()) {
1066 getWindow().getDecorView()
1067 .sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
1068 }
1069 invalidateOptionsMenu();
1070 }
Wenyi Wang917cb4a2016-12-13 17:42:18 -08001071
Wenyi Wang2829deb2017-01-04 14:05:13 -08001072 public void updateDrawerGroupMenu(long groupId) {
1073 if (mDrawerFragment != null) {
1074 mDrawerFragment.updateGroupMenu(groupId);
Wenyi Wang917cb4a2016-12-13 17:42:18 -08001075 }
1076 }
1077
1078 public void setDrawerLockMode(boolean enabled) {
1079 // Prevent drawer from being opened by sliding from the start of screen.
1080 mDrawerLayout.setDrawerLockMode(enabled ? DrawerLayout.LOCK_MODE_UNLOCKED
1081 : DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
1082
1083 // Order of these statements matter.
1084 // Display back button and disable drawer indicator.
1085 if (enabled) {
1086 getSupportActionBar().setDisplayHomeAsUpEnabled(false);
1087 mToggle.setDrawerIndicatorEnabled(true);
1088 } else {
1089 mToggle.setDrawerIndicatorEnabled(false);
1090 getSupportActionBar().setDisplayHomeAsUpEnabled(true);
1091 }
1092 }
1093
Wenyi Wang917cb4a2016-12-13 17:42:18 -08001094 public Toolbar getToolbar() {
1095 return mToolbar;
1096 }
1097
1098 @Override
1099 protected void onPostCreate(Bundle savedInstanceState) {
1100 super.onPostCreate(savedInstanceState);
1101 mToggle.syncState();
1102 }
1103
1104 @Override
1105 public void onConfigurationChanged(Configuration newConfig) {
1106 super.onConfigurationChanged(newConfig);
1107 mToggle.onConfigurationChanged(newConfig);
1108 }
1109
Wenyi Wang917cb4a2016-12-13 17:42:18 -08001110 protected void onCreateGroupMenuItemClicked() {
1111 // Select the account to create the group
1112 final Bundle extras = getIntent().getExtras();
1113 final Account account = extras == null ? null :
1114 (Account) extras.getParcelable(Intents.Insert.EXTRA_ACCOUNT);
1115 if (account == null) {
1116 selectAccountForNewGroup();
1117 } else {
1118 final String dataSet = extras == null
1119 ? null : extras.getString(Intents.Insert.EXTRA_DATA_SET);
1120 final AccountWithDataSet accountWithDataSet = new AccountWithDataSet(
1121 account.name, account.type, dataSet);
1122 onAccountChosen(accountWithDataSet, /* extraArgs */ null);
1123 }
1124 }
1125
1126 private void selectAccountForNewGroup() {
Wenyi Wangb8b86d12017-01-07 16:16:52 -08001127 // This should never block because the DrawerFragment loads the accounts and the
Wenyi Wang917cb4a2016-12-13 17:42:18 -08001128 // "Create Label" item only exists when that loading finishes
1129 final List<AccountInfo> accounts = Futures.getUnchecked(AccountTypeManager.getInstance(this)
1130 .filterAccountsAsync(AccountTypeManager.AccountFilter.GROUPS_WRITABLE));
1131 if (accounts.isEmpty()) {
1132 // We shouldn't present the add group button if there are no writable accounts
1133 // but check it since it's possible we are started with an Intent.
1134 Toast.makeText(this, R.string.groupCreateFailedToast, Toast.LENGTH_SHORT).show();
1135 return;
1136 }
1137 // If there is a single writable account, use it w/o showing a dialog.
1138 if (accounts.size() == 1) {
1139 onAccountChosen(accounts.get(0).getAccount(), /* extraArgs */ null);
1140 return;
1141 }
1142 SelectAccountDialogFragment.show(getFragmentManager(), R.string.dialog_new_group_account,
1143 AccountTypeManager.AccountFilter.GROUPS_WRITABLE, /* extraArgs */ null,
1144 TAG_SELECT_ACCOUNT_DIALOG);
1145 }
1146
Wenyi Wang2829deb2017-01-04 14:05:13 -08001147 // Implementation of SelectAccountDialogFragment.Listener
Wenyi Wang917cb4a2016-12-13 17:42:18 -08001148 @Override
1149 public void onAccountChosen(AccountWithDataSet account, Bundle extraArgs) {
1150 mNewGroupAccount = account;
1151 GroupNameEditDialogFragment.newInstanceForCreation(
1152 mNewGroupAccount, GroupUtil.ACTION_CREATE_GROUP)
1153 .show(getFragmentManager(), TAG_GROUP_NAME_EDIT_DIALOG);
1154 }
1155
1156 @Override
1157 public void onAccountSelectorCancelled() {
1158 }
1159
Wenyi Wang2829deb2017-01-04 14:05:13 -08001160 // Implementation of DrawerFragmentListener
Wenyi Wang917cb4a2016-12-13 17:42:18 -08001161 @Override
Wenyi Wang2829deb2017-01-04 14:05:13 -08001162 public void onDrawerItemClicked(){
1163 closeDrawer();
Wenyi Wang917cb4a2016-12-13 17:42:18 -08001164 }
1165
Wenyi Wang2829deb2017-01-04 14:05:13 -08001166 @Override
1167 public void onContactsViewSelected(ContactsView mode) {
1168 if (mode == ContactsView.ALL_CONTACTS) {
1169 switchToAllContacts();
1170 } else if (mode == ContactsView.ASSISTANT) {
1171 launchAssistant();
Wenyi Wang917cb4a2016-12-13 17:42:18 -08001172 } else {
Wenyi Wang2829deb2017-01-04 14:05:13 -08001173 throw new IllegalStateException("Unknown view " + mode);
1174 }
1175 }
1176
1177 @Override
1178 public void onCreateLabelButtonClicked() {
1179 onCreateGroupMenuItemClicked();
1180 }
1181
1182 @Override
1183 public void onOpenSettings() {
1184 new Handler().postDelayed(new Runnable() {
1185 @Override
1186 public void run() {
1187 startActivity(createPreferenceIntent());
Wenyi Wang917cb4a2016-12-13 17:42:18 -08001188 }
Wenyi Wang2829deb2017-01-04 14:05:13 -08001189 }, DRAWER_CLOSE_DELAY);
Wenyi Wang917cb4a2016-12-13 17:42:18 -08001190 }
1191
Wenyi Wang2829deb2017-01-04 14:05:13 -08001192 @Override
1193 public void onLaunchHelpFeedback() {
1194 HelpUtils.launchHelpAndFeedbackForMainScreen(this);
Wenyi Wang917cb4a2016-12-13 17:42:18 -08001195 }
1196
Wenyi Wang2829deb2017-01-04 14:05:13 -08001197 @Override
1198 public void onGroupViewSelected(GroupListItem groupListItem) {
1199 onGroupMenuItemClicked(groupListItem.getGroupId());
Wenyi Wang917cb4a2016-12-13 17:42:18 -08001200 }
1201
Wenyi Wang2829deb2017-01-04 14:05:13 -08001202 @Override
1203 public void onAccountViewSelected(ContactListFilter filter) {
1204 final Intent intent = new Intent();
1205 intent.putExtra(AccountFilterActivity.EXTRA_CONTACT_LIST_FILTER, filter);
1206 onFilterMenuItemClicked(intent);
Wenyi Wang917cb4a2016-12-13 17:42:18 -08001207 }
1208
1209 public boolean isGroupView() {
1210 return mCurrentView == ContactsView.GROUP_VIEW;
1211 }
1212
1213 protected boolean isAssistantView() {
1214 return mCurrentView == ContactsView.ASSISTANT;
1215 }
1216
1217 protected boolean isAllContactsView() {
1218 return mCurrentView == ContactsView.ALL_CONTACTS;
1219 }
1220
1221 protected boolean isAccountView() {
1222 return mCurrentView == ContactsView.ACCOUNT_VIEW;
1223 }
1224
1225 public boolean isInSecondLevel() {
Gary Maiee49cd92017-01-30 18:28:51 -08001226 return isGroupView() || isAssistantView();
Gary Maif6b50e82017-01-26 15:32:49 -08001227 }
1228
1229 private boolean isInThirdLevel() {
1230 return isLastBackStackTag(TAG_THIRD_LEVEL);
1231 }
1232
1233 private boolean isLastBackStackTag(String tag) {
1234 final int count = getFragmentManager().getBackStackEntryCount();
1235 if (count > 0) {
1236 final FragmentManager.BackStackEntry last =
1237 getFragmentManager().getBackStackEntryAt(count - 1);
1238 if (tag == null) {
1239 return last.getName() == null;
1240 }
1241 return tag.equals(last.getName());
1242 }
1243 return false;
1244 }
1245
1246 private void popSecondLevel() {
1247 getFragmentManager().popBackStackImmediate(
1248 TAG_ASSISTANT_HELPER, FragmentManager.POP_BACK_STACK_INCLUSIVE);
1249 getFragmentManager().popBackStackImmediate(
1250 TAG_SECOND_LEVEL, FragmentManager.POP_BACK_STACK_INCLUSIVE);
1251 mMembersFragment = null;
1252 resetToolBarStatusBarColor();
Wenyi Wang917cb4a2016-12-13 17:42:18 -08001253 }
1254
Wenyi Wang2829deb2017-01-04 14:05:13 -08001255 public void closeDrawer() {
Wenyi Wang917cb4a2016-12-13 17:42:18 -08001256 mDrawerLayout.closeDrawer(GravityCompat.START);
Wenyi Wang917cb4a2016-12-13 17:42:18 -08001257 }
1258
1259 private Intent createPreferenceIntent() {
1260 final Intent intent = new Intent(this, ContactsPreferenceActivity.class);
1261 intent.putExtra(ContactsPreferenceActivity.EXTRA_NEW_LOCAL_PROFILE,
1262 ContactEditorFragment.INTENT_EXTRA_NEW_LOCAL_PROFILE);
1263 return intent;
1264 }
1265
Walter Jangcea82122017-01-05 20:38:38 +00001266
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -08001267}