show loading indicator while bulk-selection is running
This commit is contained in:
parent
cb0993d8f7
commit
a40385554c
19 changed files with 242 additions and 114 deletions
|
|
@ -13,7 +13,7 @@ import eu.kanade.presentation.browse.components.GlobalSearchErrorResultItem
|
|||
import eu.kanade.presentation.browse.components.GlobalSearchLoadingResultItem
|
||||
import eu.kanade.presentation.browse.components.GlobalSearchResultItem
|
||||
import eu.kanade.presentation.browse.components.GlobalSearchToolbar
|
||||
import eu.kanade.presentation.components.SelectionToolbar
|
||||
import eu.kanade.presentation.components.BulkSelectionToolbar
|
||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
||||
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SearchItemResult
|
||||
|
|
@ -49,10 +49,11 @@ fun GlobalSearchScreen(
|
|||
topBar = { scrollBehavior ->
|
||||
// KMK -->
|
||||
if (bulkFavoriteState.selectionMode) {
|
||||
SelectionToolbar(
|
||||
BulkSelectionToolbar(
|
||||
selectedCount = bulkFavoriteState.selection.size,
|
||||
isRunning = bulkFavoriteState.isRunning,
|
||||
onClickClearSelection = bulkFavoriteScreenModel::toggleSelectionMode,
|
||||
onChangeCategoryClicked = bulkFavoriteScreenModel::addFavorite,
|
||||
onChangeCategoryClick = bulkFavoriteScreenModel::addFavorite,
|
||||
onSelectAll = {
|
||||
state.filteredItems.forEach { (_, result) ->
|
||||
when (result) {
|
||||
|
|
@ -84,6 +85,7 @@ fun GlobalSearchScreen(
|
|||
scrollBehavior = scrollBehavior,
|
||||
// KMK -->
|
||||
toggleSelectionMode = bulkFavoriteScreenModel::toggleSelectionMode,
|
||||
isRunning = bulkFavoriteState.isRunning,
|
||||
// KMK <--
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import androidx.compose.runtime.State
|
|||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import eu.kanade.presentation.browse.components.GlobalSearchToolbar
|
||||
import eu.kanade.presentation.components.SelectionToolbar
|
||||
import eu.kanade.presentation.components.BulkSelectionToolbar
|
||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
||||
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SearchItemResult
|
||||
|
|
@ -39,10 +39,11 @@ fun MigrateSearchScreen(
|
|||
topBar = { scrollBehavior ->
|
||||
// KMK -->
|
||||
if (bulkFavoriteState.selectionMode) {
|
||||
SelectionToolbar(
|
||||
BulkSelectionToolbar(
|
||||
selectedCount = bulkFavoriteState.selection.size,
|
||||
isRunning = bulkFavoriteState.isRunning,
|
||||
onClickClearSelection = bulkFavoriteScreenModel::toggleSelectionMode,
|
||||
onChangeCategoryClicked = bulkFavoriteScreenModel::addFavorite,
|
||||
onChangeCategoryClick = bulkFavoriteScreenModel::addFavorite,
|
||||
onSelectAll = {
|
||||
state.filteredItems.forEach { (_, result) ->
|
||||
when (result) {
|
||||
|
|
@ -74,6 +75,7 @@ fun MigrateSearchScreen(
|
|||
scrollBehavior = scrollBehavior,
|
||||
// KMK -->
|
||||
toggleSelectionMode = bulkFavoriteScreenModel::toggleSelectionMode,
|
||||
isRunning = bulkFavoriteState.isRunning,
|
||||
// KMK <--
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ import eu.kanade.presentation.browse.components.GlobalSearchResultItem
|
|||
import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.components.AppBarActions
|
||||
import eu.kanade.presentation.components.AppBarTitle
|
||||
import eu.kanade.presentation.components.BulkSelectionToolbar
|
||||
import eu.kanade.presentation.components.SearchToolbar
|
||||
import eu.kanade.presentation.components.SelectionToolbar
|
||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
||||
import eu.kanade.tachiyomi.ui.browse.bulkSelectionButton
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
|
@ -118,10 +118,11 @@ fun SourceFeedScreen(
|
|||
topBar = { scrollBehavior ->
|
||||
// KMK -->
|
||||
if (bulkFavoriteState.selectionMode) {
|
||||
SelectionToolbar(
|
||||
BulkSelectionToolbar(
|
||||
selectedCount = bulkFavoriteState.selection.size,
|
||||
isRunning = bulkFavoriteState.isRunning,
|
||||
onClickClearSelection = bulkFavoriteScreenModel::toggleSelectionMode,
|
||||
onChangeCategoryClicked = bulkFavoriteScreenModel::addFavorite,
|
||||
onChangeCategoryClick = bulkFavoriteScreenModel::addFavorite,
|
||||
onSelectAll = {
|
||||
items.forEach {
|
||||
it.results?.forEach { manga ->
|
||||
|
|
@ -146,6 +147,7 @@ fun SourceFeedScreen(
|
|||
onSourceSettingClick = onSourceSettingClick,
|
||||
onSortFeedClick = onSortFeedClick,
|
||||
toggleSelectionMode = bulkFavoriteScreenModel::toggleSelectionMode,
|
||||
isRunning = bulkFavoriteState.isRunning,
|
||||
// KMK <--
|
||||
)
|
||||
}
|
||||
|
|
@ -302,6 +304,7 @@ fun SourceFeedToolbar(
|
|||
onSourceSettingClick: (() -> Unit?)?,
|
||||
onSortFeedClick: (() -> Unit)?,
|
||||
toggleSelectionMode: () -> Unit,
|
||||
isRunning: Boolean,
|
||||
// KMK <--
|
||||
) {
|
||||
SearchToolbar(
|
||||
|
|
@ -320,7 +323,7 @@ fun SourceFeedToolbar(
|
|||
AppBarActions(
|
||||
actions = persistentListOf<AppBar.AppBarAction>().builder()
|
||||
.apply {
|
||||
add(bulkSelectionButton(toggleSelectionMode))
|
||||
add(bulkSelectionButton(isRunning, toggleSelectionMode))
|
||||
|
||||
onWebViewClick?.let {
|
||||
add(
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ fun BrowseSourceSimpleToolbar(
|
|||
scrollBehavior: TopAppBarScrollBehavior,
|
||||
// KMK -->
|
||||
toggleSelectionMode: () -> Unit,
|
||||
isRunning: Boolean,
|
||||
// KMK <--
|
||||
) {
|
||||
AppBar(
|
||||
|
|
@ -56,7 +57,7 @@ fun BrowseSourceSimpleToolbar(
|
|||
onClick = { selectingDisplayMode = true },
|
||||
),
|
||||
// KMK -->
|
||||
bulkSelectionButton(toggleSelectionMode),
|
||||
bulkSelectionButton(isRunning, toggleSelectionMode),
|
||||
// KMK <--
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ fun BrowseSourceToolbar(
|
|||
scrollBehavior: TopAppBarScrollBehavior? = null,
|
||||
// KMK -->
|
||||
toggleSelectionMode: () -> Unit,
|
||||
isRunning: Boolean,
|
||||
// KMK <--
|
||||
) {
|
||||
// Avoid capturing unstable source in actions lambda
|
||||
|
|
@ -82,7 +83,7 @@ fun BrowseSourceToolbar(
|
|||
)
|
||||
}
|
||||
// KMK -->
|
||||
add(bulkSelectionButton(toggleSelectionMode))
|
||||
add(bulkSelectionButton(isRunning, toggleSelectionMode))
|
||||
// KMK <--
|
||||
if (isLocalSource) {
|
||||
if (isConfigurableSource && displayMode != null) {
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ fun GlobalSearchToolbar(
|
|||
scrollBehavior: TopAppBarScrollBehavior,
|
||||
// KMK -->
|
||||
toggleSelectionMode: () -> Unit,
|
||||
isRunning: Boolean,
|
||||
// KMK <--
|
||||
) {
|
||||
Column(modifier = Modifier.background(MaterialTheme.colorScheme.surface)) {
|
||||
|
|
@ -65,7 +66,7 @@ fun GlobalSearchToolbar(
|
|||
actions = {
|
||||
AppBarActions(
|
||||
actions = persistentListOf(
|
||||
bulkSelectionButton(toggleSelectionMode),
|
||||
bulkSelectionButton(isRunning, toggleSelectionMode),
|
||||
),
|
||||
)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -2,9 +2,11 @@ package eu.kanade.presentation.components
|
|||
|
||||
import androidx.compose.foundation.basicMarquee
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.text.BasicTextField
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
|
|
@ -26,6 +28,7 @@ import androidx.compose.material3.TooltipDefaults
|
|||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||
import androidx.compose.material3.minimumInteractiveComponentSize
|
||||
import androidx.compose.material3.rememberTooltipState
|
||||
import androidx.compose.material3.surfaceColorAtElevation
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -35,6 +38,7 @@ import androidx.compose.runtime.key
|
|||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
|
|
@ -215,6 +219,29 @@ fun AppBarActions(
|
|||
}
|
||||
}
|
||||
|
||||
// KMK -->
|
||||
actions.filterIsInstance<AppBar.ActionCompose>().map {
|
||||
TooltipBox(
|
||||
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
|
||||
tooltip = {
|
||||
PlainTooltip {
|
||||
Text(it.title)
|
||||
}
|
||||
},
|
||||
state = rememberTooltipState(),
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.minimumInteractiveComponentSize()
|
||||
.size(40.dp),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
it.content()
|
||||
}
|
||||
}
|
||||
}
|
||||
// KMK <--
|
||||
|
||||
val overflowActions = actions.filterIsInstance<AppBar.OverflowAction>()
|
||||
if (overflowActions.isNotEmpty()) {
|
||||
TooltipBox(
|
||||
|
|
@ -419,6 +446,13 @@ sealed interface AppBar {
|
|||
val enabled: Boolean = true,
|
||||
) : AppBarAction
|
||||
|
||||
// KMK -->
|
||||
data class ActionCompose(
|
||||
val title: String,
|
||||
val content: @Composable () -> Unit,
|
||||
) : AppBarAction
|
||||
// KMK <--
|
||||
|
||||
data class OverflowAction(
|
||||
val title: String,
|
||||
val onClick: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,95 @@
|
|||
package eu.kanade.presentation.components
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.BookmarkAdd
|
||||
import androidx.compose.material.icons.filled.SelectAll
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.i18n.kmk.KMR
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
|
||||
@Composable
|
||||
fun BulkSelectionToolbar(
|
||||
selectedCount: Int,
|
||||
isRunning: Boolean,
|
||||
onClickClearSelection: () -> Unit,
|
||||
onChangeCategoryClick: () -> Unit,
|
||||
onSelectAll: (() -> Unit)? = null,
|
||||
) {
|
||||
AppBar(
|
||||
titleContent = { Text(text = "$selectedCount") },
|
||||
actions = {
|
||||
AppBarActions(
|
||||
actions = persistentListOf<AppBar.AppBarAction>()
|
||||
.builder()
|
||||
.apply {
|
||||
if (onSelectAll != null) {
|
||||
add(
|
||||
AppBar.Action(
|
||||
title = stringResource(MR.strings.action_select_all),
|
||||
icon = Icons.Filled.SelectAll,
|
||||
onClick = {
|
||||
onSelectAll()
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
if (isRunning) {
|
||||
add(
|
||||
AppBar.ActionCompose(
|
||||
title = stringResource(KMR.strings.action_bulk_select),
|
||||
) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier
|
||||
.size(24.dp),
|
||||
strokeWidth = 2.dp,
|
||||
)
|
||||
},
|
||||
)
|
||||
} else {
|
||||
add(
|
||||
AppBar.Action(
|
||||
title = stringResource(MR.strings.action_bookmark),
|
||||
icon = Icons.Filled.BookmarkAdd,
|
||||
onClick = {
|
||||
if (selectedCount > 0) {
|
||||
onChangeCategoryClick()
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}.build(),
|
||||
)
|
||||
},
|
||||
isActionMode = true,
|
||||
onCancelActionMode = onClickClearSelection,
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun SelectionToolbarPreview() {
|
||||
Column {
|
||||
BulkSelectionToolbar(
|
||||
selectedCount = 9,
|
||||
isRunning = false,
|
||||
onClickClearSelection = {},
|
||||
onChangeCategoryClick = {},
|
||||
)
|
||||
BulkSelectionToolbar(
|
||||
selectedCount = 9,
|
||||
isRunning = true,
|
||||
onClickClearSelection = {},
|
||||
onChangeCategoryClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
package eu.kanade.presentation.components
|
||||
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.BookmarkAdd
|
||||
import androidx.compose.material.icons.filled.SelectAll
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
|
||||
@Composable
|
||||
fun SelectionToolbar(
|
||||
selectedCount: Int,
|
||||
onClickClearSelection: () -> Unit,
|
||||
onChangeCategoryClicked: () -> Unit,
|
||||
onSelectAll: (() -> Unit)? = null,
|
||||
) {
|
||||
AppBar(
|
||||
titleContent = { Text(text = "$selectedCount") },
|
||||
actions = {
|
||||
AppBarActions(
|
||||
actions = persistentListOf<AppBar.AppBarAction>().builder()
|
||||
.apply {
|
||||
if (onSelectAll != null) {
|
||||
add(
|
||||
AppBar.Action(
|
||||
title = stringResource(MR.strings.action_select_all),
|
||||
icon = Icons.Filled.SelectAll,
|
||||
onClick = {
|
||||
onSelectAll()
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
add(
|
||||
AppBar.Action(
|
||||
title = stringResource(MR.strings.action_bookmark),
|
||||
icon = Icons.Filled.BookmarkAdd,
|
||||
onClick = {
|
||||
if (selectedCount > 0) {
|
||||
onChangeCategoryClicked()
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
.build(),
|
||||
)
|
||||
},
|
||||
isActionMode = true,
|
||||
onCancelActionMode = onClickClearSelection,
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun SelectionToolbarPreview() {
|
||||
SelectionToolbar(
|
||||
selectedCount = 9,
|
||||
{},
|
||||
{},
|
||||
)
|
||||
}
|
||||
|
|
@ -66,10 +66,11 @@ fun TabbedScreen(
|
|||
val searchEnabled = tab.searchEnabled
|
||||
// KMK -->
|
||||
if (bulkFavoriteState.selectionMode) {
|
||||
SelectionToolbar(
|
||||
BulkSelectionToolbar(
|
||||
selectedCount = bulkFavoriteState.selection.size,
|
||||
isRunning = bulkFavoriteState.isRunning,
|
||||
onClickClearSelection = bulkFavoriteScreenModel::toggleSelectionMode,
|
||||
onChangeCategoryClicked = bulkFavoriteScreenModel::addFavorite,
|
||||
onChangeCategoryClick = bulkFavoriteScreenModel::addFavorite,
|
||||
onSelectAll = {
|
||||
feedState.items?.forEach {
|
||||
it.results?.forEach { manga ->
|
||||
|
|
|
|||
|
|
@ -140,10 +140,14 @@ fun DuplicateMangasDialog(
|
|||
onOpenManga: () -> Unit,
|
||||
onAllowDuplicate: () -> Unit,
|
||||
onSkipDuplicate: () -> Unit,
|
||||
stopRunning: () -> Unit,
|
||||
duplicatedName: String,
|
||||
) {
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismissRequest,
|
||||
onDismissRequest = {
|
||||
stopRunning()
|
||||
onDismissRequest()
|
||||
},
|
||||
title = {
|
||||
Text(text = duplicatedName)
|
||||
},
|
||||
|
|
@ -202,6 +206,7 @@ fun DuplicateMangasDialog(
|
|||
FlowColumn {
|
||||
TextButton(
|
||||
onClick = {
|
||||
stopRunning()
|
||||
onDismissRequest()
|
||||
onOpenManga()
|
||||
},
|
||||
|
|
@ -212,6 +217,7 @@ fun DuplicateMangasDialog(
|
|||
|
||||
TextButton(
|
||||
onClick = {
|
||||
stopRunning()
|
||||
onDismissRequest()
|
||||
},
|
||||
Modifier.align(Alignment.CenterHorizontally),
|
||||
|
|
@ -235,6 +241,7 @@ fun DuplicateMangasDialogPreview() {
|
|||
onAllowDuplicate = { },
|
||||
onSkipDuplicate = { },
|
||||
duplicatedName = "Berserk",
|
||||
stopRunning = { },
|
||||
)
|
||||
}
|
||||
// KMK <--
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@ package eu.kanade.tachiyomi.ui.browse
|
|||
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Checklist
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedback
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.util.fastAny
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
import androidx.compose.ui.util.fastForEachIndexed
|
||||
|
|
@ -21,6 +21,7 @@ import eu.kanade.domain.track.interactor.AddTracks
|
|||
import eu.kanade.presentation.browse.components.RemoveMangaDialog
|
||||
import eu.kanade.presentation.category.components.ChangeCategoryDialog
|
||||
import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.components.BulkSelectionToolbar
|
||||
import eu.kanade.presentation.manga.DuplicateMangaDialog
|
||||
import eu.kanade.presentation.manga.DuplicateMangasDialog
|
||||
import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||
|
|
@ -112,8 +113,15 @@ class BulkFavoriteScreenModel(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when user click on [BulkSelectionToolbar]'s `Favorite` button.
|
||||
* It will then look for any duplicated mangas.
|
||||
* - If there is any, it will show the [DuplicateMangasDialog].
|
||||
* - If not then it will call the [addFavoriteDuplicate].
|
||||
*/
|
||||
fun addFavorite(startIdx: Int = 0) {
|
||||
screenModelScope.launch {
|
||||
startRunning()
|
||||
val mangaWithDup = getDuplicateLibraryManga(startIdx)
|
||||
if (mangaWithDup != null) {
|
||||
setDialog(Dialog.AllowDuplicate(mangaWithDup))
|
||||
|
|
@ -123,10 +131,15 @@ class BulkFavoriteScreenModel(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add mangas to library if there is default category or no category exists.
|
||||
* If not, it shows the categories list.
|
||||
*/
|
||||
fun addFavoriteDuplicate(skipAllDuplicates: Boolean = false) {
|
||||
screenModelScope.launch {
|
||||
val mangaList = if (skipAllDuplicates) getNotDuplicateLibraryMangas() else state.value.selection
|
||||
if (mangaList.isEmpty()) {
|
||||
stopRunning()
|
||||
toggleSelectionMode()
|
||||
return@launch
|
||||
}
|
||||
|
|
@ -137,11 +150,13 @@ class BulkFavoriteScreenModel(
|
|||
when {
|
||||
// Default category set
|
||||
defaultCategory != null -> {
|
||||
stopRunning()
|
||||
setMangasCategories(mangaList, listOf(defaultCategory.id), emptyList())
|
||||
}
|
||||
|
||||
// Automatic 'Default' or no categories
|
||||
defaultCategoryId == 0 || categories.isEmpty() -> {
|
||||
stopRunning()
|
||||
// Automatic 'Default' or no categories
|
||||
setMangasCategories(mangaList, emptyList(), emptyList())
|
||||
}
|
||||
|
|
@ -160,6 +175,7 @@ class BulkFavoriteScreenModel(
|
|||
}
|
||||
}
|
||||
.toImmutableList()
|
||||
stopRunning()
|
||||
setDialog(Dialog.ChangeMangasCategory(mangaList, preselected))
|
||||
}
|
||||
}
|
||||
|
|
@ -201,6 +217,7 @@ class BulkFavoriteScreenModel(
|
|||
*/
|
||||
fun setMangasCategories(mangaList: List<Manga>, addCategories: List<Long>, removeCategories: List<Long>) {
|
||||
screenModelScope.launchNonCancellable {
|
||||
startRunning()
|
||||
mangaList.fastForEach { manga ->
|
||||
val categoryIds = getCategories.await(manga.id)
|
||||
.map { it.id }
|
||||
|
|
@ -210,6 +227,7 @@ class BulkFavoriteScreenModel(
|
|||
|
||||
moveMangaToCategoriesAndAddToLibrary(manga, categoryIds)
|
||||
}
|
||||
stopRunning()
|
||||
}
|
||||
toggleSelectionMode()
|
||||
}
|
||||
|
|
@ -374,6 +392,18 @@ class BulkFavoriteScreenModel(
|
|||
}
|
||||
}
|
||||
|
||||
private fun startRunning() {
|
||||
mutableState.update {
|
||||
it.copy(isRunning = true)
|
||||
}
|
||||
}
|
||||
|
||||
fun stopRunning() {
|
||||
mutableState.update {
|
||||
it.copy(isRunning = false)
|
||||
}
|
||||
}
|
||||
|
||||
interface Dialog {
|
||||
data class RemoveManga(val manga: Manga) : Dialog
|
||||
data class AddDuplicateManga(val manga: Manga, val duplicate: Manga) : Dialog
|
||||
|
|
@ -393,6 +423,7 @@ class BulkFavoriteScreenModel(
|
|||
val dialog: Dialog? = null,
|
||||
val selection: PersistentList<Manga> = persistentListOf(),
|
||||
val selectionMode: Boolean = false,
|
||||
val isRunning: Boolean = false,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -487,19 +518,17 @@ fun AllowDuplicateDialog(bulkFavoriteScreenModel: BulkFavoriteScreenModel) {
|
|||
bulkFavoriteScreenModel.addFavorite(startIdx = dialog.duplicatedManga.first)
|
||||
},
|
||||
duplicatedName = dialog.duplicatedManga.second.title,
|
||||
stopRunning = bulkFavoriteScreenModel::stopRunning,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun bulkSelectionButton(toggleSelectionMode: () -> Unit) =
|
||||
AppBar.Action(
|
||||
fun bulkSelectionButton(
|
||||
isRunning: Boolean,
|
||||
toggleSelectionMode: () -> Unit,
|
||||
) = AppBar.Action(
|
||||
title = stringResource(KMR.strings.action_bulk_select),
|
||||
icon = Icons.Outlined.Checklist,
|
||||
iconTint = MaterialTheme.colorScheme.primary.takeIf { isRunning },
|
||||
onClick = toggleSelectionMode,
|
||||
)
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun BulkSelectionButtonPreview() {
|
||||
bulkSelectionButton { }
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -122,7 +122,10 @@ fun feedTab(
|
|||
icon = Icons.Outlined.SwapVert,
|
||||
onClick = { showingFeedOrderScreen.value = true },
|
||||
),
|
||||
bulkSelectionButton(bulkFavoriteScreenModel::toggleSelectionMode),
|
||||
bulkSelectionButton(
|
||||
isRunning = bulkFavoriteState.isRunning,
|
||||
toggleSelectionMode = bulkFavoriteScreenModel::toggleSelectionMode,
|
||||
),
|
||||
// KMK <--
|
||||
)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ import cafe.adriel.voyager.navigator.currentOrThrow
|
|||
import eu.kanade.presentation.browse.BrowseSourceContent
|
||||
import eu.kanade.presentation.browse.components.BrowseSourceFloatingActionButton
|
||||
import eu.kanade.presentation.components.AppBarActions
|
||||
import eu.kanade.presentation.components.BulkSelectionToolbar
|
||||
import eu.kanade.presentation.components.SearchToolbar
|
||||
import eu.kanade.presentation.components.SelectionToolbar
|
||||
import eu.kanade.presentation.util.Screen
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import eu.kanade.tachiyomi.ui.browse.AllowDuplicateDialog
|
||||
|
|
@ -76,10 +76,11 @@ data class SourceSearchScreen(
|
|||
topBar = { scrollBehavior ->
|
||||
// KMK -->
|
||||
if (bulkFavoriteState.selectionMode) {
|
||||
SelectionToolbar(
|
||||
BulkSelectionToolbar(
|
||||
selectedCount = bulkFavoriteState.selection.size,
|
||||
isRunning = bulkFavoriteState.isRunning,
|
||||
onClickClearSelection = bulkFavoriteScreenModel::toggleSelectionMode,
|
||||
onChangeCategoryClicked = bulkFavoriteScreenModel::addFavorite,
|
||||
onChangeCategoryClick = bulkFavoriteScreenModel::addFavorite,
|
||||
onSelectAll = {
|
||||
state.mangaDisplayingList.forEach { manga ->
|
||||
if (!bulkFavoriteState.selection.contains(manga)) {
|
||||
|
|
@ -100,7 +101,10 @@ data class SourceSearchScreen(
|
|||
actions = {
|
||||
AppBarActions(
|
||||
actions = persistentListOf(
|
||||
bulkSelectionButton(bulkFavoriteScreenModel::toggleSelectionMode),
|
||||
bulkSelectionButton(
|
||||
isRunning = bulkFavoriteState.isRunning,
|
||||
toggleSelectionMode = bulkFavoriteScreenModel::toggleSelectionMode,
|
||||
),
|
||||
),
|
||||
)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ import eu.kanade.presentation.browse.components.RemoveMangaDialog
|
|||
import eu.kanade.presentation.browse.components.SavedSearchCreateDialog
|
||||
import eu.kanade.presentation.browse.components.SavedSearchDeleteDialog
|
||||
import eu.kanade.presentation.category.components.ChangeCategoryDialog
|
||||
import eu.kanade.presentation.components.SelectionToolbar
|
||||
import eu.kanade.presentation.components.BulkSelectionToolbar
|
||||
import eu.kanade.presentation.manga.DuplicateMangaDialog
|
||||
import eu.kanade.presentation.util.AssistContentScreen
|
||||
import eu.kanade.presentation.util.Screen
|
||||
|
|
@ -176,10 +176,11 @@ data class BrowseSourceScreen(
|
|||
Column(modifier = Modifier.background(MaterialTheme.colorScheme.surface)) {
|
||||
// KMK -->
|
||||
if (bulkFavoriteState.selectionMode) {
|
||||
SelectionToolbar(
|
||||
BulkSelectionToolbar(
|
||||
selectedCount = bulkFavoriteState.selection.size,
|
||||
isRunning = bulkFavoriteState.isRunning,
|
||||
onClickClearSelection = bulkFavoriteScreenModel::toggleSelectionMode,
|
||||
onChangeCategoryClicked = bulkFavoriteScreenModel::addFavorite,
|
||||
onChangeCategoryClick = bulkFavoriteScreenModel::addFavorite,
|
||||
onSelectAll = {
|
||||
state.mangaDisplayingList.forEach { manga ->
|
||||
if (!bulkFavoriteState.selection.contains(manga)) {
|
||||
|
|
@ -208,6 +209,7 @@ data class BrowseSourceScreen(
|
|||
onSearch = screenModel::search,
|
||||
// KMK -->
|
||||
toggleSelectionMode = bulkFavoriteScreenModel::toggleSelectionMode,
|
||||
isRunning = bulkFavoriteState.isRunning,
|
||||
// KMK <--
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import eu.kanade.core.preference.asState
|
|||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import eu.kanade.presentation.browse.RelatedMangasContent
|
||||
import eu.kanade.presentation.browse.components.BrowseSourceSimpleToolbar
|
||||
import eu.kanade.presentation.components.SelectionToolbar
|
||||
import eu.kanade.presentation.components.BulkSelectionToolbar
|
||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
||||
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreen
|
||||
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchScreen
|
||||
|
|
@ -48,10 +48,11 @@ fun RelatedMangasScreen(
|
|||
Scaffold(
|
||||
topBar = { scrollBehavior ->
|
||||
if (bulkFavoriteState.selectionMode) {
|
||||
SelectionToolbar(
|
||||
BulkSelectionToolbar(
|
||||
selectedCount = bulkFavoriteState.selection.size,
|
||||
isRunning = bulkFavoriteState.isRunning,
|
||||
onClickClearSelection = bulkFavoriteScreenModel::toggleSelectionMode,
|
||||
onChangeCategoryClicked = bulkFavoriteScreenModel::addFavorite,
|
||||
onChangeCategoryClick = bulkFavoriteScreenModel::addFavorite,
|
||||
onSelectAll = {
|
||||
successState.relatedMangasSorted?.forEach {
|
||||
val relatedManga = it as RelatedManga.Success
|
||||
|
|
@ -71,6 +72,7 @@ fun RelatedMangasScreen(
|
|||
onDisplayModeChange = { displayMode = it },
|
||||
scrollBehavior = scrollBehavior,
|
||||
toggleSelectionMode = bulkFavoriteScreenModel::toggleSelectionMode,
|
||||
isRunning = bulkFavoriteState.isRunning,
|
||||
)
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import eu.kanade.presentation.browse.BrowseSourceContent
|
|||
import eu.kanade.presentation.browse.components.BrowseSourceSimpleToolbar
|
||||
import eu.kanade.presentation.browse.components.RemoveMangaDialog
|
||||
import eu.kanade.presentation.category.components.ChangeCategoryDialog
|
||||
import eu.kanade.presentation.components.SelectionToolbar
|
||||
import eu.kanade.presentation.components.BulkSelectionToolbar
|
||||
import eu.kanade.presentation.manga.DuplicateMangaDialog
|
||||
import eu.kanade.presentation.util.Screen
|
||||
import eu.kanade.tachiyomi.ui.browse.AllowDuplicateDialog
|
||||
|
|
@ -69,10 +69,11 @@ class MangaDexFollowsScreen(private val sourceId: Long) : Screen() {
|
|||
topBar = { scrollBehavior ->
|
||||
// KMK -->
|
||||
if (bulkFavoriteState.selectionMode) {
|
||||
SelectionToolbar(
|
||||
BulkSelectionToolbar(
|
||||
selectedCount = bulkFavoriteState.selection.size,
|
||||
isRunning = bulkFavoriteState.isRunning,
|
||||
onClickClearSelection = bulkFavoriteScreenModel::toggleSelectionMode,
|
||||
onChangeCategoryClicked = bulkFavoriteScreenModel::addFavorite,
|
||||
onChangeCategoryClick = bulkFavoriteScreenModel::addFavorite,
|
||||
onSelectAll = {
|
||||
state.mangaDisplayingList.forEach { manga ->
|
||||
if (!bulkFavoriteState.selection.contains(manga)) {
|
||||
|
|
@ -91,6 +92,7 @@ class MangaDexFollowsScreen(private val sourceId: Long) : Screen() {
|
|||
scrollBehavior = scrollBehavior,
|
||||
// KMK -->
|
||||
toggleSelectionMode = bulkFavoriteScreenModel::toggleSelectionMode,
|
||||
isRunning = bulkFavoriteState.isRunning,
|
||||
// KMK <--
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import cafe.adriel.voyager.navigator.LocalNavigator
|
|||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import eu.kanade.presentation.browse.BrowseSourceContent
|
||||
import eu.kanade.presentation.browse.components.BrowseSourceSimpleToolbar
|
||||
import eu.kanade.presentation.components.SelectionToolbar
|
||||
import eu.kanade.presentation.components.BulkSelectionToolbar
|
||||
import eu.kanade.presentation.util.Screen
|
||||
import eu.kanade.tachiyomi.ui.browse.AddDuplicateMangaDialog
|
||||
import eu.kanade.tachiyomi.ui.browse.AllowDuplicateDialog
|
||||
|
|
@ -65,10 +65,11 @@ class MangaDexSimilarScreen(val mangaId: Long, val sourceId: Long) : Screen() {
|
|||
topBar = { scrollBehavior ->
|
||||
// KMK -->
|
||||
if (bulkFavoriteState.selectionMode) {
|
||||
SelectionToolbar(
|
||||
BulkSelectionToolbar(
|
||||
selectedCount = bulkFavoriteState.selection.size,
|
||||
isRunning = bulkFavoriteState.isRunning,
|
||||
onClickClearSelection = bulkFavoriteScreenModel::toggleSelectionMode,
|
||||
onChangeCategoryClicked = bulkFavoriteScreenModel::addFavorite,
|
||||
onChangeCategoryClick = bulkFavoriteScreenModel::addFavorite,
|
||||
onSelectAll = {
|
||||
state.mangaDisplayingList.forEach { manga ->
|
||||
if (!bulkFavoriteState.selection.contains(manga)) {
|
||||
|
|
@ -87,6 +88,7 @@ class MangaDexSimilarScreen(val mangaId: Long, val sourceId: Long) : Screen() {
|
|||
scrollBehavior = scrollBehavior,
|
||||
// KMK -->
|
||||
toggleSelectionMode = bulkFavoriteScreenModel::toggleSelectionMode,
|
||||
isRunning = bulkFavoriteState.isRunning,
|
||||
// KMK <--
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import cafe.adriel.voyager.navigator.Navigator
|
|||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import eu.kanade.presentation.browse.BrowseSourceContent
|
||||
import eu.kanade.presentation.browse.components.BrowseSourceSimpleToolbar
|
||||
import eu.kanade.presentation.components.SelectionToolbar
|
||||
import eu.kanade.presentation.components.BulkSelectionToolbar
|
||||
import eu.kanade.presentation.util.Screen
|
||||
import eu.kanade.tachiyomi.ui.browse.AddDuplicateMangaDialog
|
||||
import eu.kanade.tachiyomi.ui.browse.AllowDuplicateDialog
|
||||
|
|
@ -64,10 +64,11 @@ class RecommendsScreen(val mangaId: Long, val sourceId: Long) : Screen() {
|
|||
topBar = { scrollBehavior ->
|
||||
// KMK -->
|
||||
if (bulkFavoriteState.selectionMode) {
|
||||
SelectionToolbar(
|
||||
BulkSelectionToolbar(
|
||||
selectedCount = bulkFavoriteState.selection.size,
|
||||
isRunning = bulkFavoriteState.isRunning,
|
||||
onClickClearSelection = bulkFavoriteScreenModel::toggleSelectionMode,
|
||||
onChangeCategoryClicked = bulkFavoriteScreenModel::addFavorite,
|
||||
onChangeCategoryClick = bulkFavoriteScreenModel::addFavorite,
|
||||
onSelectAll = {
|
||||
state.mangaDisplayingList.forEach { manga ->
|
||||
if (!bulkFavoriteState.selection.contains(manga)) {
|
||||
|
|
@ -86,6 +87,7 @@ class RecommendsScreen(val mangaId: Long, val sourceId: Long) : Screen() {
|
|||
scrollBehavior = scrollBehavior,
|
||||
// KMK -->
|
||||
toggleSelectionMode = bulkFavoriteScreenModel::toggleSelectionMode,
|
||||
isRunning = bulkFavoriteState.isRunning,
|
||||
// KMK <--
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue