소스 검색

Merge sources and extensions into one view

arkon 4 년 전
부모
커밋
d593362ba8
71개의 변경된 파일262개의 추가작업 그리고 191개의 파일을 삭제
  1. 2 2
      app/shortcuts.xml
  2. 145 0
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/BrowseController.kt
  3. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionAdapter.kt
  4. 7 3
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionController.kt
  5. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionDetailsController.kt
  6. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionDetailsPresenter.kt
  7. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionDividerItemDecoration.kt
  8. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionFilterController.kt
  9. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionGroupHolder.kt
  10. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionGroupItem.kt
  11. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionHolder.kt
  12. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionItem.kt
  13. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionPresenter.kt
  14. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionTrustDialog.kt
  15. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionViewUtils.kt
  16. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/LangHolder.kt
  17. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/LangItem.kt
  18. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceAdapter.kt
  19. 8 9
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceController.kt
  20. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceDividerItemDecoration.kt
  21. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceHolder.kt
  22. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceItem.kt
  23. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcePresenter.kt
  24. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt
  25. 14 14
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourcePresenter.kt
  26. 3 0
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/NoResultsException.kt
  27. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/Pager.kt
  28. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/ProgressItem.kt
  29. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceFilterSheet.kt
  30. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceGridHolder.kt
  31. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceHolder.kt
  32. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceItem.kt
  33. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceListHolder.kt
  34. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourcePager.kt
  35. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/CheckboxItem.kt
  36. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/GroupItem.kt
  37. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/HeaderItem.kt
  38. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/SectionItems.kt
  39. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/SelectItem.kt
  40. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/SeparatorItem.kt
  41. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/SortGroup.kt
  42. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/SortItem.kt
  43. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/TextItem.kt
  44. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/TriStateItem.kt
  45. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchAdapter.kt
  46. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchCardAdapter.kt
  47. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchCardHolder.kt
  48. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchCardItem.kt
  49. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchController.kt
  50. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchHolder.kt
  51. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchItem.kt
  52. 2 2
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchPresenter.kt
  53. 3 3
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/latest/LatestUpdatesController.kt
  54. 2 2
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/latest/LatestUpdatesPager.kt
  55. 3 3
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/latest/LatestUpdatesPresenter.kt
  56. 8 9
      app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt
  57. 7 7
      app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt
  58. 2 2
      app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoController.kt
  59. 2 2
      app/src/main/java/eu/kanade/tachiyomi/ui/migration/SearchController.kt
  60. 3 3
      app/src/main/java/eu/kanade/tachiyomi/ui/migration/SearchPresenter.kt
  61. 0 13
      app/src/main/java/eu/kanade/tachiyomi/ui/more/MoreController.kt
  62. 0 3
      app/src/main/java/eu/kanade/tachiyomi/ui/source/browse/NoResultsException.kt
  63. 0 5
      app/src/main/java/eu/kanade/tachiyomi/util/preference/PreferenceDSL.kt
  64. 1 1
      app/src/main/java/eu/kanade/tachiyomi/util/system/LocaleHelper.kt
  65. 0 37
      app/src/main/java/eu/kanade/tachiyomi/widget/preference/BadgePreference.kt
  66. 0 9
      app/src/main/res/drawable/round_textview_background.xml
  67. 1 1
      app/src/main/res/layout/manga_info_controller.xml
  68. 1 1
      app/src/main/res/layout/pager_controller.xml
  69. 0 12
      app/src/main/res/layout/pref_badge.xml
  70. 1 1
      app/src/main/res/layout/source_controller.xml
  71. 2 2
      app/src/main/res/menu/bottom_nav.xml

+ 2 - 2
app/shortcuts.xml

@@ -38,8 +38,8 @@
         android:icon="@drawable/sc_explore_48dp"
         android:shortcutDisabledMessage="@string/app_not_available"
         android:shortcutId="show_catalogues"
-        android:shortcutLongLabel="@string/label_sources"
-        android:shortcutShortLabel="@string/label_sources">
+        android:shortcutLongLabel="@string/browse"
+        android:shortcutShortLabel="@string/browse">
         <intent
             android:action="eu.kanade.tachiyomi.SHOW_CATALOGUES"
             android:targetClass="eu.kanade.tachiyomi.ui.main.MainActivity" />

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

