Loading .gitlab-ci.yml +4 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,10 @@ stages: - build before_script: - echo MURENA_CLIENT_ID=$MURENA_CLIENT_ID >> local.properties - echo MURENA_REDIRECT_URI=$MURENA_REDIRECT_URI >> local.properties - echo MURENA_BASE_URL=$MURENA_BASE_URL >> local.properties - echo MURENA_DISCOVERY_END_POINT=$MURENA_DISCOVERY_END_POINT >> local.properties - export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64 - export GRADLE_USER_HOME=$(pwd)/.gradle - chmod +x ./gradlew Loading app/build.gradle.kts +21 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,17 @@ android { if (versionName != null) { setProperty("archivesBaseName", "AccountManager-$versionName") } buildConfigField("String", "MURENA_CLIENT_ID", "\"${retrieveKey("MURENA_CLIENT_ID")}\"") buildConfigField("String", "MURENA_REDIRECT_URI", "\"${retrieveKey("MURENA_REDIRECT_URI")}\"") buildConfigField("String", "MURENA_BASE_URL", "\"${retrieveKey("MURENA_BASE_URL")}\"") buildConfigField("String", "MURENA_DISCOVERY_END_POINT", "\"${retrieveKey("MURENA_DISCOVERY_END_POINT")}\"") manifestPlaceholders.putAll( mapOf<String, Any>( "murenaAuthRedirectScheme" to retrieveKey("MURENA_REDIRECT_URI"), ) ) } } Loading Loading @@ -169,6 +180,15 @@ android { } } fun retrieveKey(keyName: String): String { val properties = Properties().apply { load(rootProject.file("local.properties").inputStream()) } return properties.getProperty(keyName) ?: throw GradleException("$keyName property not found in local.properties file") } ksp { arg("room.schemaLocation", "$projectDir/schemas") } Loading Loading @@ -264,6 +284,7 @@ dependencies { implementation(libs.commons.lang) // e-Specific dependencies implementation(libs.androidx.runtime.livedata) implementation(libs.elib) implementation(libs.ez.vcard) implementation(libs.synctools) { Loading app/src/main/kotlin/at/bitfire/davdroid/settings/AccountSettings.kt +3 −3 Original line number Diff line number Diff line Loading @@ -73,7 +73,7 @@ class AccountSettings @AssistedInject constructor( *AccountTypes.getAccountTypes().toTypedArray(), "at.bitfire.davdroid.test" // R.strings.account_type_test in androidTest ) if (!allowedAccountTypes.contains(account.type)) if (!allowedAccountTypes.any { it == account.type }) throw IllegalArgumentException("Invalid account type for AccountSettings(): ${account.type}") // synchronize because account migration must only be run one time Loading Loading @@ -157,7 +157,7 @@ class AccountSettings @AssistedInject constructor( SyncDataType.CONTACTS -> KEY_SYNC_INTERVAL_ADDRESSBOOKS SyncDataType.EVENTS -> KEY_SYNC_INTERVAL_CALENDARS SyncDataType.TASKS -> KEY_SYNC_INTERVAL_TASKS SyncDataType.DEFAULT -> KEY_SYNC_INTERVAL_DEFAULT else -> KEY_SYNC_INTERVAL_DEFAULT } val seconds = accountManager.getUserData(account, key)?.toLong() return when (seconds) { Loading @@ -178,7 +178,7 @@ class AccountSettings @AssistedInject constructor( SyncDataType.CONTACTS -> KEY_SYNC_INTERVAL_ADDRESSBOOKS SyncDataType.EVENTS -> KEY_SYNC_INTERVAL_CALENDARS SyncDataType.TASKS -> KEY_SYNC_INTERVAL_TASKS SyncDataType.DEFAULT -> KEY_SYNC_INTERVAL_DEFAULT else -> KEY_SYNC_INTERVAL_DEFAULT } val newValue = seconds ?: SYNC_INTERVAL_MANUALLY accountManager.setAndVerifyUserData(account, key, newValue.toString()) Loading app/src/main/kotlin/at/bitfire/davdroid/sync/AutomaticSyncManager.kt +12 −3 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ import at.bitfire.davdroid.resource.LocalAddressBookStore import at.bitfire.davdroid.settings.AccountSettings import at.bitfire.davdroid.sync.adapter.SyncFrameworkIntegration import at.bitfire.davdroid.sync.worker.SyncWorkerManager import foundation.e.accountmanager.Authority import kotlinx.coroutines.runBlocking import javax.inject.Inject import javax.inject.Provider Loading Loading @@ -94,7 +95,11 @@ class AutomaticSyncManager @Inject constructor( SyncDataType.CONTACTS -> throw IllegalStateException() // handled above SyncDataType.EVENTS -> CalendarContract.AUTHORITY SyncDataType.TASKS -> tasksAppManager.get().currentProvider()?.authority SyncDataType.DEFAULT -> null SyncDataType.EMAIL -> Authority.Email.authority SyncDataType.MEDIA -> Authority.Media.authority SyncDataType.NOTES -> Authority.Notes.authority SyncDataType.APP_DATA -> Authority.AppData.authority SyncDataType.E_DRIVE -> Authority.MeteredEDrive.authority } if (authority != null && syncInterval != null) { // enable given authority, but completely disable all other possible authorities Loading Loading @@ -136,9 +141,13 @@ class AutomaticSyncManager @Inject constructor( fun updateAutomaticSync(account: Account, dataType: SyncDataType) { val serviceType = when (dataType) { SyncDataType.CONTACTS -> Service.TYPE_CARDDAV SyncDataType.DEFAULT, SyncDataType.EVENTS, SyncDataType.TASKS -> Service.TYPE_CALDAV SyncDataType.TASKS, SyncDataType.EMAIL, SyncDataType.MEDIA, SyncDataType.NOTES, SyncDataType.APP_DATA, SyncDataType.E_DRIVE -> Service.TYPE_CALDAV } val hasService = runBlocking { serviceRepository.getByAccountAndType(account.name, serviceType) != null } Loading app/src/main/kotlin/at/bitfire/davdroid/sync/SyncDataType.kt +21 −3 Original line number Diff line number Diff line Loading @@ -12,12 +12,17 @@ import dagger.hilt.EntryPoint import dagger.hilt.InstallIn import dagger.hilt.android.EntryPointAccessors import dagger.hilt.components.SingletonComponent import foundation.e.accountmanager.Authority enum class SyncDataType { CONTACTS, DEFAULT, EVENTS, EMAIL, MEDIA, NOTES, APP_DATA, E_DRIVE, TASKS; @EntryPoint Loading @@ -37,7 +42,11 @@ enum class SyncDataType { CONTACTS -> listOf(ContactsContract.AUTHORITY) EVENTS -> listOf(CalendarContract.AUTHORITY) TASKS -> TaskProvider.ProviderName.entries.map { it.authority } DEFAULT -> emptyList() EMAIL -> listOf(Authority.Email.authority) MEDIA -> listOf(Authority.Media.authority) NOTES -> listOf(Authority.Notes.authority) APP_DATA -> listOf(Authority.AppData.authority) E_DRIVE -> listOf(Authority.MeteredEDrive.authority) } /** Loading @@ -56,7 +65,11 @@ enum class SyncDataType { .tasksAppManager() .currentProvider() ?.authority DEFAULT -> "" EMAIL -> Authority.Email.authority MEDIA -> Authority.Media.authority NOTES -> Authority.Notes.authority APP_DATA -> Authority.AppData.authority E_DRIVE -> Authority.MeteredEDrive.authority } Loading @@ -68,6 +81,11 @@ enum class SyncDataType { CONTACTS CalendarContract.AUTHORITY -> EVENTS Authority.Notes.authority -> NOTES Authority.Email.authority -> EMAIL Authority.Media.authority -> MEDIA Authority.AppData.authority -> APP_DATA Authority.MeteredEDrive.authority -> E_DRIVE TaskProvider.ProviderName.JtxBoard.authority, TaskProvider.ProviderName.TasksOrg.authority, TaskProvider.ProviderName.OpenTasks.authority, Loading Loading
.gitlab-ci.yml +4 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,10 @@ stages: - build before_script: - echo MURENA_CLIENT_ID=$MURENA_CLIENT_ID >> local.properties - echo MURENA_REDIRECT_URI=$MURENA_REDIRECT_URI >> local.properties - echo MURENA_BASE_URL=$MURENA_BASE_URL >> local.properties - echo MURENA_DISCOVERY_END_POINT=$MURENA_DISCOVERY_END_POINT >> local.properties - export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64 - export GRADLE_USER_HOME=$(pwd)/.gradle - chmod +x ./gradlew Loading
app/build.gradle.kts +21 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,17 @@ android { if (versionName != null) { setProperty("archivesBaseName", "AccountManager-$versionName") } buildConfigField("String", "MURENA_CLIENT_ID", "\"${retrieveKey("MURENA_CLIENT_ID")}\"") buildConfigField("String", "MURENA_REDIRECT_URI", "\"${retrieveKey("MURENA_REDIRECT_URI")}\"") buildConfigField("String", "MURENA_BASE_URL", "\"${retrieveKey("MURENA_BASE_URL")}\"") buildConfigField("String", "MURENA_DISCOVERY_END_POINT", "\"${retrieveKey("MURENA_DISCOVERY_END_POINT")}\"") manifestPlaceholders.putAll( mapOf<String, Any>( "murenaAuthRedirectScheme" to retrieveKey("MURENA_REDIRECT_URI"), ) ) } } Loading Loading @@ -169,6 +180,15 @@ android { } } fun retrieveKey(keyName: String): String { val properties = Properties().apply { load(rootProject.file("local.properties").inputStream()) } return properties.getProperty(keyName) ?: throw GradleException("$keyName property not found in local.properties file") } ksp { arg("room.schemaLocation", "$projectDir/schemas") } Loading Loading @@ -264,6 +284,7 @@ dependencies { implementation(libs.commons.lang) // e-Specific dependencies implementation(libs.androidx.runtime.livedata) implementation(libs.elib) implementation(libs.ez.vcard) implementation(libs.synctools) { Loading
app/src/main/kotlin/at/bitfire/davdroid/settings/AccountSettings.kt +3 −3 Original line number Diff line number Diff line Loading @@ -73,7 +73,7 @@ class AccountSettings @AssistedInject constructor( *AccountTypes.getAccountTypes().toTypedArray(), "at.bitfire.davdroid.test" // R.strings.account_type_test in androidTest ) if (!allowedAccountTypes.contains(account.type)) if (!allowedAccountTypes.any { it == account.type }) throw IllegalArgumentException("Invalid account type for AccountSettings(): ${account.type}") // synchronize because account migration must only be run one time Loading Loading @@ -157,7 +157,7 @@ class AccountSettings @AssistedInject constructor( SyncDataType.CONTACTS -> KEY_SYNC_INTERVAL_ADDRESSBOOKS SyncDataType.EVENTS -> KEY_SYNC_INTERVAL_CALENDARS SyncDataType.TASKS -> KEY_SYNC_INTERVAL_TASKS SyncDataType.DEFAULT -> KEY_SYNC_INTERVAL_DEFAULT else -> KEY_SYNC_INTERVAL_DEFAULT } val seconds = accountManager.getUserData(account, key)?.toLong() return when (seconds) { Loading @@ -178,7 +178,7 @@ class AccountSettings @AssistedInject constructor( SyncDataType.CONTACTS -> KEY_SYNC_INTERVAL_ADDRESSBOOKS SyncDataType.EVENTS -> KEY_SYNC_INTERVAL_CALENDARS SyncDataType.TASKS -> KEY_SYNC_INTERVAL_TASKS SyncDataType.DEFAULT -> KEY_SYNC_INTERVAL_DEFAULT else -> KEY_SYNC_INTERVAL_DEFAULT } val newValue = seconds ?: SYNC_INTERVAL_MANUALLY accountManager.setAndVerifyUserData(account, key, newValue.toString()) Loading
app/src/main/kotlin/at/bitfire/davdroid/sync/AutomaticSyncManager.kt +12 −3 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ import at.bitfire.davdroid.resource.LocalAddressBookStore import at.bitfire.davdroid.settings.AccountSettings import at.bitfire.davdroid.sync.adapter.SyncFrameworkIntegration import at.bitfire.davdroid.sync.worker.SyncWorkerManager import foundation.e.accountmanager.Authority import kotlinx.coroutines.runBlocking import javax.inject.Inject import javax.inject.Provider Loading Loading @@ -94,7 +95,11 @@ class AutomaticSyncManager @Inject constructor( SyncDataType.CONTACTS -> throw IllegalStateException() // handled above SyncDataType.EVENTS -> CalendarContract.AUTHORITY SyncDataType.TASKS -> tasksAppManager.get().currentProvider()?.authority SyncDataType.DEFAULT -> null SyncDataType.EMAIL -> Authority.Email.authority SyncDataType.MEDIA -> Authority.Media.authority SyncDataType.NOTES -> Authority.Notes.authority SyncDataType.APP_DATA -> Authority.AppData.authority SyncDataType.E_DRIVE -> Authority.MeteredEDrive.authority } if (authority != null && syncInterval != null) { // enable given authority, but completely disable all other possible authorities Loading Loading @@ -136,9 +141,13 @@ class AutomaticSyncManager @Inject constructor( fun updateAutomaticSync(account: Account, dataType: SyncDataType) { val serviceType = when (dataType) { SyncDataType.CONTACTS -> Service.TYPE_CARDDAV SyncDataType.DEFAULT, SyncDataType.EVENTS, SyncDataType.TASKS -> Service.TYPE_CALDAV SyncDataType.TASKS, SyncDataType.EMAIL, SyncDataType.MEDIA, SyncDataType.NOTES, SyncDataType.APP_DATA, SyncDataType.E_DRIVE -> Service.TYPE_CALDAV } val hasService = runBlocking { serviceRepository.getByAccountAndType(account.name, serviceType) != null } Loading
app/src/main/kotlin/at/bitfire/davdroid/sync/SyncDataType.kt +21 −3 Original line number Diff line number Diff line Loading @@ -12,12 +12,17 @@ import dagger.hilt.EntryPoint import dagger.hilt.InstallIn import dagger.hilt.android.EntryPointAccessors import dagger.hilt.components.SingletonComponent import foundation.e.accountmanager.Authority enum class SyncDataType { CONTACTS, DEFAULT, EVENTS, EMAIL, MEDIA, NOTES, APP_DATA, E_DRIVE, TASKS; @EntryPoint Loading @@ -37,7 +42,11 @@ enum class SyncDataType { CONTACTS -> listOf(ContactsContract.AUTHORITY) EVENTS -> listOf(CalendarContract.AUTHORITY) TASKS -> TaskProvider.ProviderName.entries.map { it.authority } DEFAULT -> emptyList() EMAIL -> listOf(Authority.Email.authority) MEDIA -> listOf(Authority.Media.authority) NOTES -> listOf(Authority.Notes.authority) APP_DATA -> listOf(Authority.AppData.authority) E_DRIVE -> listOf(Authority.MeteredEDrive.authority) } /** Loading @@ -56,7 +65,11 @@ enum class SyncDataType { .tasksAppManager() .currentProvider() ?.authority DEFAULT -> "" EMAIL -> Authority.Email.authority MEDIA -> Authority.Media.authority NOTES -> Authority.Notes.authority APP_DATA -> Authority.AppData.authority E_DRIVE -> Authority.MeteredEDrive.authority } Loading @@ -68,6 +81,11 @@ enum class SyncDataType { CONTACTS CalendarContract.AUTHORITY -> EVENTS Authority.Notes.authority -> NOTES Authority.Email.authority -> EMAIL Authority.Media.authority -> MEDIA Authority.AppData.authority -> APP_DATA Authority.MeteredEDrive.authority -> E_DRIVE TaskProvider.ProviderName.JtxBoard.authority, TaskProvider.ProviderName.TasksOrg.authority, TaskProvider.ProviderName.OpenTasks.authority, Loading