Rework Duplicate Dialog and Allow Migration (#492)
* (Mostly) Working Manga screen migration via duplicate dialog * Fully working migrate from Browse Search * Small tweaks for Antsy * Update app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt * Update app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt --------- Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com> (cherry picked from commit c0a888807b78891b28c6f6b9f16b719e24b03de1) # Conflicts: # app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SourceSearchScreen.kt # app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt # app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt # app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt
This commit is contained in:
parent
ec30ccccc2
commit
2ea488bff5
@ -1,16 +1,33 @@
|
|||||||
package eu.kanade.presentation.manga
|
package eu.kanade.presentation.manga
|
||||||
|
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.FlowRow
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.sizeIn
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.outlined.Add
|
||||||
|
import androidx.compose.material.icons.outlined.Book
|
||||||
|
import androidx.compose.material.icons.outlined.SwapVert
|
||||||
|
import androidx.compose.material3.HorizontalDivider
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import eu.kanade.presentation.components.AdaptiveSheet
|
||||||
|
import eu.kanade.presentation.components.TabbedDialogPaddings
|
||||||
|
import eu.kanade.presentation.more.settings.LocalPreferenceMinHeight
|
||||||
|
import eu.kanade.presentation.more.settings.widget.TextPreferenceWidget
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import tachiyomi.presentation.core.components.material.padding
|
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -18,42 +35,92 @@ fun DuplicateMangaDialog(
|
|||||||
onDismissRequest: () -> Unit,
|
onDismissRequest: () -> Unit,
|
||||||
onConfirm: () -> Unit,
|
onConfirm: () -> Unit,
|
||||||
onOpenManga: () -> Unit,
|
onOpenManga: () -> Unit,
|
||||||
|
onMigrate: () -> Unit,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
AlertDialog(
|
val minHeight = LocalPreferenceMinHeight.current
|
||||||
|
|
||||||
|
AdaptiveSheet(
|
||||||
|
modifier = modifier,
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
title = {
|
|
||||||
Text(text = stringResource(MR.strings.are_you_sure))
|
|
||||||
},
|
|
||||||
text = {
|
|
||||||
Text(text = stringResource(MR.strings.confirm_add_duplicate_manga))
|
|
||||||
},
|
|
||||||
confirmButton = {
|
|
||||||
FlowRow(
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.extraSmall),
|
|
||||||
) {
|
) {
|
||||||
TextButton(
|
Column(
|
||||||
onClick = {
|
modifier = Modifier
|
||||||
|
.padding(
|
||||||
|
vertical = TabbedDialogPaddings.Vertical,
|
||||||
|
horizontal = TabbedDialogPaddings.Horizontal,
|
||||||
|
)
|
||||||
|
.fillMaxWidth(),
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.padding(TitlePadding),
|
||||||
|
text = stringResource(MR.strings.are_you_sure),
|
||||||
|
style = MaterialTheme.typography.headlineMedium,
|
||||||
|
)
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = stringResource(MR.strings.confirm_add_duplicate_manga),
|
||||||
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(Modifier.height(PaddingSize))
|
||||||
|
|
||||||
|
TextPreferenceWidget(
|
||||||
|
title = stringResource(MR.strings.action_show_manga),
|
||||||
|
icon = Icons.Outlined.Book,
|
||||||
|
onPreferenceClick = {
|
||||||
onDismissRequest()
|
onDismissRequest()
|
||||||
onOpenManga()
|
onOpenManga()
|
||||||
},
|
},
|
||||||
) {
|
)
|
||||||
Text(text = stringResource(MR.strings.action_show_manga))
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
HorizontalDivider()
|
||||||
|
|
||||||
TextButton(onClick = onDismissRequest) {
|
TextPreferenceWidget(
|
||||||
Text(text = stringResource(MR.strings.action_cancel))
|
title = stringResource(MR.strings.action_migrate_duplicate),
|
||||||
}
|
icon = Icons.Outlined.SwapVert,
|
||||||
TextButton(
|
onPreferenceClick = {
|
||||||
onClick = {
|
onDismissRequest()
|
||||||
|
onMigrate()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
HorizontalDivider()
|
||||||
|
|
||||||
|
TextPreferenceWidget(
|
||||||
|
title = stringResource(MR.strings.action_add_anyway),
|
||||||
|
icon = Icons.Outlined.Add,
|
||||||
|
onPreferenceClick = {
|
||||||
onDismissRequest()
|
onDismissRequest()
|
||||||
onConfirm()
|
onConfirm()
|
||||||
},
|
},
|
||||||
) {
|
|
||||||
Text(text = stringResource(MR.strings.action_add))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.sizeIn(minHeight = minHeight)
|
||||||
|
.clickable { onDismissRequest.invoke() }
|
||||||
|
.padding(ButtonPadding)
|
||||||
|
.fillMaxWidth(),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
) {
|
||||||
|
OutlinedButton(onClick = onDismissRequest, modifier = Modifier.fillMaxWidth()) {
|
||||||
|
Text(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(vertical = 8.dp),
|
||||||
|
text = stringResource(MR.strings.action_cancel),
|
||||||
|
color = MaterialTheme.colorScheme.primary,
|
||||||
|
style = MaterialTheme.typography.titleLarge,
|
||||||
|
fontSize = 16.sp,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val PaddingSize = 16.dp
|
||||||
|
|
||||||
|
private val ButtonPadding = PaddingValues(top = 16.dp, bottom = 16.dp)
|
||||||
|
private val TitlePadding = PaddingValues(bottom = 16.dp, top = 8.dp)
|
||||||
|
@ -46,9 +46,15 @@ import tachiyomi.i18n.sy.SYMR
|
|||||||
import tachiyomi.presentation.core.components.material.ExtendedFloatingActionButton
|
import tachiyomi.presentation.core.components.material.ExtendedFloatingActionButton
|
||||||
import tachiyomi.presentation.core.components.material.Scaffold
|
import tachiyomi.presentation.core.components.material.Scaffold
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
|
import java.io.Serializable
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
class PreMigrationScreen(val mangaIds: List<Long>) : Screen() {
|
sealed class MigrationType : Serializable {
|
||||||
|
data class MangaList(val mangaIds: List<Long>) : MigrationType()
|
||||||
|
data class MangaSingle(val fromMangaId: Long, val toManga: Long?) : MigrationType()
|
||||||
|
}
|
||||||
|
|
||||||
|
class PreMigrationScreen(val migration: MigrationType) : Screen() {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val screenModel = rememberScreenModel { PreMigrationScreenModel() }
|
val screenModel = rememberScreenModel { PreMigrationScreenModel() }
|
||||||
@ -173,7 +179,7 @@ class PreMigrationScreen(val mangaIds: List<Long>) : Screen() {
|
|||||||
screenModel.onMigrationSheet(false)
|
screenModel.onMigrationSheet(false)
|
||||||
screenModel.saveEnabledSources()
|
screenModel.saveEnabledSources()
|
||||||
|
|
||||||
navigator replace MigrationListScreen(MigrationProcedureConfig(mangaIds, extraParam))
|
navigator replace MigrationListScreen(MigrationProcedureConfig(migration, extraParam))
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -184,10 +190,22 @@ class PreMigrationScreen(val mangaIds: List<Long>) : Screen() {
|
|||||||
navigator.push(
|
navigator.push(
|
||||||
if (skipPre) {
|
if (skipPre) {
|
||||||
MigrationListScreen(
|
MigrationListScreen(
|
||||||
MigrationProcedureConfig(mangaIds, null),
|
MigrationProcedureConfig(MigrationType.MangaList(mangaIds), null),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
PreMigrationScreen(mangaIds)
|
PreMigrationScreen(MigrationType.MangaList(mangaIds))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun navigateToMigration(skipPre: Boolean, navigator: Navigator, fromMangaId: Long, toManga: Long?) {
|
||||||
|
navigator.push(
|
||||||
|
if (skipPre) {
|
||||||
|
MigrationListScreen(
|
||||||
|
MigrationProcedureConfig(MigrationType.MangaSingle(fromMangaId, toManga), null),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
PreMigrationScreen(MigrationType.MangaSingle(fromMangaId, toManga))
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ import eu.kanade.tachiyomi.source.CatalogueSource
|
|||||||
import eu.kanade.tachiyomi.source.getNameForMangaInfo
|
import eu.kanade.tachiyomi.source.getNameForMangaInfo
|
||||||
import eu.kanade.tachiyomi.source.online.all.EHentai
|
import eu.kanade.tachiyomi.source.online.all.EHentai
|
||||||
import eu.kanade.tachiyomi.ui.browse.migration.MigrationFlags
|
import eu.kanade.tachiyomi.ui.browse.migration.MigrationFlags
|
||||||
|
import eu.kanade.tachiyomi.ui.browse.migration.advanced.design.MigrationType
|
||||||
import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigratingManga.SearchResult
|
import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigratingManga.SearchResult
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import exh.eh.EHentaiThrottleManager
|
import exh.eh.EHentaiThrottleManager
|
||||||
@ -104,8 +105,14 @@ class MigrationListScreenModel(
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
screenModelScope.launchIO {
|
screenModelScope.launchIO {
|
||||||
|
val mangaIds = when (val migration = config.migration) {
|
||||||
|
is MigrationType.MangaList -> {
|
||||||
|
migration.mangaIds
|
||||||
|
}
|
||||||
|
is MigrationType.MangaSingle -> listOf(migration.fromMangaId)
|
||||||
|
}
|
||||||
runMigrations(
|
runMigrations(
|
||||||
config.mangaIds
|
mangaIds
|
||||||
.map {
|
.map {
|
||||||
async {
|
async {
|
||||||
val manga = getManga.await(it) ?: return@async null
|
val manga = getManga.await(it) ?: return@async null
|
||||||
@ -161,9 +168,13 @@ class MigrationListScreenModel(
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
// in case it was removed
|
// in case it was removed
|
||||||
if (manga.manga.id !in config.mangaIds) {
|
when (val migration = config.migration) {
|
||||||
|
is MigrationType.MangaList -> if (manga.manga.id !in migration.mangaIds) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
else -> Unit
|
||||||
|
}
|
||||||
|
|
||||||
if (manga.searchResult.value == SearchResult.Searching && manga.migrationScope.isActive) {
|
if (manga.searchResult.value == SearchResult.Searching && manga.migrationScope.isActive) {
|
||||||
val mangaObj = manga.manga
|
val mangaObj = manga.manga
|
||||||
val mangaSource = sourceManager.getOrStub(mangaObj.source)
|
val mangaSource = sourceManager.getOrStub(mangaObj.source)
|
||||||
@ -175,6 +186,28 @@ class MigrationListScreenModel(
|
|||||||
} else {
|
} else {
|
||||||
sources.filter { it.id != mangaSource.id }
|
sources.filter { it.id != mangaSource.id }
|
||||||
}
|
}
|
||||||
|
when (val migration = config.migration) {
|
||||||
|
is MigrationType.MangaSingle -> if (migration.toManga != null) {
|
||||||
|
val localManga = getManga.await(migration.toManga)
|
||||||
|
if (localManga != null) {
|
||||||
|
val source = sourceManager.get(localManga.source) as? CatalogueSource
|
||||||
|
if (source != null) {
|
||||||
|
val chapters = if (source is EHentai) {
|
||||||
|
source.getChapterList(localManga.toSManga(), throttleManager::throttle)
|
||||||
|
} else {
|
||||||
|
source.getChapterList(localManga.toSManga())
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
syncChaptersWithSource.await(chapters, localManga, source)
|
||||||
|
} catch (_: Exception) {
|
||||||
|
}
|
||||||
|
manga.progress.value = validSources.size to validSources.size
|
||||||
|
return@async localManga
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> Unit
|
||||||
|
}
|
||||||
if (useSourceWithMost) {
|
if (useSourceWithMost) {
|
||||||
val sourceSemaphore = Semaphore(3)
|
val sourceSemaphore = Semaphore(3)
|
||||||
val processedSources = AtomicInteger()
|
val processedSources = AtomicInteger()
|
||||||
@ -523,15 +556,20 @@ class MigrationListScreenModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun removeManga(item: MigratingManga) {
|
fun removeManga(item: MigratingManga) {
|
||||||
val ids = config.mangaIds.toMutableList()
|
when (val migration = config.migration) {
|
||||||
|
is MigrationType.MangaList -> {
|
||||||
|
val ids = migration.mangaIds.toMutableList()
|
||||||
val index = ids.indexOf(item.manga.id)
|
val index = ids.indexOf(item.manga.id)
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
ids.removeAt(index)
|
ids.removeAt(index)
|
||||||
config.mangaIds = ids
|
config.migration = MigrationType.MangaList(ids)
|
||||||
val index2 = migratingItems.value.orEmpty().indexOf(item)
|
val index2 = migratingItems.value.orEmpty().indexOf(item)
|
||||||
if (index2 > -1) migratingItems.value = (migratingItems.value.orEmpty() - item).toImmutableList()
|
if (index2 > -1) migratingItems.value = (migratingItems.value.orEmpty() - item).toImmutableList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
is MigrationType.MangaSingle -> Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onDispose() {
|
override fun onDispose() {
|
||||||
super.onDispose()
|
super.onDispose()
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
package eu.kanade.tachiyomi.ui.browse.migration.advanced.process
|
package eu.kanade.tachiyomi.ui.browse.migration.advanced.process
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.ui.browse.migration.advanced.design.MigrationType
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
||||||
data class MigrationProcedureConfig(
|
data class MigrationProcedureConfig(
|
||||||
var mangaIds: List<Long>,
|
var migration: MigrationType,
|
||||||
val extraSearchParams: String?,
|
val extraSearchParams: String?,
|
||||||
) : Serializable
|
) : Serializable
|
||||||
|
@ -49,6 +49,7 @@ import eu.kanade.presentation.util.Screen
|
|||||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.ui.browse.extension.details.SourcePreferencesScreen
|
import eu.kanade.tachiyomi.ui.browse.extension.details.SourcePreferencesScreen
|
||||||
|
import eu.kanade.tachiyomi.ui.browse.migration.advanced.design.PreMigrationScreen
|
||||||
import eu.kanade.tachiyomi.ui.browse.source.SourcesScreen
|
import eu.kanade.tachiyomi.ui.browse.source.SourcesScreen
|
||||||
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreenModel.Listing
|
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreenModel.Listing
|
||||||
import eu.kanade.tachiyomi.ui.category.CategoryScreen
|
import eu.kanade.tachiyomi.ui.category.CategoryScreen
|
||||||
@ -62,6 +63,7 @@ import kotlinx.coroutines.flow.collectLatest
|
|||||||
import kotlinx.coroutines.flow.receiveAsFlow
|
import kotlinx.coroutines.flow.receiveAsFlow
|
||||||
import tachiyomi.core.common.Constants
|
import tachiyomi.core.common.Constants
|
||||||
import tachiyomi.core.common.util.lang.launchIO
|
import tachiyomi.core.common.util.lang.launchIO
|
||||||
|
import tachiyomi.domain.UnsortedPreferences
|
||||||
import tachiyomi.domain.source.model.StubSource
|
import tachiyomi.domain.source.model.StubSource
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import tachiyomi.presentation.core.components.material.Scaffold
|
import tachiyomi.presentation.core.components.material.Scaffold
|
||||||
@ -69,6 +71,8 @@ import tachiyomi.presentation.core.components.material.padding
|
|||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
import tachiyomi.presentation.core.screens.LoadingScreen
|
import tachiyomi.presentation.core.screens.LoadingScreen
|
||||||
import tachiyomi.source.local.LocalSource
|
import tachiyomi.source.local.LocalSource
|
||||||
|
import uy.kohesive.injekt.Injekt
|
||||||
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
data class BrowseSourceScreen(
|
data class BrowseSourceScreen(
|
||||||
private val sourceId: Long,
|
private val sourceId: Long,
|
||||||
@ -319,6 +323,16 @@ data class BrowseSourceScreen(
|
|||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
onConfirm = { screenModel.addFavorite(dialog.manga) },
|
onConfirm = { screenModel.addFavorite(dialog.manga) },
|
||||||
onOpenManga = { navigator.push(MangaScreen(dialog.duplicate.id)) },
|
onOpenManga = { navigator.push(MangaScreen(dialog.duplicate.id)) },
|
||||||
|
onMigrate = {
|
||||||
|
// SY -->
|
||||||
|
PreMigrationScreen.navigateToMigration(
|
||||||
|
Injekt.get<UnsortedPreferences>().skipPreMigration().get(),
|
||||||
|
navigator,
|
||||||
|
dialog.duplicate.id,
|
||||||
|
dialog.manga.id,
|
||||||
|
)
|
||||||
|
// SY <--
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is BrowseSourceScreenModel.Dialog.RemoveManga -> {
|
is BrowseSourceScreenModel.Dialog.RemoveManga -> {
|
||||||
|
@ -455,7 +455,7 @@ open class BrowseSourceScreenModel(
|
|||||||
val manga: Manga,
|
val manga: Manga,
|
||||||
val initialSelection: ImmutableList<CheckboxState.State<Category>>,
|
val initialSelection: ImmutableList<CheckboxState.State<Category>>,
|
||||||
) : Dialog
|
) : Dialog
|
||||||
data class Migrate(val newManga: Manga) : Dialog
|
data class Migrate(val newManga: Manga, val oldManga: Manga) : Dialog
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
data class DeleteSavedSearch(val idToDelete: Long, val name: String) : Dialog
|
data class DeleteSavedSearch(val idToDelete: Long, val name: String) : Dialog
|
||||||
|
@ -251,11 +251,19 @@ class MangaScreen(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is MangaScreenModel.Dialog.DuplicateManga -> DuplicateMangaDialog(
|
|
||||||
|
is MangaScreenModel.Dialog.DuplicateManga -> {
|
||||||
|
DuplicateMangaDialog(
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
onConfirm = { screenModel.toggleFavorite(onRemoved = {}, checkDuplicate = false) },
|
onConfirm = { screenModel.toggleFavorite(onRemoved = {}, checkDuplicate = false) },
|
||||||
onOpenManga = { navigator.push(MangaScreen(dialog.duplicate.id)) },
|
onOpenManga = { navigator.push(MangaScreen(dialog.duplicate.id)) },
|
||||||
|
onMigrate = {
|
||||||
|
// SY -->
|
||||||
|
migrateManga(navigator, dialog.duplicate, screenModel.manga!!.id)
|
||||||
|
// SY <--
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
}
|
||||||
MangaScreenModel.Dialog.SettingsSheet -> ChapterSettingsDialog(
|
MangaScreenModel.Dialog.SettingsSheet -> ChapterSettingsDialog(
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
manga = successState.manga,
|
manga = successState.manga,
|
||||||
@ -457,12 +465,13 @@ class MangaScreen(
|
|||||||
/**
|
/**
|
||||||
* Initiates source migration for the specific manga.
|
* Initiates source migration for the specific manga.
|
||||||
*/
|
*/
|
||||||
private fun migrateManga(navigator: Navigator, manga: Manga) {
|
private fun migrateManga(navigator: Navigator, manga: Manga, toMangaId: Long? = null) {
|
||||||
// SY -->
|
// SY -->
|
||||||
PreMigrationScreen.navigateToMigration(
|
PreMigrationScreen.navigateToMigration(
|
||||||
Injekt.get<UnsortedPreferences>().skipPreMigration().get(),
|
Injekt.get<UnsortedPreferences>().skipPreMigration().get(),
|
||||||
navigator,
|
navigator,
|
||||||
listOf(manga.id),
|
manga.id,
|
||||||
|
toMangaId,
|
||||||
)
|
)
|
||||||
// SY <--
|
// SY <--
|
||||||
}
|
}
|
||||||
|
@ -1548,6 +1548,9 @@ class MangaScreenModel(
|
|||||||
) : Dialog
|
) : Dialog
|
||||||
data class DeleteChapters(val chapters: List<Chapter>) : Dialog
|
data class DeleteChapters(val chapters: List<Chapter>) : Dialog
|
||||||
data class DuplicateManga(val manga: Manga, val duplicate: Manga) : Dialog
|
data class DuplicateManga(val manga: Manga, val duplicate: Manga) : Dialog
|
||||||
|
/* SY -->
|
||||||
|
data class Migrate(val newManga: Manga, val oldManga: Manga) : Dialog
|
||||||
|
SY <-- */
|
||||||
data class SetFetchInterval(val manga: Manga) : Dialog
|
data class SetFetchInterval(val manga: Manga) : Dialog
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
@ -1580,6 +1583,12 @@ class MangaScreenModel(
|
|||||||
updateSuccessState { it.copy(dialog = Dialog.FullCover) }
|
updateSuccessState { it.copy(dialog = Dialog.FullCover) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* SY -->
|
||||||
|
fun showMigrateDialog(duplicate: Manga) {
|
||||||
|
val manga = successState?.manga ?: return
|
||||||
|
updateSuccessState { it.copy(dialog = Dialog.Migrate(newManga = manga, oldManga = duplicate)) }
|
||||||
|
} SY <-- */
|
||||||
|
|
||||||
fun setExcludedScanlators(excludedScanlators: Set<String>) {
|
fun setExcludedScanlators(excludedScanlators: Set<String>) {
|
||||||
screenModelScope.launchIO {
|
screenModelScope.launchIO {
|
||||||
setExcludedScanlators.await(mangaId, excludedScanlators)
|
setExcludedScanlators.await(mangaId, excludedScanlators)
|
||||||
|
@ -20,15 +20,19 @@ import eu.kanade.presentation.browse.components.RemoveMangaDialog
|
|||||||
import eu.kanade.presentation.category.components.ChangeCategoryDialog
|
import eu.kanade.presentation.category.components.ChangeCategoryDialog
|
||||||
import eu.kanade.presentation.manga.DuplicateMangaDialog
|
import eu.kanade.presentation.manga.DuplicateMangaDialog
|
||||||
import eu.kanade.presentation.util.Screen
|
import eu.kanade.presentation.util.Screen
|
||||||
|
import eu.kanade.tachiyomi.ui.browse.migration.advanced.design.PreMigrationScreen
|
||||||
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreenModel
|
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreenModel
|
||||||
import eu.kanade.tachiyomi.ui.category.CategoryScreen
|
import eu.kanade.tachiyomi.ui.category.CategoryScreen
|
||||||
import eu.kanade.tachiyomi.ui.manga.MangaScreen
|
import eu.kanade.tachiyomi.ui.manga.MangaScreen
|
||||||
import exh.ui.ifSourcesLoaded
|
import exh.ui.ifSourcesLoaded
|
||||||
import tachiyomi.core.common.util.lang.launchIO
|
import tachiyomi.core.common.util.lang.launchIO
|
||||||
|
import tachiyomi.domain.UnsortedPreferences
|
||||||
import tachiyomi.i18n.sy.SYMR
|
import tachiyomi.i18n.sy.SYMR
|
||||||
import tachiyomi.presentation.core.components.material.Scaffold
|
import tachiyomi.presentation.core.components.material.Scaffold
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
import tachiyomi.presentation.core.screens.LoadingScreen
|
import tachiyomi.presentation.core.screens.LoadingScreen
|
||||||
|
import uy.kohesive.injekt.Injekt
|
||||||
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
class MangaDexFollowsScreen(private val sourceId: Long) : Screen() {
|
class MangaDexFollowsScreen(private val sourceId: Long) : Screen() {
|
||||||
|
|
||||||
@ -104,6 +108,14 @@ class MangaDexFollowsScreen(private val sourceId: Long) : Screen() {
|
|||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
onConfirm = { screenModel.addFavorite(dialog.manga) },
|
onConfirm = { screenModel.addFavorite(dialog.manga) },
|
||||||
onOpenManga = { navigator.push(MangaScreen(dialog.duplicate.id)) },
|
onOpenManga = { navigator.push(MangaScreen(dialog.duplicate.id)) },
|
||||||
|
onMigrate = {
|
||||||
|
PreMigrationScreen.navigateToMigration(
|
||||||
|
Injekt.get<UnsortedPreferences>().skipPreMigration().get(),
|
||||||
|
navigator,
|
||||||
|
dialog.duplicate.id,
|
||||||
|
dialog.manga.id,
|
||||||
|
)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is BrowseSourceScreenModel.Dialog.RemoveManga -> {
|
is BrowseSourceScreenModel.Dialog.RemoveManga -> {
|
||||||
|
@ -162,6 +162,8 @@
|
|||||||
<string name="action_webview_refresh">Refresh</string>
|
<string name="action_webview_refresh">Refresh</string>
|
||||||
<string name="action_start_downloading_now">Start downloading now</string>
|
<string name="action_start_downloading_now">Start downloading now</string>
|
||||||
<string name="action_not_now">Not now</string>
|
<string name="action_not_now">Not now</string>
|
||||||
|
<string name="action_add_anyway">Add anyway</string>
|
||||||
|
<string name="action_migrate_duplicate">Migrate existing entry</string>
|
||||||
|
|
||||||
<!-- Operations -->
|
<!-- Operations -->
|
||||||
<string name="loading">Loading…</string>
|
<string name="loading">Loading…</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user