@@ -0,0 +1,145 @@
+package eu.kanade.tachiyomi.ui.browse
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.bluelinelabs.conductor.Controller
+import com.bluelinelabs.conductor.ControllerChangeHandler
+import com.bluelinelabs.conductor.ControllerChangeType
+import com.bluelinelabs.conductor.Router
+import com.bluelinelabs.conductor.RouterTransaction
+import com.bluelinelabs.conductor.support.RouterPagerAdapter
+import com.google.android.material.badge.BadgeDrawable
+import com.google.android.material.tabs.TabLayout
+import eu.kanade.tachiyomi.R
+import eu.kanade.tachiyomi.data.preference.PreferencesHelper
+import eu.kanade.tachiyomi.databinding.PagerControllerBinding
+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.source.SourceController
+import kotlinx.android.synthetic.main.main_activity.tabs
+import uy.kohesive.injekt.injectLazy
+
+class BrowseController :
+    RxController<PagerControllerBinding>,
+    RootController,
+    TabbedController {
+
+    constructor(toExtensions: Boolean = false) : super(
+        Bundle().apply {
+            putBoolean(TO_EXTENSIONS_EXTRA, toExtensions)
+        }
+    )
+
+    @Suppress("unused")
+    constructor(bundle: Bundle) : this(bundle.getBoolean(TO_EXTENSIONS_EXTRA))
+
+    private val preferences: PreferencesHelper by injectLazy()
+
+    private val toExtensions = args.getBoolean(TO_EXTENSIONS_EXTRA, false)
+
+    private var adapter: BrowseAdapter? = null
+
+    override fun getTitle(): String? {
+        return resources!!.getString(R.string.browse)
+    }
+
+    override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
+        binding = PagerControllerBinding.inflate(inflater)
+        return binding.root
+    }
+
+    override fun onViewCreated(view: View) {
+        super.onViewCreated(view)
+
+        adapter = BrowseAdapter()
+        binding.pager.adapter = adapter
+
+        if (toExtensions) {
+            binding.pager.currentItem = EXTENSIONS_CONTROLLER
+        }
+    }
+
+    override fun onDestroyView(view: View) {
+        super.onDestroyView(view)
+        adapter = null
+    }
+
+    override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) {
+        super.onChangeStarted(handler, type)
+        if (type.isEnter) {
+            activity?.tabs?.apply {
+                setupWithViewPager(binding.pager)
+
+                // Show badge on tab for extension updates
+                setExtensionUpdateBadge()
+            }
+        }
+    }
+
+    override fun configureTabs(tabs: TabLayout) {
+        with(tabs) {
+            tabGravity = TabLayout.GRAVITY_FILL
+            tabMode = TabLayout.MODE_FIXED
+        }
+    }
+
+    override fun cleanupTabs(tabs: TabLayout) {
+        // Remove extension update badge
+        tabs.getTabAt(EXTENSIONS_CONTROLLER)?.removeBadge()
+    }
+
+    fun pushController(transaction: RouterTransaction) {
+        router.pushController(transaction)
+    }
+
+    fun setExtensionUpdateBadge() {
+        activity?.tabs?.apply {
+            val updates = preferences.extensionUpdatesCount().get()
+            if (updates > 0) {
+                val badge: BadgeDrawable = getTabAt(1)!!.orCreateBadge
+                badge.isVisible = true
+            } else {
+                getTabAt(EXTENSIONS_CONTROLLER)!!.removeBadge()
+            }
+        }
+    }
+
+    private inner class BrowseAdapter : RouterPagerAdapter(this@BrowseController) {
+
+        private val tabTitles = listOf(
+            R.string.label_sources,
+            R.string.label_extensions
+        )
+            .map { resources!!.getString(it) }
+
+        override fun getCount(): Int {
+            return tabTitles.size
+        }
+
+        override fun configureRouter(router: Router, position: Int) {
+            if (!router.hasRootController()) {
+                val controller: Controller = when (position) {
+                    SOURCES_CONTROLLER -> SourceController()
+                    EXTENSIONS_CONTROLLER -> ExtensionController()
+                    else -> error("Wrong position $position")
+                }
+                router.setRoot(RouterTransaction.with(controller))
+            }
+        }
+
+        override fun getPageTitle(position: Int): CharSequence {
+            return tabTitles[position]
+        }
+    }
+
+    companion object {
+        const val TO_EXTENSIONS_EXTRA = "to_extensions"
+
+        const val SOURCES_CONTROLLER = 0
+        const val EXTENSIONS_CONTROLLER = 1
+    }
+}

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/extension/ExtensionAdapter.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionAdapter.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.extension
+package eu.kanade.tachiyomi.ui.browse.extension
 
 import eu.davidea.flexibleadapter.FlexibleAdapter
 import eu.davidea.flexibleadapter.items.IFlexible

+ 7 - 3
app/src/main/java/eu/kanade/tachiyomi/ui/extension/ExtensionController.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionController.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.extension
+package eu.kanade.tachiyomi.ui.browse.extension
 
 import android.view.LayoutInflater
 import android.view.Menu
@@ -21,6 +21,7 @@ import eu.kanade.tachiyomi.extension.ExtensionUpdateJob
 import eu.kanade.tachiyomi.extension.model.Extension
 import eu.kanade.tachiyomi.ui.base.controller.NucleusController
 import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
