make use of the system string normalizing instead of custom regex

This commit is contained in:
tibbi
2018-11-20 23:31:50 +01:00
parent 0b75543fda
commit f0c4b012b7
10 changed files with 35 additions and 54 deletions

View File

@ -168,7 +168,7 @@ class EditContactActivity : ContactActivity() {
val phone = intent.extras.get(KEY_PHONE) val phone = intent.extras.get(KEY_PHONE)
if (phone != null) { if (phone != null) {
val phoneNumber = phone.toString() 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) { if (phoneNumber.isNotEmpty() && action == ADD_NEW_CONTACT_NUMBER) {
highlightLastPhoneNumber = true highlightLastPhoneNumber = true
} }
@ -883,7 +883,7 @@ class EditContactActivity : ContactActivity() {
val numberLabel = if (numberType == CommonDataKinds.Phone.TYPE_CUSTOM) numberHolder.contact_number_type.value else "" val numberLabel = if (numberType == CommonDataKinds.Phone.TYPE_CUSTOM) numberHolder.contact_number_type.value else ""
if (number.isNotEmpty()) { if (number.isNotEmpty()) {
phoneNumbers.add(PhoneNumber(number, numberType, numberLabel)) phoneNumbers.add(PhoneNumber(number, numberType, numberLabel, number.normalizeNumber()))
} }
} }
return phoneNumbers return phoneNumbers

View File

@ -36,7 +36,7 @@ fun Context.getEmptyContact(): Contact {
val originalContactSource = if (hasContactPermissions()) config.lastUsedContactSource else SMT_PRIVATE val originalContactSource = if (hasContactPermissions()) config.lastUsedContactSource else SMT_PRIVATE
val organization = Organization("", "") val organization = Organization("", "")
return Contact(0, "", "", "", "", "", "", "", ArrayList(), ArrayList(), ArrayList(), ArrayList(), originalContactSource, 0, 0, "", 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) { fun Context.viewContact(contact: Contact) {

View File

@ -1,8 +1,8 @@
package com.simplemobiletools.contacts.pro.extensions package com.simplemobiletools.contacts.pro.extensions
import android.telephony.PhoneNumberUtils
import android.widget.TextView import android.widget.TextView
import com.simplemobiletools.commons.helpers.getDateFormats import com.simplemobiletools.commons.helpers.getDateFormats
import com.simplemobiletools.contacts.pro.helpers.PHONE_NUMBER_PATTERN
import org.joda.time.DateTime import org.joda.time.DateTime
import org.joda.time.format.DateTimeFormat import org.joda.time.format.DateTimeFormat
import java.text.DateFormat import java.text.DateFormat
@ -34,4 +34,4 @@ fun String.getDateTimeFromDateString(viewToUpdate: TextView? = null): DateTime {
return date return date
} }
fun String.applyRegexFiltering() = replace(PHONE_NUMBER_PATTERN.toRegex(), "") fun String.normalizeNumber() = PhoneNumberUtils.normalizeNumber(this)

View File

@ -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.commons.helpers.PERMISSION_WRITE_CALL_LOG
import com.simplemobiletools.contacts.pro.activities.EditContactActivity import com.simplemobiletools.contacts.pro.activities.EditContactActivity
import com.simplemobiletools.contacts.pro.adapters.RecentCallsAdapter 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.contactClicked
import com.simplemobiletools.contacts.pro.extensions.normalizeNumber
import com.simplemobiletools.contacts.pro.helpers.IS_FROM_SIMPLE_CONTACTS import com.simplemobiletools.contacts.pro.helpers.IS_FROM_SIMPLE_CONTACTS
import com.simplemobiletools.contacts.pro.helpers.KEY_PHONE import com.simplemobiletools.contacts.pro.helpers.KEY_PHONE
import com.simplemobiletools.contacts.pro.helpers.RECENTS_TAB_MASK 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 val currAdapter = fragment_list.adapter
if (currAdapter == null) { if (currAdapter == null) {
RecentCallsAdapter(activity!!, recentCalls, activity, fragment_list, fragment_fastscroller) { 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 var selectedContact: Contact? = null
for (contact in allContacts) { for (contact in allContacts) {
if (contact.phoneNumbers.any { it.value.applyRegexFiltering() == recentCall }) { if (contact.phoneNumbers.any { it.normalizedNumber == recentCall }) {
selectedContact = contact selectedContact = contact
break break
} }

View File

@ -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 SMT_PRIVATE = "smt_private" // used at the contact source of local contacts hidden from other apps
const val IS_PRIVATE = "is_private" const val IS_PRIVATE = "is_private"
const val GROUP = "group" const val GROUP = "group"
const val PHONE_NUMBER_PATTERN = "[^0-9#*+]"
const val IS_FROM_SIMPLE_CONTACTS = "is_from_simple_contacts" const val IS_FROM_SIMPLE_CONTACTS = "is_from_simple_contacts"
const val ADD_NEW_CONTACT_NUMBER = "add_new_contact_number" const val ADD_NEW_CONTACT_NUMBER = "add_new_contact_number"
const val FIRST_CONTACT_ID = 1000000 const val FIRST_CONTACT_ID = 1000000

View File

@ -96,8 +96,8 @@ class ContactsHelper(val activity: Activity) {
Thread { Thread {
val uri = CommonDataKinds.Phone.CONTENT_URI val uri = CommonDataKinds.Phone.CONTENT_URI
val projection = arrayOf(ContactsContract.Data.RAW_CONTACT_ID) val projection = arrayOf(ContactsContract.Data.RAW_CONTACT_ID)
val selection = "${CommonDataKinds.Phone.NUMBER} = ?" val selection = "${CommonDataKinds.Phone.NORMALIZED_NUMBER} = ?"
val selectionArgs = arrayOf(number) val selectionArgs = arrayOf(number.normalizeNumber())
var cursor: Cursor? = null var cursor: Cursor? = null
try { try {
@ -180,10 +180,9 @@ class ContactsHelper(val activity: Activity) {
val groups = ArrayList<Group>() val groups = ArrayList<Group>()
val organization = Organization("", "") val organization = Organization("", "")
val websites = ArrayList<String>() val websites = ArrayList<String>()
val cleanNumbers = ArrayList<PhoneNumber>()
val ims = ArrayList<IM>() val ims = ArrayList<IM>()
val contact = Contact(id, prefix, firstName, middleName, surname, suffix, nickname, photoUri, numbers, emails, addresses, 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) contacts.put(id, contact)
} while (cursor.moveToNext()) } while (cursor.moveToNext())
@ -194,7 +193,6 @@ class ContactsHelper(val activity: Activity) {
cursor?.close() cursor?.close()
} }
val filterDuplicates = activity.config.filterDuplicates
val phoneNumbers = getPhoneNumbers(null) val phoneNumbers = getPhoneNumbers(null)
var size = phoneNumbers.size() var size = phoneNumbers.size()
for (i in 0 until size) { for (i in 0 until size) {
@ -202,13 +200,6 @@ class ContactsHelper(val activity: Activity) {
if (contacts[key] != null) { if (contacts[key] != null) {
val numbers = phoneNumbers.valueAt(i) val numbers = phoneNumbers.valueAt(i)
contacts[key].phoneNumbers = numbers 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( val projection = arrayOf(
ContactsContract.Data.RAW_CONTACT_ID, ContactsContract.Data.RAW_CONTACT_ID,
CommonDataKinds.Phone.NUMBER, CommonDataKinds.Phone.NUMBER,
CommonDataKinds.Phone.NORMALIZED_NUMBER,
CommonDataKinds.Phone.TYPE, CommonDataKinds.Phone.TYPE,
CommonDataKinds.Phone.LABEL CommonDataKinds.Phone.LABEL
) )
@ -289,6 +281,7 @@ class ContactsHelper(val activity: Activity) {
do { do {
val id = cursor.getIntValue(ContactsContract.Data.RAW_CONTACT_ID) val id = cursor.getIntValue(ContactsContract.Data.RAW_CONTACT_ID)
val number = cursor.getStringValue(CommonDataKinds.Phone.NUMBER) ?: continue val number = cursor.getStringValue(CommonDataKinds.Phone.NUMBER) ?: continue
val normalizedNumber = cursor.getStringValue(CommonDataKinds.Phone.NORMALIZED_NUMBER) ?: ""
val type = cursor.getIntValue(CommonDataKinds.Phone.TYPE) val type = cursor.getIntValue(CommonDataKinds.Phone.TYPE)
val label = cursor.getStringValue(CommonDataKinds.Phone.LABEL) ?: "" val label = cursor.getStringValue(CommonDataKinds.Phone.LABEL) ?: ""
@ -296,7 +289,7 @@ class ContactsHelper(val activity: Activity) {
phoneNumbers.put(id, ArrayList()) phoneNumbers.put(id, ArrayList())
} }
val phoneNumber = PhoneNumber(number, type, label) val phoneNumber = PhoneNumber(number, type, label, normalizedNumber)
phoneNumbers[id].add(phoneNumber) phoneNumbers[id].add(phoneNumber)
} while (cursor.moveToNext()) } while (cursor.moveToNext())
} }
@ -837,10 +830,9 @@ class ContactsHelper(val activity: Activity) {
val thumbnailUri = cursor.getStringValue(CommonDataKinds.StructuredName.PHOTO_THUMBNAIL_URI) ?: "" val thumbnailUri = cursor.getStringValue(CommonDataKinds.StructuredName.PHOTO_THUMBNAIL_URI) ?: ""
val organization = getOrganizations(id)[id] ?: Organization("", "") val organization = getOrganizations(id)[id] ?: Organization("", "")
val websites = getWebsites(id)[id] ?: ArrayList() val websites = getWebsites(id)[id] ?: ArrayList()
val cleanNumbers = ArrayList<PhoneNumber>()
val ims = getIMs(id)[id] ?: ArrayList() val ims = getIMs(id)[id] ?: ArrayList()
return Contact(id, prefix, firstName, middleName, surname, suffix, nickname, photoUri, number, emails, addresses, events, 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 { } finally {
cursor?.close() cursor?.close()
@ -990,6 +982,7 @@ class ContactsHelper(val activity: Activity) {
withValue(ContactsContract.Data.RAW_CONTACT_ID, contact.id) withValue(ContactsContract.Data.RAW_CONTACT_ID, contact.id)
withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Phone.CONTENT_ITEM_TYPE) withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
withValue(CommonDataKinds.Phone.NUMBER, it.value) withValue(CommonDataKinds.Phone.NUMBER, it.value)
withValue(CommonDataKinds.Phone.NORMALIZED_NUMBER, it.normalizedNumber)
withValue(CommonDataKinds.Phone.TYPE, it.type) withValue(CommonDataKinds.Phone.TYPE, it.type)
withValue(CommonDataKinds.Phone.LABEL, it.label) withValue(CommonDataKinds.Phone.LABEL, it.label)
operations.add(build()) operations.add(build())
@ -1292,6 +1285,7 @@ class ContactsHelper(val activity: Activity) {
withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Phone.CONTENT_ITEM_TYPE) withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
withValue(CommonDataKinds.Phone.NUMBER, it.value) withValue(CommonDataKinds.Phone.NUMBER, it.value)
withValue(CommonDataKinds.Phone.NORMALIZED_NUMBER, it.normalizedNumber)
withValue(CommonDataKinds.Phone.TYPE, it.type) withValue(CommonDataKinds.Phone.TYPE, it.type)
withValue(CommonDataKinds.Phone.LABEL, it.label) withValue(CommonDataKinds.Phone.LABEL, it.label)
operations.add(build()) operations.add(build())

View File

@ -5,8 +5,14 @@ import android.graphics.Bitmap
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.net.Uri import android.net.Uri
import android.provider.MediaStore import android.provider.MediaStore
import com.simplemobiletools.contacts.pro.extensions.* import com.simplemobiletools.contacts.pro.extensions.contactsDB
import com.simplemobiletools.contacts.pro.models.* 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) { class LocalContactsHelper(val activity: Activity) {
fun getAllContacts() = activity.contactsDB.getContacts().map { convertLocalContactToContact(it) }.toMutableList() as ArrayList<Contact> fun getAllContacts() = activity.contactsDB.getContacts().map { convertLocalContactToContact(it) }.toMutableList() as ArrayList<Contact>
@ -81,12 +87,6 @@ class LocalContactsHelper(val activity: Activity) {
return null return null
} }
val filterDuplicates = activity.config.filterDuplicates
val filteredPhoneNumbers = ArrayList<PhoneNumber>()
if (filterDuplicates) {
localContact.phoneNumbers.mapTo(filteredPhoneNumbers) { PhoneNumber(it.value.applyRegexFiltering(), 0, "") }
}
val contactPhoto = if (localContact.photo == null) { val contactPhoto = if (localContact.photo == null) {
null null
} else { } else {
@ -121,7 +121,6 @@ class LocalContactsHelper(val activity: Activity) {
groups = storedGroups.filter { localContact.groups.contains(it.id) } as ArrayList<Group> groups = storedGroups.filter { localContact.groups.contains(it.id) } as ArrayList<Group>
organization = Organization(localContact.company, localContact.jobPosition) organization = Organization(localContact.company, localContact.jobPosition)
websites = localContact.websites websites = localContact.websites
cleanPhoneNumbers = filteredPhoneNumbers
IMs = localContact.IMs IMs = localContact.IMs
} }
} }

View File

@ -9,6 +9,7 @@ import com.simplemobiletools.contacts.pro.activities.SimpleActivity
import com.simplemobiletools.contacts.pro.extensions.getCachePhoto import com.simplemobiletools.contacts.pro.extensions.getCachePhoto
import com.simplemobiletools.contacts.pro.extensions.getCachePhotoUri import com.simplemobiletools.contacts.pro.extensions.getCachePhotoUri
import com.simplemobiletools.contacts.pro.extensions.groupsDB 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.helpers.VcfImporter.ImportResult.*
import com.simplemobiletools.contacts.pro.models.* import com.simplemobiletools.contacts.pro.models.*
import ezvcard.Ezvcard 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<Email>() val emails = ArrayList<Email>()
@ -112,7 +113,6 @@ class VcfImporter(val activity: SimpleActivity) {
val photoData = ezContact.photos.firstOrNull()?.data val photoData = ezContact.photos.firstOrNull()?.data
val photo = null val photo = null
val thumbnailUri = savePhoto(photoData) val thumbnailUri = savePhoto(photoData)
val cleanPhoneNumbers = ArrayList<PhoneNumber>()
val IMs = ArrayList<IM>() val IMs = ArrayList<IM>()
ezContact.impps.forEach { 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, 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 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()) { if (contact.getNameToDisplay().isEmpty() && contact.organization.isEmpty() && ezContact.formattedName.value.isNotEmpty()) {

View File

@ -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_FIRST_NAME
import com.simplemobiletools.commons.helpers.SORT_BY_MIDDLE_NAME import com.simplemobiletools.commons.helpers.SORT_BY_MIDDLE_NAME
import com.simplemobiletools.commons.helpers.SORT_DESCENDING 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, 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<PhoneNumber>, var emails: ArrayList<Email>, var addresses: ArrayList<Address>, var photoUri: String, var phoneNumbers: ArrayList<PhoneNumber>, var emails: ArrayList<Email>, var addresses: ArrayList<Address>,
var events: ArrayList<Event>, var source: String, var starred: Int, var contactId: Int, var thumbnailUri: String, var photo: Bitmap?, var notes: String, var events: ArrayList<Event>, var source: String, var starred: Int, var contactId: Int, var thumbnailUri: String, var photo: Bitmap?, var notes: String,
var groups: ArrayList<Group>, var organization: Organization, var websites: ArrayList<String>, var cleanPhoneNumbers: ArrayList<PhoneNumber>, var groups: ArrayList<Group>, var organization: Organization, var websites: ArrayList<String>, var IMs: ArrayList<IM>) :
var IMs: ArrayList<IM>) :
Comparable<Contact> { Comparable<Contact> {
companion object { companion object {
var sorting = 0 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() 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 { fun doesContainPhoneNumber(text: String): Boolean {
if (text.isNotEmpty()) { return if (text.isNotEmpty()) {
if (phoneNumbers.any { it.value.contains(text) } || cleanPhoneNumbers.any { it.value.contains(text) }) { phoneNumbers.any { it.value.contains(text) || it.normalizedNumber?.contains(text.normalizeNumber()) == true || it.value.normalizeNumber().contains(text.normalizeNumber()) }
return true } 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
}
} }

View File

@ -1,3 +1,3 @@
package com.simplemobiletools.contacts.pro.models 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?)