Skip to content

Commit

Permalink
Allow consumers to specify the account the contact will be saved into
Browse files Browse the repository at this point in the history
  • Loading branch information
alexstyl committed Feb 19, 2022
1 parent dea3078 commit b4984b2
Show file tree
Hide file tree
Showing 8 changed files with 178 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ internal abstract class ContactStoreTestBase {
contactBuilder: MutableContactBuilder.() -> Unit
): Contact {
store.execute {
insert(contactBuilder)
insert(null, contactBuilder)
}

val contactsBefore = store.fetchContacts(columnsToFetch = withColumns.toList()).first()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package com.alexstyl.contactstore

import android.net.Uri
import com.alexstyl.contactstore.ContactColumn.Events
import com.alexstyl.contactstore.ContactColumn.ImAddresses
import com.alexstyl.contactstore.ContactColumn.Mails
import com.alexstyl.contactstore.ContactColumn.Names
import com.alexstyl.contactstore.ContactColumn.Note
import com.alexstyl.contactstore.ContactColumn.Organization
import com.alexstyl.contactstore.ContactColumn.Phones
import com.alexstyl.contactstore.ContactColumn.PostalAddresses
import com.alexstyl.contactstore.ContactColumn.Relations
import com.alexstyl.contactstore.ContactColumn.SipAddresses
import com.alexstyl.contactstore.ContactColumn.WebAddresses
import com.alexstyl.contactstore.Label.DateBirthday
import com.alexstyl.contactstore.Label.LocationHome
import com.alexstyl.contactstore.Label.PhoneNumberMobile
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking
import org.junit.Test

@ExperimentalCoroutinesApi
internal class InsertContactToAccountTest : ContactStoreTestBase() {

@Test
fun insertingContactToAccountAddsAllItemsToTheSameAccount(): Unit = runBlocking {
val account = InternetAccount("[email protected]", "test.com")
store.execute {
insert(account) {
phone("555", PhoneNumberMobile)
mail("[email protected]", LocationHome)
event(dayOfMonth = 1, month = 1, year = 2021, DateBirthday)
postalAddress(
street = "Somestreet",
poBox = "12345",
neighborhood = "Hood",
city = "City",
region = "",
postCode = "",
country = "",
label = LocationHome
)
webAddress(Uri.parse("https://acme.corp"), Label.WebsiteHomePage)
imAddress(
address = "ImAddress",
protocol = "protocol",
label = LocationHome
)
relation(name = "Person", label = Label.PhoneNumberAssistant)
sipAddress(address = "123", label = LocationHome)
}
}

val actual = store.fetchContacts(columnsToFetch = allContactColumns()).first()
val expected = contact(
displayName = "555",
columns = allContactColumns(),
phones = listOf(
LabeledValue(PhoneNumber("555"), PhoneNumberMobile, null, account)
),
mails = listOf(
LabeledValue(MailAddress("[email protected]"), LocationHome, null, account)
),
events = listOf(
LabeledValue(EventDate(1, 1, 2021), DateBirthday, null, account)
),
postalAddresses = listOf(
LabeledValue(
PostalAddress(
street = "Somestreet",
poBox = "12345",
neighborhood = "Hood",
city = "City",
region = "",
postCode = "",
country = ""
),
LocationHome,
null,
account
)
),
webAddresses = listOf(
LabeledValue(
WebAddress(Uri.parse("https://acme.corp")),
Label.WebsiteHomePage,
null,
account
)
),
imAddresses = listOf(
LabeledValue(
ImAddress(raw = "ImAddress", protocol = "protocol"),
LocationHome,
null,
account
)
),
relations = listOf(
LabeledValue(Relation(name = "Person"), Label.PhoneNumberAssistant, null, account)
),
sipAddresses = listOf(
LabeledValue(SipAddress(raw = "123"), LocationHome, null, account)
),
)
assertOnlyContact(actual = actual, expected = expected)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import com.alexstyl.contactstore.ContactColumn.Relations
import com.alexstyl.contactstore.ContactColumn.SipAddresses
import com.alexstyl.contactstore.ContactColumn.WebAddresses
import com.alexstyl.contactstore.LabeledValue
import com.alexstyl.contactstore.allContactColumns
import com.alexstyl.contactstore.containsColumn
import org.hamcrest.Description
import org.hamcrest.Matcher
Expand Down Expand Up @@ -194,7 +195,7 @@ private class SamePropertiesMatcher(
mismatchDescription.appendText("relations were ${actual.relations}")
false
}
linkedAccountsAreDifferent(actual) -> {
customDataItemsAreDifferent(actual) -> {
mismatchDescription.appendText("customDataItems were ${actual.customDataItems}")
false
}
Expand All @@ -218,7 +219,7 @@ private class SamePropertiesMatcher(
return areLabeledValuesDifferentIgnoringId(actual.relations, expected.relations)
}

private fun linkedAccountsAreDifferent(actual: Contact): Boolean {
private fun customDataItemsAreDifferent(actual: Contact): Boolean {
if (expected.containsColumn(CustomDataItems).not()) {
return false
}
Expand Down Expand Up @@ -277,7 +278,7 @@ private class SamePropertiesMatcher(
}

private fun columns(contact: Contact): List<ContactColumn> {
return standardColumns()
return allContactColumns()
.filter { contact.containsColumn(it) }
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ internal class AndroidContactStore(
request.requests.map { operation ->
when (operation) {
is Update -> existingContactOperationsFactory.updateOperation(operation.contact)
is Insert -> newContactOperationsFactory.addContactsOperation(operation.contact)
is Insert -> newContactOperationsFactory.addContactsOperation(operation.account, operation.contact)
is Delete -> existingContactOperationsFactory.deleteContactOperation(operation.contactId)
is InsertGroup -> contactGroupOperations.addGroupOperation(operation.group)
is UpdateGroup -> contactGroupOperations.updateGroupOperation(operation.group)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.alexstyl.contactstore

public sealed class ContactOperation {
public data class Insert(val contact: MutableContact) : ContactOperation()
public data class Insert(
val account: InternetAccount?, val contact: MutableContact
) : ContactOperation()

public data class Update(val contact: MutableContact) : ContactOperation()
public data class Delete(val contactId: Long) : ContactOperation()
public data class InsertGroup(val group: MutableContactGroup) : ContactOperation()
Expand Down
75 changes: 43 additions & 32 deletions library/src/main/java/com/alexstyl/contactstore/ContactStoreDSL.kt
Original file line number Diff line number Diff line change
@@ -1,39 +1,50 @@
package com.alexstyl.contactstore

import android.accounts.Account

public fun SaveRequest.insert(builder: MutableContactBuilder.() -> Unit) {
public fun SaveRequest.insert(
intoAccount: Account,
builder: MutableContactBuilder.() -> Unit
): Unit = insert(InternetAccount(intoAccount.name, intoAccount.type), builder)

public fun SaveRequest.insert(
intoAccount: InternetAccount? = null,
builder: MutableContactBuilder.() -> Unit
) {
val values = MutableContactBuilder().apply(builder)
insert(MutableContact().apply {
isStarred = values.isStarred
imageData = values.imageData

prefix = values.prefix
firstName = values.firstName
middleName = values.middleName
lastName = values.lastName
suffix = values.suffix

fullNameStyle = values.fullNameStyle
phoneticFirstName = values.phoneticFirstName
phoneticLastName = values.phoneticLastName
phoneticMiddleName = values.phoneticMiddleName

nickname = values.nickname
note = values.note?.let { Note(it) }

jobTitle = values.jobTitle
organization = values.organization

phones.addAll(values.phones)
mails.addAll(values.mails)
events.addAll(values.events)
postalAddresses.addAll(values.postalAddresses)
webAddresses.addAll(values.webAddresses)
groups.addAll(values.groupMemberships)
sipAddresses.addAll(values.sipAddresses)
relations.addAll(values.relations)
imAddresses.addAll(values.imAddresses)
})
insert(
intoAccount = intoAccount,
mutableContact = MutableContact().apply {
isStarred = values.isStarred
imageData = values.imageData

prefix = values.prefix
firstName = values.firstName
middleName = values.middleName
lastName = values.lastName
suffix = values.suffix

fullNameStyle = values.fullNameStyle
phoneticFirstName = values.phoneticFirstName
phoneticLastName = values.phoneticLastName
phoneticMiddleName = values.phoneticMiddleName

nickname = values.nickname
note = values.note?.let { Note(it) }

jobTitle = values.jobTitle
organization = values.organization

phones.addAll(values.phones)
mails.addAll(values.mails)
events.addAll(values.events)
postalAddresses.addAll(values.postalAddresses)
webAddresses.addAll(values.webAddresses)
groups.addAll(values.groupMemberships)
sipAddresses.addAll(values.sipAddresses)
relations.addAll(values.relations)
imAddresses.addAll(values.imAddresses)
})
}

public fun SaveRequest.insertGroup(builder: MutableContactGroupBuilder.() -> Unit) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.alexstyl.contactstore

import android.provider.ContactsContract.CommonDataKinds.Email as EmailColumns
import android.provider.ContactsContract.CommonDataKinds.Event as EventColumns
import android.provider.ContactsContract.CommonDataKinds.GroupMembership as GroupColumns
import android.provider.ContactsContract.CommonDataKinds.Im as ImColumns
import android.provider.ContactsContract.CommonDataKinds.Note as NoteColumns
import android.provider.ContactsContract.CommonDataKinds.Organization as OrganizationColumns
Expand All @@ -12,7 +13,6 @@ import android.provider.ContactsContract.CommonDataKinds.SipAddress as SipColumn
import android.provider.ContactsContract.CommonDataKinds.StructuredName as NameColumns
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal as PostalColumns
import android.provider.ContactsContract.CommonDataKinds.Website as WebsiteColumns
import android.provider.ContactsContract.CommonDataKinds.GroupMembership as GroupColumns
import android.content.ContentProviderOperation
import android.content.ContentProviderOperation.newInsert
import android.content.res.Resources
Expand All @@ -26,10 +26,12 @@ import android.provider.ContactsContract.RawContacts
internal class NewContactOperationsFactory(
private val resources: Resources
) {
fun addContactsOperation(contact: MutableContact): List<ContentProviderOperation> {
fun addContactsOperation(
account: InternetAccount?, contact: MutableContact
): List<ContentProviderOperation> {
return mutableListOf<ContentProviderOperation?>().apply {
with(contact) {
add(insertLocalRawAccountOperation(contact))
add(insertNewRawAccountOperation(account, contact))
add(insertNamesOperation(contact))
imageData?.run { add(insertPhotoOperation(this)) }

Expand All @@ -54,8 +56,7 @@ internal class NewContactOperationsFactory(
}

private fun hasOrganizationDetails(contact: MutableContact): Boolean {
return (contact.organization.isNullOrBlank().not()
|| contact.jobTitle.isNullOrBlank().not())
return (contact.organization.isNotBlank() || contact.jobTitle.isNotBlank())
}

private fun insertOrganization(contact: Contact): ContentProviderOperation {
Expand Down Expand Up @@ -170,10 +171,12 @@ internal class NewContactOperationsFactory(
.build()
}

private fun insertLocalRawAccountOperation(contact: MutableContact): ContentProviderOperation {
private fun insertNewRawAccountOperation(
account: InternetAccount?, contact: MutableContact
): ContentProviderOperation {
return newInsert(RawContacts.CONTENT_URI)
.withValue(RawContacts.ACCOUNT_TYPE, null)
.withValue(RawContacts.ACCOUNT_NAME, null)
.withValue(RawContacts.ACCOUNT_TYPE, account?.type)
.withValue(RawContacts.ACCOUNT_NAME, account?.name)
.withValue(Data.STARRED, boolToString(contact.isStarred))
.build()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,11 @@ public class SaveRequest {
_requests.add(Update(mutableContact))
}

public fun insert(mutableContact: MutableContact) {
_requests.add(Insert(mutableContact))
/**
* Insert the contact into the specified [InternetAccount].
*/
public fun insert(mutableContact: MutableContact, intoAccount: InternetAccount? = null) {
_requests.add(Insert(intoAccount, mutableContact))
}

public fun insertGroup(mutableContactGroup: MutableContactGroup) {
Expand Down

0 comments on commit b4984b2

Please sign in to comment.