diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/activities/EditContactActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/activities/EditContactActivity.kt index abf4376c..5ce6b5c1 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/activities/EditContactActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/activities/EditContactActivity.kt @@ -168,7 +168,7 @@ class EditContactActivity : ContactActivity() { val phone = intent.extras.get(KEY_PHONE) if (phone != null) { val phoneNumber = phone.toString() - contact!!.phoneNumbers.add(PhoneNumber(phoneNumber, DEFAULT_PHONE_NUMBER_TYPE, "")) + contact!!.phoneNumbers.add(PhoneNumber(phoneNumber, DEFAULT_PHONE_NUMBER_TYPE, "", phoneNumber.normalizeNumber())) if (phoneNumber.isNotEmpty() && action == ADD_NEW_CONTACT_NUMBER) { highlightLastPhoneNumber = true } @@ -883,7 +883,7 @@ class EditContactActivity : ContactActivity() { val numberLabel = if (numberType == CommonDataKinds.Phone.TYPE_CUSTOM) numberHolder.contact_number_type.value else "" if (number.isNotEmpty()) { - phoneNumbers.add(PhoneNumber(number, numberType, numberLabel)) + phoneNumbers.add(PhoneNumber(number, numberType, numberLabel, number.normalizeNumber())) } } return phoneNumbers diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/extensions/Context.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/extensions/Context.kt index 38691b30..cf675e63 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/extensions/Context.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/extensions/Context.kt @@ -36,7 +36,7 @@ fun Context.getEmptyContact(): Contact { val originalContactSource = if (hasContactPermissions()) config.lastUsedContactSource else SMT_PRIVATE val organization = Organization("", "") return Contact(0, "", "", "", "", "", "", "", ArrayList(), ArrayList(), ArrayList(), ArrayList(), originalContactSource, 0, 0, "", - null, "", ArrayList(), organization, ArrayList(), ArrayList(), ArrayList()) + null, "", ArrayList(), organization, ArrayList(), ArrayList()) } fun Context.viewContact(contact: Contact) { diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/extensions/String.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/extensions/String.kt index b35d3b9a..beda894f 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/extensions/String.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/extensions/String.kt @@ -1,8 +1,8 @@ package com.simplemobiletools.contacts.pro.extensions +import android.telephony.PhoneNumberUtils import android.widget.TextView import com.simplemobiletools.commons.helpers.getDateFormats -import com.simplemobiletools.contacts.pro.helpers.PHONE_NUMBER_PATTERN import org.joda.time.DateTime import org.joda.time.format.DateTimeFormat import java.text.DateFormat @@ -34,4 +34,4 @@ fun String.getDateTimeFromDateString(viewToUpdate: TextView? = null): DateTime { return date } -fun String.applyRegexFiltering() = replace(PHONE_NUMBER_PATTERN.toRegex(), "") +fun String.normalizeNumber() = PhoneNumberUtils.normalizeNumber(this) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/fragments/RecentsFragment.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/fragments/RecentsFragment.kt index 12678e9f..814df2fa 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/fragments/RecentsFragment.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/fragments/RecentsFragment.kt @@ -9,8 +9,8 @@ import com.simplemobiletools.commons.helpers.PERMISSION_READ_CALL_LOG import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_CALL_LOG import com.simplemobiletools.contacts.pro.activities.EditContactActivity import com.simplemobiletools.contacts.pro.adapters.RecentCallsAdapter -import com.simplemobiletools.contacts.pro.extensions.applyRegexFiltering import com.simplemobiletools.contacts.pro.extensions.contactClicked +import com.simplemobiletools.contacts.pro.extensions.normalizeNumber import com.simplemobiletools.contacts.pro.helpers.IS_FROM_SIMPLE_CONTACTS import com.simplemobiletools.contacts.pro.helpers.KEY_PHONE import com.simplemobiletools.contacts.pro.helpers.RECENTS_TAB_MASK @@ -43,10 +43,10 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage val currAdapter = fragment_list.adapter if (currAdapter == null) { RecentCallsAdapter(activity!!, recentCalls, activity, fragment_list, fragment_fastscroller) { - val recentCall = (it as RecentCall).number.applyRegexFiltering() + val recentCall = (it as RecentCall).number.normalizeNumber() var selectedContact: Contact? = null for (contact in allContacts) { - if (contact.phoneNumbers.any { it.value.applyRegexFiltering() == recentCall }) { + if (contact.phoneNumbers.any { it.normalizedNumber == recentCall }) { selectedContact = contact break } diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/Constants.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/Constants.kt index 7f51f50a..fbe43487 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/Constants.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/Constants.kt @@ -23,7 +23,6 @@ const val CONTACT_ID = "contact_id" const val SMT_PRIVATE = "smt_private" // used at the contact source of local contacts hidden from other apps const val IS_PRIVATE = "is_private" const val GROUP = "group" -const val PHONE_NUMBER_PATTERN = "[^0-9#*+]" const val IS_FROM_SIMPLE_CONTACTS = "is_from_simple_contacts" const val ADD_NEW_CONTACT_NUMBER = "add_new_contact_number" const val FIRST_CONTACT_ID = 1000000 diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/ContactsHelper.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/ContactsHelper.kt index aec129c8..d84acd23 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/ContactsHelper.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/ContactsHelper.kt @@ -96,8 +96,8 @@ class ContactsHelper(val activity: Activity) { Thread { val uri = CommonDataKinds.Phone.CONTENT_URI val projection = arrayOf(ContactsContract.Data.RAW_CONTACT_ID) - val selection = "${CommonDataKinds.Phone.NUMBER} = ?" - val selectionArgs = arrayOf(number) + val selection = "${CommonDataKinds.Phone.NORMALIZED_NUMBER} = ?" + val selectionArgs = arrayOf(number.normalizeNumber()) var cursor: Cursor? = null try { @@ -180,10 +180,9 @@ class ContactsHelper(val activity: Activity) { val groups = ArrayList() val organization = Organization("", "") val websites = ArrayList() - val cleanNumbers = ArrayList() val ims = ArrayList() val contact = Contact(id, prefix, firstName, middleName, surname, suffix, nickname, photoUri, numbers, emails, addresses, - events, accountName, starred, contactId, thumbnailUri, null, notes, groups, organization, websites, cleanNumbers, ims) + events, accountName, starred, contactId, thumbnailUri, null, notes, groups, organization, websites, ims) contacts.put(id, contact) } while (cursor.moveToNext()) @@ -194,7 +193,6 @@ class ContactsHelper(val activity: Activity) { cursor?.close() } - val filterDuplicates = activity.config.filterDuplicates val phoneNumbers = getPhoneNumbers(null) var size = phoneNumbers.size() for (i in 0 until size) { @@ -202,13 +200,6 @@ class ContactsHelper(val activity: Activity) { if (contacts[key] != null) { val numbers = phoneNumbers.valueAt(i) contacts[key].phoneNumbers = numbers - - if (filterDuplicates) { - // remove all spaces, dashes etc from numbers for easier comparing, used only at list views - numbers.forEach { - numbers.mapTo(contacts[key].cleanPhoneNumbers) { PhoneNumber(it.value.applyRegexFiltering(), 0, "") } - } - } } } @@ -275,6 +266,7 @@ class ContactsHelper(val activity: Activity) { val projection = arrayOf( ContactsContract.Data.RAW_CONTACT_ID, CommonDataKinds.Phone.NUMBER, + CommonDataKinds.Phone.NORMALIZED_NUMBER, CommonDataKinds.Phone.TYPE, CommonDataKinds.Phone.LABEL ) @@ -289,6 +281,7 @@ class ContactsHelper(val activity: Activity) { do { val id = cursor.getIntValue(ContactsContract.Data.RAW_CONTACT_ID) val number = cursor.getStringValue(CommonDataKinds.Phone.NUMBER) ?: continue + val normalizedNumber = cursor.getStringValue(CommonDataKinds.Phone.NORMALIZED_NUMBER) ?: "" val type = cursor.getIntValue(CommonDataKinds.Phone.TYPE) val label = cursor.getStringValue(CommonDataKinds.Phone.LABEL) ?: "" @@ -296,7 +289,7 @@ class ContactsHelper(val activity: Activity) { phoneNumbers.put(id, ArrayList()) } - val phoneNumber = PhoneNumber(number, type, label) + val phoneNumber = PhoneNumber(number, type, label, normalizedNumber) phoneNumbers[id].add(phoneNumber) } while (cursor.moveToNext()) } @@ -837,10 +830,9 @@ class ContactsHelper(val activity: Activity) { val thumbnailUri = cursor.getStringValue(CommonDataKinds.StructuredName.PHOTO_THUMBNAIL_URI) ?: "" val organization = getOrganizations(id)[id] ?: Organization("", "") val websites = getWebsites(id)[id] ?: ArrayList() - val cleanNumbers = ArrayList() val ims = getIMs(id)[id] ?: ArrayList() return Contact(id, prefix, firstName, middleName, surname, suffix, nickname, photoUri, number, emails, addresses, events, - accountName, starred, contactId, thumbnailUri, null, notes, groups, organization, websites, cleanNumbers, ims) + accountName, starred, contactId, thumbnailUri, null, notes, groups, organization, websites, ims) } } finally { cursor?.close() @@ -990,6 +982,7 @@ class ContactsHelper(val activity: Activity) { withValue(ContactsContract.Data.RAW_CONTACT_ID, contact.id) withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Phone.CONTENT_ITEM_TYPE) withValue(CommonDataKinds.Phone.NUMBER, it.value) + withValue(CommonDataKinds.Phone.NORMALIZED_NUMBER, it.normalizedNumber) withValue(CommonDataKinds.Phone.TYPE, it.type) withValue(CommonDataKinds.Phone.LABEL, it.label) operations.add(build()) @@ -1292,6 +1285,7 @@ class ContactsHelper(val activity: Activity) { withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Phone.CONTENT_ITEM_TYPE) withValue(CommonDataKinds.Phone.NUMBER, it.value) + withValue(CommonDataKinds.Phone.NORMALIZED_NUMBER, it.normalizedNumber) withValue(CommonDataKinds.Phone.TYPE, it.type) withValue(CommonDataKinds.Phone.LABEL, it.label) operations.add(build()) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/LocalContactsHelper.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/LocalContactsHelper.kt index a15396c2..438f8eee 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/LocalContactsHelper.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/LocalContactsHelper.kt @@ -5,8 +5,14 @@ import android.graphics.Bitmap import android.graphics.BitmapFactory import android.net.Uri import android.provider.MediaStore -import com.simplemobiletools.contacts.pro.extensions.* -import com.simplemobiletools.contacts.pro.models.* +import com.simplemobiletools.contacts.pro.extensions.contactsDB +import com.simplemobiletools.contacts.pro.extensions.getByteArray +import com.simplemobiletools.contacts.pro.extensions.getEmptyContact +import com.simplemobiletools.contacts.pro.extensions.getPhotoThumbnailSize +import com.simplemobiletools.contacts.pro.models.Contact +import com.simplemobiletools.contacts.pro.models.Group +import com.simplemobiletools.contacts.pro.models.LocalContact +import com.simplemobiletools.contacts.pro.models.Organization class LocalContactsHelper(val activity: Activity) { fun getAllContacts() = activity.contactsDB.getContacts().map { convertLocalContactToContact(it) }.toMutableList() as ArrayList @@ -81,12 +87,6 @@ class LocalContactsHelper(val activity: Activity) { return null } - val filterDuplicates = activity.config.filterDuplicates - val filteredPhoneNumbers = ArrayList() - if (filterDuplicates) { - localContact.phoneNumbers.mapTo(filteredPhoneNumbers) { PhoneNumber(it.value.applyRegexFiltering(), 0, "") } - } - val contactPhoto = if (localContact.photo == null) { null } else { @@ -121,7 +121,6 @@ class LocalContactsHelper(val activity: Activity) { groups = storedGroups.filter { localContact.groups.contains(it.id) } as ArrayList organization = Organization(localContact.company, localContact.jobPosition) websites = localContact.websites - cleanPhoneNumbers = filteredPhoneNumbers IMs = localContact.IMs } } diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/VcfImporter.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/VcfImporter.kt index d62a0098..fe08741a 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/VcfImporter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/VcfImporter.kt @@ -9,6 +9,7 @@ import com.simplemobiletools.contacts.pro.activities.SimpleActivity import com.simplemobiletools.contacts.pro.extensions.getCachePhoto import com.simplemobiletools.contacts.pro.extensions.getCachePhotoUri import com.simplemobiletools.contacts.pro.extensions.groupsDB +import com.simplemobiletools.contacts.pro.extensions.normalizeNumber import com.simplemobiletools.contacts.pro.helpers.VcfImporter.ImportResult.* import com.simplemobiletools.contacts.pro.models.* import ezvcard.Ezvcard @@ -59,7 +60,7 @@ class VcfImporter(val activity: SimpleActivity) { "" } - phoneNumbers.add(PhoneNumber(number, type, label)) + phoneNumbers.add(PhoneNumber(number, type, label, number.normalizeNumber())) } val emails = ArrayList() @@ -112,7 +113,6 @@ class VcfImporter(val activity: SimpleActivity) { val photoData = ezContact.photos.firstOrNull()?.data val photo = null val thumbnailUri = savePhoto(photoData) - val cleanPhoneNumbers = ArrayList() val IMs = ArrayList() ezContact.impps.forEach { @@ -136,7 +136,7 @@ class VcfImporter(val activity: SimpleActivity) { } val contact = Contact(0, prefix, firstName, middleName, surname, suffix, nickname, photoUri, phoneNumbers, emails, addresses, events, - targetContactSource, starred, contactId, thumbnailUri, photo, notes, groups, organization, websites, cleanPhoneNumbers, IMs) + targetContactSource, starred, contactId, thumbnailUri, photo, notes, groups, organization, websites, IMs) // if there is no N and ORG fields at the given contact, only FN, treat it as an organization if (contact.getNameToDisplay().isEmpty() && contact.organization.isEmpty() && ezContact.formattedName.value.isNotEmpty()) { diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/models/Contact.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/models/Contact.kt index a9e5bb92..750ccce0 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/models/Contact.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/models/Contact.kt @@ -5,13 +5,12 @@ import com.simplemobiletools.commons.extensions.normalizeString import com.simplemobiletools.commons.helpers.SORT_BY_FIRST_NAME import com.simplemobiletools.commons.helpers.SORT_BY_MIDDLE_NAME import com.simplemobiletools.commons.helpers.SORT_DESCENDING -import com.simplemobiletools.contacts.pro.extensions.applyRegexFiltering +import com.simplemobiletools.contacts.pro.extensions.normalizeNumber data class Contact(var id: Int, var prefix: String, var firstName: String, var middleName: String, var surname: String, var suffix: String, var nickname: String, var photoUri: String, var phoneNumbers: ArrayList, var emails: ArrayList, var addresses: ArrayList
, var events: ArrayList, var source: String, var starred: Int, var contactId: Int, var thumbnailUri: String, var photo: Bitmap?, var notes: String, - var groups: ArrayList, var organization: Organization, var websites: ArrayList, var cleanPhoneNumbers: ArrayList, - var IMs: ArrayList) : + var groups: ArrayList, var organization: Organization, var websites: ArrayList, var IMs: ArrayList) : Comparable { companion object { var sorting = 0 @@ -126,21 +125,11 @@ data class Contact(var id: Int, var prefix: String, var firstName: String, var m fun isABusinessContact() = prefix.isEmpty() && firstName.isEmpty() && middleName.isEmpty() && surname.isEmpty() && suffix.isEmpty() && organization.isNotEmpty() - // do a more advanced phone number check here, compare numbers and and search query with dashes, spaces and everything but numbers removed fun doesContainPhoneNumber(text: String): Boolean { - if (text.isNotEmpty()) { - if (phoneNumbers.any { it.value.contains(text) } || cleanPhoneNumbers.any { it.value.contains(text) }) { - return true - } + return if (text.isNotEmpty()) { + phoneNumbers.any { it.value.contains(text) || it.normalizedNumber?.contains(text.normalizeNumber()) == true || it.value.normalizeNumber().contains(text.normalizeNumber()) } + } else { + false } - - val filteredNumber = text.applyRegexFiltering() - if (filteredNumber.isNotEmpty()) { - if (phoneNumbers.any { it.value.contains(filteredNumber) } || cleanPhoneNumbers.any { it.value.contains(filteredNumber) }) { - return true - } - } - - return false } } diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/models/PhoneNumber.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/models/PhoneNumber.kt index b95127aa..3c0850c3 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/models/PhoneNumber.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/models/PhoneNumber.kt @@ -1,3 +1,3 @@ package com.simplemobiletools.contacts.pro.models -data class PhoneNumber(var value: String, var type: Int, var label: String) +data class PhoneNumber(var value: String, var type: Int, var label: String, var normalizedNumber: String?)