Skip to content

Commit 7aab903

Browse files
committed
Allow syncing local only subtask even when parent task is already synced
1 parent ab01b88 commit 7aab903

File tree

1 file changed

+18
-29
lines changed

1 file changed

+18
-29
lines changed

tasks-core/src/commonMain/kotlin/net/opatry/tasks/data/TaskRepository.kt

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -351,8 +351,6 @@ class TaskRepository(
351351
pushLocalTasks(
352352
localTaskListId = taskList.id,
353353
remoteTaskListId = remoteTaskListId,
354-
localParentTaskId = null,
355-
remoteParentTaskId = null,
356354
localOnlyTasks,
357355
)
358356
} ?: emptyList()
@@ -407,53 +405,44 @@ class TaskRepository(
407405
private suspend fun pushLocalTasks(
408406
localTaskListId: Long,
409407
remoteTaskListId: String,
410-
localParentTaskId: Long?,
411-
remoteParentTaskId: String?,
412408
tasks: List<LocalTask>
413409
): List<LocalTask> {
414-
val tasksToSync = computeTaskPositions(tasks.filter { it.parentTaskLocalId == localParentTaskId })
415-
var previousTaskId: String? = null
416-
return buildList {
410+
// iterate on tasks grouped by parent, top-level tasks being processed first
411+
val allTasksToSync = tasks.groupBy(LocalTask::parentTaskLocalId)
412+
.toSortedMap(compareBy<Any?> { it != null }) // null comes first
413+
.toMutableMap()
414+
val syncedTasks = mutableMapOf<Long, LocalTask>()
415+
val syncFailedTaskIds = mutableListOf<Long>()
416+
allTasksToSync.onEach { (localParentTaskId, tasksToSync) ->
417+
// don't try syncing sub tasks if parent task failed, it would break hierarchy on remote side
418+
if (localParentTaskId in syncFailedTaskIds) return@onEach
419+
420+
var previousTaskId: String? = null
417421
tasksToSync.onEach { localTask ->
418422
val remoteTask = withContext(Dispatchers.IO) {
419423
try {
420424
tasksApi.insert(
421425
taskListId = remoteTaskListId,
422426
task = localTask.asTask(),
423-
parentTaskId = remoteParentTaskId,
427+
parentTaskId = syncedTasks[localParentTaskId]?.remoteId,
424428
previousTaskId = previousTaskId,
425429
).also { remoteTask ->
426-
// ensure up to date local parent after sync
427-
val localParentTask = remoteTask.parent?.let { taskDao.getByRemoteId(it) }
428-
add(
429-
remoteTask.asTaskEntity(
430-
parentListLocalId = localTaskListId,
431-
parentTaskLocalId = localParentTask?.id,
432-
taskLocalId = localTask.id,
433-
)
430+
syncedTasks[localTask.id] = remoteTask.asTaskEntity(
431+
parentListLocalId = localTaskListId,
432+
parentTaskLocalId = localParentTaskId,
433+
taskLocalId = localTask.id,
434434
)
435435
}
436436
} catch (_: Exception) {
437+
syncFailedTaskIds += localTask.id
437438
null
438439
}
439440
}
440441
// FIXME if one of the task sync fails, it breaks sibling order
441442
previousTaskId = remoteTask?.id
442-
443-
// don't try syncing sub tasks if parent task failed, it would break hierarchy on remote side
444-
if (remoteTask != null) {
445-
addAll(
446-
pushLocalTasks(
447-
localTaskListId = localTaskListId,
448-
remoteTaskListId = remoteTaskListId,
449-
localParentTaskId = localTask.id,
450-
remoteParentTaskId = remoteTask.id,
451-
tasks = tasks,
452-
)
453-
)
454-
}
455443
}
456444
}
445+
return syncedTasks.values.toList()
457446
}
458447

459448
suspend fun createTaskList(title: String): Long {

0 commit comments

Comments
 (0)