Add more migration config options and remove skipping option (#2193)

This commit is contained in:
AntsyLich
2025-06-12 04:18:13 +06:00
committed by GitHub
parent 0290a2d815
commit 288f577a45
5 changed files with 197 additions and 59 deletions

View File

@@ -22,8 +22,6 @@ class SourcePreferences(
fun enabledLanguages() = preferenceStore.getStringSet("source_languages", LocaleHelper.getDefaultEnabledLanguages())
fun migrationSources() = preferenceStore.getLongArray("migration_sources", emptyList())
fun disabledSources() = preferenceStore.getStringSet("hidden_catalogues", emptySet())
fun incognitoExtensions() = preferenceStore.getStringSet("incognito_extensions", emptySet())
@@ -60,12 +58,20 @@ class SourcePreferences(
false,
)
fun migrationSources() = preferenceStore.getLongArray("migration_sources", emptyList())
fun migrationFlags() = preferenceStore.getObjectFromInt(
key = "migrate_flags",
key = "migration_flags",
defaultValue = MigrationFlag.entries.toSet(),
serializer = { MigrationFlag.toBit(it) },
deserializer = { value: Int -> MigrationFlag.fromBit(value) },
)
fun skipMigrationConfig() = preferenceStore.getBoolean(Preference.appStateKey("skip_migration_config"), false)
fun migrationDeepSearchMode() = preferenceStore.getBoolean("migration_deep_search", false)
fun migrationPrioritizeByChapters() = preferenceStore.getBoolean("migration_prioritize_by_chapters", false)
fun migrationHideUnmatched() = preferenceStore.getBoolean("migration_hide_unmatched", false)
fun migrationHideWithoutUpdates() = preferenceStore.getBoolean("migration_hide_without_updates", false)
}

View File

@@ -71,22 +71,6 @@ object SettingsBrowseScreen : SearchableSettings {
Preference.PreferenceItem.InfoPreference(stringResource(MR.strings.parental_controls_info)),
),
),
getMigrationCategory(sourcePreferences),
)
}
@Composable
fun getMigrationCategory(sourcePreferences: SourcePreferences): Preference.PreferenceGroup {
return Preference.PreferenceGroup(
stringResource(MR.strings.browseSettingsScreen_migrationCategoryHeader),
enabled = sourcePreferences.skipMigrationConfig().isSet(),
preferenceItems = persistentListOf(
Preference.PreferenceItem.SwitchPreference(
preference = sourcePreferences.skipMigrationConfig(),
title = stringResource(MR.strings.browseSettingsScreen_skipMigrationConfigTitle),
subtitle = stringResource(MR.strings.browseSettingsScreen_skipMigrationConfigSubtitle),
),
),
)
}
}

View File

