Fixes and such for integration to AZ

This commit is contained in:
jobobby04 2020-04-17 15:08:21 -04:00 committed by Jobobby04
parent 18f90587f2
commit aefa7a1a4a
13 changed files with 260 additions and 242 deletions

View File

@ -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

View File

@ -22,10 +22,10 @@ class MigrationMangaDialog<T>(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) ?: ""
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)

View File

@ -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<Boolean>()
override fun onCreate(savedState: Bundle?) {
super.onCreate(savedState)
replacingMangaRelay.subscribeLatestCache({ controller, isReplacingManga -> (controller as? SearchController)?.renderIsReplacingManga(isReplacingManga) })
}
override fun getEnabledSources(): List<CatalogueSource> {
// 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<SChapter>,
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()
}
}
}

View File

@ -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<SelectionHeader.Holder>() {
* 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<SelectionHeader.Holder>() {
adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>,
holder: Holder,
position: Int,
payloads: List<Any?>?
payloads: MutableList<Any?>?
) {
// Intentionally empty
}
class Holder(view: View, adapter: FlexibleAdapter<*>) : BaseFlexibleViewHolder(view, adapter) {
class Holder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>) : 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)
}
}

View File

@ -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,6 +48,7 @@ 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())) },
@ -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<HttpSource> {
val languages = prefs.enabledLanguages().getOrDefault()
val sourcesSaved = prefs.migrationSources().getOrDefault().split("/")
var sources = sourceManager.getCatalogueSources()
var sources = sourceManager.getVisibleCatalogueSources()
.filterIsInstance<HttpSource>()
.filter { it.lang in languages }
.sortedBy { "(${it.lang}) ${it.name}" }

View File

@ -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<MigratingManga>? = 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<MigratingManga>) {
private suspend fun runMigrations(mangas: List<MigratingManga>) {
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
}
@ -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()
}
}
@ -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

View File

@ -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<MigrationProcessItem>(null, controller, true) {
private val db: DatabaseHelper by injectLazy()
@ -73,7 +71,8 @@ class MigrationProcessAdapter(
launchUI {
val manga = getItem(position)?.manga ?: return@launchUI
db.inTransaction {
val toMangaObj = db.getManga(manga.searchResult.get() ?: return@launchUI).executeAsBlocking()
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()
// }
}
}

View File

@ -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))
}
}

View File

@ -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

View File

@ -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<FrameLayout.LayoutParams> {
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 <reified T : ViewGroup.LayoutParams> 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
}
}

View File

@ -333,12 +333,18 @@
app:layout_constraintTop_toBottomOf="@id/manga_genres_tags_wrapper" />
<Button
android:id="@+id/smartsearch_merge_btn"
style="@style/Widget.AppCompat.Button.Colored"
android:id="@+id/merge_btn"
style="@style/Widget.MaterialComponents.Button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:text="Merge with current" />
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/manga_info_toggle"
android:text="@string/merge"
android:visibility="gone"
tools:visibility="visible"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -357,12 +357,14 @@
android:textSize="12sp" />
<Button
android:id="@+id/smartsearch_replace_btn"
style="@style/Widget.AppCompat.Button.Colored"
android:id="@+id/merge_btn"
style="@style/Widget.MaterialComponents.Button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:text="Migrate from current" />
android:text="@string/merge"
android:visibility="gone"
tools:visibility="visible"/>
</LinearLayout>

View File

