diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/BaseController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/BaseController.kt
index 9003b2ce3..94039e889 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/BaseController.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/BaseController.kt
@@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.ui.base.controller
 
 import android.os.Bundle
 import android.view.LayoutInflater
-import android.view.MenuItem
 import android.view.View
 import android.view.ViewGroup
 import androidx.appcompat.app.AppCompatActivity
@@ -75,60 +74,10 @@ abstract class BaseController<VB : ViewBinding>(bundle: Bundle? = null) : Contro
     }
 
     fun setTitle(title: String? = null) {
-        var parentController = parentController
-        while (parentController != null) {
-            if (parentController is BaseController<*> && parentController.getTitle() != null) {
-                return
-            }
-            parentController = parentController.parentController
-        }
-
         (activity as? AppCompatActivity)?.supportActionBar?.title = title ?: getTitle()
     }
 
     private fun Controller.instance(): String {
         return "${javaClass.simpleName}@${Integer.toHexString(hashCode())}"
     }
-
-    /**
-     * Workaround for buggy menu item layout after expanding/collapsing an expandable item like a SearchView.
-     * This method should be removed when fixed upstream.
-     * Issue link: https://issuetracker.google.com/issues/37657375
-     */
-    var expandActionViewFromInteraction = false
-
-    fun MenuItem.fixExpand(onExpand: ((MenuItem) -> Boolean)? = null, onCollapse: ((MenuItem) -> Boolean)? = null) {
-        setOnActionExpandListener(
-            object : MenuItem.OnActionExpandListener {
-                override fun onMenuItemActionExpand(item: MenuItem): Boolean {
-                    return onExpand?.invoke(item) ?: true
-                }
-
-                override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
-                    activity?.invalidateOptionsMenu()
-
-                    return onCollapse?.invoke(item) ?: true
-                }
-            },
-        )
-
-        if (expandActionViewFromInteraction) {
-            expandActionViewFromInteraction = false
-            expandActionView()
-        }
-    }
-
-    /**
-     * Workaround for menu items not disappearing when expanding an expandable item like a SearchView.
-     * [expandActionViewFromInteraction] should be set to true in [onOptionsItemSelected] when the expandable item is selected
-     * This method should be called as part of [MenuItem.OnActionExpandListener.onMenuItemActionExpand]
-     */
-    open fun invalidateMenuOnExpand(): Boolean {
-        return if (expandActionViewFromInteraction) {
-            activity?.invalidateOptionsMenu()
-            false
-        } else {
-            true
-        }
-    }
 }
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/NucleusController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/NucleusController.kt
index 0786d5e13..89dfd2399 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/NucleusController.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/NucleusController.kt
@@ -9,7 +9,7 @@ import nucleus.presenter.Presenter
 
 @Suppress("LeakingThis")
 abstract class NucleusController<VB : ViewBinding, P : Presenter<*>>(val bundle: Bundle? = null) :
-    RxController<VB>(bundle),
+    BaseController<VB>(bundle),
     PresenterFactory<P> {
 
     private val delegate = NucleusConductorDelegate(this)
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/RxController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/RxController.kt
deleted file mode 100644
index 493504aeb..000000000
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/RxController.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package eu.kanade.tachiyomi.ui.base.controller
-
-import android.os.Bundle
-import android.view.View
-import androidx.annotation.CallSuper
-import androidx.viewbinding.ViewBinding
-import rx.Observable
-import rx.Subscription
-import rx.subscriptions.CompositeSubscription
-
-abstract class RxController<VB : ViewBinding>(bundle: Bundle? = null) : BaseController<VB>(bundle) {
-
-    private var untilDestroySubscriptions = CompositeSubscription()
-
-    @CallSuper
-    override fun onViewCreated(view: View) {
-        if (untilDestroySubscriptions.isUnsubscribed) {
-            untilDestroySubscriptions = CompositeSubscription()
-        }
-    }
-
-    @CallSuper
-    override fun onDestroyView(view: View) {
-        super.onDestroyView(view)
-        untilDestroySubscriptions.unsubscribe()
-    }
-
-    fun <T> Observable<T>.subscribeUntilDestroy(onNext: (T) -> Unit): Subscription {
-        return subscribe(onNext).also { untilDestroySubscriptions.add(it) }
-    }
-}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/SearchableNucleusController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/SearchableNucleusController.kt
index 34b01895d..48d6fd4c4 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/SearchableNucleusController.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/SearchableNucleusController.kt
@@ -6,7 +6,6 @@ import android.text.style.CharacterStyle
 import android.view.Menu
 import android.view.MenuInflater
 import android.view.MenuItem
-import androidx.annotation.StringRes
 import androidx.appcompat.widget.SearchView
 import androidx.core.text.getSpans
 import androidx.core.widget.doAfterTextChanged
@@ -43,10 +42,7 @@ abstract class SearchableNucleusController<VB : ViewBinding, P : BasePresenter<*
         inflater: MenuInflater,
         menuId: Int,
         searchItemId: Int,
-        @StringRes queryHint: Int? = null,
-        restoreCurrentQuery: Boolean = true,
     ) {
-        // Inflate menu
         inflater.inflate(menuId, menu)
 
         // Initialize search option.
@@ -93,21 +89,6 @@ abstract class SearchableNucleusController<VB : ViewBinding, P : BasePresenter<*
             searchItem.expandActionView()
             searchView.setQuery(nonSubmittedQuery, false)
             onSearchViewQueryTextChange(nonSubmittedQuery)
-        } else {
-            if (queryHint != null) {
-                searchView.queryHint = applicationContext?.getString(queryHint)
-            }
-
-            if (restoreCurrentQuery) {
-                // Restoring a query the user had submitted
-                if (query.isNotBlank()) {
-                    searchItem.expandActionView()
-                    searchView.setQuery(query, true)
-                    searchView.clearFocus()
-                    onSearchViewQueryTextChange(query)
-                    onSearchViewQueryTextSubmit(query)
-                }
-            }
         }
 
         // Workaround for weird behavior where searchView gets empty text change despite
