mirror of
https://github.com/bitfireAT/davx5-ose.git
synced 2025-12-23 23:17:50 -05:00
Create an option to pre-select the read-only setting for address books (bitfireAT/davx5#141)
* [WIP] add managed restriction to force read-only addressbooks * Honor app-wide read-only address book setting when syncing address books * reflect status of force read-only address books setting in the GUI Co-authored-by: Sunik Kupfer <kupfer@bitfire.at>
This commit is contained in:
@@ -46,7 +46,16 @@ open class LocalAddressBook(
|
||||
const val USER_DATA_URL = "url"
|
||||
const val USER_DATA_READ_ONLY = "read_only"
|
||||
|
||||
fun create(context: Context, provider: ContentProviderClient, mainAccount: Account, info: Collection): LocalAddressBook {
|
||||
/**
|
||||
* Creates a local address book.
|
||||
*
|
||||
* @param context app context to resolve string resources
|
||||
* @param provider contacts provider client
|
||||
* @param mainAccount main account this address book (account) belongs to
|
||||
* @param info collection where to take the name and settings from
|
||||
* @param forceReadOnly `true`: set the address book to "force read-only"; `false`: determine read-only flag from [info]
|
||||
*/
|
||||
fun create(context: Context, provider: ContentProviderClient, mainAccount: Account, info: Collection, forceReadOnly: Boolean): LocalAddressBook {
|
||||
val account = Account(accountName(mainAccount, info), context.getString(R.string.account_type_address_book))
|
||||
val userData = initialUserData(mainAccount, info.url.toString())
|
||||
Logger.log.log(Level.INFO, "Creating local address book $account", userData)
|
||||
@@ -61,7 +70,7 @@ open class LocalAddressBook(
|
||||
values.put(ContactsContract.Settings.SHOULD_SYNC, 1)
|
||||
values.put(ContactsContract.Settings.UNGROUPED_VISIBLE, 1)
|
||||
addressBook.settings = values
|
||||
addressBook.readOnly = !info.privWriteContent || info.forceReadOnly
|
||||
addressBook.readOnly = forceReadOnly || !info.privWriteContent || info.forceReadOnly
|
||||
|
||||
return addressBook
|
||||
}
|
||||
@@ -199,7 +208,13 @@ open class LocalAddressBook(
|
||||
return number
|
||||
}
|
||||
|
||||
fun update(info: Collection) {
|
||||
/**
|
||||
* Updates the address book settings.
|
||||
*
|
||||
* @param info collection where to take the settings from
|
||||
* @param forceReadOnly `true`: set the address book to "force read-only"; `false`: determine read-only flag from [info]
|
||||
*/
|
||||
fun update(info: Collection, forceReadOnly: Boolean) {
|
||||
val newAccountName = accountName(mainAccount, info)
|
||||
|
||||
if (account.name != newAccountName && Build.VERSION.SDK_INT >= 21) {
|
||||
@@ -209,7 +224,7 @@ open class LocalAddressBook(
|
||||
account = future.result
|
||||
}
|
||||
|
||||
val nowReadOnly = !info.privWriteContent || info.forceReadOnly
|
||||
val nowReadOnly = forceReadOnly || !info.privWriteContent || info.forceReadOnly
|
||||
if (nowReadOnly != readOnly) {
|
||||
Constants.log.info("Address book now read-only = $nowReadOnly, updating contacts")
|
||||
|
||||
|
||||
@@ -26,7 +26,8 @@ class DefaultsProvider(
|
||||
|
||||
override val booleanDefaults = mutableMapOf(
|
||||
Pair(Settings.DISTRUST_SYSTEM_CERTIFICATES, false),
|
||||
Pair(Settings.SYNC_ALL_COLLECTIONS, false)
|
||||
Pair(Settings.SYNC_ALL_COLLECTIONS, false),
|
||||
Pair(Settings.FORCE_READ_ONLY_ADDRESSBOOKS, false)
|
||||
)
|
||||
|
||||
override val intDefaults = mapOf(
|
||||
|
||||
@@ -38,5 +38,8 @@ object Settings {
|
||||
|
||||
/** whether detected collections are selected for synchronization for default */
|
||||
const val SYNC_ALL_COLLECTIONS = "sync_all_collections"
|
||||
|
||||
/** whether all address books are forced to be read-only */
|
||||
const val FORCE_READ_ONLY_ADDRESSBOOKS = "force_read_only_addressbooks"
|
||||
|
||||
}
|
||||
|
||||
@@ -21,6 +21,12 @@ import at.bitfire.davdroid.db.Service
|
||||
import at.bitfire.davdroid.log.Logger
|
||||
import at.bitfire.davdroid.resource.LocalAddressBook
|
||||
import at.bitfire.davdroid.settings.AccountSettings
|
||||
import at.bitfire.davdroid.settings.Settings
|
||||
import at.bitfire.davdroid.settings.SettingsManager
|
||||
import dagger.hilt.EntryPoint
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.EntryPointAccessors
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import java.util.logging.Level
|
||||
@@ -35,6 +41,15 @@ class AddressBooksSyncAdapterService : SyncAdapterService() {
|
||||
appDatabase: AppDatabase
|
||||
) : SyncAdapter(context, appDatabase) {
|
||||
|
||||
@EntryPoint
|
||||
@InstallIn(SingletonComponent::class)
|
||||
interface AddressBooksSyncAdapterEntryPoint {
|
||||
fun settingsManager(): SettingsManager
|
||||
}
|
||||
|
||||
val entryPoint = EntryPointAccessors.fromApplication(context, AddressBooksSyncAdapterEntryPoint::class.java)
|
||||
val settingsManager = entryPoint.settingsManager()
|
||||
|
||||
override fun sync(account: Account, extras: Bundle, authority: String, httpClient: Lazy<HttpClient>, provider: ContentProviderClient, syncResult: SyncResult) {
|
||||
try {
|
||||
val accountSettings = AccountSettings(context, account)
|
||||
@@ -85,6 +100,8 @@ class AddressBooksSyncAdapterService : SyncAdapterService() {
|
||||
return false
|
||||
}
|
||||
|
||||
val forceAllReadOnly = settingsManager.getBoolean(Settings.FORCE_READ_ONLY_ADDRESSBOOKS)
|
||||
|
||||
// delete/update local address books
|
||||
for (addressBook in LocalAddressBook.findAll(context, contactsProvider, account)) {
|
||||
val url = addressBook.url.toHttpUrl()
|
||||
@@ -96,7 +113,7 @@ class AddressBooksSyncAdapterService : SyncAdapterService() {
|
||||
// remote CollectionInfo found for this local collection, update data
|
||||
try {
|
||||
Logger.log.log(Level.FINE, "Updating local address book $url", info)
|
||||
addressBook.update(info)
|
||||
addressBook.update(info, forceAllReadOnly)
|
||||
} catch (e: Exception) {
|
||||
Logger.log.log(Level.WARNING, "Couldn't rename address book account", e)
|
||||
}
|
||||
@@ -108,7 +125,7 @@ class AddressBooksSyncAdapterService : SyncAdapterService() {
|
||||
// create new local address books
|
||||
for ((_, info) in remoteAddressBooks) {
|
||||
Logger.log.log(Level.INFO, "Adding local address book", info)
|
||||
LocalAddressBook.create(context, contactsProvider, account, info)
|
||||
LocalAddressBook.create(context, contactsProvider, account, info, forceAllReadOnly)
|
||||
}
|
||||
} finally {
|
||||
contactsProvider?.closeCompat()
|
||||
|
||||
@@ -11,6 +11,12 @@ import at.bitfire.davdroid.PermissionUtils
|
||||
import at.bitfire.davdroid.R
|
||||
import at.bitfire.davdroid.databinding.AccountCarddavItemBinding
|
||||
import at.bitfire.davdroid.db.Collection
|
||||
import at.bitfire.davdroid.settings.Settings
|
||||
import at.bitfire.davdroid.settings.SettingsManager
|
||||
import dagger.hilt.EntryPoint
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.EntryPointAccessors
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
|
||||
class AddressBooksFragment: CollectionsFragment() {
|
||||
|
||||
@@ -53,9 +59,18 @@ class AddressBooksFragment: CollectionsFragment() {
|
||||
class AddressBookViewHolder(
|
||||
parent: ViewGroup,
|
||||
accountModel: AccountActivity.Model,
|
||||
val fragmentManager: FragmentManager
|
||||
val fragmentManager: FragmentManager,
|
||||
): CollectionViewHolder<AccountCarddavItemBinding>(parent, AccountCarddavItemBinding.inflate(LayoutInflater.from(parent.context), parent, false), accountModel) {
|
||||
|
||||
@EntryPoint
|
||||
@InstallIn(SingletonComponent::class)
|
||||
interface AddressBookViewHolderEntryPoint {
|
||||
fun settingsManager(): SettingsManager
|
||||
}
|
||||
|
||||
private val settings = EntryPointAccessors.fromApplication(parent.context, AddressBookViewHolderEntryPoint::class.java).settingsManager()
|
||||
private val forceReadOnlyAddressBooks = settings.getBoolean(Settings.FORCE_READ_ONLY_ADDRESSBOOKS) // managed restriction
|
||||
|
||||
override fun bindTo(item: Collection) {
|
||||
binding.sync.isChecked = item.sync
|
||||
binding.title.text = item.title()
|
||||
@@ -67,12 +82,12 @@ class AddressBooksFragment: CollectionsFragment() {
|
||||
binding.description.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
binding.readOnly.visibility = if (item.readOnly()) View.VISIBLE else View.GONE
|
||||
binding.readOnly.visibility = if (item.readOnly() || forceReadOnlyAddressBooks) View.VISIBLE else View.GONE
|
||||
|
||||
itemView.setOnClickListener {
|
||||
accountModel.toggleSync(item)
|
||||
}
|
||||
binding.actionOverflow.setOnClickListener(CollectionPopupListener(accountModel, item, fragmentManager))
|
||||
binding.actionOverflow.setOnClickListener(CollectionPopupListener(accountModel, item, fragmentManager, forceReadOnlyAddressBooks))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -226,7 +226,8 @@ abstract class CollectionsFragment: Fragment(), SwipeRefreshLayout.OnRefreshList
|
||||
class CollectionPopupListener(
|
||||
private val accountModel: AccountActivity.Model,
|
||||
private val item: Collection,
|
||||
private val fragmentManager: FragmentManager
|
||||
private val fragmentManager: FragmentManager,
|
||||
private val forceReadOnly: Boolean = false
|
||||
): View.OnClickListener {
|
||||
|
||||
override fun onClick(anchor: View) {
|
||||
@@ -244,6 +245,12 @@ abstract class CollectionsFragment: Fragment(), SwipeRefreshLayout.OnRefreshList
|
||||
else
|
||||
isVisible = false
|
||||
}
|
||||
|
||||
if (item.type == Collection.TYPE_ADDRESSBOOK && forceReadOnly) {
|
||||
// managed restriction "force read-only address books" is active
|
||||
isChecked = true
|
||||
isEnabled = false
|
||||
}
|
||||
}
|
||||
popup.menu.findItem(R.id.delete_collection).isVisible = item.privUnbind
|
||||
|
||||
|
||||
Reference in New Issue
Block a user