mirror of
https://github.com/etesync/android
synced 2025-01-22 21:51:04 +00:00
Addressbook import: implement group import when importing from account.
Partially fixes #54. Only the from account is currently implemented, but that should be sufficient for most people already.
This commit is contained in:
parent
c74f9bc23d
commit
0ae278aabd
@ -22,6 +22,7 @@ import at.bitfire.vcard4android.*
|
||||
import com.etesync.syncadapter.App
|
||||
import com.etesync.syncadapter.model.CollectionInfo
|
||||
import com.etesync.syncadapter.model.JournalEntity
|
||||
import java.io.FileNotFoundException
|
||||
import java.util.*
|
||||
import java.util.logging.Level
|
||||
|
||||
@ -179,7 +180,14 @@ class LocalAddressBook(
|
||||
accountManager.removeAccount(account, null, null)
|
||||
}
|
||||
|
||||
override fun findAll(): List<LocalContact> = queryContacts(RawContacts.DELETED + "== 0", null)
|
||||
override fun findAll(): List<LocalAddress> =
|
||||
if (includeGroups)
|
||||
findAllContacts() + findAllGroups()
|
||||
else
|
||||
findAllContacts()
|
||||
|
||||
fun findAllContacts() = queryContacts("${RawContacts.DELETED}==0", null)
|
||||
fun findAllGroups() = queryGroups("${Groups.DELETED}==0", null)
|
||||
|
||||
/**
|
||||
* Returns an array of local contacts/groups which have been deleted locally. (DELETED != 0).
|
||||
@ -259,6 +267,10 @@ class LocalAddressBook(
|
||||
}
|
||||
}
|
||||
|
||||
fun findGroupById(id: Long): LocalGroup =
|
||||
queryGroups("${Groups._ID}=?", arrayOf(id.toString())).firstOrNull()
|
||||
?: throw FileNotFoundException()
|
||||
|
||||
override fun count(): Long {
|
||||
try {
|
||||
val cursor = provider?.query(syncAdapterURI(RawContacts.CONTENT_URI), null, null, null, null)
|
||||
|
@ -47,16 +47,6 @@ class LocalGroup : AndroidGroup, LocalAddress {
|
||||
val batch = BatchOperation(addressBook.provider)
|
||||
while (cursor.moveToNext()) {
|
||||
val id = cursor.getLong(0)
|
||||
Constants.log.fine("Assigning members to group $id")
|
||||
|
||||
// required for workaround for Android 7 which sets DIRTY flag when only meta-data is changed
|
||||
val changeContactIDs = HashSet<Long>()
|
||||
|
||||
// delete all memberships and cached memberships for this group
|
||||
for (contact in addressBook.getByGroupMembership(id)) {
|
||||
contact.removeGroupMemberships(batch)
|
||||
changeContactIDs += contact.id!!
|
||||
}
|
||||
|
||||
// extract list of member UIDs
|
||||
val members = LinkedList<String>()
|
||||
@ -71,26 +61,13 @@ class LocalGroup : AndroidGroup, LocalAddress {
|
||||
}
|
||||
|
||||
// insert memberships
|
||||
for (uid in members) {
|
||||
val membersIds = members.map {uid ->
|
||||
Constants.log.fine("Assigning member: $uid")
|
||||
addressBook.findContactByUID(uid)?.let { member ->
|
||||
member.addToGroup(batch, id)
|
||||
changeContactIDs += member.id!!
|
||||
} ?: Constants.log.warning("Group member not found: $uid")
|
||||
(addressBook.findByUid(uid) as LocalContact).id!!
|
||||
}
|
||||
|
||||
if (LocalContact.HASH_HACK)
|
||||
// workaround for Android 7 which sets DIRTY flag when only meta-data is changed
|
||||
changeContactIDs
|
||||
.map { addressBook.findContactByID(it) }
|
||||
.forEach { it.updateHashCode(batch) }
|
||||
|
||||
// remove pending memberships
|
||||
batch.enqueue(BatchOperation.Operation(
|
||||
ContentProviderOperation.newUpdate(addressBook.syncAdapterURI(ContentUris.withAppendedId(Groups.CONTENT_URI, id)))
|
||||
.withValue(COLUMN_PENDING_MEMBERS, null)
|
||||
.withYieldAllowed(true)
|
||||
))
|
||||
val group = addressBook.findGroupById(id)
|
||||
group.setMembers(batch, membersIds)
|
||||
|
||||
batch.commit()
|
||||
}
|
||||
@ -98,6 +75,8 @@ class LocalGroup : AndroidGroup, LocalAddress {
|
||||
}
|
||||
}
|
||||
|
||||
private var saveAsDirty = false // When true, the resource will be saved as dirty
|
||||
|
||||
override val uuid: String?
|
||||
get() = fileName
|
||||
|
||||
@ -133,6 +112,10 @@ class LocalGroup : AndroidGroup, LocalAddress {
|
||||
} finally {
|
||||
members.recycle()
|
||||
}
|
||||
|
||||
if (saveAsDirty) {
|
||||
values.put(Groups.DIRTY, true)
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
@ -187,6 +170,54 @@ class LocalGroup : AndroidGroup, LocalAddress {
|
||||
addressBook.provider!!.update(groupSyncUri(), values, null, null)
|
||||
}
|
||||
|
||||
private fun setMembers(batch: BatchOperation, members: List<Long>) {
|
||||
val id = id!!
|
||||
val addressBook = this.addressBook as LocalAddressBook
|
||||
Constants.log.fine("Assigning members to group $id")
|
||||
|
||||
// required for workaround for Android 7 which sets DIRTY flag when only meta-data is changed
|
||||
val changeContactIDs = HashSet<Long>()
|
||||
|
||||
// delete all memberships and cached memberships for this group
|
||||
for (contact in addressBook.getByGroupMembership(id)) {
|
||||
contact.removeGroupMemberships(batch)
|
||||
changeContactIDs += contact.id!!
|
||||
}
|
||||
|
||||
// insert memberships
|
||||
for (memberId in members) {
|
||||
Constants.log.fine("Assigning member: $memberId")
|
||||
addressBook.findContactByID(memberId).let { member ->
|
||||
member.addToGroup(batch, id)
|
||||
changeContactIDs += member.id!!
|
||||
} ?: Constants.log.warning("Group member not found: $memberId")
|
||||
}
|
||||
|
||||
if (LocalContact.HASH_HACK)
|
||||
// workaround for Android 7 which sets DIRTY flag when only meta-data is changed
|
||||
changeContactIDs
|
||||
.map { addressBook.findContactByID(it) }
|
||||
.forEach { it.updateHashCode(batch) }
|
||||
|
||||
// remove pending memberships
|
||||
batch.enqueue(BatchOperation.Operation(
|
||||
ContentProviderOperation.newUpdate(addressBook.syncAdapterURI(ContentUris.withAppendedId(Groups.CONTENT_URI, id)))
|
||||
.withValue(COLUMN_PENDING_MEMBERS, null)
|
||||
.withYieldAllowed(true)
|
||||
))
|
||||
}
|
||||
|
||||
fun createAsDirty(members: List<Long>): Uri {
|
||||
saveAsDirty = true
|
||||
|
||||
val ret = this.add()
|
||||
|
||||
val batch = BatchOperation(addressBook.provider!!)
|
||||
setMembers(batch, members)
|
||||
batch.commit()
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// helpers
|
||||
|
||||
|
@ -26,7 +26,7 @@ class ImportActivity : BaseActivity(), SelectImportMethod, ResultFragment.OnImpo
|
||||
|
||||
title = getString(R.string.import_dialog_title)
|
||||
|
||||
account = intent.extras!!.getParcelable(EXTRA_ACCOUNT)
|
||||
account = intent.extras!!.getParcelable(EXTRA_ACCOUNT)!!
|
||||
info = intent.extras!!.getSerializable(EXTRA_COLLECTION_INFO) as CollectionInfo
|
||||
|
||||
if (savedInstanceState == null)
|
||||
|
@ -21,13 +21,16 @@ import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import at.bitfire.vcard4android.ContactsStorageException
|
||||
import com.etesync.syncadapter.App
|
||||
import com.etesync.syncadapter.Constants.KEY_ACCOUNT
|
||||
import com.etesync.syncadapter.Constants.KEY_COLLECTION_INFO
|
||||
import com.etesync.syncadapter.R
|
||||
import com.etesync.syncadapter.model.CollectionInfo
|
||||
import com.etesync.syncadapter.resource.LocalAddressBook
|
||||
import com.etesync.syncadapter.resource.LocalContact
|
||||
import com.etesync.syncadapter.resource.LocalGroup
|
||||
import java.util.*
|
||||
import kotlin.collections.HashMap
|
||||
|
||||
class LocalContactImportFragment : Fragment() {
|
||||
|
||||
@ -132,9 +135,11 @@ class LocalContactImportFragment : Fragment() {
|
||||
try {
|
||||
val addressBook = LocalAddressBook.findByUid(context!!,
|
||||
context!!.contentResolver.acquireContentProviderClient(ContactsContract.RawContacts.CONTENT_URI)!!,
|
||||
account, info.uid!!)
|
||||
val localContacts = localAddressBook.findAll()
|
||||
val total = localContacts.size
|
||||
account, info.uid!!)!!
|
||||
val localContacts = localAddressBook.findAllContacts()
|
||||
val localGroups = localAddressBook.findAllGroups()
|
||||
val oldIdToNewId = HashMap<Long, Long>()
|
||||
val total = localContacts.size + localGroups.size
|
||||
progressDialog!!.max = total
|
||||
result.total = total.toLong()
|
||||
var progress = 0
|
||||
@ -142,8 +147,27 @@ class LocalContactImportFragment : Fragment() {
|
||||
val contact = currentLocalContact.contact
|
||||
|
||||
try {
|
||||
val localContact = LocalContact(addressBook!!, contact!!, null, null)
|
||||
val localContact = LocalContact(addressBook, contact!!, null, null)
|
||||
localContact.createAsDirty()
|
||||
oldIdToNewId[currentLocalContact.id!!] = localContact.id!!
|
||||
result.added++
|
||||
} catch (e: ContactsStorageException) {
|
||||
e.printStackTrace()
|
||||
result.e = e
|
||||
}
|
||||
|
||||
publishProgress(++progress)
|
||||
}
|
||||
for (currentLocalGroup in localGroups) {
|
||||
val group = currentLocalGroup.contact
|
||||
|
||||
try {
|
||||
val localGroup = LocalGroup(addressBook, group!!, null, null)
|
||||
val members = currentLocalGroup.getMembers().map { it ->
|
||||
oldIdToNewId[it]!!
|
||||
}
|
||||
|
||||
localGroup.createAsDirty(members)
|
||||
result.added++
|
||||
} catch (e: ContactsStorageException) {
|
||||
e.printStackTrace()
|
||||
|
Loading…
Reference in New Issue
Block a user