From 83aa99b8f8d6cb09c2374fbf75f9e4568dc704c4 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 7 Nov 2012 12:07:20 +0100 Subject: [PATCH] Can remove contact and edit existing fields inside linphone --- .../button_alert_background_default.9.png | Bin 0 -> 1674 bytes .../button_alert_background_over.9.png | Bin 0 -> 1537 bytes res/drawable/alert.xml | 7 + res/layout/contact.xml | 17 +- res/layout/contact_delete_button.xml | 14 ++ res/layout/contact_edit_row.xml | 26 ++ res/layout/edit_contact.xml | 17 +- src/org/linphone/ContactFragment.java | 10 +- src/org/linphone/EditContactFragment.java | 224 +++++++++++++++++- src/org/linphone/LinphoneActivity.java | 14 +- 10 files changed, 295 insertions(+), 34 deletions(-) create mode 100644 res/drawable-xhdpi/button_alert_background_default.9.png create mode 100644 res/drawable-xhdpi/button_alert_background_over.9.png create mode 100644 res/drawable/alert.xml create mode 100644 res/layout/contact_delete_button.xml create mode 100644 res/layout/contact_edit_row.xml diff --git a/res/drawable-xhdpi/button_alert_background_default.9.png b/res/drawable-xhdpi/button_alert_background_default.9.png new file mode 100644 index 0000000000000000000000000000000000000000..b8857340dd27df61c4863234e25a1499945da32f GIT binary patch literal 1674 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 + + + + \ No newline at end of file diff --git a/res/layout/contact.xml b/res/layout/contact.xml index 627bef0f7..040e12e04 100644 --- a/res/layout/contact.xml +++ b/res/layout/contact.xml @@ -22,22 +22,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" - android:adjustViewBounds="true" - android:layout_weight="1"/> - - + android:adjustViewBounds="true"/> diff --git a/res/layout/contact_delete_button.xml b/res/layout/contact_delete_button.xml new file mode 100644 index 000000000..90af7a399 --- /dev/null +++ b/res/layout/contact_delete_button.xml @@ -0,0 +1,14 @@ + + + \ No newline at end of file diff --git a/res/layout/contact_edit_row.xml b/res/layout/contact_edit_row.xml new file mode 100644 index 000000000..4c6b13a80 --- /dev/null +++ b/res/layout/contact_edit_row.xml @@ -0,0 +1,26 @@ + + + + + + + + \ No newline at end of file diff --git a/res/layout/edit_contact.xml b/res/layout/edit_contact.xml index ac8f68cc2..0e230638a 100644 --- a/res/layout/edit_contact.xml +++ b/res/layout/edit_contact.xml @@ -63,10 +63,25 @@ android:layout_height="wrap_content" android:textColor="@android:color/black" android:background="@drawable/chat_fast_address_background" - android:gravity="center" + android:gravity="left" android:paddingRight="5dp" android:inputType="textPersonName|textCapWords"/> + + + + + + \ No newline at end of file diff --git a/src/org/linphone/ContactFragment.java b/src/org/linphone/ContactFragment.java index a623423b0..680d5c135 100644 --- a/src/org/linphone/ContactFragment.java +++ b/src/org/linphone/ContactFragment.java @@ -39,7 +39,7 @@ import android.widget.TextView; */ public class ContactFragment extends Fragment implements OnClickListener { private Contact contact; - private TextView editContact, newContact; + private TextView editContact; private LayoutInflater inflater; private View view; private boolean displayChatAddressOnly = false; @@ -70,10 +70,6 @@ public class ContactFragment extends Fragment implements OnClickListener { editContact = (TextView) view.findViewById(R.id.editContact); editContact.setOnClickListener(this); - newContact = (TextView) view.findViewById(R.id.newContact); - if (newContact != null) { - newContact.setOnClickListener(this); - } return view; } @@ -186,10 +182,6 @@ public class ContactFragment extends Fragment implements OnClickListener { case R.id.editContact: LinphoneActivity.instance().editContact(contact); break; - - case R.id.newContact: - LinphoneActivity.instance().addContact("", ""); - break; } } } diff --git a/src/org/linphone/EditContactFragment.java b/src/org/linphone/EditContactFragment.java index 81e18b1ba..80c33c84d 100644 --- a/src/org/linphone/EditContactFragment.java +++ b/src/org/linphone/EditContactFragment.java @@ -1,8 +1,14 @@ package org.linphone; +import java.io.InputStream; import java.util.ArrayList; +import java.util.List; + +import org.linphone.compatibility.Compatibility; +import org.linphone.ui.AvatarWithShadow; import android.content.ContentProviderOperation; +import android.graphics.BitmapFactory; import android.os.Bundle; import android.provider.ContactsContract; import android.provider.ContactsContract.RawContacts; @@ -14,17 +20,23 @@ import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TableLayout; import android.widget.TextView; public class EditContactFragment extends Fragment { private View view; private TextView ok; private EditText displayName; + private LayoutInflater inflater; private boolean isNewContact = true; private int contactID; + private List numbersAndAddresses; public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + this.inflater = inflater; + Contact contact = null; if (getArguments() != null && getArguments().getSerializable("Contact") != null) { contact = (Contact) getArguments().getSerializable("Contact"); @@ -51,6 +63,11 @@ public class EditContactFragment extends Fragment { } else { updateExistingContact(); } + + for (NewOrUpdatedNumberOrAddress numberOrAddress : numbersAndAddresses) { + numberOrAddress.save(); + } + getFragmentManager().popBackStackImmediate(); } }); @@ -74,13 +91,85 @@ public class EditContactFragment extends Fragment { public void afterTextChanged(Editable s) { } }); + if (!isNewContact) { displayName.setText(contact.getName()); } + AvatarWithShadow contactPicture = (AvatarWithShadow) view.findViewById(R.id.contactPicture); + if (contact != null && contact.getPhotoUri() != null) { + InputStream input = Compatibility.getContactPictureInputStream(getActivity().getContentResolver(), contact.getID()); + contactPicture.setImageBitmap(BitmapFactory.decodeStream(input)); + } else { + contactPicture.setImageResource(R.drawable.unknown_small); + } + + initNumbersFields((TableLayout) view.findViewById(R.id.controls), contact); + return view; } + private void initNumbersFields(TableLayout controls, final Contact contact) { + controls.removeAllViews(); + numbersAndAddresses = new ArrayList(); + + if (contact != null) { + for (String numberOrAddress : contact.getNumerosOrAddresses()) { + boolean isSip = numberOrAddress.startsWith("sip:"); + if (isSip) { + numberOrAddress = numberOrAddress.replace("sip:", ""); + } + + final NewOrUpdatedNumberOrAddress nounoa = new NewOrUpdatedNumberOrAddress(numberOrAddress, isSip); + numbersAndAddresses.add(nounoa); + + final View view = inflater.inflate(R.layout.contact_edit_row, null); + + final EditText noa = (EditText) view.findViewById(R.id.numoraddr); + noa.setText(numberOrAddress); + noa.addTextChangedListener(new TextWatcher() { + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + nounoa.setNewNumberOrAddress(noa.getText().toString()); + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void afterTextChanged(Editable s) { + } + }); + + ImageView delete = (ImageView) view.findViewById(R.id.delete); + delete.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + nounoa.delete(); + view.setVisibility(View.GONE); + } + }); + + controls.addView(view); + } + + if (!isNewContact) { + View deleteContact = inflater.inflate(R.layout.contact_delete_button, null); + deleteContact.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + deleteExistingContact(); + LinphoneActivity.instance().removeContactFromLists(contact); + LinphoneActivity.instance().displayContacts(false); + } + }); + controls.addView(deleteContact); + } + + } + } + private void createNewContact() { ArrayList ops = new ArrayList(); contactID = ops.size(); @@ -93,14 +182,15 @@ public class EditContactFragment extends Fragment { ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, contactID) .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) - .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName.getText().toString()).build() + .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName.getText().toString()) + .build() ); } try { getActivity().getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); } catch (Exception e) { - + e.printStackTrace(); } } @@ -108,20 +198,140 @@ public class EditContactFragment extends Fragment { ArrayList ops = new ArrayList(); if (displayName.getText().length() > 0) { - String selectPhone = ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + "'" ; - String[] phoneArgs = new String[] { String.valueOf(contactID) }; + String select = ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + "'" ; + String[] args = new String[] { String.valueOf(contactID) }; ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI) - .withSelection(selectPhone, phoneArgs) + .withSelection(select, args) .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) - .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName.getText().toString()).build() + .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName.getText().toString()) + .build() ); } try { getActivity().getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); } catch (Exception e) { - + e.printStackTrace(); } } + + private void deleteExistingContact() { + ArrayList ops = new ArrayList(); + + if (displayName.getText().length() > 0) { + String select = ContactsContract.Data.CONTACT_ID + "=?"; + String[] args = new String[] { String.valueOf(contactID) }; + + ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) + .withSelection(select, args) + .build() + ); + } + + try { + getActivity().getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); + } catch (Exception e) { + e.printStackTrace(); + } + } + + class NewOrUpdatedNumberOrAddress { + private String oldNumberOrAddress; + private String newNumberOrAddress; + private boolean isSipAddress; + + public NewOrUpdatedNumberOrAddress(boolean isSip) { + oldNumberOrAddress = null; + newNumberOrAddress = null; + isSipAddress = isSip; + } + + public NewOrUpdatedNumberOrAddress(String old, boolean isSip) { + oldNumberOrAddress = old; + newNumberOrAddress = null; + isSipAddress = isSip; + } + + public void setNewNumberOrAddress(String newN) { + newNumberOrAddress = newN; + } + + public void save() { + if (newNumberOrAddress == null || newNumberOrAddress.equals(oldNumberOrAddress)) + return; + + ArrayList ops = new ArrayList(); + + if (oldNumberOrAddress == null) { + // New number to add + addNewNumber(ops); + } else { + // Old number to update + updateNumber(ops); + } + + try { + getActivity().getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void delete() { + //TODO + } + + private void addNewNumber(ArrayList ops) { + if (isSipAddress) { + ops.add(ContentProviderOperation. + newInsert(ContactsContract.Data.CONTENT_URI) + .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, contactID) + .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE) + .withValue(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS, newNumberOrAddress) + .withValue(ContactsContract.CommonDataKinds.SipAddress.TYPE, ContactsContract.CommonDataKinds.SipAddress.TYPE_CUSTOM) + .withValue(ContactsContract.CommonDataKinds.SipAddress.LABEL, "Linphone") + .build() + ); + } else { + ops.add(ContentProviderOperation. + newInsert(ContactsContract.Data.CONTENT_URI) + .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, contactID) + .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) + .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, newNumberOrAddress) + .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM) + .withValue(ContactsContract.CommonDataKinds.Phone.LABEL, "Linphone") + .build() + ); + } + } + + private void updateNumber(ArrayList ops) { + if (isSipAddress) { + String select = ContactsContract.Data.CONTACT_ID + "=? AND " + + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE + "' AND " + + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + "=?"; + String[] args = new String[] { String.valueOf(contactID), oldNumberOrAddress }; + + ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI) + .withSelection(select, args) + .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE) + .withValue(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS, newNumberOrAddress) + .build() + ); + } else { + String select = ContactsContract.Data.CONTACT_ID + "=? AND " + + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "' AND " + + ContactsContract.CommonDataKinds.Phone.NUMBER + "=?"; + String[] args = new String[] { String.valueOf(contactID), oldNumberOrAddress }; + + ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI) + .withSelection(select, args) + .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) + .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, newNumberOrAddress) + .build() + ); + } + } + } } diff --git a/src/org/linphone/LinphoneActivity.java b/src/org/linphone/LinphoneActivity.java index f9ebd4860..036ce7e17 100644 --- a/src/org/linphone/LinphoneActivity.java +++ b/src/org/linphone/LinphoneActivity.java @@ -1075,6 +1075,17 @@ public class LinphoneActivity extends FragmentActivity implements } } } + + public void removeContactFromLists(Contact contact) { + if (contactList.contains(contact)) { + contactList.remove(contact); + contactCursor = Compatibility.getContactsCursor(getContentResolver()); + } + if (sipContactList.contains(contact)) { + sipContactList.remove(contact); + sipContactCursor = Compatibility.getSIPContactsCursor(getContentResolver()); + } + } private synchronized void prepareContactsInBackground() { if (contactCursor != null) { @@ -1110,10 +1121,11 @@ public class LinphoneActivity extends FragmentActivity implements } } }); - sipContactsHandler.start(); contactList = new ArrayList(); sipContactList = new ArrayList(); + + sipContactsHandler.start(); } private void initInCallMenuLayout(boolean callTransfer) {