Add bulk-selection & improve display mode in RecommendsScreen
This commit is contained in:
parent
7b30a2a10f
commit
c643d8a55b
10 changed files with 92 additions and 56 deletions
|
|
@ -57,13 +57,10 @@ fun GlobalSearchScreen(
|
||||||
onChangeCategoryClick = bulkFavoriteScreenModel::addFavorite,
|
onChangeCategoryClick = bulkFavoriteScreenModel::addFavorite,
|
||||||
onSelectAll = {
|
onSelectAll = {
|
||||||
state.filteredItems.forEach { (_, result) ->
|
state.filteredItems.forEach { (_, result) ->
|
||||||
when (result) {
|
if (result is SearchItemResult.Success) {
|
||||||
is SearchItemResult.Success -> {
|
result.result.forEach { manga ->
|
||||||
result.result.forEach { manga ->
|
bulkFavoriteScreenModel.select(manga)
|
||||||
bulkFavoriteScreenModel.select(manga)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else -> {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ import tachiyomi.presentation.core.i18n.stringResource
|
||||||
fun BrowseSourceSimpleToolbar(
|
fun BrowseSourceSimpleToolbar(
|
||||||
navigateUp: () -> Unit,
|
navigateUp: () -> Unit,
|
||||||
title: String,
|
title: String,
|
||||||
displayMode: LibraryDisplayMode,
|
displayMode: LibraryDisplayMode?,
|
||||||
onDisplayModeChange: (LibraryDisplayMode) -> Unit,
|
onDisplayModeChange: (LibraryDisplayMode) -> Unit,
|
||||||
scrollBehavior: TopAppBarScrollBehavior,
|
scrollBehavior: TopAppBarScrollBehavior,
|
||||||
// KMK -->
|
// KMK -->
|
||||||
|
|
@ -38,25 +38,30 @@ fun BrowseSourceSimpleToolbar(
|
||||||
title = title,
|
title = title,
|
||||||
actions = {
|
actions = {
|
||||||
var selectingDisplayMode by remember { mutableStateOf(false) }
|
var selectingDisplayMode by remember { mutableStateOf(false) }
|
||||||
|
// KMK -->
|
||||||
AppBarActions(
|
AppBarActions(
|
||||||
// SY -->
|
actions = persistentListOf<AppBar.AppBarAction>().builder()
|
||||||
actions = persistentListOf(
|
.apply {
|
||||||
AppBar.Action(
|
displayMode?.let {
|
||||||
title = stringResource(MR.strings.action_display_mode),
|
add(
|
||||||
// KMK -->
|
AppBar.Action(
|
||||||
icon = if (displayMode == LibraryDisplayMode.List) {
|
title = stringResource(MR.strings.action_display_mode),
|
||||||
Icons.AutoMirrored.Filled.ViewList
|
icon = if (displayMode == LibraryDisplayMode.List) {
|
||||||
} else {
|
Icons.AutoMirrored.Filled.ViewList
|
||||||
Icons.Filled.ViewModule
|
} else {
|
||||||
},
|
Icons.Filled.ViewModule
|
||||||
// KMK <--
|
},
|
||||||
onClick = { selectingDisplayMode = true },
|
onClick = { selectingDisplayMode = true },
|
||||||
),
|
),
|
||||||
// KMK -->
|
)
|
||||||
bulkSelectionButton(isRunning, toggleSelectionMode),
|
add(
|
||||||
// KMK <--
|
bulkSelectionButton(isRunning, toggleSelectionMode),
|
||||||
),
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.build(),
|
||||||
)
|
)
|
||||||
|
// KMK <--
|
||||||
DropdownMenu(
|
DropdownMenu(
|
||||||
expanded = selectingDisplayMode,
|
expanded = selectingDisplayMode,
|
||||||
onDismissRequest = { selectingDisplayMode = false },
|
onDismissRequest = { selectingDisplayMode = false },
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ class MigrateSearchScreen(private val mangaId: Long, private val validSources: L
|
||||||
val bulkFavoriteState by bulkFavoriteScreenModel.state.collectAsState()
|
val bulkFavoriteState by bulkFavoriteScreenModel.state.collectAsState()
|
||||||
|
|
||||||
BackHandler(enabled = bulkFavoriteState.selectionMode) {
|
BackHandler(enabled = bulkFavoriteState.selectionMode) {
|
||||||
bulkFavoriteScreenModel.toggleSelectionMode()
|
bulkFavoriteScreenModel.backHandler()
|
||||||
}
|
}
|
||||||
// KMK <--
|
// KMK <--
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ data class SourceSearchScreen(
|
||||||
val bulkFavoriteState by bulkFavoriteScreenModel.state.collectAsState()
|
val bulkFavoriteState by bulkFavoriteScreenModel.state.collectAsState()
|
||||||
|
|
||||||
BackHandler(enabled = bulkFavoriteState.selectionMode) {
|
BackHandler(enabled = bulkFavoriteState.selectionMode) {
|
||||||
bulkFavoriteScreenModel.toggleSelectionMode()
|
bulkFavoriteScreenModel.backHandler()
|
||||||
}
|
}
|
||||||
|
|
||||||
val mangaList = screenModel.mangaPagerFlowFlow.collectAsLazyPagingItems()
|
val mangaList = screenModel.mangaPagerFlowFlow.collectAsLazyPagingItems()
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,6 @@ import kotlinx.coroutines.flow.stateIn
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlinx.serialization.encodeToString
|
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlinx.serialization.json.JsonArray
|
import kotlinx.serialization.json.JsonArray
|
||||||
import tachiyomi.core.common.preference.CheckboxState
|
import tachiyomi.core.common.preference.CheckboxState
|
||||||
|
|
|
||||||
|
|
@ -87,8 +87,6 @@ import exh.pagepreview.PagePreviewScreen
|
||||||
import exh.recs.RecommendsScreen
|
import exh.recs.RecommendsScreen
|
||||||
import exh.source.MERGED_SOURCE_ID
|
import exh.source.MERGED_SOURCE_ID
|
||||||
import exh.source.getMainSource
|
import exh.source.getMainSource
|
||||||
import exh.source.isMdBasedSource
|
|
||||||
import exh.ui.ifSourcesLoaded
|
|
||||||
import exh.ui.metadata.MetadataViewScreen
|
import exh.ui.metadata.MetadataViewScreen
|
||||||
import exh.ui.smartsearch.SmartSearchScreen
|
import exh.ui.smartsearch.SmartSearchScreen
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
|
|
@ -160,7 +158,7 @@ class MangaScreen(
|
||||||
|
|
||||||
BackHandler(enabled = bulkFavoriteState.selectionMode || showingRelatedMangasScreen.value) {
|
BackHandler(enabled = bulkFavoriteState.selectionMode || showingRelatedMangasScreen.value) {
|
||||||
when {
|
when {
|
||||||
bulkFavoriteState.selectionMode -> bulkFavoriteScreenModel.toggleSelectionMode()
|
bulkFavoriteState.selectionMode -> bulkFavoriteScreenModel.backHandler()
|
||||||
showingRelatedMangasScreen.value -> showingRelatedMangasScreen.value = false
|
showingRelatedMangasScreen.value -> showingRelatedMangasScreen.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ class MangaDexFollowsScreen(private val sourceId: Long) : Screen() {
|
||||||
val bulkFavoriteState by bulkFavoriteScreenModel.state.collectAsState()
|
val bulkFavoriteState by bulkFavoriteScreenModel.state.collectAsState()
|
||||||
|
|
||||||
BackHandler(enabled = bulkFavoriteState.selectionMode) {
|
BackHandler(enabled = bulkFavoriteState.selectionMode) {
|
||||||
bulkFavoriteScreenModel.toggleSelectionMode()
|
bulkFavoriteScreenModel.backHandler()
|
||||||
}
|
}
|
||||||
// KMK <--
|
// KMK <--
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ import eu.kanade.tachiyomi.ui.browse.RemoveMangaDialog
|
||||||
import eu.kanade.tachiyomi.ui.browse.source.SourcesScreen
|
import eu.kanade.tachiyomi.ui.browse.source.SourcesScreen
|
||||||
import eu.kanade.tachiyomi.ui.manga.MangaScreen
|
import eu.kanade.tachiyomi.ui.manga.MangaScreen
|
||||||
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
||||||
import exh.ui.ifSourcesLoaded
|
|
||||||
import mihon.presentation.core.util.collectAsLazyPagingItems
|
import mihon.presentation.core.util.collectAsLazyPagingItems
|
||||||
import tachiyomi.core.common.util.lang.launchIO
|
import tachiyomi.core.common.util.lang.launchIO
|
||||||
import tachiyomi.domain.manga.model.Manga
|
import tachiyomi.domain.manga.model.Manga
|
||||||
|
|
@ -65,7 +64,7 @@ class BrowseRecommendsScreen(
|
||||||
val haptic = LocalHapticFeedback.current
|
val haptic = LocalHapticFeedback.current
|
||||||
|
|
||||||
BackHandler(enabled = bulkFavoriteState.selectionMode) {
|
BackHandler(enabled = bulkFavoriteState.selectionMode) {
|
||||||
bulkFavoriteScreenModel.toggleSelectionMode()
|
bulkFavoriteScreenModel.backHandler()
|
||||||
}
|
}
|
||||||
// KMK <--
|
// KMK <--
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,16 @@
|
||||||
package exh.recs
|
package exh.recs
|
||||||
|
|
||||||
import androidx.activity.compose.BackHandler
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.compose.material3.SnackbarHost
|
|
||||||
import androidx.compose.material3.SnackbarHostState
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.ui.platform.LocalConfiguration
|
|
||||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||||
import cafe.adriel.voyager.core.model.rememberScreenModel
|
import cafe.adriel.voyager.core.model.rememberScreenModel
|
||||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||||
import eu.kanade.core.util.ifSourcesLoaded
|
import eu.kanade.core.util.ifSourcesLoaded
|
||||||
import eu.kanade.presentation.browse.BrowseSourceContent
|
|
||||||
import eu.kanade.presentation.browse.components.BrowseSourceSimpleToolbar
|
|
||||||
import eu.kanade.presentation.components.BulkSelectionToolbar
|
|
||||||
import eu.kanade.presentation.util.Screen
|
import eu.kanade.presentation.util.Screen
|
||||||
import eu.kanade.tachiyomi.ui.browse.AddDuplicateMangaDialog
|
import eu.kanade.tachiyomi.ui.browse.AddDuplicateMangaDialog
|
||||||
import eu.kanade.tachiyomi.ui.browse.AllowDuplicateDialog
|
import eu.kanade.tachiyomi.ui.browse.AllowDuplicateDialog
|
||||||
|
|
@ -28,14 +19,11 @@ import eu.kanade.tachiyomi.ui.browse.ChangeMangaCategoryDialog
|
||||||
import eu.kanade.tachiyomi.ui.browse.ChangeMangasCategoryDialog
|
import eu.kanade.tachiyomi.ui.browse.ChangeMangasCategoryDialog
|
||||||
import eu.kanade.tachiyomi.ui.browse.RemoveMangaDialog
|
import eu.kanade.tachiyomi.ui.browse.RemoveMangaDialog
|
||||||
import eu.kanade.tachiyomi.ui.browse.source.SourcesScreen
|
import eu.kanade.tachiyomi.ui.browse.source.SourcesScreen
|
||||||
import mihon.presentation.core.util.collectAsLazyPagingItems
|
|
||||||
import tachiyomi.core.common.util.lang.launchIO
|
|
||||||
import eu.kanade.tachiyomi.ui.manga.MangaScreen
|
import eu.kanade.tachiyomi.ui.manga.MangaScreen
|
||||||
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
||||||
import exh.recs.components.RecommendsScreen
|
import exh.recs.components.RecommendsScreen
|
||||||
import exh.ui.ifSourcesLoaded
|
import tachiyomi.core.common.util.lang.launchIO
|
||||||
import tachiyomi.domain.manga.model.Manga
|
import tachiyomi.domain.manga.model.Manga
|
||||||
import tachiyomi.presentation.core.components.material.Scaffold
|
|
||||||
import tachiyomi.presentation.core.screens.LoadingScreen
|
import tachiyomi.presentation.core.screens.LoadingScreen
|
||||||
|
|
||||||
class RecommendsScreen(val mangaId: Long, val sourceId: Long) : Screen() {
|
class RecommendsScreen(val mangaId: Long, val sourceId: Long) : Screen() {
|
||||||
|
|
@ -63,7 +51,7 @@ class RecommendsScreen(val mangaId: Long, val sourceId: Long) : Screen() {
|
||||||
val haptic = LocalHapticFeedback.current
|
val haptic = LocalHapticFeedback.current
|
||||||
|
|
||||||
BackHandler(enabled = bulkFavoriteState.selectionMode) {
|
BackHandler(enabled = bulkFavoriteState.selectionMode) {
|
||||||
bulkFavoriteScreenModel.toggleSelectionMode()
|
bulkFavoriteScreenModel.backHandler()
|
||||||
}
|
}
|
||||||
// KMK <--
|
// KMK <--
|
||||||
|
|
||||||
|
|
@ -125,8 +113,6 @@ class RecommendsScreen(val mangaId: Long, val sourceId: Long) : Screen() {
|
||||||
},
|
},
|
||||||
// KMK -->
|
// KMK -->
|
||||||
bulkFavoriteScreenModel = bulkFavoriteScreenModel,
|
bulkFavoriteScreenModel = bulkFavoriteScreenModel,
|
||||||
displayMode = screenModel.displayMode,
|
|
||||||
onDisplayModeChange = { screenModel.displayMode = it },
|
|
||||||
// KMK <--
|
// KMK <--
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,18 @@ import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
import androidx.compose.runtime.State
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import eu.kanade.presentation.browse.components.BrowseSourceSimpleToolbar
|
||||||
import eu.kanade.presentation.browse.components.GlobalSearchCardRow
|
import eu.kanade.presentation.browse.components.GlobalSearchCardRow
|
||||||
import eu.kanade.presentation.browse.components.GlobalSearchErrorResultItem
|
import eu.kanade.presentation.browse.components.GlobalSearchErrorResultItem
|
||||||
import eu.kanade.presentation.browse.components.GlobalSearchLoadingResultItem
|
import eu.kanade.presentation.browse.components.GlobalSearchLoadingResultItem
|
||||||
import eu.kanade.presentation.browse.components.GlobalSearchResultItem
|
import eu.kanade.presentation.browse.components.GlobalSearchResultItem
|
||||||
import eu.kanade.presentation.components.AppBar
|
import eu.kanade.presentation.components.BulkSelectionToolbar
|
||||||
import eu.kanade.presentation.util.formattedMessage
|
import eu.kanade.presentation.util.formattedMessage
|
||||||
|
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
||||||
|
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SearchItemResult
|
||||||
import exh.recs.RecommendationItemResult
|
import exh.recs.RecommendationItemResult
|
||||||
import exh.recs.RecommendsScreenModel
|
import exh.recs.RecommendsScreenModel
|
||||||
import exh.recs.sources.RecommendationPagingSource
|
import exh.recs.sources.RecommendationPagingSource
|
||||||
|
|
@ -30,14 +35,52 @@ fun RecommendsScreen(
|
||||||
onClickSource: (RecommendationPagingSource) -> Unit,
|
onClickSource: (RecommendationPagingSource) -> Unit,
|
||||||
onClickItem: (Manga) -> Unit,
|
onClickItem: (Manga) -> Unit,
|
||||||
onLongClickItem: (Manga) -> Unit,
|
onLongClickItem: (Manga) -> Unit,
|
||||||
|
// KMK -->
|
||||||
|
bulkFavoriteScreenModel: BulkFavoriteScreenModel,
|
||||||
|
// KMK <--
|
||||||
) {
|
) {
|
||||||
|
// KMK -->
|
||||||
|
val bulkFavoriteState by bulkFavoriteScreenModel.state.collectAsState()
|
||||||
|
// KMK <--
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = { scrollBehavior ->
|
topBar = { scrollBehavior ->
|
||||||
AppBar(
|
// KMK -->
|
||||||
title = stringResource(SYMR.strings.similar, manga.title),
|
if (bulkFavoriteState.selectionMode) {
|
||||||
scrollBehavior = scrollBehavior,
|
BulkSelectionToolbar(
|
||||||
navigateUp = navigateUp,
|
selectedCount = bulkFavoriteState.selection.size,
|
||||||
)
|
isRunning = bulkFavoriteState.isRunning,
|
||||||
|
onClickClearSelection = bulkFavoriteScreenModel::toggleSelectionMode,
|
||||||
|
onChangeCategoryClick = bulkFavoriteScreenModel::addFavorite,
|
||||||
|
onSelectAll = {
|
||||||
|
state.filteredItems.forEach { (_, result) ->
|
||||||
|
if (result is RecommendationItemResult.Success) {
|
||||||
|
result.result.forEach { manga ->
|
||||||
|
bulkFavoriteScreenModel.select(manga)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onReverseSelection = {
|
||||||
|
bulkFavoriteScreenModel.reverseSelection(
|
||||||
|
state.filteredItems.values
|
||||||
|
.filterIsInstance<SearchItemResult.Success>()
|
||||||
|
.flatMap { it.result },
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
BrowseSourceSimpleToolbar(
|
||||||
|
displayMode = null,
|
||||||
|
onDisplayModeChange = {},
|
||||||
|
toggleSelectionMode = bulkFavoriteScreenModel::toggleSelectionMode,
|
||||||
|
isRunning = bulkFavoriteState.isRunning,
|
||||||
|
// KMK <--
|
||||||
|
title = stringResource(SYMR.strings.similar, manga.title),
|
||||||
|
scrollBehavior = scrollBehavior,
|
||||||
|
navigateUp = navigateUp,
|
||||||
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
RecommendsContent(
|
RecommendsContent(
|
||||||
|
|
@ -47,6 +90,9 @@ fun RecommendsScreen(
|
||||||
onClickSource = onClickSource,
|
onClickSource = onClickSource,
|
||||||
onClickItem = onClickItem,
|
onClickItem = onClickItem,
|
||||||
onLongClickItem = onLongClickItem,
|
onLongClickItem = onLongClickItem,
|
||||||
|
// KMK -->
|
||||||
|
selection = bulkFavoriteState.selection,
|
||||||
|
// KMK <--
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -59,6 +105,9 @@ internal fun RecommendsContent(
|
||||||
onClickSource: (RecommendationPagingSource) -> Unit,
|
onClickSource: (RecommendationPagingSource) -> Unit,
|
||||||
onClickItem: (Manga) -> Unit,
|
onClickItem: (Manga) -> Unit,
|
||||||
onLongClickItem: (Manga) -> Unit,
|
onLongClickItem: (Manga) -> Unit,
|
||||||
|
// KMK -->
|
||||||
|
selection: List<Manga>,
|
||||||
|
// KMK <--
|
||||||
) {
|
) {
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
contentPadding = contentPadding,
|
contentPadding = contentPadding,
|
||||||
|
|
@ -80,6 +129,9 @@ internal fun RecommendsContent(
|
||||||
getManga = getManga,
|
getManga = getManga,
|
||||||
onClick = onClickItem,
|
onClick = onClickItem,
|
||||||
onLongClick = onLongClickItem,
|
onLongClick = onLongClickItem,
|
||||||
|
// KMK -->
|
||||||
|
selection = selection,
|
||||||
|
// KMK <--
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is RecommendationItemResult.Error -> {
|
is RecommendationItemResult.Error -> {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue