diff --git a/app/src/main/java/org/tasks/analytics/Constants.kt b/app/src/main/java/org/tasks/analytics/Constants.kt index c6713e17e..0be975e31 100644 --- a/app/src/main/java/org/tasks/analytics/Constants.kt +++ b/app/src/main/java/org/tasks/analytics/Constants.kt @@ -7,4 +7,5 @@ object Constants { const val SYNC_TYPE_GOOGLE_TASKS = "google_tasks" const val SYNC_TYPE_ETESYNC_OT = "etesync_ot" const val SYNC_TYPE_ETEBASE = "etebase" + const val SYNC_TYPE_DECSYNC = "decsync" } \ No newline at end of file diff --git a/app/src/main/java/org/tasks/data/CaldavAccount.kt b/app/src/main/java/org/tasks/data/CaldavAccount.kt index abacca22c..2ab797bfd 100644 --- a/app/src/main/java/org/tasks/data/CaldavAccount.kt +++ b/app/src/main/java/org/tasks/data/CaldavAccount.kt @@ -13,7 +13,6 @@ import org.tasks.R import org.tasks.activities.BaseListSettingsActivity import org.tasks.caldav.CaldavCalendarSettingsActivity import org.tasks.caldav.LocalListSettingsActivity -import org.tasks.data.OpenTaskDao.Companion.ACCOUNT_TYPE_ETESYNC import org.tasks.etebase.EtebaseCalendarSettingsActivity import org.tasks.etesync.EteSyncCalendarSettingsActivity import org.tasks.opentasks.OpenTasksListSettingsActivity @@ -100,9 +99,6 @@ class CaldavAccount : Parcelable { val isOpenTasks: Boolean get() = accountType == TYPE_OPENTASKS - val isOpenTaskEteSync: Boolean - get() = uuid.openTaskType() == ACCOUNT_TYPE_ETESYNC - val isTasksOrg: Boolean get() = accountType == TYPE_TASKS diff --git a/app/src/main/java/org/tasks/data/OpenTaskDao.kt b/app/src/main/java/org/tasks/data/OpenTaskDao.kt index 85c627b98..657fa1849 100644 --- a/app/src/main/java/org/tasks/data/OpenTaskDao.kt +++ b/app/src/main/java/org/tasks/data/OpenTaskDao.kt @@ -38,7 +38,7 @@ class OpenTaskDao @Inject constructor( cr.query( TaskLists.getContentUri(authority), null, - "${TaskListColumns.SYNC_ENABLED}=1 AND ($ACCOUNT_TYPE = '$ACCOUNT_TYPE_DAVx5' OR $ACCOUNT_TYPE = '$ACCOUNT_TYPE_ETESYNC')", + "${TaskListColumns.SYNC_ENABLED}=1 AND ($SUPPORTED_TYPE_FILTER)", null, null)?.use { while (it.moveToNext()) { @@ -240,14 +240,27 @@ class OpenTaskDao @Inject constructor( companion object { private const val OPENTASK_BATCH_LIMIT = 499 - const val ACCOUNT_TYPE_DAVx5 = "bitfire.at.davdroid" - const val ACCOUNT_TYPE_ETESYNC = "com.etesync.syncadapter" + private const val ACCOUNT_TYPE_DAVx5 = "bitfire.at.davdroid" + private const val ACCOUNT_TYPE_ETESYNC = "com.etesync.syncadapter" + private const val ACCOUNT_TYPE_DECSYNC = "org.decsync.tasks" + val SUPPORTED_TYPES = setOf( + ACCOUNT_TYPE_DAVx5, + ACCOUNT_TYPE_ETESYNC, + ACCOUNT_TYPE_DECSYNC + ) + val SUPPORTED_TYPE_FILTER = SUPPORTED_TYPES.joinToString(" OR ") { "ACCOUNT_TYPE = '$it'" } suspend fun Map>.newAccounts(caldavDao: CaldavDao) = filterNot { (_, lists) -> caldavDao.anyExist(lists.map { it.url!! }) } .map { it.key } .distinct() + fun String?.isDavx5(): Boolean = this?.startsWith(ACCOUNT_TYPE_DAVx5) == true + + fun String?.isEteSync(): Boolean = this?.startsWith(ACCOUNT_TYPE_ETESYNC) == true + + fun String?.isDecSync(): Boolean = this?.startsWith(ACCOUNT_TYPE_DECSYNC) == true + fun Cursor.getString(columnName: String): String? = getString(getColumnIndex(columnName)) diff --git a/app/src/main/java/org/tasks/jobs/SyncOpenTasksWork.kt b/app/src/main/java/org/tasks/jobs/SyncOpenTasksWork.kt index 15a08ed84..b62b6024f 100644 --- a/app/src/main/java/org/tasks/jobs/SyncOpenTasksWork.kt +++ b/app/src/main/java/org/tasks/jobs/SyncOpenTasksWork.kt @@ -13,8 +13,7 @@ import org.tasks.analytics.Firebase import org.tasks.data.CaldavAccount.Companion.TYPE_OPENTASKS import org.tasks.data.CaldavDao import org.tasks.data.OpenTaskDao -import org.tasks.data.OpenTaskDao.Companion.ACCOUNT_TYPE_DAVx5 -import org.tasks.data.OpenTaskDao.Companion.ACCOUNT_TYPE_ETESYNC +import org.tasks.data.OpenTaskDao.Companion.SUPPORTED_TYPES import org.tasks.opentasks.OpenTasksSynchronizer import org.tasks.preferences.Preferences @@ -41,7 +40,7 @@ class SyncOpenTasksWork @WorkerInject constructor( AccountManager .get(context) .accounts - .filter { it.type == ACCOUNT_TYPE_DAVx5 || it.type == ACCOUNT_TYPE_ETESYNC } + .filter { SUPPORTED_TYPES.contains(it.type) } .forEach { ContentResolver.requestSync( it, diff --git a/app/src/main/java/org/tasks/opentasks/OpenTaskAccountSettingsActivity.kt b/app/src/main/java/org/tasks/opentasks/OpenTaskAccountSettingsActivity.kt index 5a480537f..571d14ed2 100644 --- a/app/src/main/java/org/tasks/opentasks/OpenTaskAccountSettingsActivity.kt +++ b/app/src/main/java/org/tasks/opentasks/OpenTaskAccountSettingsActivity.kt @@ -9,6 +9,7 @@ import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.launch import org.tasks.R import org.tasks.caldav.BaseCaldavAccountSettingsActivity +import org.tasks.data.OpenTaskDao.Companion.isDavx5 @AndroidEntryPoint class OpenTaskAccountSettingsActivity : BaseCaldavAccountSettingsActivity(), Toolbar.OnMenuItemClickListener { @@ -20,13 +21,12 @@ class OpenTaskAccountSettingsActivity : BaseCaldavAccountSettingsActivity(), Too binding.passwordLayout.visibility = View.GONE binding.urlLayout.visibility = View.GONE - if (caldavAccount!!.isOpenTaskEteSync) { + if (caldavAccount?.uuid?.isDavx5() != true) { binding.repeat.visibility = View.GONE } } - override val newPassword: String? - get() = "" + override val newPassword = "" private suspend fun updateAccount(principal: String?) { hideProgressIndicator() @@ -35,7 +35,7 @@ class OpenTaskAccountSettingsActivity : BaseCaldavAccountSettingsActivity(), Too caldavAccount!!.username = newUsername caldavAccount!!.error = "" if (passwordChanged()) { - caldavAccount!!.password = encryption.encrypt(newPassword!!) + caldavAccount!!.password = encryption.encrypt(newPassword) } caldavAccount!!.isSuppressRepeatingTasks = binding.repeat.isChecked caldavDao.update(caldavAccount!!) diff --git a/app/src/main/java/org/tasks/opentasks/OpenTasksSynchronizer.kt b/app/src/main/java/org/tasks/opentasks/OpenTasksSynchronizer.kt index fefec7fb4..5f8284236 100644 --- a/app/src/main/java/org/tasks/opentasks/OpenTasksSynchronizer.kt +++ b/app/src/main/java/org/tasks/opentasks/OpenTasksSynchronizer.kt @@ -30,6 +30,9 @@ import org.tasks.data.CaldavAccount.Companion.openTaskType import org.tasks.data.OpenTaskDao.Companion.getInt import org.tasks.data.OpenTaskDao.Companion.getLong import org.tasks.data.OpenTaskDao.Companion.getString +import org.tasks.data.OpenTaskDao.Companion.isDavx5 +import org.tasks.data.OpenTaskDao.Companion.isDecSync +import org.tasks.data.OpenTaskDao.Companion.isEteSync import org.tasks.data.OpenTaskDao.Companion.newAccounts import org.tasks.date.DateTimeUtils.newDateTime import org.tasks.time.DateTime @@ -72,10 +75,11 @@ class OpenTasksSynchronizer @Inject constructor( .forEach { firebase.logEvent( R.string.event_sync_add_account, - R.string.param_type to if (it.isOpenTaskEteSync) { - Constants.SYNC_TYPE_ETESYNC_OT - } else { - Constants.SYNC_TYPE_DAVX5 + R.string.param_type to when { + it.uuid.isDavx5() -> Constants.SYNC_TYPE_DAVX5 + it.uuid.isEteSync() -> Constants.SYNC_TYPE_ETESYNC_OT + it.uuid.isDecSync() -> Constants.SYNC_TYPE_DECSYNC + else -> throw IllegalArgumentException() } ) } @@ -131,7 +135,7 @@ class OpenTasksSynchronizer @Inject constructor( listId: Long ) { Timber.d("SYNC $calendar") - val isEteSync = account.isOpenTaskEteSync + val isEteSync = account.uuid?.isEteSync() == true val moved = caldavDao.getMoved(calendar.uuid!!) val (deleted, updated) = diff --git a/app/src/main/java/org/tasks/preferences/fragments/Synchronization.kt b/app/src/main/java/org/tasks/preferences/fragments/Synchronization.kt index da2297433..d48217e53 100644 --- a/app/src/main/java/org/tasks/preferences/fragments/Synchronization.kt +++ b/app/src/main/java/org/tasks/preferences/fragments/Synchronization.kt @@ -22,8 +22,9 @@ import org.tasks.data.CaldavAccount.Companion.TYPE_TASKS import org.tasks.data.CaldavDao import org.tasks.data.GoogleTaskAccount import org.tasks.data.GoogleTaskListDao -import org.tasks.data.OpenTaskDao.Companion.ACCOUNT_TYPE_DAVx5 -import org.tasks.data.OpenTaskDao.Companion.ACCOUNT_TYPE_ETESYNC +import org.tasks.data.OpenTaskDao.Companion.isDavx5 +import org.tasks.data.OpenTaskDao.Companion.isDecSync +import org.tasks.data.OpenTaskDao.Companion.isEteSync import org.tasks.etebase.EtebaseAccountSettingsActivity import org.tasks.etesync.EteSyncAccountSettingsActivity import org.tasks.injection.InjectingPreferenceFragment @@ -151,13 +152,10 @@ class Synchronization : InjectingPreferenceFragment() { preference.setSummary(when { account.isCaldavAccount -> R.string.caldav account.isEteSyncAccount -> R.string.etesync_v1 - account.isEtebaseAccount - || (account.isOpenTasks - && account.uuid?.startsWith(ACCOUNT_TYPE_ETESYNC) == true) -> - R.string.etesync - account.isOpenTasks - && account.uuid?.startsWith(ACCOUNT_TYPE_DAVx5) == true -> - R.string.davx5 + account.isEtebaseAccount -> R.string.etesync + account.isOpenTasks && account.uuid.isEteSync() -> R.string.etesync + account.isOpenTasks && account.uuid.isDavx5() -> R.string.davx5 + account.isOpenTasks && account.uuid.isDecSync() -> R.string.decsync else -> 0 }) } else { diff --git a/app/src/main/java/org/tasks/sync/AddAccountDialog.kt b/app/src/main/java/org/tasks/sync/AddAccountDialog.kt index 84d878367..d15567698 100644 --- a/app/src/main/java/org/tasks/sync/AddAccountDialog.kt +++ b/app/src/main/java/org/tasks/sync/AddAccountDialog.kt @@ -67,6 +67,8 @@ class AddAccountDialog : DialogFragment() { 3 -> activity?.startActivityForResult( Intent(activity, EtebaseAccountSettingsActivity::class.java), REQUEST_CALDAV_SETTINGS) + 4 -> activity?.startActivity( + Intent(ACTION_VIEW, Uri.parse(getString(R.string.url_decsync)))) } dialog.dismiss() } diff --git a/app/src/main/res/drawable/ic_decsync.xml b/app/src/main/res/drawable/ic_decsync.xml new file mode 100644 index 000000000..51e0c19f3 --- /dev/null +++ b/app/src/main/res/drawable/ic_decsync.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index ca3b0e3d5..201110893 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -203,6 +203,7 @@ @string/davx5 @string/caldav @string/etesync + @string/decsync @@ -210,6 +211,7 @@ @string/davx5_selection_description @string/caldav_selection_description @string/etesync_selection_description + @string/decsync_selection_description @@ -217,6 +219,7 @@ @drawable/ic_davx5_icon_green_bg @drawable/ic_webdav_logo @drawable/ic_etesync + @drawable/ic_decsync diff --git a/app/src/main/res/values/keys.xml b/app/src/main/res/values/keys.xml index 5f6f4a02a..187a41fce 100644 --- a/app/src/main/res/values/keys.xml +++ b/app/src/main/res/values/keys.xml @@ -14,6 +14,7 @@ EteSync EteSync v1 DAVx⁵ + DecSync CC Tasks.org https://api.etesync.com https://api.etebase.com/partner/tasksorg/ @@ -22,6 +23,7 @@ https://tasks.org/davx5 https://tasks.org/caldav https://tasks.org/etesync + https://tasks.org/decsync https://tasks.org/help/tasker https://tasks.org/donate https://reddit.com/r/tasks diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e338184c9..2499c6d4b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -554,6 +554,7 @@ File %1$s contained %2$s.\n\n Basic service that synchronizes with your Google account Synchronization based on open internet standards Open source, end-to-end encrypted synchronization + Synchronize your tasks with the DecSync CC app Synchronize your tasks with the DAVx⁵ app Show advanced settings Requires an account with a CalDAV service provider or a self-hosted server. Find a service provider by visiting tasks.org/caldav