Add option to skip migration config

(cherry picked from commit 8714653a2f3b1a1f536494bcefbe66e7a7bbb4f7)

Co-authored-by: Cuong-Tran <16017808+cuong-tran@users.noreply.github.com>
This commit is contained in:
AntsyLich 2025-06-02 11:07:02 +06:00 committed by Cuong-Tran
parent 5ab24620ec
commit 2236e94f50
6 changed files with 168 additions and 37 deletions

View file

@ -78,6 +78,8 @@ class SourcePreferences(
deserializer = { value: Int -> MigrationFlag.fromBit(value) },
)
fun skipMigrationConfig() = preferenceStore.getBoolean(Preference.appStateKey("skip_migration_config"), false)
// KMK -->
fun globalSearchPinnedState() = preferenceStore.getEnum(
Preference.appStateKey("global_search_pinned_toggle_state"),
@ -124,8 +126,6 @@ class SourcePreferences(
fun useSourceWithMost() = preferenceStore.getBoolean("use_source_with_most", false)
fun skipPreMigration() = preferenceStore.getBoolean(Preference.appStateKey("skip_pre_migration"), false)
fun hideNotFoundMigration() = preferenceStore.getBoolean("hide_not_found_migration", false)
fun showOnlyUpdatesMigration() = preferenceStore.getBoolean("show_only_updates_migration", false)

View file

@ -30,6 +30,7 @@ import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
object SettingsBrowseScreen : SearchableSettings {
@Suppress("unused")
private fun readResolve(): Any = SettingsBrowseScreen
@ReadOnlyComposable
@ -171,16 +172,14 @@ object SettingsBrowseScreen : SearchableSettings {
@Composable
fun getMigrationCategory(sourcePreferences: SourcePreferences): Preference.PreferenceGroup {
val skipPreMigration by sourcePreferences.skipPreMigration().collectAsState()
val migrationSources by sourcePreferences.migrationSources().collectAsState()
return Preference.PreferenceGroup(
stringResource(SYMR.strings.migration),
enabled = skipPreMigration || migrationSources.isNotEmpty(),
stringResource(MR.strings.browseSettingsScreen_migrationCategoryHeader),
enabled = sourcePreferences.skipMigrationConfig().isSet(),
preferenceItems = persistentListOf(
Preference.PreferenceItem.SwitchPreference(
preference = sourcePreferences.skipPreMigration(),
title = stringResource(SYMR.strings.skip_pre_migration),
subtitle = stringResource(SYMR.strings.pref_skip_pre_migration_summary),
preference = sourcePreferences.skipMigrationConfig(),
title = stringResource(MR.strings.browseSettingsScreen_skipMigrationConfigTitle),
subtitle = stringResource(MR.strings.browseSettingsScreen_skipMigrationConfigSubtitle),
),
),
)

View file

@ -144,7 +144,7 @@ class MigrationBottomSheetDialogState(
}
sourceGroup.bindToPreference(preferences.useSourceWithMost())
skipStep.isChecked = preferences.skipPreMigration().get()
skipStep.isChecked = preferences.skipMigrationConfig().get()
hideNotFoundManga.isChecked = preferences.hideNotFoundMigration().get()
onlyShowUpdates.isChecked = preferences.showOnlyUpdatesMigration().get()
skipStep.setOnCheckedChangeListener { _, isChecked ->
@ -157,7 +157,7 @@ class MigrationBottomSheetDialogState(
}
migrateBtn.setOnClickListener {
preferences.skipPreMigration().set(skipStep.isChecked)
preferences.skipMigrationConfig().set(skipStep.isChecked)
preferences.hideNotFoundMigration().set(hideNotFoundManga.isChecked)
preferences.showOnlyUpdatesMigration().set(onlyShowUpdates.isChecked)
onStartMigration.value(

View file

@ -30,11 +30,13 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SmallExtendedFloatingActionButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -63,8 +65,6 @@ import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigrationProcedu
import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigrationType
import eu.kanade.tachiyomi.util.system.LocaleHelper
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import sh.calvin.reorderable.ReorderableCollectionItemScope
import sh.calvin.reorderable.ReorderableItem
@ -82,6 +82,7 @@ import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.icons.FlagEmoji
import tachiyomi.presentation.core.screens.LoadingScreen
import tachiyomi.presentation.core.util.shouldExpandFAB
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -99,6 +100,7 @@ class MigrationConfigScreen(private val mangaIds: List<Long>) : Screen() {
@Composable
override fun Content() {
val navigator = LocalNavigator.currentOrThrow
val screenModel = rememberScreenModel { ScreenModel() }
// KMK -->
var searchQuery by remember { mutableStateOf("") }
@ -107,6 +109,44 @@ class MigrationConfigScreen(private val mangaIds: List<Long>) : Screen() {
}
// KMK <--
val state by screenModel.state.collectAsState()
var migrationSheetOpen by rememberSaveable { mutableStateOf(false) }
// KMK -->
var migrationBottomSheetDialog by rememberSaveable { mutableStateOf(false) }
fun continueMigrationBottom(openSheet: Boolean, extraParam: String? = null) {
if (openSheet) {
migrationBottomSheetDialog = true
return
}
navigator.replace(
// KMK -->
MigrationListScreen(
MigrationProcedureConfig(MigrationType.MangaList(mangaIds), extraParam),
),
// KMK <--
)
}
// KMK <--
fun continueMigration(openSheet: Boolean) {
if (openSheet) {
migrationSheetOpen = true
return
}
// KMK -->
continueMigrationBottom(true)
// KMK <--
}
if (state.isLoading) {
LaunchedEffect(state.skipMigrationConfig) {
if (state.skipMigrationConfig) continueMigration(openSheet = false)
}
LoadingScreen()
return
}
val (selectedSources, availableSources) = state.sources
// KMK -->
.filter { sources ->
@ -173,9 +213,7 @@ class MigrationConfigScreen(private val mangaIds: List<Long>) : Screen() {
icon = { Icon(imageVector = Icons.AutoMirrored.Outlined.ArrowForward, contentDescription = null) },
onClick = {
screenModel.saveSources()
// KMK -->
screenModel.onMigrationSheet(true)
// KMK <--
continueMigration(openSheet = true)
},
expanded = lazyListState.shouldExpandFAB(),
)
@ -263,20 +301,24 @@ class MigrationConfigScreen(private val mangaIds: List<Long>) : Screen() {
}
}
// KMK -->
val migrationSheetOpen by screenModel.migrationSheetOpen.collectAsState()
if (migrationSheetOpen) {
MigrationConfigScreenSheet(
preferences = screenModel.sourcePreferences,
onDismissRequest = { migrationSheetOpen = false },
onStartMigration = {
migrationSheetOpen = false
continueMigration(openSheet = false)
},
)
}
// KMK -->
if (migrationBottomSheetDialog) {
MigrationBottomSheetDialog(
onDismissRequest = { screenModel.onMigrationSheet(false) },
onDismissRequest = { migrationBottomSheetDialog = false },
onStartMigration = { extraParam ->
screenModel.onMigrationSheet(false)
navigator.replace(
// KMK -->
MigrationListScreen(
MigrationProcedureConfig(MigrationType.MangaList(mangaIds), extraParam),
),
// KMK <--
)
migrationBottomSheetDialog = false
continueMigrationBottom(openSheet = false, extraParam)
},
)
}
@ -379,8 +421,8 @@ class MigrationConfigScreen(private val mangaIds: List<Long>) : Screen() {
}
private class ScreenModel(
val sourcePreferences: SourcePreferences = Injekt.get(),
private val sourceManager: SourceManager = Injekt.get(),
private val sourcePreferences: SourcePreferences = Injekt.get(),
) : StateScreenModel<ScreenModel.State>(State()) {
// KMK -->
@ -390,19 +432,14 @@ class MigrationConfigScreen(private val mangaIds: List<Long>) : Screen() {
init {
screenModelScope.launchIO {
val skipMigrationConfig = sourcePreferences.skipMigrationConfig().get()
mutableState.update { it.copy(skipMigrationConfig = skipMigrationConfig) }
if (skipMigrationConfig) return@launchIO
initSources()
mutableState.update { it.copy(isLoading = false) }
}
}
// KMK -->
private val _migrationSheetOpen = MutableStateFlow(false)
val migrationSheetOpen = _migrationSheetOpen.asStateFlow()
fun onMigrationSheet(isOpen: Boolean) {
_migrationSheetOpen.value = isOpen
}
// KMK <--
private val sourcesComparator = { includedSources: /* KMK --> */ Map<Long, Int> /* KMK <-- */ ->
compareBy<MigrationSource>(
// KMK -->
@ -505,6 +542,8 @@ class MigrationConfigScreen(private val mangaIds: List<Long>) : Screen() {
}
data class State(
val isLoading: Boolean = true,
val skipMigrationConfig: Boolean = false,
val sources: List<MigrationSource> = emptyList(),
)

View file

@ -0,0 +1,87 @@
package mihon.feature.migration.config
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.ListItem
import androidx.compose.material3.ListItemDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import eu.kanade.domain.source.service.SourcePreferences
import eu.kanade.presentation.components.AdaptiveSheet
import tachiyomi.core.common.preference.toggle
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.Button
import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.util.collectAsState
@Composable
fun MigrationConfigScreenSheet(
preferences: SourcePreferences,
onDismissRequest: () -> Unit,
onStartMigration: () -> Unit,
) {
val skipMigrationConfig by preferences.skipMigrationConfig().collectAsState()
AdaptiveSheet(onDismissRequest = onDismissRequest) {
Column(modifier = Modifier.fillMaxWidth()) {
Column(
modifier = Modifier
.fillMaxWidth()
.verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
MigrationSheetItem(
title = stringResource(MR.strings.migrationConfigScreen_skipMigrationConfigTitle),
subtitle = stringResource(MR.strings.migrationConfigScreen_skipMigrationConfigSubtitle),
action = {
Switch(
checked = skipMigrationConfig,
onCheckedChange = null,
)
},
onClick = { preferences.skipMigrationConfig().toggle() },
)
}
HorizontalDivider()
Button(
onClick = onStartMigration,
modifier = Modifier
.fillMaxWidth()
.padding(
horizontal = MaterialTheme.padding.medium,
vertical = MaterialTheme.padding.small,
),
) {
Text(text = stringResource(MR.strings.migrationConfigScreen_continueButtonText))
}
}
}
}
@Composable
private fun MigrationSheetItem(
title: String,
subtitle: String?,
action: @Composable () -> Unit,
onClick: () -> Unit,
) {
ListItem(
headlineContent = { Text(text = title) },
supportingContent = subtitle?.let { { Text(text = subtitle) } },
trailingContent = action,
colors = ListItemDefaults.colors(containerColor = Color.Transparent),
modifier = Modifier.clickable(onClick = onClick),
)
}

View file

@ -1015,4 +1015,10 @@
<string name="migrationConfigScreen.selectEnabledLabel">Select enabled sources</string>
<string name="migrationConfigScreen.selectPinnedLabel">Select pinned sources</string>
<string name="migrationConfigScreen.continueButtonText">Continue</string>
<string name="migrationConfigScreen.skipMigrationConfigTitle">Skip migration config</string>
<string name="migrationConfigScreen.skipMigrationConfigSubtitle">To show this screen again in the future, disable skipping in Settings → Browse</string>
<string name="browseSettingsScreen.migrationCategoryHeader">Migration</string>
<string name="browseSettingsScreen.skipMigrationConfigTitle">Skip migration config</string>
<string name="browseSettingsScreen.skipMigrationConfigSubtitle">Use last used sources and preferences for migration</string>
</resources>