chore: Avoid race conditions and improve bulk selection (#1606)

* avoid race conditions

* Improve Bulk selection

* Consolidate selection mode updates and list clearing into a single state update.
This commit is contained in:
Cuong-Tran 2026-04-23 16:30:55 +07:00 committed by GitHub
parent d8eb71e004
commit bdf81596e9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 28 additions and 32 deletions

View file

@ -67,7 +67,6 @@ fun Screen.BulkFavoriteDialogs(
AddDuplicateMangaDialog(
dialog = dialog,
navigator = navigator,
state = bulkFavoriteState,
onDismiss = bulkFavoriteScreenModel::dismissDialog,
stopRunning = bulkFavoriteScreenModel::stopRunning,
toggleSelectionMode = bulkFavoriteScreenModel::toggleSelectionMode,
@ -134,10 +133,9 @@ private fun Screen.ShowMigrateDialog(
private fun AddDuplicateMangaDialog(
dialog: Dialog.AddDuplicateManga,
navigator: Navigator?,
state: BulkFavoriteScreenModel.State,
onDismiss: () -> Unit,
stopRunning: () -> Unit,
toggleSelectionMode: () -> Unit,
toggleSelectionMode: (Boolean) -> Unit,
addFavorite: (Manga) -> Unit,
showMigrateDialog: (manga: Manga, duplicate: Manga) -> Unit,
) {
@ -147,9 +145,7 @@ private fun AddDuplicateMangaDialog(
duplicates = dialog.duplicates,
onDismissRequest = onDismiss,
onConfirm = {
if (state.selectionMode) {
toggleSelectionMode()
}
toggleSelectionMode(false)
addFavorite(dialog.manga)
},
onOpenManga = { navigator?.push(MangaScreen(it.id)) },

View file

@ -62,18 +62,17 @@ class BulkFavoriteScreenModel(
) : StateScreenModel<BulkFavoriteScreenModel.State>(initialState) {
fun backHandler() {
toggleSelectionMode()
toggleSelectionMode(false)
}
fun toggleSelectionMode(newMode: Boolean? = null) {
if (state.value.selectionMode) {
clearSelection()
mutableState.update { state ->
val mode = newMode ?: !state.selectionMode
state.copy(
selectionMode = mode,
selection = if (mode) state.selection else persistentListOf(),
)
}
mutableState.update { it.copy(selectionMode = newMode ?: !it.selectionMode) }
}
private fun clearSelection() {
mutableState.update { it.copy(selection = persistentListOf()) }
}
fun select(manga: Manga) {
@ -152,7 +151,7 @@ class BulkFavoriteScreenModel(
val mangaList = if (skipAllDuplicates) getNotDuplicateLibraryMangas() else state.value.selection
if (mangaList.isEmpty()) {
stopRunning()
toggleSelectionMode()
toggleSelectionMode(false)
return@launch
}
val categories = getCategories()
@ -241,7 +240,7 @@ class BulkFavoriteScreenModel(
}
stopRunning()
}
toggleSelectionMode(newMode = false)
toggleSelectionMode(false)
}
private fun moveMangaToCategoriesAndAddToLibrary(manga: Manga, categories: List<Long>) {

View file

@ -149,11 +149,10 @@ class MigrateMangaScreenModel(
selectedMangaIds.addOrRemove(it.manga.id, selected)
it.copy(selected = selected)
}
selectedPositions[0] = -1
selectedPositions[1] = -1
state.copy(titleList = newItems.toImmutableList())
}
selectedPositions[0] = -1
selectedPositions[1] = -1
}
fun invertSelection() {
@ -162,10 +161,10 @@ class MigrateMangaScreenModel(
selectedMangaIds.addOrRemove(it.manga.id, !it.selected)
it.copy(selected = !it.selected)
}
selectedPositions[0] = -1
selectedPositions[1] = -1
state.copy(titleList = newItems.toImmutableList())
}
selectedPositions[0] = -1
selectedPositions[1] = -1
}
// KMK <--

View file

@ -129,11 +129,10 @@ class LibraryUpdateErrorScreenModel(
selectedErrorIds.addOrRemove(it.error.errorId, selected)
it.copy(selected = selected)
}
selectedPositions[0] = -1
selectedPositions[1] = -1
state.copy(items = newItems)
}
selectedPositions[0] = -1
selectedPositions[1] = -1
}
fun invertSelection() {
@ -142,10 +141,10 @@ class LibraryUpdateErrorScreenModel(
selectedErrorIds.addOrRemove(it.error.errorId, !it.selected)
it.copy(selected = !it.selected)
}
selectedPositions[0] = -1
selectedPositions[1] = -1
state.copy(items = newItems)
}
selectedPositions[0] = -1
selectedPositions[1] = -1
}
@OptIn(DelicateCoroutinesApi::class)

View file

@ -461,11 +461,12 @@ class UpdatesScreenModel(
selectedChapterIds.addOrRemove(it.update.chapterId, selected)
it.copy(selected = selected)
}
// KMK -->
selectedPositions[0] = -1
selectedPositions[1] = -1
// KMK <--
state.copy(items = newItems.toPersistentList())
}
selectedPositions[0] = -1
selectedPositions[1] = -1
}
fun invertSelection() {
@ -474,10 +475,12 @@ class UpdatesScreenModel(
selectedChapterIds.addOrRemove(it.update.chapterId, !it.selected)
it.copy(selected = !it.selected)
}
// KMK -->
selectedPositions[0] = -1
selectedPositions[1] = -1
// KMK <--
state.copy(items = newItems.toPersistentList())
}
selectedPositions[0] = -1
selectedPositions[1] = -1
}
fun setDialog(dialog: Dialog?) {

View file

@ -124,7 +124,7 @@ class BrowseRecommendsScreen(
scrollBehavior = scrollBehavior,
// KMK -->
toggleSelectionMode = {
bulkFavoriteScreenModel.toggleSelectionMode()
bulkFavoriteScreenModel.toggleSelectionMode(true)
}.takeIf { !isExternalSource },
isRunning = bulkFavoriteState.isRunning,
// KMK <--