@@ -190,12 +171,40 @@ abstract class SearchableNucleusController<VB : ViewBinding, P : BasePresenter<*
     protected open fun onSearchMenuItemActionCollapse(item: MenuItem?) {
     }
 
+    /**
+     * Workaround for buggy menu item layout after expanding/collapsing an expandable item like a SearchView.
+     * This method should be removed when fixed upstream.
+     * Issue link: https://issuetracker.google.com/issues/37657375
+     */
+    private var expandActionViewFromInteraction = false
+
+    private fun MenuItem.fixExpand(onExpand: ((MenuItem) -> Boolean)? = null, onCollapse: ((MenuItem) -> Boolean)? = null) {
+        setOnActionExpandListener(
+            object : MenuItem.OnActionExpandListener {
+                override fun onMenuItemActionExpand(item: MenuItem): Boolean {
+                    return onExpand?.invoke(item) ?: true
+                }
+
+                override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
+                    activity?.invalidateOptionsMenu()
+
+                    return onCollapse?.invoke(item) ?: true
+                }
+            },
+        )
+
+        if (expandActionViewFromInteraction) {
+            expandActionViewFromInteraction = false
+            expandActionView()
+        }
+    }
+
     /**
      * During the conversion to SearchableNucleusController (after which I plan to merge its code
      * into BaseController) this addresses an issue where the searchView.onTextFocus event is not
      * triggered
      */
