mirror of
https://github.com/etesync/android
synced 2025-07-07 07:12:36 +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.App
|
||||||
import com.etesync.syncadapter.model.CollectionInfo
|
import com.etesync.syncadapter.model.CollectionInfo
|
||||||
import com.etesync.syncadapter.model.JournalEntity
|
import com.etesync.syncadapter.model.JournalEntity
|
||||||
|
import java.io.FileNotFoundException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.logging.Level
|
import java.util.logging.Level
|
||||||
|
|
||||||
@ -179,7 +180,14 @@ class LocalAddressBook(
|
|||||||
accountManager.removeAccount(account, null, null)
|
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).
|
* 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 {
|
override fun count(): Long {
|
||||||
try {
|
try {
|
||||||
val cursor = provider?.query(syncAdapterURI(RawContacts.CONTENT_URI), null, null, null, null)
|
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)
|
val batch = BatchOperation(addressBook.provider)
|
||||||
while (cursor.moveToNext()) {
|
while (cursor.moveToNext()) {
|
||||||
val id = cursor.getLong(0)
|
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
|
// extract list of member UIDs
|
||||||
val members = LinkedList<String>()
|
val members = LinkedList<String>()
|
||||||
@ -71,26 +61,13 @@ class LocalGroup : AndroidGroup, LocalAddress {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// insert memberships
|
// insert memberships
|
||||||
for (uid in members) {
|
val membersIds = members.map {uid ->
|
||||||
Constants.log.fine("Assigning member: $uid")
|
Constants.log.fine("Assigning member: $uid")
|
||||||
addressBook.findContactByUID(uid)?.let { member ->
|
(addressBook.findByUid(uid) as LocalContact).id!!
|
||||||
member.addToGroup(batch, id)
|
|
||||||
changeContactIDs += member.id!!
|
|
||||||
} ?: Constants.log.warning("Group member not found: $uid")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LocalContact.HASH_HACK)
|
val group = addressBook.findGroupById(id)
|
||||||
// workaround for Android 7 which sets DIRTY flag when only meta-data is changed
|
group.setMembers(batch, membersIds)
|
||||||
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)
|
|
||||||
))
|
|
||||||
|
|
||||||
batch.commit()
|
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?
|
override val uuid: String?
|
||||||
get() = fileName
|
get() = fileName
|
||||||
|
|
||||||
@ -133,6 +112,10 @@ class LocalGroup : AndroidGroup, LocalAddress {
|
|||||||
} finally {
|
} finally {
|
||||||
members.recycle()
|
members.recycle()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (saveAsDirty) {
|
||||||
|
values.put(Groups.DIRTY, true)
|
||||||
|
}
|
||||||
return values
|
return values
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,6 +170,54 @@ class LocalGroup : AndroidGroup, LocalAddress {
|
|||||||
addressBook.provider!!.update(groupSyncUri(), values, null, null)
|
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
|
// helpers
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ class ImportActivity : BaseActivity(), SelectImportMethod, ResultFragment.OnImpo
|
|||||||
|
|
||||||
title = getString(R.string.import_dialog_title)
|
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
|
info = intent.extras!!.getSerializable(EXTRA_COLLECTION_INFO) as CollectionInfo
|
||||||
|
|
||||||
if (savedInstanceState == null)
|
if (savedInstanceState == null)
|
||||||
|
@ -21,13 +21,16 @@ import android.view.ViewGroup
|
|||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import at.bitfire.vcard4android.ContactsStorageException
|
import at.bitfire.vcard4android.ContactsStorageException
|
||||||
|
import com.etesync.syncadapter.App
|
||||||
import com.etesync.syncadapter.Constants.KEY_ACCOUNT
|
import com.etesync.syncadapter.Constants.KEY_ACCOUNT
|
||||||
import com.etesync.syncadapter.Constants.KEY_COLLECTION_INFO
|
import com.etesync.syncadapter.Constants.KEY_COLLECTION_INFO
|
||||||
import com.etesync.syncadapter.R
|
import com.etesync.syncadapter.R
|
||||||
import com.etesync.syncadapter.model.CollectionInfo
|
import com.etesync.syncadapter.model.CollectionInfo
|
||||||
import com.etesync.syncadapter.resource.LocalAddressBook
|
import com.etesync.syncadapter.resource.LocalAddressBook
|
||||||
import com.etesync.syncadapter.resource.LocalContact
|
import com.etesync.syncadapter.resource.LocalContact
|
||||||
|
import com.etesync.syncadapter.resource.LocalGroup
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.collections.HashMap
|
||||||
|
|
||||||
class LocalContactImportFragment : Fragment() {
|
class LocalContactImportFragment : Fragment() {
|
||||||
|
|
||||||
@ -132,9 +135,11 @@ class LocalContactImportFragment : Fragment() {
|
|||||||
try {
|
try {
|
||||||
val addressBook = LocalAddressBook.findByUid(context!!,
|
val addressBook = LocalAddressBook.findByUid(context!!,
|
||||||
context!!.contentResolver.acquireContentProviderClient(ContactsContract.RawContacts.CONTENT_URI)!!,
|
context!!.contentResolver.acquireContentProviderClient(ContactsContract.RawContacts.CONTENT_URI)!!,
|
||||||
account, info.uid!!)
|
account, info.uid!!)!!
|
||||||
val localContacts = localAddressBook.findAll()
|
val localContacts = localAddressBook.findAllContacts()
|
||||||
val total = localContacts.size
|
val localGroups = localAddressBook.findAllGroups()
|
||||||
|
val oldIdToNewId = HashMap<Long, Long>()
|
||||||
|
val total = localContacts.size + localGroups.size
|
||||||
progressDialog!!.max = total
|
progressDialog!!.max = total
|
||||||
result.total = total.toLong()
|
result.total = total.toLong()
|
||||||
var progress = 0
|
var progress = 0
|
||||||
@ -142,8 +147,27 @@ class LocalContactImportFragment : Fragment() {
|
|||||||
val contact = currentLocalContact.contact
|
val contact = currentLocalContact.contact
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val localContact = LocalContact(addressBook!!, contact!!, null, null)
|
val localContact = LocalContact(addressBook, contact!!, null, null)
|
||||||
localContact.createAsDirty()
|
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++
|
result.added++
|
||||||
} catch (e: ContactsStorageException) {
|
} catch (e: ContactsStorageException) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
Loading…
Reference in New Issue
Block a user