add BulkSelection to the rest of Migrate, MangaDex…

This commit is contained in:
Cuong M. Tran 2024-03-09 18:26:58 +07:00 committed by Cuong Tran
parent df229af0eb
commit a7c6232a50
No known key found for this signature in database
GPG key ID: 733AA7624B9315C2
7 changed files with 531 additions and 62 deletions

View file

@ -59,7 +59,7 @@ fun BrowseSourceContent(
onMangaClick: (Manga) -> Unit,
onMangaLongClick: (Manga) -> Unit,
// KMK -->
selection: List<Manga>? = null,
selection: List<Manga>,
// KMK <--
) {
val context = LocalContext.current

View file

@ -2,6 +2,7 @@ package eu.kanade.presentation.browse.components
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Check
import androidx.compose.material.icons.outlined.Checklist
import androidx.compose.material.icons.outlined.ViewModule
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Icon
@ -27,6 +28,9 @@ fun BrowseSourceSimpleToolbar(
displayMode: LibraryDisplayMode?,
onDisplayModeChange: (LibraryDisplayMode) -> Unit,
scrollBehavior: TopAppBarScrollBehavior,
// KMK -->
toggleSelectionMode: () -> Unit,
// KMK <--
) {
AppBar(
navigateUp = navigateUp,
@ -41,6 +45,13 @@ fun BrowseSourceSimpleToolbar(
icon = Icons.Outlined.ViewModule,
onClick = { selectingDisplayMode = true },
),
// KMK -->
AppBar.Action(
title = stringResource(MR.strings.action_bulk_select),
icon = Icons.Outlined.Checklist,
onClick = toggleSelectionMode,
),
// KMK <--
),
)
DropdownMenu(

View file

@ -53,18 +53,19 @@ class MigrateSearchScreen(private val mangaId: Long, private val validSources: L
},
onClickItem = {
// KMK -->
if (bulkFavoriteState.selectionMode)
if (bulkFavoriteState.selectionMode) {
bulkFavoriteScreenModel.toggleSelection(it)
else {
} else
// KMK <--
// SY -->
navigator.items
.filterIsInstance<MigrationListScreen>()
.last()
.newSelectedItem = mangaId to it.id
navigator.popUntil { it is MigrationListScreen }
// SY <--
}
{
// SY -->
navigator.items
.filterIsInstance<MigrationListScreen>()
.last()
.newSelectedItem = mangaId to it.id
navigator.popUntil { it is MigrationListScreen }
// SY <--
}
},
onLongClickItem = { navigator.push(MangaScreen(it.id, true)) },
// KMK -->
@ -73,12 +74,12 @@ class MigrateSearchScreen(private val mangaId: Long, private val validSources: L
)
// KMK -->
val onDismissRequest = { bulkFavoriteScreenModel.setDialog(null) }
val onBulkDismissRequest = { bulkFavoriteScreenModel.setDialog(null) }
when (val dialog = bulkFavoriteState.dialog) {
is BulkFavoriteScreenModel.Dialog.ChangeMangasCategory -> {
ChangeCategoryDialog(
initialSelection = dialog.initialSelection,
onDismissRequest = onDismissRequest,
onDismissRequest = onBulkDismissRequest,
onEditCategories = { navigator.push(CategoryScreen()) },
onConfirm = { include, exclude ->
bulkFavoriteScreenModel.setMangasCategories(dialog.mangas, include, exclude)
@ -87,7 +88,7 @@ class MigrateSearchScreen(private val mangaId: Long, private val validSources: L
}
is BulkFavoriteScreenModel.Dialog.AllowDuplicate -> {
AllowDuplicateDialog(
onDismissRequest = onDismissRequest,
onDismissRequest = onBulkDismissRequest,
onAllowAllDuplicate = {
bulkFavoriteScreenModel.addFavoriteDuplicate()
},

View file

@ -1,5 +1,8 @@
package eu.kanade.tachiyomi.ui.browse.migration.search
import androidx.activity.compose.BackHandler
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Checklist
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable
@ -14,18 +17,27 @@ import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.presentation.browse.BrowseSourceContent
import eu.kanade.presentation.browse.components.BrowseSourceFloatingActionButton
import eu.kanade.presentation.category.components.ChangeCategoryDialog
import eu.kanade.presentation.components.AppBar
import eu.kanade.presentation.components.AppBarActions
import eu.kanade.presentation.components.SearchToolbar
import eu.kanade.presentation.components.SelectionToolbar
import eu.kanade.presentation.manga.AllowDuplicateDialog
import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigrationListScreen
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreenModel
import eu.kanade.tachiyomi.ui.browse.source.browse.SourceFilterDialog
import eu.kanade.tachiyomi.ui.category.CategoryScreen
import eu.kanade.tachiyomi.ui.manga.MangaScreen
import eu.kanade.tachiyomi.ui.webview.WebViewScreen
import kotlinx.collections.immutable.persistentListOf
import tachiyomi.core.common.Constants
import tachiyomi.domain.manga.model.Manga
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.source.local.LocalSource
data class SourceSearchScreen(
@ -44,15 +56,51 @@ data class SourceSearchScreen(
val snackbarHostState = remember { SnackbarHostState() }
// KMK -->
val bulkFavoriteScreenModel = rememberScreenModel { BulkFavoriteScreenModel() }
val bulkFavoriteState by bulkFavoriteScreenModel.state.collectAsState()
BackHandler(enabled = bulkFavoriteState.selectionMode) {
bulkFavoriteScreenModel.toggleSelectionMode()
}
// KMK <--
Scaffold(
topBar = { scrollBehavior ->
SearchToolbar(
searchQuery = state.toolbarQuery ?: "",
onChangeSearchQuery = screenModel::setToolbarQuery,
onClickCloseSearch = navigator::pop,
onSearch = screenModel::search,
scrollBehavior = scrollBehavior,
)
// KMK -->
if (bulkFavoriteState.selectionMode) {
SelectionToolbar(
selectedCount = bulkFavoriteState.selection.size,
onClickClearSelection = bulkFavoriteScreenModel::toggleSelectionMode,
onChangeCategoryClicked = bulkFavoriteScreenModel::addFavorite,
)
} else {
// KMK <--
SearchToolbar(
searchQuery = state.toolbarQuery ?: "",
onChangeSearchQuery = screenModel::setToolbarQuery,
onClickCloseSearch = navigator::pop,
onSearch = screenModel::search,
scrollBehavior = scrollBehavior,
// KMK -->
actions = {
AppBarActions(
actions = persistentListOf<AppBar.AppBarAction>().builder()
.apply {
add(
AppBar.Action(
title = stringResource(MR.strings.action_bulk_select),
icon = Icons.Outlined.Checklist,
onClick = bulkFavoriteScreenModel::toggleSelectionMode,
),
)
}
.build(),
)
},
// KMK <--
)
}
},
floatingActionButton = {
// SY -->
@ -96,8 +144,19 @@ data class SourceSearchScreen(
},
onHelpClick = { uriHandler.openUri(Constants.URL_HELP) },
onLocalSourceHelpClick = { uriHandler.openUri(LocalSource.HELP_URL) },
onMangaClick = openMigrateDialog,
onMangaClick = { manga ->
// KMK -->
if (bulkFavoriteState.selectionMode) {
bulkFavoriteScreenModel.toggleSelection(manga)
} else {
// KMK <--
openMigrateDialog(manga)
}
},
onMangaLongClick = { navigator.push(MangaScreen(it.id, true)) },
// KMK -->
selection = bulkFavoriteState.selection,
// KMK <--
)
}
@ -123,5 +182,44 @@ data class SourceSearchScreen(
}
else -> {}
}
// KMK -->
val onBulkDismissRequest = { bulkFavoriteScreenModel.setDialog(null) }
when (val dialog = bulkFavoriteState.dialog) {
is BulkFavoriteScreenModel.Dialog.ChangeMangasCategory -> {
ChangeCategoryDialog(
initialSelection = dialog.initialSelection,
onDismissRequest = onBulkDismissRequest,
onEditCategories = { navigator.push(CategoryScreen()) },
onConfirm = { include, exclude ->
bulkFavoriteScreenModel.setMangasCategories(dialog.mangas, include, exclude)
},
)
}
is BulkFavoriteScreenModel.Dialog.AllowDuplicate -> {
AllowDuplicateDialog(
onDismissRequest = onBulkDismissRequest,
onAllowAllDuplicate = {
bulkFavoriteScreenModel.addFavoriteDuplicate()
},
onSkipAllDuplicate = {
bulkFavoriteScreenModel.addFavoriteDuplicate(skipAllDuplicates = true)
},
onOpenManga = {
navigator.push(MangaScreen(dialog.duplicatedManga.second.id))
},
onAllowDuplicate = {
bulkFavoriteScreenModel.addFavorite(startIdx = dialog.duplicatedManga.first + 1)
},
onSkipDuplicate = {
bulkFavoriteScreenModel.removeDuplicateSelectedManga(index = dialog.duplicatedManga.first)
bulkFavoriteScreenModel.addFavorite(startIdx = dialog.duplicatedManga.first)
},
duplicatedName = dialog.duplicatedManga.second.title,
)
}
else -> {}
}
// KMK <--
}
}

View file

@ -1,5 +1,6 @@
package exh.md.follows
import androidx.activity.compose.BackHandler
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable
@ -18,8 +19,11 @@ 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.manga.AllowDuplicateDialog
import eu.kanade.presentation.manga.DuplicateMangaDialog
import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreenModel
import eu.kanade.tachiyomi.ui.category.CategoryScreen
import eu.kanade.tachiyomi.ui.manga.MangaScreen
@ -38,17 +42,39 @@ class MangaDexFollowsScreen(private val sourceId: Long) : Screen() {
val screenModel = rememberScreenModel { MangaDexFollowsScreenModel(sourceId) }
val state by screenModel.state.collectAsState()
// KMK -->
val bulkFavoriteScreenModel = rememberScreenModel { BulkFavoriteScreenModel() }
val bulkFavoriteState by bulkFavoriteScreenModel.state.collectAsState()
BackHandler(enabled = bulkFavoriteState.selectionMode) {
bulkFavoriteScreenModel.toggleSelectionMode()
}
// KMK <--
val snackbarHostState = remember { SnackbarHostState() }
Scaffold(
topBar = { scrollBehavior ->
BrowseSourceSimpleToolbar(
title = stringResource(SYMR.strings.mangadex_follows),
displayMode = screenModel.displayMode,
onDisplayModeChange = { screenModel.displayMode = it },
navigateUp = navigator::pop,
scrollBehavior = scrollBehavior,
)
// KMK -->
if (bulkFavoriteState.selectionMode) {
SelectionToolbar(
selectedCount = bulkFavoriteState.selection.size,
onClickClearSelection = bulkFavoriteScreenModel::toggleSelectionMode,
onChangeCategoryClicked = bulkFavoriteScreenModel::addFavorite,
)
} else {
// KMK <--
BrowseSourceSimpleToolbar(
title = stringResource(SYMR.strings.mangadex_follows),
displayMode = screenModel.displayMode,
onDisplayModeChange = { screenModel.displayMode = it },
navigateUp = navigator::pop,
scrollBehavior = scrollBehavior,
// KMK -->
toggleSelectionMode = bulkFavoriteScreenModel::toggleSelectionMode,
// KMK <--
)
}
},
snackbarHost = {
SnackbarHost(hostState = snackbarHostState)
@ -69,23 +95,42 @@ class MangaDexFollowsScreen(private val sourceId: Long) : Screen() {
onWebViewClick = null,
onHelpClick = null,
onLocalSourceHelpClick = null,
onMangaClick = { navigator.push(MangaScreen(it.id, true)) },
onMangaLongClick = { manga ->
scope.launchIO {
val duplicateManga = screenModel.getDuplicateLibraryManga(manga)
when {
manga.favorite -> screenModel.setDialog(BrowseSourceScreenModel.Dialog.RemoveManga(manga))
duplicateManga != null -> screenModel.setDialog(
BrowseSourceScreenModel.Dialog.AddDuplicateManga(
manga,
duplicateManga,
),
)
else -> screenModel.addFavorite(manga)
}
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
onMangaClick = {
// KMK -->
if (bulkFavoriteState.selectionMode) {
bulkFavoriteScreenModel.toggleSelection(it)
} else {
// KMK <--
navigator.push(MangaScreen(it.id, true))
}
},
onMangaLongClick = { manga ->
// KMK -->
if (bulkFavoriteState.selectionMode) {
navigator.push(MangaScreen(manga.id, true))
} else {
// KMK <--
scope.launchIO {
val duplicateManga = screenModel.getDuplicateLibraryManga(manga)
when {
manga.favorite -> screenModel.setDialog(
BrowseSourceScreenModel.Dialog.RemoveManga(manga)
)
duplicateManga != null -> screenModel.setDialog(
BrowseSourceScreenModel.Dialog.AddDuplicateManga(
manga,
duplicateManga,
),
)
else -> screenModel.addFavorite(manga)
}
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
}
}
},
// KMK -->
selection = bulkFavoriteState.selection,
// KMK <--
)
}
@ -123,5 +168,44 @@ class MangaDexFollowsScreen(private val sourceId: Long) : Screen() {
}
else -> {}
}
// KMK -->
val onBulkDismissRequest = { bulkFavoriteScreenModel.setDialog(null) }
when (val dialog = bulkFavoriteState.dialog) {
is BulkFavoriteScreenModel.Dialog.ChangeMangasCategory -> {
ChangeCategoryDialog(
initialSelection = dialog.initialSelection,
onDismissRequest = onBulkDismissRequest,
onEditCategories = { navigator.push(CategoryScreen()) },
onConfirm = { include, exclude ->
bulkFavoriteScreenModel.setMangasCategories(dialog.mangas, include, exclude)
},
)
}
is BulkFavoriteScreenModel.Dialog.AllowDuplicate -> {
AllowDuplicateDialog(
onDismissRequest = onBulkDismissRequest,
onAllowAllDuplicate = {
bulkFavoriteScreenModel.addFavoriteDuplicate()
},
onSkipAllDuplicate = {
bulkFavoriteScreenModel.addFavoriteDuplicate(skipAllDuplicates = true)
},
onOpenManga = {
navigator.push(MangaScreen(dialog.duplicatedManga.second.id))
},
onAllowDuplicate = {
bulkFavoriteScreenModel.addFavorite(startIdx = dialog.duplicatedManga.first + 1)
},
onSkipDuplicate = {
bulkFavoriteScreenModel.removeDuplicateSelectedManga(index = dialog.duplicatedManga.first)
bulkFavoriteScreenModel.addFavorite(startIdx = dialog.duplicatedManga.first)
},
duplicatedName = dialog.duplicatedManga.second.title,
)
}
else -> {}
}
// KMK <--
}
}

View file

@ -1,20 +1,32 @@
package exh.md.similar
import androidx.activity.compose.BackHandler
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.paging.compose.collectAsLazyPagingItems
import cafe.adriel.voyager.core.model.rememberScreenModel
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.browse.components.RemoveMangaDialog
import eu.kanade.presentation.category.components.ChangeCategoryDialog
import eu.kanade.presentation.components.SelectionToolbar
import eu.kanade.presentation.manga.AllowDuplicateDialog
import eu.kanade.presentation.manga.DuplicateMangaDialog
import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
import eu.kanade.tachiyomi.ui.category.CategoryScreen
import eu.kanade.tachiyomi.ui.manga.MangaScreen
import tachiyomi.core.common.util.lang.launchIO
import tachiyomi.domain.manga.model.Manga
import tachiyomi.i18n.sy.SYMR
import tachiyomi.presentation.core.components.material.Scaffold
@ -28,6 +40,18 @@ class MangaDexSimilarScreen(val mangaId: Long, val sourceId: Long) : Screen() {
val state by screenModel.state.collectAsState()
val navigator = LocalNavigator.currentOrThrow
// KMK -->
val bulkFavoriteScreenModel = rememberScreenModel { BulkFavoriteScreenModel() }
val bulkFavoriteState by bulkFavoriteScreenModel.state.collectAsState()
val scope = rememberCoroutineScope()
val haptic = LocalHapticFeedback.current
BackHandler(enabled = bulkFavoriteState.selectionMode) {
bulkFavoriteScreenModel.toggleSelectionMode()
}
// KMK <--
val onMangaClick: (Manga) -> Unit = {
navigator.push(MangaScreen(it.id, true))
}
@ -36,13 +60,26 @@ class MangaDexSimilarScreen(val mangaId: Long, val sourceId: Long) : Screen() {
Scaffold(
topBar = { scrollBehavior ->
BrowseSourceSimpleToolbar(
navigateUp = navigator::pop,
title = stringResource(SYMR.strings.similar, screenModel.manga.title),
displayMode = screenModel.displayMode,
onDisplayModeChange = { screenModel.displayMode = it },
scrollBehavior = scrollBehavior,
)
// KMK -->
if (bulkFavoriteState.selectionMode) {
SelectionToolbar(
selectedCount = bulkFavoriteState.selection.size,
onClickClearSelection = bulkFavoriteScreenModel::toggleSelectionMode,
onChangeCategoryClicked = bulkFavoriteScreenModel::addFavorite,
)
} else {
// KMK <--
BrowseSourceSimpleToolbar(
navigateUp = navigator::pop,
title = stringResource(SYMR.strings.similar, screenModel.manga.title),
displayMode = screenModel.displayMode,
onDisplayModeChange = { screenModel.displayMode = it },
scrollBehavior = scrollBehavior,
// KMK -->
toggleSelectionMode = bulkFavoriteScreenModel::toggleSelectionMode,
// KMK <--
)
}
},
snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
) { paddingValues ->
@ -61,9 +98,109 @@ class MangaDexSimilarScreen(val mangaId: Long, val sourceId: Long) : Screen() {
onWebViewClick = null,
onHelpClick = null,
onLocalSourceHelpClick = null,
onMangaClick = onMangaClick,
onMangaLongClick = onMangaClick,
onMangaClick = { manga ->
// KMK -->
if (bulkFavoriteState.selectionMode) {
bulkFavoriteScreenModel.toggleSelection(manga)
} else {
// KMK <--
onMangaClick(manga)
}
},
onMangaLongClick = { manga ->
// KMK -->
if (!bulkFavoriteState.selectionMode) {
scope.launchIO {
val duplicateManga = bulkFavoriteScreenModel.getDuplicateLibraryManga(manga)
when {
manga.favorite -> bulkFavoriteScreenModel.setDialog(
BulkFavoriteScreenModel.Dialog.RemoveManga(manga)
)
duplicateManga != null -> bulkFavoriteScreenModel.setDialog(
BulkFavoriteScreenModel.Dialog.AddDuplicateManga(
manga,
duplicateManga,
),
)
else -> bulkFavoriteScreenModel.addFavorite(manga)
}
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
}
} else {
// KMK <--
onMangaClick(manga)
}
},
// KMK -->
selection = bulkFavoriteState.selection,
// KMK <--
)
}
// KMK -->
val onBulkDismissRequest = { bulkFavoriteScreenModel.setDialog(null) }
when (val dialog = bulkFavoriteState.dialog) {
is BulkFavoriteScreenModel.Dialog.AddDuplicateManga -> {
DuplicateMangaDialog(
onDismissRequest = onBulkDismissRequest,
onConfirm = { bulkFavoriteScreenModel.addFavorite(dialog.manga) },
onOpenManga = { navigator.push(MangaScreen(dialog.duplicate.id)) },
)
}
is BulkFavoriteScreenModel.Dialog.RemoveManga -> {
RemoveMangaDialog(
onDismissRequest = onBulkDismissRequest,
onConfirm = {
bulkFavoriteScreenModel.changeMangaFavorite(dialog.manga)
},
mangaToRemove = dialog.manga,
)
}
is BulkFavoriteScreenModel.Dialog.ChangeMangaCategory -> {
ChangeCategoryDialog(
initialSelection = dialog.initialSelection,
onDismissRequest = onBulkDismissRequest,
onEditCategories = { navigator.push(CategoryScreen()) },
onConfirm = { include, _ ->
bulkFavoriteScreenModel.changeMangaFavorite(dialog.manga)
bulkFavoriteScreenModel.moveMangaToCategories(dialog.manga, include)
},
)
}
is BulkFavoriteScreenModel.Dialog.ChangeMangasCategory -> {
ChangeCategoryDialog(
initialSelection = dialog.initialSelection,
onDismissRequest = onBulkDismissRequest,
onEditCategories = { navigator.push(CategoryScreen()) },
onConfirm = { include, exclude ->
bulkFavoriteScreenModel.setMangasCategories(dialog.mangas, include, exclude)
},
)
}
is BulkFavoriteScreenModel.Dialog.AllowDuplicate -> {
AllowDuplicateDialog(
onDismissRequest = onBulkDismissRequest,
onAllowAllDuplicate = {
bulkFavoriteScreenModel.addFavoriteDuplicate()
},
onSkipAllDuplicate = {
bulkFavoriteScreenModel.addFavoriteDuplicate(skipAllDuplicates = true)
},
onOpenManga = {
navigator.push(MangaScreen(dialog.duplicatedManga.second.id))
},
onAllowDuplicate = {
bulkFavoriteScreenModel.addFavorite(startIdx = dialog.duplicatedManga.first + 1)
},
onSkipDuplicate = {
bulkFavoriteScreenModel.removeDuplicateSelectedManga(index = dialog.duplicatedManga.first)
bulkFavoriteScreenModel.addFavorite(startIdx = dialog.duplicatedManga.first)
},
duplicatedName = dialog.duplicatedManga.second.title,
)
}
else -> {}
}
// KMK <--
}
}

View file

@ -1,12 +1,16 @@
package exh.recs
import androidx.activity.compose.BackHandler
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.paging.compose.collectAsLazyPagingItems
import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.navigator.LocalNavigator
@ -14,8 +18,17 @@ 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.browse.components.RemoveMangaDialog
import eu.kanade.presentation.category.components.ChangeCategoryDialog
import eu.kanade.presentation.components.SelectionToolbar
import eu.kanade.presentation.manga.AllowDuplicateDialog
import eu.kanade.presentation.manga.DuplicateMangaDialog
import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
import eu.kanade.tachiyomi.ui.browse.source.SourcesScreen
import eu.kanade.tachiyomi.ui.category.CategoryScreen
import eu.kanade.tachiyomi.ui.manga.MangaScreen
import tachiyomi.core.common.util.lang.launchIO
import tachiyomi.domain.manga.model.Manga
import tachiyomi.presentation.core.components.material.Scaffold
@ -27,6 +40,18 @@ class RecommendsScreen(val mangaId: Long, val sourceId: Long) : Screen() {
val state by screenModel.state.collectAsState()
val navigator = LocalNavigator.currentOrThrow
// KMK -->
val bulkFavoriteScreenModel = rememberScreenModel { BulkFavoriteScreenModel() }
val bulkFavoriteState by bulkFavoriteScreenModel.state.collectAsState()
val scope = rememberCoroutineScope()
val haptic = LocalHapticFeedback.current
BackHandler(enabled = bulkFavoriteState.selectionMode) {
bulkFavoriteScreenModel.toggleSelectionMode()
}
// KMK <--
val onMangaClick: (Manga) -> Unit = { manga ->
openSmartSearch(navigator, manga.ogTitle)
}
@ -35,13 +60,26 @@ class RecommendsScreen(val mangaId: Long, val sourceId: Long) : Screen() {
Scaffold(
topBar = { scrollBehavior ->
BrowseSourceSimpleToolbar(
navigateUp = navigator::pop,
title = screenModel.manga.title,
displayMode = screenModel.displayMode,
onDisplayModeChange = { screenModel.displayMode = it },
scrollBehavior = scrollBehavior,
)
// KMK -->
if (bulkFavoriteState.selectionMode) {
SelectionToolbar(
selectedCount = bulkFavoriteState.selection.size,
onClickClearSelection = bulkFavoriteScreenModel::toggleSelectionMode,
onChangeCategoryClicked = bulkFavoriteScreenModel::addFavorite,
)
} else {
// KMK <--
BrowseSourceSimpleToolbar(
navigateUp = navigator::pop,
title = screenModel.manga.title,
displayMode = screenModel.displayMode,
onDisplayModeChange = { screenModel.displayMode = it },
scrollBehavior = scrollBehavior,
// KMK -->
toggleSelectionMode = bulkFavoriteScreenModel::toggleSelectionMode,
// KMK <--
)
}
},
snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
) { paddingValues ->
@ -60,10 +98,110 @@ class RecommendsScreen(val mangaId: Long, val sourceId: Long) : Screen() {
onWebViewClick = null,
onHelpClick = null,
onLocalSourceHelpClick = null,
onMangaClick = onMangaClick,
onMangaLongClick = onMangaClick,
onMangaClick = { manga ->
// KMK -->
if (bulkFavoriteState.selectionMode) {
bulkFavoriteScreenModel.toggleSelection(manga)
} else {
// KMK <--
onMangaClick(manga)
}
},
onMangaLongClick = { manga ->
// KMK -->
if (!bulkFavoriteState.selectionMode) {
scope.launchIO {
val duplicateManga = bulkFavoriteScreenModel.getDuplicateLibraryManga(manga)
when {
manga.favorite -> bulkFavoriteScreenModel.setDialog(
BulkFavoriteScreenModel.Dialog.RemoveManga(manga)
)
duplicateManga != null -> bulkFavoriteScreenModel.setDialog(
BulkFavoriteScreenModel.Dialog.AddDuplicateManga(
manga,
duplicateManga,
),
)
else -> bulkFavoriteScreenModel.addFavorite(manga)
}
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
}
} else {
// KMK <--
onMangaClick(manga)
}
},
// KMK -->
selection = bulkFavoriteState.selection,
// KMK <--
)
}
// KMK -->
val onBulkDismissRequest = { bulkFavoriteScreenModel.setDialog(null) }
when (val dialog = bulkFavoriteState.dialog) {
is BulkFavoriteScreenModel.Dialog.AddDuplicateManga -> {
DuplicateMangaDialog(
onDismissRequest = onBulkDismissRequest,
onConfirm = { bulkFavoriteScreenModel.addFavorite(dialog.manga) },
onOpenManga = { navigator.push(MangaScreen(dialog.duplicate.id)) },
)
}
is BulkFavoriteScreenModel.Dialog.RemoveManga -> {
RemoveMangaDialog(
onDismissRequest = onBulkDismissRequest,
onConfirm = {
bulkFavoriteScreenModel.changeMangaFavorite(dialog.manga)
},
mangaToRemove = dialog.manga,
)
}
is BulkFavoriteScreenModel.Dialog.ChangeMangaCategory -> {
ChangeCategoryDialog(
initialSelection = dialog.initialSelection,
onDismissRequest = onBulkDismissRequest,
onEditCategories = { navigator.push(CategoryScreen()) },
onConfirm = { include, _ ->
bulkFavoriteScreenModel.changeMangaFavorite(dialog.manga)
bulkFavoriteScreenModel.moveMangaToCategories(dialog.manga, include)
},
)
}
is BulkFavoriteScreenModel.Dialog.ChangeMangasCategory -> {
ChangeCategoryDialog(
initialSelection = dialog.initialSelection,
onDismissRequest = onBulkDismissRequest,
onEditCategories = { navigator.push(CategoryScreen()) },
onConfirm = { include, exclude ->
bulkFavoriteScreenModel.setMangasCategories(dialog.mangas, include, exclude)
},
)
}
is BulkFavoriteScreenModel.Dialog.AllowDuplicate -> {
AllowDuplicateDialog(
onDismissRequest = onBulkDismissRequest,
onAllowAllDuplicate = {
bulkFavoriteScreenModel.addFavoriteDuplicate()
},
onSkipAllDuplicate = {
bulkFavoriteScreenModel.addFavoriteDuplicate(skipAllDuplicates = true)
},
onOpenManga = {
navigator.push(MangaScreen(dialog.duplicatedManga.second.id))
},
onAllowDuplicate = {
bulkFavoriteScreenModel.addFavorite(startIdx = dialog.duplicatedManga.first + 1)
},
onSkipDuplicate = {
bulkFavoriteScreenModel.removeDuplicateSelectedManga(index = dialog.duplicatedManga.first)
bulkFavoriteScreenModel.addFavorite(startIdx = dialog.duplicatedManga.first)
},
duplicatedName = dialog.duplicatedManga.second.title,
)
}
else -> {}
}
// KMK <--
}
private fun openSmartSearch(navigator: Navigator, title: String) {