+import eu.kanade.tachiyomi.ui.browse.BrowseController
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
@@ -93,7 +94,7 @@ open class ExtensionController :
         when (item.itemId) {
             R.id.action_search -> expandActionViewFromInteraction = true
             R.id.action_settings -> {
-                router.pushController(
+                (parentController as BrowseController).pushController(
                     (RouterTransaction.with(ExtensionFilterController()))
                         .popChangeHandler(SettingsExtensionsFadeChangeHandler())
                         .pushChangeHandler(FadeChangeHandler())
@@ -182,7 +183,7 @@ open class ExtensionController :
 
     private fun openDetails(extension: Extension.Installed) {
         val controller = ExtensionDetailsController(extension.pkgName)
-        router.pushController(controller.withFadeTransaction())
+        (parentController as BrowseController).pushController(controller.withFadeTransaction())
     }
 
     private fun openTrustDialog(extension: Extension.Untrusted) {
@@ -194,6 +195,9 @@ open class ExtensionController :
         binding.extSwipeRefresh.isRefreshing = false
         this.extensions = extensions
         drawExtensions()
+
+        // Update badge on parent controller tab
+        (parentController as BrowseController).setExtensionUpdateBadge()
     }
 
     fun drawExtensions() {

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/extension/ExtensionDetailsController.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionDetailsController.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.extension
+package eu.kanade.tachiyomi.ui.browse.extension
 
 import android.annotation.SuppressLint
 import android.content.Context

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/extension/ExtensionDetailsPresenter.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionDetailsPresenter.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.extension
+package eu.kanade.tachiyomi.ui.browse.extension
 
 import android.os.Bundle
 import eu.kanade.tachiyomi.extension.ExtensionManager

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/extension/ExtensionDividerItemDecoration.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionDividerItemDecoration.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.extension
+package eu.kanade.tachiyomi.ui.browse.extension
 
 import android.content.Context
 import android.graphics.Canvas

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/extension/ExtensionFilterController.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionFilterController.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.extension
+package eu.kanade.tachiyomi.ui.browse.extension
 
 import androidx.preference.PreferenceScreen
 import eu.kanade.tachiyomi.R

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/extension/ExtensionGroupHolder.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionGroupHolder.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.extension
+package eu.kanade.tachiyomi.ui.browse.extension
 
 import android.annotation.SuppressLint
 import android.view.View

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/extension/ExtensionGroupItem.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionGroupItem.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.extension
+package eu.kanade.tachiyomi.ui.browse.extension
 
 import android.view.View
 import androidx.recyclerview.widget.RecyclerView

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/extension/ExtensionHolder.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionHolder.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.extension
+package eu.kanade.tachiyomi.ui.browse.extension
 
 import android.view.View
 import eu.kanade.tachiyomi.R

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/extension/ExtensionItem.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionItem.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.extension
+package eu.kanade.tachiyomi.ui.browse.extension
 
 import android.view.View
 import androidx.recyclerview.widget.RecyclerView

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/extension/ExtensionPresenter.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionPresenter.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.extension
+package eu.kanade.tachiyomi.ui.browse.extension
 
 import android.app.Application
 import android.os.Bundle

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/extension/ExtensionTrustDialog.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionTrustDialog.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.extension
+package eu.kanade.tachiyomi.ui.browse.extension
 
 import android.app.Dialog
 import android.os.Bundle

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/extension/ExtensionViewUtils.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionViewUtils.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.extension
+package eu.kanade.tachiyomi.ui.browse.extension
 
 import android.content.Context
 import android.content.pm.PackageManager

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/LangHolder.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/LangHolder.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source
+package eu.kanade.tachiyomi.ui.browse.source
 
 import android.view.View
 import eu.davidea.flexibleadapter.FlexibleAdapter

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/LangItem.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/LangItem.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source
+package eu.kanade.tachiyomi.ui.browse.source
 
 import android.view.View
 import androidx.recyclerview.widget.RecyclerView

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/SourceAdapter.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceAdapter.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source
+package eu.kanade.tachiyomi.ui.browse.source
 
 import eu.davidea.flexibleadapter.FlexibleAdapter
 import eu.davidea.flexibleadapter.items.IFlexible

+ 8 - 9
app/src/main/java/eu/kanade/tachiyomi/ui/source/SourceController.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceController.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source
+package eu.kanade.tachiyomi.ui.browse.source
 
 import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
 import android.view.LayoutInflater
@@ -23,13 +23,13 @@ import eu.kanade.tachiyomi.databinding.SourceMainControllerBinding
 import eu.kanade.tachiyomi.source.CatalogueSource
 import eu.kanade.tachiyomi.source.Source
 import eu.kanade.tachiyomi.ui.base.controller.NucleusController
-import eu.kanade.tachiyomi.ui.base.controller.RootController
 import eu.kanade.tachiyomi.ui.base.controller.requestPermissionsSafe
 import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
+import eu.kanade.tachiyomi.ui.browse.BrowseController
+import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceController
+import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchController
+import eu.kanade.tachiyomi.ui.browse.source.latest.LatestUpdatesController
 import eu.kanade.tachiyomi.ui.setting.SettingsSourcesController
-import eu.kanade.tachiyomi.ui.source.browse.BrowseSourceController
-import eu.kanade.tachiyomi.ui.source.globalsearch.GlobalSearchController
-import eu.kanade.tachiyomi.ui.source.latest.LatestUpdatesController
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
@@ -46,7 +46,6 @@ import uy.kohesive.injekt.api.get
  */
 class SourceController :
     NucleusController<SourceMainControllerBinding, SourcePresenter>(),
-    RootController,
     FlexibleAdapter.OnItemClickListener,
     FlexibleAdapter.OnItemLongClickListener,
     SourceAdapter.OnBrowseClickListener,
@@ -178,7 +177,7 @@ class SourceController :
      */
     private fun openCatalogue(source: CatalogueSource, controller: BrowseSourceController) {
         preferences.lastUsedCatalogueSource().set(source.id)
-        router.pushController(controller.withFadeTransaction())
+        (parentController as BrowseController).pushController(controller.withFadeTransaction())
     }
 
     /**
@@ -206,7 +205,7 @@ class SourceController :
     }
 
     fun performGlobalSearch(query: String) {
-        router.pushController(GlobalSearchController(query).withFadeTransaction())
+        (parentController as BrowseController).pushController(GlobalSearchController(query).withFadeTransaction())
     }
 
     /**
@@ -219,7 +218,7 @@ class SourceController :
         when (item.itemId) {
             // Initialize option to open catalogue settings.
             R.id.action_settings -> {
-                router.pushController(
+                (parentController as BrowseController).pushController(
                     (RouterTransaction.with(SettingsSourcesController()))
                         .popChangeHandler(SettingsSourcesFadeChangeHandler())
                         .pushChangeHandler(FadeChangeHandler())

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/SourceDividerItemDecoration.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceDividerItemDecoration.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source
+package eu.kanade.tachiyomi.ui.browse.source
 
 import android.content.Context
 import android.graphics.Canvas

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/SourceHolder.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceHolder.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source
+package eu.kanade.tachiyomi.ui.browse.source
 
 import android.view.View
 import eu.kanade.tachiyomi.R

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

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source
+package eu.kanade.tachiyomi.ui.browse.source
 
 import android.view.View
 import androidx.recyclerview.widget.RecyclerView

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/SourcePresenter.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcePresenter.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source
+package eu.kanade.tachiyomi.ui.browse.source
 
 import android.os.Bundle
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/browse/BrowseSourceController.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.browse
+package eu.kanade.tachiyomi.ui.browse.source.browse
 
 import android.content.res.Configuration
 import android.os.Bundle

+ 14 - 14
app/src/main/java/eu/kanade/tachiyomi/ui/source/browse/BrowseSourcePresenter.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourcePresenter.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.browse
+package eu.kanade.tachiyomi.ui.browse.source.browse
 
 import android.os.Bundle
 import eu.davidea.flexibleadapter.items.IFlexible
@@ -15,19 +15,19 @@ import eu.kanade.tachiyomi.source.model.Filter
 import eu.kanade.tachiyomi.source.model.FilterList
 import eu.kanade.tachiyomi.source.model.SManga
 import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
-import eu.kanade.tachiyomi.ui.source.filter.CheckboxItem
-import eu.kanade.tachiyomi.ui.source.filter.CheckboxSectionItem
-import eu.kanade.tachiyomi.ui.source.filter.GroupItem
-import eu.kanade.tachiyomi.ui.source.filter.HeaderItem
-import eu.kanade.tachiyomi.ui.source.filter.SelectItem
-import eu.kanade.tachiyomi.ui.source.filter.SelectSectionItem
-import eu.kanade.tachiyomi.ui.source.filter.SeparatorItem
-import eu.kanade.tachiyomi.ui.source.filter.SortGroup
-import eu.kanade.tachiyomi.ui.source.filter.SortItem
-import eu.kanade.tachiyomi.ui.source.filter.TextItem
-import eu.kanade.tachiyomi.ui.source.filter.TextSectionItem
-import eu.kanade.tachiyomi.ui.source.filter.TriStateItem
-import eu.kanade.tachiyomi.ui.source.filter.TriStateSectionItem
+import eu.kanade.tachiyomi.ui.browse.source.filter.CheckboxItem
+import eu.kanade.tachiyomi.ui.browse.source.filter.CheckboxSectionItem
+import eu.kanade.tachiyomi.ui.browse.source.filter.GroupItem
+import eu.kanade.tachiyomi.ui.browse.source.filter.HeaderItem
+import eu.kanade.tachiyomi.ui.browse.source.filter.SelectItem
+import eu.kanade.tachiyomi.ui.browse.source.filter.SelectSectionItem
+import eu.kanade.tachiyomi.ui.browse.source.filter.SeparatorItem
+import eu.kanade.tachiyomi.ui.browse.source.filter.SortGroup
+import eu.kanade.tachiyomi.ui.browse.source.filter.SortItem
+import eu.kanade.tachiyomi.ui.browse.source.filter.TextItem
+import eu.kanade.tachiyomi.ui.browse.source.filter.TextSectionItem
+import eu.kanade.tachiyomi.ui.browse.source.filter.TriStateItem
+import eu.kanade.tachiyomi.ui.browse.source.filter.TriStateSectionItem
 import rx.Observable
 import rx.Subscription
 import rx.android.schedulers.AndroidSchedulers

+ 3 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/NoResultsException.kt

@@ -0,0 +1,3 @@
+package eu.kanade.tachiyomi.ui.browse.source.browse
+
+class NoResultsException : Exception()

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/browse/Pager.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/Pager.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.browse
+package eu.kanade.tachiyomi.ui.browse.source.browse
 
 import com.jakewharton.rxrelay.PublishRelay
 import eu.kanade.tachiyomi.source.model.MangasPage

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/browse/ProgressItem.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/ProgressItem.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.browse
+package eu.kanade.tachiyomi.ui.browse.source.browse
 
 import android.view.View
 import android.widget.ProgressBar

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/browse/SourceFilterSheet.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceFilterSheet.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.browse
+package eu.kanade.tachiyomi.ui.browse.source.browse
 
 import android.app.Activity
 import android.content.Context

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/browse/SourceGridHolder.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceGridHolder.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.browse
+package eu.kanade.tachiyomi.ui.browse.source.browse
 
 import android.view.View
 import com.bumptech.glide.load.engine.DiskCacheStrategy

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/browse/SourceHolder.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceHolder.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.browse
+package eu.kanade.tachiyomi.ui.browse.source.browse
 
 import android.view.View
 import eu.davidea.flexibleadapter.FlexibleAdapter

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

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.browse
+package eu.kanade.tachiyomi.ui.browse.source.browse
 
 import android.view.Gravity
 import android.view.View

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/browse/SourceListHolder.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceListHolder.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.browse
+package eu.kanade.tachiyomi.ui.browse.source.browse
 
 import android.view.View
 import com.bumptech.glide.load.engine.DiskCacheStrategy

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/browse/SourcePager.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourcePager.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.browse
+package eu.kanade.tachiyomi.ui.browse.source.browse
 
 import eu.kanade.tachiyomi.source.CatalogueSource
 import eu.kanade.tachiyomi.source.model.FilterList

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/filter/CheckboxItem.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/CheckboxItem.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.filter
+package eu.kanade.tachiyomi.ui.browse.source.filter
 
 import android.view.View
 import android.widget.CheckBox

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/filter/GroupItem.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/GroupItem.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.filter
+package eu.kanade.tachiyomi.ui.browse.source.filter
 
 import android.view.View
 import android.widget.ImageView

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/filter/HeaderItem.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/HeaderItem.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.filter
+package eu.kanade.tachiyomi.ui.browse.source.filter
 
 import android.annotation.SuppressLint
 import android.view.View

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/filter/SectionItems.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/SectionItems.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.filter
+package eu.kanade.tachiyomi.ui.browse.source.filter
 
 import eu.davidea.flexibleadapter.items.ISectionable
 import eu.kanade.tachiyomi.source.model.Filter

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/filter/SelectItem.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/SelectItem.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.filter
+package eu.kanade.tachiyomi.ui.browse.source.filter
 
 import android.view.View
 import android.widget.ArrayAdapter

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/filter/SeparatorItem.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/SeparatorItem.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.filter
+package eu.kanade.tachiyomi.ui.browse.source.filter
 
 import android.annotation.SuppressLint
 import android.view.View

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/filter/SortGroup.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/SortGroup.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.filter
+package eu.kanade.tachiyomi.ui.browse.source.filter
 
 import android.view.View
 import androidx.recyclerview.widget.RecyclerView

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/filter/SortItem.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/SortItem.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.filter
+package eu.kanade.tachiyomi.ui.browse.source.filter
 
 import android.view.View
 import android.widget.CheckedTextView

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/filter/TextItem.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/TextItem.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.filter
+package eu.kanade.tachiyomi.ui.browse.source.filter
 
 import android.view.View
 import android.widget.EditText

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/filter/TriStateItem.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/TriStateItem.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.filter
+package eu.kanade.tachiyomi.ui.browse.source.filter
 
 import android.view.View
 import android.widget.CheckedTextView

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/globalsearch/GlobalSearchAdapter.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchAdapter.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.globalsearch
+package eu.kanade.tachiyomi.ui.browse.source.globalsearch
 
 import android.os.Bundle
 import android.os.Parcelable

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/globalsearch/GlobalSearchCardAdapter.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchCardAdapter.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.globalsearch
+package eu.kanade.tachiyomi.ui.browse.source.globalsearch
 
 import eu.davidea.flexibleadapter.FlexibleAdapter
 import eu.kanade.tachiyomi.data.database.models.Manga

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/globalsearch/GlobalSearchCardHolder.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchCardHolder.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.globalsearch
+package eu.kanade.tachiyomi.ui.browse.source.globalsearch
 
 import android.view.View
 import com.bumptech.glide.load.engine.DiskCacheStrategy

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/globalsearch/GlobalSearchCardItem.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchCardItem.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.globalsearch
+package eu.kanade.tachiyomi.ui.browse.source.globalsearch
 
 import android.view.View
 import androidx.recyclerview.widget.RecyclerView

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/globalsearch/GlobalSearchController.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchController.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.globalsearch
+package eu.kanade.tachiyomi.ui.browse.source.globalsearch
 
 import android.os.Bundle
 import android.view.LayoutInflater

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/globalsearch/GlobalSearchHolder.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchHolder.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.globalsearch
+package eu.kanade.tachiyomi.ui.browse.source.globalsearch
 
 import android.view.View
 import androidx.recyclerview.widget.LinearLayoutManager

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/source/globalsearch/GlobalSearchItem.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchItem.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.globalsearch
+package eu.kanade.tachiyomi.ui.browse.source.globalsearch
 
 import android.view.View
 import androidx.recyclerview.widget.RecyclerView

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/source/globalsearch/GlobalSearchPresenter.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchPresenter.kt

@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.ui.source.globalsearch
+package eu.kanade.tachiyomi.ui.browse.source.globalsearch
 
 import android.os.Bundle
 import eu.kanade.tachiyomi.data.database.DatabaseHelper
@@ -12,7 +12,7 @@ import eu.kanade.tachiyomi.source.model.FilterList
 import eu.kanade.tachiyomi.source.model.MangasPage
 import eu.kanade.tachiyomi.source.model.SManga
 import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
-import eu.kanade.tachiyomi.ui.source.browse.BrowseSourcePresenter
+import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourcePresenter
 import rx.Observable
 import rx.Subscription
 import rx.android.schedulers.AndroidSchedulers

+ 3 - 3
app/src/main/java/eu/kanade/tachiyomi/ui/source/latest/LatestUpdatesController.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/latest/LatestUpdatesController.kt

@@ -1,11 +1,11 @@
-package eu.kanade.tachiyomi.ui.source.latest
+package eu.kanade.tachiyomi.ui.browse.source.latest
 
 import android.os.Bundle
 import android.view.Menu
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.source.CatalogueSource
-import eu.kanade.tachiyomi.ui.source.browse.BrowseSourceController
-import eu.kanade.tachiyomi.ui.source.browse.BrowseSourcePresenter
+import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceController
+import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourcePresenter
 
 /**
  * Controller that shows the latest manga from the catalogue. Inherit [BrowseSourceController].

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/source/latest/LatestUpdatesPager.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/latest/LatestUpdatesPager.kt

@@ -1,8 +1,8 @@
-package eu.kanade.tachiyomi.ui.source.latest
+package eu.kanade.tachiyomi.ui.browse.source.latest
 
 import eu.kanade.tachiyomi.source.CatalogueSource
 import eu.kanade.tachiyomi.source.model.MangasPage
-import eu.kanade.tachiyomi.ui.source.browse.Pager
+import eu.kanade.tachiyomi.ui.browse.source.browse.Pager
 import rx.Observable
 import rx.android.schedulers.AndroidSchedulers
 import rx.schedulers.Schedulers

+ 3 - 3
app/src/main/java/eu/kanade/tachiyomi/ui/source/latest/LatestUpdatesPresenter.kt → app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/latest/LatestUpdatesPresenter.kt

@@ -1,8 +1,8 @@
-package eu.kanade.tachiyomi.ui.source.latest
+package eu.kanade.tachiyomi.ui.browse.source.latest
 
 import eu.kanade.tachiyomi.source.model.FilterList
-import eu.kanade.tachiyomi.ui.source.browse.BrowseSourcePresenter
-import eu.kanade.tachiyomi.ui.source.browse.Pager
+import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourcePresenter
+import eu.kanade.tachiyomi.ui.browse.source.browse.Pager
 
 /**
  * Presenter of [LatestUpdatesController]. Inherit BrowseCataloguePresenter.

+ 8 - 9
app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt

@@ -21,15 +21,14 @@ import eu.kanade.tachiyomi.ui.base.controller.NoToolbarElevationController
 import eu.kanade.tachiyomi.ui.base.controller.RootController
 import eu.kanade.tachiyomi.ui.base.controller.TabbedController
 import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
+import eu.kanade.tachiyomi.ui.browse.BrowseController
+import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchController
 import eu.kanade.tachiyomi.ui.download.DownloadController
-import eu.kanade.tachiyomi.ui.extension.ExtensionController
 import eu.kanade.tachiyomi.ui.library.LibraryController
 import eu.kanade.tachiyomi.ui.manga.MangaController
 import eu.kanade.tachiyomi.ui.more.MoreController
 import eu.kanade.tachiyomi.ui.recent.history.HistoryController
 import eu.kanade.tachiyomi.ui.recent.updates.UpdatesController
-import eu.kanade.tachiyomi.ui.source.SourceController
-import eu.kanade.tachiyomi.ui.source.globalsearch.GlobalSearchController
 import eu.kanade.tachiyomi.util.lang.launchUI
 import eu.kanade.tachiyomi.util.system.WebViewUtil
 import eu.kanade.tachiyomi.util.system.toast
@@ -95,7 +94,7 @@ class MainActivity : BaseActivity<MainActivityBinding>() {
                     R.id.nav_library -> setRoot(LibraryController(), id)
                     R.id.nav_updates -> setRoot(UpdatesController(), id)
                     R.id.nav_history -> setRoot(HistoryController(), id)
-                    R.id.nav_sources -> setRoot(SourceController(), id)
+                    R.id.nav_browse -> setRoot(BrowseController(), id)
                     R.id.nav_more -> setRoot(MoreController(), id)
                 }
             } else if (!isHandlingShortcut) {
@@ -173,9 +172,9 @@ class MainActivity : BaseActivity<MainActivityBinding>() {
     private fun setExtensionsBadge() {
         val updates = preferences.extensionUpdatesCount().get()
         if (updates > 0) {
-            binding.bottomNav.getOrCreateBadge(R.id.nav_more).number = updates
+            binding.bottomNav.getOrCreateBadge(R.id.nav_browse).number = updates
         } else {
-            binding.bottomNav.removeBadge(R.id.nav_more)
+            binding.bottomNav.removeBadge(R.id.nav_browse)
         }
     }
 
@@ -208,13 +207,13 @@ class MainActivity : BaseActivity<MainActivityBinding>() {
             SHORTCUT_LIBRARY -> setSelectedNavItem(R.id.nav_library)
             SHORTCUT_RECENTLY_UPDATED -> setSelectedNavItem(R.id.nav_updates)
             SHORTCUT_RECENTLY_READ -> setSelectedNavItem(R.id.nav_history)
-            SHORTCUT_CATALOGUES -> setSelectedNavItem(R.id.nav_sources)
+            SHORTCUT_CATALOGUES -> setSelectedNavItem(R.id.nav_browse)
             SHORTCUT_EXTENSIONS -> {
                 if (router.backstackSize > 1) {
                     router.popToRoot()
                 }
-                setSelectedNavItem(R.id.nav_more)
-                router.pushController(ExtensionController().withFadeTransaction())
+                router.pushController(BrowseController(true).withFadeTransaction())
+                setSelectedNavItem(R.id.nav_browse)
             }
             SHORTCUT_MANGA -> {
                 val extras = intent.extras ?: return false

+ 7 - 7
app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt

@@ -18,7 +18,7 @@ import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.database.DatabaseHelper
 import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.data.track.TrackManager
-import eu.kanade.tachiyomi.databinding.MangaControllerBinding
+import eu.kanade.tachiyomi.databinding.PagerControllerBinding
 import eu.kanade.tachiyomi.source.Source
 import eu.kanade.tachiyomi.source.SourceManager
 import eu.kanade.tachiyomi.ui.base.controller.RxController
@@ -33,7 +33,7 @@ import rx.Subscription
 import uy.kohesive.injekt.Injekt
 import uy.kohesive.injekt.api.get
 
-class MangaController : RxController<MangaControllerBinding>, TabbedController {
+class MangaController : RxController<PagerControllerBinding>, TabbedController {
 
     constructor(manga: Manga?, fromSource: Boolean = false) : super(
         Bundle().apply {
@@ -75,7 +75,7 @@ class MangaController : RxController<MangaControllerBinding>, TabbedController {
     }
 
     override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
-        binding = MangaControllerBinding.inflate(inflater)
+        binding = PagerControllerBinding.inflate(inflater)
         return binding.root
     }
 
@@ -87,11 +87,11 @@ class MangaController : RxController<MangaControllerBinding>, TabbedController {
         requestPermissionsSafe(arrayOf(WRITE_EXTERNAL_STORAGE), 301)
 
         adapter = MangaDetailAdapter()
-        binding.mangaPager.offscreenPageLimit = 3
-        binding.mangaPager.adapter = adapter
+        binding.pager.offscreenPageLimit = 3
+        binding.pager.adapter = adapter
 
         if (!fromSource) {
-            binding.mangaPager.currentItem = CHAPTERS_CONTROLLER
+            binding.pager.currentItem = CHAPTERS_CONTROLLER
         }
     }
 
@@ -103,7 +103,7 @@ class MangaController : RxController<MangaControllerBinding>, TabbedController {
     override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) {
         super.onChangeStarted(handler, type)
         if (type.isEnter) {
-            activity?.tabs?.setupWithViewPager(binding.mangaPager)
+            activity?.tabs?.setupWithViewPager(binding.pager)
             trackingIconSubscription = trackingIconRelay.subscribe { setTrackingIconInternal(it) }
         }
     }

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoController.kt

@@ -21,14 +21,14 @@ import eu.kanade.tachiyomi.source.model.SManga
 import eu.kanade.tachiyomi.source.online.HttpSource
 import eu.kanade.tachiyomi.ui.base.controller.NucleusController
 import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
+import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceController
+import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchController
 import eu.kanade.tachiyomi.ui.library.ChangeMangaCategoriesDialog
 import eu.kanade.tachiyomi.ui.library.LibraryController
 import eu.kanade.tachiyomi.ui.main.MainActivity
 import eu.kanade.tachiyomi.ui.manga.MangaController
 import eu.kanade.tachiyomi.ui.recent.history.HistoryController
 import eu.kanade.tachiyomi.ui.recent.updates.UpdatesController
-import eu.kanade.tachiyomi.ui.source.browse.BrowseSourceController
-import eu.kanade.tachiyomi.ui.source.globalsearch.GlobalSearchController
 import eu.kanade.tachiyomi.ui.webview.WebViewActivity
 import eu.kanade.tachiyomi.util.system.copyToClipboard
 import eu.kanade.tachiyomi.util.system.toast

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/migration/SearchController.kt

@@ -8,8 +8,8 @@ import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.ui.base.controller.DialogController
-import eu.kanade.tachiyomi.ui.source.globalsearch.GlobalSearchController
-import eu.kanade.tachiyomi.ui.source.globalsearch.GlobalSearchPresenter
+import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchController
+import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchPresenter
 import eu.kanade.tachiyomi.util.view.gone
 import eu.kanade.tachiyomi.util.view.visible
 import uy.kohesive.injekt.injectLazy

+ 3 - 3
app/src/main/java/eu/kanade/tachiyomi/ui/migration/SearchPresenter.kt

@@ -8,9 +8,9 @@ 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.source.globalsearch.GlobalSearchCardItem
-import eu.kanade.tachiyomi.ui.source.globalsearch.GlobalSearchItem
-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

+ 0 - 13
app/src/main/java/eu/kanade/tachiyomi/ui/more/MoreController.kt

@@ -3,15 +3,12 @@ package eu.kanade.tachiyomi.ui.more
 import androidx.preference.PreferenceScreen
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.ui.base.controller.RootController
 import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
 import eu.kanade.tachiyomi.ui.download.DownloadController
-import eu.kanade.tachiyomi.ui.extension.ExtensionController
 import eu.kanade.tachiyomi.ui.migration.MigrationController
 import eu.kanade.tachiyomi.ui.setting.SettingsController
 import eu.kanade.tachiyomi.ui.setting.SettingsMainController
-import eu.kanade.tachiyomi.util.preference.badgePreference
 import eu.kanade.tachiyomi.util.preference.iconRes
 import eu.kanade.tachiyomi.util.preference.iconTint
 import eu.kanade.tachiyomi.util.preference.onClick
@@ -21,7 +18,6 @@ import eu.kanade.tachiyomi.util.preference.switchPreference
 import eu.kanade.tachiyomi.util.preference.titleRes
 import eu.kanade.tachiyomi.util.system.getResourceColor
 import eu.kanade.tachiyomi.util.system.openInBrowser
-import uy.kohesive.injekt.Injekt
 import uy.kohesive.injekt.api.get
 
 class MoreController : SettingsController(), RootController {
@@ -39,15 +35,6 @@ class MoreController : SettingsController(), RootController {
         }
 
         preferenceCategory {
-            badgePreference {
-                titleRes = R.string.label_extensions
-                iconRes = R.drawable.ic_extension_24dp
-                iconTint = tintColor
-                setBadge(Injekt.get<PreferencesHelper>().extensionUpdatesCount().get())
-                onClick {
-                    router.pushController(ExtensionController().withFadeTransaction())
-                }
-            }
             preference {
                 titleRes = R.string.label_download_queue
                 iconRes = R.drawable.ic_file_download_black_24dp

+ 0 - 3
app/src/main/java/eu/kanade/tachiyomi/ui/source/browse/NoResultsException.kt

@@ -1,3 +0,0 @@
-package eu.kanade.tachiyomi.ui.source.browse
-
-class NoResultsException : Exception()

+ 0 - 5
app/src/main/java/eu/kanade/tachiyomi/util/preference/PreferenceDSL.kt

@@ -13,7 +13,6 @@ import androidx.preference.PreferenceManager
 import androidx.preference.PreferenceScreen
 import androidx.preference.SwitchPreferenceCompat
 import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat
-import eu.kanade.tachiyomi.widget.preference.BadgePreference
 import eu.kanade.tachiyomi.widget.preference.IntListPreference
 import eu.kanade.tachiyomi.widget.preference.SwitchPreferenceCategory
 
@@ -57,10 +56,6 @@ inline fun PreferenceGroup.multiSelectListPreference(block: (@DSL MultiSelectLis
     return initThenAdd(MultiSelectListPreference(context), block).also(::initDialog)
 }
 
-inline fun PreferenceGroup.badgePreference(block: (@DSL BadgePreference).() -> Unit): BadgePreference {
-    return initThenAdd(BadgePreference(context), block)
-}
-
 inline fun PreferenceScreen.preferenceCategory(block: (@DSL PreferenceCategory).() -> Unit): PreferenceCategory {
     return addThenInit(PreferenceCategory(context), block)
 }

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/util/system/LocaleHelper.kt

@@ -7,7 +7,7 @@ import android.os.Build
 import android.view.ContextThemeWrapper
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
-import eu.kanade.tachiyomi.ui.source.SourcePresenter
+import eu.kanade.tachiyomi.ui.browse.source.SourcePresenter
 import java.util.Locale
 import uy.kohesive.injekt.injectLazy
 

+ 0 - 37
app/src/main/java/eu/kanade/tachiyomi/widget/preference/BadgePreference.kt

@@ -1,37 +0,0 @@
-package eu.kanade.tachiyomi.widget.preference
-
-import android.content.Context
-import android.util.AttributeSet
-import androidx.preference.Preference
-import androidx.preference.PreferenceViewHolder
-import eu.kanade.tachiyomi.R
-import eu.kanade.tachiyomi.util.view.gone
-import eu.kanade.tachiyomi.util.view.visible
-import kotlinx.android.synthetic.main.pref_badge.view.badge
-
-class BadgePreference @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
-    Preference(context, attrs) {
-
-    private var badgeNumber: Int = 0
-
-    init {
-        widgetLayoutResource = R.layout.pref_badge
-    }
-
-    override fun onBindViewHolder(holder: PreferenceViewHolder) {
-        super.onBindViewHolder(holder)
-
-        if (badgeNumber > 0) {
-            holder.itemView.badge.text = badgeNumber.toString()
-            holder.itemView.badge.visible()
-        } else {
-            holder.itemView.badge.text = null
-            holder.itemView.badge.gone()
-        }
-    }
-
-    fun setBadge(number: Int) {
-        this.badgeNumber = number
-        notifyChanged()
-    }
-}

+ 0 - 9
app/src/main/res/drawable/round_textview_background.xml

@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-    <corners android:radius="13dp" />
-    <size
-        android:width="25dp"
-        android:height="25dp" />
-    <solid android:color="?attr/colorError" />
-</shape>

+ 1 - 1
app/src/main/res/layout/manga_info_controller.xml

@@ -5,7 +5,7 @@
     android:id="@id/swipe_refresh"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    tools:context="eu.kanade.tachiyomi.ui.source.browse.BrowseSourceController">
+    tools:context=".ui.browse.source.browse.BrowseSourceController">
 
     <androidx.core.widget.NestedScrollView
         android:layout_width="match_parent"

+ 1 - 1
app/src/main/res/layout/manga_controller.xml → app/src/main/res/layout/pager_controller.xml

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <androidx.viewpager.widget.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/manga_pager"
+    android:id="@+id/pager"
     android:layout_width="match_parent"
     android:layout_height="match_parent" />

+ 0 - 12
app/src/main/res/layout/pref_badge.xml

@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:id="@+id/badge"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:background="@drawable/round_textview_background"
-    android:gravity="center"
-    android:padding="3dp"
-    android:textAppearance="@style/TextAppearance.MaterialComponents.Badge"
-    android:textStyle="bold"
-    tools:text="3" />

+ 1 - 1
app/src/main/res/layout/source_controller.xml

@@ -14,7 +14,7 @@
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:orientation="vertical"
-            tools:context="eu.kanade.tachiyomi.ui.source.browse.BrowseSourceController">
+            tools:context=".ui.browse.source.browse.BrowseSourceController">
 
             <ProgressBar
                 android:id="@+id/progress"

+ 2 - 2
app/src/main/res/menu/bottom_nav.xml

@@ -13,9 +13,9 @@
         android:icon="@drawable/ic_history_24dp"
         android:title="@string/label_recent_manga" />
     <item
-        android:id="@+id/nav_sources"
+        android:id="@+id/nav_browse"
         android:icon="@drawable/ic_explore_state"
-        android:title="@string/label_sources" />
+        android:title="@string/browse" />
     <item
         android:id="@+id/nav_more"
         android:icon="@drawable/ic_more_horiz_24dp"