浏览代码

Split up MigrationController

arkon 4 年之前
父节点
当前提交
af1935d2e4

+ 2 - 1
app/src/main/java/eu/kanade/tachiyomi/source/Source.kt

@@ -5,6 +5,7 @@ import eu.kanade.tachiyomi.extension.ExtensionManager
 import eu.kanade.tachiyomi.source.model.Page
 import eu.kanade.tachiyomi.source.model.SChapter
 import eu.kanade.tachiyomi.source.model.SManga
+import java.io.Serializable
 import rx.Observable
 import uy.kohesive.injekt.Injekt
 import uy.kohesive.injekt.api.get
@@ -12,7 +13,7 @@ import uy.kohesive.injekt.api.get
 /**
  * A basic interface for creating a source. It could be an online source, a local source, etc...
  */
-interface Source {
+interface Source : Serializable {
 
     /**
      * Id for the source. Must be unique.

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/browse/BrowseController.kt

@@ -20,7 +20,7 @@ import eu.kanade.tachiyomi.ui.base.controller.RootController
 import eu.kanade.tachiyomi.ui.base.controller.RxController
 import eu.kanade.tachiyomi.ui.base.controller.TabbedController
 import eu.kanade.tachiyomi.ui.browse.extension.ExtensionController
-import eu.kanade.tachiyomi.ui.browse.migration.MigrationController
+import eu.kanade.tachiyomi.ui.browse.migration.sources.MigrationSourcesController
 import eu.kanade.tachiyomi.ui.browse.source.SourceController
 import kotlinx.android.synthetic.main.main_activity.tabs
 import uy.kohesive.injekt.injectLazy
@@ -126,7 +126,7 @@ class BrowseController :
                 val controller: Controller = when (position) {
                     SOURCES_CONTROLLER -> SourceController()
                     EXTENSIONS_CONTROLLER -> ExtensionController()
-                    MIGRATION_CONTROLLER -> MigrationController()
+                    MIGRATION_CONTROLLER -> MigrationSourcesController()
                     else -> error("Wrong position $position")
                 }
                 router.setRoot(RouterTransaction.with(controller))

+ 0 - 110
app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/MigrationController.kt

@@ -1,110 +0,0 @@
-package eu.kanade.tachiyomi.ui.browse.migration
-
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import androidx.recyclerview.widget.LinearLayoutManager
-import eu.davidea.flexibleadapter.FlexibleAdapter
-import eu.davidea.flexibleadapter.items.IFlexible
-import eu.kanade.tachiyomi.R
-import eu.kanade.tachiyomi.databinding.MigrationControllerBinding
-import eu.kanade.tachiyomi.ui.base.controller.NucleusController
-import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
-import eu.kanade.tachiyomi.ui.browse.migration.manga.MangaAdapter
-import eu.kanade.tachiyomi.ui.browse.migration.manga.MangaItem
-import eu.kanade.tachiyomi.ui.browse.migration.search.SearchController
-import eu.kanade.tachiyomi.ui.browse.migration.sources.SourceAdapter
-import eu.kanade.tachiyomi.ui.browse.migration.sources.SourceItem
-import eu.kanade.tachiyomi.ui.browse.source.SourceDividerItemDecoration
-
-class MigrationController :
-    NucleusController<MigrationControllerBinding, MigrationPresenter>(),
-    FlexibleAdapter.OnItemClickListener {
-
-    private var adapter: FlexibleAdapter<IFlexible<*>>? = null
-
-    private var title: String? = null
-        set(value) {
-            field = value
-            setTitle()
-        }
-
-    override fun createPresenter(): MigrationPresenter {
-        return MigrationPresenter()
-    }
-
-    override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
-        binding = MigrationControllerBinding.inflate(inflater)
-        return binding.root
-    }
-
-    override fun onViewCreated(view: View) {
-        super.onViewCreated(view)
-
-        adapter = FlexibleAdapter(null, this)
-        binding.recycler.layoutManager = LinearLayoutManager(view.context)
-        binding.recycler.adapter = adapter
-        binding.recycler.addItemDecoration(SourceDividerItemDecoration(view.context))
-    }
-
-    override fun onDestroyView(view: View) {
-        adapter = null
-        super.onDestroyView(view)
-    }
-
-    override fun getTitle(): String? {
-        return title
-    }
-
-    override fun handleBack(): Boolean {
-        return if (presenter.state.selectedSource != null) {
-            presenter.deselectSource()
-            true
-        } else {
-            super.handleBack()
-        }
-    }
-
-    fun render(state: ViewState) {
-        if (state.selectedSource == null) {
-            title = resources?.getString(R.string.label_migration)
-            if (adapter !is SourceAdapter) {
-                adapter =
-                    SourceAdapter(
-                        this
-                    )
-                binding.recycler.adapter = adapter
-                adapter?.fastScroller = binding.fastScroller
-            }
-            adapter?.updateDataSet(state.sourcesWithManga)
-        } else {
-            title = state.selectedSource.toString()
-            if (adapter !is MangaAdapter) {
-                adapter =
-                    MangaAdapter(
-                        this
-                    )
-                binding.recycler.adapter = adapter
-                adapter?.fastScroller = binding.fastScroller
-            }
-            adapter?.updateDataSet(state.mangaForSource)
-        }
-    }
-
-    override fun onItemClick(view: View, position: Int): Boolean {
-        val item = adapter?.getItem(position) ?: return false
-
-        if (item is MangaItem) {
-            val controller =
-                SearchController(
-                    item.manga
-                )
-            controller.targetController = this
-
-            parentController!!.router.pushController(controller.withFadeTransaction())
-        } else if (item is SourceItem) {
-            presenter.setSelectedSource(item.source)
-        }
-        return false
-    }
-}

+ 0 - 80
app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/MigrationPresenter.kt

@@ -1,80 +0,0 @@
-package eu.kanade.tachiyomi.ui.browse.migration
-
-import android.os.Bundle
-import com.jakewharton.rxrelay.BehaviorRelay
-import eu.kanade.tachiyomi.data.database.DatabaseHelper
-import eu.kanade.tachiyomi.data.database.models.Manga
-import eu.kanade.tachiyomi.source.LocalSource
-import eu.kanade.tachiyomi.source.Source
-import eu.kanade.tachiyomi.source.SourceManager
-import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
-import eu.kanade.tachiyomi.ui.browse.migration.manga.MangaItem
-import eu.kanade.tachiyomi.ui.browse.migration.sources.SelectionHeader
-import eu.kanade.tachiyomi.ui.browse.migration.sources.SourceItem
-import eu.kanade.tachiyomi.util.lang.combineLatest
-import rx.android.schedulers.AndroidSchedulers
-import rx.schedulers.Schedulers
-import uy.kohesive.injekt.Injekt
-import uy.kohesive.injekt.api.get
-
-class MigrationPresenter(
-    private val sourceManager: SourceManager = Injekt.get(),
-    private val db: DatabaseHelper = Injekt.get()
-) : BasePresenter<MigrationController>() {
-
-    var state = ViewState()
-        private set(value) {
-            field = value
-            stateRelay.call(value)
-        }
-
-    private val stateRelay = BehaviorRelay.create(state)
-
-    override fun onCreate(savedState: Bundle?) {
-        super.onCreate(savedState)
-
-        db.getFavoriteMangas()
-            .asRxObservable()
-            .observeOn(AndroidSchedulers.mainThread())
-            .doOnNext { state = state.copy(sourcesWithManga = findSourcesWithManga(it)) }
-            .combineLatest(
-                stateRelay.map { it.selectedSource }
-                    .distinctUntilChanged()
-            ) { library, source -> library to source }
-            .filter { (_, source) -> source != null }
-            .observeOn(Schedulers.io())
-            .map { (library, source) -> libraryToMigrationItem(library, source!!.id) }
-            .observeOn(AndroidSchedulers.mainThread())
-            .doOnNext { state = state.copy(mangaForSource = it) }
-            .subscribe()
-
-        // Render the view when any field changes
-        stateRelay.subscribeLatestCache(MigrationController::render)
-    }
-
-    fun setSelectedSource(source: Source) {
-        state = state.copy(selectedSource = source, mangaForSource = emptyList())
-    }
-
-    fun deselectSource() {
-        state = state.copy(selectedSource = null, mangaForSource = emptyList())
-    }
-
-    private fun findSourcesWithManga(library: List<Manga>): List<SourceItem> {
-        val header =
-            SelectionHeader()
-        return library.map { it.source }.toSet()
-            .mapNotNull { if (it != LocalSource.ID) sourceManager.getOrStub(it) else null }
-            .sortedBy { it.name }
-            .map {
-                SourceItem(
-                    it,
-                    header
-                )
-            }
-    }
-
-    private fun libraryToMigrationItem(library: List<Manga>, sourceId: Long): List<MangaItem> {
-        return library.filter { it.source == sourceId }.map(::MangaItem)
-    }
-}

+ 0 - 11
app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/ViewState.kt

@@ -1,11 +0,0 @@
-package eu.kanade.tachiyomi.ui.browse.migration
-
-import eu.kanade.tachiyomi.source.Source
-import eu.kanade.tachiyomi.ui.browse.migration.manga.MangaItem
-import eu.kanade.tachiyomi.ui.browse.migration.sources.SourceItem
-
-data class ViewState(
-    val selectedSource: Source? = null,
-    val mangaForSource: List<MangaItem> = emptyList(),
-    val sourcesWithManga: List<SourceItem> = emptyList()
-)

+ 0 - 18
app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/manga/MangaAdapter.kt

@@ -1,18 +0,0 @@
-package eu.kanade.tachiyomi.ui.browse.migration.manga
-
-import eu.davidea.flexibleadapter.FlexibleAdapter
-import eu.davidea.flexibleadapter.items.IFlexible
-import eu.kanade.tachiyomi.ui.browse.migration.MigrationController
-
-class MangaAdapter(controller: MigrationController) :
-    FlexibleAdapter<IFlexible<*>>(null, controller) {
-
-    private var items: List<IFlexible<*>>? = null
-
-    override fun updateDataSet(items: MutableList<IFlexible<*>>?) {
-        if (this.items !== items) {
-            this.items = items
-            super.updateDataSet(items)
-        }
-    }
-}

+ 4 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/manga/MangaItem.kt

@@ -1,5 +1,6 @@
 package eu.kanade.tachiyomi.ui.browse.migration.manga
 
+import android.os.Parcelable
 import android.view.View
 import androidx.recyclerview.widget.RecyclerView
 import eu.davidea.flexibleadapter.FlexibleAdapter
@@ -7,8 +8,10 @@ import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
 import eu.davidea.flexibleadapter.items.IFlexible
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.database.models.Manga
+import kotlinx.android.parcel.Parcelize
 
-class MangaItem(val manga: Manga) : AbstractFlexibleItem<MangaHolder>() {
+@Parcelize
+class MangaItem(val manga: Manga) : AbstractFlexibleItem<MangaHolder>(), Parcelable {
 
     override fun getLayoutRes(): Int {
         return R.layout.source_list_item

+ 76 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/manga/MigrationMangaController.kt

@@ -0,0 +1,76 @@
+package eu.kanade.tachiyomi.ui.browse.migration.manga
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.recyclerview.widget.LinearLayoutManager
+import eu.davidea.flexibleadapter.FlexibleAdapter
+import eu.davidea.flexibleadapter.items.IFlexible
+import eu.kanade.tachiyomi.databinding.MigrationControllerBinding
+import eu.kanade.tachiyomi.source.Source
+import eu.kanade.tachiyomi.ui.base.controller.NucleusController
+import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
+import eu.kanade.tachiyomi.ui.browse.migration.search.SearchController
+import eu.kanade.tachiyomi.ui.browse.source.SourceDividerItemDecoration
+
+class MigrationMangaController :
+    NucleusController<MigrationControllerBinding, MigrationMangaPresenter>,
+    FlexibleAdapter.OnItemClickListener {
+
+    private var adapter: FlexibleAdapter<IFlexible<*>>? = null
+
+    constructor(source: Source) : super(
+        Bundle().apply {
+            putSerializable(SOURCE_EXTRA, source)
+        }
+    )
+
+    @Suppress("unused")
+    constructor(bundle: Bundle) : this(bundle.getSerializable(SOURCE_EXTRA) as Source)
+
+    private val source: Source = args.getSerializable(SOURCE_EXTRA) as Source
+
+    override fun getTitle(): String? {
+        return source.name
+    }
+
+    override fun createPresenter(): MigrationMangaPresenter {
+        return MigrationMangaPresenter(source.id)
+    }
+
+    override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
+        binding = MigrationControllerBinding.inflate(inflater)
+        return binding.root
+    }
+
+    override fun onViewCreated(view: View) {
+        super.onViewCreated(view)
+
+        adapter = FlexibleAdapter<IFlexible<*>>(null, this)
+        binding.recycler.layoutManager = LinearLayoutManager(view.context)
+        binding.recycler.adapter = adapter
+        binding.recycler.addItemDecoration(SourceDividerItemDecoration(view.context))
+        adapter?.fastScroller = binding.fastScroller
+    }
+
+    override fun onDestroyView(view: View) {
+        adapter = null
+        super.onDestroyView(view)
+    }
+
+    fun setManga(manga: List<MangaItem>) {
+        adapter?.updateDataSet(manga)
+    }
+
+    override fun onItemClick(view: View, position: Int): Boolean {
+        val item = adapter?.getItem(position) as? MangaItem ?: return false
+        val controller = SearchController(item.manga)
+        router.pushController(controller.withFadeTransaction())
+        return false
+    }
+
+    companion object {
+        const val SOURCE_EXTRA = "source_id_extra"
+    }
+}

+ 31 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/manga/MigrationMangaPresenter.kt

@@ -0,0 +1,31 @@
+package eu.kanade.tachiyomi.ui.browse.migration.manga
+
+import android.os.Bundle
+import eu.kanade.tachiyomi.data.database.DatabaseHelper
+import eu.kanade.tachiyomi.data.database.models.Manga
+import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
+import rx.android.schedulers.AndroidSchedulers
+import uy.kohesive.injekt.Injekt
+import uy.kohesive.injekt.api.get
+
+class MigrationMangaPresenter(
+    private val sourceId: Long,
+    private val db: DatabaseHelper = Injekt.get()
+) : BasePresenter<MigrationMangaController>() {
+
+    override fun onCreate(savedState: Bundle?) {
+        super.onCreate(savedState)
+
+        db.getFavoriteMangas()
+            .asRxObservable()
+            .observeOn(AndroidSchedulers.mainThread())
+            .map { libraryToMigrationItem(it) }
+            .subscribeLatestCache(MigrationMangaController::setManga)
+    }
+
+    private fun libraryToMigrationItem(library: List<Manga>): List<MangaItem> {
+        return library.filter { it.source == sourceId }
+            .sortedBy { it.title }
+            .map { MangaItem(it) }
+    }
+}

+ 54 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrationSourcesController.kt

@@ -0,0 +1,54 @@
+package eu.kanade.tachiyomi.ui.browse.migration.sources
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.recyclerview.widget.LinearLayoutManager
+import eu.davidea.flexibleadapter.FlexibleAdapter
+import eu.kanade.tachiyomi.databinding.MigrationControllerBinding
+import eu.kanade.tachiyomi.ui.base.controller.NucleusController
+import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
+import eu.kanade.tachiyomi.ui.browse.migration.manga.MigrationMangaController
+import eu.kanade.tachiyomi.ui.browse.source.SourceDividerItemDecoration
+
+class MigrationSourcesController :
+    NucleusController<MigrationControllerBinding, MigrationSourcesPresenter>(),
+    FlexibleAdapter.OnItemClickListener {
+
+    private var adapter: SourceAdapter? = null
+
+    override fun createPresenter(): MigrationSourcesPresenter {
+        return MigrationSourcesPresenter()
+    }
+
+    override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
+        binding = MigrationControllerBinding.inflate(inflater)
+        return binding.root
+    }
+
+    override fun onViewCreated(view: View) {
+        super.onViewCreated(view)
+
+        adapter = SourceAdapter(this)
+        binding.recycler.layoutManager = LinearLayoutManager(view.context)
+        binding.recycler.adapter = adapter
+        binding.recycler.addItemDecoration(SourceDividerItemDecoration(view.context))
+        adapter?.fastScroller = binding.fastScroller
+    }
+
+    override fun onDestroyView(view: View) {
+        adapter = null
+        super.onDestroyView(view)
+    }
+
+    fun setSources(sourcesWithManga: List<SourceItem>) {
+        adapter?.updateDataSet(sourcesWithManga)
+    }
+
+    override fun onItemClick(view: View, position: Int): Boolean {
+        val item = adapter?.getItem(position) as? SourceItem ?: return false
+        val controller = MigrationMangaController(item.source)
+        parentController!!.router.pushController(controller.withFadeTransaction())
+        return false
+    }
+}

+ 35 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrationSourcesPresenter.kt

@@ -0,0 +1,35 @@
+package eu.kanade.tachiyomi.ui.browse.migration.sources
+
+import android.os.Bundle
+import eu.kanade.tachiyomi.data.database.DatabaseHelper
+import eu.kanade.tachiyomi.data.database.models.Manga
+import eu.kanade.tachiyomi.source.LocalSource
+import eu.kanade.tachiyomi.source.SourceManager
+import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
+import rx.android.schedulers.AndroidSchedulers
+import uy.kohesive.injekt.Injekt
+import uy.kohesive.injekt.api.get
+
+class MigrationSourcesPresenter(
+    private val sourceManager: SourceManager = Injekt.get(),
+    private val db: DatabaseHelper = Injekt.get()
+) : BasePresenter<MigrationSourcesController>() {
+
+    override fun onCreate(savedState: Bundle?) {
+        super.onCreate(savedState)
+
+        db.getFavoriteMangas()
+            .asRxObservable()
+            .observeOn(AndroidSchedulers.mainThread())
+            .map { findSourcesWithManga(it) }
+            .subscribeLatestCache(MigrationSourcesController::setSources)
+    }
+
+    private fun findSourcesWithManga(library: List<Manga>): List<SourceItem> {
+        val header = SelectionHeader()
+        return library.map { it.source }.toSet()
+            .mapNotNull { if (it != LocalSource.ID) sourceManager.getOrStub(it) else null }
+            .sortedBy { it.name }
+            .map { SourceItem(it, header) }
+    }
+}

+ 2 - 11
app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/SourceAdapter.kt

@@ -1,9 +1,9 @@
 package eu.kanade.tachiyomi.ui.browse.migration.sources
 
+import com.bluelinelabs.conductor.Controller
 import eu.davidea.flexibleadapter.FlexibleAdapter
 import eu.davidea.flexibleadapter.items.IFlexible
 import eu.kanade.tachiyomi.R
-import eu.kanade.tachiyomi.ui.browse.migration.MigrationController
 import eu.kanade.tachiyomi.util.system.getResourceColor
 
 /**
@@ -11,21 +11,12 @@ import eu.kanade.tachiyomi.util.system.getResourceColor
  *
  * @param controller instance of [MigrationController].
  */
-class SourceAdapter(val controller: MigrationController) :
+class SourceAdapter(val controller: Controller) :
     FlexibleAdapter<IFlexible<*>>(null, controller, true) {
 
     val cardBackground = controller.activity!!.getResourceColor(R.attr.colorSurface)
 
-    private var items: List<IFlexible<*>>? = null
-
     init {
         setDisplayHeadersAtStartUp(true)
     }
-
-    override fun updateDataSet(items: MutableList<IFlexible<*>>?) {
-        if (this.items !== items) {
-            this.items = items
-            super.updateDataSet(items)
-        }
-    }
 }

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/SourceItem.kt

@@ -14,7 +14,7 @@ import eu.kanade.tachiyomi.source.Source
  * @param source Instance of [Source] containing source information.
  * @param header The header for this item.
  */
-data class SourceItem(val source: Source, val header: SelectionHeader? = null) :
+data class SourceItem(val source: Source, val header: SelectionHeader) :
     AbstractSectionableItem<SourceHolder, SelectionHeader>(header) {
 
     /**