mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-31 14:27:57 +01:00 
			
		
		
		
	Remove dead code
This commit is contained in:
		| @@ -1,216 +0,0 @@ | ||||
| package eu.kanade.tachiyomi.ui.base.controller | ||||
|  | ||||
| import android.app.Activity | ||||
| import android.os.Bundle | ||||
| import android.text.style.CharacterStyle | ||||
| import android.view.Menu | ||||
| import android.view.MenuInflater | ||||
| import android.view.MenuItem | ||||
| import androidx.appcompat.widget.SearchView | ||||
| import androidx.core.text.getSpans | ||||
| import androidx.core.widget.doAfterTextChanged | ||||
| import androidx.viewbinding.ViewBinding | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter | ||||
| import kotlinx.coroutines.flow.launchIn | ||||
| import kotlinx.coroutines.flow.onEach | ||||
| import reactivecircus.flowbinding.appcompat.QueryTextEvent | ||||
| import reactivecircus.flowbinding.appcompat.queryTextEvents | ||||
|  | ||||
| /** | ||||
|  * Implementation of the NucleusController that has a built-in ViewSearch | ||||
|  */ | ||||
| abstract class SearchableNucleusController<VB : ViewBinding, P : BasePresenter<*>>(bundle: Bundle? = null) : NucleusController<VB, P>(bundle) { | ||||
|  | ||||
|     enum class SearchViewState { LOADING, LOADED, COLLAPSING, FOCUSED } | ||||
|  | ||||
|     /** | ||||
|      * Used to bypass the initial searchView being set to empty string after an onResume | ||||
|      */ | ||||
|     private var currentSearchViewState: SearchViewState = SearchViewState.LOADING | ||||
|  | ||||
|     /** | ||||
|      * Store the query text that has not been submitted to reassign it after an onResume, UI-only | ||||
|      */ | ||||
|     protected var nonSubmittedQuery: String = "" | ||||
|  | ||||
|     /** | ||||
|      * To be called by classes that extend this subclass in onCreateOptionsMenu | ||||
|      */ | ||||
|     protected fun createOptionsMenu( | ||||
|         menu: Menu, | ||||
|         inflater: MenuInflater, | ||||
|         menuId: Int, | ||||
|         searchItemId: Int, | ||||
|     ) { | ||||
|         inflater.inflate(menuId, menu) | ||||
|  | ||||
|         // Initialize search option. | ||||
|         val searchItem = menu.findItem(searchItemId) | ||||
|         val searchView = searchItem.actionView as SearchView | ||||
|         searchItem.fixExpand(onExpand = { invalidateMenuOnExpand() }) | ||||
|         searchView.maxWidth = Int.MAX_VALUE | ||||
|  | ||||
|         // Remove formatting from pasted text | ||||
|         val searchAutoComplete: SearchView.SearchAutoComplete = searchView.findViewById( | ||||
|             R.id.search_src_text, | ||||
|         ) | ||||
|         searchAutoComplete.doAfterTextChanged { editable -> | ||||
|             editable?.getSpans<CharacterStyle>()?.forEach { editable.removeSpan(it) } | ||||
|         } | ||||
|  | ||||
|         searchView.queryTextEvents() | ||||
|             .onEach { | ||||
|                 val newText = it.queryText.toString() | ||||
|  | ||||
|                 if (newText.isNotBlank() or acceptEmptyQuery()) { | ||||
|                     if (it is QueryTextEvent.QuerySubmitted) { | ||||
|                         // Abstract function for implementation | ||||
|                         // Run it first in case the old query data is needed (like BrowseSourceController) | ||||
|                         onSearchViewQueryTextSubmit(newText) | ||||
|                         presenter.query = newText | ||||
|                         nonSubmittedQuery = "" | ||||
|                     } else if ((it is QueryTextEvent.QueryChanged) && (presenter.query != newText)) { | ||||
|                         nonSubmittedQuery = newText | ||||
|  | ||||
|                         // Abstract function for implementation | ||||
|                         onSearchViewQueryTextChange(newText) | ||||
|                     } | ||||
|                 } | ||||
|                 // clear the collapsing flag | ||||
|                 setCurrentSearchViewState(SearchViewState.LOADED, SearchViewState.COLLAPSING) | ||||
|             } | ||||
|             .launchIn(viewScope) | ||||
|  | ||||
|         val query = presenter.query | ||||
|  | ||||
|         // Restoring a query the user had not submitted | ||||
|         if (nonSubmittedQuery.isNotBlank() and (nonSubmittedQuery != query)) { | ||||
|             searchItem.expandActionView() | ||||
|             searchView.setQuery(nonSubmittedQuery, false) | ||||
|             onSearchViewQueryTextChange(nonSubmittedQuery) | ||||
|         } | ||||
|  | ||||
|         // Workaround for weird behavior where searchView gets empty text change despite | ||||
|         // query being set already, prevents the query from being cleared | ||||
|         binding.root.post { | ||||
|             setCurrentSearchViewState(SearchViewState.LOADED, SearchViewState.LOADING) | ||||
|         } | ||||
|  | ||||
|         searchView.setOnQueryTextFocusChangeListener { _, hasFocus -> | ||||
|             if (hasFocus) { | ||||
|                 setCurrentSearchViewState(SearchViewState.FOCUSED) | ||||
|             } else { | ||||
|                 setCurrentSearchViewState(SearchViewState.LOADED, SearchViewState.FOCUSED) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         searchItem.setOnActionExpandListener( | ||||
|             object : MenuItem.OnActionExpandListener { | ||||
|                 override fun onMenuItemActionExpand(item: MenuItem): Boolean { | ||||
|                     onSearchMenuItemActionExpand(item) | ||||
|                     return true | ||||
|                 } | ||||
|  | ||||
|                 override fun onMenuItemActionCollapse(item: MenuItem): Boolean { | ||||
|                     val localSearchView = searchItem.actionView as SearchView | ||||
|  | ||||
|                     // if it is blank the flow event won't trigger so we would stay in a COLLAPSING state | ||||
|                     if (localSearchView.toString().isNotBlank()) { | ||||
|                         setCurrentSearchViewState(SearchViewState.COLLAPSING) | ||||
|                     } | ||||
|  | ||||
|                     onSearchMenuItemActionCollapse(item) | ||||
|                     return true | ||||
|                 } | ||||
|             }, | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     override fun onActivityResumed(activity: Activity) { | ||||
|         super.onActivityResumed(activity) | ||||
|         // Until everything is up and running don't accept empty queries | ||||
|         setCurrentSearchViewState(SearchViewState.LOADING) | ||||
|     } | ||||
|  | ||||
|     private fun acceptEmptyQuery(): Boolean { | ||||
|         return when (currentSearchViewState) { | ||||
|             SearchViewState.COLLAPSING, SearchViewState.FOCUSED -> true | ||||
|             else -> false | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun setCurrentSearchViewState(to: SearchViewState, from: SearchViewState? = null) { | ||||
|         // When loading ignore all requests other than loaded | ||||
|         if ((currentSearchViewState == SearchViewState.LOADING) && (to != SearchViewState.LOADED)) { | ||||
|             return | ||||
|         } | ||||
|  | ||||
|         // Prevent changing back to an unwanted state when using async flows (ie onFocus event doing | ||||
|         // COLLAPSING -> LOADED) | ||||
|         if ((from != null) && (currentSearchViewState != from)) { | ||||
|             return | ||||
|         } | ||||
|  | ||||
|         currentSearchViewState = to | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Called by the SearchView since since the implementation of these can vary in subclasses | ||||
|      * Not abstract as they are optional | ||||
|      */ | ||||
|     protected open fun onSearchViewQueryTextChange(newText: String?) { | ||||
|     } | ||||
|  | ||||
|     protected open fun onSearchViewQueryTextSubmit(query: String?) { | ||||
|     } | ||||
|  | ||||
|     protected open fun onSearchMenuItemActionExpand(item: MenuItem?) { | ||||
|     } | ||||
|  | ||||
|     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 | ||||
|      */ | ||||
|     private fun invalidateMenuOnExpand(): Boolean { | ||||
|         return if (expandActionViewFromInteraction) { | ||||
|             activity?.invalidateOptionsMenu() | ||||
|             setCurrentSearchViewState(SearchViewState.FOCUSED) // we are technically focused here | ||||
|             false | ||||
|         } else { | ||||
|             true | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -7,17 +7,11 @@ import kotlinx.coroutines.CoroutineScope | ||||
| import kotlinx.coroutines.MainScope | ||||
| import kotlinx.coroutines.cancel | ||||
| import nucleus.presenter.RxPresenter | ||||
| import rx.Observable | ||||
|  | ||||
| open class BasePresenter<V> : RxPresenter<V>() { | ||||
|  | ||||
|     var presenterScope: CoroutineScope = MainScope() | ||||
|  | ||||
|     /** | ||||
|      * Query from the view where applicable | ||||
|      */ | ||||
|     var query: String = "" | ||||
|  | ||||
|     override fun onCreate(savedState: Bundle?) { | ||||
|         try { | ||||
|             super.onCreate(savedState) | ||||
| @@ -39,13 +33,4 @@ open class BasePresenter<V> : RxPresenter<V>() { | ||||
|     } | ||||
|  | ||||
|     fun <T> Preference<T>.asState() = PreferenceMutableState(this, presenterScope) | ||||
|  | ||||
|     /** | ||||
|      * Subscribes an observable with [deliverLatestCache] 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>.subscribeLatestCache(onNext: (V, T) -> Unit, onError: ((V, Throwable) -> Unit) = { _, _ -> }) = compose(deliverLatestCache<T>()).subscribe(split(onNext, onError)).apply { add(this) } | ||||
| } | ||||
|   | ||||
| @@ -898,6 +898,15 @@ class ReaderPresenter( | ||||
|      */ | ||||
|     private fun <T> Observable<T>.subscribeFirst(onNext: (ReaderActivity, T) -> Unit, onError: ((ReaderActivity, 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. | ||||
|      * | ||||
|      * @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>.subscribeLatestCache(onNext: (ReaderActivity, T) -> Unit, onError: ((ReaderActivity, Throwable) -> Unit) = { _, _ -> }) = compose(deliverLatestCache<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 | ||||
|   | ||||
| @@ -1,46 +0,0 @@ | ||||
| package eu.kanade.tachiyomi.widget | ||||
|  | ||||
| import android.content.Context | ||||
| import android.util.AttributeSet | ||||
| import androidx.core.content.withStyledAttributes | ||||
| import androidx.recyclerview.widget.GridLayoutManager | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import kotlin.math.max | ||||
|  | ||||
| class AutofitRecyclerView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : | ||||
|     RecyclerView(context, attrs) { | ||||
|  | ||||
|     private val manager = GridLayoutManager(context, 1) | ||||
|  | ||||
|     private var columnWidth = -1 | ||||
|  | ||||
|     var spanCount = 0 | ||||
|         set(value) { | ||||
|             field = value | ||||
|             if (value > 0) { | ||||
|                 manager.spanCount = value | ||||
|             } | ||||
|         } | ||||
|  | ||||
|     val itemWidth: Int | ||||
|         get() = measuredWidth / manager.spanCount | ||||
|  | ||||
|     init { | ||||
|         if (attrs != null) { | ||||
|             val attrsArray = intArrayOf(android.R.attr.columnWidth) | ||||
|             context.withStyledAttributes(attrs, attrsArray) { | ||||
|                 columnWidth = getDimensionPixelSize(0, -1) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         layoutManager = manager | ||||
|     } | ||||
|  | ||||
|     override fun onMeasure(widthSpec: Int, heightSpec: Int) { | ||||
|         super.onMeasure(widthSpec, heightSpec) | ||||
|         if (spanCount == 0 && columnWidth > 0) { | ||||
|             val count = max(1, measuredWidth / columnWidth) | ||||
|             spanCount = count | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,31 +0,0 @@ | ||||
| package eu.kanade.tachiyomi.widget | ||||
|  | ||||
| import android.content.Context | ||||
| import android.util.AttributeSet | ||||
| import android.view.LayoutInflater | ||||
| import android.widget.LinearLayout | ||||
| import androidx.annotation.StringRes | ||||
| import eu.kanade.tachiyomi.databinding.CommonDialogWithCheckboxBinding | ||||
|  | ||||
| class DialogCheckboxView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : | ||||
|     LinearLayout(context, attrs) { | ||||
|  | ||||
|     private val binding: CommonDialogWithCheckboxBinding | ||||
|  | ||||
|     init { | ||||
|         binding = CommonDialogWithCheckboxBinding.inflate(LayoutInflater.from(context), this, false) | ||||
|         addView(binding.root) | ||||
|     } | ||||
|  | ||||
|     fun setDescription(@StringRes id: Int) { | ||||
|         binding.description.text = context.getString(id) | ||||
|     } | ||||
|  | ||||
|     fun setOptionDescription(@StringRes id: Int) { | ||||
|         binding.checkboxOption.text = context.getString(id) | ||||
|     } | ||||
|  | ||||
|     fun isChecked(): Boolean { | ||||
|         return binding.checkboxOption.isChecked | ||||
|     } | ||||
| } | ||||
| @@ -1,47 +0,0 @@ | ||||
| package eu.kanade.tachiyomi.widget | ||||
|  | ||||
| import android.content.Context | ||||
| import android.util.AttributeSet | ||||
| import androidx.annotation.StringRes | ||||
| import androidx.compose.material3.LocalContentColor | ||||
| import androidx.compose.material3.MaterialTheme | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.runtime.CompositionLocalProvider | ||||
| import androidx.compose.runtime.getValue | ||||
| import androidx.compose.runtime.mutableStateOf | ||||
| import androidx.compose.runtime.setValue | ||||
| import androidx.compose.ui.platform.AbstractComposeView | ||||
| import androidx.core.view.isVisible | ||||
| import eu.kanade.presentation.components.EmptyScreen | ||||
| import eu.kanade.presentation.theme.TachiyomiTheme | ||||
|  | ||||
| class EmptyView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : | ||||
|     AbstractComposeView(context, attrs) { | ||||
|  | ||||
|     var message by mutableStateOf("") | ||||
|  | ||||
|     /** | ||||
|      * Hide the information view | ||||
|      */ | ||||
|     fun hide() { | ||||
|         this.isVisible = false | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show the information view | ||||
|      * @param textResource text of information view | ||||
|      */ | ||||
|     fun show(@StringRes textResource: Int) { | ||||
|         message = context.getString(textResource) | ||||
|         this.isVisible = true | ||||
|     } | ||||
|  | ||||
|     @Composable | ||||
|     override fun Content() { | ||||
|         TachiyomiTheme { | ||||
|             CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onBackground) { | ||||
|                 EmptyScreen(message = message) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,64 +0,0 @@ | ||||
| package eu.kanade.tachiyomi.widget | ||||
|  | ||||
| import android.content.Context | ||||
| import android.util.AttributeSet | ||||
| import android.view.inputmethod.EditorInfo | ||||
| import androidx.appcompat.widget.SearchView | ||||
| import androidx.core.view.inputmethod.EditorInfoCompat | ||||
| import eu.kanade.domain.base.BasePreferences | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.util.preference.asHotFlow | ||||
| import kotlinx.coroutines.CoroutineScope | ||||
| import kotlinx.coroutines.Dispatchers | ||||
| import kotlinx.coroutines.SupervisorJob | ||||
| import kotlinx.coroutines.cancel | ||||
| import kotlinx.coroutines.flow.launchIn | ||||
| import uy.kohesive.injekt.Injekt | ||||
| import uy.kohesive.injekt.api.get | ||||
|  | ||||
| /** | ||||
|  * A custom [SearchView] that sets [EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING] to imeOptions | ||||
|  * if [BasePreferences.incognitoMode] is true. Some IMEs may not respect this flag. | ||||
|  */ | ||||
| class TachiyomiSearchView @JvmOverloads constructor( | ||||
|     context: Context, | ||||
|     attrs: AttributeSet? = null, | ||||
|     defStyleAttr: Int = R.attr.searchViewStyle, | ||||
| ) : SearchView(context, attrs, defStyleAttr) { | ||||
|  | ||||
|     private var scope: CoroutineScope? = null | ||||
|  | ||||
|     override fun onAttachedToWindow() { | ||||
|         super.onAttachedToWindow() | ||||
|         scope = CoroutineScope(SupervisorJob() + Dispatchers.Main) | ||||
|         Injekt.get<BasePreferences>().incognitoMode() | ||||
|             .asHotFlow { | ||||
|                 imeOptions = if (it) { | ||||
|                     imeOptions or EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING | ||||
|                 } else { | ||||
|                     imeOptions and EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING.inv() | ||||
|                 } | ||||
|             } | ||||
|             .launchIn(scope!!) | ||||
|     } | ||||
|  | ||||
|     override fun setOnQueryTextListener(listener: OnQueryTextListener?) { | ||||
|         super.setOnQueryTextListener(listener) | ||||
|         val searchAutoComplete: SearchAutoComplete = findViewById(R.id.search_src_text) | ||||
|         searchAutoComplete.setOnEditorActionListener { _, actionID, _ -> | ||||
|             if (actionID == EditorInfo.IME_ACTION_SEARCH || actionID == EditorInfo.IME_NULL) { | ||||
|                 clearFocus() | ||||
|                 listener?.onQueryTextSubmit(query.toString()) | ||||
|                 true | ||||
|             } else { | ||||
|                 false | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun onDetachedFromWindow() { | ||||
|         super.onDetachedFromWindow() | ||||
|         scope?.cancel() | ||||
|         scope = null | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user