From 3a4780e19b79e9afcb3e830cb02c52bd1c66bddf Mon Sep 17 00:00:00 2001 From: Jay Date: Sun, 12 Apr 2020 18:53:56 -0400 Subject: [PATCH] Added option to migrate manga from manga details Also copying manga date added to migrated manga --- .../data/database/queries/MangaQueries.kt | 6 ++++ .../resolvers/MangaDateAddedPutResolver.kt | 31 +++++++++++++++++++ .../tachiyomi/ui/library/LibraryController.kt | 12 +------ .../ui/manga/MangaDetailsController.kt | 14 ++++++++- .../ui/migration/MigrationController.kt | 22 ++++--------- .../manga/design/PreMigrationController.kt | 13 ++++++++ .../manga/process/MigrationListController.kt | 31 +++++++++++++++++-- .../manga/process/MigrationProcessAdapter.kt | 11 ++++--- app/src/main/res/menu/manga_details.xml | 6 ++++ app/src/main/res/values/strings.xml | 1 + 10 files changed, 112 insertions(+), 35 deletions(-) create mode 100644 app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaDateAddedPutResolver.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/MangaQueries.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/MangaQueries.kt index 6074cc030e..eac34db9bb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/MangaQueries.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/MangaQueries.kt @@ -7,6 +7,7 @@ import eu.kanade.tachiyomi.data.database.DbProvider import eu.kanade.tachiyomi.data.database.models.LibraryManga import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.resolvers.LibraryMangaGetResolver +import eu.kanade.tachiyomi.data.database.resolvers.MangaDateAddedPutResolver import eu.kanade.tachiyomi.data.database.resolvers.MangaFavoritePutResolver import eu.kanade.tachiyomi.data.database.resolvers.MangaFlagsPutResolver import eu.kanade.tachiyomi.data.database.resolvers.MangaInfoPutResolver @@ -92,6 +93,11 @@ interface MangaQueries : DbProvider { .withPutResolver(MangaFavoritePutResolver()) .prepare() + fun updateMangaAdded(manga: Manga) = db.put() + .`object`(manga) + .withPutResolver(MangaDateAddedPutResolver()) + .prepare() + fun updateMangaViewer(manga: Manga) = db.put() .`object`(manga) .withPutResolver(MangaViewerPutResolver()) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaDateAddedPutResolver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaDateAddedPutResolver.kt new file mode 100644 index 0000000000..27a51b3046 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaDateAddedPutResolver.kt @@ -0,0 +1,31 @@ +package eu.kanade.tachiyomi.data.database.resolvers + +import android.content.ContentValues +import com.pushtorefresh.storio.sqlite.StorIOSQLite +import com.pushtorefresh.storio.sqlite.operations.put.PutResolver +import com.pushtorefresh.storio.sqlite.operations.put.PutResult +import com.pushtorefresh.storio.sqlite.queries.UpdateQuery +import eu.kanade.tachiyomi.data.database.inTransactionReturn +import eu.kanade.tachiyomi.data.database.models.Manga +import eu.kanade.tachiyomi.data.database.tables.MangaTable + +class MangaDateAddedPutResolver : PutResolver() { + + override fun performPut(db: StorIOSQLite, manga: Manga) = db.inTransactionReturn { + val updateQuery = mapToUpdateQuery(manga) + val contentValues = mapToContentValues(manga) + + val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues) + PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table()) + } + + fun mapToUpdateQuery(manga: Manga) = UpdateQuery.builder() + .table(MangaTable.TABLE) + .where("${MangaTable.COL_ID} = ?") + .whereArgs(manga.id) + .build() + + fun mapToContentValues(manga: Manga) = ContentValues(1).apply { + put(MangaTable.COL_DATE_ADDED, manga.date_added) + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt index 5e7fe6bdbe..4ef7a1e185 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt @@ -52,8 +52,6 @@ import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.main.RootSearchInterface import eu.kanade.tachiyomi.ui.manga.MangaDetailsController 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.ui.reader.ReaderActivity import eu.kanade.tachiyomi.util.system.dpToPx import eu.kanade.tachiyomi.util.system.getResourceColor @@ -893,15 +891,7 @@ class LibraryController( } R.id.action_migrate -> { val skipPre = preferences.skipPreMigration().getOrDefault() - router.pushController( - if (skipPre) { - MigrationListController.create( - MigrationProcedureConfig(selectedMangas.mapNotNull { it.id }, null) - ) - } else { - PreMigrationController.create(selectedMangas.mapNotNull { it.id }) - }.withFadeTransaction().tag(if (skipPre) MigrationListController.TAG else null) - ) + PreMigrationController.navigateToMigration(skipPre, router, selectedMangas.mapNotNull { it.id }) destroyActionModeIfNeeded() } else -> return false diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaDetailsController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaDetailsController.kt index a4d6e85798..5777bcb818 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaDetailsController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaDetailsController.kt @@ -71,6 +71,7 @@ import eu.kanade.tachiyomi.data.download.DownloadService import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.glide.GlideApp import eu.kanade.tachiyomi.data.notification.NotificationReceiver +import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.source.Source @@ -89,6 +90,7 @@ import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersSortBottomSheet import eu.kanade.tachiyomi.ui.manga.track.TrackItem import eu.kanade.tachiyomi.ui.manga.track.TrackingBottomSheet +import eu.kanade.tachiyomi.ui.migration.manga.design.PreMigrationController import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate import eu.kanade.tachiyomi.ui.webview.WebViewActivity @@ -690,10 +692,15 @@ class MangaDetailsController : BaseController, menu.findItem(R.id.action_mark_all_as_unread).isVisible = !presenter.allUnread() && !presenter.isLockedFromSearch menu.findItem(R.id.action_remove_downloads).isVisible = - presenter.hasDownloads() && !presenter.isLockedFromSearch + presenter.hasDownloads() && !presenter.isLockedFromSearch && + manga?.source != LocalSource.ID menu.findItem(R.id.remove_non_bookmarked).isVisible = presenter.hasBookmark() && !presenter.isLockedFromSearch menu.findItem(R.id.action_mark_all_as_unread).isVisible = presenter.isTracked() + menu.findItem(R.id.action_migrate).isVisible = !presenter.isLockedFromSearch && + manga?.source != LocalSource.ID && presenter.manga.favorite + menu.findItem(R.id.action_migrate).title = view?.context?.getString(R.string.migrate_, + presenter.manga.mangaType(view!!.context)) val iconPrimary = view?.context?.getResourceColor(android.R.attr.textColorPrimary) ?: Color.BLACK menu.findItem(R.id.action_download).icon?.mutate()?.setTint(iconPrimary) @@ -753,6 +760,11 @@ class MangaDetailsController : BaseController, R.id.action_open_in_web_view -> openInWebView() R.id.action_add_to_home_screen -> addToHomeScreen() R.id.action_refresh_tracking -> presenter.refreshTrackers() + R.id.action_migrate -> + PreMigrationController.navigateToMigration( + presenter.preferences.skipPreMigration().getOrDefault(), + router, + listOf(manga!!.id!!)) R.id.action_mark_all_as_read -> { MaterialDialog(view!!.context).message(R.string.mark_all_chapters_as_read) .positiveButton(R.string.mark_as_read) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/MigrationController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/MigrationController.kt index 5dd5f4bddd..d2a39e4bfd 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/MigrationController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/MigrationController.kt @@ -11,10 +11,7 @@ import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.ui.base.controller.NucleusController -import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction 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.await import eu.kanade.tachiyomi.util.system.launchUI import eu.kanade.tachiyomi.util.view.RecyclerWindowInsetsListener @@ -111,10 +108,9 @@ class MigrationController : NucleusController(), val item = adapter?.getItem(position) ?: return false if (item is MangaItem) { - val controller = PreMigrationController.create(listOf(item.manga.id!!)) - controller.targetController = this - - router.pushController(controller.withFadeTransaction()) + PreMigrationController.navigateToMigration(Injekt.get().skipPreMigration().getOrDefault(), + router, + listOf(item.manga.id!!)) } else if (item is SourceItem) { presenter.setSelectedSource(item.source) } @@ -135,15 +131,9 @@ class MigrationController : NucleusController(), val sourceMangas = manga.asSequence().filter { it.source == item.source.id }.map { it.id!! }.toList() withContext(Dispatchers.Main) { - router.pushController( - if (Injekt.get().skipPreMigration().getOrDefault()) { - MigrationListController.create( - MigrationProcedureConfig(sourceMangas, null) - ) - } else { - PreMigrationController.create(sourceMangas) - }.withFadeTransaction() - ) + PreMigrationController.navigateToMigration(Injekt.get().skipPreMigration().getOrDefault(), + router, + sourceMangas) } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/design/PreMigrationController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/design/PreMigrationController.kt index 3ae96ce00a..02aadc0b49 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/design/PreMigrationController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/design/PreMigrationController.kt @@ -6,6 +6,7 @@ import android.view.View import android.view.ViewGroup import android.widget.FrameLayout import androidx.recyclerview.widget.LinearLayoutManager +import com.bluelinelabs.conductor.Router import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialog import eu.davidea.flexibleadapter.FlexibleAdapter @@ -152,6 +153,18 @@ class PreMigrationController(bundle: Bundle? = null) : BaseController(bundle), F companion object { private const val MANGA_IDS_EXTRA = "manga_ids" + fun navigateToMigration(skipPre: Boolean, router: Router, mangaIds: List) { + router.pushController( + if (skipPre) { + MigrationListController.create( + MigrationProcedureConfig(mangaIds, null) + ) + } else { + create(mangaIds) + }.withFadeTransaction().tag(if (skipPre) MigrationListController.TAG else null) + ) + } + fun create(mangaIds: List): PreMigrationController { return PreMigrationController(Bundle().apply { putLongArray(MANGA_IDS_EXTRA, mangaIds.toLongArray()) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/process/MigrationListController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/process/MigrationListController.kt index b74637de56..3f78bd1c70 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/process/MigrationListController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/process/MigrationListController.kt @@ -14,6 +14,7 @@ import androidx.core.graphics.ColorUtils import androidx.recyclerview.widget.LinearLayoutManager import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat import com.afollestad.materialdialogs.MaterialDialog +import com.bluelinelabs.conductor.changehandler.FadeChangeHandler import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Manga @@ -27,10 +28,13 @@ import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.ui.base.controller.BaseController import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction import eu.kanade.tachiyomi.ui.main.BottomNavBarInterface +import eu.kanade.tachiyomi.ui.manga.MangaDetailsController import eu.kanade.tachiyomi.ui.migration.MigrationMangaDialog import eu.kanade.tachiyomi.ui.migration.SearchController +import eu.kanade.tachiyomi.ui.migration.manga.design.PreMigrationController import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource import eu.kanade.tachiyomi.util.system.await +import eu.kanade.tachiyomi.util.system.executeOnIO import eu.kanade.tachiyomi.util.system.getResourceColor import eu.kanade.tachiyomi.util.system.launchUI import eu.kanade.tachiyomi.util.system.toast @@ -383,17 +387,40 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle), fun migrateMangas() { launchUI { adapter?.performMigrations(false) - router.popCurrentController() + navigateOut() } } fun copyMangas() { launchUI { adapter?.performMigrations(true) - router.popCurrentController() + navigateOut() } } + private fun navigateOut() { + if (migratingManga?.size == 1) { + launchUI { + val hasDetails = router.backstack.any { it.controller() is MangaDetailsController } + if (hasDetails) { + val manga = migratingManga?.firstOrNull()?.searchResult?.get()?.let { + db.getManga(it).executeOnIO() + } + if (manga != null) { + val newStack = router.backstack.filter { + it.controller() !is MangaDetailsController && + it.controller() !is MigrationListController && + it.controller() !is PreMigrationController + } + MangaDetailsController(manga).withFadeTransaction() + router.setBackstack(newStack, FadeChangeHandler()) + return@launchUI + } + } + router.popCurrentController() + } + } else router.popCurrentController() + } + override fun handleBack(): Boolean { activity?.let { MaterialDialog(it).show { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/process/MigrationProcessAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/process/MigrationProcessAdapter.kt index a38d05c589..1cdb3b3fb0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/process/MigrationProcessAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/process/MigrationProcessAdapter.kt @@ -13,6 +13,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.cancel import kotlinx.coroutines.withContext import uy.kohesive.injekt.injectLazy +import java.util.Date class MigrationProcessAdapter( val controller: MigrationListController @@ -101,8 +102,8 @@ class MigrationProcessAdapter( // Update chapters read if (MigrationFlags.hasChapters(flags)) { val prevMangaChapters = db.getChapters(prevManga).executeAsBlocking() - val maxChapterRead = prevMangaChapters.filter { it.read } - .maxBy { it.chapter_number }?.chapter_number + val maxChapterRead = + prevMangaChapters.filter { it.read }.maxBy { it.chapter_number }?.chapter_number if (maxChapterRead != null) { val dbChapters = db.getChapters(manga).executeAsBlocking() for (chapter in dbChapters) { @@ -134,10 +135,10 @@ class MigrationProcessAdapter( db.updateMangaFavorite(prevManga).executeAsBlocking() } manga.favorite = true + if (replace) manga.date_added = prevManga.date_added + else manga.date_added = Date().time db.updateMangaFavorite(manga).executeAsBlocking() - - // SearchPresenter#networkToLocalManga may have updated the manga title, so ensure db gets updated title + db.updateMangaAdded(manga).executeAsBlocking() db.updateMangaTitle(manga).executeAsBlocking() - // } } } diff --git a/app/src/main/res/menu/manga_details.xml b/app/src/main/res/menu/manga_details.xml index 9c146dcd0e..d5fb3ba9de 100644 --- a/app/src/main/res/menu/manga_details.xml +++ b/app/src/main/res/menu/manga_details.xml @@ -73,6 +73,12 @@ android:title="@string/edit" app:showAsAction="never" /> + + Copy now Select Migrate + Migrate %1$s Copy No chapters found, this manga cannot be used for migration