From 6b216580a2329d3ac548a362c402183e90bf1be9 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Tue, 2 Apr 2024 15:32:07 +0200 Subject: [PATCH] refactor: simplify contacts logic and remove duplicated code --- .../bnyro/contacts/enums/ContactAttributes.kt | 164 ++++++++++++ .../contacts/repo/DeviceContactsRepository.kt | 246 ++++-------------- .../contacts/ui/components/ContactEditor.kt | 1 + .../contacts/ui/components/ShareDialog.kt | 85 +++--- .../contacts/ui/components/ShareOption.kt | 6 +- .../ui/screens/SingleContactScreen.kt | 3 +- .../com/bnyro/contacts/util/ContactsHelper.kt | 14 + .../com/bnyro/contacts/util/IntentHelper.kt | 33 ++- 8 files changed, 293 insertions(+), 259 deletions(-) create mode 100644 app/src/main/java/com/bnyro/contacts/enums/ContactAttributes.kt diff --git a/app/src/main/java/com/bnyro/contacts/enums/ContactAttributes.kt b/app/src/main/java/com/bnyro/contacts/enums/ContactAttributes.kt new file mode 100644 index 00000000..6e3322dc --- /dev/null +++ b/app/src/main/java/com/bnyro/contacts/enums/ContactAttributes.kt @@ -0,0 +1,164 @@ +package com.bnyro.contacts.enums + +import android.provider.ContactsContract +import android.provider.ContactsContract.Intents +import com.bnyro.contacts.R +import com.bnyro.contacts.obj.ContactData +import com.bnyro.contacts.obj.TranslatedType +import com.bnyro.contacts.obj.ValueWithType +import com.bnyro.contacts.util.ContactsHelper + +abstract class ContactAttribute(){ + abstract val stringRes: Int + abstract val androidValueColumn: String + abstract val androidContentType: String + abstract fun set(contact: ContactData, value: T) + abstract fun get(contact: ContactData): T +} + +abstract class StringAttribute : ContactAttribute() { + abstract val insertKey: String? +} + +abstract class ListAttribute: ContactAttribute>() { + abstract val androidTypeColumn: String + abstract val types: List + abstract val insertKeys: List> +} + +class Organization : StringAttribute() { + override val stringRes: Int = R.string.organization + override val insertKey: String = Intents.Insert.COMPANY + override val androidValueColumn: String = ContactsContract.CommonDataKinds.Organization.COMPANY + override val androidContentType: String = ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE + + override fun set(contact: ContactData, value: String?) { + contact.organization = value + } + + override fun get(contact: ContactData) = contact.organization +} + +class Title : StringAttribute() { + override val stringRes: Int = R.string.title + override val insertKey: String = Intents.Insert.JOB_TITLE + override val androidValueColumn: String = ContactsContract.CommonDataKinds.Organization.TITLE + override val androidContentType: String = ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE + + override fun set(contact: ContactData, value: String?) { + contact.organization = value + } + + override fun get(contact: ContactData) = contact.organization +} + +class Nickname : StringAttribute() { + override val stringRes: Int = R.string.nick_name + override val insertKey: String? = null + override val androidValueColumn: String = ContactsContract.CommonDataKinds.Nickname.NAME + override val androidContentType: String = ContactsContract.CommonDataKinds.Nickname.CONTENT_ITEM_TYPE + + override fun set(contact: ContactData, value: String?) { + contact.nickName = value + } + + override fun get(contact: ContactData) = contact.nickName +} + +class Events : ListAttribute() { + override val stringRes: Int = R.string.event + override val insertKeys: List> = emptyList() + override val androidValueColumn: String = ContactsContract.CommonDataKinds.Event.START_DATE + override val androidTypeColumn: String = ContactsContract.CommonDataKinds.Event.TYPE + override val androidContentType: String = ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE + override fun set(contact: ContactData, value: List) { + contact.events = value + } + + override fun get(contact: ContactData) = contact.events + + override val types: List = ContactsHelper.eventTypes +} + +class Numbers : ListAttribute() { + override val stringRes: Int = R.string.phone_number + override val insertKeys: List> = listOf( + Intents.Insert.PHONE to Intents.Insert.PHONE_TYPE, + Intents.Insert.SECONDARY_PHONE to Intents.Insert.SECONDARY_PHONE, + Intents.Insert.TERTIARY_EMAIL to Intents.Insert.TERTIARY_EMAIL_TYPE + ) + override val androidValueColumn: String = ContactsContract.CommonDataKinds.Phone.NUMBER + override val androidTypeColumn: String = ContactsContract.CommonDataKinds.Phone.TYPE + override val androidContentType: String = ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE + override fun set(contact: ContactData, value: List) { + contact.numbers = value + } + + override fun get(contact: ContactData) = contact.numbers + + override val types: List = ContactsHelper.phoneNumberTypes +} + +class Emails : ListAttribute() { + override val stringRes: Int = R.string.email + override val insertKeys: List> = listOf( + Intents.Insert.EMAIL to Intents.Insert.EMAIL_TYPE, + Intents.Insert.SECONDARY_EMAIL to Intents.Insert.SECONDARY_EMAIL_TYPE, + Intents.Insert.TERTIARY_EMAIL to Intents.Insert.TERTIARY_EMAIL_TYPE + ) + override val androidValueColumn: String = ContactsContract.CommonDataKinds.Email.ADDRESS + override val androidTypeColumn: String = ContactsContract.CommonDataKinds.Email.TYPE + override val androidContentType: String = ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE + override fun set(contact: ContactData, value: List) { + contact.emails = value + } + + override fun get(contact: ContactData) = contact.emails + + override val types: List = ContactsHelper.emailTypes +} + +class Addresses : ListAttribute() { + override val stringRes: Int = R.string.address + override val insertKeys: List> = listOf(Intents.Insert.POSTAL to null) + override val androidValueColumn: String = ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS + override val androidTypeColumn: String = ContactsContract.CommonDataKinds.StructuredPostal.TYPE + override val androidContentType: String = ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE + override fun set(contact: ContactData, value: List) { + contact.addresses = value + } + + override fun get(contact: ContactData) = contact.addresses + + override val types: List = ContactsHelper.addressTypes +} + +class Notes : ListAttribute() { + override val stringRes: Int = R.string.note + override val insertKeys: List> = listOf(Intents.Insert.NOTES to null) + override val androidValueColumn: String = ContactsContract.CommonDataKinds.Note.NOTE + override val androidTypeColumn: String = ContactsContract.CommonDataKinds.Note.DATA2 + override val androidContentType: String = ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE + override fun set(contact: ContactData, value: List) { + contact.notes = value + } + + override fun get(contact: ContactData) = contact.notes + + override val types: List = emptyList() +} + +class Websites : ListAttribute() { + override val stringRes: Int = R.string.website + override val insertKeys: List> = emptyList() + override val androidValueColumn: String = ContactsContract.CommonDataKinds.Website.URL + override val androidTypeColumn: String = ContactsContract.CommonDataKinds.Website.TYPE + override val androidContentType: String = ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE + override fun set(contact: ContactData, value: List) { + contact.websites = value + } + + override fun get(contact: ContactData) = contact.websites + + override val types: List = ContactsHelper.websiteTypes +} diff --git a/app/src/main/java/com/bnyro/contacts/repo/DeviceContactsRepository.kt b/app/src/main/java/com/bnyro/contacts/repo/DeviceContactsRepository.kt index cccdad20..123b288f 100644 --- a/app/src/main/java/com/bnyro/contacts/repo/DeviceContactsRepository.kt +++ b/app/src/main/java/com/bnyro/contacts/repo/DeviceContactsRepository.kt @@ -13,23 +13,20 @@ import android.net.Uri import android.provider.ContactsContract import android.provider.ContactsContract.AUTHORITY import android.provider.ContactsContract.CALLER_IS_SYNCADAPTER -import android.provider.ContactsContract.CommonDataKinds.Email -import android.provider.ContactsContract.CommonDataKinds.Event import android.provider.ContactsContract.CommonDataKinds.GroupMembership import android.provider.ContactsContract.CommonDataKinds.Nickname -import android.provider.ContactsContract.CommonDataKinds.Note import android.provider.ContactsContract.CommonDataKinds.Organization import android.provider.ContactsContract.CommonDataKinds.Phone import android.provider.ContactsContract.CommonDataKinds.Photo import android.provider.ContactsContract.CommonDataKinds.StructuredName -import android.provider.ContactsContract.CommonDataKinds.StructuredPostal -import android.provider.ContactsContract.CommonDataKinds.Website import android.provider.ContactsContract.Contacts import android.provider.ContactsContract.Data import android.provider.ContactsContract.RawContacts import androidx.annotation.RequiresPermission import com.bnyro.contacts.R import com.bnyro.contacts.enums.BackupType +import com.bnyro.contacts.enums.ListAttribute +import com.bnyro.contacts.enums.StringAttribute import com.bnyro.contacts.ext.intValue import com.bnyro.contacts.ext.longValue import com.bnyro.contacts.ext.notAName @@ -59,9 +56,6 @@ class DeviceContactsRepository(private val context: Context) : ContactsRepositor Contacts.DISPLAY_NAME_ALTERNATIVE, StructuredName.GIVEN_NAME, StructuredName.FAMILY_NAME, - Nickname.NAME, - Organization.TITLE, - Organization.COMPANY, RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_NAME ) @@ -131,45 +125,21 @@ class DeviceContactsRepository(private val context: Context) : ContactsRepositor thumbnail = getContactPhotoThumbnail(contactId) photo = getContactPhoto(contactId) ?: thumbnail groups = getGroups(contactId, storedContactGroups) - nickName = getEntry(contactId, Nickname.CONTENT_ITEM_TYPE, Nickname.NAME) - title = getEntry(contactId, Organization.CONTENT_ITEM_TYPE, Organization.TITLE) - organization = getEntry(contactId, Organization.CONTENT_ITEM_TYPE, Organization.COMPANY) - events = getExtras( - contactId, - Event.START_DATE, - Event.TYPE, - Event.CONTENT_ITEM_TYPE - ) - numbers = getExtras( - contactId, - Phone.NUMBER, - Phone.TYPE, - Phone.CONTENT_ITEM_TYPE - ) - emails = getExtras( - contactId, - Email.ADDRESS, - Email.TYPE, - Email.CONTENT_ITEM_TYPE - ) - addresses = getExtras( - contactId, - StructuredPostal.FORMATTED_ADDRESS, - StructuredPostal.TYPE, - StructuredPostal.CONTENT_ITEM_TYPE - ) - notes = getExtras( - contactId, - Note.NOTE, - Note.DATA2, - Note.CONTENT_ITEM_TYPE - ) - websites = getExtras( - contactId, - Website.URL, - Website.TYPE, - Website.CONTENT_ITEM_TYPE - ) + + ContactsHelper.contactAttributesTypes.forEach { attribute -> + if (attribute is StringAttribute) { + val dataStr = getEntry(contactId, attribute.androidContentType, attribute.androidValueColumn) + attribute.set(this, dataStr) + } else if (attribute is ListAttribute) { + val dataEntries = getExtras( + contactId, + attribute.androidValueColumn, + attribute.androidTypeColumn, + attribute.androidContentType + ) + attribute.set(this, dataEntries) + } + } } } @@ -339,89 +309,32 @@ class DeviceContactsRepository(private val context: Context) : ContactsRepositor StructuredName.FAMILY_NAME, contact.surName.orEmpty() ), - contact.nickName?.let { - getInsertAction( - Nickname.CONTENT_ITEM_TYPE, - Nickname.NAME, - it - ) - }, - contact.title?.let { - getInsertAction( - Organization.CONTENT_ITEM_TYPE, - Organization.TITLE, - it - ) - }, - contact.organization?.let { - getInsertAction( - Organization.CONTENT_ITEM_TYPE, - Organization.COMPANY, - it - ) - }, contact.photo?.let { getInsertAction(Photo.CONTENT_ITEM_TYPE, Photo.PHOTO, getBitmapBytes(it)) }, - *contact.websites.map { - getInsertAction( - Website.CONTENT_ITEM_TYPE, - Website.URL, - it.value, - Website.TYPE, - it.type - ) - }.toTypedArray(), - *contact.numbers.map { - getInsertAction( - Phone.CONTENT_ITEM_TYPE, - Phone.NUMBER, - it.value, - Phone.TYPE, - it.type - ) - }.toTypedArray(), - *contact.emails.map { - getInsertAction( - Email.CONTENT_ITEM_TYPE, - Email.ADDRESS, - it.value, - Email.TYPE, - it.type - ) - }.toTypedArray(), - *contact.addresses.map { - getInsertAction( - StructuredPostal.CONTENT_ITEM_TYPE, - StructuredPostal.FORMATTED_ADDRESS, - it.value, - StructuredPostal.TYPE, - it.type - ) - }.toTypedArray(), - *contact.events.map { - getInsertAction( - Event.CONTENT_ITEM_TYPE, - Event.START_DATE, - it.value, - Event.TYPE, - it.type - ) - }.toTypedArray(), - *contact.notes.map { - getInsertAction( - Note.CONTENT_ITEM_TYPE, - Note.NOTE, - it.value - ) - }.toTypedArray(), *contact.groups.map { getInsertAction( GroupMembership.CONTENT_ITEM_TYPE, GroupMembership.GROUP_ROW_ID, it.rowId.toString() ) - }.toTypedArray() + }.toTypedArray(), + *ContactsHelper.contactAttributesTypes.filterIsInstance().map { attribute -> + attribute.get(contact)?.let { + getInsertAction(attribute.androidContentType, attribute.androidValueColumn, it) + } + }.toTypedArray(), + *ContactsHelper.contactAttributesTypes.filterIsInstance().map { attribute -> + attribute.get(contact).map { + getInsertAction( + attribute.androidContentType, + attribute.androidValueColumn, + it.value, + attribute.androidTypeColumn, + it.type + ) + } + }.flatten().toTypedArray() ).let { ArrayList(it) } contentResolver.applyBatch(AUTHORITY, ops) @@ -444,85 +357,20 @@ class DeviceContactsRepository(private val context: Context) : ContactsRepositor operations.add(build()) } - operations.addAll( - getUpdateSingleAction( - rawContactId, - Nickname.CONTENT_ITEM_TYPE, - Nickname.NAME, - contact.nickName - ) - ) - operations.addAll( - getUpdateSingleAction( - rawContactId, - Organization.CONTENT_ITEM_TYPE, - Organization.TITLE, - contact.title - ) - ) - operations.addAll( - getUpdateSingleAction( - rawContactId, - Organization.CONTENT_ITEM_TYPE, - Organization.COMPANY, - contact.organization - ) - ) + for (attribute in ContactsHelper.contactAttributesTypes) { + if (attribute is StringAttribute) { + operations.addAll(getUpdateSingleAction( + rawContactId, attribute.androidContentType, + attribute.androidValueColumn, attribute.get(contact) + )) + } else if (attribute is ListAttribute) { + operations.addAll(getUpdateMultipleAction( + rawContactId, attribute.androidContentType, attribute.get(contact), + attribute.androidValueColumn, attribute.androidTypeColumn + )) + } + } - operations.addAll( - getUpdateMultipleAction( - rawContactId, - Website.CONTENT_ITEM_TYPE, - contact.websites, - Website.URL, - Website.TYPE - ) - ) - operations.addAll( - getUpdateMultipleAction( - rawContactId, - Phone.CONTENT_ITEM_TYPE, - contact.numbers, - Phone.NUMBER, - Phone.TYPE - ) - ) - operations.addAll( - getUpdateMultipleAction( - rawContactId, - Email.CONTENT_ITEM_TYPE, - contact.emails, - Email.ADDRESS, - Email.TYPE - ) - ) - operations.addAll( - getUpdateMultipleAction( - rawContactId, - StructuredPostal.CONTENT_ITEM_TYPE, - contact.addresses, - StructuredPostal.FORMATTED_ADDRESS, - StructuredPostal.TYPE - ) - ) - operations.addAll( - getUpdateMultipleAction( - rawContactId, - Event.CONTENT_ITEM_TYPE, - contact.events, - Event.START_DATE, - Event.TYPE - ) - ) - operations.addAll( - getUpdateMultipleAction( - rawContactId, - Note.CONTENT_ITEM_TYPE, - contact.notes, - Note.NOTE, - null - ) - ) operations.addAll( getUpdateMultipleAction( rawContactId, diff --git a/app/src/main/java/com/bnyro/contacts/ui/components/ContactEditor.kt b/app/src/main/java/com/bnyro/contacts/ui/components/ContactEditor.kt index 79f512b6..7c3afaf8 100644 --- a/app/src/main/java/com/bnyro/contacts/ui/components/ContactEditor.kt +++ b/app/src/main/java/com/bnyro/contacts/ui/components/ContactEditor.kt @@ -359,6 +359,7 @@ fun ContactEditor( TextFieldGroup( items = websites, label = R.string.website, + types = ContactsHelper.websiteTypes, addActionText = R.string.add_website, keyboardType = KeyboardType.Uri, leadingIcon = Icons.Outlined.Web diff --git a/app/src/main/java/com/bnyro/contacts/ui/components/ShareDialog.kt b/app/src/main/java/com/bnyro/contacts/ui/components/ShareDialog.kt index 9907bcf2..98c8073c 100644 --- a/app/src/main/java/com/bnyro/contacts/ui/components/ShareDialog.kt +++ b/app/src/main/java/com/bnyro/contacts/ui/components/ShareDialog.kt @@ -4,20 +4,23 @@ import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.layout.Row import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.material3.AlertDialog import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.snapshots.SnapshotStateList import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.lifecycle.viewmodel.compose.viewModel import com.bnyro.contacts.R +import com.bnyro.contacts.enums.ListAttribute +import com.bnyro.contacts.enums.StringAttribute import com.bnyro.contacts.obj.ContactData import com.bnyro.contacts.ui.components.dialogs.DialogButton import com.bnyro.contacts.ui.models.ContactsModel import com.bnyro.contacts.util.BackupHelper +import com.bnyro.contacts.util.ContactsHelper @Composable fun ShareDialog( @@ -27,48 +30,46 @@ fun ShareDialog( val contactsModel: ContactsModel = viewModel(factory = ContactsModel.Factory) val context = LocalContext.current - val shareName = remember { mutableStateOf(true) } - val sharePhoto = remember { mutableStateOf(true) } - val shareNickName = remember { mutableStateOf(true) } - val shareTitle = remember { mutableStateOf(true) } - val shareOrganization = remember { mutableStateOf(true) } - val shareWebsite = remember { mutableStateOf(true) } - val sharePhone = remember { mutableStateOf(true) } - val shareEmail = remember { mutableStateOf(true) } - val shareAddress = remember { mutableStateOf(true) } - val shareNote = remember { mutableStateOf(true) } + val baseOptions = remember { + listOf(R.string.name, R.string.photo) + } - val options = listOf( - R.string.name to shareName, - R.string.photo to sharePhoto, - R.string.title to shareTitle, - R.string.nick_name to shareNickName, - R.string.organization to shareOrganization, - R.string.website to shareWebsite, - R.string.phone to sharePhone, - R.string.email to shareEmail, - R.string.address to shareAddress, - R.string.note to shareNote - ) + val options = remember { + baseOptions + ContactsHelper.contactAttributesTypes.map { it.stringRes } + } + + val selected = remember { + SnapshotStateList().apply { + for (i in options.indices) add(true) + } + } fun getContactData(): ContactData { - return contact.copy().apply { - if (!shareName.value) { - displayName = null - alternativeName = null - firstName = null - surName = null + val data = ContactData() + + if (selected[0]) { + data.displayName = contact.displayName + data.alternativeName = contact.alternativeName + data.firstName = contact.firstName + data.surName = contact.surName + } + if (selected[1]) { + data.photo = contact.photo + } + + ContactsHelper.contactAttributesTypes.forEachIndexed { index, contactAttribute -> + if (selected[index + baseOptions.size]) { + if (contactAttribute is StringAttribute) { + val value = contactAttribute.get(contact) + contactAttribute.set(data, value) + } else if (contactAttribute is ListAttribute) { + val value = contactAttribute.get(contact) + contactAttribute.set(data, value) + } } - if (!sharePhoto.value) photo = null - if (!shareNickName.value) nickName = null - if (!shareTitle.value) title = null - if (!shareOrganization.value) organization = null - if (!shareAddress.value) addresses = emptyList() - if (!shareEmail.value) emails = emptyList() - if (!shareNote.value) notes = emptyList() - if (!sharePhone.value) numbers = emptyList() - if (!shareWebsite.value) websites = emptyList() } + + return data } val openFilePicker = rememberLauncherForActivityResult( @@ -86,8 +87,10 @@ fun ShareDialog( title = { Text(stringResource(R.string.share)) }, text = { LazyColumn { - items(options) { - ShareOption(title = it.first, isChecked = it.second) + itemsIndexed(options) { index, it -> + ShareOption(title = it, isChecked = selected[index]) { + selected[index] = it + } } } }, diff --git a/app/src/main/java/com/bnyro/contacts/ui/components/ShareOption.kt b/app/src/main/java/com/bnyro/contacts/ui/components/ShareOption.kt index 2be4edcb..5524d4ec 100644 --- a/app/src/main/java/com/bnyro/contacts/ui/components/ShareOption.kt +++ b/app/src/main/java/com/bnyro/contacts/ui/components/ShareOption.kt @@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.width import androidx.compose.material3.Checkbox import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource @@ -17,13 +16,14 @@ import androidx.compose.ui.unit.dp @Composable fun ShareOption( @StringRes title: Int, - isChecked: MutableState + isChecked: Boolean, + onCheckedChange: (Boolean) -> Unit ) { Row( modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically ) { - Checkbox(checked = isChecked.value, onCheckedChange = { isChecked.value = it }) + Checkbox(checked = isChecked, onCheckedChange = onCheckedChange) Spacer(modifier = Modifier.width(10.dp)) Text(text = stringResource(title)) } diff --git a/app/src/main/java/com/bnyro/contacts/ui/screens/SingleContactScreen.kt b/app/src/main/java/com/bnyro/contacts/ui/screens/SingleContactScreen.kt index a5e2aede..6caa4960 100644 --- a/app/src/main/java/com/bnyro/contacts/ui/screens/SingleContactScreen.kt +++ b/app/src/main/java/com/bnyro/contacts/ui/screens/SingleContactScreen.kt @@ -6,7 +6,6 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize @@ -66,7 +65,7 @@ import com.bnyro.contacts.util.CalendarUtils import com.bnyro.contacts.util.ContactsHelper import com.bnyro.contacts.util.IntentHelper -@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class) +@OptIn(ExperimentalMaterial3Api::class) @Composable fun SingleContactScreen(contact: ContactData, onClose: () -> Unit) { val viewModel: ContactsModel = viewModel() diff --git a/app/src/main/java/com/bnyro/contacts/util/ContactsHelper.kt b/app/src/main/java/com/bnyro/contacts/util/ContactsHelper.kt index 6f0e6573..d177728f 100644 --- a/app/src/main/java/com/bnyro/contacts/util/ContactsHelper.kt +++ b/app/src/main/java/com/bnyro/contacts/util/ContactsHelper.kt @@ -2,6 +2,15 @@ package com.bnyro.contacts.util import android.provider.ContactsContract import com.bnyro.contacts.R +import com.bnyro.contacts.enums.Addresses +import com.bnyro.contacts.enums.Emails +import com.bnyro.contacts.enums.Events +import com.bnyro.contacts.enums.Nickname +import com.bnyro.contacts.enums.Notes +import com.bnyro.contacts.enums.Numbers +import com.bnyro.contacts.enums.Organization +import com.bnyro.contacts.enums.Title +import com.bnyro.contacts.enums.Websites import com.bnyro.contacts.obj.ContactData import com.bnyro.contacts.obj.TranslatedType import com.google.i18n.phonenumbers.PhoneNumberUtil @@ -77,6 +86,11 @@ object ContactsHelper { TranslatedType(ContactsContract.CommonDataKinds.Website.TYPE_OTHER, R.string.other) ) + val contactAttributesTypes = listOf( + Nickname(), Title(), Organization(), + Numbers(), Addresses(), Emails(), Events(), Websites(), Notes() + ) + fun splitFullName(displayName: String?): Pair { val displayNameParts = displayName.orEmpty().split(" ") return when { diff --git a/app/src/main/java/com/bnyro/contacts/util/IntentHelper.kt b/app/src/main/java/com/bnyro/contacts/util/IntentHelper.kt index 5106db99..cc9d9f82 100644 --- a/app/src/main/java/com/bnyro/contacts/util/IntentHelper.kt +++ b/app/src/main/java/com/bnyro/contacts/util/IntentHelper.kt @@ -8,6 +8,8 @@ import android.provider.ContactsContract import androidx.core.net.toUri import com.bnyro.contacts.R import com.bnyro.contacts.enums.IntentActionType +import com.bnyro.contacts.enums.ListAttribute +import com.bnyro.contacts.enums.StringAttribute import com.bnyro.contacts.obj.ContactData import com.bnyro.contacts.obj.TranslatedType import com.bnyro.contacts.obj.ValueWithType @@ -75,21 +77,24 @@ object IntentHelper { val name = intent.getStringExtra(ContactsContract.Intents.Insert.NAME) ?: intent.getStringExtra(ContactsContract.Intents.Insert.PHONETIC_NAME) - return ContactData( + val data = ContactData( displayName = name, firstName = name?.split(" ")?.firstOrNull(), surName = name?.split(" ", limit = 2)?.lastOrNull(), - organization = intent.getStringExtra(ContactsContract.Intents.Insert.COMPANY), - title = intent.getStringExtra(ContactsContract.Intents.Insert.JOB_TITLE), - numbers = extractIntentValue(intent, ContactsContract.Intents.Insert.PHONE, ContactsContract.Intents.Insert.PHONE_TYPE) + - extractIntentValue(intent, ContactsContract.Intents.Insert.SECONDARY_PHONE, ContactsContract.Intents.Insert.SECONDARY_PHONE_TYPE) + - extractIntentValue(intent, ContactsContract.Intents.Insert.TERTIARY_PHONE, ContactsContract.Intents.Insert.TERTIARY_PHONE_TYPE), - emails = extractIntentValue(intent, ContactsContract.Intents.Insert.EMAIL, ContactsContract.Intents.Insert.EMAIL_TYPE) + - extractIntentValue(intent, ContactsContract.Intents.Insert.SECONDARY_EMAIL, ContactsContract.Intents.Insert.SECONDARY_EMAIL_TYPE) + - extractIntentValue(intent, ContactsContract.Intents.Insert.TERTIARY_EMAIL, ContactsContract.Intents.Insert.TERTIARY_EMAIL_TYPE), - notes = extractIntentValue(intent, ContactsContract.Intents.Insert.NOTES), - addresses = extractIntentValue(intent, ContactsContract.Intents.Insert.POSTAL) ) + + ContactsHelper.contactAttributesTypes.forEach { attribute -> + if (attribute is StringAttribute) { + attribute.set(data, intent.getStringExtra(attribute.insertKey)) + } else if (attribute is ListAttribute) { + val values = attribute.insertKeys.mapNotNull { insertKey -> + extractIntentValue(intent, insertKey.first, insertKey.second) + } + attribute.set(data, values) + } + } + + return data } private fun extractIntentValue( @@ -97,8 +102,8 @@ object IntentHelper { key: String, typeKey: String? = null, types: List = emptyList() - ): List { - val entry = intent.getStringExtra(key) ?: return emptyList() + ): ValueWithType? { + val entry = intent.getStringExtra(key) ?: return null val type = if (typeKey != null) { val typeIdentifier = intent.getStringExtra(typeKey) @@ -108,6 +113,6 @@ object IntentHelper { }?.id } else null - return listOf(ValueWithType(entry, type ?: 0)) + return ValueWithType(entry, type ?: 0) } }