@ -488,17 +488,6 @@
<string name="download_unread">Unread</string>
<string name="confirm_delete_chapters">Are you sure you want to delete the selected chapters?</string>
<string name="invalid_download_dir">Invalid download location</string>
<string name="confirm_migration">Migrate %1$d%2$s manga?</string>
<string name="confirm_copy">Copy %1$d%2$s manga?</string>
<string name="skipping_x">(skipping %1$d)</string>
<plurals name="manga_migrated">
<item quantity="one">%d manga migrated</item>
<item quantity="other">%d manga migrated</item>
</plurals>
<string name="error_fetching_migration">No chapters found, this manga cannot be used for
migration</string>
<string name="no_alternatives_found">No Alternatives Found</string>
<string name="stop_migration">Stop migrating?</string>
<!-- Tracking Screen -->
<string name="manga_tracking_tab">Tracking</string>
@ -567,18 +556,6 @@
<!-- History fragment -->
<string name="recent_manga_time">Ch. %1$s - %2$s</string>
<!-- Source migration screen -->
<string name="migration_info">Tap to select the source to migrate from</string>
<string name="migration_dialog_what_to_include">Select data to include</string>
<string name="migration_selection_prompt">Select a source to migrate from</string>
<string name="select">Select</string>
<string name="migrate">Migrate</string>
<string name="migrate_">Migrate %1$s</string>
<string name="copy">Copy</string>
<string name="migrating">Migrating…</string>
<string name="migration">Migration</string>
<string name="latest_x">Latest: %1$s</string>
<!-- Downloads activity and service -->
<string name="download_queue_error">Could not download chapters. You can try again in the downloads section</string>
@ -662,18 +639,50 @@
<string name="channel_downloader">Downloader</string>
<string name="channel_new_chapters">Chapter updates</string>
<string name="channel_ext_updates">Extension updates</string>
<string name="channel_backup_restore">Backup and restore</string>
<string name="channel_backup_restore_progress">Progress</string>
<string name="channel_backup_restore_complete">Complete</string>
<string name="data_to_include_in_migration">Data to include in migration</string>
<string name="search_parameter">Search parameter (e.g. language:english)</string>
<string name="include_extra_search_parameter">Include extra search parameter when searching</string>
<!-- Migration -->
<string name="source_migration">Source migration</string>
<string name="migration">Migration</string>
<string name="skip_pre_migration">Skip pre-migration</string>
<string name="pre_migration_skip_toast">To show this screen again, go to Settings -> Library.</string>
<string name="select_a_source_to_migrate_from">Select a source to migrate from</string>
<string name="use_intelligent_search">Search title + keywords of title</string>
<string name="migrating_to">migrating to</string>
<string name="data_to_include_in_migration">Data to include in migration</string>
<string name="search_parameter_eg">Search parameter (e.g. language:english)</string>
<string name="include_extra_search_parameter">Include extra search parameter when searching</string>
<string name="use_most_chapters">Use source with the most chapters (slower)</string>
<string name="use_first_source">Use first source with alternative</string>
<string name="skip_this_step_next_time">Skip this step next time</string>
<string name="pre_migration_skip_toast">To show this screen again, go to Settings -> Library.</string>
<string name="search_parameter">Search parameter (e.g. language:english)</string>
<string name="include_extra_search_parameter">Include extra search parameter when searching</string>
<string name="to_show_again_setting_library">To show this screen again, go to Settings -> Library.</string>
<string name="latest_">Latest: %1$s</string>
<string name="migrating_to">migrating to</string>
<string name="dont_migrate">Don\'t migrate</string>
<string name="search_manually">Search manually</string>
<string name="migrate_now">Migrate now</string>
<string name="copy_now">Copy now</string>
<string name="select">Select</string>
<string name="migrate">Migrate</string>
<string name="migrate_">Migrate %1$s</string>
<string name="copy_value">Copy</string>
<string name="no_chapters_found_for_migration">No chapters found, this manga cannot be used for
migration</string>
<string name="no_alternatives_found">No Alternatives Found</string>
<string name="stop_migrating">Stop migrating?</string>
<plurals name="migrate_manga">
<item quantity="one">Migrate %1$d%2$s manga?</item>
<item quantity="other">Migrate %1$d%2$s manga?</item>
</plurals>
<plurals name="copy_manga">
<item quantity="one">Copy %1$d%2$s manga?</item>
<item quantity="other">Copy %1$d%2$s manga?</item>
</plurals>
<string name="skipping_">(skipping %1$d)</string>
<plurals name="manga_migrated">
<item quantity="one">%d manga migrated</item>
<item quantity="other">%d manga migrated</item>
</plurals>
<!-- EXH -->
<string name="label_login">Login</string>
@ -699,7 +708,8 @@
<string name="eh_rounded_corner_9">Radius of 9</string>
<string name="eh_rounded_corner_10">Radius of 10</string>
<string name="eh_rounded_corners_desc">The level of radius that the corners are rounded to. Current value is: %s</string>
<string name="merge">Merge with current</string>
<string name="eh_merge_with_another_source">Merge With Another</string>
</resources>