Add more migration config options and remove skipping option (mihonapp/mihon#2193)
(cherry picked from commit 288f577a45a6835c34ad41caab95794f164b7a0b) * Further tweak migration config screen sheet (cherry picked from commit 019fc08da2392725c36e064ffadc4e645edafb63) Co-authored-by: Cuong-Tran <16017808+cuong-tran@users.noreply.github.com>
This commit is contained in:
parent
2236e94f50
commit
42a97bb918
8 changed files with 224 additions and 135 deletions
|
|
@ -23,8 +23,6 @@ class SourcePreferences(
|
||||||
|
|
||||||
fun enabledLanguages() = preferenceStore.getStringSet("source_languages", LocaleHelper.getDefaultEnabledLanguages())
|
fun enabledLanguages() = preferenceStore.getStringSet("source_languages", LocaleHelper.getDefaultEnabledLanguages())
|
||||||
|
|
||||||
fun migrationSources() = preferenceStore.getLongArray("migration_sources", emptyList())
|
|
||||||
|
|
||||||
fun disabledSources() = preferenceStore.getStringSet("hidden_catalogues", emptySet())
|
fun disabledSources() = preferenceStore.getStringSet("hidden_catalogues", emptySet())
|
||||||
|
|
||||||
fun incognitoExtensions() = preferenceStore.getStringSet("incognito_extensions", emptySet())
|
fun incognitoExtensions() = preferenceStore.getStringSet("incognito_extensions", emptySet())
|
||||||
|
|
@ -71,14 +69,22 @@ class SourcePreferences(
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun migrationSources() = preferenceStore.getLongArray("migration_sources", emptyList())
|
||||||
|
|
||||||
fun migrationFlags() = preferenceStore.getObjectFromInt(
|
fun migrationFlags() = preferenceStore.getObjectFromInt(
|
||||||
key = "migrate_flags",
|
key = "migration_flags",
|
||||||
defaultValue = MigrationFlag.entries.toSet(),
|
defaultValue = MigrationFlag.entries.toSet(),
|
||||||
serializer = { MigrationFlag.toBit(it) },
|
serializer = { MigrationFlag.toBit(it) },
|
||||||
deserializer = { value: Int -> MigrationFlag.fromBit(value) },
|
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)
|
||||||
|
|
||||||
// KMK -->
|
// KMK -->
|
||||||
fun globalSearchPinnedState() = preferenceStore.getEnum(
|
fun globalSearchPinnedState() = preferenceStore.getEnum(
|
||||||
|
|
@ -122,14 +128,6 @@ class SourcePreferences(
|
||||||
WSRV_NL,
|
WSRV_NL,
|
||||||
}
|
}
|
||||||
|
|
||||||
fun smartMigration() = preferenceStore.getBoolean("smart_migrate", false)
|
|
||||||
|
|
||||||
fun useSourceWithMost() = preferenceStore.getBoolean("use_source_with_most", false)
|
|
||||||
|
|
||||||
fun hideNotFoundMigration() = preferenceStore.getBoolean("hide_not_found_migration", false)
|
|
||||||
|
|
||||||
fun showOnlyUpdatesMigration() = preferenceStore.getBoolean("show_only_updates_migration", false)
|
|
||||||
|
|
||||||
fun allowLocalSourceHiddenFolders() = preferenceStore.getBoolean("allow_local_source_hidden_folders", false)
|
fun allowLocalSourceHiddenFolders() = preferenceStore.getBoolean("allow_local_source_hidden_folders", false)
|
||||||
|
|
||||||
fun preferredMangaDexId() = preferenceStore.getString("preferred_mangaDex_id", "0")
|
fun preferredMangaDexId() = preferenceStore.getString("preferred_mangaDex_id", "0")
|
||||||
|
|
|
||||||
|
|
@ -166,22 +166,6 @@ object SettingsBrowseScreen : SearchableSettings {
|
||||||
Preference.PreferenceItem.InfoPreference(stringResource(MR.strings.parental_controls_info)),
|
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),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import android.view.LayoutInflater
|
||||||
import android.widget.CompoundButton
|
import android.widget.CompoundButton
|
||||||
import android.widget.RadioButton
|
import android.widget.RadioButton
|
||||||
import android.widget.RadioGroup
|
import android.widget.RadioGroup
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
|
@ -21,13 +20,11 @@ import eu.kanade.domain.source.service.SourcePreferences
|
||||||
import eu.kanade.presentation.components.AdaptiveSheet
|
import eu.kanade.presentation.components.AdaptiveSheet
|
||||||
import eu.kanade.presentation.theme.colorscheme.AndroidViewColorScheme
|
import eu.kanade.presentation.theme.colorscheme.AndroidViewColorScheme
|
||||||
import eu.kanade.tachiyomi.databinding.MigrationBottomSheetBinding
|
import eu.kanade.tachiyomi.databinding.MigrationBottomSheetBinding
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
|
||||||
import mihon.domain.migration.models.MigrationFlag
|
import mihon.domain.migration.models.MigrationFlag
|
||||||
import tachiyomi.core.common.i18n.stringResource
|
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.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import tachiyomi.i18n.sy.SYMR
|
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -85,7 +82,6 @@ fun MigrationBottomSheetDialog(
|
||||||
listOf(
|
listOf(
|
||||||
useSmartSearch,
|
useSmartSearch,
|
||||||
extraSearchParam,
|
extraSearchParam,
|
||||||
skipStep,
|
|
||||||
hideNotFoundManga,
|
hideNotFoundManga,
|
||||||
onlyShowUpdates,
|
onlyShowUpdates,
|
||||||
).forEach {
|
).forEach {
|
||||||
|
|
@ -137,29 +133,19 @@ class MigrationBottomSheetDialogState(
|
||||||
checkBox.setOnCheckedChangeListener { _, _ -> setFlags(binding) }
|
checkBox.setOnCheckedChangeListener { _, _ -> setFlags(binding) }
|
||||||
}
|
}
|
||||||
|
|
||||||
useSmartSearch.bindToPreference(preferences.smartMigration())
|
useSmartSearch.bindToPreference(preferences.migrationDeepSearchMode())
|
||||||
extraSearchParamInputLayout.isVisible = false
|
extraSearchParamInputLayout.isVisible = false
|
||||||
extraSearchParam.setOnCheckedChangeListener { _, isChecked ->
|
extraSearchParam.setOnCheckedChangeListener { _, isChecked ->
|
||||||
extraSearchParamInputLayout.isVisible = isChecked
|
extraSearchParamInputLayout.isVisible = isChecked
|
||||||
}
|
}
|
||||||
sourceGroup.bindToPreference(preferences.useSourceWithMost())
|
sourceGroup.bindToPreference(preferences.migrationPrioritizeByChapters())
|
||||||
|
|
||||||
skipStep.isChecked = preferences.skipMigrationConfig().get()
|
hideNotFoundManga.isChecked = preferences.migrationHideUnmatched().get()
|
||||||
hideNotFoundManga.isChecked = preferences.hideNotFoundMigration().get()
|
onlyShowUpdates.isChecked = preferences.migrationHideWithoutUpdates().get()
|
||||||
onlyShowUpdates.isChecked = preferences.showOnlyUpdatesMigration().get()
|
|
||||||
skipStep.setOnCheckedChangeListener { _, isChecked ->
|
|
||||||
if (isChecked) {
|
|
||||||
root.context.toast(
|
|
||||||
SYMR.strings.pre_migration_skip_toast,
|
|
||||||
Toast.LENGTH_LONG,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
migrateBtn.setOnClickListener {
|
migrateBtn.setOnClickListener {
|
||||||
preferences.skipMigrationConfig().set(skipStep.isChecked)
|
preferences.migrationHideUnmatched().set(hideNotFoundManga.isChecked)
|
||||||
preferences.hideNotFoundMigration().set(hideNotFoundManga.isChecked)
|
preferences.migrationHideWithoutUpdates().set(onlyShowUpdates.isChecked)
|
||||||
preferences.showOnlyUpdatesMigration().set(onlyShowUpdates.isChecked)
|
|
||||||
onStartMigration.value(
|
onStartMigration.value(
|
||||||
if (useSmartSearch.isChecked && !extraSearchParamText.text.isNullOrBlank()) {
|
if (useSmartSearch.isChecked && !extraSearchParamText.text.isNullOrBlank()) {
|
||||||
extraSearchParamText.text.toString()
|
extraSearchParamText.text.toString()
|
||||||
|
|
@ -175,7 +161,6 @@ class MigrationBottomSheetDialogState(
|
||||||
extraSearchParam.isVisible = false
|
extraSearchParam.isVisible = false
|
||||||
extraSearchParamInputLayout.isVisible = false
|
extraSearchParamInputLayout.isVisible = false
|
||||||
sourceGroup.isVisible = false
|
sourceGroup.isVisible = false
|
||||||
skipStep.isVisible = false
|
|
||||||
migrateBtn.text = root.context.stringResource(MR.strings.action_save)
|
migrateBtn.text = root.context.stringResource(MR.strings.action_save)
|
||||||
}
|
}
|
||||||
// KMK <--
|
// KMK <--
|
||||||
|
|
|
||||||
|
|
@ -69,10 +69,10 @@ class MigrationListScreenModel(
|
||||||
|
|
||||||
val manualMigrations = MutableStateFlow(0)
|
val manualMigrations = MutableStateFlow(0)
|
||||||
|
|
||||||
var hideNotFound = preferences.hideNotFoundMigration().get()
|
var hideNotFound = preferences.migrationHideUnmatched().get()
|
||||||
private var showOnlyUpdates = preferences.showOnlyUpdatesMigration().get()
|
private var showOnlyUpdates = preferences.migrationHideWithoutUpdates().get()
|
||||||
private var useSourceWithMost = preferences.useSourceWithMost().get()
|
private var useSourceWithMost = preferences.migrationPrioritizeByChapters().get()
|
||||||
private var useSmartSearch = preferences.smartMigration().get()
|
private var useSmartSearch = preferences.migrationDeepSearchMode().get()
|
||||||
|
|
||||||
val navigateOut = MutableSharedFlow<Unit>()
|
val navigateOut = MutableSharedFlow<Unit>()
|
||||||
|
|
||||||
|
|
@ -498,10 +498,10 @@ class MigrationListScreenModel(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateOptions() {
|
fun updateOptions() {
|
||||||
hideNotFound = preferences.hideNotFoundMigration().get()
|
hideNotFound = preferences.migrationHideUnmatched().get()
|
||||||
showOnlyUpdates = preferences.showOnlyUpdatesMigration().get()
|
showOnlyUpdates = preferences.migrationHideWithoutUpdates().get()
|
||||||
useSourceWithMost = preferences.useSourceWithMost().get()
|
useSourceWithMost = preferences.migrationPrioritizeByChapters().get()
|
||||||
useSmartSearch = preferences.smartMigration().get()
|
useSmartSearch = preferences.migrationDeepSearchMode().get()
|
||||||
}
|
}
|
||||||
// KMK <--
|
// KMK <--
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.SmallExtendedFloatingActionButton
|
import androidx.compose.material3.SmallExtendedFloatingActionButton
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
|
@ -59,7 +58,6 @@ import eu.kanade.presentation.components.AppBarActions
|
||||||
import eu.kanade.presentation.components.SOURCE_SEARCH_BOX_HEIGHT
|
import eu.kanade.presentation.components.SOURCE_SEARCH_BOX_HEIGHT
|
||||||
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.migration.advanced.design.MigrationBottomSheetDialog
|
|
||||||
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.migration.advanced.process.MigrationProcedureConfig
|
import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigrationProcedureConfig
|
||||||
import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigrationType
|
import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigrationType
|
||||||
|
|
@ -111,38 +109,24 @@ class MigrationConfigScreen(private val mangaIds: List<Long>) : Screen() {
|
||||||
val state by screenModel.state.collectAsState()
|
val state by screenModel.state.collectAsState()
|
||||||
|
|
||||||
var migrationSheetOpen by rememberSaveable { mutableStateOf(false) }
|
var migrationSheetOpen by rememberSaveable { mutableStateOf(false) }
|
||||||
// KMK -->
|
|
||||||
var migrationBottomSheetDialog by rememberSaveable { mutableStateOf(false) }
|
|
||||||
|
|
||||||
fun continueMigrationBottom(openSheet: Boolean, extraParam: String? = null) {
|
fun continueMigration(openSheet: Boolean, extraSearchQuery: String?) {
|
||||||
if (openSheet) {
|
|
||||||
migrationBottomSheetDialog = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
navigator.replace(
|
|
||||||
// KMK -->
|
|
||||||
MigrationListScreen(
|
|
||||||
MigrationProcedureConfig(MigrationType.MangaList(mangaIds), extraParam),
|
|
||||||
),
|
|
||||||
// KMK <--
|
|
||||||
)
|
|
||||||
}
|
|
||||||
// KMK <--
|
|
||||||
|
|
||||||
fun continueMigration(openSheet: Boolean) {
|
|
||||||
if (openSheet) {
|
if (openSheet) {
|
||||||
migrationSheetOpen = true
|
migrationSheetOpen = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// KMK -->
|
|
||||||
continueMigrationBottom(true)
|
navigator.replace(
|
||||||
// KMK <--
|
// KMK -->
|
||||||
|
// MigrateSearchScreen(mangaId)
|
||||||
|
MigrationListScreen(
|
||||||
|
MigrationProcedureConfig(MigrationType.MangaList(mangaIds), extraSearchQuery),
|
||||||
|
),
|
||||||
|
// KMK <--
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.isLoading) {
|
if (state.isLoading) {
|
||||||
LaunchedEffect(state.skipMigrationConfig) {
|
|
||||||
if (state.skipMigrationConfig) continueMigration(openSheet = false)
|
|
||||||
}
|
|
||||||
LoadingScreen()
|
LoadingScreen()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -213,7 +197,7 @@ class MigrationConfigScreen(private val mangaIds: List<Long>) : Screen() {
|
||||||
icon = { Icon(imageVector = Icons.AutoMirrored.Outlined.ArrowForward, contentDescription = null) },
|
icon = { Icon(imageVector = Icons.AutoMirrored.Outlined.ArrowForward, contentDescription = null) },
|
||||||
onClick = {
|
onClick = {
|
||||||
screenModel.saveSources()
|
screenModel.saveSources()
|
||||||
continueMigration(openSheet = true)
|
continueMigration(openSheet = true, extraSearchQuery = null)
|
||||||
},
|
},
|
||||||
expanded = lazyListState.shouldExpandFAB(),
|
expanded = lazyListState.shouldExpandFAB(),
|
||||||
)
|
)
|
||||||
|
|
@ -305,24 +289,12 @@ class MigrationConfigScreen(private val mangaIds: List<Long>) : Screen() {
|
||||||
MigrationConfigScreenSheet(
|
MigrationConfigScreenSheet(
|
||||||
preferences = screenModel.sourcePreferences,
|
preferences = screenModel.sourcePreferences,
|
||||||
onDismissRequest = { migrationSheetOpen = false },
|
onDismissRequest = { migrationSheetOpen = false },
|
||||||
onStartMigration = {
|
onStartMigration = { extraSearchQuery ->
|
||||||
migrationSheetOpen = false
|
migrationSheetOpen = false
|
||||||
continueMigration(openSheet = false)
|
continueMigration(openSheet = false, extraSearchQuery = extraSearchQuery)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// KMK -->
|
|
||||||
if (migrationBottomSheetDialog) {
|
|
||||||
MigrationBottomSheetDialog(
|
|
||||||
onDismissRequest = { migrationBottomSheetDialog = false },
|
|
||||||
onStartMigration = { extraParam ->
|
|
||||||
migrationBottomSheetDialog = false
|
|
||||||
continueMigrationBottom(openSheet = false, extraParam)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
// KMK <--
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -432,9 +404,6 @@ class MigrationConfigScreen(private val mangaIds: List<Long>) : Screen() {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
screenModelScope.launchIO {
|
screenModelScope.launchIO {
|
||||||
val skipMigrationConfig = sourcePreferences.skipMigrationConfig().get()
|
|
||||||
mutableState.update { it.copy(skipMigrationConfig = skipMigrationConfig) }
|
|
||||||
if (skipMigrationConfig) return@launchIO
|
|
||||||
initSources()
|
initSources()
|
||||||
mutableState.update { it.copy(isLoading = false) }
|
mutableState.update { it.copy(isLoading = false) }
|
||||||
}
|
}
|
||||||
|
|
@ -543,7 +512,6 @@ class MigrationConfigScreen(private val mangaIds: List<Long>) : Screen() {
|
||||||
|
|
||||||
data class State(
|
data class State(
|
||||||
val isLoading: Boolean = true,
|
val isLoading: Boolean = true,
|
||||||
val skipMigrationConfig: Boolean = false,
|
|
||||||
val sources: List<MigrationSource> = emptyList(),
|
val sources: List<MigrationSource> = emptyList(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,60 +3,171 @@ package mihon.feature.migration.config
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
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.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
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.HorizontalDivider
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.ListItem
|
import androidx.compose.material3.ListItem
|
||||||
import androidx.compose.material3.ListItemDefaults
|
import androidx.compose.material3.ListItemDefaults
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Switch
|
import androidx.compose.material3.Switch
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
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.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.util.fastForEach
|
||||||
|
import eu.kanade.core.util.fastFilterNot
|
||||||
import eu.kanade.domain.source.service.SourcePreferences
|
import eu.kanade.domain.source.service.SourcePreferences
|
||||||
import eu.kanade.presentation.components.AdaptiveSheet
|
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.core.common.preference.toggle
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import tachiyomi.presentation.core.components.material.Button
|
import tachiyomi.presentation.core.components.material.Button
|
||||||
import tachiyomi.presentation.core.components.material.padding
|
import tachiyomi.presentation.core.components.material.padding
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
|
import tachiyomi.presentation.core.theme.active
|
||||||
|
import tachiyomi.presentation.core.theme.header
|
||||||
import tachiyomi.presentation.core.util.collectAsState
|
import tachiyomi.presentation.core.util.collectAsState
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MigrationConfigScreenSheet(
|
fun MigrationConfigScreenSheet(
|
||||||
preferences: SourcePreferences,
|
preferences: SourcePreferences,
|
||||||
onDismissRequest: () -> Unit,
|
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) {
|
AdaptiveSheet(onDismissRequest = onDismissRequest) {
|
||||||
Column(modifier = Modifier.fillMaxWidth()) {
|
Column(modifier = Modifier.fillMaxWidth()) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
.weight(1f, fill = false)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.verticalScroll(rememberScrollState()),
|
.verticalScroll(rememberScrollState())
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
.padding(top = MaterialTheme.padding.medium),
|
||||||
) {
|
) {
|
||||||
MigrationSheetItem(
|
Text(
|
||||||
title = stringResource(MR.strings.migrationConfigScreen_skipMigrationConfigTitle),
|
text = stringResource(MR.strings.migrationConfigScreen_dataToMigrateHeader),
|
||||||
subtitle = stringResource(MR.strings.migrationConfigScreen_skipMigrationConfigSubtitle),
|
style = MaterialTheme.typography.header,
|
||||||
action = {
|
modifier = Modifier
|
||||||
Switch(
|
.fillMaxWidth()
|
||||||
checked = skipMigrationConfig,
|
.padding(top = MaterialTheme.padding.extraSmall)
|
||||||
onCheckedChange = null,
|
.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
|
||||||
|
.fastFilterNot { it == MigrationFlag.REMOVE_DOWNLOAD }
|
||||||
|
.fastForEach { flag ->
|
||||||
|
val selected = flag in migrationFlags
|
||||||
|
FilterChip(
|
||||||
|
selected = selected,
|
||||||
|
onClick = {
|
||||||
|
preferences.migrationFlags().getAndSet { currentFlags ->
|
||||||
|
if (flag in currentFlags) {
|
||||||
|
currentFlags - flag
|
||||||
|
} else {
|
||||||
|
currentFlags + 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 {
|
||||||
|
// KMK -->
|
||||||
|
if (MigrationFlag.REMOVE_DOWNLOAD in it) {
|
||||||
|
// KMK <--
|
||||||
|
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)) },
|
||||||
|
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(),
|
||||||
|
)
|
||||||
|
MigrationSheetSwitchItem(
|
||||||
|
title = stringResource(MR.strings.migrationConfigScreen_hideWithoutUpdatesTitle),
|
||||||
|
subtitle = stringResource(MR.strings.migrationConfigScreen_hideWithoutUpdatesSubtitle),
|
||||||
|
preference = preferences.migrationHideWithoutUpdates(),
|
||||||
|
)
|
||||||
|
MigrationSheetDividerItem()
|
||||||
|
MigrationSheetWarningItem(stringResource(MR.strings.migrationConfigScreen_enhancedOptionsWarning))
|
||||||
|
MigrationSheetSwitchItem(
|
||||||
|
title = stringResource(MR.strings.migrationConfigScreen_deepSearchModeTitle),
|
||||||
|
subtitle = stringResource(MR.strings.migrationConfigScreen_deepSearchModeSubtitle),
|
||||||
|
preference = preferences.migrationDeepSearchMode(),
|
||||||
|
)
|
||||||
|
MigrationSheetSwitchItem(
|
||||||
|
title = stringResource(MR.strings.migrationConfigScreen_prioritizeByChaptersTitle),
|
||||||
|
subtitle = stringResource(MR.strings.migrationConfigScreen_prioritizeByChaptersSubtitle),
|
||||||
|
preference = preferences.migrationPrioritizeByChapters(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
HorizontalDivider()
|
HorizontalDivider()
|
||||||
Button(
|
Button(
|
||||||
onClick = onStartMigration,
|
onClick = {
|
||||||
|
val cleanedExtraSearchQuery = extraSearchQuery.trim().ifBlank { null }
|
||||||
|
onStartMigration(cleanedExtraSearchQuery)
|
||||||
|
},
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(
|
.padding(
|
||||||
|
|
@ -71,17 +182,63 @@ fun MigrationConfigScreenSheet(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun MigrationSheetItem(
|
private fun MigrationSheetSwitchItem(
|
||||||
title: String,
|
title: String,
|
||||||
subtitle: String?,
|
subtitle: String?,
|
||||||
action: @Composable () -> Unit,
|
preference: Preference<Boolean>,
|
||||||
|
) {
|
||||||
|
MigrationSheetSwitchItem(
|
||||||
|
title = title,
|
||||||
|
subtitle = subtitle,
|
||||||
|
checked = preference.collectAsState().value,
|
||||||
|
onClick = { preference.toggle() },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun MigrationSheetSwitchItem(
|
||||||
|
title: String,
|
||||||
|
subtitle: String?,
|
||||||
|
checked: Boolean,
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
) {
|
) {
|
||||||
ListItem(
|
ListItem(
|
||||||
headlineContent = { Text(text = title) },
|
headlineContent = { Text(text = title) },
|
||||||
supportingContent = subtitle?.let { { Text(text = subtitle) } },
|
supportingContent = subtitle?.let { { Text(text = subtitle) } },
|
||||||
trailingContent = action,
|
trailingContent = {
|
||||||
|
Switch(
|
||||||
|
checked = checked,
|
||||||
|
onCheckedChange = null,
|
||||||
|
)
|
||||||
|
},
|
||||||
colors = ListItemDefaults.colors(containerColor = Color.Transparent),
|
colors = ListItemDefaults.colors(containerColor = Color.Transparent),
|
||||||
modifier = Modifier.clickable(onClick = onClick),
|
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,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
colors = ListItemDefaults.colors(containerColor = Color.Transparent),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -189,15 +189,6 @@
|
||||||
android:textSize="14sp"/>
|
android:textSize="14sp"/>
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<com.google.android.material.materialswitch.MaterialSwitch
|
|
||||||
android:id="@+id/skip_step"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:paddingHorizontal="16dp"
|
|
||||||
android:paddingVertical="16dp"
|
|
||||||
android:text="@string/skip_this_step_next_time" />
|
|
||||||
|
|
||||||
<com.google.android.material.materialswitch.MaterialSwitch
|
<com.google.android.material.materialswitch.MaterialSwitch
|
||||||
android:id="@+id/hide_not_found_manga"
|
android:id="@+id/hide_not_found_manga"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
||||||
|
|
@ -1015,10 +1015,16 @@
|
||||||
<string name="migrationConfigScreen.selectEnabledLabel">Select enabled sources</string>
|
<string name="migrationConfigScreen.selectEnabledLabel">Select enabled sources</string>
|
||||||
<string name="migrationConfigScreen.selectPinnedLabel">Select pinned sources</string>
|
<string name="migrationConfigScreen.selectPinnedLabel">Select pinned sources</string>
|
||||||
<string name="migrationConfigScreen.continueButtonText">Continue</string>
|
<string name="migrationConfigScreen.continueButtonText">Continue</string>
|
||||||
<string name="migrationConfigScreen.skipMigrationConfigTitle">Skip migration config</string>
|
<string name="migrationConfigScreen.dataToMigrateHeader">Data to migrate</string>
|
||||||
<string name="migrationConfigScreen.skipMigrationConfigSubtitle">To show this screen again in the future, disable skipping in Settings → Browse</string>
|
<string name="migrationConfigScreen.removeDownloadsTitle">Delete downloads of current entry after migration</string>
|
||||||
|
<string name="migrationConfigScreen.additionalSearchQueryLabel">Additional keywords (optional)</string>
|
||||||
<string name="browseSettingsScreen.migrationCategoryHeader">Migration</string>
|
<string name="migrationConfigScreen.additionalSearchQuerySupportingText">Helps narrow down search results by adding additional keywords</string>
|
||||||
<string name="browseSettingsScreen.skipMigrationConfigTitle">Skip migration config</string>
|
<string name="migrationConfigScreen.hideUnmatchedTitle">Hide entries without a match</string>
|
||||||
<string name="browseSettingsScreen.skipMigrationConfigSubtitle">Use last used sources and preferences for migration</string>
|
<string name="migrationConfigScreen.hideWithoutUpdatesTitle">Hide entries without newer chapters</string>
|
||||||
|
<string name="migrationConfigScreen.hideWithoutUpdatesSubtitle">Only show entry if the match has additional chapters</string>
|
||||||
|
<string name="migrationConfigScreen.enhancedOptionsWarning">These options are slow and dangerous and may lead to restrictions from sources</string>
|
||||||
|
<string name="migrationConfigScreen.deepSearchModeTitle">Advanced search mode</string>
|
||||||
|
<string name="migrationConfigScreen.deepSearchModeSubtitle">Breaks down the title into keywords for a wider search</string>
|
||||||
|
<string name="migrationConfigScreen.prioritizeByChaptersTitle">Match based on chapter number</string>
|
||||||
|
<string name="migrationConfigScreen.prioritizeByChaptersSubtitle">If enabled, chooses the match furthest ahead. Otherwise, picks the first match by source priority.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue