From aefa7a1a4ae44557b5ada2c91e4bc40f983cf420 Mon Sep 17 00:00:00 2001 From: jobobby04 Date: Fri, 17 Apr 2020 15:08:21 -0400 Subject: [PATCH] Fixes and such for integration to AZ --- .../smartsearch/SmartSearchEngine.kt | 2 +- .../ui/migration/MigrationMangaDialog.kt | 10 +- .../tachiyomi/ui/migration/SearchPresenter.kt | 126 +----------------- .../tachiyomi/ui/migration/SelectionHeader.kt | 10 +- .../manga/design/PreMigrationController.kt | 21 +-- .../manga/process/MigrationListController.kt | 115 +++++++++------- .../manga/process/MigrationProcessAdapter.kt | 13 +- .../manga/process/MigrationProcessHolder.kt | 4 +- .../system => exh/util}/DatabaseExtensions.kt | 2 +- app/src/main/java/exh/util/ViewExtensions.kt | 101 ++++++++++++++ .../res/layout-land/manga_info_controller.xml | 14 +- .../main/res/layout/manga_info_controller.xml | 10 +- app/src/main/res/values/strings.xml | 74 +++++----- 13 files changed, 260 insertions(+), 242 deletions(-) rename app/src/main/java/{eu/kanade/tachiyomi/util/system => exh/util}/DatabaseExtensions.kt (95%) create mode 100644 app/src/main/java/exh/util/ViewExtensions.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/smartsearch/SmartSearchEngine.kt b/app/src/main/java/eu/kanade/tachiyomi/smartsearch/SmartSearchEngine.kt index 8ff9fc1c8..6cd25571f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/smartsearch/SmartSearchEngine.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/smartsearch/SmartSearchEngine.kt @@ -5,7 +5,7 @@ import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.SManga -import eu.kanade.tachiyomi.util.await +import exh.util.await import info.debatty.java.stringsimilarity.NormalizedLevenshtein import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.CoroutineScope diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/MigrationMangaDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/MigrationMangaDialog.kt index ec53b2785..6bb8d0854 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/MigrationMangaDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/MigrationMangaDialog.kt @@ -22,11 +22,11 @@ class MigrationMangaDialog(bundle: Bundle? = null) : DialogController(bundle) } override fun onCreateDialog(savedViewState: Bundle?): Dialog { - val confirmRes = if (copy) R.string.confirm_copy else R.string.confirm_migration - val confirmString = applicationContext?.getString(confirmRes, mangaSet, ( - if (mangaSkipped > 0) - " " + applicationContext?.getString(R.string.skipping_x, mangaSkipped) ?: "" - else "")) ?: "" + val confirmRes = if (copy) R.plurals.copy_manga else R.plurals.migrate_manga + val confirmString = applicationContext?.resources?.getQuantityString(confirmRes, mangaSet, + mangaSet, ( + if (mangaSkipped > 0) " " + applicationContext?.getString(R.string.skipping_, mangaSkipped) + else "")) ?: "" return MaterialDialog.Builder(activity!!) .content(confirmString) .positiveText(if (copy) R.string.copy else R.string.migrate) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/SearchPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/SearchPresenter.kt index b701e97e5..b8ad1f385 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/SearchPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/SearchPresenter.kt @@ -1,34 +1,16 @@ package eu.kanade.tachiyomi.ui.migration -import android.os.Bundle -import com.jakewharton.rxrelay.BehaviorRelay import eu.kanade.tachiyomi.data.database.models.Manga -import eu.kanade.tachiyomi.data.database.models.MangaCategory import eu.kanade.tachiyomi.source.CatalogueSource -import eu.kanade.tachiyomi.source.Source -import eu.kanade.tachiyomi.source.model.SChapter -import eu.kanade.tachiyomi.source.model.SManga -import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchCardItem -import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchItem -import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchPresenter -import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource -import rx.Observable -import rx.android.schedulers.AndroidSchedulers -import rx.schedulers.Schedulers +import eu.kanade.tachiyomi.ui.source.globalsearch.GlobalSearchCardItem +import eu.kanade.tachiyomi.ui.source.globalsearch.GlobalSearchItem +import eu.kanade.tachiyomi.ui.source.globalsearch.GlobalSearchPresenter class SearchPresenter( initialQuery: String? = "", private val manga: Manga ) : GlobalSearchPresenter(initialQuery) { - private val replacingMangaRelay = BehaviorRelay.create() - - override fun onCreate(savedState: Bundle?) { - super.onCreate(savedState) - - replacingMangaRelay.subscribeLatestCache({ controller, isReplacingManga -> (controller as? SearchController)?.renderIsReplacingManga(isReplacingManga) }) - } - override fun getEnabledSources(): List { // Put the source of the selected manga at the top return super.getEnabledSources() @@ -39,106 +21,4 @@ class SearchPresenter( // Set the catalogue search item as highlighted if the source matches that of the selected manga return GlobalSearchItem(source, results, source.id == manga.source) } - - override fun networkToLocalManga(sManga: SManga, sourceId: Long): Manga { - val localManga = super.networkToLocalManga(sManga, sourceId) - // For migration, displayed title should always match source rather than local DB - localManga.title = sManga.title - return localManga - } - - fun migrateManga(prevManga: Manga, manga: Manga, replace: Boolean) { - val source = sourceManager.get(manga.source) ?: return - - replacingMangaRelay.call(true) - - Observable.defer { source.fetchChapterList(manga) } - .onErrorReturn { emptyList() } - .doOnNext { migrateMangaInternal(source, it, prevManga, manga, replace) } - .onErrorReturn { emptyList() } - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .doOnUnsubscribe { replacingMangaRelay.call(false) } - .subscribe() - } - - private fun migrateMangaInternal( - source: Source, - sourceChapters: List, - prevManga: Manga, - manga: Manga, - replace: Boolean - ) { - val flags = preferences.migrateFlags().get() - val migrateChapters = MigrationFlags.hasChapters(flags) - val migrateCategories = MigrationFlags.hasCategories(flags) - val migrateTracks = MigrationFlags.hasTracks(flags) - - db.inTransaction { - // Update chapters read - if (migrateChapters) { - try { - syncChaptersWithSource(db, sourceChapters, manga, source) - } catch (e: Exception) { - // Worst case, chapters won't be synced - } - - val prevMangaChapters = db.getChapters(prevManga).executeAsBlocking() - val maxChapterRead = prevMangaChapters - .filter { it.read } - .maxBy { it.chapter_number }?.chapter_number - val bookmarkedChapters = prevMangaChapters - .filter { it.bookmark && it.isRecognizedNumber } - .map { it.chapter_number } - if (maxChapterRead != null) { - val dbChapters = db.getChapters(manga).executeAsBlocking() - for (chapter in dbChapters) { - if (chapter.isRecognizedNumber) { - if (chapter.chapter_number <= maxChapterRead) { - chapter.read = true - } - if (chapter.chapter_number in bookmarkedChapters) { - chapter.bookmark = true - } - } - } - db.insertChapters(dbChapters).executeAsBlocking() - } - } - - // Update categories - if (migrateCategories) { - val categories = db.getCategoriesForManga(prevManga).executeAsBlocking() - val mangaCategories = categories.map { MangaCategory.create(manga, it) } - db.setMangaCategories(mangaCategories, listOf(manga)) - } - - // Update track - if (migrateTracks) { - val tracks = db.getTracks(prevManga).executeAsBlocking() - for (track in tracks) { - track.id = null - track.manga_id = manga.id!! - } - db.insertTracks(tracks).executeAsBlocking() - } - - // Update favorite status - if (replace) { - prevManga.favorite = false - db.updateMangaFavorite(prevManga).executeAsBlocking() - } - manga.favorite = true - db.updateMangaFavorite(manga).executeAsBlocking() - - // Update reading preferences - manga.chapter_flags = prevManga.chapter_flags - db.updateFlags(manga).executeAsBlocking() - manga.viewer = prevManga.viewer - db.updateMangaViewer(manga).executeAsBlocking() - - // SearchPresenter#networkToLocalManga may have updated the manga title, so ensure db gets updated title - db.updateMangaTitle(manga).executeAsBlocking() - } - } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/SelectionHeader.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/SelectionHeader.kt index 9530c68bc..ab199eec3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/SelectionHeader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/SelectionHeader.kt @@ -7,7 +7,7 @@ import eu.davidea.flexibleadapter.items.AbstractHeaderItem import eu.davidea.flexibleadapter.items.IFlexible import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder -import kotlinx.android.synthetic.main.source_main_controller_card_header.title +import kotlinx.android.synthetic.main.source_main_controller_card.title /** * Item that contains the selection header. @@ -18,7 +18,7 @@ class SelectionHeader : AbstractHeaderItem() { * Returns the layout resource of this item. */ override fun getLayoutRes(): Int { - return R.layout.source_main_controller_card_header + return R.layout.source_main_controller_card } /** @@ -35,14 +35,14 @@ class SelectionHeader : AbstractHeaderItem() { adapter: FlexibleAdapter>, holder: Holder, position: Int, - payloads: List? + payloads: MutableList? ) { // Intentionally empty } - class Holder(view: View, adapter: FlexibleAdapter<*>) : BaseFlexibleViewHolder(view, adapter) { + class Holder(view: View, adapter: FlexibleAdapter>) : BaseFlexibleViewHolder(view, adapter) { init { - title.text = view.context.getString(R.string.migration_selection_prompt) + title.text = view.context.getString(R.string.select_a_source_to_migrate_from) } } 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 fd7672ecf..55b2340bb 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 @@ -19,12 +19,12 @@ import eu.kanade.tachiyomi.ui.base.controller.BaseController import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction import eu.kanade.tachiyomi.ui.migration.manga.process.MigrationListController import eu.kanade.tachiyomi.ui.migration.manga.process.MigrationProcedureConfig -import eu.kanade.tachiyomi.util.view.doOnApplyWindowInsets -import eu.kanade.tachiyomi.util.view.marginBottom -import eu.kanade.tachiyomi.util.view.updateLayoutParams -import eu.kanade.tachiyomi.util.view.updatePaddingRelative -import kotlinx.android.synthetic.main.pre_migration_controller.fab -import kotlinx.android.synthetic.main.pre_migration_controller.recycler +import exh.util.applyWindowInsetsForController +import exh.util.doOnApplyWindowInsets +import exh.util.marginBottom +import exh.util.updateLayoutParams +import exh.util.updatePaddingRelative +import kotlinx.android.synthetic.main.pre_migration_controller.* import uy.kohesive.injekt.injectLazy class PreMigrationController(bundle: Bundle? = null) : BaseController(bundle), FlexibleAdapter @@ -48,10 +48,11 @@ class PreMigrationController(bundle: Bundle? = null) : BaseController(bundle), F override fun onViewCreated(view: View) { super.onViewCreated(view) + view.applyWindowInsetsForController() val ourAdapter = adapter ?: MigrationSourceAdapter( - getEnabledSources().map { MigrationSourceItem(it, isEnabled(it.id.toString())) }, - this + getEnabledSources().map { MigrationSourceItem(it, isEnabled(it.id.toString())) }, + this ) adapter = ourAdapter recycler.layoutManager = LinearLayoutManager(view.context) @@ -99,7 +100,7 @@ class PreMigrationController(bundle: Bundle? = null) : BaseController(bundle), F config.toList(), extraSearchParams = extraParam ) - ).withFadeTransaction()) + ).withFadeTransaction().tag(MigrationListController.TAG)) } override fun onSaveInstanceState(outState: Bundle) { @@ -129,7 +130,7 @@ class PreMigrationController(bundle: Bundle? = null) : BaseController(bundle), F private fun getEnabledSources(): List { val languages = prefs.enabledLanguages().getOrDefault() val sourcesSaved = prefs.migrationSources().getOrDefault().split("/") - var sources = sourceManager.getCatalogueSources() + var sources = sourceManager.getVisibleCatalogueSources() .filterIsInstance() .filter { it.lang in languages } .sortedBy { "(${it.lang}) ${it.name}" } 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 86fb7553b..73dee306e 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 @@ -31,12 +31,14 @@ import eu.kanade.tachiyomi.ui.manga.MangaController 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.await import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource import eu.kanade.tachiyomi.util.lang.launchUI -import eu.kanade.tachiyomi.util.system.executeOnIO +import eu.kanade.tachiyomi.util.system.getResourceColor import eu.kanade.tachiyomi.util.system.toast -import eu.kanade.tachiyomi.util.view.RecyclerWindowInsetsListener +import exh.util.RecyclerWindowInsetsListener +import exh.util.applyWindowInsetsForController +import exh.util.await +import exh.util.executeOnIO import java.util.concurrent.atomic.AtomicInteger import kotlin.coroutines.CoroutineContext import kotlinx.android.synthetic.main.chapters_controller.* @@ -55,8 +57,7 @@ import timber.log.Timber import uy.kohesive.injekt.injectLazy class MigrationListController(bundle: Bundle? = null) : BaseController(bundle), - MigrationProcessAdapter.MigrationProcessInterface, - CoroutineScope { + MigrationProcessAdapter.MigrationProcessInterface, CoroutineScope { init { setHasOptionsMenu(true) @@ -74,7 +75,8 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle), private val smartSearchEngine = SmartSearchEngine(coroutineContext, config?.extraSearchParams) - private var migrationsJob: Job? = null + var migrationsJob: Job? = null + private set private var migratingManga: MutableList? = null private var selectedPosition: Int? = null private var manaulMigrations = 0 @@ -84,12 +86,15 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle), } override fun getTitle(): String? { - return resources?.getString(R.string.migration) + " (${adapter?.items?.count { it.manga - .migrationStatus != MigrationStatus.RUNNUNG }}/${adapter?.itemCount ?: 0})" + return resources?.getString(R.string.migration) + " (${adapter?.items?.count { + it.manga.migrationStatus != MigrationStatus.RUNNUNG + }}/${adapter?.itemCount ?: 0})" } override fun onViewCreated(view: View) { + super.onViewCreated(view) + view.applyWindowInsetsForController() setTitle() val config = this.config ?: return @@ -101,7 +106,7 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle), new } - adapter = MigrationProcessAdapter(this, view.context) + adapter = MigrationProcessAdapter(this) recycler.adapter = adapter recycler.layoutManager = LinearLayoutManager(view.context) @@ -117,23 +122,14 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle), } } - fun migrationFailure() { - activity?.let { - MaterialDialog.Builder(it) - .title("Migration failure") - .content("An unknown error occured while migrating this manga!") - .positiveText("Ok") - .show() - } - } - - suspend fun runMigrations(mangas: List) { + private suspend fun runMigrations(mangas: List) { val useSourceWithMost = preferences.useSourceWithMost().getOrDefault() val useSmartSearch = preferences.smartMigration().getOrDefault() val sources = preferences.migrationSources().getOrDefault().split("/").mapNotNull { val value = it.toLongOrNull() ?: return - sourceManager.get(value) as? CatalogueSource } + sourceManager.get(value) as? CatalogueSource + } if (config == null) return for (manga in mangas) { if (migrationsJob?.isCancelled == true) { @@ -173,11 +169,23 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle), } if (searchResult != null) { - val localManga = smartSearchEngine.networkToLocalManga(searchResult, source.id) - val chapters = source.fetchChapterList(localManga).toSingle().await( - Schedulers.io()) + val localManga = + smartSearchEngine.networkToLocalManga( + searchResult, + source.id + ) + val chapters = + source.fetchChapterList(localManga).toSingle() + .await( + Schedulers.io() + ) try { - syncChaptersWithSource(db, chapters, localManga, source) + syncChaptersWithSource( + db, + chapters, + localManga, + source + ) } catch (e: Exception) { return@async null } @@ -208,7 +216,7 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle), val localManga = smartSearchEngine.networkToLocalManga(searchResult, source.id) val chapters = try { source.fetchChapterList(localManga) - .toSingle().await(Schedulers.io()) } catch (e: java.lang.Exception) { + .toSingle().await(Schedulers.io()) } catch (e: java.lang.Exception) { Timber.e(e) emptyList() } ?: emptyList() @@ -239,10 +247,9 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle), if (result != null && result.thumbnail_url == null) { try { - val newManga = sourceManager.getOrStub(result.source) - .fetchMangaDetails(result) - .toSingle() - .await() + val newManga = + sourceManager.getOrStub(result.source).fetchMangaDetails(result) + .toSingle().await() result.copyFrom(newManga) db.insertManga(result).executeAsBlocking() @@ -253,8 +260,8 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle), } } - manga.migrationStatus = if (result == null) MigrationStatus.MANGA_NOT_FOUND else - MigrationStatus.MANGA_FOUND + manga.migrationStatus = + if (result == null) MigrationStatus.MANGA_NOT_FOUND else MigrationStatus.MANGA_FOUND adapter?.sourceFinished() manga.searchResult.initialize(result?.id) } @@ -286,8 +293,7 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle), ids.removeAt(index) config.mangaIds = ids val index2 = migratingManga?.indexOf(item.manga) ?: return - if (index2 > -1) - migratingManga?.removeAt(index2) + if (index2 > -1) migratingManga?.removeAt(index2) } } @@ -296,8 +302,9 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle), val res = resources if (res != null) { activity?.toast( - res.getQuantityString(R.plurals.manga_migrated, - manaulMigrations, manaulMigrations) + res.getQuantityString( + R.plurals.manga_migrated, manaulMigrations, manaulMigrations + ) ) } router.popCurrentController() @@ -366,7 +373,7 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle), adapter?.notifyDataSetChanged() } else { migratingManga.manga.migrationStatus = MigrationStatus.MANGA_NOT_FOUND - activity?.toast(R.string.error_fetching_migration, Toast.LENGTH_LONG) + activity?.toast(R.string.no_chapters_found_for_migration, Toast.LENGTH_LONG) adapter?.notifyDataSetChanged() } } @@ -397,8 +404,8 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle), if (manga != null) { val newStack = router.backstack.filter { it.controller() !is MangaController && - it.controller() !is MigrationListController && - it.controller() !is PreMigrationController + it.controller() !is MigrationListController && + it.controller() !is PreMigrationController } + MangaController(manga).withFadeTransaction() router.setBackstack(newStack, FadeChangeHandler()) return@launchUI @@ -411,7 +418,7 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle), override fun handleBack(): Boolean { activity?.let { - MaterialDialog.Builder(it).title(R.string.stop_migration) + MaterialDialog.Builder(it).title(R.string.stop_migrating) .positiveText(R.string.action_stop) .negativeText(android.R.string.cancel) .onPositive { _, _ -> @@ -441,12 +448,16 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle), if (adapter?.itemCount == 1) { menuMigrate.icon = VectorDrawableCompat.create( - resources!!, R.drawable.ic_done, null + resources!!, R.drawable.ic_done_24dp, null ) } - val translucentWhite = ColorUtils.setAlphaComponent(Color.WHITE, 127) - menuCopy.icon?.setTint(if (allMangasDone) Color.WHITE else translucentWhite) - menuMigrate?.icon?.setTint(if (allMangasDone) Color.WHITE else translucentWhite) + + menuCopy.icon.mutate() + menuMigrate.icon.mutate() + val tintColor = activity?.getResourceColor(R.attr.colorPrimary) ?: Color.WHITE + val translucentWhite = ColorUtils.setAlphaComponent(tintColor, 127) + menuCopy.icon?.setTint(if (allMangasDone) tintColor else translucentWhite) + menuMigrate?.icon?.setTint(if (allMangasDone) tintColor else translucentWhite) menuCopy.isEnabled = allMangasDone menuMigrate.isEnabled = allMangasDone } @@ -455,10 +466,18 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle), val totalManga = adapter?.itemCount ?: 0 val mangaSkipped = adapter?.mangasSkipped() ?: 0 when (item.itemId) { - R.id.action_copy_manga -> MigrationMangaDialog(this, true, totalManga, mangaSkipped) - .showDialog(router) - R.id.action_migrate_manga -> MigrationMangaDialog(this, false, totalManga, mangaSkipped) - .showDialog(router) + R.id.action_copy_manga -> MigrationMangaDialog( + this, + true, + totalManga, + mangaSkipped + ).showDialog(router) + R.id.action_migrate_manga -> MigrationMangaDialog( + this, + false, + totalManga, + mangaSkipped + ).showDialog(router) else -> return super.onOptionsItemSelected(item) } return true 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 c1c328916..5f6e6a63c 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 @@ -1,6 +1,5 @@ package eu.kanade.tachiyomi.ui.migration.manga.process -import android.content.Context import android.view.MenuItem import eu.davidea.flexibleadapter.FlexibleAdapter import eu.kanade.tachiyomi.data.database.DatabaseHelper @@ -16,8 +15,7 @@ import kotlinx.coroutines.withContext import uy.kohesive.injekt.injectLazy class MigrationProcessAdapter( - val controller: MigrationListController, - context: Context + val controller: MigrationListController ) : FlexibleAdapter(null, controller, true) { private val db: DatabaseHelper by injectLazy() @@ -73,8 +71,9 @@ class MigrationProcessAdapter( launchUI { val manga = getItem(position)?.manga ?: return@launchUI db.inTransaction { - val toMangaObj = db.getManga(manga.searchResult.get() ?: return@launchUI).executeAsBlocking() - ?: return@launchUI + val toMangaObj = + db.getManga(manga.searchResult.get() ?: return@launchUI).executeAsBlocking() + ?: return@launchUI migrateMangaInternal( manga.manga() ?: return@launchUI, toMangaObj, !copy ) @@ -135,8 +134,8 @@ class MigrationProcessAdapter( db.updateMangaFavorite(prevManga).executeAsBlocking() } manga.favorite = true - // SearchPresenter#networkToLocalManga may have updated the manga title, so ensure db gets updated title + + db.updateMangaFavorite(manga).executeAsBlocking() db.updateMangaTitle(manga).executeAsBlocking() - // } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/process/MigrationProcessHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/process/MigrationProcessHolder.kt index 2dd14b626..ca02adb7b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/process/MigrationProcessHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/process/MigrationProcessHolder.kt @@ -152,10 +152,10 @@ class MigrationProcessHolder( val latestChapter = mangaChapters.maxBy { it.chapter_number }?.chapter_number ?: -1f if (latestChapter > 0f) { - manga_last_chapter_label.text = context.getString(R.string.latest_x, + manga_last_chapter_label.text = context.getString(R.string.latest_, DecimalFormat("#.#").format(latestChapter)) } else { - manga_last_chapter_label.text = context.getString(R.string.latest_x, + manga_last_chapter_label.text = context.getString(R.string.latest_, context.getString(R.string.unknown)) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/system/DatabaseExtensions.kt b/app/src/main/java/exh/util/DatabaseExtensions.kt similarity index 95% rename from app/src/main/java/eu/kanade/tachiyomi/util/system/DatabaseExtensions.kt rename to app/src/main/java/exh/util/DatabaseExtensions.kt index 94c6fdf3b..f7ea231a1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/system/DatabaseExtensions.kt +++ b/app/src/main/java/exh/util/DatabaseExtensions.kt @@ -1,4 +1,4 @@ -package eu.kanade.tachiyomi.util.system +package exh.util import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetListOfObjects import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetObject diff --git a/app/src/main/java/exh/util/ViewExtensions.kt b/app/src/main/java/exh/util/ViewExtensions.kt new file mode 100644 index 000000000..10eda11b2 --- /dev/null +++ b/app/src/main/java/exh/util/ViewExtensions.kt @@ -0,0 +1,101 @@ +package exh.util + +import android.view.View +import android.view.ViewGroup +import android.view.WindowInsets +import android.widget.FrameLayout +import androidx.annotation.Px + +inline val View.marginTop: Int + get() = (layoutParams as? ViewGroup.MarginLayoutParams)?.topMargin ?: 0 + +inline val View.marginBottom: Int + get() = (layoutParams as? ViewGroup.MarginLayoutParams)?.bottomMargin ?: 0 + +inline val View.marginRight: Int + get() = (layoutParams as? ViewGroup.MarginLayoutParams)?.rightMargin ?: 0 + +inline val View.marginLeft: Int + get() = (layoutParams as? ViewGroup.MarginLayoutParams)?.leftMargin ?: 0 + +fun View.doOnApplyWindowInsets(f: (View, WindowInsets, ViewPaddingState) -> Unit) { + // Create a snapshot of the view's padding state + val paddingState = createStateForView(this) + setOnApplyWindowInsetsListener { v, insets -> + f(v, insets, paddingState) + insets + } + requestApplyInsetsWhenAttached() +} + +object ControllerViewWindowInsetsListener : View.OnApplyWindowInsetsListener { + override fun onApplyWindowInsets(v: View, insets: WindowInsets): WindowInsets { + v.updateLayoutParams { + val attrsArray = intArrayOf(android.R.attr.actionBarSize) + val array = v.context.obtainStyledAttributes(attrsArray) + topMargin = insets.systemWindowInsetTop + array.getDimensionPixelSize(0, 0) + array.recycle() + } + return insets + } +} + +fun View.requestApplyInsetsWhenAttached() { + if (isAttachedToWindow) { + requestApplyInsets() + } else { + addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener { + override fun onViewAttachedToWindow(v: View) { + v.requestApplyInsets() + } + + override fun onViewDetachedFromWindow(v: View) = Unit + }) + } +} + +inline fun View.updateLayoutParams(block: T.() -> Unit) { + val params = layoutParams as T + block(params) + layoutParams = params +} + +fun View.applyWindowInsetsForController() { + setOnApplyWindowInsetsListener(ControllerViewWindowInsetsListener) + requestApplyInsetsWhenAttached() +} + +inline fun View.updatePaddingRelative( + @Px start: Int = paddingStart, + @Px top: Int = paddingTop, + @Px end: Int = paddingEnd, + @Px bottom: Int = paddingBottom +) { + setPaddingRelative(start, top, end, bottom) +} + +private fun createStateForView(view: View) = ViewPaddingState( + view.paddingLeft, + view.paddingTop, + view.paddingRight, + view.paddingBottom, + view.paddingStart, + view.paddingEnd +) + +data class ViewPaddingState( + val left: Int, + val top: Int, + val right: Int, + val bottom: Int, + val start: Int, + val end: Int +) + +object RecyclerWindowInsetsListener : View.OnApplyWindowInsetsListener { + override fun onApplyWindowInsets(v: View, insets: WindowInsets): WindowInsets { + v.updatePaddingRelative(bottom = insets.systemWindowInsetBottom) + // v.updatePaddingRelative(bottom = v.paddingBottom + insets.systemWindowInsetBottom) + return insets + } +} diff --git a/app/src/main/res/layout-land/manga_info_controller.xml b/app/src/main/res/layout-land/manga_info_controller.xml index 2326b83f8..0bd179b81 100644 --- a/app/src/main/res/layout-land/manga_info_controller.xml +++ b/app/src/main/res/layout-land/manga_info_controller.xml @@ -333,12 +333,18 @@ app:layout_constraintTop_toBottomOf="@id/manga_genres_tags_wrapper" />