diff --git a/src/org/linphone/ContactsListFragment.java b/src/org/linphone/ContactsListFragment.java index c3bbf7464..235f8de9f 100644 --- a/src/org/linphone/ContactsListFragment.java +++ b/src/org/linphone/ContactsListFragment.java @@ -58,7 +58,7 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O private ListView contactsList; private TextView noSipContact, noContact; private ImageView allContacts, linphoneContacts, newContact, edit, selectAll, deselectAll, delete, cancel; - private boolean onlyDisplayLinphoneContacts, isEditMode; + private boolean onlyDisplayLinphoneContacts, isEditMode, isSearchMode; private View allContactsSelected, linphoneContactsSelected; private LinearLayout editList, topbar; private int lastKnownPosition; @@ -72,33 +72,33 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mInflater = inflater; View view = inflater.inflate(R.layout.contacts_list, container, false); - + if (getArguments() != null) { editOnClick = getArguments().getBoolean("EditOnClick"); sipAddressToAdd = getArguments().getString("SipAddress"); - + onlyDisplayChatAddress = getArguments().getBoolean("ChatAddressOnly"); } - + noSipContact = (TextView) view.findViewById(R.id.noSipContact); noContact = (TextView) view.findViewById(R.id.noContact); - + contactsList = (ListView) view.findViewById(R.id.contactsList); contactsList.setOnItemClickListener(this); - + allContacts = (ImageView) view.findViewById(R.id.all_contacts); allContacts.setOnClickListener(this); - + linphoneContacts = (ImageView) view.findViewById(R.id.linphone_contacts); linphoneContacts.setOnClickListener(this); allContactsSelected = view.findViewById(R.id.all_contacts_select); linphoneContactsSelected = view.findViewById(R.id.linphone_contacts_select); - + newContact = (ImageView) view.findViewById(R.id.newContact); newContact.setOnClickListener(this); newContact.setEnabled(LinphoneManager.getLc().getCallsNb() == 0); - + allContacts.setEnabled(onlyDisplayLinphoneContacts); linphoneContacts.setEnabled(!allContacts.isEnabled()); @@ -119,29 +119,29 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O edit = (ImageView) view.findViewById(R.id.edit); edit.setOnClickListener(this); - + clearSearchField = (ImageView) view.findViewById(R.id.clearSearchField); clearSearchField.setOnClickListener(this); - + searchField = (EditText) view.findViewById(R.id.searchField); searchField.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { - + } - + @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { - + } - + @Override public void afterTextChanged(Editable s) { searchContacts(searchField.getText().toString()); } }); - + contactsFetchInProgress = (ProgressBar) view.findViewById(R.id.contactsFetchInProgress); contactsFetchInProgress.setVisibility(View.VISIBLE); @@ -224,14 +224,14 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O enabledDeleteButton(false); isEditMode = true; } - + if (id == R.id.all_contacts) { onlyDisplayLinphoneContacts = false; allContactsSelected.setVisibility(View.VISIBLE); allContacts.setEnabled(false); linphoneContacts.setEnabled(true); linphoneContactsSelected.setVisibility(View.INVISIBLE); - } + } else if (id == R.id.linphone_contacts) { allContactsSelected.setVisibility(View.INVISIBLE); linphoneContactsSelected.setVisibility(View.VISIBLE); @@ -255,7 +255,7 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O if (id == R.id.newContact) { editConsumed = true; LinphoneActivity.instance().addContact(null, sipAddressToAdd); - } + } else if (id == R.id.clearSearchField) { searchField.setText(""); } @@ -271,7 +271,7 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O private void removeContacts() { ArrayList ids = new ArrayList(); int size = contactsList.getAdapter().getCount(); - + for (int i = size - 1; i >= 0; i--) { if (contactsList.isItemChecked(i)) { LinphoneContact contact = (LinphoneContact) contactsList.getAdapter().getItem(i); @@ -283,7 +283,7 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O } } } - + ContactsManager.getInstance().deleteMultipleContactsAtOnce(ids); } @@ -316,6 +316,8 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O } changeContactsToggle(); + isSearchMode = true; + if (onlyDisplayLinphoneContacts) { contactsList.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE); contactsList.setAdapter(new ContactsListAdapter(ContactsManager.getInstance().getSIPContacts(search))); @@ -324,10 +326,11 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O contactsList.setAdapter(new ContactsListAdapter(ContactsManager.getInstance().getContacts(search))); } } - + private void changeContactsAdapter() { changeContactsToggle(); + isSearchMode = false; noSipContact.setVisibility(View.GONE); noContact.setVisibility(View.GONE); contactsList.setVisibility(View.VISIBLE); @@ -344,13 +347,13 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O contactsList.setAdapter(adapter); edit.setEnabled(true); } - + if (adapter.getCount() > 0) { contactsFetchInProgress.setVisibility(View.GONE); } ContactsManager.getInstance().setLinphoneContactsPrefered(onlyDisplayLinphoneContacts); } - + private void changeContactsToggle() { if (onlyDisplayLinphoneContacts) { allContacts.setEnabled(true); @@ -376,7 +379,7 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O LinphoneActivity.instance().displayContact(contact, onlyDisplayChatAddress); } } - + @Override public void onResume() { ContactsManager.addContactsListener(this); @@ -395,18 +398,18 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O changeContactsToggle(); invalidate(); } - + @Override public void onPause() { ContactsManager.removeContactsListener(this); super.onPause(); } - + @Override public void onContactsUpdated() { invalidate(); } - + public void invalidate() { if (searchField != null && searchField.getText().toString().length() > 0) { searchContacts(searchField.getText().toString()); @@ -415,7 +418,7 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O } contactsList.setSelectionFromTop(lastKnownPosition, 0); } - + class ContactsListAdapter extends BaseAdapter implements SectionIndexer { private class ViewHolder { public CheckBox delete; @@ -426,7 +429,7 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O public ImageView contactPicture; public TextView organization; //public ImageView friendStatus; - + public ViewHolder(View view) { delete = (CheckBox) view.findViewById(R.id.delete); linphoneFriend = (ImageView) view.findViewById(R.id.friendLinphone); @@ -438,15 +441,15 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O //friendStatus = (ImageView) view.findViewById(R.id.friendStatus); } } - + private List contacts; String[] sections; ArrayList sectionsList; Mapmap = new LinkedHashMap(); - + ContactsListAdapter(List contactsList) { contacts = contactsList; - + map = new LinkedHashMap(); String prevLetter = null; for (int i = 0; i < contacts.size(); i++) { @@ -465,7 +468,7 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O sections = new String[sectionsList.size()]; sectionsList.toArray(sections); } - + public int getCount() { return contacts.size(); } @@ -483,7 +486,7 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O View view = null; LinphoneContact contact = (LinphoneContact) getItem(position); if (contact == null) return null; - + ViewHolder holder = null; if (convertView != null) { view = convertView; @@ -493,17 +496,21 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O holder = new ViewHolder(view); view.setTag(holder); } - + holder.name.setText(contact.getFullName()); - - if (getPositionForSection(getSectionForPosition(position)) != position) { - holder.separator.setVisibility(View.GONE); - } else { - holder.separator.setVisibility(View.VISIBLE); - String fullName = contact.getFullName(); - if (fullName != null && !fullName.isEmpty()) { - holder.separatorText.setText(String.valueOf(fullName.charAt(0))); + + if (!isSearchMode) { + if (getPositionForSection(getSectionForPosition(position)) != position) { + holder.separator.setVisibility(View.GONE); + } else { + holder.separator.setVisibility(View.VISIBLE); + String fullName = contact.getFullName(); + if (fullName != null && !fullName.isEmpty()) { + holder.separatorText.setText(String.valueOf(fullName.charAt(0))); + } } + } else { + holder.separator.setVisibility(View.GONE); } if (contact.isInLinphoneFriendList()) { @@ -522,7 +529,7 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O } else { holder.contactPicture.setImageResource(R.drawable.avatar); } - + boolean isOrgVisible = getResources().getBoolean(R.bool.display_contact_organization); String org = contact.getOrganization(); if (org != null && !org.isEmpty() && isOrgVisible) { @@ -563,7 +570,7 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O } else { holder.delete.setVisibility(View.GONE); } - + /*LinphoneFriend[] friends = LinphoneManager.getLc().getFriendList(); if (!ContactsManager.getInstance().isContactPresenceDisabled() && friends != null) { holder.friendStatus.setVisibility(View.VISIBLE); @@ -580,7 +587,7 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O holder.friendStatus.setImageResource(R.drawable.call_quality_indicator_0); } }*/ - + return view; } diff --git a/src/org/linphone/ContactsManager.java b/src/org/linphone/ContactsManager.java index dd9d24c6d..1f2746306 100644 --- a/src/org/linphone/ContactsManager.java +++ b/src/org/linphone/ContactsManager.java @@ -59,7 +59,7 @@ public class ContactsManager extends ContentObserver { private ContentResolver contentResolver; private Context context; private ContactsFetchTask contactsFetchTask; - + private static ArrayList contactsUpdatedListeners; public static void addContactsListener(ContactsUpdatedListener listener) { contactsUpdatedListeners.add(listener); @@ -67,11 +67,11 @@ public class ContactsManager extends ContentObserver { public static void removeContactsListener(ContactsUpdatedListener listener) { contactsUpdatedListeners.remove(listener); } - + private static Handler handler = new Handler() { @Override public void handleMessage (Message msg) { - + } }; @@ -81,24 +81,24 @@ public class ContactsManager extends ContentObserver { contacts = new ArrayList(); sipContacts = new ArrayList(); } - + public void destroy() { if (contactsFetchTask != null && !contactsFetchTask.isCancelled()) { contactsFetchTask.cancel(true); } instance = null; } - + @Override public void onChange(boolean selfChange) { onChange(selfChange, null); } - + @Override public void onChange(boolean selfChange, Uri uri) { fetchContactsAsync(); } - + public ContentResolver getContentResolver() { return contentResolver; } @@ -107,49 +107,58 @@ public class ContactsManager extends ContentObserver { if (instance == null) instance = new ContactsManager(handler); return instance; } - + public synchronized boolean hasContacts() { return contacts.size() > 0; } - + public synchronized List getContacts() { return contacts; } - + public synchronized List getSIPContacts() { + setContacts(contacts); return sipContacts; } - + public synchronized List getContacts(String search) { search = search.toLowerCase(Locale.getDefault()); - List searchContacts = new ArrayList(); + List searchContactsBegin = new ArrayList(); + List searchContactsContain = new ArrayList(); for (LinphoneContact contact : contacts) { if (contact.getFullName() != null) { - if (contact.getFullName().toLowerCase(Locale.getDefault()).contains(search)) { - searchContacts.add(contact); + if (contact.getFullName().toLowerCase(Locale.getDefault()).startsWith(search)) { + searchContactsBegin.add(contact); + } else if (contact.getFullName().toLowerCase(Locale.getDefault()).contains(search)) { + searchContactsContain.add(contact); } } } - return searchContacts; + searchContactsBegin.addAll(searchContactsContain); + return searchContactsBegin; } - + public synchronized List getSIPContacts(String search) { search = search.toLowerCase(Locale.getDefault()); - List searchContacts = new ArrayList(); + List searchContactsBegin = new ArrayList(); + List searchContactsContain = new ArrayList(); for (LinphoneContact contact : sipContacts) { if (contact.getFullName() != null) { - if (contact.getFullName().toLowerCase(Locale.getDefault()).contains(search)) { - searchContacts.add(contact); + if (contact.getFullName().toLowerCase(Locale.getDefault()).startsWith(search)) { + searchContactsBegin.add(contact); + } else if (contact.getFullName().toLowerCase(Locale.getDefault()).contains(search)) { + searchContactsContain.add(contact); } } } - return searchContacts; + searchContactsBegin.addAll(searchContactsContain); + return searchContactsBegin; } - + public void enableContactsAccess() { hasContactAccess = true; } - + public boolean hasContactsAccess() { return hasContactAccess && !context.getResources().getBoolean(R.bool.force_use_of_linphone_friends); } @@ -187,17 +196,17 @@ public class ContactsManager extends ContentObserver { } initializeContactManager(context, contentResolver); } - + public LinphoneContact findContactFromAddress(LinphoneAddress address) { String sipUri = address.asStringUriOnly(); String username = address.getUserName(); - + LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); LinphoneProxyConfig lpc = null; if (lc != null) { lpc = lc.getDefaultProxyConfig(); } - + for (LinphoneContact c: getContacts()) { for (LinphoneNumberOrAddress noa: c.getNumbersOrAddresses()) { String normalized = null; @@ -205,7 +214,7 @@ public class ContactsManager extends ContentObserver { normalized = lpc.normalizePhoneNumber(noa.getValue()); } String alias = c.getPresenceModelForUri(noa.getValue()); - + if ((noa.isSIPAddress() && noa.getValue().equals(sipUri)) || (alias != null && alias.equals(sipUri)) || (normalized != null && !noa.isSIPAddress() && normalized.equals(username)) || (!noa.isSIPAddress() && noa.getValue().equals(username))) { return c; } @@ -213,14 +222,14 @@ public class ContactsManager extends ContentObserver { } return null; } - + public LinphoneContact findContactFromPhoneNumber(String phoneNumber) { LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); LinphoneProxyConfig lpc = null; if (lc != null) { lpc = lc.getDefaultProxyConfig(); } - + for (LinphoneContact c: getContacts()) { for (LinphoneNumberOrAddress noa: c.getNumbersOrAddresses()) { String normalized = null; @@ -234,7 +243,7 @@ public class ContactsManager extends ContentObserver { } return null; } - + public synchronized void setContacts(List c) { contacts = c; sipContacts = new ArrayList(); @@ -244,7 +253,7 @@ public class ContactsManager extends ContentObserver { } } } - + public synchronized void fetchContactsAsync() { if (contactsFetchTask != null && !contactsFetchTask.isCancelled()) { contactsFetchTask.cancel(true); @@ -252,12 +261,12 @@ public class ContactsManager extends ContentObserver { contactsFetchTask = new ContactsFetchTask(); contactsFetchTask.execute(); } - + private class ContactsFetchTask extends AsyncTask, List> { @SuppressWarnings("unchecked") protected List doInBackground(Void... params) { List contacts = new ArrayList(); - + if (hasContactsAccess()) { Cursor c = getContactsCursor(contentResolver); if (c != null) { @@ -312,7 +321,7 @@ public class ContactsManager extends ContentObserver { contact.minimalRefresh(); } Collections.sort(contacts); - + // Public the current list of contacts without all the informations populated publishProgress(contacts); @@ -320,17 +329,17 @@ public class ContactsManager extends ContentObserver { // This time fetch all informations including phone numbers and SIP addresses contact.refresh(); } - + return contacts; } - + protected void onProgressUpdate(List... result) { setContacts(result[0]); for (ContactsUpdatedListener listener : contactsUpdatedListeners) { listener.onContactsUpdated(); } } - + protected void onPostExecute(List result) { setContacts(result); for (ContactsUpdatedListener listener : contactsUpdatedListeners) { @@ -338,7 +347,7 @@ public class ContactsManager extends ContentObserver { } } } - + public static String getAddressOrNumberForAndroidContact(ContentResolver resolver, Uri contactUri) { // Phone Numbers String[] projection = new String[] { ContactsContract.CommonDataKinds.Phone.NUMBER }; @@ -366,17 +375,17 @@ public class ContactsManager extends ContentObserver { } return null; } - + public void delete(String id) { ArrayList ids = new ArrayList(); ids.add(id); deleteMultipleContactsAtOnce(ids); } - + public void deleteMultipleContactsAtOnce(List ids) { String select = ContactsContract.Data.CONTACT_ID + " = ?"; ArrayList ops = new ArrayList(); - + for (String id : ids) { String[] args = new String[] { id }; ops.add(ContentProviderOperation.newDelete(ContactsContract.RawContacts.CONTENT_URI).withSelection(select, args).build()); @@ -389,11 +398,11 @@ public class ContactsManager extends ContentObserver { Log.e(e); } } - + public String getString(int resourceID) { return context.getString(resourceID); } - + private Cursor getContactsCursor(ContentResolver cr) { String req = "(" + Data.MIMETYPE + " = '" + CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "' AND " + CommonDataKinds.Phone.NUMBER + " IS NOT NULL " @@ -406,7 +415,7 @@ public class ContactsManager extends ContentObserver { if (cursor == null) { return cursor; } - + MatrixCursor result = new MatrixCursor(cursor.getColumnNames()); Set groupBy = new HashSet(); while (cursor.moveToNext()) { @@ -414,13 +423,13 @@ public class ContactsManager extends ContentObserver { if (!groupBy.contains(name)) { groupBy.add(name); Object[] newRow = new Object[cursor.getColumnCount()]; - + int contactID = cursor.getColumnIndex(Data.CONTACT_ID); int displayName = cursor.getColumnIndex(Data.DISPLAY_NAME); - + newRow[contactID] = cursor.getString(contactID); newRow[displayName] = cursor.getString(displayName); - + result.addRow(newRow); } }