allow edit migration options while already being searching (#616)

This commit is contained in:
Cuong-Tran 2024-12-31 11:46:16 +07:00 committed by GitHub
parent 468529cd47
commit a6f3a2cdcf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 86 additions and 11 deletions

View file

@ -14,6 +14,7 @@ import androidx.compose.material.icons.outlined.ContentCopy
import androidx.compose.material.icons.outlined.CopyAll import androidx.compose.material.icons.outlined.CopyAll
import androidx.compose.material.icons.outlined.Done import androidx.compose.material.icons.outlined.Done
import androidx.compose.material.icons.outlined.DoneAll import androidx.compose.material.icons.outlined.DoneAll
import androidx.compose.material.icons.outlined.Settings
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
@ -54,6 +55,7 @@ fun MigrationListScreen(
// KMK --> // KMK -->
cancelManga: (Long) -> Unit, cancelManga: (Long) -> Unit,
navigateUp: () -> Unit, navigateUp: () -> Unit,
openMigrationOptionsDialog: () -> Unit,
// KMK <-- // KMK <--
searchManually: (MigratingManga) -> Unit, searchManually: (MigratingManga) -> Unit,
migrateNow: (Long) -> Unit, migrateNow: (Long) -> Unit,
@ -75,6 +77,13 @@ fun MigrationListScreen(
actions = { actions = {
AppBarActions( AppBarActions(
persistentListOf( persistentListOf(
// KMK -->
AppBar.Action(
title = stringResource(MR.strings.action_settings),
icon = Icons.Outlined.Settings,
onClick = openMigrationOptionsDialog,
),
// KMK <--
AppBar.Action( AppBar.Action(
title = stringResource(MR.strings.copy), title = stringResource(MR.strings.copy),
icon = if (items.size == 1) Icons.Outlined.ContentCopy else Icons.Outlined.CopyAll, icon = if (items.size == 1) Icons.Outlined.ContentCopy else Icons.Outlined.CopyAll,

View file

@ -22,9 +22,11 @@ import eu.kanade.presentation.components.AdaptiveSheet
import eu.kanade.tachiyomi.databinding.MigrationBottomSheetBinding import eu.kanade.tachiyomi.databinding.MigrationBottomSheetBinding
import eu.kanade.tachiyomi.ui.browse.migration.MigrationFlags import eu.kanade.tachiyomi.ui.browse.migration.MigrationFlags
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.common.preference.Preference import tachiyomi.core.common.preference.Preference
import tachiyomi.core.common.util.lang.toLong import tachiyomi.core.common.util.lang.toLong
import tachiyomi.domain.UnsortedPreferences import tachiyomi.domain.UnsortedPreferences
import tachiyomi.i18n.MR
import tachiyomi.i18n.sy.SYMR import tachiyomi.i18n.sy.SYMR
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
@ -32,10 +34,18 @@ import uy.kohesive.injekt.injectLazy
fun MigrationBottomSheetDialog( fun MigrationBottomSheetDialog(
onDismissRequest: () -> Unit, onDismissRequest: () -> Unit,
onStartMigration: (extraParam: String?) -> Unit, onStartMigration: (extraParam: String?) -> Unit,
// KMK -->
fullSettings: Boolean = true,
// KMK <--
) { ) {
val startMigration = rememberUpdatedState(onStartMigration) val startMigration = rememberUpdatedState(onStartMigration)
val state = remember { val state = remember {
MigrationBottomSheetDialogState(startMigration) MigrationBottomSheetDialogState(
startMigration,
// KMK -->
fullSettings,
// KMK <--
)
} }
// KMK --> // KMK -->
@ -132,7 +142,12 @@ fun MigrationBottomSheetDialog(
} }
} }
class MigrationBottomSheetDialogState(private val onStartMigration: State<(extraParam: String?) -> Unit>) { class MigrationBottomSheetDialogState(
private val onStartMigration: State<(extraParam: String?) -> Unit>,
// KMK -->
private val fullSettings: Boolean = true,
// KMK <--
) {
private val preferences: UnsortedPreferences by injectLazy() private val preferences: UnsortedPreferences by injectLazy()
/** /**
@ -186,6 +201,17 @@ class MigrationBottomSheetDialogState(private val onStartMigration: State<(extra
}, },
) )
} }
// KMK -->
if (!fullSettings) {
binding.useSmartSearch.isVisible = false
binding.extraSearchParam.isVisible = false
binding.extraSearchParamText.isVisible = false
binding.sourceGroup.isVisible = false
binding.skipStep.isVisible = false
binding.migrateBtn.text = binding.root.context.stringResource(MR.strings.action_save)
}
// KMK <--
} }
private fun setFlags(binding: MigrationBottomSheetBinding) { private fun setFlags(binding: MigrationBottomSheetBinding) {

View file

@ -99,6 +99,9 @@ sealed class MigrationType : Serializable {
data class MangaSingle(val fromMangaId: Long, val toManga: Long?) : MigrationType() data class MangaSingle(val fromMangaId: Long, val toManga: Long?) : MigrationType()
} }
/**
* The screen showing a list of selectable sources used for migration, with migration setting dialog.
*/
class PreMigrationScreen(val migration: MigrationType) : Screen() { class PreMigrationScreen(val migration: MigrationType) : Screen() {
@Composable @Composable
override fun Content() { override fun Content() {

View file

@ -14,6 +14,7 @@ import eu.kanade.presentation.browse.components.MigrationExitDialog
import eu.kanade.presentation.browse.components.MigrationMangaDialog import eu.kanade.presentation.browse.components.MigrationMangaDialog
import eu.kanade.presentation.browse.components.MigrationProgressDialog import eu.kanade.presentation.browse.components.MigrationProgressDialog
import eu.kanade.presentation.util.Screen import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.ui.browse.migration.advanced.design.MigrationBottomSheetDialog
import eu.kanade.tachiyomi.ui.browse.migration.advanced.design.PreMigrationScreen import eu.kanade.tachiyomi.ui.browse.migration.advanced.design.PreMigrationScreen
import eu.kanade.tachiyomi.ui.browse.migration.search.MigrateSearchScreen import eu.kanade.tachiyomi.ui.browse.migration.search.MigrateSearchScreen
import eu.kanade.tachiyomi.ui.manga.MangaScreen import eu.kanade.tachiyomi.ui.manga.MangaScreen
@ -25,6 +26,9 @@ import tachiyomi.core.common.i18n.pluralStringResource
import tachiyomi.core.common.util.lang.withUIContext import tachiyomi.core.common.util.lang.withUIContext
import tachiyomi.i18n.sy.SYMR import tachiyomi.i18n.sy.SYMR
/**
* Screen showing a list of pair of source-dest manga entries being migrated.
*/
class MigrationListScreen(private val config: MigrationProcedureConfig) : Screen() { class MigrationListScreen(private val config: MigrationProcedureConfig) : Screen() {
var newSelectedItem: Pair<Long, Long>? = null var newSelectedItem: Pair<Long, Long>? = null
@ -106,6 +110,7 @@ class MigrationListScreen(private val config: MigrationProcedureConfig) : Screen
// KMK --> // KMK -->
cancelManga = { screenModel.cancelManga(it) }, cancelManga = { screenModel.cancelManga(it) },
navigateUp = { navigator.pop() }, navigateUp = { navigator.pop() },
openMigrationOptionsDialog = screenModel::openMigrationOptionsDialog,
// KMK <-- // KMK <--
searchManually = { migrationItem -> searchManually = { migrationItem ->
val sources = screenModel.getMigrationSources() val sources = screenModel.getMigrationSources()
@ -143,6 +148,18 @@ class MigrationListScreen(private val config: MigrationProcedureConfig) : Screen
exitMigration = navigator::pop, exitMigration = navigator::pop,
) )
} }
// KMK -->
MigrationListScreenModel.Dialog.MigrationOptionsDialog -> {
MigrationBottomSheetDialog(
onDismissRequest = onDismissRequest,
onStartMigration = { _ ->
onDismissRequest()
screenModel.updateOptions()
},
fullSettings = false,
)
}
// KMK <--
null -> Unit null -> Unit
} }

View file

@ -58,6 +58,7 @@ import tachiyomi.domain.track.interactor.DeleteTrack
import tachiyomi.domain.track.interactor.GetTracks import tachiyomi.domain.track.interactor.GetTracks
import tachiyomi.domain.track.interactor.InsertTrack import tachiyomi.domain.track.interactor.InsertTrack
import tachiyomi.i18n.sy.SYMR import tachiyomi.i18n.sy.SYMR
import timber.log.Timber
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicInteger
@ -93,8 +94,10 @@ class MigrationListScreenModel(
val manualMigrations = MutableStateFlow(0) val manualMigrations = MutableStateFlow(0)
val hideNotFound = preferences.hideNotFoundMigration().get() var hideNotFound = preferences.hideNotFoundMigration().get()
val showOnlyUpdates = preferences.showOnlyUpdatesMigration().get() private var showOnlyUpdates = preferences.showOnlyUpdatesMigration().get()
private var useSourceWithMost = preferences.useSourceWithMost().get()
private var useSmartSearch = preferences.smartMigration().get()
val navigateOut = MutableSharedFlow<Unit>() val navigateOut = MutableSharedFlow<Unit>()
@ -144,7 +147,7 @@ class MigrationListScreenModel(
suspend fun getManga(result: SearchResult.Result) = getManga(result.id) suspend fun getManga(result: SearchResult.Result) = getManga(result.id)
suspend fun getManga(id: Long) = getManga.await(id) suspend fun getManga(id: Long) = getManga.await(id)
suspend fun getChapterInfo(result: SearchResult.Result) = getChapterInfo(result.id) suspend fun getChapterInfo(result: SearchResult.Result) = getChapterInfo(result.id)
suspend fun getChapterInfo(id: Long) = getChaptersByMangaId.await(id).let { chapters -> private suspend fun getChapterInfo(id: Long) = getChaptersByMangaId.await(id).let { chapters ->
MigratingManga.ChapterInfo( MigratingManga.ChapterInfo(
latestChapter = chapters.maxOfOrNull { it.chapterNumber }, latestChapter = chapters.maxOfOrNull { it.chapterNumber },
chapterCount = chapters.size, chapterCount = chapters.size,
@ -160,8 +163,6 @@ class MigrationListScreenModel(
private suspend fun runMigrations(mangas: List<MigratingManga>) { private suspend fun runMigrations(mangas: List<MigratingManga>) {
throttleManager.resetThrottle() throttleManager.resetThrottle()
// KMK: finishedCount.value = mangas.size // KMK: finishedCount.value = mangas.size
val useSourceWithMost = preferences.useSourceWithMost().get()
val useSmartSearch = preferences.smartMigration().get()
val sources = getMigrationSources() val sources = getMigrationSources()
for (manga in mangas) { for (manga in mangas) {
@ -311,6 +312,7 @@ class MigrationListScreenModel(
// Ignore cancellations // Ignore cancellations
throw e throw e
} catch (e: Exception) { } catch (e: Exception) {
Timber.tag("MigrationListScreenModel").e(e, "Error updating manga from source")
} }
} }
@ -346,10 +348,10 @@ class MigrationListScreenModel(
} }
} }
fun allMangasDone() = migratingItems.value.orEmpty().all { it.searchResult.value != SearchResult.Searching } && private fun allMangasDone() = migratingItems.value.orEmpty().all { it.searchResult.value != SearchResult.Searching } &&
migratingItems.value.orEmpty().any { it.searchResult.value is SearchResult.Result } migratingItems.value.orEmpty().any { it.searchResult.value is SearchResult.Result }
fun mangasSkipped() = migratingItems.value.orEmpty().count { it.searchResult.value == SearchResult.NotFound } private fun mangasSkipped() = migratingItems.value.orEmpty().count { it.searchResult.value == SearchResult.NotFound }
private suspend fun migrateMangaInternal( private suspend fun migrateMangaInternal(
prevManga: Manga, prevManga: Manga,
@ -480,6 +482,7 @@ class MigrationListScreenModel(
// Ignore cancellations // Ignore cancellations
throw e throw e
} catch (e: Exception) { } catch (e: Exception) {
Timber.tag("MigrationListScreenModel").e(e, "Error updating manga from source")
} }
migratingManga.searchResult.value = SearchResult.Result(result.id) migratingManga.searchResult.value = SearchResult.Result(result.id)
@ -593,7 +596,7 @@ class MigrationListScreenModel(
} }
} }
fun removeManga(item: MigratingManga) { private fun removeManga(item: MigratingManga) {
when (val migration = config.migration) { when (val migration = config.migration) {
is MigrationType.MangaList -> { is MigrationType.MangaList -> {
val ids = migration.mangaIds.toMutableList() val ids = migration.mangaIds.toMutableList()
@ -626,8 +629,25 @@ class MigrationListScreenModel(
) )
} }
// KMK -->
fun openMigrationOptionsDialog() {
dialog.value = Dialog.MigrationOptionsDialog
}
fun updateOptions() {
hideNotFound = preferences.hideNotFoundMigration().get()
showOnlyUpdates = preferences.showOnlyUpdatesMigration().get()
useSourceWithMost = preferences.useSourceWithMost().get()
useSmartSearch = preferences.smartMigration().get()
}
// KMK <--
sealed class Dialog { sealed class Dialog {
data class MigrateMangaDialog(val copy: Boolean, val mangaSet: Int, val mangaSkipped: Int) : Dialog() data class MigrateMangaDialog(val copy: Boolean, val mangaSet: Int, val mangaSkipped: Int) : Dialog()
object MigrationExitDialog : Dialog() data object MigrationExitDialog : Dialog()
// KMK -->
data object MigrationOptionsDialog : Dialog()
// KMK <--
} }
} }