Fix no sources while migrating alongside UI and code cleanup (mihonapp/mihon#2155)

(cherry picked from commit 5919f34fc96f254724bd3042ac2b91ac65912930)
(cherry picked from commit f0e6103f44d5a59e19decbd3ff48269009d782fc)

Co-authored-by: Cuong-Tran <16017808+cuong-tran@users.noreply.github.com>
This commit is contained in:
AntsyLich 2025-05-31 16:11:49 +06:00 committed by Cuong-Tran
parent c328b37675
commit 2196c84a0c
7 changed files with 55 additions and 40 deletions

View file

@ -21,7 +21,7 @@ import eu.kanade.tachiyomi.util.system.toast
import exh.util.overEq import exh.util.overEq
import exh.util.underEq import exh.util.underEq
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import mihon.feature.migration.MigrateMangaConfigScreen import mihon.feature.migration.config.MigrationConfigScreen
import tachiyomi.core.common.i18n.pluralStringResource 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
@ -76,7 +76,7 @@ class MigrationListScreen(private val config: MigrationProcedureConfig) : Screen
val newStack = navigator.items.filter { val newStack = navigator.items.filter {
it !is MangaScreen && it !is MangaScreen &&
it !is MigrationListScreen && it !is MigrationListScreen &&
it !is MigrateMangaConfigScreen it !is MigrationConfigScreen
} + MangaScreen(mangaId) } + MangaScreen(mangaId)
navigator replaceAll newStack.first() navigator replaceAll newStack.first()
navigator.push(newStack.drop(1)) navigator.push(newStack.drop(1))

View file

@ -13,7 +13,7 @@ import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.ui.manga.MangaScreen import eu.kanade.tachiyomi.ui.manga.MangaScreen
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import mihon.feature.migration.MigrateMangaConfigScreen import mihon.feature.migration.config.MigrationConfigScreen
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.screens.LoadingScreen import tachiyomi.presentation.core.screens.LoadingScreen
@ -38,14 +38,14 @@ data class MigrateMangaScreen(
navigateUp = navigator::pop, navigateUp = navigator::pop,
title = state.source?.name ?: "???", title = state.source?.name ?: "???",
state = state, state = state,
onClickItem = { navigator.push(MigrateMangaConfigScreen(listOf(it.id))) }, onClickItem = { navigator.push(MigrationConfigScreen(listOf(it.id))) },
onClickCover = { navigator.push(MangaScreen(it.id)) }, onClickCover = { navigator.push(MangaScreen(it.id)) },
// KMK --> // KMK -->
onMultiMigrateClicked = { onMultiMigrateClicked = {
if (state.selectionMode) { if (state.selectionMode) {
navigator.push(MigrateMangaConfigScreen(state.selected.map { it.manga.id })) navigator.push(MigrationConfigScreen(state.selected.map { it.manga.id }))
} else { } else {
navigator.push(MigrateMangaConfigScreen(state.titles.map { it.manga.id })) navigator.push(MigrationConfigScreen(state.titles.map { it.manga.id }))
} }
}, },
onSelectAll = screenModel::toggleAllSelection, onSelectAll = screenModel::toggleAllSelection,

View file

@ -66,7 +66,7 @@ import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import mihon.feature.migration.MigrateMangaConfigScreen import mihon.feature.migration.config.MigrationConfigScreen
import tachiyomi.core.common.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.common.util.lang.launchIO import tachiyomi.core.common.util.lang.launchIO
import tachiyomi.domain.category.model.Category import tachiyomi.domain.category.model.Category
@ -210,7 +210,7 @@ data object LibraryTab : Tab {
.map { it.id } .map { it.id }
screenModel.clearSelection() screenModel.clearSelection()
if (selectedMangaIds.isNotEmpty()) { if (selectedMangaIds.isNotEmpty()) {
navigator.push(MigrateMangaConfigScreen(selectedMangaIds)) navigator.push(MigrationConfigScreen(selectedMangaIds))
} else { } else {
context.toast(SYMR.strings.no_valid_entry) context.toast(SYMR.strings.no_valid_entry)
} }

View file

@ -9,7 +9,7 @@ import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.presentation.libraryUpdateError.LibraryUpdateErrorScreen import eu.kanade.presentation.libraryUpdateError.LibraryUpdateErrorScreen
import eu.kanade.presentation.util.Screen import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.ui.manga.MangaScreen import eu.kanade.tachiyomi.ui.manga.MangaScreen
import mihon.feature.migration.MigrateMangaConfigScreen import mihon.feature.migration.config.MigrationConfigScreen
class LibraryUpdateErrorScreen : Screen() { class LibraryUpdateErrorScreen : Screen() {
@ -22,11 +22,11 @@ class LibraryUpdateErrorScreen : Screen() {
LibraryUpdateErrorScreen( LibraryUpdateErrorScreen(
state = state, state = state,
onClick = { item -> onClick = { item ->
navigator.push(MigrateMangaConfigScreen(listOf(item.error.mangaId))) navigator.push(MigrationConfigScreen(listOf(item.error.mangaId)))
}, },
onClickCover = { item -> navigator.push(MangaScreen(item.error.mangaId)) }, onClickCover = { item -> navigator.push(MangaScreen(item.error.mangaId)) },
onMultiMigrateClicked = { onMultiMigrateClicked = {
navigator.push(MigrateMangaConfigScreen(state.selected.map { it.error.mangaId })) navigator.push(MigrationConfigScreen(state.selected.map { it.error.mangaId }))
}, },
onSelectAll = screenModel::toggleAllSelection, onSelectAll = screenModel::toggleAllSelection,
onInvertSelection = screenModel::invertSelection, onInvertSelection = screenModel::invertSelection,

View file

@ -103,7 +103,7 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.take import kotlinx.coroutines.flow.take
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import logcat.LogPriority import logcat.LogPriority
import mihon.feature.migration.MigrateMangaConfigScreen import mihon.feature.migration.config.MigrationConfigScreen
import tachiyomi.core.common.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.common.util.lang.launchIO import tachiyomi.core.common.util.lang.launchIO
import tachiyomi.core.common.util.lang.launchUI import tachiyomi.core.common.util.lang.launchUI
@ -366,7 +366,7 @@ class MangaScreen(
successState.manga.favorite successState.manga.favorite
}, },
onMigrateClicked = { onMigrateClicked = {
navigator.push(MigrateMangaConfigScreen(listOf(successState.manga.id))) navigator.push(MigrationConfigScreen(listOf(successState.manga.id)))
}.takeIf { successState.manga.favorite }, }.takeIf { successState.manga.favorite },
// SY --> // SY -->
previewsRowCount = successState.previewsRowCount, previewsRowCount = successState.previewsRowCount,

View file

@ -53,6 +53,16 @@ object LocaleHelper {
return Locale.forLanguageTag(normalizedLang).displayName return Locale.forLanguageTag(normalizedLang).displayName
} }
fun getShortDisplayName(lang: String?): String {
return when (lang) {
null -> ""
"es-419" -> "es-la"
"zh-CN" -> "zh-hans"
"zh-TW" -> "zh-hant"
else -> lang
}
}
/** /**
* Returns display name of a string language code. * Returns display name of a string language code.
* *

View file

@ -1,4 +1,4 @@
package mihon.feature.migration package mihon.feature.migration.config
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
@ -38,7 +38,6 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
@ -66,7 +65,7 @@ import eu.kanade.tachiyomi.util.system.LocaleHelper
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.updateAndGet import kotlinx.coroutines.flow.update
import sh.calvin.reorderable.ReorderableCollectionItemScope import sh.calvin.reorderable.ReorderableCollectionItemScope
import sh.calvin.reorderable.ReorderableItem import sh.calvin.reorderable.ReorderableItem
import sh.calvin.reorderable.ReorderableLazyListState import sh.calvin.reorderable.ReorderableLazyListState
@ -79,7 +78,6 @@ import tachiyomi.i18n.kmk.KMR
import tachiyomi.i18n.sy.SYMR import tachiyomi.i18n.sy.SYMR
import tachiyomi.presentation.core.components.FastScrollLazyColumn import tachiyomi.presentation.core.components.FastScrollLazyColumn
import tachiyomi.presentation.core.components.Pill import tachiyomi.presentation.core.components.Pill
import tachiyomi.presentation.core.components.material.DISABLED_ALPHA
import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.components.material.Scaffold
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
@ -96,7 +94,7 @@ import uy.kohesive.injekt.api.get
* *
* @param mangaIds IDs of the manga that will be migrated using the sources configured on this screen. * @param mangaIds IDs of the manga that will be migrated using the sources configured on this screen.
*/ */
class MigrateMangaConfigScreen(private val mangaIds: List<Long>) : Screen() { class MigrationConfigScreen(private val mangaIds: List<Long>) : Screen() {
@Composable @Composable
override fun Content() { override fun Content() {
@ -174,6 +172,7 @@ class MigrateMangaConfigScreen(private val mangaIds: List<Long>) : Screen() {
text = { Text(text = stringResource(MR.strings.migrationConfigScreen_continueButtonText)) }, text = { Text(text = stringResource(MR.strings.migrationConfigScreen_continueButtonText)) },
icon = { Icon(imageVector = Icons.AutoMirrored.Outlined.ArrowForward, contentDescription = null) }, icon = { Icon(imageVector = Icons.AutoMirrored.Outlined.ArrowForward, contentDescription = null) },
onClick = { onClick = {
screenModel.saveSources()
// KMK --> // KMK -->
screenModel.onMigrationSheet(true) screenModel.onMigrationSheet(true)
// KMK <-- // KMK <--
@ -232,9 +231,8 @@ class MigrateMangaConfigScreen(private val mangaIds: List<Long>) : Screen() {
SourceItemContainer( SourceItemContainer(
firstItem = index == 0, firstItem = index == 0,
lastItem = index == (sources.size - 1), lastItem = index == (sources.size - 1),
source = item.source, source = item,
showLanguage = showLanguage, showLanguage = showLanguage,
isSelected = item.isSelected,
dragEnabled = selectedSourceList && sources.size > 1, dragEnabled = selectedSourceList && sources.size > 1,
state = reorderableState, state = reorderableState,
key = { if (selectedSourceList) it.id else "available-${it.id}" }, key = { if (selectedSourceList) it.id else "available-${it.id}" },
@ -289,12 +287,11 @@ class MigrateMangaConfigScreen(private val mangaIds: List<Long>) : Screen() {
private fun LazyItemScope.SourceItemContainer( private fun LazyItemScope.SourceItemContainer(
firstItem: Boolean, firstItem: Boolean,
lastItem: Boolean, lastItem: Boolean,
source: Source, source: MigrationSource,
showLanguage: Boolean, showLanguage: Boolean,
isSelected: Boolean,
dragEnabled: Boolean, dragEnabled: Boolean,
state: ReorderableLazyListState, state: ReorderableLazyListState,
key: (Source) -> Any, key: (MigrationSource) -> Any,
onClick: () -> Unit, onClick: () -> Unit,
) { ) {
val shape = remember(firstItem, lastItem) { val shape = remember(firstItem, lastItem) {
@ -317,7 +314,6 @@ class MigrateMangaConfigScreen(private val mangaIds: List<Long>) : Screen() {
SourceItem( SourceItem(
source = source, source = source,
showLanguage = showLanguage, showLanguage = showLanguage,
isSelected = isSelected,
dragEnabled = dragEnabled, dragEnabled = dragEnabled,
scope = this@ReorderableItem, scope = this@ReorderableItem,
onClick = onClick, onClick = onClick,
@ -332,9 +328,8 @@ class MigrateMangaConfigScreen(private val mangaIds: List<Long>) : Screen() {
@Composable @Composable
private fun SourceItem( private fun SourceItem(
source: Source, source: MigrationSource,
showLanguage: Boolean, showLanguage: Boolean,
isSelected: Boolean,
dragEnabled: Boolean, dragEnabled: Boolean,
scope: ReorderableCollectionItemScope, scope: ReorderableCollectionItemScope,
onClick: () -> Unit, onClick: () -> Unit,
@ -345,7 +340,7 @@ class MigrateMangaConfigScreen(private val mangaIds: List<Long>) : Screen() {
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small), horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
SourceIcon(source = source) SourceIcon(source = source.source)
Text( Text(
text = source.name, text = source.name,
maxLines = 1, maxLines = 1,
@ -355,7 +350,9 @@ class MigrateMangaConfigScreen(private val mangaIds: List<Long>) : Screen() {
) )
if (showLanguage) { if (showLanguage) {
Pill( Pill(
text = FlagEmoji.getEmojiLangFlag(source.lang) + " (${LocaleHelper.getLocalizedDisplayName(source.lang)})", // KMK -->
text = FlagEmoji.getEmojiLangFlag(source.shortLanguage) + " (${source.upperShortLanguage})",
// KMK <--
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
) )
} }
@ -377,9 +374,7 @@ class MigrateMangaConfigScreen(private val mangaIds: List<Long>) : Screen() {
colors = ListItemDefaults.colors( colors = ListItemDefaults.colors(
containerColor = Color.Transparent, containerColor = Color.Transparent,
), ),
modifier = Modifier modifier = Modifier.clickable(onClick = onClick),
.clickable(onClick = onClick)
.alpha(if (isSelected) 1f else DISABLED_ALPHA),
) )
} }
@ -414,12 +409,12 @@ class MigrateMangaConfigScreen(private val mangaIds: List<Long>) : Screen() {
// { !it.isSelected }, // { !it.isSelected },
{ includedSources[it.source.id] ?: Int.MAX_VALUE }, { includedSources[it.source.id] ?: Int.MAX_VALUE },
// KMK <-- // KMK <--
{ with(it.source) { "$name (${LocaleHelper.getLocalizedDisplayName(lang)})" } }, { with(it) { "$name ($shortLanguage)" } },
) )
} }
private fun updateSources(save: Boolean = true, action: (List<MigrationSource>) -> List<MigrationSource>) { private fun updateSources(save: Boolean = true, action: (List<MigrationSource>) -> List<MigrationSource>) {
val state = mutableState.updateAndGet { state -> mutableState.update { state ->
val updatedSources = action(state.sources) val updatedSources = action(state.sources)
val includedSources = updatedSources.mapNotNull { if (!it.isSelected) null else it.id } val includedSources = updatedSources.mapNotNull { if (!it.isSelected) null else it.id }
// KMK --> // KMK -->
@ -427,11 +422,7 @@ class MigrateMangaConfigScreen(private val mangaIds: List<Long>) : Screen() {
// KMK <-- // KMK <--
state.copy(sources = updatedSources.sortedWith(sourcesComparator(includedSources))) state.copy(sources = updatedSources.sortedWith(sourcesComparator(includedSources)))
} }
if (!save) return if (save) saveSources()
state.sources
.filter { source -> source.isSelected }
.map { source -> source.source.id }
.let { sources -> sourcePreferences.migrationSources().set(sources) }
} }
private fun initSources() { private fun initSources() {
@ -506,6 +497,13 @@ class MigrateMangaConfigScreen(private val mangaIds: List<Long>) : Screen() {
} }
} }
fun saveSources() {
state.value.sources
.filter { source -> source.isSelected }
.map { source -> source.source.id }
.let { sources -> sourcePreferences.migrationSources().set(sources) }
}
data class State( data class State(
val sources: List<MigrationSource> = emptyList(), val sources: List<MigrationSource> = emptyList(),
) )
@ -521,8 +519,15 @@ class MigrateMangaConfigScreen(private val mangaIds: List<Long>) : Screen() {
data class MigrationSource( data class MigrationSource(
val source: Source, val source: Source,
val isSelected: Boolean, val isSelected: Boolean,
// KMK -->
val shortLanguage: String = LocaleHelper.getShortDisplayName(source.lang),
val upperShortLanguage: String = shortLanguage.uppercase(),
// KMK <--
) { ) {
val id = source.id val id: Long
val visualName = source.visualName inline get() = source.id
val name: String
inline get() = source.name
} }
} }