Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove concept of main accounts #989

Merged
merged 30 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8c86a82
Acquire account settings via address book account
sunkup Aug 20, 2024
b355678
Extract the code to find an address books main account to the account…
sunkup Aug 20, 2024
f9089a9
Use collection id as reference in address book account
sunkup Sep 9, 2024
83c3b1c
Remove obsolete baos
sunkup Sep 14, 2024
d57c43a
Find main account directly from collection in SyncManager
sunkup Sep 14, 2024
8b239a8
Require main account to get account settings
sunkup Sep 14, 2024
c7b1809
Stop deleting address book accounts without a main account, since the…
sunkup Sep 14, 2024
f3c0849
Require content provider and introduce static deleteByCollection method
sunkup Sep 14, 2024
5fd7655
Update KDoc
sunkup Sep 14, 2024
4c596d3
Show all address book accounts separately
sunkup Sep 14, 2024
67d0409
Drop mainAccount method
sunkup Sep 14, 2024
484212c
[DI] Use AssistedInject for LocalAddressBook
rfc2822 Sep 17, 2024
e738203
Merge remote-tracking branch 'origin/main-ose' into 878-remove-concep…
rfc2822 Sep 17, 2024
e32c10c
Renaming, remove "main account" concept
rfc2822 Sep 17, 2024
35332e7
Fix debug info
rfc2822 Sep 17, 2024
ee40f02
AccountsCleanupWorker: Rename main account to account
rfc2822 Sep 17, 2024
ea8617a
Further remove main accounts
rfc2822 Sep 17, 2024
53c4ca1
Reduce redundancy
rfc2822 Sep 17, 2024
6555584
AccountSettings: check account type
rfc2822 Sep 17, 2024
5c31a8a
AccountSettingsMigrations: drop v5 -> v6 migration (not tested anyway)
rfc2822 Sep 17, 2024
866cdf0
AccountRepository: directly delete accounts
rfc2822 Sep 17, 2024
beb201b
Remove obsolete workerAccount
rfc2822 Sep 17, 2024
04b6e35
Get all address books, even if not sync enabled
sunkup Sep 18, 2024
cbb2718
Delete orphan address book accounts
sunkup Sep 18, 2024
6e5b3c5
Rename two more occurrences of main account concept
sunkup Sep 18, 2024
dd4efa1
AccountSettings: allow test accounts
rfc2822 Sep 19, 2024
26d3667
Syncer: rename methods for clarity, add KDoc
rfc2822 Sep 19, 2024
dfd81ff
Drop empty test class
sunkup Sep 19, 2024
3b7fa46
Make code more readable and add comment
sunkup Sep 19, 2024
d7ab51f
Merge branch 'main-ose' into 878-remove-concept-of-main-accounts
rfc2822 Sep 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
[DI] Use AssistedInject for LocalAddressBook
  • Loading branch information
rfc2822 committed Sep 17, 2024
commit 484212c11a67ee1fe36bcba1b2a5aea6850de9af

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import android.provider.ContactsContract
import android.provider.ContactsContract.CommonDataKinds.GroupMembership
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.GrantPermissionRule
import at.bitfire.davdroid.settings.SettingsManager
import at.bitfire.vcard4android.BatchOperation
import at.bitfire.vcard4android.CachedGroupMembership
import at.bitfire.vcard4android.Contact
Expand Down Expand Up @@ -68,7 +67,7 @@ class LocalGroupTest {
lateinit var context: Context

@Inject
lateinit var settingsManager: SettingsManager
lateinit var addressbookFactory: LocalTestAddressBook.Factory


private lateinit var addressBookGroupsAsCategories: LocalTestAddressBook
Expand All @@ -78,8 +77,8 @@ class LocalGroupTest {
fun setup() {
hiltRule.inject()

addressBookGroupsAsCategories = LocalTestAddressBook(context, provider, GroupMethod.CATEGORIES)
addressBookGroupsAsVCards = LocalTestAddressBook(context, provider, GroupMethod.GROUP_VCARDS)
addressBookGroupsAsCategories = addressbookFactory.create(provider, GroupMethod.CATEGORIES)
addressBookGroupsAsVCards = addressbookFactory.create(provider, GroupMethod.GROUP_VCARDS)

// clear contacts
addressBookGroupsAsCategories.clear()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,33 @@ package at.bitfire.davdroid.resource
import android.accounts.Account
import android.content.ContentProviderClient
import android.content.Context
import at.bitfire.davdroid.repository.DavCollectionRepository
import at.bitfire.davdroid.repository.DavServiceRepository
import at.bitfire.davdroid.settings.AccountSettings
import at.bitfire.vcard4android.GroupMethod

class LocalTestAddressBook(
context: Context,
provider: ContentProviderClient,
override val groupMethod: GroupMethod
): LocalAddressBook(context, ACCOUNT, provider) {
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import dagger.hilt.android.qualifiers.ApplicationContext

class LocalTestAddressBook @AssistedInject constructor(
@Assisted provider: ContentProviderClient,
@Assisted override val groupMethod: GroupMethod,
@ApplicationContext context: Context,
accountSettingsFactory: AccountSettings.Factory,
collectionRepository: DavCollectionRepository,
serviceRepository: DavServiceRepository
): LocalAddressBook(ACCOUNT, provider, context, accountSettingsFactory, collectionRepository, serviceRepository) {

companion object {
val ACCOUNT = Account("LocalTestAddressBook", "at.bitfire.davdroid.test")
}

@AssistedFactory
interface Factory {
fun create(provider: ContentProviderClient, groupMethod: GroupMethod): LocalTestAddressBook
}

override var readOnly: Boolean
get() = false
set(_) = throw NotImplementedError()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ class CachedGroupMembershipHandlerTest {
}


@Inject
lateinit var addressbookFactory: LocalTestAddressBook.Factory

@Inject
@ApplicationContext
lateinit var context: Context
Expand All @@ -70,7 +73,7 @@ class CachedGroupMembershipHandlerTest {

@Test
fun testMembership() {
val addressBook = LocalTestAddressBook(context, provider, GroupMethod.GROUP_VCARDS)
val addressBook = addressbookFactory.create(provider, GroupMethod.GROUP_VCARDS)

val contact = Contact()
val localContact = LocalContact(addressBook, contact, null, null, 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ class GroupMembershipBuilderTest {
@get:Rule
val hiltRule = HiltAndroidRule(this)

@Inject
lateinit var addressbookFactory: LocalTestAddressBook.Factory

@Inject
@ApplicationContext
lateinit var context: Context
Expand All @@ -71,7 +74,7 @@ class GroupMembershipBuilderTest {
val contact = Contact().apply {
categories += "TEST GROUP"
}
val addressBookGroupsAsCategories = LocalTestAddressBook(context, provider, GroupMethod.CATEGORIES)
val addressBookGroupsAsCategories = addressbookFactory.create(provider, GroupMethod.CATEGORIES)
GroupMembershipBuilder(Uri.EMPTY, null, contact, addressBookGroupsAsCategories, false).build().also { result ->
assertEquals(1, result.size)
assertEquals(GroupMembership.CONTENT_ITEM_TYPE, result[0].values[GroupMembership.MIMETYPE])
Expand All @@ -84,7 +87,7 @@ class GroupMembershipBuilderTest {
val contact = Contact().apply {
categories += "TEST GROUP"
}
val addressBookGroupsAsVCards = LocalTestAddressBook(context, provider, GroupMethod.GROUP_VCARDS)
val addressBookGroupsAsVCards = addressbookFactory.create(provider, GroupMethod.GROUP_VCARDS)
GroupMembershipBuilder(Uri.EMPTY, null, contact, addressBookGroupsAsVCards, false).build().also { result ->
// group membership is constructed during post-processing
assertEquals(0, result.size)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ class GroupMembershipHandlerTest {

}

@Inject
lateinit var addressbookFactory: LocalTestAddressBook.Factory

@Inject @ApplicationContext
lateinit var context: Context

Expand All @@ -71,7 +74,7 @@ class GroupMembershipHandlerTest {

@Test
fun testMembership_GroupsAsCategories() {
val addressBookGroupsAsCategories = LocalTestAddressBook(context, provider, GroupMethod.CATEGORIES)
val addressBookGroupsAsCategories = addressbookFactory.create(provider, GroupMethod.CATEGORIES)
val addressBookGroupsAsCategoriesGroup = addressBookGroupsAsCategories.findOrCreateGroup("TEST GROUP")

val contact = Contact()
Expand All @@ -87,7 +90,7 @@ class GroupMembershipHandlerTest {

@Test
fun testMembership_GroupsAsVCards() {
val addressBookGroupsAsVCards = LocalTestAddressBook(context, provider, GroupMethod.GROUP_VCARDS)
val addressBookGroupsAsVCards = addressbookFactory.create(provider, GroupMethod.GROUP_VCARDS)

val contact = Contact()
val localContact = LocalContact(addressBookGroupsAsVCards, contact, null, null, 0)
Expand Down
rfc2822 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import android.provider.ContactsContract
import android.provider.ContactsContract.CommonDataKinds.GroupMembership
import android.provider.ContactsContract.Groups
import android.provider.ContactsContract.RawContacts
import androidx.annotation.OpenForTesting
import at.bitfire.davdroid.R
import at.bitfire.davdroid.db.Collection
import at.bitfire.davdroid.db.SyncState
Expand All @@ -30,14 +31,17 @@ import at.bitfire.vcard4android.AndroidAddressBook
import at.bitfire.vcard4android.AndroidContact
import at.bitfire.vcard4android.AndroidGroup
import at.bitfire.vcard4android.GroupMethod
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import dagger.hilt.EntryPoint
import dagger.hilt.InstallIn
import dagger.hilt.android.EntryPointAccessors
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import java.util.LinkedList
import java.util.logging.Level
import java.util.logging.Logger
import javax.inject.Inject

/**
* A local address book. Requires an own Android account, because Android manages contacts per
Expand All @@ -47,14 +51,24 @@ import javax.inject.Inject
* @param account Address book account storing the actual android address book
* @param provider Content provider needed to access and modify the address book.
*/
open class LocalAddressBook @Inject constructor(
private val context: Context,
account: Account,
provider: ContentProviderClient
@OpenForTesting
open class LocalAddressBook @AssistedInject constructor(
@Assisted account: Account,
@Assisted provider: ContentProviderClient,
@ApplicationContext val context: Context,
private val accountSettingsFactory: AccountSettings.Factory,
private val collectionRepository: DavCollectionRepository,
private val serviceRepository: DavServiceRepository
): AndroidAddressBook<LocalContact, LocalGroup>(account, provider, LocalContact.Factory, LocalGroup.Factory), LocalCollection<LocalAddress> {

companion object {


@EntryPoint
@InstallIn(SingletonComponent::class)
interface LocalAddressBookCompanionEntryPoint {
fun localAddressBookFactory(): Factory
}

private val logger
get() = Logger.getGlobal()

Expand All @@ -77,7 +91,9 @@ open class LocalAddressBook @Inject constructor(
if (!AccountUtils.createAccount(context, account, userData))
throw IllegalStateException("Couldn't create address book account")

val addressBook = LocalAddressBook(context, account, provider)
val entryPoint = EntryPointAccessors.fromApplication<LocalAddressBookCompanionEntryPoint>(context)
val factory = entryPoint.localAddressBookFactory()
val addressBook = factory.create(account, provider)
addressBook.updateSyncFrameworkSettings()

// initialize Contacts Provider Settings
Expand All @@ -92,15 +108,20 @@ open class LocalAddressBook @Inject constructor(

/**
* Finds a [LocalAddressBook] based on its corresponding collection.
* @param info The corresponding collection
*
* @param info The corresponding collection. Used to calculate the address book name to look for.
*
* @return The [LocalAddressBook] for the given collection or *null* if not found
*/
fun find(context: Context, provider: ContentProviderClient, info: Collection) =
AccountManager.get(context)
fun find(context: Context, provider: ContentProviderClient, info: Collection): LocalAddressBook? {
val entryPoint = EntryPointAccessors.fromApplication<LocalAddressBookCompanionEntryPoint>(context)
val factory = entryPoint.localAddressBookFactory()
return AccountManager.get(context)
.getAccountsByType(context.getString(R.string.account_type_address_book))
.filter { account -> account.name == accountName(info) }
.map { account -> LocalAddressBook(context, account, provider) }
.map { account -> factory.create(account, provider) }
.firstOrNull()
}

/**
* Deletes a [LocalAddressBook] based on its corresponding database collection.
Expand Down Expand Up @@ -142,23 +163,16 @@ open class LocalAddressBook @Inject constructor(
}
}

@EntryPoint
@InstallIn(SingletonComponent::class)
interface LocalAddressBookEntryPoint {
fun accountSettingsFactory(): AccountSettings.Factory
fun collectionRepository(): DavCollectionRepository
fun serviceRepository(): DavServiceRepository
@AssistedFactory
interface Factory {
fun create(account: Account, provider: ContentProviderClient): LocalAddressBook
}
private val entryPoint = EntryPointAccessors.fromApplication(context, LocalAddressBookEntryPoint::class.java)
private val accountSettingsFactory = entryPoint.accountSettingsFactory()
private val collectionRepository = entryPoint.collectionRepository()
private val serviceRepository = entryPoint.serviceRepository()


override val tag: String
get() = "contacts-${account.name}"

override val title = account.name!!
override val title = account.name

/**
* Whether contact groups ([LocalGroup]) are included in query results
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class AddressBookSyncer @AssistedInject constructor(
@Assisted extras: Array<String>,
@Assisted syncResult: SyncResult,
private val contactsSyncManagerFactory: ContactsSyncManager.Factory,
private val localAddressbookFactory: LocalAddressBook.Factory,
settingsManager: SettingsManager
): Syncer<LocalAddressBook>(account, extras, syncResult) {

Expand Down Expand Up @@ -118,7 +119,7 @@ class AddressBookSyncer @AssistedInject constructor(
throw IllegalArgumentException("Main account for address book account missing. Can't sync address book")

val accountSettings = accountSettingsFactory.forAccount(mainAccount)
val addressBook = LocalAddressBook(context, account, provider)
val addressBook = localAddressbookFactory.create(account, provider)

// handle group method change
val groupMethod = accountSettings.getGroupMethod().name
Expand Down
5 changes: 3 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ glance = "1.1.0"
guava = "33.3.0-android"
hilt = "2.52"
# keep in sync with ksp version
kotlin = "2.0.20"
# Don't use 2.0.20 until https://github.com/google/ksp/issues/2072 is fixed
kotlin = "2.0.10"
kotlinx-coroutines = "1.8.1"
# see https://github.com/google/ksp/releases for version numbers
ksp = "2.0.20-1.0.24"
ksp = "2.0.10-1.0.24"
mikepenz-aboutLibraries = "11.2.3"
nsk90-kstatemachine = "0.31.1"
mockk = "1.13.12"
Expand Down
Loading