Allow migrate mangas when using Bulk-favorite (#824)
* Combine ChangeMangaCategoryDialog * Allow migrating a single manga when using Bulk-favorite * Allow migrating mangas one by one when using Bulk-favorite * set visibility * Fix duplicate toggleSelection after migration * After migration, continue adding favorites if there are more to bulk-favorite or push new Manga screen if it's a single manga being added by long-click * fix usage of ChangeMangaCategory * improve toggleSelection code * refactoring ChangeMangasCategory * switch LocalNavigator.currentOrThrow to current * split composable to `presentation` * hoisting the state to a common parent composable * Fix migration dialog dismissed when clicking on Show entry * Don't push new Manga screen after migration of duplicated entries everywhere
This commit is contained in:
parent
8d94c09a43
commit
fa7b18590e
19 changed files with 282 additions and 231 deletions
|
|
@ -17,13 +17,13 @@ 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.browse.components.bulkSelectionButton
|
||||||
import eu.kanade.presentation.components.AppBar
|
import eu.kanade.presentation.components.AppBar
|
||||||
import eu.kanade.presentation.components.AppBarActions
|
import eu.kanade.presentation.components.AppBarActions
|
||||||
import eu.kanade.presentation.components.AppBarTitle
|
import eu.kanade.presentation.components.AppBarTitle
|
||||||
import eu.kanade.presentation.components.BulkSelectionToolbar
|
import eu.kanade.presentation.components.BulkSelectionToolbar
|
||||||
import eu.kanade.presentation.components.SearchToolbar
|
import eu.kanade.presentation.components.SearchToolbar
|
||||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
||||||
import eu.kanade.tachiyomi.ui.browse.bulkSelectionButton
|
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import tachiyomi.domain.manga.model.Manga
|
import tachiyomi.domain.manga.model.Manga
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ import eu.kanade.presentation.components.AppBar
|
||||||
import eu.kanade.presentation.components.AppBarActions
|
import eu.kanade.presentation.components.AppBarActions
|
||||||
import eu.kanade.presentation.components.DropdownMenu
|
import eu.kanade.presentation.components.DropdownMenu
|
||||||
import eu.kanade.presentation.components.RadioMenuItem
|
import eu.kanade.presentation.components.RadioMenuItem
|
||||||
import eu.kanade.tachiyomi.ui.browse.bulkSelectionButton
|
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import tachiyomi.domain.library.model.LibraryDisplayMode
|
import tachiyomi.domain.library.model.LibraryDisplayMode
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ import eu.kanade.presentation.components.RadioMenuItem
|
||||||
import eu.kanade.presentation.components.SearchToolbar
|
import eu.kanade.presentation.components.SearchToolbar
|
||||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import eu.kanade.tachiyomi.ui.browse.bulkSelectionButton
|
|
||||||
import exh.source.anyIs
|
import exh.source.anyIs
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import tachiyomi.domain.library.model.LibraryDisplayMode
|
import tachiyomi.domain.library.model.LibraryDisplayMode
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,225 @@
|
||||||
|
package eu.kanade.presentation.browse.components
|
||||||
|
|
||||||
|
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.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||||
|
import cafe.adriel.voyager.navigator.Navigator
|
||||||
|
import eu.kanade.presentation.category.components.ChangeCategoryDialog
|
||||||
|
import eu.kanade.presentation.components.AppBar
|
||||||
|
import eu.kanade.presentation.manga.DuplicateMangaDialog
|
||||||
|
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
||||||
|
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel.Dialog
|
||||||
|
import eu.kanade.tachiyomi.ui.browse.migration.search.MigrateDialog
|
||||||
|
import eu.kanade.tachiyomi.ui.browse.migration.search.MigrateDialogScreenModel
|
||||||
|
import eu.kanade.tachiyomi.ui.category.CategoryScreen
|
||||||
|
import eu.kanade.tachiyomi.ui.manga.MangaScreen
|
||||||
|
import tachiyomi.domain.manga.model.Manga
|
||||||
|
import tachiyomi.i18n.kmk.KMR
|
||||||
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compose to shows the bulk favorite dialogs.
|
||||||
|
*
|
||||||
|
* @param bulkFavoriteScreenModel the screen model.
|
||||||
|
* @param dialog the dialog to show.
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun BulkFavoriteDialogs(
|
||||||
|
bulkFavoriteScreenModel: BulkFavoriteScreenModel,
|
||||||
|
dialog: Dialog?,
|
||||||
|
) {
|
||||||
|
val navigator = LocalNavigator.current
|
||||||
|
val bulkFavoriteState by bulkFavoriteScreenModel.state.collectAsState()
|
||||||
|
|
||||||
|
when (dialog) {
|
||||||
|
/* Bulk-favorite actions */
|
||||||
|
is Dialog.ChangeMangasCategory ->
|
||||||
|
ChangeMangasCategoryDialog(
|
||||||
|
dialog = dialog,
|
||||||
|
navigator = navigator,
|
||||||
|
onDismiss = bulkFavoriteScreenModel::dismissDialog,
|
||||||
|
onConfirm = { include, exclude ->
|
||||||
|
bulkFavoriteScreenModel.setMangasCategories(dialog.mangas, include, exclude)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
is Dialog.BulkAllowDuplicate ->
|
||||||
|
BulkAllowDuplicateDialog(
|
||||||
|
dialog = dialog,
|
||||||
|
navigator = navigator,
|
||||||
|
onDismiss = bulkFavoriteScreenModel::dismissDialog,
|
||||||
|
stopRunning = bulkFavoriteScreenModel::stopRunning,
|
||||||
|
addFavorite = bulkFavoriteScreenModel::addFavorite,
|
||||||
|
showMigrateDialog = bulkFavoriteScreenModel::showMigrateDialog,
|
||||||
|
addFavoriteDuplicate = bulkFavoriteScreenModel::addFavoriteDuplicate,
|
||||||
|
removeDuplicateSelectedManga = bulkFavoriteScreenModel::removeDuplicateSelectedManga,
|
||||||
|
)
|
||||||
|
|
||||||
|
/* Single-favorite actions for screens originally don't have it */
|
||||||
|
is Dialog.AddDuplicateManga ->
|
||||||
|
AddDuplicateMangaDialog(
|
||||||
|
dialog = dialog,
|
||||||
|
navigator = navigator,
|
||||||
|
state = bulkFavoriteState,
|
||||||
|
onDismiss = bulkFavoriteScreenModel::dismissDialog,
|
||||||
|
stopRunning = bulkFavoriteScreenModel::stopRunning,
|
||||||
|
toggleSelectionMode = bulkFavoriteScreenModel::toggleSelectionMode,
|
||||||
|
addFavorite = bulkFavoriteScreenModel::addFavorite,
|
||||||
|
showMigrateDialog = bulkFavoriteScreenModel::showMigrateDialog,
|
||||||
|
)
|
||||||
|
|
||||||
|
is Dialog.RemoveManga ->
|
||||||
|
RemoveMangaDialog(
|
||||||
|
dialog = dialog,
|
||||||
|
onDismiss = bulkFavoriteScreenModel::dismissDialog,
|
||||||
|
changeMangaFavorite = bulkFavoriteScreenModel::changeMangaFavorite,
|
||||||
|
)
|
||||||
|
|
||||||
|
is Dialog.Migrate ->
|
||||||
|
ShowMigrateDialog(
|
||||||
|
dialog = dialog,
|
||||||
|
navigator = navigator,
|
||||||
|
state = bulkFavoriteState,
|
||||||
|
onDismiss = bulkFavoriteScreenModel::dismissDialog,
|
||||||
|
stopRunning = bulkFavoriteScreenModel::stopRunning,
|
||||||
|
toggleSelection = bulkFavoriteScreenModel::toggleSelection,
|
||||||
|
addFavorite = bulkFavoriteScreenModel::addFavorite,
|
||||||
|
)
|
||||||
|
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ShowMigrateDialog(
|
||||||
|
dialog: Dialog.Migrate,
|
||||||
|
navigator: Navigator?,
|
||||||
|
state: BulkFavoriteScreenModel.State,
|
||||||
|
onDismiss: () -> Unit,
|
||||||
|
stopRunning: () -> Unit,
|
||||||
|
toggleSelection: (Manga, toSelectedState: Boolean) -> Unit,
|
||||||
|
addFavorite: () -> Unit,
|
||||||
|
) {
|
||||||
|
stopRunning()
|
||||||
|
|
||||||
|
MigrateDialog(
|
||||||
|
oldManga = dialog.oldManga,
|
||||||
|
newManga = dialog.newManga,
|
||||||
|
screenModel = MigrateDialogScreenModel(),
|
||||||
|
onDismissRequest = onDismiss,
|
||||||
|
onClickTitle = { navigator?.push(MangaScreen(dialog.oldManga.id)) },
|
||||||
|
onPopScreen = {
|
||||||
|
toggleSelection(dialog.newManga, false)
|
||||||
|
onDismiss()
|
||||||
|
// `selection.size` is at current value before calling above `toggleSelection`
|
||||||
|
if (state.selection.size > 1) {
|
||||||
|
// Continue adding favorites
|
||||||
|
addFavorite()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows dialog to add a single manga to library when there are duplicates.
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
private fun AddDuplicateMangaDialog(
|
||||||
|
dialog: Dialog.AddDuplicateManga,
|
||||||
|
navigator: Navigator?,
|
||||||
|
state: BulkFavoriteScreenModel.State,
|
||||||
|
onDismiss: () -> Unit,
|
||||||
|
stopRunning: () -> Unit,
|
||||||
|
toggleSelectionMode: () -> Unit,
|
||||||
|
addFavorite: (Manga) -> Unit,
|
||||||
|
showMigrateDialog: (manga: Manga, duplicate: Manga) -> Unit,
|
||||||
|
) {
|
||||||
|
stopRunning()
|
||||||
|
|
||||||
|
DuplicateMangaDialog(
|
||||||
|
duplicates = dialog.duplicates,
|
||||||
|
onDismissRequest = onDismiss,
|
||||||
|
onConfirm = {
|
||||||
|
if (state.selectionMode) {
|
||||||
|
toggleSelectionMode()
|
||||||
|
}
|
||||||
|
addFavorite(dialog.manga)
|
||||||
|
},
|
||||||
|
onOpenManga = { navigator?.push(MangaScreen(it.id)) },
|
||||||
|
onMigrate = { showMigrateDialog(dialog.manga, it) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun RemoveMangaDialog(
|
||||||
|
dialog: Dialog.RemoveManga,
|
||||||
|
onDismiss: () -> Unit,
|
||||||
|
changeMangaFavorite: (Manga) -> Unit,
|
||||||
|
) {
|
||||||
|
RemoveMangaDialog(
|
||||||
|
onDismissRequest = onDismiss,
|
||||||
|
onConfirm = { changeMangaFavorite(dialog.manga) },
|
||||||
|
mangaToRemove = dialog.manga,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ChangeMangasCategoryDialog(
|
||||||
|
dialog: Dialog.ChangeMangasCategory,
|
||||||
|
navigator: Navigator?,
|
||||||
|
onDismiss: () -> Unit,
|
||||||
|
onConfirm: (List<Long>, List<Long>) -> Unit,
|
||||||
|
) {
|
||||||
|
ChangeCategoryDialog(
|
||||||
|
initialSelection = dialog.initialSelection,
|
||||||
|
onDismissRequest = onDismiss,
|
||||||
|
onEditCategories = { navigator?.push(CategoryScreen()) },
|
||||||
|
onConfirm = onConfirm,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows dialog to bulk allow/skip or migrate multiple manga to library when there are duplicates.
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
private fun BulkAllowDuplicateDialog(
|
||||||
|
dialog: Dialog.BulkAllowDuplicate,
|
||||||
|
navigator: Navigator?,
|
||||||
|
onDismiss: () -> Unit,
|
||||||
|
stopRunning: () -> Unit,
|
||||||
|
addFavorite: (startIdx: Int) -> Unit,
|
||||||
|
showMigrateDialog: (manga: Manga, duplicate: Manga) -> Unit,
|
||||||
|
addFavoriteDuplicate: (skipAllDuplicates: Boolean) -> Unit,
|
||||||
|
removeDuplicateSelectedManga: (index: Int) -> Unit,
|
||||||
|
) {
|
||||||
|
DuplicateMangaDialog(
|
||||||
|
duplicates = dialog.duplicates,
|
||||||
|
onDismissRequest = onDismiss,
|
||||||
|
onConfirm = { addFavorite(dialog.currentIdx + 1) },
|
||||||
|
onOpenManga = { navigator?.push(MangaScreen(it.id)) },
|
||||||
|
onMigrate = { showMigrateDialog(dialog.manga, it) },
|
||||||
|
bulkFavoriteManga = dialog.manga,
|
||||||
|
onAllowAllDuplicate = { addFavoriteDuplicate(false) },
|
||||||
|
onSkipAllDuplicate = { addFavoriteDuplicate(true) },
|
||||||
|
onSkipDuplicate = {
|
||||||
|
removeDuplicateSelectedManga(dialog.currentIdx)
|
||||||
|
addFavorite(dialog.currentIdx)
|
||||||
|
},
|
||||||
|
stopRunning = stopRunning,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
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,
|
||||||
|
)
|
||||||
|
|
@ -28,7 +28,6 @@ import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import eu.kanade.presentation.components.AppBarActions
|
import eu.kanade.presentation.components.AppBarActions
|
||||||
import eu.kanade.presentation.components.SearchToolbar
|
import eu.kanade.presentation.components.SearchToolbar
|
||||||
import eu.kanade.tachiyomi.ui.browse.bulkSelectionButton
|
|
||||||
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SourceFilter
|
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SourceFilter
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
|
|
|
||||||
|
|
@ -147,12 +147,7 @@ fun DuplicateMangaDialog(
|
||||||
DuplicateMangaListItem(
|
DuplicateMangaListItem(
|
||||||
manga = it,
|
manga = it,
|
||||||
getSource = { sourceManager.getOrStub(it.source) },
|
getSource = { sourceManager.getOrStub(it.source) },
|
||||||
onMigrate = {
|
onMigrate = { onMigrate(it) },
|
||||||
// KMK -->
|
|
||||||
if (bulkFavoriteManga == null) onDismissRequest()
|
|
||||||
// KMK <--
|
|
||||||
onMigrate(it)
|
|
||||||
},
|
|
||||||
onOpenManga = { onOpenManga(it) },
|
onOpenManga = { onOpenManga(it) },
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -184,7 +179,7 @@ fun DuplicateMangaDialog(
|
||||||
},
|
},
|
||||||
Modifier.align(Alignment.CenterHorizontally),
|
Modifier.align(Alignment.CenterHorizontally),
|
||||||
) {
|
) {
|
||||||
Text(text = stringResource(KMR.strings.action_allow_duplicate_manga))
|
Text(text = stringResource(MR.strings.action_add_anyway))
|
||||||
}
|
}
|
||||||
|
|
||||||
TextButton(
|
TextButton(
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,6 @@
|
||||||
package eu.kanade.tachiyomi.ui.browse
|
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.Immutable
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.ui.hapticfeedback.HapticFeedback
|
import androidx.compose.ui.hapticfeedback.HapticFeedback
|
||||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||||
import androidx.compose.ui.util.fastAny
|
import androidx.compose.ui.util.fastAny
|
||||||
|
|
@ -15,20 +9,11 @@ import androidx.compose.ui.util.fastForEach
|
||||||
import androidx.compose.ui.util.fastForEachIndexed
|
import androidx.compose.ui.util.fastForEachIndexed
|
||||||
import cafe.adriel.voyager.core.model.StateScreenModel
|
import cafe.adriel.voyager.core.model.StateScreenModel
|
||||||
import cafe.adriel.voyager.core.model.screenModelScope
|
import cafe.adriel.voyager.core.model.screenModelScope
|
||||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
|
||||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
|
||||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||||
import eu.kanade.domain.track.interactor.AddTracks
|
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.components.BulkSelectionToolbar
|
||||||
import eu.kanade.presentation.manga.DuplicateMangaDialog
|
import eu.kanade.presentation.manga.DuplicateMangaDialog
|
||||||
import eu.kanade.tachiyomi.data.cache.CoverCache
|
import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel.Dialog
|
|
||||||
import eu.kanade.tachiyomi.ui.browse.migration.advanced.design.PreMigrationScreen
|
|
||||||
import eu.kanade.tachiyomi.ui.category.CategoryScreen
|
|
||||||
import eu.kanade.tachiyomi.ui.manga.MangaScreen
|
|
||||||
import eu.kanade.tachiyomi.util.removeCovers
|
import eu.kanade.tachiyomi.util.removeCovers
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.PersistentList
|
import kotlinx.collections.immutable.PersistentList
|
||||||
|
|
@ -43,7 +28,6 @@ import tachiyomi.core.common.preference.CheckboxState
|
||||||
import tachiyomi.core.common.preference.mapAsCheckboxState
|
import tachiyomi.core.common.preference.mapAsCheckboxState
|
||||||
import tachiyomi.core.common.util.lang.launchIO
|
import tachiyomi.core.common.util.lang.launchIO
|
||||||
import tachiyomi.core.common.util.lang.launchNonCancellable
|
import tachiyomi.core.common.util.lang.launchNonCancellable
|
||||||
import tachiyomi.domain.UnsortedPreferences
|
|
||||||
import tachiyomi.domain.category.interactor.GetCategories
|
import tachiyomi.domain.category.interactor.GetCategories
|
||||||
import tachiyomi.domain.category.interactor.SetMangaCategories
|
import tachiyomi.domain.category.interactor.SetMangaCategories
|
||||||
import tachiyomi.domain.category.model.Category
|
import tachiyomi.domain.category.model.Category
|
||||||
|
|
@ -53,8 +37,6 @@ import tachiyomi.domain.manga.interactor.GetDuplicateLibraryManga
|
||||||
import tachiyomi.domain.manga.model.Manga
|
import tachiyomi.domain.manga.model.Manga
|
||||||
import tachiyomi.domain.manga.model.toMangaUpdate
|
import tachiyomi.domain.manga.model.toMangaUpdate
|
||||||
import tachiyomi.domain.source.service.SourceManager
|
import tachiyomi.domain.source.service.SourceManager
|
||||||
import tachiyomi.i18n.kmk.KMR
|
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
@ -76,11 +58,11 @@ class BulkFavoriteScreenModel(
|
||||||
toggleSelectionMode()
|
toggleSelectionMode()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleSelectionMode() {
|
fun toggleSelectionMode(newMode: Boolean? = null) {
|
||||||
if (state.value.selectionMode) {
|
if (state.value.selectionMode) {
|
||||||
clearSelection()
|
clearSelection()
|
||||||
}
|
}
|
||||||
mutableState.update { it.copy(selectionMode = !it.selectionMode) }
|
mutableState.update { it.copy(selectionMode = newMode ?: !it.selectionMode) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun clearSelection() {
|
private fun clearSelection() {
|
||||||
|
|
@ -97,10 +79,13 @@ class BulkFavoriteScreenModel(
|
||||||
fun toggleSelection(manga: Manga, toSelectedState: Boolean? = null) {
|
fun toggleSelection(manga: Manga, toSelectedState: Boolean? = null) {
|
||||||
mutableState.update { state ->
|
mutableState.update { state ->
|
||||||
val newSelection = state.selection.mutate { list ->
|
val newSelection = state.selection.mutate { list ->
|
||||||
if (toSelectedState != true && list.fastAny { it.id == manga.id }) {
|
val isSelected = list.fastAny { it.id == manga.id }
|
||||||
list.removeAll { it.id == manga.id }
|
val shouldSelect = toSelectedState ?: !isSelected
|
||||||
} else if (toSelectedState != false && list.none { it.id == manga.id }) {
|
// Both condition to avoid adding duplicate entries
|
||||||
|
if (shouldSelect && !isSelected) {
|
||||||
list.add(manga)
|
list.add(manga)
|
||||||
|
} else if (!shouldSelect && isSelected) {
|
||||||
|
list.removeAll { it.id == manga.id }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state.copy(
|
state.copy(
|
||||||
|
|
@ -151,8 +136,11 @@ class BulkFavoriteScreenModel(
|
||||||
/**
|
/**
|
||||||
* Add mangas to library if there is default category or no category exists.
|
* Add mangas to library if there is default category or no category exists.
|
||||||
* If not, it shows the categories list.
|
* If not, it shows the categories list.
|
||||||
|
*
|
||||||
|
* @param skipAllDuplicates if true, skip all duplicates and add all selected mangas to library.
|
||||||
|
* if false, allow all duplicates and add all selected mangas to library
|
||||||
*/
|
*/
|
||||||
fun addFavoriteDuplicate(skipAllDuplicates: Boolean = false) {
|
internal fun addFavoriteDuplicate(skipAllDuplicates: Boolean = false) {
|
||||||
screenModelScope.launch {
|
screenModelScope.launch {
|
||||||
val mangaList = if (skipAllDuplicates) getNotDuplicateLibraryMangas() else state.value.selection
|
val mangaList = if (skipAllDuplicates) getNotDuplicateLibraryMangas() else state.value.selection
|
||||||
if (mangaList.isEmpty()) {
|
if (mangaList.isEmpty()) {
|
||||||
|
|
@ -216,7 +204,7 @@ class BulkFavoriteScreenModel(
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeDuplicateSelectedManga(index: Int) {
|
internal fun removeDuplicateSelectedManga(index: Int) {
|
||||||
mutableState.update { state ->
|
mutableState.update { state ->
|
||||||
val newSelection = state.selection.mutate { list ->
|
val newSelection = state.selection.mutate { list ->
|
||||||
list.removeAt(index)
|
list.removeAt(index)
|
||||||
|
|
@ -232,7 +220,7 @@ class BulkFavoriteScreenModel(
|
||||||
* @param addCategories the categories to add for all mangas.
|
* @param addCategories the categories to add for all mangas.
|
||||||
* @param removeCategories the categories to remove in all mangas.
|
* @param removeCategories the categories to remove in all mangas.
|
||||||
*/
|
*/
|
||||||
fun setMangasCategories(mangaList: List<Manga>, addCategories: List<Long>, removeCategories: List<Long>) {
|
internal fun setMangasCategories(mangaList: List<Manga>, addCategories: List<Long>, removeCategories: List<Long>) {
|
||||||
screenModelScope.launchNonCancellable {
|
screenModelScope.launchNonCancellable {
|
||||||
startRunning()
|
startRunning()
|
||||||
mangaList.fastForEach { manga ->
|
mangaList.fastForEach { manga ->
|
||||||
|
|
@ -246,7 +234,7 @@ class BulkFavoriteScreenModel(
|
||||||
}
|
}
|
||||||
stopRunning()
|
stopRunning()
|
||||||
}
|
}
|
||||||
toggleSelectionMode()
|
toggleSelectionMode(newMode = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun moveMangaToCategoriesAndAddToLibrary(manga: Manga, categories: List<Long>) {
|
private fun moveMangaToCategoriesAndAddToLibrary(manga: Manga, categories: List<Long>) {
|
||||||
|
|
@ -293,7 +281,7 @@ class BulkFavoriteScreenModel(
|
||||||
*
|
*
|
||||||
* @return List of categories, not including the default category
|
* @return List of categories, not including the default category
|
||||||
*/
|
*/
|
||||||
suspend fun getCategories(): List<Category> {
|
private suspend fun getCategories(): List<Category> {
|
||||||
return getCategories.subscribe()
|
return getCategories.subscribe()
|
||||||
.firstOrNull()
|
.firstOrNull()
|
||||||
?.filterNot { it.isSystemCategory }
|
?.filterNot { it.isSystemCategory }
|
||||||
|
|
@ -304,7 +292,7 @@ class BulkFavoriteScreenModel(
|
||||||
moveMangaToCategories(manga, categories.filter { it.id != 0L }.map { it.id })
|
moveMangaToCategories(manga, categories.filter { it.id != 0L }.map { it.id })
|
||||||
}
|
}
|
||||||
|
|
||||||
fun moveMangaToCategories(manga: Manga, categoryIds: List<Long>) {
|
private fun moveMangaToCategories(manga: Manga, categoryIds: List<Long>) {
|
||||||
screenModelScope.launchIO {
|
screenModelScope.launchIO {
|
||||||
setMangaCategories.await(
|
setMangaCategories.await(
|
||||||
mangaId = manga.id,
|
mangaId = manga.id,
|
||||||
|
|
@ -318,7 +306,7 @@ class BulkFavoriteScreenModel(
|
||||||
*
|
*
|
||||||
* @param manga the manga to update.
|
* @param manga the manga to update.
|
||||||
*/
|
*/
|
||||||
fun changeMangaFavorite(manga: Manga) {
|
internal fun changeMangaFavorite(manga: Manga) {
|
||||||
val source = sourceManager.getOrStub(manga.source)
|
val source = sourceManager.getOrStub(manga.source)
|
||||||
|
|
||||||
screenModelScope.launch {
|
screenModelScope.launch {
|
||||||
|
|
@ -341,7 +329,7 @@ class BulkFavoriteScreenModel(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addFavorite(manga: Manga) {
|
internal fun addFavorite(manga: Manga) {
|
||||||
screenModelScope.launch {
|
screenModelScope.launch {
|
||||||
val categories = getCategories()
|
val categories = getCategories()
|
||||||
val defaultCategoryId = libraryPreferences.defaultCategory().get()
|
val defaultCategoryId = libraryPreferences.defaultCategory().get()
|
||||||
|
|
@ -364,8 +352,8 @@ class BulkFavoriteScreenModel(
|
||||||
else -> {
|
else -> {
|
||||||
val preselectedIds = getCategories.await(manga.id).map { it.id }
|
val preselectedIds = getCategories.await(manga.id).map { it.id }
|
||||||
setDialog(
|
setDialog(
|
||||||
Dialog.ChangeMangaCategory(
|
Dialog.ChangeMangasCategory(
|
||||||
manga,
|
listOf(manga),
|
||||||
categories.mapAsCheckboxState { it.id in preselectedIds }.toImmutableList(),
|
categories.mapAsCheckboxState { it.id in preselectedIds }.toImmutableList(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
@ -388,13 +376,17 @@ class BulkFavoriteScreenModel(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun showMigrateDialog(manga: Manga, duplicate: Manga) {
|
||||||
|
setDialog(Dialog.Migrate(newManga = manga, oldManga = duplicate))
|
||||||
|
}
|
||||||
|
|
||||||
private fun setDialog(dialog: Dialog?) {
|
private fun setDialog(dialog: Dialog?) {
|
||||||
mutableState.update {
|
mutableState.update {
|
||||||
it.copy(dialog = dialog)
|
it.copy(dialog = dialog)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun dismissDialog() {
|
internal fun dismissDialog() {
|
||||||
mutableState.update {
|
mutableState.update {
|
||||||
it.copy(dialog = null)
|
it.copy(dialog = null)
|
||||||
}
|
}
|
||||||
|
|
@ -406,20 +398,17 @@ class BulkFavoriteScreenModel(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun stopRunning() {
|
internal fun stopRunning() {
|
||||||
mutableState.update {
|
mutableState.update {
|
||||||
it.copy(isRunning = false)
|
it.copy(isRunning = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Dialog {
|
sealed interface Dialog {
|
||||||
|
data class Migrate(val newManga: Manga, val oldManga: Manga) : Dialog
|
||||||
data class AddDuplicateManga(val manga: Manga, val duplicates: List<Manga>) : Dialog
|
data class AddDuplicateManga(val manga: Manga, val duplicates: List<Manga>) : Dialog
|
||||||
data class BulkAllowDuplicate(val manga: Manga, val duplicates: List<Manga>, val currentIdx: Int) : Dialog
|
data class BulkAllowDuplicate(val manga: Manga, val duplicates: List<Manga>, val currentIdx: Int) : Dialog
|
||||||
data class RemoveManga(val manga: Manga) : Dialog
|
data class RemoveManga(val manga: Manga) : Dialog
|
||||||
data class ChangeMangaCategory(
|
|
||||||
val manga: Manga,
|
|
||||||
val initialSelection: ImmutableList<CheckboxState.State<Category>>,
|
|
||||||
) : Dialog
|
|
||||||
data class ChangeMangasCategory(
|
data class ChangeMangasCategory(
|
||||||
val mangas: List<Manga>,
|
val mangas: List<Manga>,
|
||||||
val initialSelection: ImmutableList<CheckboxState<Category>>,
|
val initialSelection: ImmutableList<CheckboxState<Category>>,
|
||||||
|
|
@ -434,158 +423,3 @@ class BulkFavoriteScreenModel(
|
||||||
val isRunning: Boolean = false,
|
val isRunning: Boolean = false,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Compose to shows the bulk favorite dialogs.
|
|
||||||
*
|
|
||||||
* @param bulkFavoriteScreenModel the screen model.
|
|
||||||
* @param dialog the dialog to show.
|
|
||||||
*/
|
|
||||||
@Composable
|
|
||||||
fun BulkFavoriteDialogs(
|
|
||||||
bulkFavoriteScreenModel: BulkFavoriteScreenModel,
|
|
||||||
dialog: Dialog?,
|
|
||||||
) {
|
|
||||||
when (dialog) {
|
|
||||||
/* Bulk-favorite actions */
|
|
||||||
is Dialog.ChangeMangasCategory ->
|
|
||||||
ChangeMangasCategoryDialog(bulkFavoriteScreenModel)
|
|
||||||
|
|
||||||
is Dialog.BulkAllowDuplicate ->
|
|
||||||
BulkAllowDuplicateDialog(bulkFavoriteScreenModel)
|
|
||||||
|
|
||||||
/* Single-favorite actions for screens originally don't have it */
|
|
||||||
is Dialog.AddDuplicateManga ->
|
|
||||||
AddDuplicateMangaDialog(bulkFavoriteScreenModel)
|
|
||||||
|
|
||||||
is Dialog.RemoveManga ->
|
|
||||||
RemoveMangaDialog(bulkFavoriteScreenModel)
|
|
||||||
|
|
||||||
is Dialog.ChangeMangaCategory ->
|
|
||||||
ChangeMangaCategoryDialog(bulkFavoriteScreenModel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows dialog to add a single manga to library when there are duplicates.
|
|
||||||
*
|
|
||||||
* @param bulkFavoriteScreenModel the screen model.
|
|
||||||
*/
|
|
||||||
@Composable
|
|
||||||
fun AddDuplicateMangaDialog(bulkFavoriteScreenModel: BulkFavoriteScreenModel) {
|
|
||||||
val navigator = LocalNavigator.currentOrThrow
|
|
||||||
val bulkFavoriteState by bulkFavoriteScreenModel.state.collectAsState()
|
|
||||||
val dialog = bulkFavoriteState.dialog as Dialog.AddDuplicateManga
|
|
||||||
|
|
||||||
bulkFavoriteScreenModel.stopRunning()
|
|
||||||
|
|
||||||
DuplicateMangaDialog(
|
|
||||||
duplicates = dialog.duplicates,
|
|
||||||
onDismissRequest = bulkFavoriteScreenModel::dismissDialog,
|
|
||||||
onConfirm = {
|
|
||||||
if (bulkFavoriteState.selectionMode) {
|
|
||||||
bulkFavoriteScreenModel.toggleSelectionMode()
|
|
||||||
}
|
|
||||||
bulkFavoriteScreenModel.addFavorite(dialog.manga)
|
|
||||||
},
|
|
||||||
onOpenManga = { navigator.push(MangaScreen(it.id)) },
|
|
||||||
onMigrate = {
|
|
||||||
PreMigrationScreen.navigateToMigration(
|
|
||||||
Injekt.get<UnsortedPreferences>().skipPreMigration().get(),
|
|
||||||
navigator,
|
|
||||||
it.id,
|
|
||||||
dialog.manga.id,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun RemoveMangaDialog(bulkFavoriteScreenModel: BulkFavoriteScreenModel) {
|
|
||||||
val bulkFavoriteState by bulkFavoriteScreenModel.state.collectAsState()
|
|
||||||
val dialog = bulkFavoriteState.dialog as Dialog.RemoveManga
|
|
||||||
|
|
||||||
RemoveMangaDialog(
|
|
||||||
onDismissRequest = bulkFavoriteScreenModel::dismissDialog,
|
|
||||||
onConfirm = {
|
|
||||||
bulkFavoriteScreenModel.changeMangaFavorite(dialog.manga)
|
|
||||||
},
|
|
||||||
mangaToRemove = dialog.manga,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun ChangeMangaCategoryDialog(bulkFavoriteScreenModel: BulkFavoriteScreenModel) {
|
|
||||||
val navigator = LocalNavigator.currentOrThrow
|
|
||||||
val bulkFavoriteState by bulkFavoriteScreenModel.state.collectAsState()
|
|
||||||
val dialog = bulkFavoriteState.dialog as Dialog.ChangeMangaCategory
|
|
||||||
|
|
||||||
ChangeCategoryDialog(
|
|
||||||
initialSelection = dialog.initialSelection,
|
|
||||||
onDismissRequest = bulkFavoriteScreenModel::dismissDialog,
|
|
||||||
onEditCategories = { navigator.push(CategoryScreen()) },
|
|
||||||
onConfirm = { include, _ ->
|
|
||||||
bulkFavoriteScreenModel.changeMangaFavorite(dialog.manga)
|
|
||||||
bulkFavoriteScreenModel.moveMangaToCategories(dialog.manga, include)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun ChangeMangasCategoryDialog(bulkFavoriteScreenModel: BulkFavoriteScreenModel) {
|
|
||||||
val navigator = LocalNavigator.currentOrThrow
|
|
||||||
val bulkFavoriteState by bulkFavoriteScreenModel.state.collectAsState()
|
|
||||||
val dialog = bulkFavoriteState.dialog as Dialog.ChangeMangasCategory
|
|
||||||
|
|
||||||
ChangeCategoryDialog(
|
|
||||||
initialSelection = dialog.initialSelection,
|
|
||||||
onDismissRequest = bulkFavoriteScreenModel::dismissDialog,
|
|
||||||
onEditCategories = { navigator.push(CategoryScreen()) },
|
|
||||||
onConfirm = { include, exclude ->
|
|
||||||
bulkFavoriteScreenModel.setMangasCategories(dialog.mangas, include, exclude)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows dialog to bulk allow/skip or migrate multiple manga to library when there are duplicates.
|
|
||||||
*
|
|
||||||
* @param bulkFavoriteScreenModel the screen model.
|
|
||||||
*/
|
|
||||||
@Composable
|
|
||||||
fun BulkAllowDuplicateDialog(bulkFavoriteScreenModel: BulkFavoriteScreenModel) {
|
|
||||||
val navigator = LocalNavigator.currentOrThrow
|
|
||||||
val bulkFavoriteState by bulkFavoriteScreenModel.state.collectAsState()
|
|
||||||
val dialog = bulkFavoriteState.dialog as Dialog.BulkAllowDuplicate
|
|
||||||
|
|
||||||
DuplicateMangaDialog(
|
|
||||||
duplicates = dialog.duplicates,
|
|
||||||
onDismissRequest = bulkFavoriteScreenModel::dismissDialog,
|
|
||||||
onConfirm = {
|
|
||||||
bulkFavoriteScreenModel.addFavorite(startIdx = dialog.currentIdx + 1)
|
|
||||||
},
|
|
||||||
onOpenManga = { navigator.push(MangaScreen(it.id)) },
|
|
||||||
onMigrate = { navigator.push(MangaScreen(it.id)) },
|
|
||||||
bulkFavoriteManga = dialog.manga,
|
|
||||||
onAllowAllDuplicate = bulkFavoriteScreenModel::addFavoriteDuplicate,
|
|
||||||
onSkipAllDuplicate = {
|
|
||||||
bulkFavoriteScreenModel.addFavoriteDuplicate(skipAllDuplicates = true)
|
|
||||||
},
|
|
||||||
onSkipDuplicate = {
|
|
||||||
bulkFavoriteScreenModel.removeDuplicateSelectedManga(index = dialog.currentIdx)
|
|
||||||
bulkFavoriteScreenModel.addFavorite(startIdx = dialog.currentIdx)
|
|
||||||
},
|
|
||||||
stopRunning = bulkFavoriteScreenModel::stopRunning,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
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,
|
|
||||||
)
|
|
||||||
|
|
|
||||||
|
|
@ -22,13 +22,13 @@ import eu.kanade.presentation.browse.FeedAddDialog
|
||||||
import eu.kanade.presentation.browse.FeedAddSearchDialog
|
import eu.kanade.presentation.browse.FeedAddSearchDialog
|
||||||
import eu.kanade.presentation.browse.FeedOrderScreen
|
import eu.kanade.presentation.browse.FeedOrderScreen
|
||||||
import eu.kanade.presentation.browse.FeedScreen
|
import eu.kanade.presentation.browse.FeedScreen
|
||||||
|
import eu.kanade.presentation.browse.components.BulkFavoriteDialogs
|
||||||
import eu.kanade.presentation.browse.components.FeedActionsDialog
|
import eu.kanade.presentation.browse.components.FeedActionsDialog
|
||||||
import eu.kanade.presentation.browse.components.SourceFeedDeleteDialog
|
import eu.kanade.presentation.browse.components.SourceFeedDeleteDialog
|
||||||
|
import eu.kanade.presentation.browse.components.bulkSelectionButton
|
||||||
import eu.kanade.presentation.components.AppBar
|
import eu.kanade.presentation.components.AppBar
|
||||||
import eu.kanade.presentation.components.TabContent
|
import eu.kanade.presentation.components.TabContent
|
||||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteDialogs
|
|
||||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
||||||
import eu.kanade.tachiyomi.ui.browse.bulkSelectionButton
|
|
||||||
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreen
|
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreen
|
||||||
import eu.kanade.tachiyomi.ui.home.HomeScreen
|
import eu.kanade.tachiyomi.ui.home.HomeScreen
|
||||||
import eu.kanade.tachiyomi.ui.manga.MangaScreen
|
import eu.kanade.tachiyomi.ui.manga.MangaScreen
|
||||||
|
|
|
||||||
|
|
@ -102,10 +102,7 @@ internal fun MigrateDialog(
|
||||||
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.extraSmall),
|
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.extraSmall),
|
||||||
) {
|
) {
|
||||||
TextButton(
|
TextButton(
|
||||||
onClick = {
|
onClick = { onClickTitle() },
|
||||||
onDismissRequest()
|
|
||||||
onClickTitle()
|
|
||||||
},
|
|
||||||
) {
|
) {
|
||||||
Text(text = stringResource(MR.strings.action_show_manga))
|
Text(text = stringResource(MR.strings.action_show_manga))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,15 @@ 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.presentation.browse.MigrateSearchScreen
|
import eu.kanade.presentation.browse.MigrateSearchScreen
|
||||||
|
import eu.kanade.presentation.browse.components.BulkFavoriteDialogs
|
||||||
import eu.kanade.presentation.util.Screen
|
import eu.kanade.presentation.util.Screen
|
||||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteDialogs
|
|
||||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
||||||
import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigrationListScreen
|
import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigrationListScreen
|
||||||
import eu.kanade.tachiyomi.ui.manga.MangaScreen
|
import eu.kanade.tachiyomi.ui.manga.MangaScreen
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manual search [validSources] for manga to migrate to.
|
||||||
|
*/
|
||||||
class MigrateSearchScreen(private val mangaId: Long, private val validSources: List<Long>) : Screen() {
|
class MigrateSearchScreen(private val mangaId: Long, private val validSources: List<Long>) : Screen() {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -73,6 +76,7 @@ class MigrateSearchScreen(private val mangaId: Long, private val validSources: L
|
||||||
)
|
)
|
||||||
|
|
||||||
// KMK -->
|
// KMK -->
|
||||||
|
// Bulk-favorite actions only
|
||||||
BulkFavoriteDialogs(
|
BulkFavoriteDialogs(
|
||||||
bulkFavoriteScreenModel = bulkFavoriteScreenModel,
|
bulkFavoriteScreenModel = bulkFavoriteScreenModel,
|
||||||
dialog = bulkFavoriteState.dialog,
|
dialog = bulkFavoriteState.dialog,
|
||||||
|
|
|
||||||
|
|
@ -16,14 +16,14 @@ 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.BrowseSourceContent
|
||||||
import eu.kanade.presentation.browse.components.BrowseSourceFloatingActionButton
|
import eu.kanade.presentation.browse.components.BrowseSourceFloatingActionButton
|
||||||
|
import eu.kanade.presentation.browse.components.BulkFavoriteDialogs
|
||||||
|
import eu.kanade.presentation.browse.components.bulkSelectionButton
|
||||||
import eu.kanade.presentation.components.AppBarActions
|
import eu.kanade.presentation.components.AppBarActions
|
||||||
import eu.kanade.presentation.components.BulkSelectionToolbar
|
import eu.kanade.presentation.components.BulkSelectionToolbar
|
||||||
import eu.kanade.presentation.components.SearchToolbar
|
import eu.kanade.presentation.components.SearchToolbar
|
||||||
import eu.kanade.presentation.util.Screen
|
import eu.kanade.presentation.util.Screen
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteDialogs
|
|
||||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
||||||
import eu.kanade.tachiyomi.ui.browse.bulkSelectionButton
|
|
||||||
import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigrationListScreen
|
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.BrowseSourceScreenModel
|
||||||
import eu.kanade.tachiyomi.ui.browse.source.browse.SourceFilterDialog
|
import eu.kanade.tachiyomi.ui.browse.source.browse.SourceFilterDialog
|
||||||
|
|
@ -41,7 +41,7 @@ import tachiyomi.presentation.core.screens.LoadingScreen
|
||||||
import tachiyomi.source.local.LocalSource
|
import tachiyomi.source.local.LocalSource
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opened when click on a source in [MigrateSearchScreen]
|
* Opened when click on a source in [MigrateSearchScreen] while doing manual search for migration
|
||||||
*/
|
*/
|
||||||
data class SourceSearchScreen(
|
data class SourceSearchScreen(
|
||||||
private val oldManga: Manga,
|
private val oldManga: Manga,
|
||||||
|
|
@ -212,6 +212,7 @@ data class SourceSearchScreen(
|
||||||
}
|
}
|
||||||
|
|
||||||
// KMK -->
|
// KMK -->
|
||||||
|
// Bulk-favorite actions only
|
||||||
BulkFavoriteDialogs(
|
BulkFavoriteDialogs(
|
||||||
bulkFavoriteScreenModel = bulkFavoriteScreenModel,
|
bulkFavoriteScreenModel = bulkFavoriteScreenModel,
|
||||||
dialog = bulkFavoriteState.dialog,
|
dialog = bulkFavoriteState.dialog,
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ import eu.kanade.core.util.ifSourcesLoaded
|
||||||
import eu.kanade.presentation.browse.BrowseSourceContent
|
import eu.kanade.presentation.browse.BrowseSourceContent
|
||||||
import eu.kanade.presentation.browse.MissingSourceScreen
|
import eu.kanade.presentation.browse.MissingSourceScreen
|
||||||
import eu.kanade.presentation.browse.components.BrowseSourceToolbar
|
import eu.kanade.presentation.browse.components.BrowseSourceToolbar
|
||||||
|
import eu.kanade.presentation.browse.components.BulkFavoriteDialogs
|
||||||
import eu.kanade.presentation.browse.components.RemoveMangaDialog
|
import eu.kanade.presentation.browse.components.RemoveMangaDialog
|
||||||
import eu.kanade.presentation.browse.components.SavedSearchCreateDialog
|
import eu.kanade.presentation.browse.components.SavedSearchCreateDialog
|
||||||
import eu.kanade.presentation.browse.components.SavedSearchDeleteDialog
|
import eu.kanade.presentation.browse.components.SavedSearchDeleteDialog
|
||||||
|
|
@ -52,7 +53,6 @@ import eu.kanade.presentation.util.Screen
|
||||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteDialogs
|
|
||||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
||||||
import eu.kanade.tachiyomi.ui.browse.extension.details.SourcePreferencesScreen
|
import eu.kanade.tachiyomi.ui.browse.extension.details.SourcePreferencesScreen
|
||||||
import eu.kanade.tachiyomi.ui.browse.migration.search.MigrateDialog
|
import eu.kanade.tachiyomi.ui.browse.migration.search.MigrateDialog
|
||||||
|
|
@ -463,9 +463,7 @@ data class BrowseSourceScreen(
|
||||||
screenModel = MigrateDialogScreenModel(),
|
screenModel = MigrateDialogScreenModel(),
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
onClickTitle = { navigator.push(MangaScreen(dialog.oldManga.id)) },
|
onClickTitle = { navigator.push(MangaScreen(dialog.oldManga.id)) },
|
||||||
onPopScreen = {
|
onPopScreen = { onDismissRequest() },
|
||||||
onDismissRequest()
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is BrowseSourceScreenModel.Dialog.RemoveManga -> {
|
is BrowseSourceScreenModel.Dialog.RemoveManga -> {
|
||||||
|
|
@ -504,6 +502,7 @@ data class BrowseSourceScreen(
|
||||||
}
|
}
|
||||||
|
|
||||||
// KMK -->
|
// KMK -->
|
||||||
|
// Bulk-favorite actions only
|
||||||
BulkFavoriteDialogs(
|
BulkFavoriteDialogs(
|
||||||
bulkFavoriteScreenModel = bulkFavoriteScreenModel,
|
bulkFavoriteScreenModel = bulkFavoriteScreenModel,
|
||||||
dialog = bulkFavoriteState.dialog,
|
dialog = bulkFavoriteState.dialog,
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import eu.kanade.presentation.browse.MissingSourceScreen
|
||||||
import eu.kanade.presentation.browse.SourceFeedOrderScreen
|
import eu.kanade.presentation.browse.SourceFeedOrderScreen
|
||||||
import eu.kanade.presentation.browse.SourceFeedScreen
|
import eu.kanade.presentation.browse.SourceFeedScreen
|
||||||
import eu.kanade.presentation.browse.SourceFeedUI
|
import eu.kanade.presentation.browse.SourceFeedUI
|
||||||
|
import eu.kanade.presentation.browse.components.BulkFavoriteDialogs
|
||||||
import eu.kanade.presentation.browse.components.FeedActionsDialog
|
import eu.kanade.presentation.browse.components.FeedActionsDialog
|
||||||
import eu.kanade.presentation.browse.components.SourceFeedAddDialog
|
import eu.kanade.presentation.browse.components.SourceFeedAddDialog
|
||||||
import eu.kanade.presentation.browse.components.SourceFeedDeleteDialog
|
import eu.kanade.presentation.browse.components.SourceFeedDeleteDialog
|
||||||
|
|
@ -27,7 +28,6 @@ import eu.kanade.presentation.util.Screen
|
||||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteDialogs
|
|
||||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
||||||
import eu.kanade.tachiyomi.ui.browse.extension.details.SourcePreferencesScreen
|
import eu.kanade.tachiyomi.ui.browse.extension.details.SourcePreferencesScreen
|
||||||
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreen
|
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreen
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@ 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.GlobalSearchScreen
|
import eu.kanade.presentation.browse.GlobalSearchScreen
|
||||||
|
import eu.kanade.presentation.browse.components.BulkFavoriteDialogs
|
||||||
import eu.kanade.presentation.util.Screen
|
import eu.kanade.presentation.util.Screen
|
||||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteDialogs
|
|
||||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
||||||
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreen
|
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreen
|
||||||
import eu.kanade.tachiyomi.ui.manga.MangaScreen
|
import eu.kanade.tachiyomi.ui.manga.MangaScreen
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,7 @@ data object HistoryTab : Tab {
|
||||||
screenModel = MigrateDialogScreenModel(),
|
screenModel = MigrateDialogScreenModel(),
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
onClickTitle = { navigator.push(MangaScreen(dialog.oldManga.id)) },
|
onClickTitle = { navigator.push(MangaScreen(dialog.oldManga.id)) },
|
||||||
onPopScreen = { navigator.replace(MangaScreen(dialog.newManga.id)) },
|
onPopScreen = { onDismissRequest() },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
null -> {}
|
null -> {}
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ import dev.chrisbanes.haze.hazeEffect
|
||||||
import eu.kanade.core.util.ifSourcesLoaded
|
import eu.kanade.core.util.ifSourcesLoaded
|
||||||
import eu.kanade.domain.manga.model.hasCustomCover
|
import eu.kanade.domain.manga.model.hasCustomCover
|
||||||
import eu.kanade.domain.manga.model.toSManga
|
import eu.kanade.domain.manga.model.toSManga
|
||||||
|
import eu.kanade.presentation.browse.components.BulkFavoriteDialogs
|
||||||
import eu.kanade.presentation.category.components.ChangeCategoryDialog
|
import eu.kanade.presentation.category.components.ChangeCategoryDialog
|
||||||
import eu.kanade.presentation.components.NavigatorAdaptiveSheet
|
import eu.kanade.presentation.components.NavigatorAdaptiveSheet
|
||||||
import eu.kanade.presentation.manga.ChapterSettingsDialog
|
import eu.kanade.presentation.manga.ChapterSettingsDialog
|
||||||
|
|
@ -63,7 +64,6 @@ import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import eu.kanade.tachiyomi.source.isLocalOrStub
|
import eu.kanade.tachiyomi.source.isLocalOrStub
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteDialogs
|
|
||||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
||||||
import eu.kanade.tachiyomi.ui.browse.extension.ExtensionsScreen
|
import eu.kanade.tachiyomi.ui.browse.extension.ExtensionsScreen
|
||||||
import eu.kanade.tachiyomi.ui.browse.extension.details.SourcePreferencesScreen
|
import eu.kanade.tachiyomi.ui.browse.extension.details.SourcePreferencesScreen
|
||||||
|
|
@ -470,7 +470,7 @@ class MangaScreen(
|
||||||
screenModel = MigrateDialogScreenModel(),
|
screenModel = MigrateDialogScreenModel(),
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
onClickTitle = { navigator.push(MangaScreen(dialog.oldManga.id)) },
|
onClickTitle = { navigator.push(MangaScreen(dialog.oldManga.id)) },
|
||||||
onPopScreen = { navigator.replace(MangaScreen(dialog.newManga.id)) },
|
onPopScreen = { onDismissRequest() },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
MangaScreenModel.Dialog.SettingsSheet -> ChapterSettingsDialog(
|
MangaScreenModel.Dialog.SettingsSheet -> ChapterSettingsDialog(
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,12 @@ 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.BrowseSourceContent
|
||||||
import eu.kanade.presentation.browse.components.BrowseSourceSimpleToolbar
|
import eu.kanade.presentation.browse.components.BrowseSourceSimpleToolbar
|
||||||
|
import eu.kanade.presentation.browse.components.BulkFavoriteDialogs
|
||||||
import eu.kanade.presentation.browse.components.RemoveMangaDialog
|
import eu.kanade.presentation.browse.components.RemoveMangaDialog
|
||||||
import eu.kanade.presentation.category.components.ChangeCategoryDialog
|
import eu.kanade.presentation.category.components.ChangeCategoryDialog
|
||||||
import eu.kanade.presentation.components.BulkSelectionToolbar
|
import eu.kanade.presentation.components.BulkSelectionToolbar
|
||||||
import eu.kanade.presentation.manga.DuplicateMangaDialog
|
import eu.kanade.presentation.manga.DuplicateMangaDialog
|
||||||
import eu.kanade.presentation.util.Screen
|
import eu.kanade.presentation.util.Screen
|
||||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteDialogs
|
|
||||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
||||||
import eu.kanade.tachiyomi.ui.browse.migration.search.MigrateDialog
|
import eu.kanade.tachiyomi.ui.browse.migration.search.MigrateDialog
|
||||||
import eu.kanade.tachiyomi.ui.browse.migration.search.MigrateDialogScreenModel
|
import eu.kanade.tachiyomi.ui.browse.migration.search.MigrateDialogScreenModel
|
||||||
|
|
@ -175,9 +175,7 @@ class MangaDexFollowsScreen(private val sourceId: Long) : Screen() {
|
||||||
screenModel = MigrateDialogScreenModel(),
|
screenModel = MigrateDialogScreenModel(),
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
onClickTitle = { navigator.push(MangaScreen(dialog.oldManga.id)) },
|
onClickTitle = { navigator.push(MangaScreen(dialog.oldManga.id)) },
|
||||||
onPopScreen = {
|
onPopScreen = { onDismissRequest() },
|
||||||
onDismissRequest()
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// KMK <--
|
// KMK <--
|
||||||
|
|
@ -207,6 +205,7 @@ class MangaDexFollowsScreen(private val sourceId: Long) : Screen() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// KMK -->
|
// KMK -->
|
||||||
|
// Bulk-favorite actions only
|
||||||
BulkFavoriteDialogs(
|
BulkFavoriteDialogs(
|
||||||
bulkFavoriteScreenModel = bulkFavoriteScreenModel,
|
bulkFavoriteScreenModel = bulkFavoriteScreenModel,
|
||||||
dialog = bulkFavoriteState.dialog,
|
dialog = bulkFavoriteState.dialog,
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,9 @@ 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.BrowseSourceContent
|
||||||
import eu.kanade.presentation.browse.components.BrowseSourceSimpleToolbar
|
import eu.kanade.presentation.browse.components.BrowseSourceSimpleToolbar
|
||||||
|
import eu.kanade.presentation.browse.components.BulkFavoriteDialogs
|
||||||
import eu.kanade.presentation.components.BulkSelectionToolbar
|
import eu.kanade.presentation.components.BulkSelectionToolbar
|
||||||
import eu.kanade.presentation.util.Screen
|
import eu.kanade.presentation.util.Screen
|
||||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteDialogs
|
|
||||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ 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.components.BulkFavoriteDialogs
|
||||||
import eu.kanade.presentation.util.Screen
|
import eu.kanade.presentation.util.Screen
|
||||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteDialogs
|
|
||||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
||||||
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
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue