diff --git a/app/src/androidTest/java/org/tasks/data/DeletionDaoTests.kt b/app/src/androidTest/java/org/tasks/data/DeletionDaoTests.kt
index 95ac4f7b8..cc45b38da 100644
--- a/app/src/androidTest/java/org/tasks/data/DeletionDaoTests.kt
+++ b/app/src/androidTest/java/org/tasks/data/DeletionDaoTests.kt
@@ -9,8 +9,8 @@ import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test
import org.tasks.data.dao.CaldavDao
-import org.tasks.data.dao.CaldavDao.Companion.LOCAL
import org.tasks.data.dao.DeletionDao
+import org.tasks.data.entity.CaldavAccount
import org.tasks.data.entity.CaldavCalendar
import org.tasks.data.entity.CaldavTask
import org.tasks.date.DateTimeUtils.newDateTime
@@ -62,7 +62,8 @@ class DeletionDaoTests : InjectingTestCase() {
fun purgeDeletedLocalTask() = runBlocking {
val task = newTask(with(DELETION_TIME, newDateTime()))
taskDao.createNew(task)
- caldavDao.insert(CaldavCalendar(name = "", uuid = "1234", account = LOCAL))
+ caldavDao.insert(CaldavAccount(uuid = "abcd", accountType = CaldavAccount.TYPE_LOCAL))
+ caldavDao.insert(CaldavCalendar(name = "", uuid = "1234", account = "abcd"))
caldavDao.insert(CaldavTask(task = task.id, calendar = "1234"))
deletionDao.purgeDeleted()
@@ -74,7 +75,8 @@ class DeletionDaoTests : InjectingTestCase() {
fun dontPurgeActiveTasks() = runBlocking {
val task = newTask()
taskDao.createNew(task)
- caldavDao.insert(CaldavCalendar(name = "", uuid = "1234", account = LOCAL))
+ caldavDao.insert(CaldavAccount(uuid = "abcd", accountType = CaldavAccount.TYPE_LOCAL))
+ caldavDao.insert(CaldavCalendar(name = "", uuid = "1234", account = "abcd"))
caldavDao.insert(CaldavTask(task = task.id, calendar = "1234"))
deletionDao.purgeDeleted()
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 96871d96c..954258193 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -418,6 +418,10 @@
android:name=".caldav.CaldavAccountSettingsActivity"
android:theme="@style/Tasks"/>
+
+
diff --git a/app/src/main/java/com/todoroo/astrid/activity/MainActivity.kt b/app/src/main/java/com/todoroo/astrid/activity/MainActivity.kt
index da5d8cedf..3c3d69e62 100644
--- a/app/src/main/java/com/todoroo/astrid/activity/MainActivity.kt
+++ b/app/src/main/java/com/todoroo/astrid/activity/MainActivity.kt
@@ -11,8 +11,10 @@ import android.graphics.Color
import android.os.Bundle
import androidx.activity.SystemBarStyle
import androidx.activity.compose.BackHandler
+import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
+import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.view.ActionMode
@@ -31,13 +33,16 @@ import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.unit.dp
import androidx.core.content.IntentCompat.getParcelableExtra
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
+import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
+import androidx.navigation.toRoute
import com.todoroo.astrid.adapter.SubheaderClickHandler
import com.todoroo.astrid.dao.TaskDao
+import com.todoroo.astrid.gtasks.auth.GtasksLoginActivity
import com.todoroo.astrid.service.TaskCreator
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
@@ -45,22 +50,36 @@ import kotlinx.coroutines.runBlocking
import org.tasks.BuildConfig
import org.tasks.R
import org.tasks.analytics.Firebase
+import org.tasks.auth.SignInActivity
import org.tasks.billing.Inventory
+import org.tasks.caldav.CaldavAccountSettingsActivity
+import org.tasks.compose.AddAccountDestination
import org.tasks.compose.HomeDestination
+import org.tasks.compose.accounts.AddAccountScreen
+import org.tasks.compose.accounts.AddAccountViewModel
import org.tasks.compose.home.HomeScreen
import org.tasks.data.dao.AlarmDao
import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.LocationDao
import org.tasks.data.dao.TagDataDao
import org.tasks.data.entity.Task
+import org.tasks.dialogs.ImportTasksDialog
import org.tasks.dialogs.NewFilterDialog
+import org.tasks.etebase.EtebaseAccountSettingsActivity
import org.tasks.extensions.Context.nightMode
+import org.tasks.extensions.Context.toast
import org.tasks.extensions.broughtToFront
import org.tasks.extensions.flagsToString
import org.tasks.extensions.isFromHistory
+import org.tasks.files.FileHelper
import org.tasks.filters.Filter
+import org.tasks.jobs.WorkManager
import org.tasks.preferences.DefaultFilterProvider
import org.tasks.preferences.Preferences
+import org.tasks.preferences.fragments.FRAG_TAG_IMPORT_TASKS
+import org.tasks.sync.AddAccountDialog
+import org.tasks.sync.SyncAdapters
+import org.tasks.sync.microsoft.MicrosoftSignInViewModel
import org.tasks.themes.ColorProvider
import org.tasks.themes.TasksTheme
import org.tasks.themes.Theme
@@ -82,6 +101,8 @@ class MainActivity : AppCompatActivity() {
@Inject lateinit var alarmDao: AlarmDao
@Inject lateinit var firebase: Firebase
@Inject lateinit var caldavDao: CaldavDao
+ @Inject lateinit var syncAdapters: SyncAdapters
+ @Inject lateinit var workManager: WorkManager
private val viewModel: MainActivityViewModel by viewModels()
private var currentNightMode = 0
@@ -125,7 +146,7 @@ class MainActivity : AppCompatActivity() {
LaunchedEffect(hasAccount) {
Timber.d("hasAccount=$hasAccount")
if (hasAccount == false) {
- // TODO: navigate to add account screen
+ navController.navigate(AddAccountDestination(showImport = true))
}
isReady = hasAccount != null
}
@@ -133,7 +154,87 @@ class MainActivity : AppCompatActivity() {
navController = navController,
startDestination = HomeDestination,
) {
+ composable {
+ val route = it.toRoute()
+ LaunchedEffect(hasAccount) {
+ if (route.showImport && hasAccount == true) {
+ navController.popBackStack()
+ }
+ }
+ val addAccountViewModel: AddAccountViewModel = hiltViewModel()
+ val microsoftVM: MicrosoftSignInViewModel = hiltViewModel()
+ val syncLauncher =
+ rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
+ if (result.resultCode == RESULT_OK) {
+ syncAdapters.sync(true)
+ workManager.updateBackgroundSync()
+ } else {
+ result.data
+ ?.getStringExtra(GtasksLoginActivity.EXTRA_ERROR)
+ ?.let { toast(it) }
+ }
+ }
+ val importBackupLauncher =
+ rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
+ if (result.resultCode == RESULT_OK) {
+ val uri = result.data?.data ?: return@rememberLauncherForActivityResult
+ ImportTasksDialog.newImportTasksDialog(uri)
+ .show(supportFragmentManager, FRAG_TAG_IMPORT_TASKS)
+ }
+ }
+ AddAccountScreen(
+ gettingStarted = route.showImport,
+ hasTasksAccount = inventory.hasTasksAccount,
+ hasPro = inventory.hasPro,
+ onBack = { navController.popBackStack() },
+ signIn = { platform ->
+ firebase.logEvent(R.string.event_onboarding_sync, R.string.param_selection to platform)
+ when (platform) {
+ AddAccountDialog.Platform.TASKS_ORG ->
+ syncLauncher.launch(
+ Intent(this@MainActivity, SignInActivity::class.java)
+ )
+
+ AddAccountDialog.Platform.GOOGLE_TASKS ->
+ syncLauncher.launch(
+ Intent(this@MainActivity, GtasksLoginActivity::class.java)
+ )
+
+ AddAccountDialog.Platform.MICROSOFT ->
+ microsoftVM.signIn(this@MainActivity)
+
+ AddAccountDialog.Platform.CALDAV ->
+ syncLauncher.launch(
+ Intent(this@MainActivity, CaldavAccountSettingsActivity::class.java)
+ )
+
+ AddAccountDialog.Platform.ETESYNC ->
+ syncLauncher.launch(
+ Intent(this@MainActivity, EtebaseAccountSettingsActivity::class.java)
+ )
+
+ AddAccountDialog.Platform.LOCAL ->
+ addAccountViewModel.createLocalAccount()
+
+ else -> throw IllegalArgumentException()
+ }
+ },
+ openUrl = { platform ->
+ firebase.logEvent(R.string.event_onboarding_sync, R.string.param_selection to platform.name)
+ addAccountViewModel.openUrl(this@MainActivity, platform)
+ },
+ onImportBackup = {
+ firebase.logEvent(R.string.event_onboarding_sync, R.string.param_selection to "import_backup")
+ importBackupLauncher.launch(
+ FileHelper.newFilePickerIntent(this@MainActivity, preferences.backupDirectory),
+ )
+ }
+ )
+ }
composable {
+ if (hasAccount != true) {
+ return@composable
+ }
val scope = rememberCoroutineScope()
val state = viewModel.state.collectAsStateWithLifecycle().value
val drawerState = rememberDrawerState(
diff --git a/app/src/main/java/org/tasks/analytics/Constants.kt b/app/src/main/java/org/tasks/analytics/Constants.kt
index 39a7843ac..b27aa3926 100644
--- a/app/src/main/java/org/tasks/analytics/Constants.kt
+++ b/app/src/main/java/org/tasks/analytics/Constants.kt
@@ -9,4 +9,5 @@ object Constants {
const val SYNC_TYPE_ETEBASE = "etebase"
const val SYNC_TYPE_DECSYNC = "decsync"
const val SYNC_TYPE_MICROSOFT = "microsoft"
+ const val SYNC_TYPE_LOCAL = "local"
}
\ No newline at end of file
diff --git a/app/src/main/java/org/tasks/caldav/BaseCaldavAccountSettingsActivity.kt b/app/src/main/java/org/tasks/caldav/BaseCaldavAccountSettingsActivity.kt
index 453718cc7..a6062f790 100644
--- a/app/src/main/java/org/tasks/caldav/BaseCaldavAccountSettingsActivity.kt
+++ b/app/src/main/java/org/tasks/caldav/BaseCaldavAccountSettingsActivity.kt
@@ -36,6 +36,7 @@ import org.tasks.compose.ServerSelector
import org.tasks.data.dao.CaldavDao
import org.tasks.data.entity.CaldavAccount
import org.tasks.data.entity.CaldavAccount.Companion.SERVER_UNKNOWN
+import org.tasks.data.entity.CaldavAccount.Companion.TYPE_LOCAL
import org.tasks.data.entity.Task
import org.tasks.databinding.ActivityCaldavAccountSettingsBinding
import org.tasks.dialogs.DialogBuilder
@@ -116,7 +117,7 @@ abstract class BaseCaldavAccountSettingsActivity : ThemedInjectingAppCompatActiv
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(binding.name, InputMethodManager.SHOW_IMPLICIT)
}
- if (!inventory.hasPro) {
+ if (!inventory.hasPro && caldavAccount?.accountType != TYPE_LOCAL) {
newSnackbar(getString(R.string.this_feature_requires_a_subscription))
.setDuration(BaseTransientBottomBar.LENGTH_INDEFINITE)
.setAction(R.string.button_subscribe) {
@@ -308,7 +309,8 @@ abstract class BaseCaldavAccountSettingsActivity : ThemedInjectingAppCompatActiv
private fun newSnackbar(message: String?): Snackbar {
val snackbar = Snackbar.make(binding.rootLayout, message!!, 8000)
- .setTextColor(getColor(R.color.snackbar_text_color))
+ .setBackgroundTint(getColor(R.color.dialog_background))
+ .setTextColor(getColor(R.color.text_primary))
.setActionTextColor(getColor(R.color.snackbar_action_color))
snackbar
.view
@@ -341,7 +343,7 @@ abstract class BaseCaldavAccountSettingsActivity : ThemedInjectingAppCompatActiv
}
}
- private fun removeAccountPrompt() {
+ protected open suspend fun removeAccountPrompt() {
if (requestInProgress()) {
return
}
@@ -378,7 +380,9 @@ abstract class BaseCaldavAccountSettingsActivity : ThemedInjectingAppCompatActiv
override fun onMenuItemClick(item: MenuItem): Boolean {
when (item.itemId) {
R.id.menu_help -> openUri(helpUrl)
- R.id.remove -> removeAccountPrompt()
+ R.id.remove -> lifecycleScope.launch {
+ removeAccountPrompt()
+ }
}
return onOptionsItemSelected(item)
}
diff --git a/app/src/main/java/org/tasks/caldav/LocalAccountSettingsActivity.kt b/app/src/main/java/org/tasks/caldav/LocalAccountSettingsActivity.kt
new file mode 100644
index 000000000..febacd7a7
--- /dev/null
+++ b/app/src/main/java/org/tasks/caldav/LocalAccountSettingsActivity.kt
@@ -0,0 +1,90 @@
+package org.tasks.caldav
+
+import android.app.Activity
+import android.os.Bundle
+import android.view.View
+import androidx.appcompat.widget.Toolbar
+import androidx.lifecycle.lifecycleScope
+import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.launch
+import org.tasks.R
+import org.tasks.analytics.Constants
+import org.tasks.data.UUIDHelper
+import org.tasks.data.entity.CaldavAccount
+
+@AndroidEntryPoint
+class LocalAccountSettingsActivity : BaseCaldavAccountSettingsActivity(), Toolbar.OnMenuItemClickListener {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ binding.userLayout.visibility = View.GONE
+ binding.passwordLayout.visibility = View.GONE
+ binding.urlLayout.visibility = View.GONE
+ binding.serverSelector.visibility = View.GONE
+ }
+
+ override fun hasChanges() = newName != caldavAccount!!.name
+
+ override fun save() = lifecycleScope.launch {
+ if (newName.isBlank()) {
+ binding.nameLayout.error = getString(R.string.name_cannot_be_empty)
+ return@launch
+ }
+ updateAccount()
+ }
+
+ private suspend fun addAccount() {
+ caldavDao.insert(
+ CaldavAccount(
+ name = newName,
+ uuid = UUIDHelper.newUUID(),
+ )
+ )
+ firebase.logEvent(
+ R.string.event_sync_add_account,
+ R.string.param_type to Constants.SYNC_TYPE_LOCAL
+ )
+ setResult(Activity.RESULT_OK)
+ finish()
+ }
+
+ override suspend fun updateAccount() {
+ caldavAccount!!.name = newName
+ caldavDao.update(caldavAccount!!)
+ setResult(Activity.RESULT_OK)
+ finish()
+ }
+
+ override suspend fun addAccount(url: String, username: String, password: String) {
+ addAccount()
+ }
+
+ override suspend fun updateAccount(url: String, username: String, password: String) {
+ updateAccount()
+ }
+
+ override suspend fun removeAccountPrompt() {
+ val countTasks = caldavAccount?.uuid?.let { caldavDao.countTasks(it) } ?: 0
+ val countString = resources.getQuantityString(R.plurals.task_count, countTasks, countTasks)
+ dialogBuilder
+ .newDialog()
+ .setTitle(
+ R.string.delete_tag_confirmation,
+ caldavAccount?.name?.takeIf { it.isNotBlank() } ?: getString(R.string.local_lists)
+ )
+ .apply {
+ if (countTasks > 0) {
+ setMessage(R.string.delete_tasks_warning, countString)
+ } else {
+ setMessage(R.string.logout_warning)
+ }
+ }
+ .setPositiveButton(R.string.delete) { _, _ -> lifecycleScope.launch { removeAccount() } }
+ .setNegativeButton(R.string.cancel, null)
+ .show()
+ }
+
+ override val newPassword: String? = null
+
+ override val helpUrl = R.string.url_caldav
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/tasks/caldav/LocalListSettingsActivity.kt b/app/src/main/java/org/tasks/caldav/LocalListSettingsActivity.kt
index 87fe90983..47012d586 100644
--- a/app/src/main/java/org/tasks/caldav/LocalListSettingsActivity.kt
+++ b/app/src/main/java/org/tasks/caldav/LocalListSettingsActivity.kt
@@ -3,26 +3,20 @@ package org.tasks.caldav
import android.os.Bundle
import androidx.activity.compose.setContent
import dagger.hilt.android.AndroidEntryPoint
-import kotlinx.coroutines.runBlocking
import org.tasks.compose.DeleteButton
-import org.tasks.data.dao.CaldavDao
import org.tasks.data.entity.CaldavAccount
import org.tasks.data.entity.CaldavCalendar
import org.tasks.themes.TasksTheme
@AndroidEntryPoint
class LocalListSettingsActivity : BaseCaldavCalendarSettingsActivity() {
-
-
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- val canDelete = runBlocking { caldavDao.getCalendarsByAccount(CaldavDao.LOCAL).size > 1 }
-
setContent {
TasksTheme {
BaseCaldavSettingsContent (
- optionButton = { if (!isNew && canDelete) DeleteButton(caldavCalendar?.name ?: "") { delete() } }
+ optionButton = { if (!isNew) DeleteButton(caldavCalendar?.name ?: "") { delete() } }
)
}
}
@@ -37,4 +31,4 @@ class LocalListSettingsActivity : BaseCaldavCalendarSettingsActivity() {
override suspend fun deleteCalendar(caldavAccount: CaldavAccount, caldavCalendar: CaldavCalendar) =
onDeleted(true)
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/org/tasks/compose/AddAccountDialog.kt b/app/src/main/java/org/tasks/compose/AddAccountDialog.kt
index 9a06f6c98..de8c75250 100644
--- a/app/src/main/java/org/tasks/compose/AddAccountDialog.kt
+++ b/app/src/main/java/org/tasks/compose/AddAccountDialog.kt
@@ -16,7 +16,6 @@ import org.tasks.themes.TasksTheme
fun AddAccountDialog(
hasTasksAccount: Boolean,
hasPro: Boolean,
- enableMicrosoftSync: Boolean = true,
selected: (Platform) -> Unit,
) {
Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
@@ -36,15 +35,13 @@ fun AddAccountDialog(
icon = R.drawable.ic_google,
onClick = { selected(Platform.GOOGLE_TASKS) }
)
- if (enableMicrosoftSync) {
- SyncAccount(
- title = R.string.microsoft,
- cost = if (hasPro) null else R.string.cost_free,
- description = R.string.microsoft_selection_description,
- icon = R.drawable.ic_microsoft_tasks,
- onClick = { selected(Platform.MICROSOFT) }
- )
- }
+ SyncAccount(
+ title = R.string.microsoft,
+ cost = if (hasPro) null else R.string.cost_free,
+ description = R.string.microsoft_selection_description,
+ icon = R.drawable.ic_microsoft_tasks,
+ onClick = { selected(Platform.MICROSOFT) }
+ )
SyncAccount(
title = R.string.davx5,
cost = if (hasPro) null else R.string.cost_money,
diff --git a/app/src/main/java/org/tasks/compose/Destinations.kt b/app/src/main/java/org/tasks/compose/Destinations.kt
index a33d5f661..579b334a2 100644
--- a/app/src/main/java/org/tasks/compose/Destinations.kt
+++ b/app/src/main/java/org/tasks/compose/Destinations.kt
@@ -4,3 +4,6 @@ import kotlinx.serialization.Serializable
@Serializable
object HomeDestination
+
+@Serializable
+data class AddAccountDestination(val showImport: Boolean)
diff --git a/app/src/main/java/org/tasks/compose/accounts/AddAccountScreen.kt b/app/src/main/java/org/tasks/compose/accounts/AddAccountScreen.kt
new file mode 100644
index 000000000..5e3a8692f
--- /dev/null
+++ b/app/src/main/java/org/tasks/compose/accounts/AddAccountScreen.kt
@@ -0,0 +1,348 @@
+package org.tasks.compose.accounts
+
+import androidx.activity.compose.BackHandler
+import androidx.annotation.DrawableRes
+import androidx.annotation.StringRes
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.ExperimentalLayoutApi
+import androidx.compose.foundation.layout.FlowRow
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.automirrored.outlined.ArrowBack
+import androidx.compose.material.icons.automirrored.outlined.HelpOutline
+import androidx.compose.material.icons.outlined.Backup
+import androidx.compose.material.icons.outlined.CloudOff
+import androidx.compose.material3.Card
+import androidx.compose.material3.CardDefaults
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.OutlinedCard
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.SpanStyle
+import androidx.compose.ui.text.buildAnnotatedString
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.text.withStyle
+import androidx.compose.ui.tooling.preview.PreviewFontScale
+import androidx.compose.ui.tooling.preview.PreviewLightDark
+import androidx.compose.ui.tooling.preview.PreviewScreenSizes
+import androidx.compose.ui.unit.dp
+import org.tasks.R
+import org.tasks.sync.AddAccountDialog.Platform
+import org.tasks.themes.TasksTheme
+
+@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)
+@Composable
+fun AddAccountScreen(
+ gettingStarted: Boolean,
+ hasTasksAccount: Boolean,
+ hasPro: Boolean,
+ onBack: () -> Unit,
+ signIn: (Platform) -> Unit,
+ openUrl: (Platform) -> Unit,
+ onImportBackup: () -> Unit,
+) {
+ BackHandler {
+ if (!gettingStarted) {
+ onBack()
+ }
+ }
+ Scaffold(
+ topBar = {
+ TopAppBar(
+ colors = TopAppBarDefaults.topAppBarColors(),
+ navigationIcon = {
+ if (!gettingStarted) {
+ IconButton(onClick = onBack) {
+ Icon(
+ imageVector = Icons.AutoMirrored.Outlined.ArrowBack,
+ contentDescription = stringResource(R.string.back),
+ )
+ }
+ }
+ },
+ title = {
+ Text(
+ text = if (gettingStarted) {
+ stringResource(R.string.sign_in)
+ } else {
+ stringResource(R.string.add_account)
+ }
+ )
+ }
+ )
+ }
+ ) { paddingValues ->
+ Column(
+ modifier = Modifier
+ .padding(paddingValues)
+ .padding(vertical = 16.dp)
+ .fillMaxSize()
+ .verticalScroll(rememberScrollState()),
+ ) {
+ FlowRow(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.SpaceEvenly,
+ verticalArrangement = Arrangement.spacedBy(16.dp),
+ maxItemsInEachRow = 5
+ ) {
+ if (gettingStarted) {
+ ActionCard(
+ title = R.string.backup_BAc_import,
+ icon = Icons.Outlined.Backup,
+ onClick = onImportBackup,
+ isOutlined = true
+ )
+
+ ActionCard(
+ title = R.string.continue_without_sync,
+ icon = Icons.Outlined.CloudOff,
+ onClick = { signIn(Platform.LOCAL) },
+ isOutlined = true
+ )
+ }
+ if (!hasTasksAccount) {
+ AccountTypeCard(
+ title = R.string.tasks_org,
+ cost = R.string.cost_more_money,
+ icon = R.drawable.ic_round_icon,
+ onClick = { signIn(Platform.TASKS_ORG) }
+ )
+ }
+
+ AccountTypeCard(
+ title = R.string.microsoft,
+ cost = if (hasPro) null else R.string.cost_free,
+ icon = R.drawable.ic_microsoft_tasks,
+ onClick = { signIn(Platform.MICROSOFT) }
+ )
+
+ AccountTypeCard(
+ title = R.string.gtasks_GPr_header,
+ cost = if (hasPro) null else R.string.cost_free,
+ icon = R.drawable.ic_google,
+ onClick = { signIn(Platform.GOOGLE_TASKS) }
+ )
+
+ AccountTypeCard(
+ title = R.string.davx5,
+ cost = if (hasPro) null else R.string.cost_money,
+ icon = R.drawable.ic_davx5_icon_green_bg,
+ onClick = { openUrl(Platform.DAVX5) }
+ )
+
+ AccountTypeCard(
+ title = R.string.caldav,
+ cost = if (hasPro) null else R.string.cost_money,
+ icon = R.drawable.ic_webdav_logo,
+ tint = MaterialTheme.colorScheme.onSurface.copy(alpha = .8f),
+ onClick = { signIn(Platform.CALDAV) }
+ )
+
+ AccountTypeCard(
+ title = R.string.etesync,
+ cost = if (hasPro) null else R.string.cost_money,
+ icon = R.drawable.ic_etesync,
+ onClick = { signIn(Platform.ETESYNC) }
+ )
+
+ AccountTypeCard(
+ title = R.string.decsync,
+ cost = if (hasPro) null else R.string.cost_money,
+ icon = R.drawable.ic_decsync,
+ onClick = { openUrl(Platform.DECSYNC_CC) }
+ )
+
+ if (gettingStarted) {
+ ActionCard(
+ title = R.string.help_me_choose,
+ icon = Icons.AutoMirrored.Outlined.HelpOutline,
+ onClick = { openUrl(Platform.LOCAL) },
+ isOutlined = true
+ )
+ }
+ }
+ }
+ }
+}
+
+@Composable
+fun AccountTypeCard(
+ @StringRes title: Int,
+ @StringRes cost: Int? = null,
+ @DrawableRes icon: Int,
+ tint: Color? = null,
+ onClick: () -> Unit,
+) {
+ Card(
+ modifier = Modifier
+ .width(108.dp),
+ shape = MaterialTheme.shapes.medium,
+ elevation = CardDefaults.cardElevation(defaultElevation = 2.dp),
+ onClick = onClick
+ ) {
+ Column(
+ modifier = Modifier.padding(12.dp).fillMaxWidth(),
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ Icon(
+ painter = painterResource(id = icon),
+ contentDescription = stringResource(id = title),
+ tint = tint ?: Color.Unspecified,
+ modifier = Modifier.size(48.dp)
+ )
+
+ Spacer(modifier = Modifier.height(8.dp))
+
+ Text(
+ text = buildAnnotatedString {
+ append(stringResource(id = title))
+ cost?.let {
+ append("\n")
+ withStyle(
+ style = SpanStyle(
+ color = MaterialTheme.colorScheme.primary,
+ fontSize = MaterialTheme.typography.labelSmall.fontSize
+ )
+ ) {
+ append(stringResource(id = it))
+ }
+ }
+ },
+ style = MaterialTheme.typography.bodyMedium,
+ color = MaterialTheme.colorScheme.onSurface,
+ textAlign = TextAlign.Center,
+ minLines = 3,
+ maxLines = 3,
+ overflow = TextOverflow.Ellipsis,
+ )
+ }
+ }
+}
+
+@Composable
+fun ActionCard(
+ @StringRes title: Int,
+ icon: ImageVector,
+ onClick: () -> Unit,
+ isOutlined: Boolean = false
+) {
+ if (isOutlined) {
+ OutlinedCard(
+ modifier = Modifier
+ .width(108.dp),
+ shape = MaterialTheme.shapes.medium,
+ onClick = onClick
+ ) {
+ Column(
+ modifier = Modifier.padding(16.dp),
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ Icon(
+ imageVector = icon,
+ contentDescription = stringResource(id = title),
+ tint = MaterialTheme.colorScheme.primary,
+ modifier = Modifier.size(40.dp)
+ )
+
+ Spacer(modifier = Modifier.height(8.dp))
+
+ Text(
+ text = stringResource(id = title),
+ style = MaterialTheme.typography.bodyMedium,
+ color = MaterialTheme.colorScheme.onSurface,
+ textAlign = TextAlign.Center,
+ minLines = 3,
+ maxLines = 3,
+ overflow = TextOverflow.Ellipsis
+ )
+ }
+ }
+ } else {
+ Card(
+ modifier = Modifier
+ .width(150.dp),
+ shape = MaterialTheme.shapes.medium,
+ elevation = CardDefaults.cardElevation(defaultElevation = 2.dp),
+ onClick = onClick
+ ) {
+ Column(
+ modifier = Modifier.padding(16.dp),
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ Icon(
+ imageVector = icon,
+ contentDescription = stringResource(id = title),
+ tint = MaterialTheme.colorScheme.primary,
+ modifier = Modifier.size(40.dp)
+ )
+
+ Spacer(modifier = Modifier.height(8.dp))
+
+ Text(
+ text = stringResource(id = title),
+ style = MaterialTheme.typography.bodyMedium,
+ color = MaterialTheme.colorScheme.onSurface,
+ textAlign = TextAlign.Center,
+ maxLines = 2,
+ overflow = TextOverflow.Ellipsis
+ )
+ }
+ }
+ }
+}
+
+@PreviewLightDark
+@PreviewScreenSizes
+@PreviewFontScale
+@Composable
+fun GettingStartedPreview() {
+ TasksTheme {
+ AddAccountScreen(
+ gettingStarted = true,
+ hasTasksAccount = false,
+ hasPro = false,
+ onBack = {},
+ signIn = {},
+ openUrl = {},
+ onImportBackup = {},
+ )
+ }
+}
+
+@PreviewLightDark
+@Composable
+fun AddAccountPreview() {
+ TasksTheme {
+ AddAccountScreen(
+ gettingStarted = false,
+ hasTasksAccount = false,
+ hasPro = false,
+ onBack = {},
+ signIn = {},
+ openUrl = {},
+ onImportBackup = {},
+ )
+ }
+}
diff --git a/app/src/main/java/org/tasks/compose/accounts/AddAccountViewModel.kt b/app/src/main/java/org/tasks/compose/accounts/AddAccountViewModel.kt
new file mode 100644
index 000000000..9dc7ee676
--- /dev/null
+++ b/app/src/main/java/org/tasks/compose/accounts/AddAccountViewModel.kt
@@ -0,0 +1,32 @@
+package org.tasks.compose.accounts
+
+import android.content.Context
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.launch
+import org.tasks.R
+import org.tasks.data.dao.CaldavDao
+import org.tasks.data.newLocalAccount
+import org.tasks.extensions.Context.openUri
+import org.tasks.sync.AddAccountDialog
+import javax.inject.Inject
+
+@HiltViewModel
+class AddAccountViewModel @Inject constructor(
+ private val caldavDao: CaldavDao,
+) : ViewModel() {
+ fun createLocalAccount() = viewModelScope.launch {
+ caldavDao.newLocalAccount()
+ }
+
+ fun openUrl(context: Context, platform: AddAccountDialog.Platform) {
+ val url = when (platform) {
+ AddAccountDialog.Platform.DAVX5 -> R.string.url_davx5
+ AddAccountDialog.Platform.DECSYNC_CC -> R.string.url_decsync
+ AddAccountDialog.Platform.LOCAL -> R.string.help_url_sync
+ else -> return
+ }
+ context.openUri(context.getString(url))
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/tasks/data/CaldavAccountExtensions.kt b/app/src/main/java/org/tasks/data/CaldavAccountExtensions.kt
index 945aed3ee..ec853a187 100644
--- a/app/src/main/java/org/tasks/data/CaldavAccountExtensions.kt
+++ b/app/src/main/java/org/tasks/data/CaldavAccountExtensions.kt
@@ -7,6 +7,7 @@ import org.tasks.activities.GoogleTaskListSettingsActivity
import org.tasks.caldav.BaseCaldavAccountSettingsActivity
import org.tasks.caldav.CaldavAccountSettingsActivity
import org.tasks.caldav.CaldavCalendarSettingsActivity
+import org.tasks.caldav.LocalAccountSettingsActivity
import org.tasks.caldav.LocalListSettingsActivity
import org.tasks.data.OpenTaskDao.Companion.isDavx5
import org.tasks.data.OpenTaskDao.Companion.isDavx5Managed
@@ -29,6 +30,7 @@ val CaldavAccount.prefTitle: Int
uuid.isDecSync() -> R.string.decsync
isMicrosoft -> R.string.microsoft
isGoogleTasks -> R.string.gtasks_GPr_header
+ isLocalList -> R.string.local_lists
else -> 0
}
@@ -42,6 +44,7 @@ val CaldavAccount.prefIcon: Int
uuid.isDecSync() -> R.drawable.ic_decsync
isMicrosoft -> R.drawable.ic_microsoft_tasks
isGoogleTasks -> R.drawable.ic_google
+ isLocalList -> R.drawable.ic_outline_cloud_off_24px
else -> 0
}
@@ -66,6 +69,7 @@ val CaldavAccount.accountSettingsClass: Class CaldavAccountSettingsActivity::class.java
isEtebaseAccount -> EtebaseAccountSettingsActivity::class.java
isOpenTasks -> OpenTaskAccountSettingsActivity::class.java
+ isLocalList -> LocalAccountSettingsActivity::class.java
else -> throw IllegalArgumentException("Unexpected account type: $this")
}
diff --git a/app/src/main/java/org/tasks/filters/PreferenceDrawerConfiguration.kt b/app/src/main/java/org/tasks/filters/PreferenceDrawerConfiguration.kt
index 766ea00ba..5447f4da0 100644
--- a/app/src/main/java/org/tasks/filters/PreferenceDrawerConfiguration.kt
+++ b/app/src/main/java/org/tasks/filters/PreferenceDrawerConfiguration.kt
@@ -27,7 +27,4 @@ class PreferenceDrawerConfiguration(
override val recentlyModifiedFilter: Boolean
get() = preferences.getBoolean(R.string.p_show_recently_modified_filter, super.recentlyModifiedFilter)
-
- override val localListsEnabled: Boolean
- get() = preferences.getBoolean(R.string.p_lists_enabled, super.localListsEnabled)
}
\ No newline at end of file
diff --git a/app/src/main/java/org/tasks/jobs/MigrateLocalWork.kt b/app/src/main/java/org/tasks/jobs/MigrateLocalWork.kt
index 1ed084b40..bd24b8ce2 100644
--- a/app/src/main/java/org/tasks/jobs/MigrateLocalWork.kt
+++ b/app/src/main/java/org/tasks/jobs/MigrateLocalWork.kt
@@ -3,14 +3,14 @@ package org.tasks.jobs
import android.content.Context
import androidx.hilt.work.HiltWorker
import androidx.work.WorkerParameters
+import com.todoroo.astrid.service.TaskDeleter
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
-import org.tasks.R
import org.tasks.analytics.Firebase
import org.tasks.caldav.CaldavClientProvider
import org.tasks.data.dao.CaldavDao
+import org.tasks.data.entity.CaldavAccount
import org.tasks.injection.BaseWorker
-import org.tasks.preferences.Preferences
import org.tasks.sync.SyncAdapters
@HiltWorker
@@ -20,14 +20,18 @@ class MigrateLocalWork @AssistedInject constructor(
firebase: Firebase,
private val clientProvider: CaldavClientProvider,
private val caldavDao: CaldavDao,
- private val preferences: Preferences,
- private val syncAdapters: SyncAdapters
+ private val syncAdapters: SyncAdapters,
+ private val taskDeleter: TaskDeleter,
) : BaseWorker(context, workerParams, firebase) {
override suspend fun run(): Result {
val uuid = inputData.getString(EXTRA_ACCOUNT) ?: return Result.failure()
val caldavAccount = caldavDao.getAccountByUuid(uuid) ?: return Result.failure()
val caldavClient = clientProvider.forAccount(caldavAccount)
- caldavDao.getCalendarsByAccount(CaldavDao.LOCAL).forEach {
+ val fromAccount = caldavDao
+ .getAccounts(CaldavAccount.TYPE_LOCAL)
+ .firstOrNull()
+ ?: return Result.success()
+ caldavDao.getCalendarsByAccount(fromAccount.uuid!!).forEach {
caldavDao.update(
it.copy(
url = caldavClient.makeCollection(it.name!!, it.color),
@@ -35,7 +39,7 @@ class MigrateLocalWork @AssistedInject constructor(
)
)
}
- preferences.setBoolean(R.string.p_lists_enabled, false)
+ taskDeleter.delete(fromAccount)
syncAdapters.sync()
return Result.success()
}
diff --git a/app/src/main/java/org/tasks/preferences/DefaultFilterProvider.kt b/app/src/main/java/org/tasks/preferences/DefaultFilterProvider.kt
index bc72bbc80..f86996191 100644
--- a/app/src/main/java/org/tasks/preferences/DefaultFilterProvider.kt
+++ b/app/src/main/java/org/tasks/preferences/DefaultFilterProvider.kt
@@ -11,8 +11,6 @@ import org.tasks.data.dao.TagDataDao
import org.tasks.data.entity.CaldavCalendar.Companion.ACCESS_READ_ONLY
import org.tasks.data.entity.CaldavTask
import org.tasks.data.entity.Task
-import org.tasks.data.getLocalAccount
-import org.tasks.data.getLocalList
import org.tasks.filters.CaldavFilter
import org.tasks.filters.CustomFilter
import org.tasks.filters.Filter
@@ -92,7 +90,7 @@ class DefaultFilterProvider @Inject constructor(
?.let { caldavDao.getAccountByUuid(it) }
?.let { account -> CaldavFilter(calendar = list, account = account) }
}
- ?: CaldavFilter(calendar = caldavDao.getLocalList(), account = caldavDao.getLocalAccount())
+ ?: throw IllegalStateException()
defaultList = filter
return filter
}
diff --git a/app/src/main/java/org/tasks/preferences/PreferencesViewModel.kt b/app/src/main/java/org/tasks/preferences/PreferencesViewModel.kt
index 13e9f7919..e280b6ea7 100644
--- a/app/src/main/java/org/tasks/preferences/PreferencesViewModel.kt
+++ b/app/src/main/java/org/tasks/preferences/PreferencesViewModel.kt
@@ -17,7 +17,6 @@ import org.tasks.R
import org.tasks.backup.BackupConstants
import org.tasks.data.dao.CaldavDao
import org.tasks.data.entity.CaldavAccount
-import org.tasks.data.entity.CaldavAccount.Companion.TYPE_LOCAL
import org.tasks.date.DateTimeUtils.newDateTime
import org.tasks.googleapis.InvokerFactory
import org.tasks.gtasks.GoogleAccountManager
@@ -38,7 +37,7 @@ class PreferencesViewModel @Inject constructor(
val lastDriveBackup = MutableLiveData()
val lastAndroidBackup = MutableLiveData()
val caldavAccounts: Flow>
- get() = caldavDao.watchAccounts(exclude = listOf(TYPE_LOCAL))
+ get() = caldavDao.watchAccounts()
private fun isStale(timestamp: Long?) =
timestamp != null
diff --git a/app/src/main/java/org/tasks/preferences/fragments/Backups.kt b/app/src/main/java/org/tasks/preferences/fragments/Backups.kt
index dffd5226f..3f6416628 100644
--- a/app/src/main/java/org/tasks/preferences/fragments/Backups.kt
+++ b/app/src/main/java/org/tasks/preferences/fragments/Backups.kt
@@ -27,7 +27,7 @@ const val REQUEST_DRIVE_BACKUP = 12002
private const val REQUEST_PICKER = 10003
private const val REQUEST_BACKUP_NOW = 10004
private const val FRAG_TAG_EXPORT_TASKS = "frag_tag_export_tasks"
-private const val FRAG_TAG_IMPORT_TASKS = "frag_tag_import_tasks"
+const val FRAG_TAG_IMPORT_TASKS = "frag_tag_import_tasks"
@AndroidEntryPoint
class Backups : InjectingPreferenceFragment() {
diff --git a/app/src/main/java/org/tasks/preferences/fragments/MainSettingsFragment.kt b/app/src/main/java/org/tasks/preferences/fragments/MainSettingsFragment.kt
index d0b484c32..b51998860 100644
--- a/app/src/main/java/org/tasks/preferences/fragments/MainSettingsFragment.kt
+++ b/app/src/main/java/org/tasks/preferences/fragments/MainSettingsFragment.kt
@@ -136,6 +136,8 @@ class MainSettingsFragment : InjectingPreferenceFragment() {
)
Platform.DECSYNC_CC ->
context?.openUri(R.string.url_decsync)
+
+ Platform.LOCAL -> {}
}
}
}
@@ -160,13 +162,6 @@ class MainSettingsFragment : InjectingPreferenceFragment() {
})
}
preferenceScreen.removeAt(current, index - current)
- if (caldavAccounts.isEmpty()) {
- addAccount.setTitle(R.string.not_signed_in)
- addAccount.setIcon(R.drawable.ic_outline_cloud_off_24px)
- } else {
- addAccount.setTitle(R.string.add_account)
- addAccount.setIcon(R.drawable.ic_outline_add_24px)
- }
tintIcons(addAccount, requireContext().getColor(R.color.icon_tint_with_alpha))
}
@@ -210,7 +205,7 @@ class MainSettingsFragment : InjectingPreferenceFragment() {
pref.setTitle(account.prefTitle)
pref.summary = account.name
pref.setIcon(account.prefIcon)
- if (account.isCaldavAccount) {
+ if (account.isCaldavAccount || account.isLocalList) {
tintIcons(pref, requireContext().getColor(R.color.icon_tint_with_alpha))
}
pref.setOnPreferenceClickListener {
diff --git a/app/src/main/java/org/tasks/preferences/fragments/TasksAccount.kt b/app/src/main/java/org/tasks/preferences/fragments/TasksAccount.kt
index 2985a1827..ec3e8d206 100644
--- a/app/src/main/java/org/tasks/preferences/fragments/TasksAccount.kt
+++ b/app/src/main/java/org/tasks/preferences/fragments/TasksAccount.kt
@@ -22,7 +22,6 @@ import org.tasks.auth.SignInActivity
import org.tasks.auth.SignInActivity.Platform
import org.tasks.billing.Inventory
import org.tasks.billing.Purchase
-import org.tasks.data.dao.CaldavDao
import org.tasks.data.entity.CaldavAccount
import org.tasks.data.entity.CaldavAccount.Companion.isPaymentRequired
import org.tasks.extensions.Context.openUri
@@ -203,7 +202,8 @@ class TasksAccount : BaseAccountPreference() {
}
lifecycleScope.launch {
- val listCount = caldavDao.listCount(CaldavDao.LOCAL)
+ val localAccount = caldavDao.getAccounts(CaldavAccount.TYPE_LOCAL).firstOrNull()
+ val listCount = localAccount?.uuid?.let { caldavDao.listCount(it) } ?: 0
val quantityString = resources.getQuantityString(R.plurals.list_count, listCount, listCount)
findPreference(R.string.migrate).isVisible = listCount > 0
findPreference(R.string.local_lists).summary =
diff --git a/app/src/main/java/org/tasks/sync/AddAccountDialog.kt b/app/src/main/java/org/tasks/sync/AddAccountDialog.kt
index 16af244f3..2f6b33d1d 100644
--- a/app/src/main/java/org/tasks/sync/AddAccountDialog.kt
+++ b/app/src/main/java/org/tasks/sync/AddAccountDialog.kt
@@ -7,6 +7,7 @@ import androidx.fragment.app.DialogFragment
import androidx.fragment.app.setFragmentResult
import dagger.hilt.android.AndroidEntryPoint
import org.tasks.R
+import org.tasks.compose.AddAccountDialog
import org.tasks.dialogs.DialogBuilder
import org.tasks.extensions.Context.openUri
import org.tasks.preferences.Preferences
@@ -34,7 +35,8 @@ class AddAccountDialog : DialogFragment() {
DAVX5,
CALDAV,
ETESYNC,
- DECSYNC_CC
+ DECSYNC_CC,
+ LOCAL,
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
@@ -46,9 +48,8 @@ class AddAccountDialog : DialogFragment() {
theme = theme.themeBase.index,
primary = theme.themeColor.primaryColor,
) {
- org.tasks.compose.AddAccountDialog(
+ AddAccountDialog(
hasTasksAccount = hasTasksAccount,
- enableMicrosoftSync = preferences.getBoolean(R.string.p_microsoft_sync, false),
hasPro = hasPro,
selected = this::selected
)
diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml
index 87a25eb25..a8067639c 100644
--- a/app/src/main/res/values-ar/strings.xml
+++ b/app/src/main/res/values-ar/strings.xml
@@ -481,7 +481,6 @@
راعي
يستلزم التوثيق
رعاة GitHub
- لم تسجل الدخول
تم إلغاء التخويل
تعقب المشكلة
انضم إلى #tasks على Libera Chat
diff --git a/app/src/main/res/values-bg-rBG/strings.xml b/app/src/main/res/values-bg-rBG/strings.xml
index 6eb9a9674..22837f35c 100644
--- a/app/src/main/res/values-bg-rBG/strings.xml
+++ b/app/src/main/res/values-bg-rBG/strings.xml
@@ -641,7 +641,6 @@
Всички приложения, които използват паролата ще бъдат отписани
Използвайте тези данни за вход за настройка на друго приложение. Те дават пълен достъп до профила ви в Tasks.org за това не ги записвайте никъде и не ги споделяйте с никого!
Синхронизирайте задачите и календарите си с други настолни и мобилни приложения. Докоснете за повече информация
- Не сте вписани
Недостатъчно ниво на абонамент. За да бъде възстановена услугата надстройте своя абонамент.
Удостоверяването е спряно
Местоположение във фонов режим
diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml
index ee0c5c808..64e477316 100644
--- a/app/src/main/res/values-cs/strings.xml
+++ b/app/src/main/res/values-cs/strings.xml
@@ -578,7 +578,6 @@
Přihlášení přes Google
sponzoři na GitHubu
předplatitelé Google Play
- Nepřihlášeni
Autorizace zrušena
Soukromí
Otevřený zdrojový kód
diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml
index 461d23315..fcdfca0fe 100644
--- a/app/src/main/res/values-da/strings.xml
+++ b/app/src/main/res/values-da/strings.xml
@@ -515,7 +515,6 @@
Log ind med Google
GitHub-sponsorer
Google Play-abonnenter
- Ikke logget ind
Autorisation annulleret
Følg r/tasks
Nuværende abonnement: %s
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index 972b8d8cd..6e472509d 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -543,7 +543,6 @@
Mit GitHub anmelden
GitHub-Sponsoren
Google Play-Abonnenten
- Nicht angemeldet
Autorisierung abgebrochen
Mit Google anmelden
Nicht im „Wähle deinen Preis“-Abonnement enthalten
diff --git a/app/src/main/res/values-eo/strings.xml b/app/src/main/res/values-eo/strings.xml
index 29a727948..27240733d 100644
--- a/app/src/main/res/values-eo/strings.xml
+++ b/app/src/main/res/values-eo/strings.xml
@@ -611,7 +611,6 @@
Ŝpari je %d%%
%1$s ne plu povos atingi %2$s
Komunigi liston
- Ne ensalutinte
Fenestraĵa ID: %d
Komenci %s
Malfermi liston de laste rigardita
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index 41c8ef5ff..ba5503019 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -556,7 +556,6 @@
Acceder con GitHub
Patrocinadores de GitHub
Suscriptores de Google Play
- No registrado
No se encontró ninguna suscripción de Google Play elegible
No se encontró ningún patrocinio de GitHub elegible
Por encima del promedio
diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml
index e9f4b969b..2967e5cce 100644
--- a/app/src/main/res/values-et/strings.xml
+++ b/app/src/main/res/values-et/strings.xml
@@ -491,7 +491,6 @@
Kolmandate osapoolte litsentsid
Ütle oma hind
Peida kasutamata asukohad
- Ei ole sisse logitud
Viimati kasutatud: %s
Kutse ootab vastust
Esita lõpetamise heli
diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml
index 1785ac596..0ab8516d7 100644
--- a/app/src/main/res/values-eu/strings.xml
+++ b/app/src/main/res/values-eu/strings.xml
@@ -555,7 +555,6 @@
Autentifikazioa derrigorrezkoa
Hasi saioa GitHub erabiliz
Google Play harpideak
- Saioa hasi gabe
Ez da Google Play harpidetza egokirik aurkitu
Ez da GitHub sponsorship egokirik aurkitu
Zerrenda lokalak
diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml
index 8da091712..4ce60adbd 100644
--- a/app/src/main/res/values-fi/strings.xml
+++ b/app/src/main/res/values-fi/strings.xml
@@ -585,7 +585,6 @@
Astrid manuaalinen lajittelu
GitHubin sponsorit
Google Play -tilaajat
- Ei kirjautunut sisään
Lupa peruutettu
yksityisyys
Avoin lähdekoodi
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 82386b59c..afcdd98d4 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -561,7 +561,6 @@
Connectez-vous avec « GitHub »
Parrains « GitHub »
Abonnés « Google Play »
- Non connecté
Aucun abonnement « Google Play » éligible n\'a été trouvé
Aucun parrainage « GitHub » éligible n\'a été trouvé
Au dessus de la moyenne
diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml
index 70f746b7a..e5574245b 100644
--- a/app/src/main/res/values-gl/strings.xml
+++ b/app/src/main/res/values-gl/strings.xml
@@ -512,7 +512,6 @@
Ten un recordatorio
$%s/mes
Cancelouse a autenticación
- Sen acceso
Por riba da media
Gardar %d%%
Contrasinal da app
diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml
index ebc0ce8ef..ce42273de 100644
--- a/app/src/main/res/values-hr/strings.xml
+++ b/app/src/main/res/values-hr/strings.xml
@@ -139,7 +139,6 @@
Popisi na uređaju
Pomoć
Odaberi platformu
- Nisi prijavljen/a
Kontaktiraj programera
Sakrij nekorištena mjesta
Postavke mjesta
diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml
index a0defeedb..34d9e1870 100644
--- a/app/src/main/res/values-hu/strings.xml
+++ b/app/src/main/res/values-hu/strings.xml
@@ -539,7 +539,6 @@
Bejelentkezés GitHub fiókkal
GitHub szponzorok
Google Play előfizetők
- Nincs bejelentkezve
Nem található Google Play előfizetés
Nem található GitHub szponzorálás
Mentés %d%%
diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml
index c93e21876..a767a0985 100644
--- a/app/src/main/res/values-id/strings.xml
+++ b/app/src/main/res/values-id/strings.xml
@@ -441,7 +441,6 @@
Masuk dengan Google
Sponsor GitHub
Pelanggan Google Play
- Tidak masuk
Otorisasi dibatalkan
Gabung r/tasks
Langganan saat ini: %s
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index b1f63b93a..4d6fbe316 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -556,7 +556,6 @@
Accedi con GitHub
Sponsor di GitHub
Abbonati a Google Play
- Accesso non eseguito
Nessun abbonamento Google Play idoneo trovato
Nessuna sponsorizzazione GitHub idonea trovata
Sincronizzazione basata sui file
diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml
index a7a65b2e8..869f83ec8 100644
--- a/app/src/main/res/values-iw/strings.xml
+++ b/app/src/main/res/values-iw/strings.xml
@@ -565,7 +565,6 @@
להיכנס באמצעות Google
נותני חסות GitHub
מנויי Google Play
- לא מחובר
הרשאה בוטלה
לא נמצא מינוי Google Play זכאי
לא נמצאה חסות GitHub זכאית
diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml
index fe41abd94..015007c62 100644
--- a/app/src/main/res/values-ja/strings.xml
+++ b/app/src/main/res/values-ja/strings.xml
@@ -561,7 +561,6 @@
Issue tracker / 問題追跡
プライバシー
認証が取り消されました
- サインインしていません
Tasks.org のアカウントが必要です
「価格はあなた次第」でのサブスクリプションには含まれていません
リストメンバー
diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml
index 69c894fe2..f41d1f630 100644
--- a/app/src/main/res/values-ko/strings.xml
+++ b/app/src/main/res/values-ko/strings.xml
@@ -521,7 +521,6 @@
구글을 이용해서 로그인
깃허브 후원자
구글 플레이 구독자
- 로그인 되어있지 않음
r/tasks 구독
적합한 구글 플레이 구독을 찾을 수 없습니다
적합한 깃허브 후원 자격을 찾을 수 없습니다
diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml
index d3edb7f54..109474eab 100644
--- a/app/src/main/res/values-lt/strings.xml
+++ b/app/src/main/res/values-lt/strings.xml
@@ -566,7 +566,6 @@
Programėlių slaptažodžiai
Programėlės slaptažodis
Autentifikacija privaloma
- Neprisijungta
Autorizavimas atšauktas
Privatumas
Atviras kodas
diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml
index 074a7f445..4896b7a20 100644
--- a/app/src/main/res/values-nb/strings.xml
+++ b/app/src/main/res/values-nb/strings.xml
@@ -542,7 +542,6 @@
Fant ikke noe GitHub-sponsorabonnement
Flytt %s til Tasks.org
Logg inn med GitHub
- Ikke innlogget
- %d liste
- %d lister
diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml
index ba35e06bd..467b90326 100644
--- a/app/src/main/res/values-nl/strings.xml
+++ b/app/src/main/res/values-nl/strings.xml
@@ -539,7 +539,6 @@
GitHub sponsors
Google Play abonnees
Log in met GitHub
- Niet ingelogd
Geen in aanmerking komend Google Play abonnement gevonden
Geen in aanmerking komend GitHub-sponsoring gevonden
Bespaar %d%%
diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
index 608442b43..0e1321f5d 100644
--- a/app/src/main/res/values-pl/strings.xml
+++ b/app/src/main/res/values-pl/strings.xml
@@ -538,7 +538,6 @@
Wymagane uwierzytelnienie
Zaloguj z GitHub
Zaloguj z Google
- Niezalogowany
piąty
- %d lista
diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml
index 0a578be40..1e73fa2eb 100644
--- a/app/src/main/res/values-pt-rBR/strings.xml
+++ b/app/src/main/res/values-pt-rBR/strings.xml
@@ -592,7 +592,6 @@
Faça login com Google
Patrocinadores do GitHub
Assinantes do Google Play
- Não autenticado
Autorização cancelada
Privacidade
Código aberto
diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml
index 1951ababf..a23ab86ed 100644
--- a/app/src/main/res/values-pt/strings.xml
+++ b/app/src/main/res/values-pt/strings.xml
@@ -558,7 +558,6 @@
Iniciar sessão com o Google
Patrocinadores do GitHub
Subscritores do Google Play
- Não autenticado
Privacidade
Código-fonte aberto
Reportar problemas
diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml
index 6630833f5..bcb6c2ed0 100644
--- a/app/src/main/res/values-ro/strings.xml
+++ b/app/src/main/res/values-ro/strings.xml
@@ -55,7 +55,6 @@
Conectează-te cu Google
Sponsorii GitHub
Abonații Google Play
- Nu este conectat
Autorizație anulată
Confidențialitate
Sursă deschisă
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 79d70d6f7..19176c88e 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -550,7 +550,6 @@
Войти через Google
Спонсоры GitHub
Подписчики Google Play
- Не авторизован
Авторизация отменена
Подходящей подписки Google Play не найдено
Подходящее спонсорство GitHub не найдено
diff --git a/app/src/main/res/values-si/strings.xml b/app/src/main/res/values-si/strings.xml
index 297933ad8..d4979b309 100644
--- a/app/src/main/res/values-si/strings.xml
+++ b/app/src/main/res/values-si/strings.xml
@@ -91,7 +91,6 @@
GitHub සමඟ පුරනය වන්න
GitHub අනුග්රාහකයන්
Google Play ග්රාහකයින්
- පුරනය වී නොමැත
අවසරය අවලංගු කරන ලදි
පෞද්ගලිකත්වය
විවෘත මූලාශ්රය
diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml
index 95e00c096..f29e45fce 100644
--- a/app/src/main/res/values-sk/strings.xml
+++ b/app/src/main/res/values-sk/strings.xml
@@ -685,7 +685,6 @@
Bez nastavenej dôležitosti
Bez štítkov
Súkromie
- Neprihlásený
%s pred termínom
Dokumentácia
Viac farieb
diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml
index a1eabf909..7a922d881 100644
--- a/app/src/main/res/values-sv/strings.xml
+++ b/app/src/main/res/values-sv/strings.xml
@@ -468,7 +468,6 @@
Logga in med Google
GitHub-sponsorer
Google Play-prenumeranter
- Inte inloggad
Auktorisationen upphävd
Integritet
Öppen källkod
diff --git a/app/src/main/res/values-ta/strings.xml b/app/src/main/res/values-ta/strings.xml
index 1a718b404..57c7d3693 100644
--- a/app/src/main/res/values-ta/strings.xml
+++ b/app/src/main/res/values-ta/strings.xml
@@ -682,7 +682,6 @@
தொடக்கத்திற்குப் பிறகு %s
குறிச்சொற்கள், வடிப்பான்கள் அல்லது இடங்களுக்கு கிடைக்கவில்லை
ஏற்பு ரத்து செய்யப்பட்டது
- உள்நுழையவில்லை
சராசரிக்கு மேல்
பயன்பாட்டு கடவுச்சொற்கள்
Tasks.org உடன் ஒத்திசைத்து பிற பயனர்களுடன் ஒத்துழைக்கவும்
diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml
index f3fb740d0..c1cd31adb 100644
--- a/app/src/main/res/values-th/strings.xml
+++ b/app/src/main/res/values-th/strings.xml
@@ -81,7 +81,6 @@
ออกจากระบบ
คุณลักษณะนี้ต้องการการสมัครใช้งาน
ไม่สามารถเชื่อมต่อได้
- ไม่ได้ลงชื่อเข้าใช้
ยกเลิกการตรวจสอบแล้ว
ข้อมูลส่วนบุคคล
เปิดแหล่งที่มา
diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml
index 1fb44bedd..d2c41668d 100644
--- a/app/src/main/res/values-tr/strings.xml
+++ b/app/src/main/res/values-tr/strings.xml
@@ -539,7 +539,6 @@
GitHub ile oturum aç
GitHub Sponsorları
Google Play aboneleri
- Oturum açılmadı
Uygun Google Play aboneliği bulunamadı
Uygun GitHub sponsorluğu bulunamadı
%%%d tasarruf
diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml
index a7b8d0731..6d3137f9f 100644
--- a/app/src/main/res/values-uk/strings.xml
+++ b/app/src/main/res/values-uk/strings.xml
@@ -478,7 +478,6 @@
Увійти через Google
Спонсори GitHub
Підписники Google Play
- Не авторизовані
Авторизацію скасовано
Долучитися до r/tasks
Поточна підписка: %s
diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml
index 1af347a6c..25674c0bc 100644
--- a/app/src/main/res/values-vi/strings.xml
+++ b/app/src/main/res/values-vi/strings.xml
@@ -100,7 +100,6 @@
Đăng nhập bằng Google
Người đăng ký trên Google Play
Nhà tài trợ trên GitHub
- Chưa đăng nhập
Đã huỷ xác thực
Riêng tư
Mã nguồn mở
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index 1eada7492..717d71f01 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -533,7 +533,6 @@
使用 GitHub 登录
Github 赞助者
Google Play 订阅者
- 未登录
找不到符合要求的 Google Play 订阅
找不到符合要求的 GitHub 赞助
高于平均
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
index 324baa846..d06aeb4f3 100644
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -287,7 +287,6 @@
使用 Google 登入
GitHub 贊助者
Goole Play 訂閱者
- 未登入
取消授權
目前訂閱: %s
$%s/每月
diff --git a/app/src/main/res/values/keys.xml b/app/src/main/res/values/keys.xml
index d890de343..3f97b3338 100644
--- a/app/src/main/res/values/keys.xml
+++ b/app/src/main/res/values/keys.xml
@@ -13,7 +13,7 @@
DAVx⁵
DecSync CC
Tasks.org
- Microsoft To Do
+ Microsoft To Do
https://api.etebase.com/partner/tasksorg/
https://tasks.org/sync
ownCloud
@@ -99,7 +99,6 @@
drawer_tags_enabled
drawer_tags_hide_unused
drawer_places_enabled
- drawer_lists_enabled
drawer_places_hide_unused
@@ -411,6 +410,7 @@
result
state
click
+ selection
cp_todoagenda
cp_astrid2taskprovider
sync_add_account
@@ -422,6 +422,7 @@
request_review
create_shortcut
create_widget
+ onboarding_sync
type
picker_mode_date
picker_mode_time
@@ -429,7 +430,6 @@
completed_tasks_at_bottom
shown_beast_mode_hint
last_sync_time
- microsoft_sync
multiline_title
dynamic_color
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index dd1b3fa9b..289cbbeb3 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -411,6 +411,8 @@ File %1$s contained %2$s.\n\n
Copy selected tasks?
Date and time
Add account
+ Continue without sync
+ Help me choose
User
Password
URL
@@ -479,6 +481,7 @@ File %1$s contained %2$s.\n\n
Requires pro subscription
This feature requires a subscription
Log out
+ %s will be deleted. This cannot be undone!
All data for this account will be removed from your device
Cannot access account
Reinitialize
@@ -638,7 +641,6 @@ File %1$s contained %2$s.\n\n
Open source
Privacy
Authorization cancelled
- Not signed in
Google Play subscribers
GitHub Sponsors
Sign in with Google
diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml
index 4f5b44302..423cb1df3 100644
--- a/app/src/main/res/xml/preferences.xml
+++ b/app/src/main/res/xml/preferences.xml
@@ -4,8 +4,9 @@
xmlns:tools="http://schemas.android.com/tools">
+ android:key="@string/add_account"
+ android:title="@string/add_account"
+ app:icon="@drawable/ic_outline_add_24px" />
-
-
-
-
-
-
\ No newline at end of file
diff --git a/data/src/commonMain/kotlin/org/tasks/data/dao/CaldavDao.kt b/data/src/commonMain/kotlin/org/tasks/data/dao/CaldavDao.kt
index 9a5de8869..04537449c 100644
--- a/data/src/commonMain/kotlin/org/tasks/data/dao/CaldavDao.kt
+++ b/data/src/commonMain/kotlin/org/tasks/data/dao/CaldavDao.kt
@@ -66,13 +66,12 @@ abstract class CaldavDao {
@Query("""
SELECT *
FROM caldav_accounts
-WHERE cda_account_type NOT IN (:exclude)
ORDER BY CASE cda_account_type
WHEN $TYPE_TASKS THEN 0
ELSE 1
END, UPPER(cda_name)
""")
- abstract fun watchAccounts(exclude: List = emptyList()): Flow>
+ abstract fun watchAccounts(): Flow>
@Query("""
SELECT *
@@ -416,9 +415,16 @@ ORDER BY primary_sort
@Insert(onConflict = OnConflictStrategy.REPLACE)
abstract suspend fun insertOrReplace(googleTaskList: CaldavCalendar): Long
- companion object {
- const val LOCAL = "local"
+ @Query("""
+ SELECT COUNT(*)
+ FROM caldav_tasks
+ INNER JOIN caldav_lists ON cd_calendar = cdl_uuid
+ WHERE cdl_account = :account
+ AND cd_deleted = 0
+ """)
+ abstract suspend fun countTasks(account: String): Int
+ companion object {
fun Long.toAppleEpoch(): Long = (this - APPLE_EPOCH) / 1000
}
}
\ No newline at end of file
diff --git a/data/src/commonMain/kotlin/org/tasks/data/dao/DeletionDao.kt b/data/src/commonMain/kotlin/org/tasks/data/dao/DeletionDao.kt
index 9e78ac63e..09a494c30 100644
--- a/data/src/commonMain/kotlin/org/tasks/data/dao/DeletionDao.kt
+++ b/data/src/commonMain/kotlin/org/tasks/data/dao/DeletionDao.kt
@@ -5,7 +5,6 @@ import androidx.room.Delete
import androidx.room.Query
import androidx.room.Transaction
import co.touchlab.kermit.Logger
-import org.tasks.data.dao.CaldavDao.Companion.LOCAL
import org.tasks.data.db.SuspendDbUtils.chunkedMap
import org.tasks.data.db.SuspendDbUtils.eachChunk
import org.tasks.data.entity.CaldavAccount
@@ -90,7 +89,14 @@ WHERE recurring = 1
@Delete
internal abstract suspend fun deleteCaldavAccount(caldavAccount: CaldavAccount)
- @Query("DELETE FROM tasks WHERE _id IN (SELECT _id FROM tasks INNER JOIN caldav_tasks ON _id = cd_task INNER JOIN caldav_lists ON cdl_uuid = cd_calendar WHERE cdl_account = '$LOCAL' AND deleted > 0 AND cd_deleted = 0)")
+ @Query("""
+ DELETE FROM tasks WHERE _id IN (
+ SELECT _id FROM tasks
+ INNER JOIN caldav_tasks ON _id = cd_task
+ INNER JOIN caldav_lists ON cdl_uuid = cd_calendar
+ INNER JOIN caldav_accounts ON cdl_account = cda_uuid
+ WHERE cda_account_type == ${CaldavAccount.TYPE_LOCAL} AND deleted > 0 AND cd_deleted = 0)
+ """)
abstract suspend fun purgeDeleted()
@Transaction
diff --git a/data/src/commonMain/kotlin/org/tasks/data/entity/CaldavAccount.kt b/data/src/commonMain/kotlin/org/tasks/data/entity/CaldavAccount.kt
index 72d8837bc..7ed916fd6 100644
--- a/data/src/commonMain/kotlin/org/tasks/data/entity/CaldavAccount.kt
+++ b/data/src/commonMain/kotlin/org/tasks/data/entity/CaldavAccount.kt
@@ -62,6 +62,9 @@ data class CaldavAccount(
val isGoogleTasks: Boolean
get() = accountType == TYPE_GOOGLE_TASKS
+ val isLocalList: Boolean
+ get() = accountType == TYPE_LOCAL
+
val isSuppressRepeatingTasks: Boolean
get() = when (serverType) {
SERVER_OPEN_XCHANGE,
diff --git a/kmp/src/commonMain/kotlin/org/tasks/compose/drawer/DrawerConfiguration.kt b/kmp/src/commonMain/kotlin/org/tasks/compose/drawer/DrawerConfiguration.kt
index b48aabcc5..bb3565a9a 100644
--- a/kmp/src/commonMain/kotlin/org/tasks/compose/drawer/DrawerConfiguration.kt
+++ b/kmp/src/commonMain/kotlin/org/tasks/compose/drawer/DrawerConfiguration.kt
@@ -21,7 +21,4 @@ interface DrawerConfiguration {
val recentlyModifiedFilter: Boolean
get() = true
-
- val localListsEnabled: Boolean
- get() = true
}
\ No newline at end of file
diff --git a/kmp/src/commonMain/kotlin/org/tasks/data/CaldavDaoExtensions.kt b/kmp/src/commonMain/kotlin/org/tasks/data/CaldavDaoExtensions.kt
index e59d05564..7ccb8070c 100644
--- a/kmp/src/commonMain/kotlin/org/tasks/data/CaldavDaoExtensions.kt
+++ b/kmp/src/commonMain/kotlin/org/tasks/data/CaldavDaoExtensions.kt
@@ -11,8 +11,12 @@ import tasks.kmp.generated.resources.default_list
private val mutex = Mutex()
-suspend fun CaldavDao.setupLocalAccount(): CaldavAccount = mutex.withLock {
- val account = getLocalAccount()
+suspend fun CaldavDao.newLocalAccount(): CaldavAccount = mutex.withLock {
+ val account = CaldavAccount(
+ accountType = CaldavAccount.TYPE_LOCAL,
+ uuid = UUIDHelper.newUUID(),
+ )
+ .let { it.copy(id = insert(it)) }
getLocalList(account)
return account
}
@@ -22,12 +26,7 @@ suspend fun CaldavDao.getLocalList() = mutex.withLock {
}
suspend fun CaldavDao.getLocalAccount() =
- getAccountByUuid(CaldavDao.LOCAL)
- ?: CaldavAccount(
- accountType = CaldavAccount.TYPE_LOCAL,
- uuid = CaldavDao.LOCAL,
- )
- .let { it.copy(id = insert(it)) }
+ getAccounts(CaldavAccount.TYPE_LOCAL).firstOrNull() ?: newLocalAccount()
private suspend fun CaldavDao.getLocalList(account: CaldavAccount): CaldavCalendar =
getCalendarsByAccount(account.uuid!!).getOrNull(0)
diff --git a/kmp/src/commonMain/kotlin/org/tasks/filters/FilterProvider.kt b/kmp/src/commonMain/kotlin/org/tasks/filters/FilterProvider.kt
index 893002a6e..dac985bba 100644
--- a/kmp/src/commonMain/kotlin/org/tasks/filters/FilterProvider.kt
+++ b/kmp/src/commonMain/kotlin/org/tasks/filters/FilterProvider.kt
@@ -13,7 +13,6 @@ import org.tasks.data.dao.TaskDao
import org.tasks.data.entity.CaldavAccount
import org.tasks.data.entity.CaldavAccount.Companion.TYPE_LOCAL
import org.tasks.data.entity.CaldavAccount.Companion.TYPE_OPENTASKS
-import org.tasks.data.setupLocalAccount
import org.tasks.data.toLocationFilter
import org.tasks.data.toTagFilter
import org.tasks.filters.NavigationDrawerSubheader.SubheaderType
@@ -193,9 +192,8 @@ class FilterProvider(
showCreate: Boolean,
forceExpand: Boolean,
): List =
- caldavDao.getAccounts()
- .ifEmpty { listOf(caldavDao.setupLocalAccount()) }
- .filter { it.accountType != TYPE_LOCAL || configuration.localListsEnabled }
+ caldavDao
+ .getAccounts()
.flatMap {
caldavFilter(
it,
@@ -213,7 +211,7 @@ class FilterProvider(
return listOf(
NavigationDrawerSubheader(
if (account.accountType == TYPE_LOCAL) {
- getString(Res.string.drawer_local_lists)
+ account.name?.takeIf { it.isNotBlank() } ?: getString(Res.string.drawer_local_lists)
} else {
account.name
},