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)
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

View File

@ -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) {

View File

@ -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)

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.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
}

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 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

View File

@ -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<Group>()
val organization = Organization("", "")
val websites = ArrayList<String>()
val cleanNumbers = ArrayList<PhoneNumber>()
val ims = ArrayList<IM>()
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<PhoneNumber>()
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())

View File

@ -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<Contact>
@ -81,12 +87,6 @@ class LocalContactsHelper(val activity: Activity) {
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) {
null
} else {
@ -121,7 +121,6 @@ class LocalContactsHelper(val activity: Activity) {
groups = storedGroups.filter { localContact.groups.contains(it.id) } as ArrayList<Group>
organization = Organization(localContact.company, localContact.jobPosition)
websites = localContact.websites
cleanPhoneNumbers = filteredPhoneNumbers
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.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<Email>()
@ -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<PhoneNumber>()
val IMs = ArrayList<IM>()
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()) {

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_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<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 groups: ArrayList<Group>, var organization: Organization, var websites: ArrayList<String>, var cleanPhoneNumbers: ArrayList<PhoneNumber>,
var IMs: ArrayList<IM>) :
var groups: ArrayList<Group>, var organization: Organization, var websites: ArrayList<String>, var IMs: ArrayList<IM>) :
Comparable<Contact> {
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
}
}

View File

@ -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?)