blob: ea7ab645a0635b603381225d9af1f7ba653fd417 [file] [log] [blame]
Walter Jang4715c042016-04-06 17:14:23 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
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 */
16package com.android.contacts.group;
17
Walter Jangec807e12016-06-27 12:10:40 -070018import android.app.Activity;
Walter Jang44e91b12016-05-22 12:37:00 -070019import android.app.LoaderManager.LoaderCallbacks;
Sean Midfordff6f1bb2016-10-12 09:48:23 -070020import android.content.ContentResolver;
John Shaobd9ef3c2016-12-15 12:42:03 -080021import android.content.Context;
Walter Jang44e91b12016-05-22 12:37:00 -070022import android.content.CursorLoader;
Wenyi Wang6927bf32016-08-15 18:31:24 -070023import android.content.Intent;
Walter Jang44e91b12016-05-22 12:37:00 -070024import android.content.Loader;
25import android.database.Cursor;
Walter Jang2552c112016-06-17 14:29:09 -070026import android.database.CursorWrapper;
John Shaobd9ef3c2016-12-15 12:42:03 -080027import android.graphics.PorterDuff;
28import android.graphics.drawable.Drawable;
Walter Jang4715c042016-04-06 17:14:23 -070029import android.net.Uri;
30import android.os.Bundle;
Wenyi Wang17fe7982016-10-05 13:54:09 -070031import android.os.Handler;
32import android.os.Message;
Sean Midfordff6f1bb2016-10-12 09:48:23 -070033import android.provider.ContactsContract;
Wenyi Wang38860a52016-06-24 17:47:34 -070034import android.provider.ContactsContract.Contacts;
John Shaobd9ef3c2016-12-15 12:42:03 -080035import android.support.v4.content.ContextCompat;
Sean Midfordff6f1bb2016-10-12 09:48:23 -070036import android.text.TextUtils;
Walter Jang44e91b12016-05-22 12:37:00 -070037import android.util.Log;
yaolud8effeb2016-06-29 14:42:38 -070038import android.view.Gravity;
Walter Jang4715c042016-04-06 17:14:23 -070039import android.view.LayoutInflater;
Wenyi Wang6927bf32016-08-15 18:31:24 -070040import android.view.Menu;
41import android.view.MenuInflater;
42import android.view.MenuItem;
Walter Jang4715c042016-04-06 17:14:23 -070043import android.view.View;
44import android.view.ViewGroup;
yaolud8effeb2016-06-29 14:42:38 -070045import android.widget.Button;
46import android.widget.FrameLayout;
47import android.widget.ImageView;
48import android.widget.LinearLayout;
Wenyi Wang6927bf32016-08-15 18:31:24 -070049import android.widget.Toast;
Walter Jang4715c042016-04-06 17:14:23 -070050
Wenyi Wang6927bf32016-08-15 18:31:24 -070051import com.android.contacts.ContactSaveService;
Wenyi Wang79675452016-08-17 10:43:28 -070052import com.android.contacts.ContactsDrawerActivity;
Gary Mai0a49afa2016-12-05 15:53:58 -080053import com.android.contacts.ContactsUtils;
Walter Jang44e91b12016-05-22 12:37:00 -070054import com.android.contacts.GroupMetaDataLoader;
Walter Jang4715c042016-04-06 17:14:23 -070055import com.android.contacts.R;
Wenyi Wang6927bf32016-08-15 18:31:24 -070056import com.android.contacts.activities.ActionBarAdapter;
Gary Mai0a49afa2016-12-05 15:53:58 -080057import com.android.contacts.group.GroupMembersAdapter.GroupMembersQuery;
58import com.android.contacts.interactions.GroupDeletionDialogFragment;
59import com.android.contacts.list.ContactsRequest;
Gary Mai69c182a2016-12-05 13:07:03 -080060import com.android.contacts.list.ContactsSectionIndexer;
Gary Mai0a49afa2016-12-05 15:53:58 -080061import com.android.contacts.list.MultiSelectContactsListFragment;
Gary Mai69c182a2016-12-05 13:07:03 -080062import com.android.contacts.list.MultiSelectEntryContactListAdapter.DeleteContactListener;
Gary Mai0a49afa2016-12-05 15:53:58 -080063import com.android.contacts.list.UiIntentActions;
Gary Mai69c182a2016-12-05 13:07:03 -080064import com.android.contacts.logging.ListEvent;
65import com.android.contacts.logging.ListEvent.ListType;
66import com.android.contacts.logging.Logger;
67import com.android.contacts.logging.ScreenEvent;
68import com.android.contacts.model.account.AccountWithDataSet;
69import com.android.contacts.util.ImplicitIntentsUtil;
James Laskey1387e782016-10-26 13:34:23 -070070import com.android.contactsbind.FeedbackHelper;
Sean Midford4b2ccd22016-10-14 13:03:49 -070071import com.google.common.primitives.Longs;
Walter Jang4715c042016-04-06 17:14:23 -070072
Walter Jang2552c112016-06-17 14:29:09 -070073import java.util.ArrayList;
Sean Midford4b2ccd22016-10-14 13:03:49 -070074import java.util.HashMap;
Walter Jang2552c112016-06-17 14:29:09 -070075import java.util.HashSet;
Wenyi Wang38860a52016-06-24 17:47:34 -070076import java.util.List;
Sean Midford4b2ccd22016-10-14 13:03:49 -070077import java.util.Map;
Walter Jang2552c112016-06-17 14:29:09 -070078import java.util.Set;
79
Walter Jang4715c042016-04-06 17:14:23 -070080/** Displays the members of a group. */
Wenyi Wang88a9f242016-08-25 16:07:15 -070081public class GroupMembersFragment extends MultiSelectContactsListFragment<GroupMembersAdapter> {
Walter Jang4715c042016-04-06 17:14:23 -070082
Walter Jang44e91b12016-05-22 12:37:00 -070083 private static final String TAG = "GroupMembers";
84
Wenyi Wang6927bf32016-08-15 18:31:24 -070085 private static final String KEY_IS_EDIT_MODE = "editMode";
Walter Jang44e91b12016-05-22 12:37:00 -070086 private static final String KEY_GROUP_URI = "groupUri";
Walter Jang4715c042016-04-06 17:14:23 -070087 private static final String KEY_GROUP_METADATA = "groupMetadata";
88
Wenyi Wang6927bf32016-08-15 18:31:24 -070089 public static final String TAG_GROUP_NAME_EDIT_DIALOG = "groupNameEditDialog";
90
Walter Jang44e91b12016-05-22 12:37:00 -070091 private static final String ARG_GROUP_URI = "groupUri";
92
93 private static final int LOADER_GROUP_METADATA = 0;
Wenyi Wang17fe7982016-10-05 13:54:09 -070094 private static final int MSG_FAIL_TO_LOAD = 1;
Wenyi Wang6927bf32016-08-15 18:31:24 -070095 private static final int RESULT_GROUP_ADD_MEMBER = 100;
Walter Jang4715c042016-04-06 17:14:23 -070096
Walter Jang2552c112016-06-17 14:29:09 -070097 /** Filters out duplicate contacts. */
98 private class FilterCursorWrapper extends CursorWrapper {
99
100 private int[] mIndex;
101 private int mCount = 0;
102 private int mPos = 0;
103
104 public FilterCursorWrapper(Cursor cursor) {
105 super(cursor);
106
107 mCount = super.getCount();
108 mIndex = new int[mCount];
109
Wenyi Wang38860a52016-06-24 17:47:34 -0700110 final List<Integer> indicesToFilter = new ArrayList<>();
111
Walter Jang2552c112016-06-17 14:29:09 -0700112 if (Log.isLoggable(TAG, Log.VERBOSE)) {
113 Log.v(TAG, "Group members CursorWrapper start: " + mCount);
114 }
115
Wenyi Wang38860a52016-06-24 17:47:34 -0700116 final Bundle bundle = cursor.getExtras();
117 final String sections[] = bundle.getStringArray(Contacts
118 .EXTRA_ADDRESS_BOOK_INDEX_TITLES);
119 final int counts[] = bundle.getIntArray(Contacts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS);
120 final ContactsSectionIndexer indexer = (sections == null || counts == null)
121 ? null : new ContactsSectionIndexer(sections, counts);
122
Walter Jang2552c112016-06-17 14:29:09 -0700123 mGroupMemberContactIds.clear();
124 for (int i = 0; i < mCount; i++) {
125 super.moveToPosition(i);
126 final String contactId = getString(GroupMembersQuery.CONTACT_ID);
127 if (!mGroupMemberContactIds.contains(contactId)) {
128 mIndex[mPos++] = i;
129 mGroupMemberContactIds.add(contactId);
Wenyi Wang38860a52016-06-24 17:47:34 -0700130 } else {
131 indicesToFilter.add(i);
Walter Jang2552c112016-06-17 14:29:09 -0700132 }
133 }
Wenyi Wang38860a52016-06-24 17:47:34 -0700134
135 if (indexer != null && GroupUtil.needTrimming(mCount, counts, indexer.getPositions())) {
136 GroupUtil.updateBundle(bundle, indexer, indicesToFilter, sections, counts);
137 }
138
Walter Jang2552c112016-06-17 14:29:09 -0700139 mCount = mPos;
140 mPos = 0;
141 super.moveToFirst();
142
143 if (Log.isLoggable(TAG, Log.VERBOSE)) {
144 Log.v(TAG, "Group members CursorWrapper end: " + mCount);
145 }
146 }
147
148 @Override
149 public boolean move(int offset) {
150 return moveToPosition(mPos + offset);
151 }
152
153 @Override
154 public boolean moveToNext() {
155 return moveToPosition(mPos + 1);
156 }
157
158 @Override
159 public boolean moveToPrevious() {
160 return moveToPosition(mPos - 1);
161 }
162
163 @Override
164 public boolean moveToFirst() {
165 return moveToPosition(0);
166 }
167
168 @Override
169 public boolean moveToLast() {
170 return moveToPosition(mCount - 1);
171 }
172
173 @Override
174 public boolean moveToPosition(int position) {
John Shao2b0d2982016-07-26 14:50:05 -0700175 if (position >= mCount) {
176 mPos = mCount;
177 return false;
178 } else if (position < 0) {
179 mPos = -1;
180 return false;
181 }
182 mPos = mIndex[position];
183 return super.moveToPosition(mPos);
Walter Jang2552c112016-06-17 14:29:09 -0700184 }
185
186 @Override
187 public int getCount() {
188 return mCount;
189 }
190
191 @Override
192 public int getPosition() {
193 return mPos;
194 }
195 }
196
Walter Jang5a496962016-09-09 18:32:50 -0700197 private final LoaderCallbacks<Cursor> mGroupMetaDataCallbacks = new LoaderCallbacks<Cursor>() {
Walter Jang44e91b12016-05-22 12:37:00 -0700198
199 @Override
200 public CursorLoader onCreateLoader(int id, Bundle args) {
Wenyi Wang79675452016-08-17 10:43:28 -0700201 return new GroupMetaDataLoader(mActivity, mGroupUri);
Walter Jang44e91b12016-05-22 12:37:00 -0700202 }
203
204 @Override
205 public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
206 if (cursor == null || cursor.isClosed() || !cursor.moveToNext()) {
207 Log.e(TAG, "Failed to load group metadata for " + mGroupUri);
Wenyi Wang6927bf32016-08-15 18:31:24 -0700208 Toast.makeText(getContext(), R.string.groupLoadErrorToast, Toast.LENGTH_SHORT)
209 .show();
Wenyi Wang17fe7982016-10-05 13:54:09 -0700210 mHandler.sendEmptyMessage(MSG_FAIL_TO_LOAD);
Walter Jang44e91b12016-05-22 12:37:00 -0700211 return;
212 }
Walter Jang428824e2016-09-09 13:18:35 -0700213 mGroupMetaData = new GroupMetaData(getActivity(), cursor);
Walter Jang44e91b12016-05-22 12:37:00 -0700214 onGroupMetadataLoaded();
215 }
216
217 @Override
218 public void onLoaderReset(Loader<Cursor> loader) {}
219 };
220
Wenyi Wang6927bf32016-08-15 18:31:24 -0700221 private ActionBarAdapter mActionBarAdapter;
222
Wenyi Wang79675452016-08-17 10:43:28 -0700223 private ContactsDrawerActivity mActivity;
224
Walter Jang44e91b12016-05-22 12:37:00 -0700225 private Uri mGroupUri;
226
Wenyi Wang6927bf32016-08-15 18:31:24 -0700227 private boolean mIsEditMode;
Walter Jang4715c042016-04-06 17:14:23 -0700228
Walter Jang428824e2016-09-09 13:18:35 -0700229 private GroupMetaData mGroupMetaData;
Walter Jang4715c042016-04-06 17:14:23 -0700230
Walter Jang2552c112016-06-17 14:29:09 -0700231 private Set<String> mGroupMemberContactIds = new HashSet();
232
Wenyi Wang17fe7982016-10-05 13:54:09 -0700233 private Handler mHandler = new Handler() {
234 @Override
235 public void handleMessage(Message msg) {
236 if(msg.what == MSG_FAIL_TO_LOAD) {
237 mActivity.onBackPressed();
238 }
239 }
240 };
241
Walter Jang90f2fe52016-06-17 16:38:43 -0700242 public static GroupMembersFragment newInstance(Uri groupUri) {
Walter Jang0680a312016-05-18 13:09:01 -0700243 final Bundle args = new Bundle();
Walter Jang44e91b12016-05-22 12:37:00 -0700244 args.putParcelable(ARG_GROUP_URI, groupUri);
Walter Jang0680a312016-05-18 13:09:01 -0700245
Walter Jang90f2fe52016-06-17 16:38:43 -0700246 final GroupMembersFragment fragment = new GroupMembersFragment();
Walter Jang0680a312016-05-18 13:09:01 -0700247 fragment.setArguments(args);
248 return fragment;
249 }
250
Walter Jang90f2fe52016-06-17 16:38:43 -0700251 public GroupMembersFragment() {
Walter Jang4715c042016-04-06 17:14:23 -0700252 setPhotoLoaderEnabled(true);
253 setSectionHeaderDisplayEnabled(true);
Walter Jangdebf9da2016-06-20 12:42:27 -0700254 setHasOptionsMenu(true);
Wenyi Wang2b943992016-05-20 17:21:35 -0700255 setListType(ListType.GROUP);
Walter Jang4715c042016-04-06 17:14:23 -0700256 }
257
Wenyi Wang6927bf32016-08-15 18:31:24 -0700258 @Override
259 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
Walter Jang5a496962016-09-09 18:32:50 -0700260 if (mGroupMetaData == null) {
Wenyi Wang6927bf32016-08-15 18:31:24 -0700261 // Hide menu options until metadata is fully loaded
262 return;
263 }
Wenyi Wang6927bf32016-08-15 18:31:24 -0700264 inflater.inflate(R.menu.view_group, menu);
265 }
266
267 @Override
268 public void onPrepareOptionsMenu(Menu menu) {
269 final boolean isSelectionMode = mActionBarAdapter.isSelectionMode();
Walter Jang5a496962016-09-09 18:32:50 -0700270 final boolean isGroupEditable = mGroupMetaData != null && mGroupMetaData.editable;
271 final boolean isGroupReadOnly = mGroupMetaData != null && mGroupMetaData.readOnly;
Wenyi Wang6927bf32016-08-15 18:31:24 -0700272
John Shaobd9ef3c2016-12-15 12:42:03 -0800273 setVisible(getContext(), menu, R.id.menu_multi_send_email, !mIsEditMode && !isGroupEmpty());
274 setVisible(getContext(), menu, R.id.menu_multi_send_message,
275 !mIsEditMode && !isGroupEmpty());
276 setVisible(getContext(), menu, R.id.menu_add, isGroupEditable && !isSelectionMode);
277 setVisible(getContext(), menu, R.id.menu_rename_group,
278 !isGroupReadOnly && !isSelectionMode);
279 setVisible(getContext(), menu, R.id.menu_delete_group,
280 !isGroupReadOnly && !isSelectionMode);
281 setVisible(getContext(), menu, R.id.menu_edit_group,
282 isGroupEditable && !mIsEditMode && !isSelectionMode && !isGroupEmpty());
283 setVisible(getContext(), menu, R.id.menu_remove_from_group,
284 isGroupEditable && isSelectionMode && !mIsEditMode);
Wenyi Wang6927bf32016-08-15 18:31:24 -0700285 }
286
287 private boolean isGroupEmpty() {
288 return getAdapter() != null && getAdapter().isEmpty();
289 }
290
John Shaobd9ef3c2016-12-15 12:42:03 -0800291 private static void setVisible(Context context, Menu menu, int id, boolean visible) {
Wenyi Wang6927bf32016-08-15 18:31:24 -0700292 final MenuItem menuItem = menu.findItem(id);
293 if (menuItem != null) {
294 menuItem.setVisible(visible);
John Shaobd9ef3c2016-12-15 12:42:03 -0800295 final Drawable icon = menuItem.getIcon();
296 if (icon != null) {
297 icon.mutate().setColorFilter(ContextCompat.getColor(context,
298 R.color.actionbar_icon_color), PorterDuff.Mode.SRC_ATOP);
299 }
Wenyi Wang6927bf32016-08-15 18:31:24 -0700300 }
301 }
302
Sean Midfordff6f1bb2016-10-12 09:48:23 -0700303 /**
304 * Helper class for cp2 query used to look up all contact's emails and phone numbers.
305 */
Sean Midford9970f302016-11-07 12:23:45 -0800306 public static abstract class Query {
Sean Midfordff6f1bb2016-10-12 09:48:23 -0700307 public static final String EMAIL_SELECTION =
308 ContactsContract.Data.MIMETYPE + "='"
309 + ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE + "'";
310
311 public static final String PHONE_SELECTION =
312 ContactsContract.Data.MIMETYPE + "='"
313 + ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "'";
314
Sean Midford4b2ccd22016-10-14 13:03:49 -0700315 public static final String[] EMAIL_PROJECTION = {
Sean Midfordff6f1bb2016-10-12 09:48:23 -0700316 ContactsContract.Data.CONTACT_ID,
Sean Midford4b2ccd22016-10-14 13:03:49 -0700317 ContactsContract.CommonDataKinds.Email._ID,
318 ContactsContract.Data.IS_SUPER_PRIMARY,
Sean Midford009bb752016-10-27 14:18:22 -0700319 ContactsContract.Data.TIMES_USED,
Sean Midfordff6f1bb2016-10-12 09:48:23 -0700320 ContactsContract.Data.DATA1
321 };
322
Sean Midford4b2ccd22016-10-14 13:03:49 -0700323 public static final String[] PHONE_PROJECTION = {
324 ContactsContract.Data.CONTACT_ID,
325 ContactsContract.CommonDataKinds.Phone._ID,
326 ContactsContract.Data.IS_SUPER_PRIMARY,
Sean Midford009bb752016-10-27 14:18:22 -0700327 ContactsContract.Data.TIMES_USED,
Sean Midford4b2ccd22016-10-14 13:03:49 -0700328 ContactsContract.Data.DATA1
329 };
330
331 public static final int CONTACT_ID = 0;
332 public static final int ITEM_ID = 1;
333 public static final int PRIMARY = 2;
Sean Midford009bb752016-10-27 14:18:22 -0700334 public static final int TIMES_USED = 3;
335 public static final int DATA1 = 4;
336 }
337
338 /**
339 * Helper class for managing data related to contacts and emails/phone numbers.
340 */
341 private class ContactDataHelperClass {
342
343 private List<String> items = new ArrayList<>();
344 private String mostUsedItemId = null;
345 private int mostUsedTimes;
346 private String primaryItemId = null;
347
348 public void addItem(String item, int timesUsed, boolean primaryFlag) {
349 if (mostUsedItemId == null || timesUsed > mostUsedTimes) {
350 mostUsedItemId = item;
351 mostUsedTimes = timesUsed;
352 }
353 if (primaryFlag) {
354 primaryItemId = item;
355 }
356 items.add(item);
357 }
358
359 public boolean hasDefaultItem() {
360 return primaryItemId != null || items.size() == 1;
361 }
362
363 public String getDefaultSelectionItemId() {
364 return primaryItemId != null
365 ? primaryItemId
366 : mostUsedItemId;
367 }
Sean Midfordff6f1bb2016-10-12 09:48:23 -0700368 }
369
370 private void sendToGroup(long[] ids, String sendScheme, String title) {
Gary Mai4ac56292016-10-31 10:41:11 -0700371 if (ids == null || ids.length == 0) return;
Sean Midfordff6f1bb2016-10-12 09:48:23 -0700372
373 // Get emails or phone numbers
Sean Midford009bb752016-10-27 14:18:22 -0700374 // contactMap <contact_id, contact_data>
375 final Map<String, ContactDataHelperClass> contactMap = new HashMap<>();
Sean Midford4b2ccd22016-10-14 13:03:49 -0700376 // itemList <item_data>
377 final List<String> itemList = new ArrayList<>();
Sean Midfordff6f1bb2016-10-12 09:48:23 -0700378 final String sIds = GroupUtil.convertArrayToString(ids);
379 final String select = (ContactsUtils.SCHEME_MAILTO.equals(sendScheme)
Sean Midfordb460f442016-10-13 10:42:35 -0700380 ? Query.EMAIL_SELECTION
381 : Query.PHONE_SELECTION)
Sean Midfordff6f1bb2016-10-12 09:48:23 -0700382 + " AND " + ContactsContract.Data.CONTACT_ID + " IN (" + sIds + ")";
383 final ContentResolver contentResolver = getContext().getContentResolver();
384 final Cursor cursor = contentResolver.query(ContactsContract.Data.CONTENT_URI,
Sean Midford4b2ccd22016-10-14 13:03:49 -0700385 ContactsUtils.SCHEME_MAILTO.equals(sendScheme)
386 ? Query.EMAIL_PROJECTION
387 : Query.PHONE_PROJECTION,
388 select, null, null);
Sean Midfordff6f1bb2016-10-12 09:48:23 -0700389
390 if (cursor == null) {
391 return;
392 }
393
394 try {
395 cursor.moveToPosition(-1);
396 while (cursor.moveToNext()) {
Sean Midford4b2ccd22016-10-14 13:03:49 -0700397 final String contactId = cursor.getString(Query.CONTACT_ID);
398 final String itemId = cursor.getString(Query.ITEM_ID);
399 final boolean isPrimary = cursor.getInt(Query.PRIMARY) != 0;
Sean Midford009bb752016-10-27 14:18:22 -0700400 final int timesUsed = cursor.getInt(Query.TIMES_USED);
Sean Midfordb460f442016-10-13 10:42:35 -0700401 final String data = cursor.getString(Query.DATA1);
Sean Midfordff6f1bb2016-10-12 09:48:23 -0700402
Sean Midford4b2ccd22016-10-14 13:03:49 -0700403 if (!TextUtils.isEmpty(data)) {
Sean Midford009bb752016-10-27 14:18:22 -0700404 final ContactDataHelperClass contact;
405 if (!contactMap.containsKey(contactId)) {
406 contact = new ContactDataHelperClass();
407 contactMap.put(contactId, contact);
408 } else {
409 contact = contactMap.get(contactId);
410 }
411 contact.addItem(itemId, timesUsed, isPrimary);
Sean Midford4b2ccd22016-10-14 13:03:49 -0700412 itemList.add(data);
Sean Midfordff6f1bb2016-10-12 09:48:23 -0700413 }
414 }
415 } finally {
416 cursor.close();
417 }
418
Sean Midford009bb752016-10-27 14:18:22 -0700419 // Start picker if a contact does not have a default
420 for (ContactDataHelperClass i : contactMap.values()) {
421 if (!i.hasDefaultItem()) {
Sean Midford4b2ccd22016-10-14 13:03:49 -0700422 // Build list of default selected item ids
423 final List<Long> defaultSelection = new ArrayList<>();
Sean Midford009bb752016-10-27 14:18:22 -0700424 for (ContactDataHelperClass j : contactMap.values()) {
425 final String selectionItemId = j.getDefaultSelectionItemId();
426 if (selectionItemId != null) {
427 defaultSelection.add(Long.parseLong(selectionItemId));
Sean Midford4b2ccd22016-10-14 13:03:49 -0700428 }
429 }
430 final long[] defaultSelectionArray = Longs.toArray(defaultSelection);
431 startSendToSelectionPickerActivity(ids, defaultSelectionArray, sendScheme, title);
432 return;
433 }
434 }
435
Sean Midford009bb752016-10-27 14:18:22 -0700436 if (itemList.size() == 0 || contactMap.size() < ids.length) {
Sean Midfordff6f1bb2016-10-12 09:48:23 -0700437 Toast.makeText(getContext(), ContactsUtils.SCHEME_MAILTO.equals(sendScheme)
438 ? getString(R.string.groupSomeContactsNoEmailsToast)
439 : getString(R.string.groupSomeContactsNoPhonesToast),
440 Toast.LENGTH_LONG).show();
441 }
442
Sean Midford4b2ccd22016-10-14 13:03:49 -0700443 if (itemList.size() == 0) {
Sean Midfordff6f1bb2016-10-12 09:48:23 -0700444 return;
445 }
446
Sean Midford4b2ccd22016-10-14 13:03:49 -0700447 final String itemsString = TextUtils.join(",", itemList);
Sean Midford9970f302016-11-07 12:23:45 -0800448 GroupUtil.startSendToSelectionActivity(this, itemsString, sendScheme, title);
Sean Midfordff6f1bb2016-10-12 09:48:23 -0700449 }
450
Sean Midford4b2ccd22016-10-14 13:03:49 -0700451 private void startSendToSelectionPickerActivity(long[] ids, long[] defaultSelection,
452 String sendScheme, String title) {
Sean Midford9970f302016-11-07 12:23:45 -0800453 startActivity(GroupUtil.createSendToSelectionPickerIntent(getContext(), ids,
454 defaultSelection, sendScheme, title));
Sean Midfordff6f1bb2016-10-12 09:48:23 -0700455 }
456
Wenyi Wang6927bf32016-08-15 18:31:24 -0700457 private void startGroupAddMemberActivity() {
Walter Jang5a496962016-09-09 18:32:50 -0700458 startActivityForResult(GroupUtil.createPickMemberIntent(getContext(), mGroupMetaData,
Wenyi Wang6927bf32016-08-15 18:31:24 -0700459 getMemberContactIds()), RESULT_GROUP_ADD_MEMBER);
460 }
461
462 @Override
463 public boolean onOptionsItemSelected(MenuItem item) {
464 switch (item.getItemId()) {
465 case android.R.id.home: {
Wenyi Wang79675452016-08-17 10:43:28 -0700466 mActivity.onBackPressed();
Wenyi Wang6927bf32016-08-15 18:31:24 -0700467 return true;
468 }
469 case R.id.menu_add: {
470 startGroupAddMemberActivity();
471 return true;
472 }
Sean Midfordff6f1bb2016-10-12 09:48:23 -0700473 case R.id.menu_multi_send_email: {
474 final long[] ids = mActionBarAdapter.isSelectionMode()
475 ? getAdapter().getSelectedContactIdsArray()
476 : GroupUtil.convertStringSetToLongArray(mGroupMemberContactIds);
477 sendToGroup(ids, ContactsUtils.SCHEME_MAILTO,
478 getString(R.string.menu_sendEmailOption));
479 return true;
480 }
481 case R.id.menu_multi_send_message: {
482 final long[] ids = mActionBarAdapter.isSelectionMode()
483 ? getAdapter().getSelectedContactIdsArray()
484 : GroupUtil.convertStringSetToLongArray(mGroupMemberContactIds);
485 sendToGroup(ids, ContactsUtils.SCHEME_SMSTO,
486 getString(R.string.menu_sendMessageOption));
487 return true;
488 }
Wenyi Wang6927bf32016-08-15 18:31:24 -0700489 case R.id.menu_rename_group: {
490 GroupNameEditDialogFragment.newInstanceForUpdate(
Walter Jang5a496962016-09-09 18:32:50 -0700491 new AccountWithDataSet(mGroupMetaData.accountName,
492 mGroupMetaData.accountType, mGroupMetaData.dataSet),
493 GroupUtil.ACTION_UPDATE_GROUP, mGroupMetaData.groupId,
494 mGroupMetaData.groupName).show(getFragmentManager(),
Wenyi Wang6927bf32016-08-15 18:31:24 -0700495 TAG_GROUP_NAME_EDIT_DIALOG);
496 return true;
497 }
498 case R.id.menu_delete_group: {
499 deleteGroup();
500 return true;
501 }
502 case R.id.menu_edit_group: {
503 mIsEditMode = true;
504 mActionBarAdapter.setSelectionMode(true);
505 displayDeleteButtons(true);
506 return true;
507 }
508 case R.id.menu_remove_from_group: {
509 logListEvent();
510 removeSelectedContacts();
511 return true;
512 }
513 }
514 return super.onOptionsItemSelected(item);
515 }
516
517 private void removeSelectedContacts() {
518 final long[] contactIds = getAdapter().getSelectedContactIdsArray();
519 new UpdateGroupMembersAsyncTask(UpdateGroupMembersAsyncTask.TYPE_REMOVE,
Walter Jang5a496962016-09-09 18:32:50 -0700520 getContext(), contactIds, mGroupMetaData.groupId, mGroupMetaData.accountName,
Walter Jang792dae72016-09-14 13:04:00 -0700521 mGroupMetaData.accountType, mGroupMetaData.dataSet).execute();
Wenyi Wang6927bf32016-08-15 18:31:24 -0700522
523 mActionBarAdapter.setSelectionMode(false);
524 }
525
526 @Override
527 public void onActivityResult(int requestCode, int resultCode, Intent data) {
Sean Midford9970f302016-11-07 12:23:45 -0800528 if (resultCode != Activity.RESULT_OK || data == null
529 || requestCode != RESULT_GROUP_ADD_MEMBER) {
Sean Midfordb460f442016-10-13 10:42:35 -0700530 return;
531 }
Sean Midford9970f302016-11-07 12:23:45 -0800532
533 long[] contactIds = data.getLongArrayExtra(
534 UiIntentActions.TARGET_CONTACT_IDS_EXTRA_KEY);
535 if (contactIds == null) {
536 final long contactId = data.getLongExtra(
537 UiIntentActions.TARGET_CONTACT_ID_EXTRA_KEY, -1);
538 if (contactId > -1) {
539 contactIds = new long[1];
540 contactIds[0] = contactId;
Sean Midfordb460f442016-10-13 10:42:35 -0700541 }
Wenyi Wang6927bf32016-08-15 18:31:24 -0700542 }
Sean Midford9970f302016-11-07 12:23:45 -0800543 new UpdateGroupMembersAsyncTask(
544 UpdateGroupMembersAsyncTask.TYPE_ADD,
545 getContext(), contactIds, mGroupMetaData.groupId, mGroupMetaData.accountName,
546 mGroupMetaData.accountType, mGroupMetaData.dataSet).execute();
Wenyi Wang6927bf32016-08-15 18:31:24 -0700547 }
548
Wenyi Wang88a9f242016-08-25 16:07:15 -0700549 private final ActionBarAdapter.Listener mActionBarListener = new ActionBarAdapter.Listener() {
550 @Override
551 public void onAction(int action) {
552 switch (action) {
553 case ActionBarAdapter.Listener.Action.START_SELECTION_MODE:
554 if (mIsEditMode) {
555 displayDeleteButtons(true);
556 mActionBarAdapter.setActionBarTitle(getString(R.string.title_edit_group));
557 } else {
558 displayCheckBoxes(true);
559 }
Wenyi Wang79675452016-08-17 10:43:28 -0700560 mActivity.invalidateOptionsMenu();
Wenyi Wang88a9f242016-08-25 16:07:15 -0700561 break;
562 case ActionBarAdapter.Listener.Action.STOP_SEARCH_AND_SELECTION_MODE:
563 mActionBarAdapter.setSearchMode(false);
564 if (mIsEditMode) {
565 displayDeleteButtons(false);
566 } else {
567 displayCheckBoxes(false);
568 }
Wenyi Wang79675452016-08-17 10:43:28 -0700569 mActivity.invalidateOptionsMenu();
Wenyi Wang88a9f242016-08-25 16:07:15 -0700570 break;
571 case ActionBarAdapter.Listener.Action.BEGIN_STOPPING_SEARCH_AND_SELECTION_MODE:
572 break;
573 }
574 }
Wenyi Wang6927bf32016-08-15 18:31:24 -0700575
Wenyi Wang88a9f242016-08-25 16:07:15 -0700576 @Override
577 public void onUpButtonPressed() {
Wenyi Wang79675452016-08-17 10:43:28 -0700578 mActivity.onBackPressed();
Wenyi Wang88a9f242016-08-25 16:07:15 -0700579 }
580 };
581
582 private final OnCheckBoxListActionListener mCheckBoxListener =
583 new OnCheckBoxListActionListener() {
584 @Override
585 public void onStartDisplayingCheckBoxes() {
586 mActionBarAdapter.setSelectionMode(true);
Wenyi Wang6927bf32016-08-15 18:31:24 -0700587 }
Wenyi Wang88a9f242016-08-25 16:07:15 -0700588
589 @Override
590 public void onSelectedContactIdsChanged() {
591 if (mActionBarAdapter == null) {
592 return;
593 }
594 if (mIsEditMode) {
595 mActionBarAdapter.setActionBarTitle(getString(R.string.title_edit_group));
596 } else {
597 mActionBarAdapter.setSelectionCount(getSelectedContactIds().size());
598 }
Wenyi Wang6927bf32016-08-15 18:31:24 -0700599 }
Wenyi Wang6927bf32016-08-15 18:31:24 -0700600
Wenyi Wang88a9f242016-08-25 16:07:15 -0700601 @Override
602 public void onStopDisplayingCheckBoxes() {
603 mActionBarAdapter.setSelectionMode(false);
604 }
605 };
Wenyi Wang6927bf32016-08-15 18:31:24 -0700606
607 private void logListEvent() {
608 Logger.logListEvent(
609 ListEvent.ActionType.REMOVE_LABEL,
610 getListType(),
611 getAdapter().getCount(),
612 /* clickedIndex */ -1,
613 getAdapter().getSelectedContactIdsArray().length);
614 }
615
616 private void deleteGroup() {
617 if (getMemberCount() == 0) {
618 final Intent intent = ContactSaveService.createGroupDeletionIntent(
Walter Jang5a496962016-09-09 18:32:50 -0700619 getContext(), mGroupMetaData.groupId);
Wenyi Wang6927bf32016-08-15 18:31:24 -0700620 getContext().startService(intent);
Wenyi Wang79675452016-08-17 10:43:28 -0700621 mActivity.switchToAllContacts();
Wenyi Wang6927bf32016-08-15 18:31:24 -0700622 } else {
Walter Jang5a496962016-09-09 18:32:50 -0700623 GroupDeletionDialogFragment.show(getFragmentManager(), mGroupMetaData.groupId,
624 mGroupMetaData.groupName);
Wenyi Wang6927bf32016-08-15 18:31:24 -0700625 }
626 }
627
628 @Override
629 public void onActivityCreated(Bundle savedInstanceState) {
630 super.onActivityCreated(savedInstanceState);
Wenyi Wang79675452016-08-17 10:43:28 -0700631 mActivity = (ContactsDrawerActivity) getActivity();
632 mActionBarAdapter = new ActionBarAdapter(mActivity, mActionBarListener,
Wenyi Wangf6606072016-10-03 17:34:53 -0700633 mActivity.getSupportActionBar(), mActivity.getToolbar(),
634 R.string.enter_contact_name);
Wenyi Wang6927bf32016-08-15 18:31:24 -0700635 mActionBarAdapter.setShowHomeIcon(true);
636 final ContactsRequest contactsRequest = new ContactsRequest();
637 contactsRequest.setActionCode(ContactsRequest.ACTION_GROUP);
638 mActionBarAdapter.initialize(savedInstanceState, contactsRequest);
Walter Jang5a496962016-09-09 18:32:50 -0700639 if (mGroupMetaData != null) {
640 mActivity.setTitle(mGroupMetaData.groupName);
641 if (mGroupMetaData.editable) {
Wenyi Wang79675452016-08-17 10:43:28 -0700642 setCheckBoxListListener(mCheckBoxListener);
643 }
644 }
Wenyi Wang6927bf32016-08-15 18:31:24 -0700645 }
646
Wenyi Wang79675452016-08-17 10:43:28 -0700647 @Override
Wenyi Wang6927bf32016-08-15 18:31:24 -0700648 public ActionBarAdapter getActionBarAdapter() {
649 return mActionBarAdapter;
Walter Jang4715c042016-04-06 17:14:23 -0700650 }
651
Walter Jang05e71472016-06-23 19:00:10 -0700652 public void displayDeleteButtons(boolean displayDeleteButtons) {
653 getAdapter().setDisplayDeleteButtons(displayDeleteButtons);
654 }
655
Walter Jang2552c112016-06-17 14:29:09 -0700656 public ArrayList<String> getMemberContactIds() {
Wenyi Wang79675452016-08-17 10:43:28 -0700657 return new ArrayList<>(mGroupMemberContactIds);
Walter Jang2552c112016-06-17 14:29:09 -0700658 }
659
660 public int getMemberCount() {
661 return mGroupMemberContactIds.size();
662 }
663
Wenyi Wang6927bf32016-08-15 18:31:24 -0700664 public boolean isEditMode() {
665 return mIsEditMode;
666 }
667
Walter Jang4715c042016-04-06 17:14:23 -0700668 @Override
669 public void onCreate(Bundle savedState) {
670 super.onCreate(savedState);
Walter Jang0680a312016-05-18 13:09:01 -0700671 if (savedState == null) {
Walter Jang44e91b12016-05-22 12:37:00 -0700672 mGroupUri = getArguments().getParcelable(ARG_GROUP_URI);
Walter Jang0680a312016-05-18 13:09:01 -0700673 } else {
Wenyi Wang6927bf32016-08-15 18:31:24 -0700674 mIsEditMode = savedState.getBoolean(KEY_IS_EDIT_MODE);
Walter Jang44e91b12016-05-22 12:37:00 -0700675 mGroupUri = savedState.getParcelable(KEY_GROUP_URI);
Walter Jang428824e2016-09-09 13:18:35 -0700676 mGroupMetaData = savedState.getParcelable(KEY_GROUP_METADATA);
Walter Jang4715c042016-04-06 17:14:23 -0700677 }
Wenyi Wang88a9f242016-08-25 16:07:15 -0700678 maybeAttachCheckBoxListener();
679 }
680
681 @Override
682 public void onResume() {
683 super.onResume();
684 // Re-register the listener, which may have been cleared when onSaveInstanceState was
685 // called. See also: onSaveInstanceState
686 mActionBarAdapter.setListener(mActionBarListener);
Walter Jang0680a312016-05-18 13:09:01 -0700687 }
688
689 @Override
Walter Jang44e91b12016-05-22 12:37:00 -0700690 protected void startLoading() {
Walter Jang428824e2016-09-09 13:18:35 -0700691 if (mGroupMetaData == null || !mGroupMetaData.isValid()) {
Walter Jang5a496962016-09-09 18:32:50 -0700692 getLoaderManager().restartLoader(LOADER_GROUP_METADATA, null, mGroupMetaDataCallbacks);
Walter Jang44e91b12016-05-22 12:37:00 -0700693 } else {
694 onGroupMetadataLoaded();
695 }
Walter Jang4715c042016-04-06 17:14:23 -0700696 }
697
698 @Override
Walter Jang2552c112016-06-17 14:29:09 -0700699 public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
700 if (data != null) {
Walter Jangdebf9da2016-06-20 12:42:27 -0700701 // Wait until contacts are loaded before showing the scrollbar
702 setVisibleScrollbarEnabled(true);
703
Walter Jang2552c112016-06-17 14:29:09 -0700704 final FilterCursorWrapper cursorWrapper = new FilterCursorWrapper(data);
705 bindMembersCount(cursorWrapper.getCount());
706 super.onLoadFinished(loader, cursorWrapper);
Wenyi Wang35e6f742016-08-01 15:16:47 -0700707 // Update state of menu items (e.g. "Remove contacts") based on number of group members.
Wenyi Wang79675452016-08-17 10:43:28 -0700708 mActivity.invalidateOptionsMenu();
Walter Jang2552c112016-06-17 14:29:09 -0700709 }
710 }
711
712 private void bindMembersCount(int memberCount) {
713 final View accountFilterContainer = getView().findViewById(
714 R.id.account_filter_header_container);
yaolud8effeb2016-06-29 14:42:38 -0700715 final View emptyGroupView = getView().findViewById(R.id.empty_group);
716 if (memberCount > 0) {
Wenyi Wang1114fde2016-07-11 21:44:02 -0700717 final AccountWithDataSet accountWithDataSet = new AccountWithDataSet(
Walter Jang428824e2016-09-09 13:18:35 -0700718 mGroupMetaData.accountName, mGroupMetaData.accountType, mGroupMetaData.dataSet);
Wenyi Wang1114fde2016-07-11 21:44:02 -0700719 bindListHeader(getContext(), getListView(), accountFilterContainer,
720 accountWithDataSet, memberCount);
yaolud8effeb2016-06-29 14:42:38 -0700721 emptyGroupView.setVisibility(View.GONE);
Walter Jang2552c112016-06-17 14:29:09 -0700722 } else {
Wenyi Wang1114fde2016-07-11 21:44:02 -0700723 hideHeaderAndAddPadding(getContext(), getListView(), accountFilterContainer);
yaolud8effeb2016-06-29 14:42:38 -0700724 emptyGroupView.setVisibility(View.VISIBLE);
Walter Jang2552c112016-06-17 14:29:09 -0700725 }
726 }
727
728 @Override
Walter Jang4715c042016-04-06 17:14:23 -0700729 public void onSaveInstanceState(Bundle outState) {
730 super.onSaveInstanceState(outState);
Wenyi Wang6927bf32016-08-15 18:31:24 -0700731 if (mActionBarAdapter != null) {
Wenyi Wang88a9f242016-08-25 16:07:15 -0700732 mActionBarAdapter.setListener(null);
Wenyi Wang6927bf32016-08-15 18:31:24 -0700733 mActionBarAdapter.onSaveInstanceState(outState);
734 }
735 outState.putBoolean(KEY_IS_EDIT_MODE, mIsEditMode);
Walter Jang44e91b12016-05-22 12:37:00 -0700736 outState.putParcelable(KEY_GROUP_URI, mGroupUri);
Walter Jang428824e2016-09-09 13:18:35 -0700737 outState.putParcelable(KEY_GROUP_METADATA, mGroupMetaData);
Walter Jang4715c042016-04-06 17:14:23 -0700738 }
739
Walter Jang44e91b12016-05-22 12:37:00 -0700740 private void onGroupMetadataLoaded() {
Walter Jang428824e2016-09-09 13:18:35 -0700741 if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "Loaded " + mGroupMetaData);
Walter Jang44e91b12016-05-22 12:37:00 -0700742
743 maybeAttachCheckBoxListener();
744
Walter Jang5a496962016-09-09 18:32:50 -0700745 mActivity.setTitle(mGroupMetaData.groupName);
746 mActivity.updateGroupMenu(mGroupMetaData);
Wenyi Wang79675452016-08-17 10:43:28 -0700747 mActivity.invalidateOptionsMenu();
Walter Jang44e91b12016-05-22 12:37:00 -0700748
749 // Start loading the group members
750 super.startLoading();
751 }
752
753 private void maybeAttachCheckBoxListener() {
754 // Don't attach the multi select check box listener if we can't edit the group
Walter Jang428824e2016-09-09 13:18:35 -0700755 if (mGroupMetaData != null && mGroupMetaData.editable) {
Wenyi Wang88a9f242016-08-25 16:07:15 -0700756 setCheckBoxListListener(mCheckBoxListener);
Walter Jang44e91b12016-05-22 12:37:00 -0700757 }
Walter Jang4715c042016-04-06 17:14:23 -0700758 }
759
760 @Override
Walter Jang90f2fe52016-06-17 16:38:43 -0700761 protected GroupMembersAdapter createListAdapter() {
762 final GroupMembersAdapter adapter = new GroupMembersAdapter(getContext());
Walter Jangdebf9da2016-06-20 12:42:27 -0700763 adapter.setSectionHeaderDisplayEnabled(true);
Walter Jang4715c042016-04-06 17:14:23 -0700764 adapter.setDisplayPhotos(true);
Wenyi Wang88a9f242016-08-25 16:07:15 -0700765 adapter.setDeleteContactListener(new DeletionListener());
Walter Jang4715c042016-04-06 17:14:23 -0700766 return adapter;
767 }
768
769 @Override
Walter Jang4715c042016-04-06 17:14:23 -0700770 protected void configureAdapter() {
771 super.configureAdapter();
Walter Jang428824e2016-09-09 13:18:35 -0700772 if (mGroupMetaData != null) {
773 getAdapter().setGroupId(mGroupMetaData.groupId);
Walter Jang44e91b12016-05-22 12:37:00 -0700774 }
Walter Jang4715c042016-04-06 17:14:23 -0700775 }
776
777 @Override
778 protected View inflateView(LayoutInflater inflater, ViewGroup container) {
yaolud8effeb2016-06-29 14:42:38 -0700779 final View view = inflater.inflate(R.layout.contact_list_content, /* root */ null);
780 final View emptyGroupView = inflater.inflate(R.layout.empty_group_view, null);
yaolub5046052016-07-28 15:34:02 -0700781
yaolud8effeb2016-06-29 14:42:38 -0700782 final ImageView image = (ImageView) emptyGroupView.findViewById(R.id.empty_group_image);
783 final LinearLayout.LayoutParams params =
784 (LinearLayout.LayoutParams) image.getLayoutParams();
yaolub5046052016-07-28 15:34:02 -0700785 final int screenHeight = getResources().getDisplayMetrics().heightPixels;
786 params.setMargins(0, screenHeight /
787 getResources().getInteger(R.integer.empty_group_view_image_margin_divisor), 0, 0);
yaolud8effeb2016-06-29 14:42:38 -0700788 params.gravity = Gravity.CENTER_HORIZONTAL;
789 image.setLayoutParams(params);
790
791 final FrameLayout contactListLayout = (FrameLayout) view.findViewById(R.id.contact_list);
792 contactListLayout.addView(emptyGroupView);
793
794 final Button addContactsButton =
795 (Button) emptyGroupView.findViewById(R.id.add_member_button);
796 addContactsButton.setOnClickListener(new View.OnClickListener() {
797 @Override
798 public void onClick(View v) {
Wenyi Wang6927bf32016-08-15 18:31:24 -0700799 startActivityForResult(GroupUtil.createPickMemberIntent(getContext(),
Walter Jang5a496962016-09-09 18:32:50 -0700800 mGroupMetaData, getMemberContactIds()), RESULT_GROUP_ADD_MEMBER);
yaolud8effeb2016-06-29 14:42:38 -0700801 }
802 });
803 return view;
Walter Jang4715c042016-04-06 17:14:23 -0700804 }
805
806 @Override
807 protected void onItemClick(int position, long id) {
Walter Jang8b8b30c2016-05-12 19:07:13 -0700808 final Uri uri = getAdapter().getContactUri(position);
809 if (uri == null) {
810 return;
811 }
812 if (getAdapter().isDisplayingCheckBoxes()) {
813 super.onItemClick(position, id);
814 return;
815 }
Wenyi Wang6927bf32016-08-15 18:31:24 -0700816 final int count = getAdapter().getCount();
817 Logger.logListEvent(ListEvent.ActionType.CLICK, ListEvent.ListType.GROUP, count,
818 /* clickedIndex */ position, /* numSelected */ 0);
Walter Jang0396cf72016-09-21 13:23:29 -0700819 ImplicitIntentsUtil.startQuickContact(
820 getActivity(), uri, ScreenEvent.ScreenType.LIST_GROUP);
Walter Jang4715c042016-04-06 17:14:23 -0700821 }
Walter Jangec807e12016-06-27 12:10:40 -0700822
823 @Override
824 protected boolean onItemLongClick(int position, long id) {
Wenyi Wang79675452016-08-17 10:43:28 -0700825 if (mActivity != null && mIsEditMode) {
826 return true;
Walter Jangec807e12016-06-27 12:10:40 -0700827 }
828 return super.onItemLongClick(position, id);
829 }
Tingting Wang4e2656f2016-06-28 22:58:43 -0700830
Wenyi Wang88a9f242016-08-25 16:07:15 -0700831 private final class DeletionListener implements DeleteContactListener {
832 @Override
833 public void onContactDeleteClicked(int position) {
834 final long contactId = getAdapter().getContactId(position);
835 final long[] contactIds = new long[1];
836 contactIds[0] = contactId;
837 new UpdateGroupMembersAsyncTask(UpdateGroupMembersAsyncTask.TYPE_REMOVE,
Walter Jang5a496962016-09-09 18:32:50 -0700838 getContext(), contactIds, mGroupMetaData.groupId, mGroupMetaData.accountName,
Walter Jang792dae72016-09-14 13:04:00 -0700839 mGroupMetaData.accountType, mGroupMetaData.dataSet).execute();
Wenyi Wang88a9f242016-08-25 16:07:15 -0700840 }
Wenyi Wang6927bf32016-08-15 18:31:24 -0700841 }
842
Walter Jang5a496962016-09-09 18:32:50 -0700843 public GroupMetaData getGroupMetaData() {
844 return mGroupMetaData;
Tingting Wang4e2656f2016-06-28 22:58:43 -0700845 }
Wenyi Wang88a9f242016-08-25 16:07:15 -0700846
Wenyi Wang79675452016-08-17 10:43:28 -0700847 public boolean isCurrentGroup(long groupId) {
Walter Jang5a496962016-09-09 18:32:50 -0700848 return mGroupMetaData != null && mGroupMetaData.groupId == groupId;
Wenyi Wang79675452016-08-17 10:43:28 -0700849 }
850
Wenyi Wang17fe7982016-10-05 13:54:09 -0700851 /**
852 * Return true if the fragment is not yet added, being removed, or detached.
853 */
854 public boolean isInactive() {
855 return !isAdded() || isRemoving() || isDetached();
856 }
857
Wenyi Wang88a9f242016-08-25 16:07:15 -0700858 @Override
859 public void onDestroy() {
860 if (mActionBarAdapter != null) {
861 mActionBarAdapter.setListener(null);
862 }
863 super.onDestroy();
864 }
Wenyi Wangcc8f2722016-09-07 14:52:32 -0700865
Wenyi Wangf6606072016-10-03 17:34:53 -0700866 public void updateExistingGroupFragment(Uri newGroupUri, String action) {
James Laskey1387e782016-10-26 13:34:23 -0700867 toastForSaveAction(action);
Wenyi Wangcc8f2722016-09-07 14:52:32 -0700868
869 if (isEditMode() && getGroupCount() == 1) {
870 // If we're deleting the last group member, exit edit mode
871 exitEditMode();
872 } else if (!GroupUtil.ACTION_REMOVE_FROM_GROUP.equals(action)) {
873 mGroupUri = newGroupUri;
Walter Jang5a496962016-09-09 18:32:50 -0700874 mGroupMetaData = null; // Clear mGroupMetaData to trigger a new load.
Wenyi Wangcc8f2722016-09-07 14:52:32 -0700875 reloadData();
876 mActivity.invalidateOptionsMenu();
877 }
878 }
879
James Laskey1387e782016-10-26 13:34:23 -0700880 public void toastForSaveAction(String action) {
881 int id = -1;
Wenyi Wangcc8f2722016-09-07 14:52:32 -0700882 switch(action) {
883 case GroupUtil.ACTION_UPDATE_GROUP:
James Laskey1387e782016-10-26 13:34:23 -0700884 id = R.string.groupUpdatedToast;
885 break;
Wenyi Wangcc8f2722016-09-07 14:52:32 -0700886 case GroupUtil.ACTION_REMOVE_FROM_GROUP:
James Laskey1387e782016-10-26 13:34:23 -0700887 id = R.string.groupMembersRemovedToast;
888 break;
Wenyi Wangcc8f2722016-09-07 14:52:32 -0700889 case GroupUtil.ACTION_CREATE_GROUP:
James Laskey1387e782016-10-26 13:34:23 -0700890 id = R.string.groupCreatedToast;
891 break;
892 case GroupUtil.ACTION_ADD_TO_GROUP:
893 id = R.string.groupMembersAddedToast;
894 break;
895 case GroupUtil.ACTION_SWITCH_GROUP:
896 // No toast associated with this action.
897 break;
Wenyi Wangcc8f2722016-09-07 14:52:32 -0700898 default:
James Laskey1387e782016-10-26 13:34:23 -0700899 FeedbackHelper.sendFeedback(getContext(), TAG,
900 "toastForSaveAction passed unknown action: " + action,
901 new IllegalArgumentException("Unhandled contact save action " + action));
Wenyi Wangcc8f2722016-09-07 14:52:32 -0700902 }
James Laskey1387e782016-10-26 13:34:23 -0700903 toast(id);
Wenyi Wangcc8f2722016-09-07 14:52:32 -0700904 }
905
906 private void toast(int resId) {
907 if (resId >= 0) {
908 Toast.makeText(getContext(), resId, Toast.LENGTH_SHORT).show();
909 }
910 }
911
912 private int getGroupCount() {
913 return getAdapter() != null ? getAdapter().getCount() : -1;
914 }
915
916 public void exitEditMode() {
917 mIsEditMode = false;
918 mActionBarAdapter.setSelectionMode(false);
919 displayDeleteButtons(false);
920 }
Walter Jang4715c042016-04-06 17:14:23 -0700921}