1 package com.android.contacts.editor;
2 
3 import android.app.AlertDialog;
4 import android.app.Dialog;
5 import android.app.DialogFragment;
6 import android.content.Context;
7 import android.content.DialogInterface;
8 import android.content.Intent;
9 import android.os.Bundle;
10 import android.text.TextUtils;
11 import android.view.LayoutInflater;
12 import android.view.View;
13 import android.view.ViewGroup;
14 import android.widget.BaseAdapter;
15 import android.widget.ImageView;
16 import android.widget.ListAdapter;
17 import android.widget.TextView;
18 
19 import com.android.contacts.ContactPhotoManager;
20 import com.android.contacts.R;
21 import com.android.contacts.activities.ContactSelectionActivity;
22 import com.android.contacts.editor.PickRawContactLoader.RawContact;
23 import com.android.contacts.editor.PickRawContactLoader.RawContactsMetadata;
24 import com.android.contacts.list.UiIntentActions;
25 import com.android.contacts.logging.EditorEvent;
26 import com.android.contacts.logging.Logger;
27 import com.android.contacts.model.AccountTypeManager;
28 import com.android.contacts.model.account.AccountDisplayInfo;
29 import com.android.contacts.model.account.AccountDisplayInfoFactory;
30 import com.android.contacts.model.account.AccountInfo;
31 import com.android.contacts.model.account.AccountType;
32 import com.android.contacts.model.account.AccountWithDataSet;
33 import com.android.contacts.model.account.GoogleAccountType;
34 import com.android.contacts.preference.ContactsPreferences;
35 
36 /**
37  * Should only be started from an activity that implements {@link PickRawContactListener}.
38  * Dialog containing the raw contacts that make up a contact. On selection the editor is loaded
39  * for the chosen raw contact.
40  */
41 public class PickRawContactDialogFragment extends DialogFragment {
42     private static final String ARGS_RAW_CONTACTS_METADATA = "rawContactsMetadata";
43     private static final int REQUEST_CODE_JOIN = 3;
44 
45     public interface PickRawContactListener {
onPickRawContact(long rawContactId)46         void onPickRawContact(long rawContactId);
47     }
48 
49     /**
50      * Used to list the account info for the given raw contacts list.
51      */
52     private final class RawContactAccountListAdapter extends BaseAdapter {
53         private final LayoutInflater mInflater;
54         private final Context mContext;
55         private final RawContactsMetadata mRawContactsMetadata;
56         private final AccountTypeManager mAccountTypeManager;
57         private final ContactsPreferences mPreferences;
58 
RawContactAccountListAdapter(Context context, RawContactsMetadata rawContactsMetadata)59         public RawContactAccountListAdapter(Context context,
60                 RawContactsMetadata rawContactsMetadata) {
61             mContext = context;
62             mInflater = LayoutInflater.from(context);
63             mAccountTypeManager = AccountTypeManager.getInstance(context);
64             mPreferences = new ContactsPreferences(context);
65             mRawContactsMetadata = rawContactsMetadata;
66         }
67 
68         @Override
getCount()69         public int getCount() {
70             return mRawContactsMetadata.rawContacts.size();
71         }
72 
73         @Override
getItem(int position)74         public Object getItem(int position) {
75             return mRawContactsMetadata.rawContacts.get(position);
76         }
77 
78         @Override
getItemId(int position)79         public long getItemId(int position) {
80             return mRawContactsMetadata.rawContacts.get(position).id;
81         }
82 
83         @Override
getView(int position, View convertView, ViewGroup parent)84         public View getView(int position, View convertView, ViewGroup parent) {
85             final View view;
86             final RawContactViewHolder holder;
87             if (convertView == null) {
88                 view = mInflater.inflate(R.layout.raw_contact_list_item, parent, false);
89                 holder = new RawContactViewHolder();
90                 holder.displayName = (TextView) view.findViewById(R.id.display_name);
91                 holder.accountName = (TextView) view.findViewById(R.id.account_name);
92                 holder.accountIcon = (ImageView) view.findViewById(R.id.account_icon);
93                 holder.photo = (ImageView) view.findViewById(R.id.photo);
94                 view.setTag(holder);
95             } else {
96                 view = convertView;
97                 holder = (RawContactViewHolder) view.getTag();
98             }
99             final RawContact rawContact = mRawContactsMetadata.rawContacts.get(position);
100             final AccountType account = mAccountTypeManager.getAccountType(rawContact.accountType,
101                     rawContact.accountDataSet);
102 
103             String displayName =
104                     mPreferences.getDisplayOrder() == ContactsPreferences.DISPLAY_ORDER_PRIMARY
105                             ? rawContact.displayName : rawContact.displayNameAlt;
106 
107             if (TextUtils.isEmpty(displayName)) {
108                 displayName = mContext.getString(R.string.missing_name);
109             }
110             holder.displayName.setText(displayName);
111 
112             final String accountDisplayLabel;
113 
114             // Use the same string as editor if it's an editable user profile raw contact.
115             if (mRawContactsMetadata.isUserProfile && account.areContactsWritable()) {
116                 final AccountInfo accountInfo =
117                         AccountTypeManager.getInstance(getContext()).getAccountInfoForAccount(
118                                 new AccountWithDataSet(rawContact.accountName,
119                                         rawContact.accountType, rawContact.accountDataSet));
120                 accountDisplayLabel = EditorUiUtils.getAccountHeaderLabelForMyProfile(mContext,
121                         accountInfo);
122             } else if (GoogleAccountType.ACCOUNT_TYPE.equals(rawContact.accountType)
123                     && account.dataSet == null) {
124                 // Focus Google accounts have the account name shown
125                 accountDisplayLabel = rawContact.accountName;
126             } else {
127                 accountDisplayLabel = account.getDisplayLabel(mContext).toString();
128             }
129 
130             holder.accountName.setText(accountDisplayLabel);
131             holder.accountIcon.setImageDrawable(account.getDisplayIcon(mContext));
132             final ContactPhotoManager.DefaultImageRequest
133                     request = new ContactPhotoManager.DefaultImageRequest(
134                     displayName, String.valueOf(rawContact.id), /* isCircular = */ true);
135 
136             ContactPhotoManager.getInstance(mContext).loadThumbnail(holder.photo,
137                     rawContact.photoId,
138                     /* darkTheme = */ false,
139                     /* isCircular = */ true,
140                     request);
141             return view;
142         }
143 
144         class RawContactViewHolder {
145             TextView displayName;
146             TextView accountName;
147             ImageView accountIcon;
148             ImageView photo;
149         }
150     }
151 
152     private ListAdapter mAdapter;
153     private boolean mShouldFinishActivity = true;
154 
getInstance(RawContactsMetadata metadata)155     public static PickRawContactDialogFragment getInstance(RawContactsMetadata metadata) {
156         final PickRawContactDialogFragment fragment = new PickRawContactDialogFragment();
157         final Bundle args = new Bundle();
158         args.putParcelable(ARGS_RAW_CONTACTS_METADATA, metadata);
159         fragment.setArguments(args);
160         return fragment;
161     }
162 
163     @Override
onCreateDialog(Bundle savedInstanceState)164     public Dialog onCreateDialog(Bundle savedInstanceState) {
165         if (!(getActivity() instanceof PickRawContactListener)) {
166             throw new IllegalArgumentException(
167                     "Host activity doesn't implement PickRawContactListener");
168         }
169         final Bundle args = getArguments();
170         if (args == null) {
171             throw new IllegalArgumentException("Dialog created with no arguments");
172         }
173 
174         final RawContactsMetadata metadata = args.getParcelable(ARGS_RAW_CONTACTS_METADATA);
175         if (metadata == null) {
176             throw new IllegalArgumentException("Dialog created with null RawContactsMetadata");
177         }
178 
179         final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
180         mAdapter = new RawContactAccountListAdapter(getContext(), metadata);
181         if (metadata.showReadOnly) {
182             builder.setTitle(R.string.contact_editor_pick_linked_contact_dialog_title);
183             // Only provide link editing options for non-user profile contacts.
184             if (!metadata.isUserProfile) {
185                 builder.setPositiveButton(R.string.contact_editor_add_linked_contact,
186                         new DialogInterface.OnClickListener() {
187                             @Override
188                             public void onClick(DialogInterface dialog, int which) {
189                                 mShouldFinishActivity = false;
190                                 final Intent intent = new Intent(getActivity(),
191                                         ContactSelectionActivity.class);
192                                 intent.setAction(UiIntentActions.PICK_JOIN_CONTACT_ACTION);
193                                 intent.putExtra(UiIntentActions.TARGET_CONTACT_ID_EXTRA_KEY,
194                                         metadata.contactId);
195                                 getActivity().startActivityForResult(intent, REQUEST_CODE_JOIN);
196                             }
197                         });
198                 builder.setNegativeButton(R.string.contact_editor_unlink_contacts,
199                         new DialogInterface.OnClickListener() {
200                             @Override
201                             public void onClick(DialogInterface dialog, int which) {
202                                 mShouldFinishActivity = false;
203                                 final SplitContactConfirmationDialogFragment splitDialog = new
204                                         SplitContactConfirmationDialogFragment();
205                                 splitDialog.show(getActivity().getFragmentManager(),
206                                         SplitContactConfirmationDialogFragment.TAG);
207                             }
208                         });
209             }
210         } else {
211             builder.setTitle(R.string.contact_editor_pick_raw_contact_to_edit_dialog_title);
212         }
213         builder.setAdapter(mAdapter, new DialogInterface.OnClickListener() {
214             @Override
215             public void onClick(DialogInterface dialog, int which) {
216                 final long rawContactId = mAdapter.getItemId(which);
217                 ((PickRawContactListener) getActivity()).onPickRawContact(rawContactId);
218             }
219         });
220         builder.setCancelable(true);
221         if (savedInstanceState == null) {
222             Logger.logEditorEvent(EditorEvent.EventType.SHOW_RAW_CONTACT_PICKER,
223                     /* numberRawContacts */ mAdapter.getCount());
224         }
225         return builder.create();
226     }
227 
228     @Override
onDismiss(DialogInterface dialog)229     public void onDismiss(DialogInterface dialog) {
230         super.onDismiss(dialog);
231         if (mShouldFinishActivity) {
232             finishActivity();
233         }
234     }
235 
236     @Override
getContext()237     public Context getContext() {
238         return getActivity();
239     }
240 
finishActivity()241     private void finishActivity() {
242         if (getActivity() != null && !getActivity().isFinishing()) {
243             getActivity().finish();
244         }
245     }
246 }
247