diff --git a/app/build.gradle b/app/build.gradle index d2163fc4..472c5040 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -41,7 +41,7 @@ ext { } dependencies { - implementation 'com.simplemobiletools:commons:3.5.5' + implementation 'com.simplemobiletools:commons:3.5.6' implementation 'joda-time:joda-time:2.9.9' //debugImplementation "com.squareup.leakcanary:leakcanary-android:$leakCanaryVersion" diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ContactActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ContactActivity.kt index ef2163e6..92a2d9f4 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ContactActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ContactActivity.kt @@ -234,6 +234,7 @@ class ContactActivity : SimpleActivity() { contact_source.text = contact!!.source contact_toggle_favorite.apply { + beVisible() setImageDrawable(getStarDrawable(contact!!.starred == 1)) tag = contact!!.starred applyColorFilter(config.textColor) @@ -306,14 +307,9 @@ class ContactActivity : SimpleActivity() { private fun setupNewContact() { window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE) supportActionBar?.title = resources.getString(R.string.new_contact) - contact = Contact(0, "", "", "", "", ArrayList(), ArrayList(), ArrayList(), "", 0) + contact = Contact(0, "", "", "", "", ArrayList(), ArrayList(), ArrayList(), "", 0, 0) contact_source.text = config.lastUsedContactSource contact_source.setOnClickListener { showAccountSourcePicker() } - - contact_toggle_favorite.apply { - tag = 0 - applyColorFilter(config.textColor) - } } private fun showPhotoPlaceholder() { @@ -678,10 +674,7 @@ class ContactActivity : SimpleActivity() { private fun isContactStarred() = contact_toggle_favorite.tag == 1 - private fun getStarDrawable(on: Boolean): Drawable { - val newDrawable = resources.getDrawable(if (on) R.drawable.ic_star_on else R.drawable.ic_star_off) - return newDrawable - } + private fun getStarDrawable(on: Boolean) = resources.getDrawable(if (on) R.drawable.ic_star_on_big else R.drawable.ic_star_off_big) private fun trySetPhoto() { val items = arrayListOf( diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/adapters/ContactsAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/adapters/ContactsAdapter.kt index 4c14002f..71b2a2df 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/adapters/ContactsAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/adapters/ContactsAdapter.kt @@ -137,8 +137,9 @@ class ContactsAdapter(activity: SimpleActivity, var contactItems: MutableList() - favoritesToRemove.mapTo(favoriteIDsToRemove, { it.id.toString() }) + val favoriteIDsToRemove = ArrayList() + favoritesToRemove.mapTo(favoriteIDsToRemove, { it.contactId.toString() }) + ContactsHelper(activity).removeFavorites(favoriteIDsToRemove) if (contactItems.isEmpty()) { listener?.refreshFavorites() finishActMode() @@ -152,8 +153,9 @@ class ContactsAdapter(activity: SimpleActivity, var contactItems: MutableList() - selectedPositions.forEach { newFavorites.add(contactItems[it].id.toString()) } + val newFavorites = ArrayList() + selectedPositions.forEach { newFavorites.add(contactItems[it].contactId.toString()) } + ContactsHelper(activity).addFavorites(newFavorites) listener?.refreshFavorites() finishActMode() } diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/adapters/SelectContactsAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/adapters/SelectContactsAdapter.kt index 4d68bbae..476c5c8b 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/adapters/SelectContactsAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/adapters/SelectContactsAdapter.kt @@ -61,9 +61,9 @@ class SelectContactsAdapter(val activity: SimpleActivity, val contacts: List { - val selectedItemsSet = HashSet(selectedPositions.size) - selectedPositions.forEach { selectedItemsSet.add(contacts[it].id.toString()) } + fun getSelectedItemsSet(): HashSet { + val selectedItemsSet = HashSet(selectedPositions.size) + selectedPositions.forEach { selectedItemsSet.add(contacts[it]) } return selectedItemsSet } diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/AddFavoritesDialog.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/AddFavoritesDialog.kt index f1bbfa33..884c8be9 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/AddFavoritesDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/AddFavoritesDialog.kt @@ -10,8 +10,6 @@ import com.simplemobiletools.contacts.extensions.config import com.simplemobiletools.contacts.helpers.ContactsHelper import com.simplemobiletools.contacts.models.Contact import kotlinx.android.synthetic.main.layout_select_contact.view.* -import java.util.HashSet -import kotlin.collections.ArrayList class AddFavoritesDialog(val activity: SimpleActivity, val callback: () -> Unit) { private var dialog: AlertDialog? = null @@ -45,22 +43,31 @@ class AddFavoritesDialog(val activity: SimpleActivity, val callback: () -> Unit) } dialog = AlertDialog.Builder(activity) - .setPositiveButton(R.string.ok, { dialog, which -> dialogConfirmed() }) + .setPositiveButton(R.string.ok, null) .setNegativeButton(R.string.cancel, null) .create().apply { activity.setupDialogStuff(view, this) + getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener { + dialogConfirmed() + } } } private fun dialogConfirmed() { - val allDisplayedIDs = ArrayList() - allContacts.mapTo(allDisplayedIDs, { it.id.toString() }) - val selectedItems = (view.select_contact_list.adapter as SelectContactsAdapter).getSelectedItemsSet() - allDisplayedIDs.removeAll(selectedItems) + Thread { + val contactsHelper = ContactsHelper(activity) + val allDisplayedContacts = ArrayList() + allContacts.mapTo(allDisplayedContacts, { it }) + val selectedContacts = (view.select_contact_list.adapter as SelectContactsAdapter).getSelectedItemsSet() + val contactIDsToAdd = selectedContacts.map { it.contactId.toString() } as ArrayList + contactsHelper.addFavorites(contactIDsToAdd) - val favoriteIDsToRemove = HashSet() - allDisplayedIDs.mapTo(favoriteIDsToRemove, { it }) - callback() - dialog?.dismiss() + allDisplayedContacts.removeAll(selectedContacts) + val contactIDsToRemove = allDisplayedContacts.map { it.contactId.toString() } as ArrayList + contactsHelper.removeFavorites(contactIDsToRemove) + + callback() + dialog?.dismiss() + }.start() } } diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt index 6cd84f0f..3d6dd75e 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt @@ -3,6 +3,7 @@ package com.simplemobiletools.contacts.helpers import android.content.ContentProviderOperation import android.content.ContentProviderResult import android.content.ContentUris +import android.content.ContentValues import android.database.Cursor import android.graphics.Bitmap import android.net.Uri @@ -52,7 +53,8 @@ class ContactsHelper(val activity: BaseSimpleActivity) { val events = ArrayList() val accountName = cursor.getStringValue(ContactsContract.RawContacts.ACCOUNT_NAME) val starred = cursor.getIntValue(ContactsContract.CommonDataKinds.StructuredName.STARRED) - val contact = Contact(id, firstName, middleName, surname, photoUri, number, emails, events, accountName, starred) + val contactId = cursor.getIntValue(ContactsContract.Data.CONTACT_ID) + val contact = Contact(id, firstName, middleName, surname, photoUri, number, emails, events, accountName, starred, contactId) contacts.put(id, contact) } while (cursor.moveToNext()) } @@ -77,8 +79,9 @@ class ContactsHelper(val activity: BaseSimpleActivity) { } val contactsSize = contacts.size() - val resultContacts = ArrayList(contactsSize) + var resultContacts = ArrayList(contactsSize) (0 until contactsSize).mapTo(resultContacts) { contacts.valueAt(it) } + resultContacts = resultContacts.distinctBy { it.contactId } as ArrayList callback(resultContacts) }.start() } @@ -207,7 +210,8 @@ class ContactsHelper(val activity: BaseSimpleActivity) { val events = getEvents(id)[id] ?: ArrayList() val accountName = cursor.getStringValue(ContactsContract.RawContacts.ACCOUNT_NAME) val starred = cursor.getIntValue(ContactsContract.CommonDataKinds.StructuredName.STARRED) - return Contact(id, firstName, middleName, surname, photoUri, number, emails, events, accountName, starred) + val contactId = cursor.getIntValue(ContactsContract.Data.CONTACT_ID) + return Contact(id, firstName, middleName, surname, photoUri, number, emails, events, accountName, starred, contactId) } } finally { cursor?.close() @@ -239,7 +243,7 @@ class ContactsHelper(val activity: BaseSimpleActivity) { }.start() } - fun getContactSourceType(accountName: String): String { + private fun getContactSourceType(accountName: String): String { val uri = ContactsContract.RawContacts.CONTENT_URI val projection = arrayOf(ContactsContract.RawContacts.ACCOUNT_TYPE) val selection = "${ContactsContract.RawContacts.ACCOUNT_NAME} = ?" @@ -258,6 +262,7 @@ class ContactsHelper(val activity: BaseSimpleActivity) { } private fun getContactProjection() = arrayOf( + ContactsContract.Data.CONTACT_ID, ContactsContract.Data.RAW_CONTACT_ID, ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME, @@ -354,6 +359,16 @@ class ContactsHelper(val activity: BaseSimpleActivity) { } } + // favorite + try { + val uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, contact.contactId.toString()) + val contentValues = ContentValues(1) + contentValues.put(ContactsContract.Contacts.STARRED, contact.starred) + activity.contentResolver.update(uri, contentValues, null, null) + } catch (e: Exception) { + activity.showErrorToast(e) + } + // photo when (photoUpdateStatus) { PHOTO_ADDED, PHOTO_CHANGED -> addPhoto(contact, operations) @@ -540,6 +555,30 @@ class ContactsHelper(val activity: BaseSimpleActivity) { return "" } + fun addFavorites(ids: ArrayList) { + toggleFavorites(ids, true) + } + + fun removeFavorites(ids: ArrayList) { + toggleFavorites(ids, false) + } + + private fun toggleFavorites(ids: ArrayList, areFavorites: Boolean) { + try { + val operations = ArrayList() + ids.forEach { + val uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, it) + ContentProviderOperation.newUpdate(uri).apply { + withValue(ContactsContract.Contacts.STARRED, if (areFavorites) 1 else 0) + operations.add(build()) + } + } + activity.contentResolver.applyBatch(ContactsContract.AUTHORITY, operations) + } catch (e: Exception) { + activity.showErrorToast(e) + } + } + fun deleteContact(contact: Contact) = deleteContacts(arrayListOf(contact)) fun deleteContacts(contacts: ArrayList) { diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/models/Contact.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/models/Contact.kt index fab1fec3..44e3ab64 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/models/Contact.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/models/Contact.kt @@ -6,7 +6,7 @@ import com.simplemobiletools.commons.helpers.SORT_DESCENDING data class Contact(val id: Int, var firstName: String, var middleName: String, var surname: String, var photoUri: String, var phoneNumbers: ArrayList, var emails: ArrayList, var events: ArrayList, var source: String, - var starred: Int) : Comparable { + var starred: Int, val contactId: Int) : Comparable { companion object { var sorting: Int = 0 } diff --git a/app/src/main/res/layout/activity_contact.xml b/app/src/main/res/layout/activity_contact.xml index 00b4d0c4..9d1477b4 100644 --- a/app/src/main/res/layout/activity_contact.xml +++ b/app/src/main/res/layout/activity_contact.xml @@ -28,7 +28,8 @@ android:layout_toRightOf="@+id/contact_photo" android:adjustViewBounds="true" android:padding="@dimen/tiny_margin" - android:src="@drawable/ic_star_off"/> + android:src="@drawable/ic_star_off_big" + android:visibility="gone"/>