From 346bf22fb3990c86b40b760cbcc1eaa72a80bd4d Mon Sep 17 00:00:00 2001 From: Alex Baker Date: Wed, 3 Jun 2020 14:42:00 -0500 Subject: [PATCH] Local lists --- app/build.gradle.kts | 4 +- .../todoroo/astrid/service/TaskMoverTest.kt | 61 ------------------- .../java/org/tasks/data/DeletionDaoTests.kt | 49 +++++++++++++-- app/src/main/AndroidManifest.xml | 4 ++ .../astrid/activity/TaskListFragment.kt | 6 +- .../com/todoroo/astrid/adapter/TaskAdapter.kt | 11 +--- .../astrid/backup/TasksXmlImporter.java | 7 ++- .../java/com/todoroo/astrid/dao/TaskDao.kt | 18 ++---- .../main/java/com/todoroo/astrid/data/Task.kt | 10 +-- .../com/todoroo/astrid/service/TaskMover.java | 39 ++++++++---- .../com/todoroo/astrid/service/Upgrader.kt | 9 ++- .../activities/BaseListSettingsActivity.java | 2 +- .../java/org/tasks/activities/ListPicker.kt | 21 +++---- .../org/tasks/backup/TasksJsonImporter.java | 10 ++- .../BaseCaldavCalendarSettingsActivity.java | 2 +- .../tasks/caldav/LocalListSettingsActivity.kt | 31 ++++++++++ .../main/java/org/tasks/data/CaldavAccount.kt | 12 ++++ app/src/main/java/org/tasks/data/CaldavDao.kt | 37 ++++++++++- .../main/java/org/tasks/data/DeletionDao.kt | 4 ++ .../java/org/tasks/data/TaskContainer.java | 1 - .../tasks/filters/FilterCriteriaProvider.java | 4 +- .../java/org/tasks/filters/FilterProvider.kt | 18 +++--- .../org/tasks/injection/ActivityComponent.kt | 2 + .../main/java/org/tasks/jobs/CleanupWork.java | 3 + .../main/java/org/tasks/jobs/WorkManager.java | 3 +- .../preferences/DefaultFilterProvider.kt | 12 +++- .../preferences/fragments/Synchronization.kt | 5 +- .../preferences/fragments/TaskDefaults.kt | 23 +++---- .../java/org/tasks/sync/SyncAdapters.java | 2 +- .../main/java/org/tasks/ui/ListFragment.kt | 50 +++++---------- .../java/org/tasks/ui/SubtaskControlSet.kt | 1 - .../res/layout/control_set_remote_list.xml | 27 ++------ app/src/main/res/values-bg-rBG/strings.xml | 1 - app/src/main/res/values-cs/strings.xml | 1 - app/src/main/res/values-de/strings.xml | 1 - app/src/main/res/values-es/strings.xml | 1 - app/src/main/res/values-et/strings.xml | 1 - app/src/main/res/values-eu/strings.xml | 1 - app/src/main/res/values-fi/strings.xml | 1 - app/src/main/res/values-fr/strings.xml | 1 - app/src/main/res/values-hu/strings.xml | 1 - app/src/main/res/values-id/strings.xml | 1 - app/src/main/res/values-it/strings.xml | 1 - app/src/main/res/values-iw/strings.xml | 1 - app/src/main/res/values-ja/strings.xml | 1 - app/src/main/res/values-ko/strings.xml | 1 - app/src/main/res/values-lt/strings.xml | 1 - app/src/main/res/values-nb/strings.xml | 1 - app/src/main/res/values-nl/strings.xml | 1 - app/src/main/res/values-pl/strings.xml | 1 - app/src/main/res/values-pt-rBR/strings.xml | 1 - app/src/main/res/values-ru/strings.xml | 1 - app/src/main/res/values-sk/strings.xml | 1 - app/src/main/res/values-sv/strings.xml | 1 - app/src/main/res/values-tl/strings.xml | 1 - app/src/main/res/values-tr/strings.xml | 1 - app/src/main/res/values-uk/strings.xml | 1 - app/src/main/res/values-zh-rCN/strings.xml | 1 - app/src/main/res/values/keys.xml | 1 + app/src/main/res/values/strings.xml | 2 +- .../res/xml/preferences_navigation_drawer.xml | 7 +++ 61 files changed, 269 insertions(+), 255 deletions(-) create mode 100644 app/src/main/java/org/tasks/caldav/LocalListSettingsActivity.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 1cda73ae3..028657a59 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -42,8 +42,8 @@ android { defaultConfig { testApplicationId = "org.tasks.test" applicationId = "org.tasks" - versionCode = 90501 - versionName = "9.5" + versionCode = 90600 + versionName = "9.6" targetSdkVersion(Versions.targetSdk) minSdkVersion(Versions.minSdk) testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" diff --git a/app/src/androidTest/java/com/todoroo/astrid/service/TaskMoverTest.kt b/app/src/androidTest/java/com/todoroo/astrid/service/TaskMoverTest.kt index 3437d9a05..13e244ef5 100644 --- a/app/src/androidTest/java/com/todoroo/astrid/service/TaskMoverTest.kt +++ b/app/src/androidTest/java/com/todoroo/astrid/service/TaskMoverTest.kt @@ -238,63 +238,6 @@ class TaskMoverTest : InjectingTestCase() { assertEquals(2, taskDao.fetch(3)!!.parent) } - @Test - fun dontSyncGoogleTask() { - createTasks(1) - googleTaskDao.insert(newGoogleTask(with(TASK, 1), with(LIST, "1"))) - dontSync(1) - assertNull(googleTaskDao.getByTaskId(1)) - assertFalse(taskDao.fetch(1)!!.isDeleted) - } - - @Test - fun dontSyncCaldavTask() { - createTasks(1) - caldavDao.insert(newCaldavTask(with(CaldavTaskMaker.TASK, 1L), with(CALENDAR, "1"))) - dontSync(1) - assertNull(caldavDao.getTask(1)) - assertFalse(taskDao.fetch(1)!!.isDeleted) - } - - @Test - fun dontSyncGoogleTaskWithSubtasks() { - createTasks(1, 2) - googleTaskDao.insert(newGoogleTask(with(TASK, 1), with(LIST, "1"))) - googleTaskDao.insert(newGoogleTask(with(TASK, 2), with(LIST, "1"), with(PARENT, 1L))) - dontSync(1) - assertNull(googleTaskDao.getByTaskId(2)) - val task = taskDao.fetch(2)!! - assertFalse(task.isDeleted) - assertEquals(1, task.parent) - assertEquals(taskDao.fetch(1)!!.uuid, task.parentUuid) - } - - @Test - fun dontSyncCaldavWithSubtasks() { - createTasks(1) - createSubtask(2, 1) - createSubtask(3, 2) - caldavDao.insert( - listOf( - newCaldavTask( - with(CaldavTaskMaker.TASK, 1L), with(CALENDAR, "1"), with(REMOTE_ID, "a")), - newCaldavTask( - with(CaldavTaskMaker.TASK, 2L), - with(CALENDAR, "1"), - with(REMOTE_ID, "b"), - with(REMOTE_PARENT, "a")), - newCaldavTask( - with(CaldavTaskMaker.TASK, 3L), - with(CALENDAR, "1"), - with(REMOTE_PARENT, "b")))) - dontSync(1) - assertNull(caldavDao.getTask(3)) - val task = taskDao.fetch(3)!! - assertFalse(task.isDeleted) - assertEquals(2, task.parent) - assertEquals(taskDao.fetch(2)!!.uuid, task.parentUuid) - } - @Test fun moveToSameGoogleTaskListIsNoop() { createTasks(1) @@ -356,9 +299,5 @@ class TaskMoverTest : InjectingTestCase() { taskMover.move(tasks.toList(), CaldavFilter(CaldavCalendar("", calendar))) } - private fun dontSync(task: Long) { - taskMover.move(listOf(task), null) - } - override fun inject(component: TestComponent) = component.inject(this) } \ No newline at end of file diff --git a/app/src/androidTest/java/org/tasks/data/DeletionDaoTests.kt b/app/src/androidTest/java/org/tasks/data/DeletionDaoTests.kt index 7b1143529..a1129006d 100644 --- a/app/src/androidTest/java/org/tasks/data/DeletionDaoTests.kt +++ b/app/src/androidTest/java/org/tasks/data/DeletionDaoTests.kt @@ -1,14 +1,18 @@ package org.tasks.data import androidx.test.ext.junit.runners.AndroidJUnit4 -import com.natpryce.makeiteasy.MakeItEasy +import com.natpryce.makeiteasy.MakeItEasy.with import com.todoroo.astrid.dao.TaskDao -import org.junit.Assert.assertTrue +import com.todoroo.astrid.helper.UUIDHelper +import org.junit.Assert.* import org.junit.Test import org.junit.runner.RunWith +import org.tasks.data.CaldavDao.Companion.LOCAL +import org.tasks.date.DateTimeUtils.newDateTime import org.tasks.injection.InjectingTestCase import org.tasks.injection.TestComponent import org.tasks.makers.TaskMaker.CREATION_TIME +import org.tasks.makers.TaskMaker.DELETION_TIME import org.tasks.makers.TaskMaker.newTask import org.tasks.time.DateTime import org.tasks.time.DateTimeUtils @@ -18,6 +22,7 @@ import javax.inject.Inject class DeletionDaoTests : InjectingTestCase() { @Inject lateinit var taskDao: TaskDao @Inject lateinit var deletionDao: DeletionDao + @Inject lateinit var caldavDao: CaldavDao @Test fun deleting1000DoesntCrash() { @@ -31,7 +36,7 @@ class DeletionDaoTests : InjectingTestCase() { @Test fun markDeletedUpdatesModificationTime() { - var task = newTask(MakeItEasy.with(CREATION_TIME, DateTime().minusMinutes(1))) + var task = newTask(with(CREATION_TIME, DateTime().minusMinutes(1))) taskDao.createNew(task) deletionDao.markDeleted(listOf(task.id)) task = taskDao.fetch(task.id)!! @@ -41,7 +46,7 @@ class DeletionDaoTests : InjectingTestCase() { @Test fun markDeletedUpdatesDeletionTime() { - var task = newTask(MakeItEasy.with(CREATION_TIME, DateTime().minusMinutes(1))) + var task = newTask(with(CREATION_TIME, DateTime().minusMinutes(1))) taskDao.createNew(task) deletionDao.markDeleted(listOf(task.id)) task = taskDao.fetch(task.id)!! @@ -49,5 +54,41 @@ class DeletionDaoTests : InjectingTestCase() { assertTrue(task.deletionDate < DateTimeUtils.currentTimeMillis()) } + @Test + fun purgeDeletedLocalTask() { + val task = newTask(with(DELETION_TIME, newDateTime())) + taskDao.createNew(task) + caldavDao.insert(CaldavCalendar("", "1234").apply { account = LOCAL }) + caldavDao.insert(CaldavTask(task.id, "1234")) + + deletionDao.purgeDeleted() + + assertNull(taskDao.fetch(task.id)) + } + + @Test + fun dontPurgeActiveTasks() { + val task = newTask() + taskDao.createNew(task) + caldavDao.insert(CaldavCalendar("", "1234").apply { account = LOCAL }) + caldavDao.insert(CaldavTask(task.id, "1234")) + + deletionDao.purgeDeleted() + + assertNotNull(taskDao.fetch(task.id)) + } + + @Test + fun dontPurgeDeletedCaldavTask() { + val task = newTask(with(DELETION_TIME, newDateTime())) + taskDao.createNew(task) + caldavDao.insert(CaldavCalendar("", "1234").apply { account = UUIDHelper.newUUID() }) + caldavDao.insert(CaldavTask(task.id, "1234")) + + deletionDao.purgeDeleted() + + assertNotNull(taskDao.fetch(task.id)) + } + override fun inject(component: TestComponent) = component.inject(this) } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 52b7e7838..194dc7a53 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -300,6 +300,10 @@ android:name=".caldav.CaldavCalendarSettingsActivity" android:theme="@style/Tasks"/> + + diff --git a/app/src/main/java/com/todoroo/astrid/activity/TaskListFragment.kt b/app/src/main/java/com/todoroo/astrid/activity/TaskListFragment.kt index eda3490fb..3ff2c4142 100644 --- a/app/src/main/java/com/todoroo/astrid/activity/TaskListFragment.kt +++ b/app/src/main/java/com/todoroo/astrid/activity/TaskListFragment.kt @@ -55,7 +55,6 @@ import org.tasks.R import org.tasks.ShortcutManager import org.tasks.activities.* import org.tasks.caldav.BaseCaldavCalendarSettingsActivity -import org.tasks.caldav.CaldavCalendarSettingsActivity import org.tasks.data.CaldavDao import org.tasks.data.TagDataDao import org.tasks.data.TaskContainer @@ -63,7 +62,6 @@ import org.tasks.db.DbUtils import org.tasks.dialogs.DateTimePicker.Companion.newDateTimePicker import org.tasks.dialogs.DialogBuilder import org.tasks.dialogs.SortDialog -import org.tasks.etesync.EteSyncCalendarSettingsActivity import org.tasks.filters.PlaceFilter import org.tasks.injection.FragmentComponent import org.tasks.injection.InjectingFragment @@ -360,9 +358,7 @@ class TaskListFragment : InjectingFragment(), OnRefreshListener, Toolbar.OnMenuI R.id.menu_caldav_list_fragment -> { val calendar = (filter as CaldavFilter).calendar val account = caldavDao.getAccountByUuid(calendar.account!!) - val caldavSettings = Intent( - activity, - if (account!!.isCaldavAccount) CaldavCalendarSettingsActivity::class.java else EteSyncCalendarSettingsActivity::class.java) + val caldavSettings = Intent(activity, account!!.listSettingsClass()) caldavSettings.putExtra(BaseCaldavCalendarSettingsActivity.EXTRA_CALDAV_CALENDAR, calendar) startActivityForResult(caldavSettings, REQUEST_LIST_SETTINGS) true diff --git a/app/src/main/java/com/todoroo/astrid/adapter/TaskAdapter.kt b/app/src/main/java/com/todoroo/astrid/adapter/TaskAdapter.kt index 0930d3e23..0cef7fcba 100644 --- a/app/src/main/java/com/todoroo/astrid/adapter/TaskAdapter.kt +++ b/app/src/main/java/com/todoroo/astrid/adapter/TaskAdapter.kt @@ -153,7 +153,6 @@ open class TaskAdapter( } newParent.isGoogleTask -> changeGoogleTaskParent(task, newParent) newParent.isCaldavTask -> changeCaldavParent(task, newParent) - else -> changeLocalParent(task, newParent) } } @@ -228,17 +227,9 @@ open class TaskAdapter( when { task.isGoogleTask -> changeGoogleTaskParent(task, null) task.isCaldavTask -> changeCaldavParent(task, null) - else -> changeLocalParent(task, null) } } - private fun changeLocalParent(task: TaskContainer, newParent: TaskContainer?) { - val t = task.getTask() - t.parent = newParent?.id ?: 0 - t.parentUuid = newParent?.uuid - taskDao.save(t, null) - } - private fun changeGoogleTaskParent(task: TaskContainer, newParent: TaskContainer?) { val list = newParent?.googleTaskList ?: task.googleTaskList!! if (newParent == null || task.googleTaskList == newParent.googleTaskList) { @@ -292,7 +283,7 @@ open class TaskAdapter( } else { caldavDao.update(caldavTask) } - taskDao.setParent(newParentId, null, listOf(task.id)) + taskDao.setParent(newParentId, listOf(task.id)) taskDao.touch(task.id) localBroadcastManager.broadcastRefresh() } diff --git a/app/src/main/java/com/todoroo/astrid/backup/TasksXmlImporter.java b/app/src/main/java/com/todoroo/astrid/backup/TasksXmlImporter.java index 1bf06b113..de3c65561 100755 --- a/app/src/main/java/com/todoroo/astrid/backup/TasksXmlImporter.java +++ b/app/src/main/java/com/todoroo/astrid/backup/TasksXmlImporter.java @@ -17,6 +17,7 @@ import android.text.TextUtils; import com.todoroo.andlib.utility.DialogUtilities; import com.todoroo.astrid.dao.TaskDao; import com.todoroo.astrid.data.Task; +import com.todoroo.astrid.service.TaskMover; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -55,6 +56,7 @@ public class TasksXmlImporter { private final AlarmDao alarmDao; private final TagDao tagDao; private final GoogleTaskDao googleTaskDao; + private final TaskMover taskMover; private final LocationDao locationDao; private Activity activity; private Handler handler; @@ -75,7 +77,8 @@ public class TasksXmlImporter { LocalBroadcastManager localBroadcastManager, AlarmDao alarmDao, TagDao tagDao, - GoogleTaskDao googleTaskDao) { + GoogleTaskDao googleTaskDao, + TaskMover taskMover) { this.tagDataDao = tagDataDao; this.userActivityDao = userActivityDao; this.dialogBuilder = dialogBuilder; @@ -85,6 +88,7 @@ public class TasksXmlImporter { this.alarmDao = alarmDao; this.tagDao = tagDao; this.googleTaskDao = googleTaskDao; + this.taskMover = taskMover; } private void setProgressMessage(final String message) { @@ -102,6 +106,7 @@ public class TasksXmlImporter { () -> { try { performImport(); + taskMover.migrateLocalTasks(); } catch (IOException | XmlPullParserException e) { Timber.e(e); } diff --git a/app/src/main/java/com/todoroo/astrid/dao/TaskDao.kt b/app/src/main/java/com/todoroo/astrid/dao/TaskDao.kt index e5b880868..67b9e6d16 100644 --- a/app/src/main/java/com/todoroo/astrid/dao/TaskDao.kt +++ b/app/src/main/java/com/todoroo/astrid/dao/TaskDao.kt @@ -162,19 +162,8 @@ abstract class TaskDao(private val database: Database) { @Query("UPDATE tasks SET modified = strftime('%s','now')*1000 WHERE _id in (:ids)") abstract fun touchInternal(ids: List) - @Query("UPDATE tasks SET parent = IFNULL((" - + " SELECT parent._id FROM tasks AS parent" - + " WHERE parent.remoteId = tasks.parent_uuid AND parent.deleted = 0), 0)" - + "WHERE parent_uuid IS NOT NULL AND parent_uuid != ''") - abstract fun updateParents() - - @Query("UPDATE tasks SET parent_uuid = " - + " (SELECT parent.remoteId FROM tasks AS parent WHERE parent._id = tasks.parent)" - + " WHERE parent > 0 AND _id IN (:tasks)") - abstract fun updateParentUids(tasks: List) - - @Query("UPDATE tasks SET parent = :parent, parent_uuid = :parentUuid WHERE _id IN (:children)") - abstract fun setParent(parent: Long, parentUuid: String?, children: List) + @Query("UPDATE tasks SET parent = :parent WHERE _id IN (:children)") + abstract fun setParent(parent: Long, children: List) @Transaction open fun fetchChildren(id: Long): List { @@ -281,6 +270,9 @@ abstract class TaskDao(private val database: Database) { return tasks.map(TaskContainer::getTask) } + @Query("SELECT _id FROM tasks LEFT JOIN google_tasks ON _id = gt_task AND gt_deleted = 0 LEFT JOIN caldav_tasks ON _id = cd_task AND cd_deleted = 0 WHERE gt_id IS NULL AND cd_id IS NULL AND parent = 0") + abstract fun getLocalTasks(): List + /** Generates SQL clauses */ object TaskCriteria { /** @return tasks that have not yet been completed or deleted diff --git a/app/src/main/java/com/todoroo/astrid/data/Task.kt b/app/src/main/java/com/todoroo/astrid/data/Task.kt index 97d8ee630..780b5044c 100644 --- a/app/src/main/java/com/todoroo/astrid/data/Task.kt +++ b/app/src/main/java/com/todoroo/astrid/data/Task.kt @@ -7,7 +7,6 @@ import androidx.annotation.IntDef import androidx.core.os.ParcelCompat import androidx.room.* import com.google.ical.values.RRule -import com.todoroo.andlib.data.Property import com.todoroo.andlib.data.Table import com.todoroo.andlib.sql.Field import com.todoroo.andlib.utility.DateUtilities @@ -111,6 +110,7 @@ class Task : Parcelable { @Transient var parent = 0L + @Deprecated(message = "no longer used") @ColumnInfo(name = "parent_uuid") var parentUuid: String? = null @@ -170,7 +170,6 @@ class Task : Parcelable { transitoryData = parcel.readHashMap(ContentValues::class.java.classLoader) as HashMap? isCollapsed = ParcelCompat.readBoolean(parcel) parent = parcel.readLong() - parentUuid = parcel.readString() } var uuid: String @@ -307,7 +306,6 @@ class Task : Parcelable { dest.writeMap(transitoryData as Map<*, *>?) ParcelCompat.writeBoolean(dest, isCollapsed) dest.writeLong(parent) - dest.writeString(parentUuid) } fun insignificantChange(task: Task?): Boolean { @@ -333,7 +331,7 @@ class Task : Parcelable { && recurrence == task.recurrence && repeatUntil == task.repeatUntil && calendarURI == task.calendarURI - && parent == task.parent && parentUuid == task.parentUuid + && parent == task.parent && remoteId == task.remoteId } @@ -444,7 +442,6 @@ class Task : Parcelable { if (remoteId != other.remoteId) return false if (isCollapsed != other.isCollapsed) return false if (parent != other.parent) return false - if (parentUuid != other.parentUuid) return false if (transitoryData != other.transitoryData) return false return true @@ -474,13 +471,12 @@ class Task : Parcelable { result = 31 * result + remoteId.hashCode() result = 31 * result + isCollapsed.hashCode() result = 31 * result + parent.hashCode() - result = 31 * result + (parentUuid?.hashCode() ?: 0) result = 31 * result + (transitoryData?.hashCode() ?: 0) return result } override fun toString(): String { - return "Task(id=$id, title=$title, priority=$priority, dueDate=$dueDate, hideUntil=$hideUntil, creationDate=$creationDate, modificationDate=$modificationDate, completionDate=$completionDate, deletionDate=$deletionDate, notes=$notes, estimatedSeconds=$estimatedSeconds, elapsedSeconds=$elapsedSeconds, timerStart=$timerStart, reminderFlags=$reminderFlags, reminderPeriod=$reminderPeriod, reminderLast=$reminderLast, reminderSnooze=$reminderSnooze, recurrence=$recurrence, repeatUntil=$repeatUntil, calendarURI=$calendarURI, remoteId='$remoteId', isCollapsed=$isCollapsed, parent=$parent, parentUuid=$parentUuid, transitoryData=$transitoryData)" + return "Task(id=$id, title=$title, priority=$priority, dueDate=$dueDate, hideUntil=$hideUntil, creationDate=$creationDate, modificationDate=$modificationDate, completionDate=$completionDate, deletionDate=$deletionDate, notes=$notes, estimatedSeconds=$estimatedSeconds, elapsedSeconds=$elapsedSeconds, timerStart=$timerStart, reminderFlags=$reminderFlags, reminderPeriod=$reminderPeriod, reminderLast=$reminderLast, reminderSnooze=$reminderSnooze, recurrence=$recurrence, repeatUntil=$repeatUntil, calendarURI=$calendarURI, remoteId='$remoteId', isCollapsed=$isCollapsed, parent=$parent, transitoryData=$transitoryData)" } @Retention(AnnotationRetention.SOURCE) diff --git a/app/src/main/java/com/todoroo/astrid/service/TaskMover.java b/app/src/main/java/com/todoroo/astrid/service/TaskMover.java index 952e01cd4..6bb4378b6 100644 --- a/app/src/main/java/com/todoroo/astrid/service/TaskMover.java +++ b/app/src/main/java/com/todoroo/astrid/service/TaskMover.java @@ -6,7 +6,8 @@ import static com.google.common.collect.Lists.transform; import static com.todoroo.andlib.utility.DateUtilities.now; import static java.util.Collections.emptyList; -import androidx.annotation.Nullable; +import android.content.Context; +import androidx.annotation.NonNull; import com.todoroo.astrid.api.CaldavFilter; import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.GtasksFilter; @@ -17,15 +18,20 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; +import org.tasks.BuildConfig; import org.tasks.LocalBroadcastManager; +import org.tasks.data.CaldavCalendar; import org.tasks.data.CaldavDao; import org.tasks.data.CaldavTask; import org.tasks.data.GoogleTask; import org.tasks.data.GoogleTaskDao; import org.tasks.data.GoogleTaskListDao; +import org.tasks.injection.ForApplication; import org.tasks.preferences.Preferences; public class TaskMover { + + private final Context context; private final TaskDao taskDao; private final CaldavDao caldavDao; private final GoogleTaskDao googleTaskDao; @@ -35,12 +41,14 @@ public class TaskMover { @Inject public TaskMover( + @ForApplication Context context, TaskDao taskDao, CaldavDao caldavDao, GoogleTaskDao googleTaskDao, GoogleTaskListDao googleTaskListDao, Preferences preferences, LocalBroadcastManager localBroadcastManager) { + this.context = context; this.taskDao = taskDao; this.caldavDao = caldavDao; this.googleTaskDao = googleTaskDao; @@ -64,11 +72,11 @@ public class TaskMover { return null; } - public void move(List tasks, Filter selectedList) { + public void move(List tasks, @NonNull Filter selectedList) { tasks = new ArrayList<>(tasks); tasks.removeAll(googleTaskDao.findChildrenInList(tasks)); tasks.removeAll(taskDao.findChildrenInList(tasks)); - taskDao.setParent(0, null, tasks); + taskDao.setParent(0, tasks); for (Task task : taskDao.fetch(tasks)) { performMove(task, selectedList); } @@ -79,7 +87,12 @@ public class TaskMover { localBroadcastManager.broadcastRefresh(); } - private void performMove(Task task, @Nullable Filter selectedList) { + public void migrateLocalTasks() { + CaldavCalendar list = caldavDao.setupLocalAccount(context); + move(taskDao.getLocalTasks(), new CaldavFilter(list)); + } + + private void performMove(Task task, @NonNull Filter selectedList) { long id = task.getId(); GoogleTask googleTask = googleTaskDao.getByTaskId(id); @@ -97,7 +110,7 @@ public class TaskMover { moveLocalTask(task, selectedList); } - private void moveGoogleTask(Task task, GoogleTask googleTask, Filter selected) { + private void moveGoogleTask(Task task, GoogleTask googleTask, @NonNull Filter selected) { if (selected instanceof GtasksFilter && googleTask.getListId().equals(((GtasksFilter) selected).getRemoteId())) { return; @@ -134,12 +147,12 @@ public class TaskMover { newChild.setRemoteParent(newParent.getRemoteId()); return newChild; })); - } else { - taskDao.setParent(task.getId(), task.getUuid(), childIds); + } else if (BuildConfig.DEBUG) { + throw new IllegalArgumentException(); } } - private void moveCaldavTask(Task task, CaldavTask caldavTask, Filter selected) { + private void moveCaldavTask(Task task, CaldavTask caldavTask, @NonNull Filter selected) { if (selected instanceof CaldavFilter && caldavTask.getCalendar().equals(((CaldavFilter) selected).getUuid())) { return; @@ -174,12 +187,12 @@ public class TaskMover { })); } else if (selected instanceof GtasksFilter) { moveToGoogleTasks(id, childIds, (GtasksFilter) selected); - } else { - taskDao.updateParentUids(from(children).transform(CaldavTask::getTask).toList()); + } else if (BuildConfig.DEBUG) { + throw new IllegalArgumentException(); } } - private void moveLocalTask(Task task, @Nullable Filter selected) { + private void moveLocalTask(Task task, @NonNull Filter selected) { if (selected instanceof GtasksFilter) { moveToGoogleTasks(task.getId(), taskDao.getChildren(task.getId()), (GtasksFilter) selected); } else if (selected instanceof CaldavFilter) { @@ -195,11 +208,13 @@ public class TaskMover { } caldavDao.insert(task, root, preferences.addTasksToTop()); caldavDao.insert(tasks.values()); + } else if (BuildConfig.DEBUG) { + throw new IllegalArgumentException(); } } private void moveToGoogleTasks(long id, List children, GtasksFilter filter) { - taskDao.setParent(0, null, children); + taskDao.setParent(0, children); String listId = filter.getRemoteId(); googleTaskDao.insertAndShift(new GoogleTask(id, listId), preferences.addTasksToTop()); List newChildren = new ArrayList<>(); diff --git a/app/src/main/java/com/todoroo/astrid/service/Upgrader.kt b/app/src/main/java/com/todoroo/astrid/service/Upgrader.kt index 2bb3b1b87..5b37a0060 100644 --- a/app/src/main/java/com/todoroo/astrid/service/Upgrader.kt +++ b/app/src/main/java/com/todoroo/astrid/service/Upgrader.kt @@ -38,10 +38,13 @@ class Upgrader @Inject constructor( private val taskDao: TaskDao, private val locationDao: LocationDao, private val iCal: iCalendar, - private val widgetManager: AppWidgetManager) { + private val widgetManager: AppWidgetManager, + private val taskMover: TaskMover) { fun upgrade(from: Int, to: Int) { - if (from > 0) { + if (from == 0) { + caldavDao.setupLocalAccount(context) + } else { run(from, V4_9_5) { removeDuplicateTags() } run(from, V5_3_0) { migrateFilters() } run(from, V6_0_beta_1) { migrateDefaultSyncList() } @@ -56,6 +59,7 @@ class Upgrader @Inject constructor( run(from, V8_8) { preferences.setBoolean(R.string.p_linkify_task_edit, true) } run(from, V8_10) { migrateWidgets() } run(from, V9_3) { applyCaldavOrder() } + run(from, V9_6) { taskMover.migrateLocalTasks() } preferences.setBoolean(R.string.p_just_updated, true) } preferences.setCurrentVersion(to) @@ -297,6 +301,7 @@ class Upgrader @Inject constructor( private const val V8_8 = 717 private const val V8_10 = 735 private const val V9_3 = 90300 + const val V9_6 = 90600 @JvmStatic fun getAndroidColor(context: Context, index: Int): Int { diff --git a/app/src/main/java/org/tasks/activities/BaseListSettingsActivity.java b/app/src/main/java/org/tasks/activities/BaseListSettingsActivity.java index 901af29fc..214c83391 100644 --- a/app/src/main/java/org/tasks/activities/BaseListSettingsActivity.java +++ b/app/src/main/java/org/tasks/activities/BaseListSettingsActivity.java @@ -51,7 +51,7 @@ public abstract class BaseListSettingsActivity extends ThemedInjectingAppCompatA TextView icon; @BindView(R.id.toolbar) - Toolbar toolbar; + protected Toolbar toolbar; @Inject DialogBuilder dialogBuilder; @Inject ColorProvider colorProvider; diff --git a/app/src/main/java/org/tasks/activities/ListPicker.kt b/app/src/main/java/org/tasks/activities/ListPicker.kt index 2afb45322..fb1757261 100644 --- a/app/src/main/java/org/tasks/activities/ListPicker.kt +++ b/app/src/main/java/org/tasks/activities/ListPicker.kt @@ -65,7 +65,7 @@ class ListPicker : InjectingDialogFragment() { override fun inject(component: DialogFragmentComponent) = component.inject(this) - private fun selectedList(list: Filter?) { + private fun selectedList(list: Filter) { targetFragment!!.onActivityResult( targetRequestCode, Activity.RESULT_OK, @@ -75,7 +75,7 @@ class ListPicker : InjectingDialogFragment() { private fun refresh() { val noSelection = requireArguments().getBoolean(EXTRA_NO_SELECTION, false) val selected: Filter? = if (noSelection) null else arguments?.getParcelable(EXTRA_SELECTED_FILTER) - disposables!!.add(Single.fromCallable(filterProvider::remoteListPickerItems) + disposables!!.add(Single.fromCallable(filterProvider::listPickerItems) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe { items: List? -> filterAdapter.setData(items!!, selected) }) @@ -106,21 +106,14 @@ class ListPicker : InjectingDialogFragment() { private fun createDialog( filterAdapter: FilterAdapter, dialogBuilder: DialogBuilder, - handler: (Filter?) -> Unit): AlertDialog { + handler: (Filter) -> Unit): AlertDialog { val builder = dialogBuilder .newDialog() .setNegativeButton(android.R.string.cancel, null) - .setSingleChoiceItems( - filterAdapter, - -1 - ) { dialog: DialogInterface, which: Int -> - if (which == 0) { - handler.invoke(null) - } else { - val item = filterAdapter.getItem(which) - if (item is GtasksFilter || item is CaldavFilter) { - handler.invoke(item as Filter) - } + .setSingleChoiceItems(filterAdapter,-1) { dialog: DialogInterface, which: Int -> + val item = filterAdapter.getItem(which) + if (item is GtasksFilter || item is CaldavFilter) { + handler.invoke(item as Filter) } dialog.dismiss() } diff --git a/app/src/main/java/org/tasks/backup/TasksJsonImporter.java b/app/src/main/java/org/tasks/backup/TasksJsonImporter.java index 27ee58d3a..defd61ec7 100644 --- a/app/src/main/java/org/tasks/backup/TasksJsonImporter.java +++ b/app/src/main/java/org/tasks/backup/TasksJsonImporter.java @@ -14,6 +14,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.todoroo.astrid.dao.TaskDao; import com.todoroo.astrid.data.Task; +import com.todoroo.astrid.service.TaskMover; import com.todoroo.astrid.service.Upgrader; import java.io.FileNotFoundException; import java.io.IOException; @@ -64,6 +65,7 @@ public class TasksJsonImporter { private final TaskAttachmentDao taskAttachmentDao; private final CaldavDao caldavDao; private final Preferences preferences; + private final TaskMover taskMover; private final LocationDao locationDao; private final ImportResult result = new ImportResult(); @@ -82,7 +84,8 @@ public class TasksJsonImporter { FilterDao filterDao, TaskAttachmentDao taskAttachmentDao, CaldavDao caldavDao, - Preferences preferences) { + Preferences preferences, + TaskMover taskMover) { this.tagDataDao = tagDataDao; this.userActivityDao = userActivityDao; this.taskDao = taskDao; @@ -96,6 +99,7 @@ public class TasksJsonImporter { this.taskAttachmentDao = taskAttachmentDao; this.caldavDao = caldavDao; this.preferences = preferences; + this.taskMover = taskMover; } private void setProgressMessage( @@ -235,7 +239,6 @@ public class TasksJsonImporter { googleTaskDao.updateParents(); caldavDao.updateParents(); - taskDao.updateParents(); for (Entry entry : backupContainer.getIntPrefs().entrySet()) { if (P_CURRENT_VERSION.equals(entry.getKey())) { @@ -259,6 +262,9 @@ public class TasksJsonImporter { R.string.p_theme_color, Upgrader.getAndroidColor(context, themeIndex)); } + if (version < Upgrader.V9_6) { + taskMover.migrateLocalTasks(); + } reader.close(); is.close(); diff --git a/app/src/main/java/org/tasks/caldav/BaseCaldavCalendarSettingsActivity.java b/app/src/main/java/org/tasks/caldav/BaseCaldavCalendarSettingsActivity.java index 159a6acc8..976bbac8c 100644 --- a/app/src/main/java/org/tasks/caldav/BaseCaldavCalendarSettingsActivity.java +++ b/app/src/main/java/org/tasks/caldav/BaseCaldavCalendarSettingsActivity.java @@ -34,7 +34,7 @@ public abstract class BaseCaldavCalendarSettingsActivity extends BaseListSetting public static final String EXTRA_CALDAV_CALENDAR = "extra_caldav_calendar"; public static final String EXTRA_CALDAV_ACCOUNT = "extra_caldav_account"; - @Inject CaldavDao caldavDao; + @Inject protected CaldavDao caldavDao; @Inject TaskDeleter taskDeleter; @BindView(R.id.root_layout) diff --git a/app/src/main/java/org/tasks/caldav/LocalListSettingsActivity.kt b/app/src/main/java/org/tasks/caldav/LocalListSettingsActivity.kt new file mode 100644 index 000000000..70a2b3515 --- /dev/null +++ b/app/src/main/java/org/tasks/caldav/LocalListSettingsActivity.kt @@ -0,0 +1,31 @@ +package org.tasks.caldav + +import android.os.Bundle +import org.tasks.R +import org.tasks.data.CaldavAccount +import org.tasks.data.CaldavCalendar +import org.tasks.data.CaldavDao +import org.tasks.injection.ActivityComponent + +class LocalListSettingsActivity : BaseCaldavCalendarSettingsActivity() { + + override fun getLayout() = R.layout.activity_caldav_calendar_settings + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + toolbar.menu.findItem(R.id.delete)?.isVisible = caldavDao.getCalendarsByAccount(CaldavDao.LOCAL).size > 1 + } + + override fun inject(component: ActivityComponent) = component.inject(this) + + override fun createCalendar(caldavAccount: CaldavAccount, name: String, color: Int) = + createSuccessful(null) + + override fun updateNameAndColor( + account: CaldavAccount, calendar: CaldavCalendar, name: String, color: Int) = + updateCalendar() + + override fun deleteCalendar(caldavAccount: CaldavAccount, caldavCalendar: CaldavCalendar) = + onDeleted(true) +} \ 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 c05dc5b89..663d91292 100644 --- a/app/src/main/java/org/tasks/data/CaldavAccount.kt +++ b/app/src/main/java/org/tasks/data/CaldavAccount.kt @@ -8,6 +8,10 @@ import androidx.room.Entity import androidx.room.Ignore import androidx.room.PrimaryKey import com.todoroo.astrid.data.Task +import org.tasks.activities.BaseListSettingsActivity +import org.tasks.caldav.CaldavCalendarSettingsActivity +import org.tasks.caldav.LocalListSettingsActivity +import org.tasks.etesync.EteSyncCalendarSettingsActivity import org.tasks.security.KeyStoreEncryption @Entity(tableName = "caldav_accounts") @@ -80,6 +84,12 @@ class CaldavAccount : Parcelable { val isEteSyncAccount: Boolean get() = accountType == TYPE_ETESYNC + fun listSettingsClass(): Class = when(accountType) { + TYPE_ETESYNC -> EteSyncCalendarSettingsActivity::class.java + TYPE_LOCAL -> LocalListSettingsActivity::class.java + else -> CaldavCalendarSettingsActivity::class.java + } + override fun describeContents() = 0 override fun writeToParcel(dest: Parcel, flags: Int) { @@ -137,6 +147,8 @@ class CaldavAccount : Parcelable { companion object { private const val TYPE_CALDAV = 0 const val TYPE_ETESYNC = 1 + const val TYPE_LOCAL = 2 + @JvmField val CREATOR: Parcelable.Creator = object : Parcelable.Creator { override fun createFromParcel(source: Parcel): CaldavAccount? { return CaldavAccount(source) diff --git a/app/src/main/java/org/tasks/data/CaldavDao.kt b/app/src/main/java/org/tasks/data/CaldavDao.kt index 0071ff9a0..7a2dc66e0 100644 --- a/app/src/main/java/org/tasks/data/CaldavDao.kt +++ b/app/src/main/java/org/tasks/data/CaldavDao.kt @@ -1,11 +1,13 @@ package org.tasks.data +import android.content.Context import androidx.lifecycle.LiveData import androidx.room.* import com.todoroo.andlib.utility.DateUtilities.now import com.todoroo.astrid.core.SortHelper.APPLE_EPOCH import com.todoroo.astrid.data.Task -import io.reactivex.Single +import com.todoroo.astrid.helper.UUIDHelper +import org.tasks.R import org.tasks.date.DateTimeUtils.toAppleEpoch import org.tasks.db.DbUtils import org.tasks.filters.CaldavFilters @@ -19,11 +21,14 @@ abstract class CaldavDao { @Query("SELECT * FROM caldav_lists WHERE cdl_uuid = :uuid LIMIT 1") abstract fun getCalendarByUuid(uuid: String): CaldavCalendar? + @Query("SELECT * FROM caldav_lists WHERE cdl_account = :uuid") + abstract fun getCalendarsByAccount(uuid: String): List + @Query("SELECT * FROM caldav_accounts WHERE cda_uuid = :uuid LIMIT 1") abstract fun getAccountByUuid(uuid: String): CaldavAccount? - @Query("SELECT COUNT(*) FROM caldav_accounts") - abstract fun accountCount(): Single + @Query("SELECT COUNT(*) FROM caldav_accounts WHERE cda_account_type != 2") + abstract fun accountCount(): Int @Query("SELECT * FROM caldav_accounts ORDER BY cda_account_type, UPPER(cda_name)") abstract fun getAccounts(): List @@ -239,4 +244,30 @@ abstract class CaldavDao { @Query("SELECT task.*, caldav_task.*, IFNULL(cd_order, (created - $APPLE_EPOCH) / 1000) AS primary_sort FROM caldav_tasks AS caldav_task INNER JOIN tasks AS task ON _id = cd_task WHERE cd_calendar = :calendar AND parent = :parent AND cd_deleted = 0 AND deleted = 0 AND primary_sort >= :from AND primary_sort < IFNULL(:to, ${Long.MAX_VALUE}) ORDER BY primary_sort") internal abstract fun getTasksToShift(calendar: String, parent: Long, from: Long, to: Long?): List + + fun setupLocalAccount(context: Context): CaldavCalendar { + val account = getAccountByUuid(LOCAL) ?: createLocalAccount() + return getCalendarsByAccount(account.uuid!!).getOrElse(0) { + createLocalList(context, account) + } + } + + private fun createLocalAccount(): CaldavAccount { + val account = CaldavAccount() + account.accountType = CaldavAccount.TYPE_LOCAL + account.uuid = LOCAL + account.id = insert(account) + return account + } + + private fun createLocalList(context: Context, account: CaldavAccount): CaldavCalendar { + val list = CaldavCalendar(context.getString(R.string.default_list), UUIDHelper.newUUID()) + list.account = account.uuid + insert(list) + return list + } + + companion object { + const val LOCAL = "local" + } } \ No newline at end of file diff --git a/app/src/main/java/org/tasks/data/DeletionDao.kt b/app/src/main/java/org/tasks/data/DeletionDao.kt index 981e08b3f..5be7ddd56 100644 --- a/app/src/main/java/org/tasks/data/DeletionDao.kt +++ b/app/src/main/java/org/tasks/data/DeletionDao.kt @@ -4,6 +4,7 @@ import androidx.room.Dao import androidx.room.Delete import androidx.room.Query import androidx.room.Transaction +import org.tasks.data.CaldavDao.Companion.LOCAL import org.tasks.db.DbUtils import java.util.* @@ -98,6 +99,9 @@ abstract class DeletionDao { @Delete abstract 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)") + abstract fun purgeDeleted() + @Transaction open fun delete(caldavAccount: CaldavAccount): List { val deleted = ArrayList() diff --git a/app/src/main/java/org/tasks/data/TaskContainer.java b/app/src/main/java/org/tasks/data/TaskContainer.java index 4970f1af2..37f3f1ed5 100644 --- a/app/src/main/java/org/tasks/data/TaskContainer.java +++ b/app/src/main/java/org/tasks/data/TaskContainer.java @@ -189,7 +189,6 @@ public class TaskContainer { } else { task.setParent(parent); } - task.setParentUuid(null); } public boolean hasParent() { diff --git a/app/src/main/java/org/tasks/filters/FilterCriteriaProvider.java b/app/src/main/java/org/tasks/filters/FilterCriteriaProvider.java index c15ae40f1..f4e9bdf8a 100644 --- a/app/src/main/java/org/tasks/filters/FilterCriteriaProvider.java +++ b/app/src/main/java/org/tasks/filters/FilterCriteriaProvider.java @@ -109,9 +109,7 @@ public class FilterCriteriaProvider { if (!googleTaskListDao.getAccounts().isEmpty()) { result.add(getGtasksFilterCriteria()); } - if (!caldavDao.getAccounts().isEmpty()) { - result.add(getCaldavFilterCriteria()); - } + result.add(getCaldavFilterCriteria()); return result; } diff --git a/app/src/main/java/org/tasks/filters/FilterProvider.kt b/app/src/main/java/org/tasks/filters/FilterProvider.kt index e736610f7..b10fff15f 100644 --- a/app/src/main/java/org/tasks/filters/FilterProvider.kt +++ b/app/src/main/java/org/tasks/filters/FilterProvider.kt @@ -16,9 +16,8 @@ import org.tasks.activities.GoogleTaskListSettingsActivity import org.tasks.activities.TagSettingsActivity import org.tasks.billing.Inventory import org.tasks.caldav.BaseCaldavCalendarSettingsActivity -import org.tasks.caldav.CaldavCalendarSettingsActivity import org.tasks.data.* -import org.tasks.etesync.EteSyncCalendarSettingsActivity +import org.tasks.data.CaldavAccount.Companion.TYPE_LOCAL import org.tasks.filters.NavigationDrawerSubheader.SubheaderType import org.tasks.injection.ForApplication import org.tasks.location.LocationPickerActivity @@ -41,13 +40,10 @@ class FilterProvider @Inject constructor( private val preferences: Preferences, private val locationDao: LocationDao) { - val remoteListPickerItems: List + val listPickerItems: List get() { AndroidUtilities.assertNotMainThread() val items: MutableList = ArrayList() - val item = Filter(context.getString(R.string.dont_sync), null) - item.icon = R.drawable.ic_outline_cloud_off_24px - items.add(item) for ((account, value) in googleTaskFilters) { items.addAll( getSubmenu( @@ -173,6 +169,9 @@ class FilterProvider @Inject constructor( } } for ((account, value) in caldavFilters) { + if (account.accountType == TYPE_LOCAL && !preferences.getBoolean(R.string.p_lists_enabled, true)) { + continue + } items.addAll( getSubmenu( account.name, @@ -187,9 +186,7 @@ class FilterProvider @Inject constructor( NavigationDrawerAction( context.getString(R.string.new_list), R.drawable.ic_outline_add_24px, - Intent( - context, - if (account.isCaldavAccount) CaldavCalendarSettingsActivity::class.java else EteSyncCalendarSettingsActivity::class.java) + Intent(context, account.listSettingsClass()) .putExtra(BaseCaldavCalendarSettingsActivity.EXTRA_CALDAV_ACCOUNT, account), NavigationDrawerFragment.REQUEST_NEW_LIST)) } @@ -261,6 +258,9 @@ class FilterProvider @Inject constructor( val accounts = caldavDao.getAccounts() val filters = LinkedHashMap>() for (account in accounts) { + if (account.accountType == TYPE_LOCAL) { + account.name = context.getString(R.string.lists) + } filters[account] = if (account.isCollapsed) { emptyList() } else { diff --git a/app/src/main/java/org/tasks/injection/ActivityComponent.kt b/app/src/main/java/org/tasks/injection/ActivityComponent.kt index b59e294bb..11cac1dc6 100644 --- a/app/src/main/java/org/tasks/injection/ActivityComponent.kt +++ b/app/src/main/java/org/tasks/injection/ActivityComponent.kt @@ -12,6 +12,7 @@ import org.tasks.activities.attribution.AttributionActivity import org.tasks.billing.PurchaseActivity import org.tasks.caldav.CaldavAccountSettingsActivity import org.tasks.caldav.CaldavCalendarSettingsActivity +import org.tasks.caldav.LocalListSettingsActivity import org.tasks.dashclock.DashClockSettings import org.tasks.drive.DriveLoginActivity import org.tasks.etesync.EncryptionSettingsActivity @@ -75,4 +76,5 @@ interface ActivityComponent { fun inject(activity: ManageSpaceActivity) fun inject(activity: SyncPreferences) fun inject(activity: PlaceSettingsActivity) + fun inject(activity: LocalListSettingsActivity) } \ No newline at end of file diff --git a/app/src/main/java/org/tasks/jobs/CleanupWork.java b/app/src/main/java/org/tasks/jobs/CleanupWork.java index f67991f1f..3d657b24b 100644 --- a/app/src/main/java/org/tasks/jobs/CleanupWork.java +++ b/app/src/main/java/org/tasks/jobs/CleanupWork.java @@ -7,6 +7,7 @@ import com.todoroo.astrid.alarms.AlarmService; import com.todoroo.astrid.reminders.ReminderService; import com.todoroo.astrid.timers.TimerPlugin; import javax.inject.Inject; +import org.tasks.data.DeletionDao; import org.tasks.data.Geofence; import org.tasks.data.LocationDao; import org.tasks.data.TaskAttachment; @@ -32,6 +33,7 @@ public class CleanupWork extends InjectingWorker { @Inject TaskAttachmentDao taskAttachmentDao; @Inject UserActivityDao userActivityDao; @Inject LocationDao locationDao; + @Inject DeletionDao deletionDao; public CleanupWork(@NonNull Context context, @NonNull WorkerParameters workerParams) { super(context, workerParams); @@ -64,6 +66,7 @@ public class CleanupWork extends InjectingWorker { } } timerPlugin.updateNotifications(); + deletionDao.purgeDeleted(); return Result.success(); } diff --git a/app/src/main/java/org/tasks/jobs/WorkManager.java b/app/src/main/java/org/tasks/jobs/WorkManager.java index 3d3b5a4d8..b78240c51 100644 --- a/app/src/main/java/org/tasks/jobs/WorkManager.java +++ b/app/src/main/java/org/tasks/jobs/WorkManager.java @@ -31,6 +31,7 @@ import androidx.work.PeriodicWorkRequest; import androidx.work.Worker; import com.google.common.primitives.Longs; import com.todoroo.astrid.data.Task; +import io.reactivex.Single; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; import java.util.Random; @@ -155,7 +156,7 @@ public class WorkManager { (forceAccountPresent == null ? zip( googleTaskListDao.accountCount(), - caldavDao.accountCount(), + Single.fromCallable(caldavDao::accountCount), (googleCount, caldavCount) -> googleCount > 0 || caldavCount > 0) : just(forceAccountPresent)) .subscribeOn(Schedulers.io()) diff --git a/app/src/main/java/org/tasks/preferences/DefaultFilterProvider.kt b/app/src/main/java/org/tasks/preferences/DefaultFilterProvider.kt index 0e8b3ffc1..cb805bfc3 100644 --- a/app/src/main/java/org/tasks/preferences/DefaultFilterProvider.kt +++ b/app/src/main/java/org/tasks/preferences/DefaultFilterProvider.kt @@ -41,8 +41,8 @@ class DefaultFilterProvider @Inject constructor( get() = getFilterFromPreference(R.string.p_last_viewed_list) set(filter) = setFilterPreference(filter, R.string.p_last_viewed_list) - var defaultRemoteList: Filter? - get() = getFilterFromPreference(R.string.p_default_remote_list) + var defaultRemoteList: Filter + get() = getFilterFromPreference(R.string.p_default_remote_list) ?: getAnyList() set(filter) = setFilterPreference(filter, R.string.p_default_remote_list) val startupFilter: Filter? @@ -60,6 +60,14 @@ class DefaultFilterProvider @Inject constructor( fun getFilterFromPreference(prefString: String?): Filter? = getFilterFromPreference(prefString, getMyTasksFilter(context.resources)) + private fun getAnyList(): Filter { + val filter = googleTaskListDao.getAllLists().getOrNull(0) + ?.let { GtasksFilter(it) } + ?: CaldavFilter(caldavDao.getCalendars()[0]) + defaultFilter = filter + return filter + } + private fun getFilterFromPreference(preferenceValue: String?, def: Filter?): Filter? { if (!isNullOrEmpty(preferenceValue)) { try { 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 f5116097e..e6d2b1574 100644 --- a/app/src/main/java/org/tasks/preferences/fragments/Synchronization.kt +++ b/app/src/main/java/org/tasks/preferences/fragments/Synchronization.kt @@ -13,6 +13,7 @@ import org.tasks.R import org.tasks.Strings.isNullOrEmpty import org.tasks.caldav.CaldavAccountSettingsActivity import org.tasks.data.CaldavAccount +import org.tasks.data.CaldavAccount.Companion.TYPE_LOCAL import org.tasks.data.CaldavDao import org.tasks.data.GoogleTaskAccount import org.tasks.data.GoogleTaskListDao @@ -138,7 +139,9 @@ class Synchronization : InjectingPreferenceFragment() { } private fun addCaldavAccounts(category: PreferenceCategory): Boolean { - val accounts: List = caldavDao.getAccounts() + val accounts: List = caldavDao.getAccounts().filter { + it.accountType != TYPE_LOCAL + } for (account in accounts) { val preference = Preference(context) preference.title = account.name diff --git a/app/src/main/java/org/tasks/preferences/fragments/TaskDefaults.kt b/app/src/main/java/org/tasks/preferences/fragments/TaskDefaults.kt index 20c791f55..ca5a5ad50 100644 --- a/app/src/main/java/org/tasks/preferences/fragments/TaskDefaults.kt +++ b/app/src/main/java/org/tasks/preferences/fragments/TaskDefaults.kt @@ -18,9 +18,9 @@ import org.tasks.preferences.DefaultFilterProvider import org.tasks.preferences.Preferences import javax.inject.Inject -private const val FRAG_TAG_REMOTE_LIST_SELECTION = "frag_tag_remote_list_selection" +private const val FRAG_TAG_DEFAULT_LIST_SELECTION = "frag_tag_default_list_selection" private const val FRAG_TAG_CALENDAR_PICKER = "frag_tag_calendar_picker" -private const val REQUEST_REMOTE_LIST = 10010 +private const val REQUEST_DEFAULT_LIST = 10010 private const val REQUEST_CALENDAR_SELECTION = 10011 class TaskDefaults : InjectingPreferenceFragment() { @@ -47,11 +47,10 @@ class TaskDefaults : InjectingPreferenceFragment() { findPreference(R.string.p_default_remote_list) .setOnPreferenceClickListener { ListPicker.newListPicker( - defaultFilterProvider.defaultRemoteList, - this, - REQUEST_REMOTE_LIST - ) - .show(parentFragmentManager, FRAG_TAG_REMOTE_LIST_SELECTION) + defaultFilterProvider.defaultRemoteList, + this, + REQUEST_DEFAULT_LIST) + .show(parentFragmentManager, FRAG_TAG_DEFAULT_LIST_SELECTION) false } updateRemoteListSummary() @@ -60,11 +59,9 @@ class TaskDefaults : InjectingPreferenceFragment() { } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - if (requestCode == REQUEST_REMOTE_LIST) { + if (requestCode == REQUEST_DEFAULT_LIST) { val list: Filter? = data!!.getParcelableExtra(ListPicker.EXTRA_SELECTED_FILTER) - if (list == null) { - preferences.setString(R.string.p_default_remote_list, null) - } else if (list is GtasksFilter || list is CaldavFilter) { + if (list is GtasksFilter || list is CaldavFilter) { defaultFilterProvider.defaultRemoteList = list } else { throw RuntimeException("Unhandled filter type") @@ -91,9 +88,7 @@ class TaskDefaults : InjectingPreferenceFragment() { private fun updateRemoteListSummary() { val defaultFilter = defaultFilterProvider.defaultRemoteList - findPreference(R.string.p_default_remote_list).summary = - if (defaultFilter == null) getString(R.string.dont_sync) - else defaultFilter.listingTitle + findPreference(R.string.p_default_remote_list).summary = defaultFilter.listingTitle } override fun inject(component: FragmentComponent) = component.inject(this) diff --git a/app/src/main/java/org/tasks/sync/SyncAdapters.java b/app/src/main/java/org/tasks/sync/SyncAdapters.java index 9baebbffc..fff4c4871 100644 --- a/app/src/main/java/org/tasks/sync/SyncAdapters.java +++ b/app/src/main/java/org/tasks/sync/SyncAdapters.java @@ -46,6 +46,6 @@ public class SyncAdapters { } public boolean isCaldavSyncEnabled() { - return caldavDao.getAccounts().size() > 0; + return caldavDao.accountCount() > 0; } } diff --git a/app/src/main/java/org/tasks/ui/ListFragment.kt b/app/src/main/java/org/tasks/ui/ListFragment.kt index 19a93854c..a08e248e5 100644 --- a/app/src/main/java/org/tasks/ui/ListFragment.kt +++ b/app/src/main/java/org/tasks/ui/ListFragment.kt @@ -6,7 +6,6 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.TextView import butterknife.BindView import com.google.android.material.chip.ChipGroup import com.todoroo.astrid.api.CaldavFilter @@ -26,9 +25,6 @@ import org.tasks.preferences.DefaultFilterProvider import javax.inject.Inject class ListFragment : TaskEditControlFragment() { - @BindView(R.id.dont_sync) - lateinit var textView: TextView - @BindView(R.id.chip_group) lateinit var chipGroup: ChipGroup @@ -39,8 +35,8 @@ class ListFragment : TaskEditControlFragment() { @Inject lateinit var taskMover: TaskMover @Inject lateinit var chipProvider: ChipProvider - private var originalList: Filter? = null - private var selectedList: Filter? = null + private lateinit var originalList: Filter + private lateinit var selectedList: Filter private lateinit var callback: OnListChanged interface OnListChanged { @@ -56,8 +52,8 @@ class ListFragment : TaskEditControlFragment() { inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { val view = super.onCreateView(inflater, container, savedInstanceState) if (savedInstanceState != null) { - originalList = savedInstanceState.getParcelable(EXTRA_ORIGINAL_LIST) - setSelected(savedInstanceState.getParcelable(EXTRA_SELECTED_LIST)) + originalList = savedInstanceState.getParcelable(EXTRA_ORIGINAL_LIST)!! + setSelected(savedInstanceState.getParcelable(EXTRA_SELECTED_LIST)!!) } else { if (task.isNew) { if (task.hasTransitory(GoogleTask.KEY)) { @@ -94,7 +90,7 @@ class ListFragment : TaskEditControlFragment() { return view } - private fun setSelected(filter: Filter?) { + private fun setSelected(filter: Filter) { selectedList = filter refreshView() callback.onListChanged(filter) @@ -102,12 +98,8 @@ class ListFragment : TaskEditControlFragment() { override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) - if (originalList != null) { - outState.putParcelable(EXTRA_ORIGINAL_LIST, originalList) - } - if (selectedList != null) { - outState.putParcelable(EXTRA_SELECTED_LIST, selectedList) - } + outState.putParcelable(EXTRA_ORIGINAL_LIST, originalList) + outState.putParcelable(EXTRA_SELECTED_LIST, selectedList) } override val layout: Int @@ -135,7 +127,6 @@ class ListFragment : TaskEditControlFragment() { override fun apply(task: Task) { if (isNew || hasChanges()) { task.parent = 0 - task.parentUuid = null taskMover.move(listOf(task.id), selectedList) } } @@ -153,17 +144,17 @@ class ListFragment : TaskEditControlFragment() { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { if (requestCode == REQUEST_CODE_SELECT_LIST) { if (resultCode == Activity.RESULT_OK) { - setList(data?.getParcelableExtra(ListPicker.EXTRA_SELECTED_FILTER)) + data?.getParcelableExtra(ListPicker.EXTRA_SELECTED_FILTER)?.let { + setList(it) + } } } else { super.onActivityResult(requestCode, resultCode, data) } } - private fun setList(list: Filter?) { - if (list == null) { - setSelected(null) - } else if (list is GtasksFilter || list is CaldavFilter) { + private fun setList(list: Filter) { + if (list is GtasksFilter || list is CaldavFilter) { setSelected(list) } else { throw RuntimeException("Unhandled filter type") @@ -171,19 +162,10 @@ class ListFragment : TaskEditControlFragment() { } private fun refreshView() { - if (selectedList == null) { - textView.visibility = View.VISIBLE - chipGroup.visibility = View.GONE - } else { - textView.visibility = View.GONE - chipGroup.visibility = View.VISIBLE - chipGroup.removeAllViews() - val chip = chipProvider.newChip(selectedList, R.drawable.ic_list_24px, true, true) - chip.isCloseIconVisible = true - chip.setOnClickListener { openPicker() } - chip.setOnCloseIconClickListener { setSelected(null) } - chipGroup.addView(chip) - } + chipGroup.removeAllViews() + val chip = chipProvider.newChip(selectedList, R.drawable.ic_list_24px, true, true) + chip.setOnClickListener { openPicker() } + chipGroup.addView(chip) } companion object { diff --git a/app/src/main/java/org/tasks/ui/SubtaskControlSet.kt b/app/src/main/java/org/tasks/ui/SubtaskControlSet.kt index 719556458..0ef2ace44 100644 --- a/app/src/main/java/org/tasks/ui/SubtaskControlSet.kt +++ b/app/src/main/java/org/tasks/ui/SubtaskControlSet.kt @@ -136,7 +136,6 @@ class SubtaskControlSet : TaskEditControlFragment(), SubtaskViewHolder.Callbacks } else -> { subtask.parent = task.id - subtask.parentUuid = task.uuid taskDao.save(subtask) } } diff --git a/app/src/main/res/layout/control_set_remote_list.xml b/app/src/main/res/layout/control_set_remote_list.xml index 27820248b..e8326dcae 100644 --- a/app/src/main/res/layout/control_set_remote_list.xml +++ b/app/src/main/res/layout/control_set_remote_list.xml @@ -1,27 +1,8 @@ - - - - - - - - + app:chipSpacingVertical="@dimen/chip_spacing" + app:chipSpacingHorizontal="@dimen/chip_spacing" /> diff --git a/app/src/main/res/values-bg-rBG/strings.xml b/app/src/main/res/values-bg-rBG/strings.xml index 69866a89f..2703b52bf 100644 --- a/app/src/main/res/values-bg-rBG/strings.xml +++ b/app/src/main/res/values-bg-rBG/strings.xml @@ -419,7 +419,6 @@ Показвай броя задачи върху икона на Tasks в лаунчера. Не всички лаунчери поддържат значки. Комбинирай множество нотификации в една на един и същ ден всеки месец - Не синхронизирай всеки %1$s %2$s на всеки %1$s %2$s първи diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index e12e9c99c..cce5ce5ea 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -434,7 +434,6 @@ Zobrazit počet úkolů u ikony Tasks. Některé spouštěče tuto funkci nepodporují. Seskupit několik upozornění do jednoho ve stejný den každý měsíc - Nesynchronizovat každý %1$s %2$s první druhý diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 7b6b032eb..f54112070 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -410,7 +410,6 @@ Anzeige eines Aufgabenzählers am Tasks Launcher Icon. Nicht alle Launcher unterstützen Badges. Mehrere Benachrichtigungen in einer zusammenfassen am selben Tag jeden Monats - Nicht synchronisieren jeden %1$s %2$s an jedem %1$s %2$s ersten diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 0598bbf3a..9c6e318f7 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -418,7 +418,6 @@ Mostrar número de tareas en icono de Task. No todos los launchers lo soportan. Combinar múltiples notificaciones en una sola el mismo día cada mes - No sincronizar cada %1$s %2$s cada %1$s %2$s primer diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml index 3f2384ac4..16f1d46cb 100644 --- a/app/src/main/res/values-et/strings.xml +++ b/app/src/main/res/values-et/strings.xml @@ -254,7 +254,6 @@ Kalendri seaded Koonda teavitused Nimekiri - Ära sünkrooni esimene teine kolmas diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index 6932d50b5..4b0a8193e 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -424,7 +424,6 @@ Bistaratu zeregin kopurua abiarazleko Tasks ikonoan. Abiarazle guztiek ez dituzte dominak onartzen. Taldekatu hainbat jakinarazpen batean egun berean hilero - Ez sinkronizatu %1$s %2$s bakoitzean %1$s %2$s bakoitzean lehen diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 1fb6971a6..8827c0764 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -391,7 +391,6 @@ Näytä tehtävien lukumäärä Tasksin käynnistyskuvakkeessa. Kaikki käynnistimet eivät tue merkkejä. Yhdistä useita ilmoituksia yhdeksi sama päivä joka kuukausi - Älä synkronoi joka %1$s %2$s jokaisella %1$s %2$s ensimmäinen diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 8dfc3f3ac..667146a09 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -400,7 +400,6 @@ Afficher un compteur de tâche sur l\'icône du lanceur de Tasks. Certains lanceurs ne supportent pas les badges. Combiner plusieurs notifications en une seule le même jour chaque mois - Ne pas synchroniser tous les %1$s %2$s tous les %1$s %2$s première diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index e66753c60..8b668a1fc 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -419,7 +419,6 @@ Feladatok számának megjelenítése a Tasks ikonon. Nem minden launcher által támogatott funkció. Több értesítés összevonása eggyé minden hónap egyazon napján - Szinkronizáció kikapcsolva minden %1$s %2$s minden %1$s %2$s első diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml index b5ec669a0..83cf6c4d6 100644 --- a/app/src/main/res/values-id/strings.xml +++ b/app/src/main/res/values-id/strings.xml @@ -352,7 +352,6 @@ Tampilkan jumlah tugas pada ikon peluncur Tasks. Tidak semua peluncur mendukung fitur ini. Gabung beberapa notifikasi menjadi satu notifikasi pada hari yang sama setiap bulan - Jangan sinkron pertama kedua ketiga diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index afa17b228..f536ffc7f 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -415,7 +415,6 @@ Mostra contatore di notifiche sull\'icona di Task. Non tutti i launcher lo supportano. Combina diverse notifiche in una sola lo stesso giorno di ogni mese - Non sincronizzare ogni %1$s %2$s ogni %1$s %2$s primo diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index 496b45d30..00ef7015c 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -453,7 +453,6 @@ הצג מספר משימות על סמליל משגר Tasks. לא כל המשגרים תומכים בתגים. שלב מספר התראות בהתראה אחת באותו היום בכל חודש - ללא סנכרון בכל %1$s %2$s בכל %1$s %2$s ראשון diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 65193b96e..11985ba8c 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -416,7 +416,6 @@ Tasks ランチャーアイコンにタスク数を表示します。 すべてのランチャーがバッジをサポートしているわけではありません。 複数の通知を1つの通知にまとめる 毎月同じ日に - 同期しない %1$s %2$s ごと %1$s %2$s ごとに 第一週 diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 309c554aa..139f6193b 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -418,7 +418,6 @@ Tasks 앱 아이콘 위에 할일 개수를 표시합니다. 모든 런처가 배지 기능을 지원하지는 않습니다. 상태바에 알림이 여러 개 있을 경우 하나로 모아서 표시합니다 매월 같은 날에 - 동기화하지 않음 매 %1$s %2$s 매 %1$s %2$s 마다 첫번째 diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index 52ef9232c..f4d62f064 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -415,7 +415,6 @@ Rodyti užduočių kiekį Tasks paleidimo piktogramoje. Ne visos sistemos palaiko šią funkciją. Sujungti kelis pranešimus į vieną pranešimą Tą pačią mėnesio dieną - Nesinchronizuoti Kiekvieną %1$s %2$s Kiekvieną %1$s %2$s pirmą diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index 89bdbabb5..bb494c242 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -424,7 +424,6 @@ Forvalgt kalender Vis gjøremålsantall i Task-oppstarterikonet. Ikke alle oppstartere støtter merker. på samme dag hver måned - Ikke synkroniser hver %1$s %2$s hver %1$s %2$s første diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 9a7effb9e..49e3aaa00 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -409,7 +409,6 @@ Toon een taken teller bij de Tasks app icon. Niet alle launchers ondersteunen dit. Combineer meerdere notificaties samen in één Op dezelfde dag elke maand - Niet synchroniseren elke %1$s %2$s op elke %1$s %2$s eerste diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 1dbe6a04b..3a200304d 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -430,7 +430,6 @@ Wyświetl liczbę zadań na ikonie Tasks. Nie wszystkie launchery to wspierają. Wyświetlaj wiele powiadomień jako jedno tego samego dnia każdego miesiąca - Nie synchronizowane każdy %1$s %2$s co każde %1$s %2$s pierwszy diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 30204fa4c..011dc53f7 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -416,7 +416,6 @@ Mostrar a contagem de tarefas no ícone do Tasks no launcher. Nem todos os launchers suportam emblemas. Combinar múltiplas notificações em uma única notificação no mesmo dia cada mês - Não sincronizar todo %1$s %2$s em todo %1$s %2$s primeiro diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 2dd2aa535..337f6217b 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -436,7 +436,6 @@ Отображать количество задач на иконке приложения. Не все лаунчеры это поддерживают. Группировать несколько уведомлений в одно общее в тот же день ежемесячно - Не синхронизировать каждый %1$s %2$s в каждый %1$s %2$s первая diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index fdd476b12..359602f4b 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -415,7 +415,6 @@ Zobraziť počet úloh na ikone spustenia Úloh. Niektoré spúšťače nepodporujú odznaky. Zlúč viaceré upozornenia do jedného v ten istý deň v každom mesiaci - Nesynchronizovať každý %1$s %2$s na každý %1$s %2$s prvý diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 044e16e1e..8ba3c0737 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -419,7 +419,6 @@ Visa en en summering av uppgifter på Tasks ikon med ett märke. Inte alla hemskärmsappar stödjer märken. Kombinera flera aviseringar i ett enda meddelande samma dag varje månad - Synkronisera inte varje %1$s %2$s på varje %1$s %2$s första diff --git a/app/src/main/res/values-tl/strings.xml b/app/src/main/res/values-tl/strings.xml index 6eee73585..942ac5260 100644 --- a/app/src/main/res/values-tl/strings.xml +++ b/app/src/main/res/values-tl/strings.xml @@ -61,7 +61,6 @@ Magdagdag ng account Gumagamit Mga baterya optimization ay maaaring antalahin ang mga notification - Huwag i-sync Sa metered connections laang Ipaalala sa pagdating Dumating sa %s diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 0840da2a7..4782fbdfd 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -421,7 +421,6 @@ Tasks başlatıcı simgesinde görev sayısı göster. Tüm başlatıcılar rozetleri desteklemez. Birden çok bildirimi tek bildirime birleştir her ayın aynı gününde - Eşzamanlama yapma her %1$s %2$s her %1$s %2$s birinci diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 65dacca49..05bf084cd 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -434,7 +434,6 @@ Відображати кількість задач на іконці запуску Tasks. Не всі лаунчери підтримують такі значки. Згрупувати декілька сповіщень в одне того ж дня щомісяця - Не синхронізувати що %1$s %2$s що %1$s %2$s перший(а) diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 51626b05c..6a4198c50 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -402,7 +402,6 @@ 在Tasks启动图标上显示任务计数。不是所有的启动器都支持角标。 将多个通知合并为一个通知 在每月的同一天 - 不同步 每 %1$s %2$s 在每 %1$s 个 %2$s 第一个 diff --git a/app/src/main/res/values/keys.xml b/app/src/main/res/values/keys.xml index d87d3e138..d997ab445 100644 --- a/app/src/main/res/values/keys.xml +++ b/app/src/main/res/values/keys.xml @@ -61,6 +61,7 @@ drawer_tags_enabled drawer_tags_hide_unused drawer_places_enabled + drawer_lists_enabled drawer_places_hide_unused diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a07d7d215..cbded1f2c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -465,7 +465,6 @@ File %1$s contained %2$s.\n\n Display a task count on Tasks\' launcher icon. Not all launchers support badges. Combine multiple notifications into one on the same day each month - Don\'t sync every %1$s %2$s on every %1$s %2$s first @@ -630,4 +629,5 @@ File %1$s contained %2$s.\n\n Modified %s On launch Open last viewed list + Lists diff --git a/app/src/main/res/xml/preferences_navigation_drawer.xml b/app/src/main/res/xml/preferences_navigation_drawer.xml index d7ceffe40..67b05a16a 100644 --- a/app/src/main/res/xml/preferences_navigation_drawer.xml +++ b/app/src/main/res/xml/preferences_navigation_drawer.xml @@ -51,4 +51,11 @@ + + + + \ No newline at end of file