feat(migration): Allow skipping smart search for single entry migration (#1496)
* feat(migration): Allow skipping smart search for single entry migration Introduces a "Smart search" setting when migrating a single manga, allowing users to choose between an automated best-match search or manual selection directly. * ensure manual migration is only triggered once * Add UI toggle * refactor pref
This commit is contained in:
parent
36c1c642ca
commit
fe7b10f941
6 changed files with 70 additions and 15 deletions
|
|
@ -87,6 +87,8 @@ class SourcePreferences(
|
|||
fun migrationHideWithoutUpdates() = preferenceStore.getBoolean("migration_hide_without_updates", false)
|
||||
|
||||
// KMK -->
|
||||
fun migrationSmartSearchSingleEntry() = preferenceStore.getBoolean("migration_smart_search_single_entry", false)
|
||||
|
||||
fun globalSearchPinnedState() = preferenceStore.getEnum(
|
||||
Preference.appStateKey("global_search_pinned_toggle_state"),
|
||||
SourceFilter.PinnedOnly,
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ class MigrationConfigScreen(private val mangaIds: Collection<Long>) : Screen() {
|
|||
return
|
||||
}
|
||||
val screen = // KMK --> if (mangaId == null) {
|
||||
MigrationListScreen(mangaIds, extraSearchQuery)
|
||||
MigrationListScreen(mangaIds, extraSearchQuery, screenModel.sourcePreferences.migrationSmartSearchSingleEntry().get())
|
||||
// KMK -->
|
||||
// } else {
|
||||
// MigrateSearchScreen(mangaId)
|
||||
|
|
@ -297,6 +297,9 @@ class MigrationConfigScreen(private val mangaIds: Collection<Long>) : Screen() {
|
|||
migrationSheetOpen = false
|
||||
continueMigration(openSheet = false, extraSearchQuery = extraSearchQuery)
|
||||
},
|
||||
// KMK -->
|
||||
isSingleEntry = mangaIds.size == 1,
|
||||
// KMK <--
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import tachiyomi.core.common.preference.Preference
|
|||
import tachiyomi.core.common.preference.getAndSet
|
||||
import tachiyomi.core.common.preference.toggle
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.i18n.kmk.KMR
|
||||
import tachiyomi.presentation.core.components.material.Button
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
|
|
@ -53,6 +54,7 @@ fun MigrationConfigScreenSheet(
|
|||
onStartMigration: (extraSearchQuery: String?) -> Unit,
|
||||
// KMK -->
|
||||
fullSettings: Boolean = true,
|
||||
isSingleEntry: Boolean = false,
|
||||
// KMK <--
|
||||
) {
|
||||
var extraSearchQuery by rememberSaveable { mutableStateOf("") }
|
||||
|
|
@ -160,6 +162,18 @@ fun MigrationConfigScreenSheet(
|
|||
if (fullSettings) {
|
||||
// KMK <--
|
||||
MigrationSheetDividerItem()
|
||||
// KMK -->
|
||||
val migrationSmartSearchSingleEntryPref = preferences.migrationSmartSearchSingleEntry()
|
||||
val isSmartSearchSingleEntry by migrationSmartSearchSingleEntryPref.collectAsState()
|
||||
if (isSingleEntry) {
|
||||
MigrationSheetSwitchItem(
|
||||
title = stringResource(KMR.strings.migrationConfigScreen_smartSearchSingleEntryTitle),
|
||||
subtitle = stringResource(KMR.strings.migrationConfigScreen_smartSearchSingleEntrySubtitle),
|
||||
preference = migrationSmartSearchSingleEntryPref,
|
||||
)
|
||||
}
|
||||
if (!isSingleEntry || isSmartSearchSingleEntry) {
|
||||
// KMK <--
|
||||
MigrationSheetWarningItem(stringResource(MR.strings.migrationConfigScreen_enhancedOptionsWarning))
|
||||
MigrationSheetSwitchItem(
|
||||
title = stringResource(MR.strings.migrationConfigScreen_deepSearchModeTitle),
|
||||
|
|
@ -173,6 +187,7 @@ fun MigrationConfigScreenSheet(
|
|||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
HorizontalDivider()
|
||||
Button(
|
||||
onClick = {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import cafe.adriel.voyager.core.model.rememberScreenModel
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
|
|
@ -25,7 +28,13 @@ import tachiyomi.i18n.MR
|
|||
/**
|
||||
* Screen showing a list of pair of current-target manga entries being migrated.
|
||||
*/
|
||||
class MigrationListScreen(private val mangaIds: Collection<Long>, private val extraSearchQuery: String?) : Screen() {
|
||||
class MigrationListScreen(
|
||||
private val mangaIds: Collection<Long>,
|
||||
private val extraSearchQuery: String?,
|
||||
// KMK -->
|
||||
private val isSmartSearchSingleEntry: Boolean = false,
|
||||
// KMK <--
|
||||
) : Screen() {
|
||||
|
||||
private var matchOverride: Pair<Long, Long>? = null
|
||||
|
||||
|
|
@ -36,10 +45,24 @@ class MigrationListScreen(private val mangaIds: Collection<Long>, private val ex
|
|||
@Composable
|
||||
override fun Content() {
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
val screenModel = rememberScreenModel { MigrationListScreenModel(mangaIds, extraSearchQuery) }
|
||||
// KMK -->
|
||||
val singleEntryNoSmartSearch = mangaIds.size == 1 && !isSmartSearchSingleEntry
|
||||
// KMK <--
|
||||
val screenModel = rememberScreenModel { MigrationListScreenModel(mangaIds, extraSearchQuery, /* KMK --> */ singleEntryNoSmartSearch /* KMK <-- */) }
|
||||
val state by screenModel.state.collectAsState()
|
||||
val context = LocalContext.current
|
||||
|
||||
// KMK -->
|
||||
var hasPushedManual by rememberSaveable(mangaIds) { mutableStateOf(false) }
|
||||
LaunchedEffect(mangaIds) {
|
||||
if (singleEntryNoSmartSearch && !hasPushedManual) {
|
||||
@Suppress("AssignedValueIsNeverRead")
|
||||
hasPushedManual = true
|
||||
navigator.push(MigrateSearchScreen(mangaIds.single()))
|
||||
}
|
||||
}
|
||||
// KMK <--
|
||||
|
||||
LaunchedEffect(matchOverride) {
|
||||
val (current, target) = matchOverride ?: return@LaunchedEffect
|
||||
screenModel.useMangaForMigration(
|
||||
|
|
|
|||
|
|
@ -48,6 +48,9 @@ import uy.kohesive.injekt.api.get
|
|||
class MigrationListScreenModel(
|
||||
mangaIds: Collection<Long>,
|
||||
extraSearchQuery: String?,
|
||||
// KMK -->
|
||||
runManually: Boolean = false,
|
||||
// KMK <--
|
||||
val preferences: SourcePreferences = Injekt.get(),
|
||||
private val sourceManager: SourceManager = Injekt.get(),
|
||||
private val getManga: GetManga = Injekt.get(),
|
||||
|
|
@ -100,12 +103,19 @@ class MigrationListScreenModel(
|
|||
// KMK <--
|
||||
),
|
||||
parentContext = screenModelScope.coroutineContext,
|
||||
)
|
||||
// KMK -->
|
||||
).apply {
|
||||
if (runManually) searchResult.value = SearchResult.NotFound
|
||||
// KMK <--
|
||||
}
|
||||
}
|
||||
}
|
||||
.awaitAll()
|
||||
.filterNotNull()
|
||||
mutableState.update { it.copy(items = manga.toImmutableList()) }
|
||||
// KMK -->
|
||||
if (runManually) return@launchIO
|
||||
// KMK <--
|
||||
runMigrations(manga)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -183,6 +183,8 @@
|
|||
<string name="sort_feed_confirmation">Would you like to sort the feeds alphabetically?</string>
|
||||
<!-- Migration -->
|
||||
<string name="current_">Current: %1$s</string>
|
||||
<string name="migrationConfigScreen_smartSearchSingleEntryTitle">Use smart search</string>
|
||||
<string name="migrationConfigScreen_smartSearchSingleEntrySubtitle">If enabled, automatically picks the best match result. Otherwise, shows all search results for manual selection.</string>
|
||||
<!-- Misc -->
|
||||
<string name="job_failed_schedule_update_check">Failed to schedule automatic library update: %s</string>
|
||||
<string name="job_failed_schedule_backup_check">Failed to schedule automatic backup: %s</string>
|
||||
|
|
|
|||
Loading…
Reference in a new issue