Merge branch '13.9.8'

pull/2908/head
Alex Baker 4 weeks ago
commit be861597ef

@ -1,3 +1,8 @@
### 13.9.8 (2024-05-30)
* Fix import backup crashes
* Fix showing completed subtasks in edit screen
### 13.9.7 (2024-05-23) ### 13.9.7 (2024-05-23)
* Add default reminders when adding start/due dates to existing tasks [#1846](https://github.com/tasks/tasks/issues/1846) * Add default reminders when adding start/due dates to existing tasks [#1846](https://github.com/tasks/tasks/issues/1846)

@ -54,8 +54,8 @@ android {
defaultConfig { defaultConfig {
testApplicationId = "org.tasks.test" testApplicationId = "org.tasks.test"
applicationId = "org.tasks" applicationId = "org.tasks"
versionCode = 130907 versionCode = 130908
versionName = "13.9.7" versionName = "13.9.8"
targetSdk = libs.versions.android.targetSdk.get().toInt() targetSdk = libs.versions.android.targetSdk.get().toInt()
minSdk = libs.versions.android.minSdk.get().toInt() minSdk = libs.versions.android.minSdk.get().toInt()
testInstrumentationRunner = "org.tasks.TestRunner" testInstrumentationRunner = "org.tasks.TestRunner"

@ -30,6 +30,7 @@ interface Filter : FilterListItem, Parcelable {
fun supportsHiddenTasks(): Boolean = true fun supportsHiddenTasks(): Boolean = true
fun supportsSubtasks(): Boolean = true fun supportsSubtasks(): Boolean = true
fun supportsSorting(): Boolean = true fun supportsSorting(): Boolean = true
fun disableHeaders(): Boolean = !supportsSorting()
} }
@Deprecated("Use manual ordering") @Deprecated("Use manual ordering")

@ -42,15 +42,14 @@ class BackupContainer(
@Serializable @Serializable
class TaskBackup( class TaskBackup(
val task: Task, val task: Task,
val alarms: List<Alarm>, val alarms: List<Alarm>?,
val geofences: List<Geofence>?, val geofences: List<Geofence>?,
val tags: List<Tag>, val tags: List<Tag>?,
val comments: List<UserActivity>, val comments: List<UserActivity>?,
val attachments: List<Attachment>?, val attachments: List<Attachment>?,
val caldavTasks: List<CaldavTask>?, val caldavTasks: List<CaldavTask>?,
val vtodo: String? = null, val vtodo: String?,
val google: List<GoogleTask> = emptyList(), val google: List<GoogleTask>? = null,
) { val locations: List<LegacyLocation>? = null,
val locations: List<LegacyLocation> = emptyList() )
}
} }

@ -93,7 +93,7 @@ class TasksJsonImporter @Inject constructor(
try { try {
val data = input.jsonObject["data"]!! val data = input.jsonObject["data"]!!
val version = input.jsonObject["version"]!!.jsonPrimitive.int val version = input.jsonObject["version"]!!.jsonPrimitive.int
val backupContainer = Json.decodeFromJsonElement<BackupContainer>(data) val backupContainer = json.decodeFromJsonElement<BackupContainer>(data)
backupContainer.tags?.forEach { tagData -> backupContainer.tags?.forEach { tagData ->
findTagData(tagData)?.let { findTagData(tagData)?.let {
return@forEach return@forEach
@ -204,7 +204,7 @@ class TasksJsonImporter @Inject constructor(
taskDao.createNew(task) taskDao.createNew(task)
val taskId = task.id val taskId = task.id
val taskUuid = task.uuid val taskUuid = task.uuid
alarmDao.insert(backup.alarms.map { it.copy(task = taskId) }) backup.alarms?.map { it.copy(task = taskId) }?.let { alarmDao.insert(it) }
if (version < V12_4) { if (version < V12_4) {
task.defaultReminders(task.ringFlags) task.defaultReminders(task.ringFlags)
alarmDao.insert(task.getDefaultAlarms()) alarmDao.insert(task.getDefaultAlarms())
@ -219,14 +219,14 @@ class TasksJsonImporter @Inject constructor(
task.repeatFrom = task.recurrence.repeatFrom() task.repeatFrom = task.recurrence.repeatFrom()
task.recurrence = task.recurrence.withoutFrom() task.recurrence = task.recurrence.withoutFrom()
} }
for (comment in backup.comments) { backup.comments?.forEach { comment ->
comment.targetId = taskUuid comment.targetId = taskUuid
if (version < V6_4) { if (version < V6_4) {
comment.convertPictureUri() comment.convertPictureUri()
} }
userActivityDao.createNew(comment) userActivityDao.createNew(comment)
} }
for (googleTask in backup.google) { backup.google?.forEach { googleTask ->
caldavDao.insert( caldavDao.insert(
CaldavTask( CaldavTask(
task = taskId, task = taskId,
@ -238,7 +238,7 @@ class TasksJsonImporter @Inject constructor(
) )
) )
} }
for (location in backup.locations) { backup.locations?.forEach { location ->
val place = Place( val place = Place(
longitude = location.longitude, longitude = location.longitude,
latitude = location.latitude, latitude = location.latitude,
@ -257,8 +257,8 @@ class TasksJsonImporter @Inject constructor(
) )
) )
} }
for (tag in backup.tags) { backup.tags?.forEach tags@ { tag ->
val tagData = findTagData(tag) ?: continue val tagData = findTagData(tag) ?: return@tags
tagDao.insert( tagDao.insert(
tag.copy( tag.copy(
task = taskId, task = taskId,
@ -350,6 +350,7 @@ class TasksJsonImporter @Inject constructor(
var skipCount = 0 var skipCount = 0
} }
@Deprecated("For backup use only")
@Serializable @Serializable
class LegacyLocation { class LegacyLocation {
var name: String? = null var name: String? = null
@ -364,6 +365,7 @@ class TasksJsonImporter @Inject constructor(
} }
companion object { companion object {
private val json = Json { ignoreUnknownKeys = true}
private val ignorePrefs = intArrayOf( private val ignorePrefs = intArrayOf(
R.string.p_current_version, R.string.p_current_version,
R.string.p_backups_android_backup_last R.string.p_backups_android_backup_last

@ -0,0 +1,34 @@
package org.tasks.filters
import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.api.FilterListItem
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
import org.tasks.data.dao.TaskDao
import org.tasks.data.entity.Task
import org.tasks.data.sql.Criterion
import org.tasks.data.sql.QueryTemplate
@Parcelize
data class SubtaskFilter(
private val parent: Long,
) : Filter {
@IgnoredOnParcel
override val title: String = "subtasks"
@IgnoredOnParcel
override val sql: String =
QueryTemplate()
.where(
Criterion.and(
TaskDao.TaskCriteria.activeAndVisible(),
Task.PARENT.eq(parent)
)
)
.toString()
override fun disableHeaders() = true
override fun areItemsTheSame(other: FilterListItem): Boolean =
other is SubtaskFilter && parent == other.parent
}

@ -9,12 +9,8 @@ import androidx.fragment.app.activityViewModels
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.google.android.material.composethemeadapter.MdcTheme import com.google.android.material.composethemeadapter.MdcTheme
import org.tasks.data.sql.Criterion
import org.tasks.data.sql.QueryTemplate
import com.todoroo.astrid.activity.MainActivityViewModel import com.todoroo.astrid.activity.MainActivityViewModel
import com.todoroo.astrid.api.FilterImpl
import com.todoroo.astrid.dao.TaskDao import com.todoroo.astrid.dao.TaskDao
import org.tasks.data.entity.Task
import com.todoroo.astrid.service.TaskCompleter import com.todoroo.astrid.service.TaskCompleter
import com.todoroo.astrid.service.TaskCreator import com.todoroo.astrid.service.TaskCreator
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
@ -23,7 +19,8 @@ import org.tasks.R
import org.tasks.compose.collectAsStateLifecycleAware import org.tasks.compose.collectAsStateLifecycleAware
import org.tasks.compose.edit.SubtaskRow import org.tasks.compose.edit.SubtaskRow
import org.tasks.data.dao.GoogleTaskDao import org.tasks.data.dao.GoogleTaskDao
import org.tasks.data.dao.TaskDao.TaskCriteria.activeAndVisible import org.tasks.data.entity.Task
import org.tasks.filters.SubtaskFilter
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
import org.tasks.tasklist.SectionedDataSource import org.tasks.tasklist.SectionedDataSource
import org.tasks.themes.ColorProvider import org.tasks.themes.ColorProvider
@ -47,7 +44,7 @@ class SubtaskControlSet : TaskEditControlFragment() {
override fun createView(savedInstanceState: Bundle?) { override fun createView(savedInstanceState: Bundle?) {
viewModel.task.takeIf { it.id > 0 }?.let { viewModel.task.takeIf { it.id > 0 }?.let {
listViewModel.setFilter(FilterImpl("subtasks", getQueryTemplate(it))) listViewModel.setFilter(SubtaskFilter(it.id))
} }
} }
@ -112,13 +109,5 @@ class SubtaskControlSet : TaskEditControlFragment() {
companion object { companion object {
val TAG = R.string.TEA_ctrl_subtask_pref val TAG = R.string.TEA_ctrl_subtask_pref
private fun getQueryTemplate(task: Task): String = QueryTemplate()
.where(
Criterion.and(
activeAndVisible(),
Task.PARENT.eq(task.id)
)
)
.toString()
} }
} }

@ -30,11 +30,11 @@ import org.tasks.R
import org.tasks.analytics.Firebase import org.tasks.analytics.Firebase
import org.tasks.billing.Inventory import org.tasks.billing.Inventory
import org.tasks.compose.throttleLatest import org.tasks.compose.throttleLatest
import org.tasks.data.dao.DeletionDao
import org.tasks.data.entity.Task
import org.tasks.data.TaskContainer import org.tasks.data.TaskContainer
import org.tasks.data.dao.TaskDao
import org.tasks.data.TaskListQuery.getQuery import org.tasks.data.TaskListQuery.getQuery
import org.tasks.data.dao.DeletionDao
import org.tasks.data.dao.TaskDao
import org.tasks.data.entity.Task
import org.tasks.data.fetchTasks import org.tasks.data.fetchTasks
import org.tasks.db.QueryUtils import org.tasks.db.QueryUtils
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
@ -156,7 +156,7 @@ class TaskListViewModel @Inject constructor(
tasks = TasksResults.Results( tasks = TasksResults.Results(
SectionedDataSource( SectionedDataSource(
tasks = tasks, tasks = tasks,
disableHeaders = !it.filter.supportsSorting() disableHeaders = it.filter.disableHeaders()
|| (it.filter.supportsManualSort() && preferences.isManualSort) || (it.filter.supportsManualSort() && preferences.isManualSort)
|| (it.filter is AstridOrderingFilter && preferences.isAstridSort), || (it.filter is AstridOrderingFilter && preferences.isAstridSort),
groupMode = preferences.groupMode, groupMode = preferences.groupMode,

@ -0,0 +1,2 @@
* Fix import backup crashes
* Fix showing completed subtasks in edit screen
Loading…
Cancel
Save