@@ -22,7 +22,6 @@ import androidx.compose.material3.ListItemDefaults
import androidx.compose.material3.MaterialTheme
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
@@ -81,18 +80,11 @@ class MigrationConfigScreen(private val mangaId: Long) : Screen() {
var migrationSheetOpen by rememberSaveable { mutableStateOf(false) }
fun continueMigration(openSheet: Boolean) {
if (openSheet) {
migrationSheetOpen = true
return
}
fun continueMigration(openSheet: Boolean, extraSearchQuery: String?) {
navigator.replace(MigrateSearchScreen(mangaId))
}
if (state.isLoading) {
LaunchedEffect(state.skipMigrationConfig) {
if (state.skipMigrationConfig) continueMigration(openSheet = false)
}
LoadingScreen()
return
}
@@ -143,7 +135,7 @@ class MigrationConfigScreen(private val mangaId: Long) : Screen() {
icon = { Icon(imageVector = Icons.AutoMirrored.Outlined.ArrowForward, contentDescription = null) },
onClick = {
screenModel.saveSources()
continueMigration(openSheet = true)
continueMigration(openSheet = true, extraSearchQuery = null)
},
expanded = lazyListState.shouldExpandFAB(),
)
@@ -204,9 +196,9 @@ class MigrationConfigScreen(private val mangaId: Long) : Screen() {
MigrationConfigScreenSheet(
preferences = screenModel.sourcePreferences,
onDismissRequest = { migrationSheetOpen = false },
onStartMigration = {
onStartMigration = { extraSearchQuery ->
migrationSheetOpen = false
continueMigration(openSheet = false)
continueMigration(openSheet = false, extraSearchQuery = extraSearchQuery)
},
)
}
@@ -312,9 +304,6 @@ class MigrationConfigScreen(private val mangaId: 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) }
}
@@ -414,7 +403,6 @@ class MigrationConfigScreen(private val mangaId: Long) : Screen() {
data class State(
val isLoading: Boolean = true,
val skipMigrationConfig: Boolean = false,
val sources: List<MigrationSource> = emptyList(),
)

View File

@@ -3,60 +3,166 @@ 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.FlowRow
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Check
import androidx.compose.material.icons.outlined.Warning
import androidx.compose.material3.FilterChip
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.ListItemDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
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.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 mihon.domain.migration.models.MigrationFlag
import mihon.feature.common.utils.getLabel
import tachiyomi.core.common.preference.Preference
import tachiyomi.core.common.preference.getAndSet
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.theme.active
import tachiyomi.presentation.core.theme.header
import tachiyomi.presentation.core.util.collectAsState
@Composable
fun MigrationConfigScreenSheet(
preferences: SourcePreferences,
onDismissRequest: () -> Unit,
onStartMigration: () -> Unit,
onStartMigration: (extraSearchQuery: String?) -> Unit,
) {
val skipMigrationConfig by preferences.skipMigrationConfig().collectAsState()
var extraSearchQuery by rememberSaveable { mutableStateOf("") }
val migrationFlags by preferences.migrationFlags().collectAsState()
AdaptiveSheet(onDismissRequest = onDismissRequest) {
Column(modifier = Modifier.fillMaxWidth()) {
Column(
modifier = Modifier
.weight(1f, fill = false)
.fillMaxWidth()
.verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(8.dp),
.verticalScroll(rememberScrollState())
.padding(top = MaterialTheme.padding.medium),
) {
MigrationSheetItem(
title = stringResource(MR.strings.migrationConfigScreen_skipMigrationConfigTitle),
subtitle = stringResource(MR.strings.migrationConfigScreen_skipMigrationConfigSubtitle),
action = {
Switch(
checked = skipMigrationConfig,
onCheckedChange = null,
Text(
text = stringResource(MR.strings.migrationConfigScreen_dataToMigrateHeader),
style = MaterialTheme.typography.header,
modifier = Modifier
.fillMaxWidth()
.padding(top = MaterialTheme.padding.extraSmall)
.padding(horizontal = MaterialTheme.padding.medium),
)
Spacer(modifier = Modifier.height(MaterialTheme.padding.extraSmall))
FlowRow(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = MaterialTheme.padding.medium)
.padding(bottom = MaterialTheme.padding.extraSmall),
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small),
) {
MigrationFlag.entries.forEach { flag ->
if (flag == MigrationFlag.REMOVE_DOWNLOAD) return@forEach
val selected = flag in migrationFlags
FilterChip(
selected = selected,
onClick = {
preferences.migrationFlags().getAndSet {
if (selected) {
it - flag
} else {
it + flag
}
}
},
label = { Text(stringResource(flag.getLabel())) },
leadingIcon = {
if (selected) {
Icon(
imageVector = Icons.Outlined.Check,
contentDescription = null,
)
}
},
)
}
}
val removeDownloads = MigrationFlag.REMOVE_DOWNLOAD in migrationFlags
MigrationSheetSwitchItem(
title = stringResource(MR.strings.migrationConfigScreen_removeDownloadsTitle),
subtitle = null,
checked = removeDownloads,
onClick = {
preferences.migrationFlags().getAndSet {
if (removeDownloads) {
it - MigrationFlag.REMOVE_DOWNLOAD
} else {
it + MigrationFlag.REMOVE_DOWNLOAD
}
}
},
onClick = { preferences.skipMigrationConfig().toggle() },
)
MigrationSheetDividerItem()
OutlinedTextField(
value = extraSearchQuery,
onValueChange = { extraSearchQuery = it },
label = { Text(stringResource(MR.strings.migrationConfigScreen_additionalSearchQueryLabel)) },
placeholder = {
Text(stringResource(MR.strings.migrationConfigScreen_additionalSearchQueryPlaceholder))
},
supportingText = {
Text(stringResource(MR.strings.migrationConfigScreen_additionalSearchQuerySupportingText))
},
singleLine = true,
modifier = Modifier
.fillMaxWidth()
.padding(
horizontal = MaterialTheme.padding.medium,
vertical = MaterialTheme.padding.extraSmall,
),
)
MigrationSheetSwitchItem(
title = stringResource(MR.strings.migrationConfigScreen_hideUnmatchedTitle),
subtitle = null,
preference = preferences.migrationHideUnmatched(),
)
MigrationSheetDividerItem()
MigrationSheetWarningItem(stringResource(MR.strings.migrationConfigScreen_enhancedOptionsWarning))
MigrationSheetSwitchItem(
title = stringResource(MR.strings.migrationConfigScreen_hideWithoutUpdatesTitle),
subtitle = stringResource(MR.strings.migrationConfigScreen_hideWithoutUpdatesSubtitle),
preference = preferences.migrationHideWithoutUpdates(),
)
MigrationSheetSwitchItem(
title = stringResource(MR.strings.migrationConfigScreen_deepSearchModeTitle),
subtitle = stringResource(MR.strings.migrationConfigScreen_deepSearchModeSubtitle),
preference = preferences.migrationDeepSearchMode(),
)
MigrationSheetSwitchItem(
title = stringResource(MR.strings.migrationConfigScreen_prioritizeByChaptersTitle),
subtitle = null,
preference = preferences.migrationPrioritizeByChapters(),
)
}
HorizontalDivider()
Button(
onClick = onStartMigration,
onClick = { onStartMigration(extraSearchQuery) },
modifier = Modifier
.fillMaxWidth()
.padding(
@@ -71,17 +177,65 @@ fun MigrationConfigScreenSheet(
}
@Composable
private fun MigrationSheetItem(
private fun MigrationSheetSwitchItem(
title: String,
subtitle: String?,
action: @Composable () -> Unit,
preference: Preference<Boolean>,
) {
val checked by preference.collectAsState()
MigrationSheetSwitchItem(
title = title,
subtitle = subtitle,
checked = checked,
onClick = { preference.toggle() },
)
}
@Composable
private fun MigrationSheetSwitchItem(
title: String,
subtitle: String?,
checked: Boolean,
onClick: () -> Unit,
) {
ListItem(
headlineContent = { Text(text = title) },
supportingContent = subtitle?.let { { Text(text = subtitle) } },
trailingContent = action,
trailingContent = {
Switch(
checked = checked,
onCheckedChange = null,
)
},
colors = ListItemDefaults.colors(containerColor = Color.Transparent),
modifier = Modifier.clickable(onClick = onClick),
)
}
@Composable
private fun MigrationSheetDividerItem() {
HorizontalDivider(modifier = Modifier.padding(vertical = MaterialTheme.padding.extraSmall))
}
@Composable
private fun MigrationSheetWarningItem(
text: String,
) {
ListItem(
leadingContent = {
Icon(
imageVector = Icons.Outlined.Warning,
contentDescription = null,
tint = MaterialTheme.colorScheme.active,
)
},
headlineContent = {
Text(
text = text,
color = MaterialTheme.colorScheme.error,
modifier = Modifier,
)
},
colors = ListItemDefaults.colors(containerColor = Color.Transparent),
)
}

View File

@@ -1004,10 +1004,16 @@
<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>
<string name="migrationConfigScreen.dataToMigrateHeader">Data to migrate</string>
<string name="migrationConfigScreen.removeDownloadsTitle">Delete downloads after migration</string>
<string name="migrationConfigScreen.additionalSearchQueryLabel">Additional search keywords</string>
<string name="migrationConfigScreen.additionalSearchQueryPlaceholder">e.g. language:english</string>
<string name="migrationConfigScreen.additionalSearchQuerySupportingText">Appends keywords to the search query</string>
<string name="migrationConfigScreen.hideUnmatchedTitle">Hide unmatched manga</string>
<string name="migrationConfigScreen.enhancedOptionsWarning">Settings below can be slower and may lead to temporary source restrictions</string>
<string name="migrationConfigScreen.hideWithoutUpdatesTitle">Hide if no new chapters</string>
<string name="migrationConfigScreen.hideWithoutUpdatesSubtitle">Show only if the match offers newer chapters</string>
<string name="migrationConfigScreen.deepSearchModeTitle">Deep search mode</string>
<string name="migrationConfigScreen.deepSearchModeSubtitle">More detailed keyword search</string>
<string name="migrationConfigScreen.prioritizeByChaptersTitle">Prioritize by newer chapters</string>
</resources>