14c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson /* 2bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * Copyright (C) 2010 The Android Open Source Project 3bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * 4bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * Licensed under the Apache License, Version 2.0 (the "License"); 5bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * you may not use this file except in compliance with the License. 6bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * You may obtain a copy of the License at 7bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * 8bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * http://www.apache.org/licenses/LICENSE-2.0 9bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * 10bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * Unless required by applicable law or agreed to in writing, software 11bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * distributed under the License is distributed on an "AS IS" BASIS, 12bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * See the License for the specific language governing permissions and 14bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * limitations under the License. 15bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa */ 16bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 17bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawapackage com.android.calendar.event; 18bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 19bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport com.android.calendar.CalendarEventModel.Attendee; 20bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport com.android.calendar.ContactsAsyncHelper; 21bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport com.android.calendar.R; 22ddbc002f3471e224fc112d406116e396ee1c50aeSara Tingimport com.android.calendar.Utils; 23bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport com.android.calendar.event.EditEventHelper.AttendeeItem; 24bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport com.android.common.Rfc822Validator; 25bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 26bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.content.AsyncQueryHandler; 27bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.content.ContentResolver; 28bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.content.ContentUris; 29bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.content.Context; 30bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.content.res.Resources; 31bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.database.Cursor; 324c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelsonimport android.graphics.ColorMatrix; 334c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelsonimport android.graphics.ColorMatrixColorFilter; 34bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.graphics.Paint; 35bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.graphics.drawable.Drawable; 36bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.net.Uri; 37a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Attendees; 38bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Email; 39ddbc002f3471e224fc112d406116e396ee1c50aeSara Tingimport android.provider.ContactsContract.CommonDataKinds.Identity; 40bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.provider.ContactsContract.Contacts; 41ddbc002f3471e224fc112d406116e396ee1c50aeSara Tingimport android.provider.ContactsContract.Data; 42ddbc002f3471e224fc112d406116e396ee1c50aeSara Tingimport android.provider.ContactsContract.RawContacts; 43bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.text.TextUtils; 44bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.text.util.Rfc822Token; 45bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.util.AttributeSet; 46bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.util.Log; 47bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.view.LayoutInflater; 48bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.view.View; 49bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.widget.ImageButton; 50bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.widget.LinearLayout; 51bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.widget.QuickContactBadge; 52bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.widget.TextView; 53bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 54bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport java.util.ArrayList; 55bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport java.util.HashMap; 56bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport java.util.LinkedHashSet; 57bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 58bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawapublic class AttendeesView extends LinearLayout implements View.OnClickListener { 59bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa private static final String TAG = "AttendeesView"; 60bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa private static final boolean DEBUG = false; 61bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 628fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann private static final int EMAIL_PROJECTION_CONTACT_ID_INDEX = 0; 638fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann private static final int EMAIL_PROJECTION_CONTACT_LOOKUP_INDEX = 1; 648fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann private static final int EMAIL_PROJECTION_PHOTO_ID_INDEX = 2; 65bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 66ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting private static final String[] PROJECTION = new String[] { 67ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting RawContacts.CONTACT_ID, // 0 688fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann Contacts.LOOKUP_KEY, // 1 69ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting Contacts.PHOTO_ID, // 2 70bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa }; 71bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 72bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa private final Context mContext; 73bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa private final LayoutInflater mInflater; 74bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa private final PresenceQueryHandler mPresenceQueryHandler; 75bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa private final Drawable mDefaultBadge; 764c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson private final ColorMatrixColorFilter mGrayscaleFilter; 77bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 78bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa // TextView shown at the top of each type of attendees 79bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa // e.g. 80bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa // Yes <-- divider 81bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa // example_for_yes <exampleyes@example.com> 82bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa // No <-- divider 83bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa // example_for_no <exampleno@example.com> 844c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson private final CharSequence[] mEntries; 85bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa private final View mDividerForYes; 86bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa private final View mDividerForNo; 87bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa private final View mDividerForMaybe; 88bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa private final View mDividerForNoResponse; 894c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson private final int mNoResponsePhotoAlpha; 904c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson private final int mDefaultPhotoAlpha; 91bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa private Rfc822Validator mValidator; 92bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 93bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa // Number of attendees responding or not responding. 94bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa private int mYes; 95bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa private int mNo; 96bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa private int mMaybe; 97bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa private int mNoResponse; 98bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 9980d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson // Cache for loaded photos 10080d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson HashMap<String, Drawable> mRecycledPhotos; 10180d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson 102bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa public AttendeesView(Context context, AttributeSet attrs) { 103bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa super(context, attrs); 104bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa mContext = context; 105ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 106bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa mPresenceQueryHandler = new PresenceQueryHandler(context.getContentResolver()); 107bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 108bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa final Resources resources = context.getResources(); 109bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa mDefaultBadge = resources.getDrawable(R.drawable.ic_contact_picture); 1104c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson mNoResponsePhotoAlpha = 1114c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson resources.getInteger(R.integer.noresponse_attendee_photo_alpha_level); 1124c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson mDefaultPhotoAlpha = resources.getInteger(R.integer.default_attendee_photo_alpha_level); 1134c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson 1144c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson // Create dividers between groups of attendees (accepted, declined, etc...) 1154c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson mEntries = resources.getTextArray(R.array.response_labels1); 1164c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson mDividerForYes = constructDividerView(mEntries[1]); 1174c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson mDividerForNo = constructDividerView(mEntries[3]); 1184c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson mDividerForMaybe = constructDividerView(mEntries[2]); 1194c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson mDividerForNoResponse = constructDividerView(mEntries[0]); 1204c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson 1214c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson // Create a filter to convert photos of declined attendees to grayscale. 1224c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson ColorMatrix matrix = new ColorMatrix(); 1234c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson matrix.setSaturation(0); 1244c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson mGrayscaleFilter = new ColorMatrixColorFilter(matrix); 125bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 126bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 127bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 1284c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson // Disable/enable removal of attendings 129ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan @Override 130ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan public void setEnabled(boolean enabled) { 131ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan super.setEnabled(enabled); 132ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan int visibility = isEnabled() ? View.VISIBLE : View.GONE; 133ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan int count = getChildCount(); 134ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan for (int i = 0; i < count; i++) { 135ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan View child = getChildAt(i); 136ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan View minusButton = child.findViewById(R.id.contact_remove); 137ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan if (minusButton != null) { 138ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan minusButton.setVisibility(visibility); 139ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan } 140ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan } 141ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan } 142ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan 143bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa public void setRfc822Validator(Rfc822Validator validator) { 144bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa mValidator = validator; 145bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 146bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 147bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa private View constructDividerView(CharSequence label) { 14810b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson final TextView textView = 14910b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson (TextView)mInflater.inflate(R.layout.event_info_label, this, false); 150bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa textView.setText(label); 151bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa textView.setClickable(false); 152bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa return textView; 153bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 154bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 1554c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson // Add the number of attendees in the specific status (corresponding to the divider) in 1564c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson // parenthesis next to the label 1574c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson private void updateDividerViewLabel(View divider, CharSequence label, int count) { 1584c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson if (count <= 0) { 1594c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson ((TextView)divider).setText(label); 1604c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson } 1614c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson else { 1624c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson ((TextView)divider).setText(label + " (" + count + ")"); 1634c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson } 1644c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson } 1654c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson 1664c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson 167bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa /** 168bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * Inflates a layout for a given attendee view and set up each element in it, and returns 169bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * the constructed View object. The object is also stored in {@link AttendeeItem#mView}. 170bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa */ 171bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa private View constructAttendeeView(AttendeeItem item) { 172bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa item.mView = mInflater.inflate(R.layout.contact_item, null); 173bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa return updateAttendeeView(item); 174bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 175bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 176bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa /** 177bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * Set up each element in {@link AttendeeItem#mView} using the latest information. View 178bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * object is reused. 179bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa */ 180bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa private View updateAttendeeView(AttendeeItem item) { 181bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa final Attendee attendee = item.mAttendee; 182bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa final View view = item.mView; 183ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan final TextView nameView = (TextView) view.findViewById(R.id.name); 184bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa nameView.setText(TextUtils.isEmpty(attendee.mName) ? attendee.mEmail : attendee.mName); 185bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa if (item.mRemoved) { 186bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa nameView.setPaintFlags(Paint.STRIKE_THRU_TEXT_FLAG | nameView.getPaintFlags()); 187bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } else { 188bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa nameView.setPaintFlags((~Paint.STRIKE_THRU_TEXT_FLAG) & nameView.getPaintFlags()); 189bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 190bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 191ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan // Set up the Image button even if the view is disabled 192ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan // Everything will be ready when the view is enabled later 193ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan final ImageButton button = (ImageButton) view.findViewById(R.id.contact_remove); 1949f5268d5bdfafe5c20dba64fbca124fcf25d68d9Erik button.setVisibility(isEnabled() ? View.VISIBLE : View.GONE); 195bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa button.setTag(item); 196bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa if (item.mRemoved) { 19767c0ac313280bbe0ae4c2e191cf64d926995c7c7Michael Chan button.setImageResource(R.drawable.ic_menu_add_field_holo_light); 1989ceed1f3df98c5fc85441da0c6e7e5d45cf17a1eIsaac Katzenelson button.setContentDescription(mContext.getString(R.string.accessibility_add_attendee)); 199bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } else { 20067c0ac313280bbe0ae4c2e191cf64d926995c7c7Michael Chan button.setImageResource(R.drawable.ic_menu_remove_field_holo_light); 2019ceed1f3df98c5fc85441da0c6e7e5d45cf17a1eIsaac Katzenelson button.setContentDescription(mContext. 2029ceed1f3df98c5fc85441da0c6e7e5d45cf17a1eIsaac Katzenelson getString(R.string.accessibility_remove_attendee)); 203bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 204bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa button.setOnClickListener(this); 205bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 2068fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann final QuickContactBadge badgeView = (QuickContactBadge) view.findViewById(R.id.badge); 20780d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson 20880d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson Drawable badge = null; 20980d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson // Search for photo in recycled photos 21080d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson if (mRecycledPhotos != null) { 21180d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson badge = mRecycledPhotos.get(item.mAttendee.mEmail); 21280d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson } 21380d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson if (badge != null) { 21480d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson item.mBadge = badge; 21580d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson } 21680d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson badgeView.setImageDrawable(item.mBadge); 21780d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson 2184c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson if (item.mAttendee.mStatus == Attendees.ATTENDEE_STATUS_NONE) { 2194c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson item.mBadge.setAlpha(mNoResponsePhotoAlpha); 2204c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson } else { 2214c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson item.mBadge.setAlpha(mDefaultPhotoAlpha); 2224c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson } 2234c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson if (item.mAttendee.mStatus == Attendees.ATTENDEE_STATUS_DECLINED) { 2244c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson item.mBadge.setColorFilter(mGrayscaleFilter); 2254c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson } else { 2264c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson item.mBadge.setColorFilter(null); 2274c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson } 22880d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson 2298fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann // If we know the lookup-uri of the contact, it is a good idea to set this here. This 2308fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann // allows QuickContact to be started without an extra database lookup. If we don't know 2318fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann // the lookup uri (yet), we can set Email and QuickContact will lookup once tapped. 2328fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann if (item.mContactLookupUri != null) { 2338fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann badgeView.assignContactUri(item.mContactLookupUri); 2348fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann } else { 2358fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann badgeView.assignContactFromEmail(item.mAttendee.mEmail, true); 2368fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann } 2378fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann badgeView.setMaxHeight(60); 238bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 239bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa return view; 240bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 241bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 242bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa public boolean contains(Attendee attendee) { 243bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa final int size = getChildCount(); 244bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa for (int i = 0; i < size; i++) { 245bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa final View view = getChildAt(i); 246ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan if (view instanceof TextView) { // divider 247bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa continue; 248bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 249ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan AttendeeItem attendeeItem = (AttendeeItem) view.getTag(); 250bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa if (TextUtils.equals(attendee.mEmail, attendeeItem.mAttendee.mEmail)) { 251bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa return true; 252bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 253bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 254bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa return false; 255bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 256bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 257c7f3c3896f1bc4cad43aa7f0bca1dee603704613RoboErik public void clearAttendees() { 25880d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson 25980d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson // Before clearing the views, save all the badges. The updateAtendeeView will use the saved 26080d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson // photo instead of the default badge thus prevent switching between the two while the 26180d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson // most current photo is loaded in the background. 26280d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson mRecycledPhotos = new HashMap<String, Drawable> (); 26380d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson final int size = getChildCount(); 26480d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson for (int i = 0; i < size; i++) { 26580d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson final View view = getChildAt(i); 26680d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson if (view instanceof TextView) { // divider 26780d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson continue; 26880d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson } 26980d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson AttendeeItem attendeeItem = (AttendeeItem) view.getTag(); 27080d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson mRecycledPhotos.put(attendeeItem.mAttendee.mEmail, attendeeItem.mBadge); 27180d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson } 27280d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson 273c7f3c3896f1bc4cad43aa7f0bca1dee603704613RoboErik removeAllViews(); 274c7f3c3896f1bc4cad43aa7f0bca1dee603704613RoboErik mYes = 0; 275c7f3c3896f1bc4cad43aa7f0bca1dee603704613RoboErik mNo = 0; 276c7f3c3896f1bc4cad43aa7f0bca1dee603704613RoboErik mMaybe = 0; 277c7f3c3896f1bc4cad43aa7f0bca1dee603704613RoboErik mNoResponse = 0; 278c7f3c3896f1bc4cad43aa7f0bca1dee603704613RoboErik } 2794c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson 280bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa private void addOneAttendee(Attendee attendee) { 281bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa if (contains(attendee)) { 282bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa return; 283bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 2841784d2de8ee81c6759bef7199a902e13de3b300fRoboErik final AttendeeItem item = new AttendeeItem(attendee, mDefaultBadge); 285bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa final int status = attendee.mStatus; 286bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa final int index; 28710b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson boolean firstAttendeeInCategory = false; 288bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa switch (status) { 289ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan case Attendees.ATTENDEE_STATUS_ACCEPTED: { 290ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan final int startIndex = 0; 2914c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson updateDividerViewLabel(mDividerForYes, mEntries[1], mYes + 1); 292ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan if (mYes == 0) { 293ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan addView(mDividerForYes, startIndex); 29410b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson firstAttendeeInCategory = true; 295ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan } 296ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan mYes++; 297ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan index = startIndex + mYes; 298ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan break; 299bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 300ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan case Attendees.ATTENDEE_STATUS_DECLINED: { 301ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan final int startIndex = (mYes == 0 ? 0 : 1 + mYes); 3024c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson updateDividerViewLabel(mDividerForNo, mEntries[3], mNo + 1); 303ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan if (mNo == 0) { 304ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan addView(mDividerForNo, startIndex); 30510b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson firstAttendeeInCategory = true; 306ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan } 307ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan mNo++; 308ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan index = startIndex + mNo; 309ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan break; 310bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 311ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan case Attendees.ATTENDEE_STATUS_TENTATIVE: { 312ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan final int startIndex = (mYes == 0 ? 0 : 1 + mYes) + (mNo == 0 ? 0 : 1 + mNo); 3134c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson updateDividerViewLabel(mDividerForMaybe, mEntries[2], mMaybe + 1); 314ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan if (mMaybe == 0) { 315ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan addView(mDividerForMaybe, startIndex); 31610b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson firstAttendeeInCategory = true; 317ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan } 318ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan mMaybe++; 319ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan index = startIndex + mMaybe; 320ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan break; 321ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan } 322ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan default: { 323ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan final int startIndex = (mYes == 0 ? 0 : 1 + mYes) + (mNo == 0 ? 0 : 1 + mNo) 324ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan + (mMaybe == 0 ? 0 : 1 + mMaybe); 32510b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson updateDividerViewLabel(mDividerForNoResponse, mEntries[0], mNoResponse + 1); 32610b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson if (mNoResponse == 0) { 32710b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson addView(mDividerForNoResponse, startIndex); 32810b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson firstAttendeeInCategory = true; 32910b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson } 330ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan mNoResponse++; 33110b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson index = startIndex + mNoResponse; 332ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan break; 333bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 334bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 335bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 336bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa final View view = constructAttendeeView(item); 337bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa view.setTag(item); 338bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa addView(view, index); 33910b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson // Show separator between Attendees 34010b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson if (!firstAttendeeInCategory) { 34110b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson View prevItem = getChildAt(index - 1); 34210b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson if (prevItem != null) { 34310b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson View Separator = prevItem.findViewById(R.id.contact_separator); 34410b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson if (Separator != null) { 34510b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson Separator.setVisibility(View.VISIBLE); 34610b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson } 34710b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson } 348bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 349bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 350ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting Uri uri; 351ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting String selection = null; 352ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting String[] selectionArgs = null; 353ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting if (attendee.mIdentity != null && attendee.mIdNamespace != null) { 354ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting // Query by identity + namespace 355ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting uri = Data.CONTENT_URI; 356ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting selection = Data.MIMETYPE + "=? AND " + Identity.IDENTITY + "=? AND " + 357ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting Identity.NAMESPACE + "=?"; 358ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting selectionArgs = new String[] {Identity.CONTENT_ITEM_TYPE, attendee.mIdentity, 359ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting attendee.mIdNamespace}; 360ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting } else { 361ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting // Query by email 362ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting uri = Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(attendee.mEmail)); 363ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting } 364ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting 365ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting mPresenceQueryHandler.startQuery(item.mUpdateCounts + 1, item, uri, PROJECTION, selection, 366ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting selectionArgs, null); 367bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 368bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 369bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa public void addAttendees(ArrayList<Attendee> attendees) { 370bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa synchronized (this) { 371bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa for (final Attendee attendee : attendees) { 372bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa addOneAttendee(attendee); 373bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 374bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 375bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 376bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 377bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa public void addAttendees(HashMap<String, Attendee> attendees) { 378bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa synchronized (this) { 379bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa for (final Attendee attendee : attendees.values()) { 380bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa addOneAttendee(attendee); 381bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 382bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 383bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 384bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 385bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa public void addAttendees(String attendees) { 386bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa final LinkedHashSet<Rfc822Token> addresses = 387bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa EditEventHelper.getAddressesFromList(attendees, mValidator); 388bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa synchronized (this) { 389bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa for (final Rfc822Token address : addresses) { 390bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa final Attendee attendee = new Attendee(address.getName(), address.getAddress()); 391bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa if (TextUtils.isEmpty(attendee.mName)) { 392bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa attendee.mName = attendee.mEmail; 393bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 394bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa addOneAttendee(attendee); 395bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 396bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 397bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 398bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 399bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa /** 400bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * Returns true when the attendee at that index is marked as "removed" (the name of 401bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * the attendee is shown with a strike through line). 402bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa */ 403bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa public boolean isMarkAsRemoved(int index) { 404bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa final View view = getChildAt(index); 405ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan if (view instanceof TextView) { // divider 406bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa return false; 407bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 408ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan return ((AttendeeItem) view.getTag()).mRemoved; 409bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 410bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 411bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa // TODO put this into a Loader for auto-requeries 412bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa private class PresenceQueryHandler extends AsyncQueryHandler { 413bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa public PresenceQueryHandler(ContentResolver cr) { 414bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa super(cr); 415bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 416bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 417bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa @Override 418bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa protected void onQueryComplete(int queryIndex, Object cookie, Cursor cursor) { 419bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa if (cursor == null || cookie == null) { 420bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa if (DEBUG) { 421bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa Log.d(TAG, "onQueryComplete: cursor=" + cursor + ", cookie=" + cookie); 422bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 423bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa return; 424bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 425bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 426bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa final AttendeeItem item = (AttendeeItem)cookie; 427bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa try { 4288fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann if (item.mUpdateCounts < queryIndex) { 4298fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann item.mUpdateCounts = queryIndex; 4308fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann if (cursor.moveToFirst()) { 4318fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann final long contactId = cursor.getLong(EMAIL_PROJECTION_CONTACT_ID_INDEX); 4328fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann final Uri contactUri = 4338fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 4348fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann 4358fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann final String lookupKey = 4368fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann cursor.getString(EMAIL_PROJECTION_CONTACT_LOOKUP_INDEX); 4378fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann item.mContactLookupUri = Contacts.getLookupUri(contactId, lookupKey); 4388fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann 4398fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann final long photoId = cursor.getLong(EMAIL_PROJECTION_PHOTO_ID_INDEX); 4408fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann // If we found a picture, start the async loading 4418fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann if (photoId > 0) { 4428fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann // Query for this contacts picture 4438fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann ContactsAsyncHelper.retrieveContactPhotoAsync( 4448fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann mContext, item, new Runnable() { 4458fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann @Override 4468fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann public void run() { 4478fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann updateAttendeeView(item); 4488fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann } 4498fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann }, contactUri); 4508fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann } else { 4518fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann // call update view to make sure that the lookup key gets set in 4528fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann // the QuickContactBadge 4538fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann updateAttendeeView(item); 4548fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann } 4558fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann } else { 456ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting // Contact not found. For real emails, keep the QuickContactBadge with 457ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting // its Email address set, so that the user can create a contact by tapping. 4588fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann item.mContactLookupUri = null; 459ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting if (!Utils.isValidEmail(item.mAttendee.mEmail)) { 460ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting item.mAttendee.mEmail = null; 461ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting updateAttendeeView(item); 462ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting } 463bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 464bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 465bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } finally { 466bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa cursor.close(); 467bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 468bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 469bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 470bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 471bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa public Attendee getItem(int index) { 472bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa final View view = getChildAt(index); 473ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan if (view instanceof TextView) { // divider 474bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa return null; 475bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 476ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan return ((AttendeeItem) view.getTag()).mAttendee; 477bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 478bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa 479bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa @Override 480bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa public void onClick(View view) { 481bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa // Button corresponding to R.id.contact_remove. 482bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa final AttendeeItem item = (AttendeeItem) view.getTag(); 483bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa item.mRemoved = !item.mRemoved; 484bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa updateAttendeeView(item); 485bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa } 486bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa} 487