Fixes and such for integration to AZ
This commit is contained in:
parent
18f90587f2
commit
aefa7a1a4a
@ -5,7 +5,7 @@ import eu.kanade.tachiyomi.data.database.models.Manga
|
|||||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import eu.kanade.tachiyomi.util.await
|
import exh.util.await
|
||||||
import info.debatty.java.stringsimilarity.NormalizedLevenshtein
|
import info.debatty.java.stringsimilarity.NormalizedLevenshtein
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
@ -22,11 +22,11 @@ class MigrationMangaDialog<T>(bundle: Bundle? = null) : DialogController(bundle)
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||||
val confirmRes = if (copy) R.string.confirm_copy else R.string.confirm_migration
|
val confirmRes = if (copy) R.plurals.copy_manga else R.plurals.migrate_manga
|
||||||
val confirmString = applicationContext?.getString(confirmRes, mangaSet, (
|
val confirmString = applicationContext?.resources?.getQuantityString(confirmRes, mangaSet,
|
||||||
if (mangaSkipped > 0)
|
mangaSet, (
|
||||||
" " + applicationContext?.getString(R.string.skipping_x, mangaSkipped) ?: ""
|
if (mangaSkipped > 0) " " + applicationContext?.getString(R.string.skipping_, mangaSkipped)
|
||||||
else "")) ?: ""
|
else "")) ?: ""
|
||||||
return MaterialDialog.Builder(activity!!)
|
return MaterialDialog.Builder(activity!!)
|
||||||
.content(confirmString)
|
.content(confirmString)
|
||||||
.positiveText(if (copy) R.string.copy else R.string.migrate)
|
.positiveText(if (copy) R.string.copy else R.string.migrate)
|
||||||
|
@ -1,34 +1,16 @@
|
|||||||
package eu.kanade.tachiyomi.ui.migration
|
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.Manga
|
||||||
import eu.kanade.tachiyomi.data.database.models.MangaCategory
|
|
||||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.ui.source.globalsearch.GlobalSearchCardItem
|
||||||
import eu.kanade.tachiyomi.source.model.SChapter
|
import eu.kanade.tachiyomi.ui.source.globalsearch.GlobalSearchItem
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.ui.source.globalsearch.GlobalSearchPresenter
|
||||||
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
|
|
||||||
|
|
||||||
class SearchPresenter(
|
class SearchPresenter(
|
||||||
initialQuery: String? = "",
|
initialQuery: String? = "",
|
||||||
private val manga: Manga
|
private val manga: Manga
|
||||||
) : GlobalSearchPresenter(initialQuery) {
|
) : 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> {
|
override fun getEnabledSources(): List<CatalogueSource> {
|
||||||
// Put the source of the selected manga at the top
|
// Put the source of the selected manga at the top
|
||||||
return super.getEnabledSources()
|
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
|
// Set the catalogue search item as highlighted if the source matches that of the selected manga
|
||||||
return GlobalSearchItem(source, results, source.id == manga.source)
|
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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import eu.davidea.flexibleadapter.items.AbstractHeaderItem
|
|||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
|
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.
|
* Item that contains the selection header.
|
||||||
@ -18,7 +18,7 @@ class SelectionHeader : AbstractHeaderItem<SelectionHeader.Holder>() {
|
|||||||
* Returns the layout resource of this item.
|
* Returns the layout resource of this item.
|
||||||
*/
|
*/
|
||||||
override fun getLayoutRes(): Int {
|
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>>,
|
adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>,
|
||||||
holder: Holder,
|
holder: Holder,
|
||||||
position: Int,
|
position: Int,
|
||||||
payloads: List<Any?>?
|
payloads: MutableList<Any?>?
|
||||||
) {
|
) {
|
||||||
// Intentionally empty
|
// Intentionally empty
|
||||||
}
|
}
|
||||||
|
|
||||||
class Holder(view: View, adapter: FlexibleAdapter<*>) : BaseFlexibleViewHolder(view, adapter) {
|
class Holder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>) : BaseFlexibleViewHolder(view, adapter) {
|
||||||
init {
|
init {
|
||||||
title.text = view.context.getString(R.string.migration_selection_prompt)
|
title.text = view.context.getString(R.string.select_a_source_to_migrate_from)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.base.controller.withFadeTransaction
|
||||||
import eu.kanade.tachiyomi.ui.migration.manga.process.MigrationListController
|
import eu.kanade.tachiyomi.ui.migration.manga.process.MigrationListController
|
||||||
import eu.kanade.tachiyomi.ui.migration.manga.process.MigrationProcedureConfig
|
import eu.kanade.tachiyomi.ui.migration.manga.process.MigrationProcedureConfig
|
||||||
import eu.kanade.tachiyomi.util.view.doOnApplyWindowInsets
|
import exh.util.applyWindowInsetsForController
|
||||||
import eu.kanade.tachiyomi.util.view.marginBottom
|
import exh.util.doOnApplyWindowInsets
|
||||||
import eu.kanade.tachiyomi.util.view.updateLayoutParams
|
import exh.util.marginBottom
|
||||||
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
|
import exh.util.updateLayoutParams
|
||||||
import kotlinx.android.synthetic.main.pre_migration_controller.fab
|
import exh.util.updatePaddingRelative
|
||||||
import kotlinx.android.synthetic.main.pre_migration_controller.recycler
|
import kotlinx.android.synthetic.main.pre_migration_controller.*
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
class PreMigrationController(bundle: Bundle? = null) : BaseController(bundle), FlexibleAdapter
|
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) {
|
override fun onViewCreated(view: View) {
|
||||||
super.onViewCreated(view)
|
super.onViewCreated(view)
|
||||||
|
view.applyWindowInsetsForController()
|
||||||
|
|
||||||
val ourAdapter = adapter ?: MigrationSourceAdapter(
|
val ourAdapter = adapter ?: MigrationSourceAdapter(
|
||||||
getEnabledSources().map { MigrationSourceItem(it, isEnabled(it.id.toString())) },
|
getEnabledSources().map { MigrationSourceItem(it, isEnabled(it.id.toString())) },
|
||||||
this
|
this
|
||||||
)
|
)
|
||||||
adapter = ourAdapter
|
adapter = ourAdapter
|
||||||
recycler.layoutManager = LinearLayoutManager(view.context)
|
recycler.layoutManager = LinearLayoutManager(view.context)
|
||||||
@ -99,7 +100,7 @@ class PreMigrationController(bundle: Bundle? = null) : BaseController(bundle), F
|
|||||||
config.toList(),
|
config.toList(),
|
||||||
extraSearchParams = extraParam
|
extraSearchParams = extraParam
|
||||||
)
|
)
|
||||||
).withFadeTransaction())
|
).withFadeTransaction().tag(MigrationListController.TAG))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
@ -129,7 +130,7 @@ class PreMigrationController(bundle: Bundle? = null) : BaseController(bundle), F
|
|||||||
private fun getEnabledSources(): List<HttpSource> {
|
private fun getEnabledSources(): List<HttpSource> {
|
||||||
val languages = prefs.enabledLanguages().getOrDefault()
|
val languages = prefs.enabledLanguages().getOrDefault()
|
||||||
val sourcesSaved = prefs.migrationSources().getOrDefault().split("/")
|
val sourcesSaved = prefs.migrationSources().getOrDefault().split("/")
|
||||||
var sources = sourceManager.getCatalogueSources()
|
var sources = sourceManager.getVisibleCatalogueSources()
|
||||||
.filterIsInstance<HttpSource>()
|
.filterIsInstance<HttpSource>()
|
||||||
.filter { it.lang in languages }
|
.filter { it.lang in languages }
|
||||||
.sortedBy { "(${it.lang}) ${it.name}" }
|
.sortedBy { "(${it.lang}) ${it.name}" }
|
||||||
|
@ -31,12 +31,14 @@ 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.ui.migration.manga.design.PreMigrationController
|
||||||
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.getResourceColor
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
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 java.util.concurrent.atomic.AtomicInteger
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
import kotlinx.android.synthetic.main.chapters_controller.*
|
import kotlinx.android.synthetic.main.chapters_controller.*
|
||||||
@ -55,8 +57,7 @@ import timber.log.Timber
|
|||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
|
class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
|
||||||
MigrationProcessAdapter.MigrationProcessInterface,
|
MigrationProcessAdapter.MigrationProcessInterface, CoroutineScope {
|
||||||
CoroutineScope {
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
setHasOptionsMenu(true)
|
setHasOptionsMenu(true)
|
||||||
@ -74,7 +75,8 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
|
|
||||||
private val smartSearchEngine = SmartSearchEngine(coroutineContext, config?.extraSearchParams)
|
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 migratingManga: MutableList<MigratingManga>? = null
|
||||||
private var selectedPosition: Int? = null
|
private var selectedPosition: Int? = null
|
||||||
private var manaulMigrations = 0
|
private var manaulMigrations = 0
|
||||||
@ -84,12 +86,15 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getTitle(): String? {
|
override fun getTitle(): String? {
|
||||||
return resources?.getString(R.string.migration) + " (${adapter?.items?.count { it.manga
|
return resources?.getString(R.string.migration) + " (${adapter?.items?.count {
|
||||||
.migrationStatus != MigrationStatus.RUNNUNG }}/${adapter?.itemCount ?: 0})"
|
it.manga.migrationStatus != MigrationStatus.RUNNUNG
|
||||||
|
}}/${adapter?.itemCount ?: 0})"
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View) {
|
override fun onViewCreated(view: View) {
|
||||||
|
|
||||||
super.onViewCreated(view)
|
super.onViewCreated(view)
|
||||||
|
view.applyWindowInsetsForController()
|
||||||
setTitle()
|
setTitle()
|
||||||
val config = this.config ?: return
|
val config = this.config ?: return
|
||||||
|
|
||||||
@ -101,7 +106,7 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
new
|
new
|
||||||
}
|
}
|
||||||
|
|
||||||
adapter = MigrationProcessAdapter(this, view.context)
|
adapter = MigrationProcessAdapter(this)
|
||||||
|
|
||||||
recycler.adapter = adapter
|
recycler.adapter = adapter
|
||||||
recycler.layoutManager = LinearLayoutManager(view.context)
|
recycler.layoutManager = LinearLayoutManager(view.context)
|
||||||
@ -117,23 +122,14 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun migrationFailure() {
|
private suspend fun runMigrations(mangas: List<MigratingManga>) {
|
||||||
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>) {
|
|
||||||
val useSourceWithMost = preferences.useSourceWithMost().getOrDefault()
|
val useSourceWithMost = preferences.useSourceWithMost().getOrDefault()
|
||||||
val useSmartSearch = preferences.smartMigration().getOrDefault()
|
val useSmartSearch = preferences.smartMigration().getOrDefault()
|
||||||
|
|
||||||
val sources = preferences.migrationSources().getOrDefault().split("/").mapNotNull {
|
val sources = preferences.migrationSources().getOrDefault().split("/").mapNotNull {
|
||||||
val value = it.toLongOrNull() ?: return
|
val value = it.toLongOrNull() ?: return
|
||||||
sourceManager.get(value) as? CatalogueSource }
|
sourceManager.get(value) as? CatalogueSource
|
||||||
|
}
|
||||||
if (config == null) return
|
if (config == null) return
|
||||||
for (manga in mangas) {
|
for (manga in mangas) {
|
||||||
if (migrationsJob?.isCancelled == true) {
|
if (migrationsJob?.isCancelled == true) {
|
||||||
@ -173,11 +169,23 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (searchResult != null) {
|
if (searchResult != null) {
|
||||||
val localManga = smartSearchEngine.networkToLocalManga(searchResult, source.id)
|
val localManga =
|
||||||
val chapters = source.fetchChapterList(localManga).toSingle().await(
|
smartSearchEngine.networkToLocalManga(
|
||||||
Schedulers.io())
|
searchResult,
|
||||||
|
source.id
|
||||||
|
)
|
||||||
|
val chapters =
|
||||||
|
source.fetchChapterList(localManga).toSingle()
|
||||||
|
.await(
|
||||||
|
Schedulers.io()
|
||||||
|
)
|
||||||
try {
|
try {
|
||||||
syncChaptersWithSource(db, chapters, localManga, source)
|
syncChaptersWithSource(
|
||||||
|
db,
|
||||||
|
chapters,
|
||||||
|
localManga,
|
||||||
|
source
|
||||||
|
)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
return@async null
|
return@async null
|
||||||
}
|
}
|
||||||
@ -208,7 +216,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()) } catch (e: java.lang.Exception) {
|
.toSingle().await(Schedulers.io()) } catch (e: java.lang.Exception) {
|
||||||
Timber.e(e)
|
Timber.e(e)
|
||||||
emptyList<SChapter>()
|
emptyList<SChapter>()
|
||||||
} ?: emptyList()
|
} ?: emptyList()
|
||||||
@ -239,10 +247,9 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
|
|
||||||
if (result != null && result.thumbnail_url == null) {
|
if (result != null && result.thumbnail_url == null) {
|
||||||
try {
|
try {
|
||||||
val newManga = sourceManager.getOrStub(result.source)
|
val newManga =
|
||||||
.fetchMangaDetails(result)
|
sourceManager.getOrStub(result.source).fetchMangaDetails(result)
|
||||||
.toSingle()
|
.toSingle().await()
|
||||||
.await()
|
|
||||||
result.copyFrom(newManga)
|
result.copyFrom(newManga)
|
||||||
|
|
||||||
db.insertManga(result).executeAsBlocking()
|
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
|
manga.migrationStatus =
|
||||||
MigrationStatus.MANGA_FOUND
|
if (result == null) MigrationStatus.MANGA_NOT_FOUND else MigrationStatus.MANGA_FOUND
|
||||||
adapter?.sourceFinished()
|
adapter?.sourceFinished()
|
||||||
manga.searchResult.initialize(result?.id)
|
manga.searchResult.initialize(result?.id)
|
||||||
}
|
}
|
||||||
@ -286,8 +293,7 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
ids.removeAt(index)
|
ids.removeAt(index)
|
||||||
config.mangaIds = ids
|
config.mangaIds = ids
|
||||||
val index2 = migratingManga?.indexOf(item.manga) ?: return
|
val index2 = migratingManga?.indexOf(item.manga) ?: return
|
||||||
if (index2 > -1)
|
if (index2 > -1) migratingManga?.removeAt(index2)
|
||||||
migratingManga?.removeAt(index2)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,8 +302,9 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
val res = resources
|
val res = resources
|
||||||
if (res != null) {
|
if (res != null) {
|
||||||
activity?.toast(
|
activity?.toast(
|
||||||
res.getQuantityString(R.plurals.manga_migrated,
|
res.getQuantityString(
|
||||||
manaulMigrations, manaulMigrations)
|
R.plurals.manga_migrated, manaulMigrations, manaulMigrations
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
router.popCurrentController()
|
router.popCurrentController()
|
||||||
@ -366,7 +373,7 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
adapter?.notifyDataSetChanged()
|
adapter?.notifyDataSetChanged()
|
||||||
} else {
|
} else {
|
||||||
migratingManga.manga.migrationStatus = MigrationStatus.MANGA_NOT_FOUND
|
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()
|
adapter?.notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -397,8 +404,8 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
if (manga != null) {
|
if (manga != null) {
|
||||||
val newStack = router.backstack.filter {
|
val newStack = router.backstack.filter {
|
||||||
it.controller() !is MangaController &&
|
it.controller() !is MangaController &&
|
||||||
it.controller() !is MigrationListController &&
|
it.controller() !is MigrationListController &&
|
||||||
it.controller() !is PreMigrationController
|
it.controller() !is PreMigrationController
|
||||||
} + MangaController(manga).withFadeTransaction()
|
} + MangaController(manga).withFadeTransaction()
|
||||||
router.setBackstack(newStack, FadeChangeHandler())
|
router.setBackstack(newStack, FadeChangeHandler())
|
||||||
return@launchUI
|
return@launchUI
|
||||||
@ -411,7 +418,7 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
|
|
||||||
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_migrating)
|
||||||
.positiveText(R.string.action_stop)
|
.positiveText(R.string.action_stop)
|
||||||
.negativeText(android.R.string.cancel)
|
.negativeText(android.R.string.cancel)
|
||||||
.onPositive { _, _ ->
|
.onPositive { _, _ ->
|
||||||
@ -441,12 +448,16 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
|
|
||||||
if (adapter?.itemCount == 1) {
|
if (adapter?.itemCount == 1) {
|
||||||
menuMigrate.icon = VectorDrawableCompat.create(
|
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)
|
menuCopy.icon.mutate()
|
||||||
menuMigrate?.icon?.setTint(if (allMangasDone) Color.WHITE else translucentWhite)
|
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
|
menuCopy.isEnabled = allMangasDone
|
||||||
menuMigrate.isEnabled = allMangasDone
|
menuMigrate.isEnabled = allMangasDone
|
||||||
}
|
}
|
||||||
@ -455,10 +466,18 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
val totalManga = adapter?.itemCount ?: 0
|
val totalManga = adapter?.itemCount ?: 0
|
||||||
val mangaSkipped = adapter?.mangasSkipped() ?: 0
|
val mangaSkipped = adapter?.mangasSkipped() ?: 0
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.action_copy_manga -> MigrationMangaDialog(this, true, totalManga, mangaSkipped)
|
R.id.action_copy_manga -> MigrationMangaDialog(
|
||||||
.showDialog(router)
|
this,
|
||||||
R.id.action_migrate_manga -> MigrationMangaDialog(this, false, totalManga, mangaSkipped)
|
true,
|
||||||
.showDialog(router)
|
totalManga,
|
||||||
|
mangaSkipped
|
||||||
|
).showDialog(router)
|
||||||
|
R.id.action_migrate_manga -> MigrationMangaDialog(
|
||||||
|
this,
|
||||||
|
false,
|
||||||
|
totalManga,
|
||||||
|
mangaSkipped
|
||||||
|
).showDialog(router)
|
||||||
else -> return super.onOptionsItemSelected(item)
|
else -> return super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package eu.kanade.tachiyomi.ui.migration.manga.process
|
package eu.kanade.tachiyomi.ui.migration.manga.process
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||||
@ -16,8 +15,7 @@ import kotlinx.coroutines.withContext
|
|||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
class MigrationProcessAdapter(
|
class MigrationProcessAdapter(
|
||||||
val controller: MigrationListController,
|
val controller: MigrationListController
|
||||||
context: Context
|
|
||||||
) : FlexibleAdapter<MigrationProcessItem>(null, controller, true) {
|
) : FlexibleAdapter<MigrationProcessItem>(null, controller, true) {
|
||||||
|
|
||||||
private val db: DatabaseHelper by injectLazy()
|
private val db: DatabaseHelper by injectLazy()
|
||||||
@ -73,8 +71,9 @@ class MigrationProcessAdapter(
|
|||||||
launchUI {
|
launchUI {
|
||||||
val manga = getItem(position)?.manga ?: return@launchUI
|
val manga = getItem(position)?.manga ?: return@launchUI
|
||||||
db.inTransaction {
|
db.inTransaction {
|
||||||
val toMangaObj = db.getManga(manga.searchResult.get() ?: return@launchUI).executeAsBlocking()
|
val toMangaObj =
|
||||||
?: return@launchUI
|
db.getManga(manga.searchResult.get() ?: return@launchUI).executeAsBlocking()
|
||||||
|
?: return@launchUI
|
||||||
migrateMangaInternal(
|
migrateMangaInternal(
|
||||||
manga.manga() ?: return@launchUI, toMangaObj, !copy
|
manga.manga() ?: return@launchUI, toMangaObj, !copy
|
||||||
)
|
)
|
||||||
@ -135,8 +134,8 @@ class MigrationProcessAdapter(
|
|||||||
db.updateMangaFavorite(prevManga).executeAsBlocking()
|
db.updateMangaFavorite(prevManga).executeAsBlocking()
|
||||||
}
|
}
|
||||||
manga.favorite = true
|
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()
|
db.updateMangaTitle(manga).executeAsBlocking()
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,10 +152,10 @@ class MigrationProcessHolder(
|
|||||||
val latestChapter = mangaChapters.maxBy { it.chapter_number }?.chapter_number ?: -1f
|
val latestChapter = mangaChapters.maxBy { it.chapter_number }?.chapter_number ?: -1f
|
||||||
|
|
||||||
if (latestChapter > 0f) {
|
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))
|
DecimalFormat("#.#").format(latestChapter))
|
||||||
} else {
|
} 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))
|
context.getString(R.string.unknown))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.PreparedGetListOfObjects
|
||||||
import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetObject
|
import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetObject
|
101
app/src/main/java/exh/util/ViewExtensions.kt
Normal file
101
app/src/main/java/exh/util/ViewExtensions.kt
Normal 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
|
||||||
|
}
|
||||||
|
}
|
@ -333,12 +333,18 @@
|
|||||||
app:layout_constraintTop_toBottomOf="@id/manga_genres_tags_wrapper" />
|
app:layout_constraintTop_toBottomOf="@id/manga_genres_tags_wrapper" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/smartsearch_merge_btn"
|
android:id="@+id/merge_btn"
|
||||||
style="@style/Widget.AppCompat.Button.Colored"
|
style="@style/Widget.MaterialComponents.Button"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="0dp"
|
||||||
android:layout_weight="1"
|
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>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
@ -357,12 +357,14 @@
|
|||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/smartsearch_replace_btn"
|
android:id="@+id/merge_btn"
|
||||||
style="@style/Widget.AppCompat.Button.Colored"
|
style="@style/Widget.MaterialComponents.Button"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="0dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="Migrate from current" />
|
android:text="@string/merge"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -488,17 +488,6 @@
|
|||||||
<string name="download_unread">Unread</string>
|
<string name="download_unread">Unread</string>
|
||||||
<string name="confirm_delete_chapters">Are you sure you want to delete the selected chapters?</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="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 -->
|
<!-- Tracking Screen -->
|
||||||
<string name="manga_tracking_tab">Tracking</string>
|
<string name="manga_tracking_tab">Tracking</string>
|
||||||
@ -567,18 +556,6 @@
|
|||||||
<!-- History fragment -->
|
<!-- History fragment -->
|
||||||
<string name="recent_manga_time">Ch. %1$s - %2$s</string>
|
<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 -->
|
<!-- Downloads activity and service -->
|
||||||
<string name="download_queue_error">Could not download chapters. You can try again in the downloads section</string>
|
<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_downloader">Downloader</string>
|
||||||
<string name="channel_new_chapters">Chapter updates</string>
|
<string name="channel_new_chapters">Chapter updates</string>
|
||||||
<string name="channel_ext_updates">Extension 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>
|
<!-- Migration -->
|
||||||
<string name="channel_backup_restore_complete">Complete</string>
|
<string name="source_migration">Source migration</string>
|
||||||
<string name="data_to_include_in_migration">Data to include in migration</string>
|
<string name="migration">Migration</string>
|
||||||
<string name="search_parameter">Search parameter (e.g. language:english)</string>
|
<string name="skip_pre_migration">Skip pre-migration</string>
|
||||||
<string name="include_extra_search_parameter">Include extra search parameter when searching</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="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_most_chapters">Use source with the most chapters (slower)</string>
|
||||||
<string name="use_first_source">Use first source with alternative</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="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 -->
|
<!-- EXH -->
|
||||||
<string name="label_login">Login</string>
|
<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_9">Radius of 9</string>
|
||||||
<string name="eh_rounded_corner_10">Radius of 10</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="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>
|
</resources>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user