Added option to migrate manga from manga details
(cherry picked from commit 3a4780e19b79e9afcb3e830cb02c52bd1c66bddf)
This commit is contained in:
parent
f47e9b6e14
commit
18f90587f2
@ -37,10 +37,7 @@ import eu.kanade.tachiyomi.ui.main.MainActivity
|
|||||||
import eu.kanade.tachiyomi.ui.main.offsetFabAppbarHeight
|
import eu.kanade.tachiyomi.ui.main.offsetFabAppbarHeight
|
||||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||||
import eu.kanade.tachiyomi.ui.migration.MigrationController
|
import eu.kanade.tachiyomi.ui.migration.MigrationController
|
||||||
import eu.kanade.tachiyomi.ui.migration.MigrationInterface
|
|
||||||
import eu.kanade.tachiyomi.ui.migration.manga.design.PreMigrationController
|
import eu.kanade.tachiyomi.ui.migration.manga.design.PreMigrationController
|
||||||
import eu.kanade.tachiyomi.ui.migration.manga.process.MigrationListController
|
|
||||||
import eu.kanade.tachiyomi.ui.migration.manga.process.MigrationProcedureConfig
|
|
||||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import eu.kanade.tachiyomi.util.view.inflate
|
import eu.kanade.tachiyomi.util.view.inflate
|
||||||
@ -68,8 +65,7 @@ class LibraryController(
|
|||||||
TabbedController,
|
TabbedController,
|
||||||
ActionMode.Callback,
|
ActionMode.Callback,
|
||||||
ChangeMangaCategoriesDialog.Listener,
|
ChangeMangaCategoriesDialog.Listener,
|
||||||
DeleteLibraryMangasDialog.Listener,
|
DeleteLibraryMangasDialog.Listener {
|
||||||
MigrationInterface {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Position of the active category.
|
* Position of the active category.
|
||||||
@ -486,16 +482,8 @@ class LibraryController(
|
|||||||
R.id.action_select_all -> selectAllCategoryManga()
|
R.id.action_select_all -> selectAllCategoryManga()
|
||||||
R.id.action_select_inverse -> selectInverseCategoryManga()
|
R.id.action_select_inverse -> selectInverseCategoryManga()
|
||||||
R.id.action_migrate -> {
|
R.id.action_migrate -> {
|
||||||
router.pushController(
|
val skipPre = preferences.skipPreMigration().getOrDefault()
|
||||||
if (preferences.skipPreMigration().getOrDefault()) {
|
PreMigrationController.navigateToMigration(skipPre, router, selectedMangas.mapNotNull { it.id })
|
||||||
MigrationListController.create(
|
|
||||||
MigrationProcedureConfig(
|
|
||||||
selectedMangas.mapNotNull { it.id }, null)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
PreMigrationController.create(selectedMangas.mapNotNull { it.id })
|
|
||||||
}
|
|
||||||
.withFadeTransaction())
|
|
||||||
destroyActionModeIfNeeded()
|
destroyActionModeIfNeeded()
|
||||||
}
|
}
|
||||||
else -> return false
|
else -> return false
|
||||||
@ -503,15 +491,6 @@ class LibraryController(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun migrateManga(prevManga: Manga, manga: Manga, replace: Boolean): Manga? {
|
|
||||||
if (manga.id != prevManga.id) {
|
|
||||||
presenter.migrateManga(prevManga, manga, replace = replace)
|
|
||||||
}
|
|
||||||
val nextManga = migratingMangas.firstOrNull() ?: return null
|
|
||||||
migratingMangas.remove(nextManga)
|
|
||||||
return nextManga
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyActionMode(mode: ActionMode?) {
|
override fun onDestroyActionMode(mode: ActionMode?) {
|
||||||
// Clear all the manga selections and notify child views.
|
// Clear all the manga selections and notify child views.
|
||||||
selectedMangas.clear()
|
selectedMangas.clear()
|
||||||
|
@ -30,6 +30,10 @@ import eu.kanade.tachiyomi.ui.main.MainActivity
|
|||||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||||
import eu.kanade.tachiyomi.ui.recent.history.HistoryController
|
import eu.kanade.tachiyomi.ui.recent.history.HistoryController
|
||||||
import eu.kanade.tachiyomi.ui.recent.updates.UpdatesController
|
import eu.kanade.tachiyomi.ui.recent.updates.UpdatesController
|
||||||
|
import eu.kanade.tachiyomi.ui.migration.manga.design.PreMigrationController
|
||||||
|
import eu.kanade.tachiyomi.ui.source.SourceController
|
||||||
|
import eu.kanade.tachiyomi.ui.source.browse.BrowseSourceController
|
||||||
|
import eu.kanade.tachiyomi.ui.source.global_search.GlobalSearchController
|
||||||
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
||||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
@ -219,6 +223,16 @@ class MangaInfoController(private val fromSource: Boolean = false) :
|
|||||||
// EXH <--
|
// EXH <--
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EXH -->
|
||||||
|
private fun openSmartSearch() {
|
||||||
|
val smartSearchConfig = SourceController.SmartSearchConfig(presenter.manga.title, presenter.manga.id!!)
|
||||||
|
|
||||||
|
parentController?.router?.pushController(SourceController(Bundle().apply {
|
||||||
|
putParcelable(SourceController.SMART_SEARCH_CONFIG, smartSearchConfig)
|
||||||
|
}).withFadeTransaction())
|
||||||
|
}
|
||||||
|
// EXH <--
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if manga is initialized.
|
* Check if manga is initialized.
|
||||||
* If true update view with manga information,
|
* If true update view with manga information,
|
||||||
|
@ -6,6 +6,7 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.bluelinelabs.conductor.Router
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
@ -151,6 +152,18 @@ class PreMigrationController(bundle: Bundle? = null) : BaseController(bundle), F
|
|||||||
companion object {
|
companion object {
|
||||||
private const val MANGA_IDS_EXTRA = "manga_ids"
|
private const val MANGA_IDS_EXTRA = "manga_ids"
|
||||||
|
|
||||||
|
fun navigateToMigration(skipPre: Boolean, router: Router, mangaIds: List<Long>) {
|
||||||
|
router.pushController(
|
||||||
|
if (skipPre) {
|
||||||
|
MigrationListController.create(
|
||||||
|
MigrationProcedureConfig(mangaIds, null)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
create(mangaIds)
|
||||||
|
}.withFadeTransaction().tag(if (skipPre) MigrationListController.TAG else null)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun create(mangaIds: List<Long>): PreMigrationController {
|
fun create(mangaIds: List<Long>): PreMigrationController {
|
||||||
return PreMigrationController(Bundle().apply {
|
return PreMigrationController(Bundle().apply {
|
||||||
putLongArray(MANGA_IDS_EXTRA, mangaIds.toLongArray())
|
putLongArray(MANGA_IDS_EXTRA, mangaIds.toLongArray())
|
||||||
|
@ -14,6 +14,7 @@ import androidx.core.graphics.ColorUtils
|
|||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat
|
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat
|
||||||
import com.afollestad.materialdialogs.MaterialDialog
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
|
import com.bluelinelabs.conductor.changehandler.FadeChangeHandler
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
@ -26,11 +27,14 @@ import eu.kanade.tachiyomi.source.SourceManager
|
|||||||
import eu.kanade.tachiyomi.source.model.SChapter
|
import eu.kanade.tachiyomi.source.model.SChapter
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.BaseController
|
import eu.kanade.tachiyomi.ui.base.controller.BaseController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||||
|
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||||
import eu.kanade.tachiyomi.ui.migration.MigrationMangaDialog
|
import eu.kanade.tachiyomi.ui.migration.MigrationMangaDialog
|
||||||
import eu.kanade.tachiyomi.ui.migration.SearchController
|
import eu.kanade.tachiyomi.ui.migration.SearchController
|
||||||
|
import eu.kanade.tachiyomi.ui.migration.manga.design.PreMigrationController
|
||||||
import eu.kanade.tachiyomi.util.await
|
import eu.kanade.tachiyomi.util.await
|
||||||
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
|
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
|
||||||
import eu.kanade.tachiyomi.util.lang.launchUI
|
import eu.kanade.tachiyomi.util.lang.launchUI
|
||||||
|
import eu.kanade.tachiyomi.util.system.executeOnIO
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import eu.kanade.tachiyomi.util.view.RecyclerWindowInsetsListener
|
import eu.kanade.tachiyomi.util.view.RecyclerWindowInsetsListener
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
@ -204,8 +208,7 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
val localManga = smartSearchEngine.networkToLocalManga(searchResult, source.id)
|
val localManga = smartSearchEngine.networkToLocalManga(searchResult, source.id)
|
||||||
val chapters = try {
|
val chapters = try {
|
||||||
source.fetchChapterList(localManga)
|
source.fetchChapterList(localManga)
|
||||||
.toSingle().await(Schedulers.io()) }
|
.toSingle().await(Schedulers.io()) } catch (e: java.lang.Exception) {
|
||||||
catch (e: java.lang.Exception) {
|
|
||||||
Timber.e(e)
|
Timber.e(e)
|
||||||
emptyList<SChapter>()
|
emptyList<SChapter>()
|
||||||
} ?: emptyList()
|
} ?: emptyList()
|
||||||
@ -372,17 +375,40 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
fun migrateMangas() {
|
fun migrateMangas() {
|
||||||
launchUI {
|
launchUI {
|
||||||
adapter?.performMigrations(false)
|
adapter?.performMigrations(false)
|
||||||
router.popCurrentController()
|
navigateOut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun copyMangas() {
|
fun copyMangas() {
|
||||||
launchUI {
|
launchUI {
|
||||||
adapter?.performMigrations(true)
|
adapter?.performMigrations(true)
|
||||||
router.popCurrentController()
|
navigateOut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun navigateOut() {
|
||||||
|
if (migratingManga?.size == 1) {
|
||||||
|
launchUI {
|
||||||
|
val hasDetails = router.backstack.any { it.controller() is MangaController }
|
||||||
|
if (hasDetails) {
|
||||||
|
val manga = migratingManga?.firstOrNull()?.searchResult?.get()?.let {
|
||||||
|
db.getManga(it).executeOnIO()
|
||||||
|
}
|
||||||
|
if (manga != null) {
|
||||||
|
val newStack = router.backstack.filter {
|
||||||
|
it.controller() !is MangaController &&
|
||||||
|
it.controller() !is MigrationListController &&
|
||||||
|
it.controller() !is PreMigrationController
|
||||||
|
} + MangaController(manga).withFadeTransaction()
|
||||||
|
router.setBackstack(newStack, FadeChangeHandler())
|
||||||
|
return@launchUI
|
||||||
|
}
|
||||||
|
}
|
||||||
|
router.popCurrentController()
|
||||||
|
}
|
||||||
|
} else router.popCurrentController()
|
||||||
|
}
|
||||||
|
|
||||||
override fun handleBack(): Boolean {
|
override fun handleBack(): Boolean {
|
||||||
activity?.let {
|
activity?.let {
|
||||||
MaterialDialog.Builder(it).title(R.string.stop_migration)
|
MaterialDialog.Builder(it).title(R.string.stop_migration)
|
||||||
@ -440,6 +466,7 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val CONFIG_EXTRA = "config_extra"
|
const val CONFIG_EXTRA = "config_extra"
|
||||||
|
const val TAG = "migration_list"
|
||||||
|
|
||||||
fun create(config: MigrationProcedureConfig): MigrationListController {
|
fun create(config: MigrationProcedureConfig): MigrationListController {
|
||||||
return MigrationListController(Bundle().apply {
|
return MigrationListController(Bundle().apply {
|
||||||
|
@ -102,8 +102,8 @@ class MigrationProcessAdapter(
|
|||||||
// Update chapters read
|
// Update chapters read
|
||||||
if (MigrationFlags.hasChapters(flags)) {
|
if (MigrationFlags.hasChapters(flags)) {
|
||||||
val prevMangaChapters = db.getChapters(prevManga).executeAsBlocking()
|
val prevMangaChapters = db.getChapters(prevManga).executeAsBlocking()
|
||||||
val maxChapterRead = prevMangaChapters.filter { it.read }
|
val maxChapterRead =
|
||||||
.maxBy { it.chapter_number }?.chapter_number
|
prevMangaChapters.filter { it.read }.maxBy { it.chapter_number }?.chapter_number
|
||||||
if (maxChapterRead != null) {
|
if (maxChapterRead != null) {
|
||||||
val dbChapters = db.getChapters(manga).executeAsBlocking()
|
val dbChapters = db.getChapters(manga).executeAsBlocking()
|
||||||
for (chapter in dbChapters) {
|
for (chapter in dbChapters) {
|
||||||
@ -135,8 +135,6 @@ class MigrationProcessAdapter(
|
|||||||
db.updateMangaFavorite(prevManga).executeAsBlocking()
|
db.updateMangaFavorite(prevManga).executeAsBlocking()
|
||||||
}
|
}
|
||||||
manga.favorite = true
|
manga.favorite = true
|
||||||
db.updateMangaFavorite(manga).executeAsBlocking()
|
|
||||||
|
|
||||||
// SearchPresenter#networkToLocalManga may have updated the manga title, so ensure db gets updated title
|
// SearchPresenter#networkToLocalManga may have updated the manga title, so ensure db gets updated title
|
||||||
db.updateMangaTitle(manga).executeAsBlocking()
|
db.updateMangaTitle(manga).executeAsBlocking()
|
||||||
// }
|
// }
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
package eu.kanade.tachiyomi.util.system
|
||||||
|
|
||||||
|
import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetListOfObjects
|
||||||
|
import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetObject
|
||||||
|
import com.pushtorefresh.storio.sqlite.operations.put.PreparedPutCollectionOfObjects
|
||||||
|
import com.pushtorefresh.storio.sqlite.operations.put.PreparedPutObject
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
suspend fun <T> PreparedGetListOfObjects<T>.executeOnIO(): List<T> {
|
||||||
|
return withContext(Dispatchers.IO) { executeAsBlocking() }
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun <T> PreparedGetObject<T>.executeOnIO(): T? {
|
||||||
|
return withContext(Dispatchers.IO) { executeAsBlocking() }
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun <T> PreparedPutObject<T>.executeOnIO() {
|
||||||
|
withContext(Dispatchers.IO) { executeAsBlocking() }
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun <T> PreparedPutCollectionOfObjects<T>.executeOnIO() {
|
||||||
|
withContext(Dispatchers.IO) { executeAsBlocking() }
|
||||||
|
}
|
@ -573,6 +573,7 @@
|
|||||||
<string name="migration_selection_prompt">Select a source to migrate from</string>
|
<string name="migration_selection_prompt">Select a source to migrate from</string>
|
||||||
<string name="select">Select</string>
|
<string name="select">Select</string>
|
||||||
<string name="migrate">Migrate</string>
|
<string name="migrate">Migrate</string>
|
||||||
|
<string name="migrate_">Migrate %1$s</string>
|
||||||
<string name="copy">Copy</string>
|
<string name="copy">Copy</string>
|
||||||
<string name="migrating">Migrating…</string>
|
<string name="migrating">Migrating…</string>
|
||||||
<string name="migration">Migration</string>
|
<string name="migration">Migration</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user