-    override fun invalidateMenuOnExpand(): Boolean {
+    private fun invalidateMenuOnExpand(): Boolean {
         return if (expandActionViewFromInteraction) {
             activity?.invalidateOptionsMenu()
             setCurrentSearchViewState(SearchViewState.FOCUSED) // we are technically focused here
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/presenter/BasePresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/presenter/BasePresenter.kt
index edc2a7752..2a373aad4 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/presenter/BasePresenter.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/presenter/BasePresenter.kt
@@ -40,15 +40,6 @@ open class BasePresenter<V> : RxPresenter<V>() {
 
     fun <T> Preference<T>.asState() = PreferenceMutableState(this, presenterScope)
 
-    /**
-     * Subscribes an observable with [deliverFirst] and adds it to the presenter's lifecycle
-     * subscription list.
-     *
-     * @param onNext function to execute when the observable emits an item.
-     * @param onError function to execute when the observable throws an error.
-     */
-    fun <T> Observable<T>.subscribeFirst(onNext: (V, T) -> Unit, onError: ((V, Throwable) -> Unit) = { _, _ -> }) = compose(deliverFirst<T>()).subscribe(split(onNext, onError)).apply { add(this) }
-
     /**
      * Subscribes an observable with [deliverLatestCache] and adds it to the presenter's lifecycle
      * subscription list.
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchController.kt
index 2304826d6..46a243b1a 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchController.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchController.kt
@@ -92,8 +92,6 @@ open class GlobalSearchController(
             inflater,
             R.menu.global_search,
             R.id.action_search,
-            null,
-            false, // the onMenuItemActionExpand will handle this
         )
 
         optionsMenuSearchItem = menu.findItem(R.id.action_search)
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/more/MoreController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/more/MoreController.kt
index 80c0052d3..7e43a24dd 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/more/MoreController.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/more/MoreController.kt
@@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.ui.more
 
 import androidx.compose.runtime.Composable
 import eu.kanade.presentation.more.MoreScreen
-import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.ui.base.controller.FullComposeController
 import eu.kanade.tachiyomi.ui.base.controller.RootController
 import eu.kanade.tachiyomi.ui.base.controller.pushController
@@ -15,8 +14,6 @@ class MoreController :
     FullComposeController<MorePresenter>(),
     RootController {
 
-    override fun getTitle() = resources?.getString(R.string.label_more)
-
     override fun createPresenter() = MorePresenter()
 
     @Composable
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt
index e9e2e33dd..033e0cab4 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt
@@ -879,6 +879,15 @@ class ReaderPresenter(
         }
     }
 
+    /**
+     * Subscribes an observable with [deliverFirst] and adds it to the presenter's lifecycle
+     * subscription list.
+     *
+     * @param onNext function to execute when the observable emits an item.
+     * @param onError function to execute when the observable throws an error.
+     */
+    private fun <T> Observable<T>.subscribeFirst(onNext: (ReaderActivity, T) -> Unit, onError: ((ReaderActivity, Throwable) -> Unit) = { _, _ -> }) = compose(deliverFirst<T>()).subscribe(split(onNext, onError)).apply { add(this) }
+
     companion object {
         // Safe theoretical max filename size is 255 bytes and 1 char = 2-4 bytes (UTF-8)
         private const val MAX_FILE_NAME_BYTES = 250
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsController.kt
index a2e20a57d..79445818f 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsController.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsController.kt
@@ -21,7 +21,6 @@ import com.bluelinelabs.conductor.ControllerChangeType
 import dev.chrisbanes.insetter.applyInsetter
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
-import eu.kanade.tachiyomi.ui.base.controller.BaseController
 import eu.kanade.tachiyomi.util.preference.asHotFlow
 import eu.kanade.tachiyomi.util.system.getResourceColor
 import kotlinx.coroutines.CoroutineScope
@@ -114,20 +113,8 @@ abstract class SettingsController : PreferenceController() {
             }
     }
 
-    open fun getTitle(): String? {
-        return preferenceScreen?.title?.toString()
-    }
-
     private fun setTitle() {
-        var parentController = parentController
-        while (parentController != null) {
-            if (parentController is BaseController<*> && parentController.getTitle() != null) {
-                return
-            }
-            parentController = parentController.parentController
-        }
-
-        (activity as? AppCompatActivity)?.supportActionBar?.title = getTitle()
+        (activity as? AppCompatActivity)?.supportActionBar?.title = preferenceScreen?.title?.toString()
     }
 
     inline fun <T> Preference.visibleIf(preference: eu.kanade.tachiyomi.core.preference.Preference<T>, crossinline block: (T) -> Boolean) {
diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/storage/DiskUtil.kt b/app/src/main/java/eu/kanade/tachiyomi/util/storage/DiskUtil.kt
index bcbbf2520..50a5099e9 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/util/storage/DiskUtil.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/util/storage/DiskUtil.kt
@@ -43,9 +43,8 @@ object DiskUtil {
     /**
      * Returns the root folders of all the available external storages.
      */
-    fun getExternalStorages(context: Context): Collection<File> {
-        val directories = mutableSetOf<File>()
-        directories += ContextCompat.getExternalFilesDirs(context, null)
+    fun getExternalStorages(context: Context): List<File> {
+        return ContextCompat.getExternalFilesDirs(context, null)
             .filterNotNull()
             .mapNotNull {
                 val file = File(it.absolutePath.substringBefore("/Android/"))
@@ -56,8 +55,6 @@ object DiskUtil {
                     null
                 }
             }
-
-        return directories
     }
 
     /**
diff --git a/core/src/main/java/eu/kanade/tachiyomi/core/security/SecurityPreferences.kt b/core/src/main/java/eu/kanade/tachiyomi/core/security/SecurityPreferences.kt
index d4aeb5c38..dbd1194ea 100644
--- a/core/src/main/java/eu/kanade/tachiyomi/core/security/SecurityPreferences.kt
+++ b/core/src/main/java/eu/kanade/tachiyomi/core/security/SecurityPreferences.kt
@@ -27,5 +27,4 @@ class SecurityPreferences(
         INCOGNITO(R.string.pref_incognito_mode),
         NEVER(R.string.lock_never),
     }
-
 }