mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-04 08:08:55 +01:00 
			
		
		
		
	Clean up base classes
Should be able to throw away some of the search controller stuff after Global Search is migrated
This commit is contained in:
		@@ -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
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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) }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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.
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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) {
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -27,5 +27,4 @@ class SecurityPreferences(
 | 
			
		||||
        INCOGNITO(R.string.pref_incognito_mode),
 | 
			
		||||
        NEVER(R.string.lock_never),
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user