Assign category positions inside the database

A new category's position is computed by its insert, one after the highest, so two categories created at once can't take the same one. Inserts take a NewCategory rather than a Category whose id and position would be ignored. Reordering places any category missing from the given order after the rest instead of leaving it at a stale position. Restore still creates missing categories all or none, in backup order, and the create dialog no longer accepts an empty name.
This commit is contained in:
AntsyLich
2026-09-27 22:53:09 +06:00
parent fc5592ff75
commit 8bfa495f34
8 changed files with 42 additions and 46 deletions
@@ -110,7 +110,7 @@ fun CategoryRenameDialog(
onDismissRequest = onDismissRequest,
confirmButton = {
TextButton(
enabled = valueHasChanged && !nameAlreadyExists,
enabled = valueHasChanged && name.isNotEmpty() && !nameAlreadyExists,
onClick = {
onRename(name)
onDismissRequest()
@@ -11,14 +11,7 @@ class BackupCategory(
@ProtoNumber(3) var id: Long = 0,
// @ProtoNumber(3) val updateInterval: Int = 0, 1.x value not used in 0.x
@ProtoNumber(100) var flags: Long = 0,
) {
fun toCategory(id: Long) = Category(
id = id,
name = this@BackupCategory.name,
flags = this@BackupCategory.flags,
order = this@BackupCategory.order,
)
}
)
val backupCategoryMapper = { category: Category ->
BackupCategory(
@@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.data.backup.restore.restorers
import dev.zacsweers.metro.Inject
import eu.kanade.tachiyomi.data.backup.models.BackupCategory
import tachiyomi.domain.category.interactor.GetCategories
import tachiyomi.domain.category.model.NewCategory
import tachiyomi.domain.category.repository.CategoryRepository
import tachiyomi.domain.library.service.LibraryPreferences
@@ -14,22 +15,20 @@ class CategoriesRestorer(
) {
suspend operator fun invoke(backupCategories: List<BackupCategory>) {
if (backupCategories.isNotEmpty()) {
val dbCategories = getCategories.await()
val dbCategoriesByName = dbCategories.associateBy { it.name }
var nextOrder = dbCategories.maxOfOrNull { it.order }?.plus(1) ?: 0
if (backupCategories.isEmpty()) return
val categories = backupCategories
.sortedBy { it.order }
.filter { it.name !in dbCategoriesByName }
.map { it.toCategory(id = 0).copy(order = nextOrder++) }
categoryRepository.insertAll(categories)
val dbCategories = getCategories.await()
val dbCategoryNames = dbCategories.mapTo(HashSet()) { it.name }
libraryPreferences.categorizedDisplaySettings.set(
(dbCategories + categories)
.distinctBy { it.flags }
.size > 1,
)
val newCategories = backupCategories
.filter { it.name !in dbCategoryNames }
.sortedBy { it.order }
categoryRepository.insertAll(newCategories.map { NewCategory(name = it.name, flags = it.flags) })
val flags = buildSet {
dbCategories.mapTo(this) { it.flags }
newCategories.mapTo(this) { it.flags }
}
libraryPreferences.categorizedDisplaySettings.set(flags.size > 1)
}
}