Initial work on auto-migrate

This commit is contained in:
NerdNumber9
2019-07-30 19:29:12 -04:00
parent e7abe27bb6
commit f811cc5c87
16 changed files with 722 additions and 0 deletions

View File

@ -39,6 +39,7 @@ import eu.kanade.tachiyomi.util.toast
import exh.favorites.FavoritesIntroDialog
import exh.favorites.FavoritesSyncStatus
import exh.ui.LoaderManager
import exh.ui.migration.manga.design.MigrationDesignController
import kotlinx.android.synthetic.main.library_controller.*
import kotlinx.android.synthetic.main.main_activity.*
import rx.Subscription
@ -435,6 +436,10 @@ class LibraryController(
}
R.id.action_move_to_category -> showChangeMangaCategoriesDialog()
R.id.action_delete -> showDeleteMangaDialog()
R.id.action_auto_source_migration -> {
destroyActionModeIfNeeded()
router.pushController(MigrationDesignController().withFadeTransaction())
}
else -> return false
}
return true

View File

@ -0,0 +1,29 @@
package exh.ui.base
import android.support.annotation.LayoutRes
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import eu.kanade.tachiyomi.ui.base.controller.BaseController
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlin.coroutines.CoroutineContext
abstract class BaseExhController : BaseController(), CoroutineScope {
abstract val layoutId: Int
@LayoutRes get
override val coroutineContext: CoroutineContext = Job() + Dispatchers.Default
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
return inflater.inflate(layoutId, container, false)
}
override fun onDestroy() {
super.onDestroy()
cancel()
}
}

View File

@ -0,0 +1,91 @@
package exh.ui.migration.manga.design
import android.support.v7.widget.LinearLayoutManager
import android.view.View
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
import exh.ui.base.BaseExhController
import exh.ui.migration.manga.process.MigrationProcedureController
import kotlinx.android.synthetic.main.eh_migration_design.*
import uy.kohesive.injekt.injectLazy
// TODO Handle config changes
// TODO Select all in library
class MigrationDesignController : BaseExhController(), FlexibleAdapter.OnItemClickListener {
private val sourceManager: SourceManager by injectLazy()
private val prefs: PreferencesHelper by injectLazy()
override val layoutId: Int = R.layout.eh_migration_design
private var adapter: FlexibleAdapter<MigrationSourceItem>? = null
override fun getTitle() = "Select target sources"
override fun onViewCreated(view: View) {
super.onViewCreated(view)
adapter = MigrationSourceAdapter(
getEnabledSources().map { MigrationSourceItem(it, true) },
this
)
recycler.layoutManager = LinearLayoutManager(view.context)
recycler.setHasFixedSize(true)
recycler.adapter = adapter
adapter?.isHandleDragEnabled = true
migration_mode.setOnClickListener {
prioritize_chapter_count.toggle()
}
fuzzy_search.setOnClickListener {
use_smart_search.toggle()
}
prioritize_chapter_count.setOnCheckedChangeListener { _, b ->
updatePrioritizeChapterCount(b)
}
updatePrioritizeChapterCount(prioritize_chapter_count.isChecked)
begin_migration_btn.setOnClickListener {
router.replaceTopController(MigrationProcedureController().withFadeTransaction())
}
}
private fun updatePrioritizeChapterCount(migrationMode: Boolean) {
migration_mode.text = if(migrationMode) {
"Use source with most chapters and use the above list to break ties"
} else {
"Use the first source in the list that has at least one chapter of the manga"
}
}
override fun onItemClick(view: View, position: Int): Boolean {
adapter?.getItem(position)?.let {
it.sourceEnabled = !it.sourceEnabled
}
adapter?.notifyItemChanged(position)
return false
}
/**
* Returns a list of enabled sources ordered by language and name.
*
* @return list containing enabled sources.
*/
private fun getEnabledSources(): List<HttpSource> {
val languages = prefs.enabledLanguages().getOrDefault()
val hiddenCatalogues = prefs.hiddenCatalogues().getOrDefault()
return sourceManager.getVisibleCatalogueSources()
.filterIsInstance<HttpSource>()
.filter { it.lang in languages }
.filterNot { it.id.toString() in hiddenCatalogues }
.sortedBy { "(${it.lang}) ${it.name}" }
}
}

View File

@ -0,0 +1,10 @@
package exh.ui.migration.manga.design
import eu.davidea.flexibleadapter.FlexibleAdapter
class MigrationSourceAdapter(val items: List<MigrationSourceItem>,
val controller: MigrationDesignController): FlexibleAdapter<MigrationSourceItem>(
items,
controller,
true
)

View File

@ -0,0 +1,40 @@
package exh.ui.migration.manga.design
import android.view.View
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
import eu.kanade.tachiyomi.util.getRound
import kotlinx.android.synthetic.main.eh_source_item.*
import android.graphics.Paint.STRIKE_THRU_TEXT_FLAG
class MigrationSourceHolder(view: View, val adapter: FlexibleAdapter<MigrationSourceItem>):
BaseFlexibleViewHolder(view, adapter) {
init {
setDragHandleView(reorder)
}
fun bind(source: HttpSource, sourceEnabled: Boolean) {
// Set capitalized title.
title.text = source.name.capitalize()
// Update circle letter image.
itemView.post {
image.setImageDrawable(image.getRound(source.name.take(1).toUpperCase(),false))
}
if(sourceEnabled) {
title.alpha = 1.0f
image.alpha = 1.0f
title.paintFlags = title.paintFlags and STRIKE_THRU_TEXT_FLAG.inv()
} else {
title.alpha = DISABLED_ALPHA
image.alpha = DISABLED_ALPHA
title.paintFlags = title.paintFlags or STRIKE_THRU_TEXT_FLAG
}
}
companion object {
private const val DISABLED_ALPHA = 0.3f
}
}

View File

@ -0,0 +1,51 @@
package exh.ui.migration.manga.design
import android.support.v7.widget.RecyclerView
import android.view.View
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.online.HttpSource
class MigrationSourceItem(val source: HttpSource, var sourceEnabled: Boolean): AbstractFlexibleItem<MigrationSourceHolder>() {
override fun getLayoutRes() = R.layout.eh_source_item
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): MigrationSourceHolder {
return MigrationSourceHolder(view, adapter as MigrationSourceAdapter)
}
/**
* Binds the given view holder with this item.
*
* @param adapter The adapter of this item.
* @param holder The holder to bind.
* @param position The position of this item in the adapter.
* @param payloads List of partial changes.
*/
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>,
holder: MigrationSourceHolder,
position: Int,
payloads: List<Any?>?) {
holder.bind(source, sourceEnabled)
}
/**
* Returns true if this item is draggable.
*/
override fun isDraggable(): Boolean {
return true
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other is MigrationSourceItem) {
return source.id == other.source.id
}
return false
}
override fun hashCode(): Int {
return source.id.hashCode()
}
}

View File

@ -0,0 +1,34 @@
package exh.ui.migration.manga.process
import android.content.pm.ActivityInfo
import android.os.Build
import android.view.View
import eu.kanade.tachiyomi.R
import exh.ui.base.BaseExhController
class MigrationProcedureController : BaseExhController() {
override val layoutId = R.layout.eh_migration_process
private var titleText = "Migrate manga (1/300)"
override fun getTitle(): String {
return titleText
}
override fun onViewCreated(view: View) {
super.onViewCreated(view)
setTitle()
activity?.requestedOrientation = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
} else {
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
}
}
override fun onDestroy() {
super.onDestroy()
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
}
}