From 22518f173fba856df75066e69a5a8d749e72e280 Mon Sep 17 00:00:00 2001 From: mpm11011 Date: Sun, 16 Aug 2020 19:08:09 -0400 Subject: [PATCH 01/14] Adding class stubs for settings search, UI elements. --- app/build.gradle | 2 + .../ui/setting/SettingsControllerFactory.kt | 13 ++ .../ui/setting/SettingsMainController.kt | 34 ++++ .../settingssearch/SettingsSearchAdapter.kt | 81 ++++++++ .../SettingsSearchController.kt | 177 ++++++++++++++++++ .../settingssearch/SettingsSearchHolder.kt | 51 +++++ .../settingssearch/SettingsSearchItem.kt | 71 +++++++ .../settingssearch/SettingsSearchPresenter.kt | 83 ++++++++ .../res/layout/settings_search_controller.xml | 36 ++++ .../settings_search_controller_card.xml | 57 ++++++ app/src/main/res/menu/settings_main.xml | 12 ++ 11 files changed, 617 insertions(+) create mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsControllerFactory.kt create mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchAdapter.kt create mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt create mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHolder.kt create mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchItem.kt create mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchPresenter.kt create mode 100644 app/src/main/res/layout/settings_search_controller.xml create mode 100644 app/src/main/res/layout/settings_search_controller_card.xml create mode 100644 app/src/main/res/menu/settings_main.xml diff --git a/app/build.gradle b/app/build.gradle index 4f5df7db6f..fcab50ecce 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -201,6 +201,8 @@ dependencies { // Preferences implementation 'com.github.tfcporciuncula:flow-preferences:1.3.0' + implementation 'com.github.ByteHamster:SearchPreference:v1.0.3' + implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" // Model View Presenter final nucleus_version = '3.0.0' diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsControllerFactory.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsControllerFactory.kt new file mode 100644 index 0000000000..7f892f56db --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsControllerFactory.kt @@ -0,0 +1,13 @@ +package eu.kanade.tachiyomi.ui.setting + +import android.content.Context +import com.bytehamster.lib.preferencesearch.SearchPreference +import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys + +class SettingsControllerFactory(context: Context) { + var searchablePrefs = Keys::class.members.map { member -> SearchPreference(context).key = member.name } + + companion object Factory { + var controllers: List? = null + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt index 9c3f48580b..72527ee648 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt @@ -1,14 +1,23 @@ package eu.kanade.tachiyomi.ui.setting +import android.view.Menu +import android.view.MenuInflater +import androidx.appcompat.widget.SearchView import androidx.preference.PreferenceScreen import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction +import eu.kanade.tachiyomi.ui.setting.settingssearch.SettingsSearchController import eu.kanade.tachiyomi.util.preference.iconRes import eu.kanade.tachiyomi.util.preference.iconTint import eu.kanade.tachiyomi.util.preference.onClick import eu.kanade.tachiyomi.util.preference.preference import eu.kanade.tachiyomi.util.preference.titleRes import eu.kanade.tachiyomi.util.system.getResourceColor +import kotlinx.coroutines.flow.filterIsInstance +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import reactivecircus.flowbinding.appcompat.QueryTextEvent +import reactivecircus.flowbinding.appcompat.queryTextEvents class SettingsMainController : SettingsController() { @@ -82,4 +91,29 @@ class SettingsMainController : SettingsController() { private fun navigateTo(controller: SettingsController) { router.pushController(controller.withFadeTransaction()) } + + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + // Inflate menu + inflater.inflate(R.menu.settings_main, menu) + + // Initialize search option. + val searchItem = menu.findItem(R.id.action_search) + val searchView = searchItem.actionView as SearchView + searchView.maxWidth = Int.MAX_VALUE + + // Change hint to show global search. + searchView.queryHint = applicationContext?.getString(R.string.action_global_search_hint) + + // Create query listener which opens the global search view. + searchView.queryTextEvents() + .filterIsInstance() + .onEach { performSettingsSearch(it.queryText.toString()) } + .launchIn(scope) + } + + private fun performSettingsSearch(query: String) { + router.pushController( + SettingsSearchController(query).withFadeTransaction() + ) + } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchAdapter.kt new file mode 100644 index 0000000000..a733df777d --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchAdapter.kt @@ -0,0 +1,81 @@ +package eu.kanade.tachiyomi.ui.setting.settingssearch + +import android.os.Bundle +import android.os.Parcelable +import android.util.SparseArray +import androidx.preference.Preference +import androidx.recyclerview.widget.RecyclerView +import eu.davidea.flexibleadapter.FlexibleAdapter + +/** + * Adapter that holds the search cards. + * + * @param controller instance of [SettingsSearchController]. + */ +class SettingsSearchAdapter(val controller: SettingsSearchController) : + FlexibleAdapter(null, controller, true) { + + val titleClickListener: OnTitleClickListener = controller + + /** + * Bundle where the view state of the holders is saved. + */ + private var bundle = Bundle() + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int, payloads: List) { + super.onBindViewHolder(holder, position, payloads) + restoreHolderState(holder) + } + + override fun onViewRecycled(holder: RecyclerView.ViewHolder) { + super.onViewRecycled(holder) + saveHolderState(holder, bundle) + } + + override fun onSaveInstanceState(outState: Bundle) { + val holdersBundle = Bundle() + allBoundViewHolders.forEach { saveHolderState(it, holdersBundle) } + outState.putBundle(HOLDER_BUNDLE_KEY, holdersBundle) + super.onSaveInstanceState(outState) + } + + override fun onRestoreInstanceState(savedInstanceState: Bundle) { + super.onRestoreInstanceState(savedInstanceState) + bundle = savedInstanceState.getBundle(HOLDER_BUNDLE_KEY)!! + } + + /** + * Saves the view state of the given holder. + * + * @param holder The holder to save. + * @param outState The bundle where the state is saved. + */ + private fun saveHolderState(holder: RecyclerView.ViewHolder, outState: Bundle) { + val key = "holder_${holder.bindingAdapterPosition}" + val holderState = SparseArray() + holder.itemView.saveHierarchyState(holderState) + outState.putSparseParcelableArray(key, holderState) + } + + /** + * Restores the view state of the given holder. + * + * @param holder The holder to restore. + */ + private fun restoreHolderState(holder: RecyclerView.ViewHolder) { + val key = "holder_${holder.bindingAdapterPosition}" + val holderState = bundle.getSparseParcelableArray(key) + if (holderState != null) { + holder.itemView.restoreHierarchyState(holderState) + bundle.remove(key) + } + } + + interface OnTitleClickListener { + fun onTitleClick(pref: Preference) + } + + private companion object { + const val HOLDER_BUNDLE_KEY = "holder_bundle" + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt new file mode 100644 index 0000000000..4b9a74233b --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt @@ -0,0 +1,177 @@ +package eu.kanade.tachiyomi.ui.setting.settingssearch + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.Menu +import android.view.MenuInflater +import android.view.MenuItem +import android.view.View +import android.view.ViewGroup +import androidx.appcompat.widget.SearchView +import androidx.preference.Preference +import androidx.recyclerview.widget.LinearLayoutManager +import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.databinding.SettingsSearchControllerBinding +import eu.kanade.tachiyomi.ui.base.controller.NucleusController +import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction +import eu.kanade.tachiyomi.ui.setting.SettingsControllerFactory +import kotlinx.coroutines.flow.filterIsInstance +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import reactivecircus.flowbinding.appcompat.QueryTextEvent +import reactivecircus.flowbinding.appcompat.queryTextEvents + +/** + * This controller shows and manages the different search result in settings search. + * This controller should only handle UI actions, IO actions should be done by [SettingsSearchPresenter] + * [SettingsSearchAdapter.WhatListener] called when preference is clicked in settings search + */ +open class SettingsSearchController( + protected val initialQuery: String? = null, + protected val extensionFilter: String? = null +) : NucleusController(), + SettingsSearchAdapter.OnTitleClickListener { + + /** + * Adapter containing search results grouped by lang. + */ + protected var adapter: SettingsSearchAdapter? = null + + protected var controllers = SettingsControllerFactory.controllers + + init { + setHasOptionsMenu(true) + } + + /** + * Initiate the view with [R.layout.settings_search_controller]. + * + * @param inflater used to load the layout xml. + * @param container containing parent views. + * @return inflated view + */ + override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View { + binding = SettingsSearchControllerBinding.inflate(inflater) + return binding.root + } + + override fun getTitle(): String? { + return presenter.query + } + + /** + * Create the [SettingsSearchPresenter] used in controller. + * + * @return instance of [SettingsSearchPresenter] + */ + override fun createPresenter(): SettingsSearchPresenter { + return SettingsSearchPresenter(initialQuery, extensionFilter) + } + + /** + * Adds items to the options menu. + * + * @param menu menu containing options. + * @param inflater used to load the menu xml. + */ + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + // Inflate menu. + inflater.inflate(R.menu.settings_main, menu) + + // Initialize search menu + val searchItem = menu.findItem(R.id.action_search) + val searchView = searchItem.actionView as SearchView + searchView.maxWidth = Int.MAX_VALUE + + searchItem.setOnActionExpandListener(object : MenuItem.OnActionExpandListener { + override fun onMenuItemActionExpand(item: MenuItem?): Boolean { + searchView.onActionViewExpanded() // Required to show the query in the view + searchView.setQuery(presenter.query, false) + return true + } + + override fun onMenuItemActionCollapse(item: MenuItem?): Boolean { + return true + } + }) + + searchView.queryTextEvents() + .filterIsInstance() + .onEach { + presenter.search(it.queryText.toString()) + searchItem.collapseActionView() + setTitle() // Update toolbar title + } + .launchIn(scope) + } + + /** + * Called when the view is created + * + * @param view view of controller + */ + override fun onViewCreated(view: View) { + super.onViewCreated(view) + + adapter = SettingsSearchAdapter(this) + + // Create recycler and set adapter. + binding.recycler.layoutManager = LinearLayoutManager(view.context) + binding.recycler.adapter = adapter + } + + override fun onDestroyView(view: View) { + adapter = null + super.onDestroyView(view) + } + + override fun onSaveViewState(view: View, outState: Bundle) { + super.onSaveViewState(view, outState) + adapter?.onSaveInstanceState(outState) + } + + override fun onRestoreViewState(view: View, savedViewState: Bundle) { + super.onRestoreViewState(view, savedViewState) + adapter?.onRestoreInstanceState(savedViewState) + } + + /** + * Returns the view holder for the given preference. + * + * @param pref used to find holder containing source + * @return the holder of the preference or null if it's not bound. + */ + private fun getHolder(pref: Preference): SettingsSearchHolder? { + val adapter = adapter ?: return null + + adapter.allBoundViewHolders.forEach { holder -> + val item = adapter.getItem(holder.bindingAdapterPosition) + if (item != null && pref.key == item.pref.key) { + return holder as SettingsSearchHolder + } + } + + return null + } + + /** + * Add search result to adapter. + * + * @param searchResult result of search. + */ + fun setItems(searchResult: List) { + adapter?.updateDataSet(searchResult) + } + + /** + * Opens a catalogue with the given search. + */ + override fun onTitleClick(pref: Preference) { + // TODO - These asserts will be the death of me, fix them. + for (ctrl in this!!.controllers!!) { + if (ctrl.findPreference(pref.key) != null) { + router.pushController(ctrl.withFadeTransaction()) + } + } + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHolder.kt new file mode 100644 index 0000000000..a5c91bec13 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHolder.kt @@ -0,0 +1,51 @@ +package eu.kanade.tachiyomi.ui.setting.settingssearch + +import android.view.View +import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder +import kotlinx.android.synthetic.main.settings_search_controller_card.setting +import kotlinx.android.synthetic.main.settings_search_controller_card.title_wrapper + +/** + * Holder that binds the [SettingsSearchItem] containing catalogue cards. + * + * @param view view of [SettingsSearchItem] + * @param adapter instance of [SettingsSearchAdapter] + */ +class SettingsSearchHolder(view: View, val adapter: SettingsSearchAdapter) : + BaseFlexibleViewHolder(view, adapter) { + + /** + * Adapter containing preference from search results. + */ + private val settingsAdapter = SettingsSearchAdapter(adapter.controller) + + private var lastBoundResults: List? = null + + init { + title_wrapper.setOnClickListener { + adapter.getItem(bindingAdapterPosition)?.let { + adapter.titleClickListener.onTitleClick(it.pref) + } + } + } + + /** + * Show the loading of source search result. + * + * @param item item of card. + */ + fun bind(item: SettingsSearchItem) { + val preference = item.pref + val results = item.results + + val titlePrefix = if (item.highlighted) "▶ " else "" + + // Set Title with country code if available. + setting.text = titlePrefix + preference.key + + if (results !== lastBoundResults) { + settingsAdapter.updateDataSet(results) + lastBoundResults = results + } + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchItem.kt new file mode 100644 index 0000000000..60fb219a28 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchItem.kt @@ -0,0 +1,71 @@ +package eu.kanade.tachiyomi.ui.setting.settingssearch + +import android.view.View +import androidx.preference.Preference +import androidx.recyclerview.widget.RecyclerView +import eu.davidea.flexibleadapter.FlexibleAdapter +import eu.davidea.flexibleadapter.items.AbstractFlexibleItem +import eu.davidea.flexibleadapter.items.IFlexible +import eu.kanade.tachiyomi.R + +/** + * Item that contains search result information. + * + * @param pref the source for the search results. + * @param results the search results. + * @param highlighted whether this search item should be highlighted/marked in the catalogue search view. + */ +class SettingsSearchItem(val pref: Preference, val results: List?, val highlighted: Boolean = false) : + AbstractFlexibleItem() { + + /** + * Set view. + * + * @return id of view + */ + override fun getLayoutRes(): Int { + return R.layout.settings_search_controller_card + } + + /** + * Create view holder (see [SettingsSearchAdapter]. + * + * @return holder of view. + */ + override fun createViewHolder(view: View, adapter: FlexibleAdapter>): SettingsSearchHolder { + return SettingsSearchHolder(view, adapter as SettingsSearchAdapter) + } + + /** + * Bind item to view. + */ + override fun bindViewHolder( + adapter: FlexibleAdapter>, + holder: SettingsSearchHolder, + position: Int, + payloads: List? + ) { + holder.bind(this) + } + + /** + * Used to check if two items are equal. + * + * @return items are equal? + */ + override fun equals(other: Any?): Boolean { + if (other is SettingsSearchItem) { + return pref.key == other.pref.key + } + return false + } + + /** + * Return hash code of item. + * + * @return hashcode + */ + override fun hashCode(): Int { + return pref.key.toInt() + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchPresenter.kt new file mode 100644 index 0000000000..8fd1a52591 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchPresenter.kt @@ -0,0 +1,83 @@ +package eu.kanade.tachiyomi.ui.setting.settingssearch + +import android.os.Bundle +import androidx.preference.Preference +import eu.kanade.tachiyomi.data.database.DatabaseHelper +import eu.kanade.tachiyomi.data.preference.PreferencesHelper +import eu.kanade.tachiyomi.extension.ExtensionManager +import eu.kanade.tachiyomi.source.Source +import eu.kanade.tachiyomi.source.SourceManager +import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter +import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourcePresenter +import rx.Subscription +import rx.subjects.PublishSubject +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get +import uy.kohesive.injekt.injectLazy + +/** + * Presenter of [SettingsSearchController] + * Function calls should be done from here. UI calls should be done from the controller. + * + * @param sourceManager manages the different sources. + * @param db manages the database calls. + * @param preferences manages the preference calls. + */ +open class SettingsSearchPresenter( + val initialQuery: String? = "", + val initialExtensionFilter: String? = null, + val sourceManager: SourceManager = Injekt.get(), + val db: DatabaseHelper = Injekt.get(), + val preferences: PreferencesHelper = Injekt.get() +) : BasePresenter() { + + /** + * Query from the view. + */ + var query = "" + private set + + /** + * Fetches the different sources by user settings. + */ + private var fetchSourcesSubscription: Subscription? = null + + /** + * Subject which fetches image of given manga. + */ + private val fetchImageSubject = PublishSubject.create, Source>>() + + /** + * Subscription for fetching images of manga. + */ + private var fetchImageSubscription: Subscription? = null + + private val extensionManager by injectLazy() + + private var extensionFilter: String? = null + + override fun onCreate(savedState: Bundle?) { + super.onCreate(savedState) + + extensionFilter = savedState?.getString(SettingsSearchPresenter::extensionFilter.name) + ?: initialExtensionFilter + + // TODO - Perform a search with previous or initial state + } + + override fun onDestroy() { + fetchSourcesSubscription?.unsubscribe() + fetchImageSubscription?.unsubscribe() + super.onDestroy() + } + + override fun onSave(state: Bundle) { + state.putString(BrowseSourcePresenter::query.name, query) + state.putString(SettingsSearchPresenter::extensionFilter.name, extensionFilter) + super.onSave(state) + } + + fun search(toString: String) { + // TODO - My ignorance of kotlin pattern is showing here... why would the search logic take place in the Presenter? + } +} diff --git a/app/src/main/res/layout/settings_search_controller.xml b/app/src/main/res/layout/settings_search_controller.xml new file mode 100644 index 0000000000..807f904dda --- /dev/null +++ b/app/src/main/res/layout/settings_search_controller.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/settings_search_controller_card.xml b/app/src/main/res/layout/settings_search_controller_card.xml new file mode 100644 index 0000000000..94c63ed4b8 --- /dev/null +++ b/app/src/main/res/layout/settings_search_controller_card.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + diff --git a/app/src/main/res/menu/settings_main.xml b/app/src/main/res/menu/settings_main.xml new file mode 100644 index 0000000000..112431a726 --- /dev/null +++ b/app/src/main/res/menu/settings_main.xml @@ -0,0 +1,12 @@ + + + + + From 8c82b766e393307a300c62caf88c19f3e4513435 Mon Sep 17 00:00:00 2001 From: lmj0011 <9396189+lmj0011@users.noreply.github.com> Date: Wed, 19 Aug 2020 09:28:29 -0500 Subject: [PATCH 02/14] - implement searchable settings - `SettingsController.setupPreferenceScreen` must return a PreferenceScreen --- app/build.gradle | 2 +- .../extension/ExtensionFilterController.kt | 2 +- .../browse/source/SourceFilterController.kt | 4 +- .../tachiyomi/ui/more/AboutController.kt | 2 +- .../tachiyomi/ui/more/MoreController.kt | 2 +- .../ui/setting/SettingsAdvancedController.kt | 2 +- .../ui/setting/SettingsBackupController.kt | 2 +- .../ui/setting/SettingsBrowseController.kt | 2 +- .../ui/setting/SettingsController.kt | 2 +- .../ui/setting/SettingsDownloadController.kt | 2 +- .../ui/setting/SettingsGeneralController.kt | 2 +- .../ui/setting/SettingsLibraryController.kt | 2 +- .../ui/setting/SettingsMainController.kt | 11 +- .../SettingsParentalControlsController.kt | 2 +- .../ui/setting/SettingsReaderController.kt | 2 +- .../ui/setting/SettingsSecurityController.kt | 2 +- .../ui/setting/SettingsTrackingController.kt | 2 +- .../settingssearch/SettingsSearchAdapter.kt | 4 +- .../SettingsSearchController.kt | 79 ++++++++----- .../settingssearch/SettingsSearchHelper.kt | 106 ++++++++++++++++++ .../settingssearch/SettingsSearchHolder.kt | 30 ++--- .../settingssearch/SettingsSearchItem.kt | 8 +- .../settings_search_controller_card.xml | 41 +++---- app/src/main/res/values/dimens.xml | 4 + 24 files changed, 218 insertions(+), 99 deletions(-) create mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt diff --git a/app/build.gradle b/app/build.gradle index fcab50ecce..bf29d4fd84 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -202,7 +202,6 @@ dependencies { // Preferences implementation 'com.github.tfcporciuncula:flow-preferences:1.3.0' implementation 'com.github.ByteHamster:SearchPreference:v1.0.3' - implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" // Model View Presenter final nucleus_version = '3.0.0' @@ -276,6 +275,7 @@ dependencies { testImplementation "org.robolectric:shadows-play-services:$robolectric_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$BuildPluginsVersion.KOTLIN" + implementation "org.jetbrains.kotlin:kotlin-reflect:$BuildPluginsVersion.KOTLIN" final coroutines_version = '1.3.8' implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionFilterController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionFilterController.kt index 31f72bc728..8a5b3abf87 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionFilterController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionFilterController.kt @@ -13,7 +13,7 @@ import uy.kohesive.injekt.api.get class ExtensionFilterController : SettingsController() { - override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) { + override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply { titleRes = R.string.label_extensions val activeLangs = preferences.enabledLanguages().get() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceFilterController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceFilterController.kt index 1edf4969e6..2b11f75509 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceFilterController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceFilterController.kt @@ -24,7 +24,7 @@ class SourceFilterController : SettingsController() { private val onlineSources by lazy { Injekt.get().getOnlineSources() } - override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) { + override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply { titleRes = R.string.label_sources // Get the list of active language codes. @@ -46,7 +46,7 @@ class SourceFilterController : SettingsController() { // Create a preference group and set initial state and change listener switchPreferenceCategory { - preferenceScreen.addPreference(this) + this@apply.addPreference(this) title = LocaleHelper.getSourceDisplayName(lang, context) isPersistent = false if (lang in activeLangsCodes) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt index 1abef4141e..7ee57ce569 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt @@ -41,7 +41,7 @@ class AboutController : SettingsController() { private val isUpdaterEnabled = BuildConfig.INCLUDE_UPDATER - override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) { + override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply { titleRes = R.string.pref_category_about preference { 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 b49007f3ee..7f357e727f 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 @@ -38,7 +38,7 @@ class MoreController : private var isDownloading: Boolean = false private var downloadQueueSize: Int = 0 - override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) { + override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply { titleRes = R.string.label_more val tintColor = context.getResourceColor(R.attr.colorAccent) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt index 9be61ad9d5..7ac4b8532c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt @@ -41,7 +41,7 @@ class SettingsAdvancedController : SettingsController() { private val db: DatabaseHelper by injectLazy() @SuppressLint("BatteryLife") - override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) { + override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply { titleRes = R.string.pref_category_advanced switchPreference { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt index f030d36803..c42d21dfe3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt @@ -49,7 +49,7 @@ class SettingsBackupController : SettingsController() { requestPermissionsSafe(arrayOf(WRITE_EXTERNAL_STORAGE), 500) } - override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) { + override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply { titleRes = R.string.backup preference { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBrowseController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBrowseController.kt index ab4d0bd7b4..7212095c36 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBrowseController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBrowseController.kt @@ -12,7 +12,7 @@ import eu.kanade.tachiyomi.util.preference.titleRes class SettingsBrowseController : SettingsController() { - override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) { + override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply { titleRes = R.string.browse preferenceCategory { 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 ee9c15366d..6915b17df6 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 @@ -50,7 +50,7 @@ abstract class SettingsController : PreferenceController() { setupPreferenceScreen(screen) } - abstract fun setupPreferenceScreen(screen: PreferenceScreen): Any? + abstract fun setupPreferenceScreen(screen: PreferenceScreen): PreferenceScreen private fun getThemedContext(): Context { val tv = TypedValue() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt index 82c055a0fc..76ff9f1967 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt @@ -40,7 +40,7 @@ class SettingsDownloadController : SettingsController() { private val db: DatabaseHelper by injectLazy() - override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) { + override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply { titleRes = R.string.pref_category_downloads preference { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt index f3785bea66..e7feda39cf 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt @@ -24,7 +24,7 @@ import kotlinx.coroutines.flow.launchIn class SettingsGeneralController : SettingsController() { - override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) { + override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply { titleRes = R.string.pref_category_general intListPreference { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt index b42ed0b0a0..477d880e79 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt @@ -40,7 +40,7 @@ class SettingsLibraryController : SettingsController() { private val db: DatabaseHelper = Injekt.get() - override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) { + override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply { titleRes = R.string.pref_category_library val dbCategories = db.getCategories().executeAsBlocking() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt index 72527ee648..c3a4f0e9cb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt @@ -7,6 +7,7 @@ import androidx.preference.PreferenceScreen import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction import eu.kanade.tachiyomi.ui.setting.settingssearch.SettingsSearchController +import eu.kanade.tachiyomi.ui.setting.settingssearch.SettingsSearchHelper import eu.kanade.tachiyomi.util.preference.iconRes import eu.kanade.tachiyomi.util.preference.iconTint import eu.kanade.tachiyomi.util.preference.onClick @@ -21,7 +22,9 @@ import reactivecircus.flowbinding.appcompat.queryTextEvents class SettingsMainController : SettingsController() { - override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) { + override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply { + SettingsSearchHelper.initPreferenceSearchResultCollection(context, preferenceManager) + titleRes = R.string.label_settings val tintColor = context.getResourceColor(R.attr.colorAccent) @@ -106,8 +109,10 @@ class SettingsMainController : SettingsController() { // Create query listener which opens the global search view. searchView.queryTextEvents() - .filterIsInstance() - .onEach { performSettingsSearch(it.queryText.toString()) } + .filterIsInstance() + .onEach { + performSettingsSearch(it.queryText.toString()) + } .launchIn(scope) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsParentalControlsController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsParentalControlsController.kt index 016b626c59..42708094ae 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsParentalControlsController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsParentalControlsController.kt @@ -13,7 +13,7 @@ import eu.kanade.tachiyomi.util.preference.titleRes class SettingsParentalControlsController : SettingsController() { - override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) { + override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply { titleRes = R.string.pref_category_parental_controls listPreference { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsReaderController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsReaderController.kt index e35f49666b..fbbcd90564 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsReaderController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsReaderController.kt @@ -19,7 +19,7 @@ import kotlinx.coroutines.flow.launchIn class SettingsReaderController : SettingsController() { - override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) { + override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply { titleRes = R.string.pref_category_reader intListPreference { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSecurityController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSecurityController.kt index 6fb3a1e663..bf1bb76fdc 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSecurityController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSecurityController.kt @@ -14,7 +14,7 @@ import kotlinx.coroutines.flow.launchIn class SettingsSecurityController : SettingsController() { - override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) { + override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply { titleRes = R.string.pref_category_security if (BiometricManager.from(context).canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsTrackingController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsTrackingController.kt index d61cce20ae..dbe4e5ad99 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsTrackingController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsTrackingController.kt @@ -31,7 +31,7 @@ class SettingsTrackingController : private val trackManager: TrackManager by injectLazy() - override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) { + override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply { titleRes = R.string.pref_category_tracking switchPreference { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchAdapter.kt index a733df777d..75cfae28cc 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchAdapter.kt @@ -3,9 +3,9 @@ package eu.kanade.tachiyomi.ui.setting.settingssearch import android.os.Bundle import android.os.Parcelable import android.util.SparseArray -import androidx.preference.Preference import androidx.recyclerview.widget.RecyclerView import eu.davidea.flexibleadapter.FlexibleAdapter +import eu.kanade.tachiyomi.ui.setting.SettingsController /** * Adapter that holds the search cards. @@ -72,7 +72,7 @@ class SettingsSearchAdapter(val controller: SettingsSearchController) : } interface OnTitleClickListener { - fun onTitleClick(pref: Preference) + fun onTitleClick(ctrl: SettingsController) } private companion object { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt index 4b9a74233b..5184607532 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt @@ -8,18 +8,13 @@ import android.view.MenuItem import android.view.View import android.view.ViewGroup import androidx.appcompat.widget.SearchView -import androidx.preference.Preference import androidx.recyclerview.widget.LinearLayoutManager import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.databinding.SettingsSearchControllerBinding import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction +import eu.kanade.tachiyomi.ui.setting.SettingsController import eu.kanade.tachiyomi.ui.setting.SettingsControllerFactory -import kotlinx.coroutines.flow.filterIsInstance -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import reactivecircus.flowbinding.appcompat.QueryTextEvent -import reactivecircus.flowbinding.appcompat.queryTextEvents /** * This controller shows and manages the different search result in settings search. @@ -83,10 +78,13 @@ open class SettingsSearchController( val searchView = searchItem.actionView as SearchView searchView.maxWidth = Int.MAX_VALUE + searchItem.expandActionView() + setItems(getResultSet()) + searchItem.setOnActionExpandListener(object : MenuItem.OnActionExpandListener { override fun onMenuItemActionExpand(item: MenuItem?): Boolean { searchView.onActionViewExpanded() // Required to show the query in the view - searchView.setQuery(presenter.query, false) + setItems(getResultSet()) return true } @@ -95,14 +93,19 @@ open class SettingsSearchController( } }) - searchView.queryTextEvents() - .filterIsInstance() - .onEach { - presenter.search(it.queryText.toString()) + searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { + override fun onQueryTextSubmit(query: String?): Boolean { searchItem.collapseActionView() - setTitle() // Update toolbar title + setTitle(query) // Update toolbar title + setItems(getResultSet(query)) + return false } - .launchIn(scope) + + override fun onQueryTextChange(newText: String?): Boolean { + setItems(getResultSet(newText)) + return false + } + }) } /** @@ -141,17 +144,44 @@ open class SettingsSearchController( * @param pref used to find holder containing source * @return the holder of the preference or null if it's not bound. */ - private fun getHolder(pref: Preference): SettingsSearchHolder? { - val adapter = adapter ?: return null +// private fun getHolder(pref: Preference): SettingsSearchHolder? { +// val adapter = adapter ?: return null +// +// adapter.allBoundViewHolders.forEach { holder -> +// val item = adapter.getItem(holder.bindingAdapterPosition) +// if (item != null && pref.key == item.pref.key) { +// return holder as SettingsSearchHolder +// } +// } +// +// return null +// } - adapter.allBoundViewHolders.forEach { holder -> - val item = adapter.getItem(holder.bindingAdapterPosition) - if (item != null && pref.key == item.pref.key) { - return holder as SettingsSearchHolder + /** + * returns a list of `SettingsSearchItem` to be shown as search results + */ + fun getResultSet(query: String? = null): List { + val list = mutableListOf() + + if (query.isNullOrBlank()) { + SettingsSearchHelper.prefSearchResultList.forEach { + list.add(SettingsSearchItem(it, null)) } + } else { + SettingsSearchHelper.prefSearchResultList + .filter { + val inTitle = it.title.contains(query, true) + val inSummary = it.summary.contains(query, true) + val inBreadcrumb = it.breadcrumb.contains(query, true) + + return@filter inTitle || inSummary || inBreadcrumb + } + .forEach { + list.add(SettingsSearchItem(it, null)) + } } - return null + return list } /** @@ -166,12 +196,7 @@ open class SettingsSearchController( /** * Opens a catalogue with the given search. */ - override fun onTitleClick(pref: Preference) { - // TODO - These asserts will be the death of me, fix them. - for (ctrl in this!!.controllers!!) { - if (ctrl.findPreference(pref.key) != null) { - router.pushController(ctrl.withFadeTransaction()) - } - } + override fun onTitleClick(ctrl: SettingsController) { + router.replaceTopController(ctrl.withFadeTransaction()) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt new file mode 100644 index 0000000000..1f8d6458c2 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt @@ -0,0 +1,106 @@ +package eu.kanade.tachiyomi.ui.setting.settingssearch + +import android.content.Context +import androidx.preference.Preference +import androidx.preference.PreferenceCategory +import androidx.preference.PreferenceGroup +import androidx.preference.PreferenceManager +import eu.kanade.tachiyomi.ui.browse.extension.ExtensionFilterController +import eu.kanade.tachiyomi.ui.browse.source.SourceFilterController +import eu.kanade.tachiyomi.ui.more.AboutController +import eu.kanade.tachiyomi.ui.more.MoreController +import eu.kanade.tachiyomi.ui.setting.SettingsAdvancedController +import eu.kanade.tachiyomi.ui.setting.SettingsBackupController +import eu.kanade.tachiyomi.ui.setting.SettingsBrowseController +import eu.kanade.tachiyomi.ui.setting.SettingsController +import eu.kanade.tachiyomi.ui.setting.SettingsDownloadController +import eu.kanade.tachiyomi.ui.setting.SettingsGeneralController +import eu.kanade.tachiyomi.ui.setting.SettingsLibraryController +import eu.kanade.tachiyomi.ui.setting.SettingsParentalControlsController +import eu.kanade.tachiyomi.ui.setting.SettingsReaderController +import eu.kanade.tachiyomi.ui.setting.SettingsSecurityController +import eu.kanade.tachiyomi.ui.setting.SettingsTrackingController +import kotlin.reflect.KClass +import kotlin.reflect.full.createInstance + +object SettingsSearchHelper { + var prefSearchResultList: MutableList = mutableListOf() + private set + + /** + * All subclasses of `SettingsController` should be listed here, in order to have their preferences searchable. + */ + private val settingControllersList: List> = listOf( + SettingsAdvancedController::class, + SettingsBackupController::class, + SettingsBrowseController::class, + SettingsDownloadController::class, + SettingsGeneralController::class, + SettingsLibraryController::class, + SettingsParentalControlsController::class, + SettingsReaderController::class, + SettingsSecurityController::class, + SettingsTrackingController::class, + ExtensionFilterController::class, + SourceFilterController::class, + AboutController::class, + MoreController::class + ) + + /** + * Must be called to populate `prefSearchResultList` + */ + fun initPreferenceSearchResultCollection(context: Context, preferenceManager: PreferenceManager) { + prefSearchResultList.clear() + + settingControllersList.forEach { kClass -> + val ctrl = kClass.createInstance() + val settingsPrefScreen = ctrl.setupPreferenceScreen(preferenceManager.createPreferenceScreen(context)) + val prefCount = settingsPrefScreen.preferenceCount + for (i in 0 until prefCount) { + val rootPref = settingsPrefScreen.getPreference(i) + if (rootPref.title == null) continue // no title, not a preference. (note: only info notes appear to not have titles) + getSettingSearchResult(ctrl, rootPref, "${settingsPrefScreen.title}") + } + } + } + + /** + * Extracts the data needed from a `Preference` to create a `SettingsSearchResult`, and then adds it to `prefSearchResultList` + */ + private fun getSettingSearchResult(ctrl: SettingsController, pref: Preference, breadcrumbs: String = "") { + when (pref) { + is PreferenceGroup -> { + val breadcrumbsStr = breadcrumbs + " > ${pref.title}" + + for (x in 0 until pref.preferenceCount) { + val subPref = pref.getPreference(x) + getSettingSearchResult(ctrl, subPref, breadcrumbsStr) // recursion + } + } + is PreferenceCategory -> { + val breadcrumbsStr = breadcrumbs + " > ${pref.title}" + + for (x in 0 until pref.preferenceCount) { + val subPref = pref.getPreference(x) + getSettingSearchResult(ctrl, subPref, breadcrumbsStr) // recursion + } + } + else -> { + // Is an actual preference + val title = pref.title.toString() + val summary = if (pref.summary != null) pref.summary.toString() else "" + val breadcrumbsStr = breadcrumbs + " > ${pref.title}" + + prefSearchResultList.add(SettingsSearchResult(title, summary, breadcrumbsStr, ctrl)) + } + } + } + + data class SettingsSearchResult( + val title: String, + val summary: String, + val breadcrumb: String, + val searchController: SettingsController + ) +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHolder.kt index a5c91bec13..11ab808190 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHolder.kt @@ -2,8 +2,8 @@ package eu.kanade.tachiyomi.ui.setting.settingssearch import android.view.View import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder -import kotlinx.android.synthetic.main.settings_search_controller_card.setting -import kotlinx.android.synthetic.main.settings_search_controller_card.title_wrapper +import kotlin.reflect.full.createInstance +import kotlinx.android.synthetic.main.settings_search_controller_card.* /** * Holder that binds the [SettingsSearchItem] containing catalogue cards. @@ -14,17 +14,12 @@ import kotlinx.android.synthetic.main.settings_search_controller_card.title_wrap class SettingsSearchHolder(view: View, val adapter: SettingsSearchAdapter) : BaseFlexibleViewHolder(view, adapter) { - /** - * Adapter containing preference from search results. - */ - private val settingsAdapter = SettingsSearchAdapter(adapter.controller) - - private var lastBoundResults: List? = null - init { title_wrapper.setOnClickListener { adapter.getItem(bindingAdapterPosition)?.let { - adapter.titleClickListener.onTitleClick(it.pref) + val ctrl = it.settingsSearchResult.searchController + // needs to be a new instance to avoid this error https://github.com/bluelinelabs/Conductor/issues/446 + adapter.titleClickListener.onTitleClick(ctrl::class.createInstance()) } } } @@ -35,17 +30,8 @@ class SettingsSearchHolder(view: View, val adapter: SettingsSearchAdapter) : * @param item item of card. */ fun bind(item: SettingsSearchItem) { - val preference = item.pref - val results = item.results - - val titlePrefix = if (item.highlighted) "▶ " else "" - - // Set Title with country code if available. - setting.text = titlePrefix + preference.key - - if (results !== lastBoundResults) { - settingsAdapter.updateDataSet(results) - lastBoundResults = results - } + search_result_pref_title.text = item.settingsSearchResult.title + search_result_pref_summary.text = item.settingsSearchResult.summary + search_result_pref_breadcrumb.text = item.settingsSearchResult.breadcrumb } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchItem.kt index 60fb219a28..f555abf9f3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchItem.kt @@ -1,7 +1,6 @@ package eu.kanade.tachiyomi.ui.setting.settingssearch import android.view.View -import androidx.preference.Preference import androidx.recyclerview.widget.RecyclerView import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.items.AbstractFlexibleItem @@ -13,9 +12,8 @@ import eu.kanade.tachiyomi.R * * @param pref the source for the search results. * @param results the search results. - * @param highlighted whether this search item should be highlighted/marked in the catalogue search view. */ -class SettingsSearchItem(val pref: Preference, val results: List?, val highlighted: Boolean = false) : +class SettingsSearchItem(val settingsSearchResult: SettingsSearchHelper.SettingsSearchResult, val results: List?) : AbstractFlexibleItem() { /** @@ -55,7 +53,7 @@ class SettingsSearchItem(val pref: Preference, val results: List + + - - + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/search_result_pref_summary" + tools:text="Location" /> diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index fd1c4105e1..8b59b5c6cb 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -23,4 +23,8 @@ 14sp 0dp + + 50dp + 20dp + 20dp From 5b5ea5ab8a9079860e38d8b97e4376de41887381 Mon Sep 17 00:00:00 2001 From: mpm11011 Date: Wed, 26 Aug 2020 20:53:56 -0400 Subject: [PATCH 03/14] Remove unneeded SettingsControllerFactory. --- app/build.gradle | 1 - .../ui/setting/SettingsControllerFactory.kt | 13 ------------- .../settingssearch/SettingsSearchController.kt | 3 --- 3 files changed, 17 deletions(-) delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsControllerFactory.kt diff --git a/app/build.gradle b/app/build.gradle index bf29d4fd84..8768cac00d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -201,7 +201,6 @@ dependencies { // Preferences implementation 'com.github.tfcporciuncula:flow-preferences:1.3.0' - implementation 'com.github.ByteHamster:SearchPreference:v1.0.3' // Model View Presenter final nucleus_version = '3.0.0' diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsControllerFactory.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsControllerFactory.kt deleted file mode 100644 index 7f892f56db..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsControllerFactory.kt +++ /dev/null @@ -1,13 +0,0 @@ -package eu.kanade.tachiyomi.ui.setting - -import android.content.Context -import com.bytehamster.lib.preferencesearch.SearchPreference -import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys - -class SettingsControllerFactory(context: Context) { - var searchablePrefs = Keys::class.members.map { member -> SearchPreference(context).key = member.name } - - companion object Factory { - var controllers: List? = null - } -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt index 5184607532..7227bd8b90 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt @@ -14,7 +14,6 @@ import eu.kanade.tachiyomi.databinding.SettingsSearchControllerBinding import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction import eu.kanade.tachiyomi.ui.setting.SettingsController -import eu.kanade.tachiyomi.ui.setting.SettingsControllerFactory /** * This controller shows and manages the different search result in settings search. @@ -32,8 +31,6 @@ open class SettingsSearchController( */ protected var adapter: SettingsSearchAdapter? = null - protected var controllers = SettingsControllerFactory.controllers - init { setHasOptionsMenu(true) } From 8fe315c3547fa391c0ddc1b61f999ba59ee0d692 Mon Sep 17 00:00:00 2001 From: mpm11011 Date: Wed, 26 Aug 2020 21:46:36 -0400 Subject: [PATCH 04/14] Set query hint, clean up code smell. --- .../settingssearch/SettingsSearchController.kt | 3 +++ .../settingssearch/SettingsSearchPresenter.kt | 14 -------------- app/src/main/res/values/strings.xml | 1 + 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt index 7227bd8b90..44b06597e7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt @@ -75,6 +75,9 @@ open class SettingsSearchController( val searchView = searchItem.actionView as SearchView searchView.maxWidth = Int.MAX_VALUE + // Change hint to show "search settings." + searchView.queryHint = applicationContext?.getString(R.string.action_search_settings) + searchItem.expandActionView() setItems(getResultSet()) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchPresenter.kt index 8fd1a52591..8be02aea14 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchPresenter.kt @@ -1,16 +1,13 @@ package eu.kanade.tachiyomi.ui.setting.settingssearch import android.os.Bundle -import androidx.preference.Preference import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.extension.ExtensionManager -import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourcePresenter import rx.Subscription -import rx.subjects.PublishSubject import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy @@ -42,11 +39,6 @@ open class SettingsSearchPresenter( */ private var fetchSourcesSubscription: Subscription? = null - /** - * Subject which fetches image of given manga. - */ - private val fetchImageSubject = PublishSubject.create, Source>>() - /** * Subscription for fetching images of manga. */ @@ -61,8 +53,6 @@ open class SettingsSearchPresenter( extensionFilter = savedState?.getString(SettingsSearchPresenter::extensionFilter.name) ?: initialExtensionFilter - - // TODO - Perform a search with previous or initial state } override fun onDestroy() { @@ -76,8 +66,4 @@ open class SettingsSearchPresenter( state.putString(SettingsSearchPresenter::extensionFilter.name, extensionFilter) super.onSave(state) } - - fun search(toString: String) { - // TODO - My ignorance of kotlin pattern is showing here... why would the search logic take place in the Presenter? - } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3f0e8822f8..f1d38f72b8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -44,6 +44,7 @@ Latest chapter Date added Search + Search settings Global search Select all Select inverse From 3ebea4c3057b4f49b1a9f68747d3ad836f4a6acb Mon Sep 17 00:00:00 2001 From: mpm11011 Date: Wed, 26 Aug 2020 23:07:59 -0400 Subject: [PATCH 05/14] Add search button to MoreController, stop infinite recursion. --- .../tachiyomi/ui/more/MoreController.kt | 38 +++++++++++++++++++ .../ui/setting/SettingsMainController.kt | 2 +- .../settingssearch/SettingsSearchHelper.kt | 4 +- 3 files changed, 40 insertions(+), 4 deletions(-) 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 7f357e727f..55261c3afa 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,6 +2,9 @@ package eu.kanade.tachiyomi.ui.more import android.content.Context import android.util.AttributeSet +import android.view.Menu +import android.view.MenuInflater +import androidx.appcompat.widget.SearchView import androidx.preference.Preference import androidx.preference.PreferenceScreen import eu.kanade.tachiyomi.R @@ -15,6 +18,8 @@ import eu.kanade.tachiyomi.ui.category.CategoryController import eu.kanade.tachiyomi.ui.download.DownloadController import eu.kanade.tachiyomi.ui.setting.SettingsController import eu.kanade.tachiyomi.ui.setting.SettingsMainController +import eu.kanade.tachiyomi.ui.setting.settingssearch.SettingsSearchController +import eu.kanade.tachiyomi.ui.setting.settingssearch.SettingsSearchHelper import eu.kanade.tachiyomi.util.preference.add import eu.kanade.tachiyomi.util.preference.iconRes import eu.kanade.tachiyomi.util.preference.iconTint @@ -26,6 +31,11 @@ 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 kotlinx.coroutines.flow.filterIsInstance +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import reactivecircus.flowbinding.appcompat.QueryTextEvent +import reactivecircus.flowbinding.appcompat.queryTextEvents import rx.android.schedulers.AndroidSchedulers import uy.kohesive.injekt.injectLazy @@ -39,6 +49,7 @@ class MoreController : private var downloadQueueSize: Int = 0 override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply { + SettingsSearchHelper.initPreferenceSearchResultCollection(context, preferenceManager) titleRes = R.string.label_more val tintColor = context.getResourceColor(R.attr.colorAccent) @@ -140,6 +151,33 @@ class MoreController : } } + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + // Inflate menu + inflater.inflate(R.menu.settings_main, menu) + + // Initialize search option. + val searchItem = menu.findItem(R.id.action_search) + val searchView = searchItem.actionView as SearchView + searchView.maxWidth = Int.MAX_VALUE + + // Change hint to show global search. + searchView.queryHint = applicationContext?.getString(R.string.action_search_settings) + + // Create query listener which opens the global search view. + searchView.queryTextEvents() + .filterIsInstance() + .onEach { + performSettingsSearch(it.queryText.toString()) + } + .launchIn(scope) + } + + private fun performSettingsSearch(query: String) { + router.pushController( + SettingsSearchController(query).withFadeTransaction() + ) + } + companion object { private const val URL_HELP = "https://tachiyomi.org/help/" } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt index c3a4f0e9cb..8e85c618ca 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt @@ -105,7 +105,7 @@ class SettingsMainController : SettingsController() { searchView.maxWidth = Int.MAX_VALUE // Change hint to show global search. - searchView.queryHint = applicationContext?.getString(R.string.action_global_search_hint) + searchView.queryHint = applicationContext?.getString(R.string.action_search_settings) // Create query listener which opens the global search view. searchView.queryTextEvents() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt index 1f8d6458c2..f57fc2ee69 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt @@ -8,7 +8,6 @@ import androidx.preference.PreferenceManager import eu.kanade.tachiyomi.ui.browse.extension.ExtensionFilterController import eu.kanade.tachiyomi.ui.browse.source.SourceFilterController import eu.kanade.tachiyomi.ui.more.AboutController -import eu.kanade.tachiyomi.ui.more.MoreController import eu.kanade.tachiyomi.ui.setting.SettingsAdvancedController import eu.kanade.tachiyomi.ui.setting.SettingsBackupController import eu.kanade.tachiyomi.ui.setting.SettingsBrowseController @@ -43,8 +42,7 @@ object SettingsSearchHelper { SettingsTrackingController::class, ExtensionFilterController::class, SourceFilterController::class, - AboutController::class, - MoreController::class + AboutController::class ) /** From 437a34b5dce46fb7a1bb773a3a0af1fc66d48009 Mon Sep 17 00:00:00 2001 From: lmj0011 <9396189+lmj0011@users.noreply.github.com> Date: Thu, 27 Aug 2020 00:53:50 -0500 Subject: [PATCH 06/14] - initialize SearchResultCollection once in Activity.onCreate --- .../eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt | 4 ++++ .../main/java/eu/kanade/tachiyomi/ui/more/MoreController.kt | 2 -- .../kanade/tachiyomi/ui/setting/SettingsMainController.kt | 3 --- .../ui/setting/settingssearch/SettingsSearchHelper.kt | 6 +++++- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt index 0ecde8b1d6..d2953c5dba 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt @@ -10,6 +10,8 @@ import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate +import eu.kanade.tachiyomi.ui.setting.settingssearch.SettingsSearchHelper +import eu.kanade.tachiyomi.util.lang.launchNow import eu.kanade.tachiyomi.util.system.LocaleHelper import uy.kohesive.injekt.injectLazy @@ -76,6 +78,8 @@ abstract class BaseActivity : AppCompatActivity() { super.onCreate(savedInstanceState) secureActivityDelegate.onCreate() + + launchNow { SettingsSearchHelper.initPreferenceSearchResultCollection(this@BaseActivity) } } override fun onResume() { 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 55261c3afa..f45b6ae7c7 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 @@ -19,7 +19,6 @@ import eu.kanade.tachiyomi.ui.download.DownloadController import eu.kanade.tachiyomi.ui.setting.SettingsController import eu.kanade.tachiyomi.ui.setting.SettingsMainController import eu.kanade.tachiyomi.ui.setting.settingssearch.SettingsSearchController -import eu.kanade.tachiyomi.ui.setting.settingssearch.SettingsSearchHelper import eu.kanade.tachiyomi.util.preference.add import eu.kanade.tachiyomi.util.preference.iconRes import eu.kanade.tachiyomi.util.preference.iconTint @@ -49,7 +48,6 @@ class MoreController : private var downloadQueueSize: Int = 0 override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply { - SettingsSearchHelper.initPreferenceSearchResultCollection(context, preferenceManager) titleRes = R.string.label_more val tintColor = context.getResourceColor(R.attr.colorAccent) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt index 8e85c618ca..71cd5537d4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt @@ -7,7 +7,6 @@ import androidx.preference.PreferenceScreen import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction import eu.kanade.tachiyomi.ui.setting.settingssearch.SettingsSearchController -import eu.kanade.tachiyomi.ui.setting.settingssearch.SettingsSearchHelper import eu.kanade.tachiyomi.util.preference.iconRes import eu.kanade.tachiyomi.util.preference.iconTint import eu.kanade.tachiyomi.util.preference.onClick @@ -23,8 +22,6 @@ import reactivecircus.flowbinding.appcompat.queryTextEvents class SettingsMainController : SettingsController() { override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply { - SettingsSearchHelper.initPreferenceSearchResultCollection(context, preferenceManager) - titleRes = R.string.label_settings val tintColor = context.getResourceColor(R.attr.colorAccent) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt index f57fc2ee69..a2a1ae265a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt @@ -1,5 +1,6 @@ package eu.kanade.tachiyomi.ui.setting.settingssearch +import android.annotation.SuppressLint import android.content.Context import androidx.preference.Preference import androidx.preference.PreferenceCategory @@ -48,7 +49,10 @@ object SettingsSearchHelper { /** * Must be called to populate `prefSearchResultList` */ - fun initPreferenceSearchResultCollection(context: Context, preferenceManager: PreferenceManager) { + @SuppressLint("RestrictedApi") + fun initPreferenceSearchResultCollection(context: Context) { + val preferenceManager = PreferenceManager(context) + prefSearchResultList.clear() settingControllersList.forEach { kClass -> From 78072ad2853256b8c0a53aae466866c4f1fb7b6d Mon Sep 17 00:00:00 2001 From: lmj0011 <9396189+lmj0011@users.noreply.github.com> Date: Fri, 28 Aug 2020 12:52:30 -0500 Subject: [PATCH 07/14] - implement prefernce highlighting after settings search --- .../ui/setting/SettingsController.kt | 34 +++++++++++++++++++ .../settingssearch/SettingsSearchHelper.kt | 11 +++++- .../settingssearch/SettingsSearchHolder.kt | 8 +++-- 3 files changed, 49 insertions(+), 4 deletions(-) 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 6915b17df6..a6a3e11ff2 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 @@ -1,6 +1,9 @@ package eu.kanade.tachiyomi.ui.setting +import android.animation.ArgbEvaluator +import android.animation.ValueAnimator import android.content.Context +import android.graphics.Color import android.os.Bundle import android.util.TypedValue import android.view.ContextThemeWrapper @@ -9,6 +12,7 @@ import android.view.View import android.view.ViewGroup import androidx.appcompat.app.AppCompatActivity import androidx.preference.PreferenceController +import androidx.preference.PreferenceGroup import androidx.preference.PreferenceScreen import com.bluelinelabs.conductor.ControllerChangeHandler import com.bluelinelabs.conductor.ControllerChangeType @@ -26,6 +30,7 @@ import uy.kohesive.injekt.api.get abstract class SettingsController : PreferenceController() { + var preferenceKey: String? = null val preferences: PreferencesHelper = Injekt.get() val scope = CoroutineScope(Job() + Dispatchers.Main) @@ -39,6 +44,24 @@ abstract class SettingsController : PreferenceController() { return super.onCreateView(inflater, container, savedInstanceState) } + override fun onAttach(view: View) { + super.onAttach(view) + + preferenceKey?.let { prefKey -> + val adapter = listView.adapter + scrollToPreference(prefKey) + + listView.post { + if (adapter is PreferenceGroup.PreferencePositionCallback) { + val pos = adapter.getPreferenceAdapterPosition(prefKey) + listView.findViewHolderForAdapterPosition(pos)?.let { + animatePreferenceHighlight(it.itemView) + } + } + } + } + } + override fun onDestroyView(view: View) { super.onDestroyView(view) untilDestroySubscriptions.unsubscribe() @@ -58,6 +81,17 @@ abstract class SettingsController : PreferenceController() { return ContextThemeWrapper(activity, tv.resourceId) } + private fun animatePreferenceHighlight(view: View) { + val duration = 500L + val repeat = 2 + + val colorAnimation = ValueAnimator.ofObject(ArgbEvaluator(), Color.TRANSPARENT, Color.WHITE) + colorAnimation.duration = duration + colorAnimation.repeatCount = repeat + colorAnimation.addUpdateListener { animator -> view.setBackgroundColor(animator.animatedValue as Int) } + colorAnimation.reverse() + } + open fun getTitle(): String? { return preferenceScreen?.title?.toString() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt index a2a1ae265a..9da5103ed6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt @@ -94,12 +94,21 @@ object SettingsSearchHelper { val summary = if (pref.summary != null) pref.summary.toString() else "" val breadcrumbsStr = breadcrumbs + " > ${pref.title}" - prefSearchResultList.add(SettingsSearchResult(title, summary, breadcrumbsStr, ctrl)) + prefSearchResultList.add( + SettingsSearchResult( + key = pref.key, + title = title, + summary = summary, + breadcrumb = breadcrumbsStr, + searchController = ctrl + ) + ) } } } data class SettingsSearchResult( + val key: String?, val title: String, val summary: String, val breadcrumb: String, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHolder.kt index 11ab808190..7313fc9fef 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHolder.kt @@ -17,9 +17,11 @@ class SettingsSearchHolder(view: View, val adapter: SettingsSearchAdapter) : init { title_wrapper.setOnClickListener { adapter.getItem(bindingAdapterPosition)?.let { - val ctrl = it.settingsSearchResult.searchController - // needs to be a new instance to avoid this error https://github.com/bluelinelabs/Conductor/issues/446 - adapter.titleClickListener.onTitleClick(ctrl::class.createInstance()) + val ctrl = it.settingsSearchResult.searchController::class.createInstance() + ctrl.preferenceKey = it.settingsSearchResult.key + + // must pass a new Controller instance to avoid this error https://github.com/bluelinelabs/Conductor/issues/446 + adapter.titleClickListener.onTitleClick(ctrl) } } } From 50c7b32b00f3c73c62152ea5bc1e4f4543018819 Mon Sep 17 00:00:00 2001 From: lmj0011 <9396189+lmj0011@users.noreply.github.com> Date: Fri, 28 Aug 2020 20:47:18 -0500 Subject: [PATCH 08/14] - Ensure all Preferences have a key set or else the highlighting effect will have no effect on it. - remove ExtensionFilterController and SourceFilterController from settingControllersList in SettingsSearchHelper, since those are related to Extensions and not Settings --- .../data/preference/PreferenceKeys.kt | 42 +++++++++++++++++++ .../tachiyomi/ui/more/AboutController.kt | 13 ++++++ .../ui/setting/SettingsAdvancedController.kt | 7 +++- .../ui/setting/SettingsBackupController.kt | 2 + .../ui/setting/SettingsGeneralController.kt | 1 + .../ui/setting/SettingsLibraryController.kt | 2 + .../settingssearch/SettingsSearchHelper.kt | 4 -- app/src/main/res/values/strings.xml | 1 + 8 files changed, 66 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt index 2c7f66dcf1..410df4b2c6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt @@ -165,6 +165,48 @@ object PreferenceKeys { const val enableDoh = "enable_doh" + const val disableBatteryOptimization = "pref_disable_battery_optimization" + + const val clearDatabase = "pref_clear_database" + + const val clearCookies = "pref_clear_cookies" + + const val refreshLibraryCovers = "pref_refresh_library_covers" + + const val refreshLibraryTracking = "pref_refresh_library_tracking" + + const val createBackup = "pref_create_backup" + + const val restoreBackup = "pref_restore_backup" + + const val manageNotifications = "pref_manage_notifications" + + const val libraryColumns = "pref_library_columns" + + const val actionEditCategories = "pref_action_edit_categories" + + const val parentalControlsInfo = "pref_parental_controls_info" + + const val aboutVersion = "pref_about_version" + + const val aboutBuildTime = "pref_about_build_time" + + const val aboutCheckForUpdates = "pref_about_check_for_updates" + + const val aboutWhatsNew = "pref_about_whats_new" + + const val aboutNotices = "pref_about_notices" + + const val aboutWebsite = "pref_about_website" + + const val aboutDiscord = "pref_about_discord" + + const val aboutGitHub = "pref_about_github" + + const val aboutLabelExtensions = "pref_about_label_extensions" + + const val aboutLicenses = "pref_about_licenses" + fun trackUsername(syncId: Int) = "pref_mangasync_username_$syncId" fun trackPassword(syncId: Int) = "pref_mangasync_password_$syncId" diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt index 7ee57ce569..2c3fb84ad4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt @@ -10,6 +10,7 @@ import com.afollestad.materialdialogs.MaterialDialog import com.mikepenz.aboutlibraries.LibsBuilder import eu.kanade.tachiyomi.BuildConfig import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys import eu.kanade.tachiyomi.data.updater.UpdateChecker import eu.kanade.tachiyomi.data.updater.UpdateResult import eu.kanade.tachiyomi.data.updater.UpdaterService @@ -45,6 +46,7 @@ class AboutController : SettingsController() { titleRes = R.string.pref_category_about preference { + key = Keys.aboutVersion titleRes = R.string.version summary = if (BuildConfig.DEBUG) { "Preview r${BuildConfig.COMMIT_COUNT} (${BuildConfig.COMMIT_SHA})" @@ -55,17 +57,20 @@ class AboutController : SettingsController() { onClick { copyDebugInfo() } } preference { + key = Keys.aboutBuildTime titleRes = R.string.build_time summary = getFormattedBuildTime() } if (isUpdaterEnabled) { preference { + key = Keys.aboutCheckForUpdates titleRes = R.string.check_for_updates onClick { checkVersion() } } } preference { + key = Keys.aboutWhatsNew titleRes = R.string.whats_new onClick { @@ -81,6 +86,7 @@ class AboutController : SettingsController() { } if (BuildConfig.DEBUG) { preference { + key = Keys.aboutNotices titleRes = R.string.notices onClick { @@ -91,7 +97,10 @@ class AboutController : SettingsController() { } preferenceCategory { + titleRes = R.string.about_resources + preference { + key = Keys.aboutWebsite titleRes = R.string.website val url = "https://tachiyomi.org" summary = url @@ -101,6 +110,7 @@ class AboutController : SettingsController() { } } preference { + key = Keys.aboutDiscord title = "Discord" val url = "https://discord.gg/tachiyomi" summary = url @@ -110,6 +120,7 @@ class AboutController : SettingsController() { } } preference { + key = Keys.aboutGitHub title = "GitHub" val url = "https://github.com/inorichi/tachiyomi" summary = url @@ -119,6 +130,7 @@ class AboutController : SettingsController() { } } preference { + key = Keys.aboutLabelExtensions titleRes = R.string.label_extensions val url = "https://github.com/inorichi/tachiyomi-extensions" summary = url @@ -128,6 +140,7 @@ class AboutController : SettingsController() { } } preference { + key = Keys.aboutLicenses titleRes = R.string.licenses onClick { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt index 7ac4b8532c..1b06065fc5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt @@ -33,7 +33,6 @@ import rx.schedulers.Schedulers import uy.kohesive.injekt.injectLazy class SettingsAdvancedController : SettingsController() { - private val network: NetworkHelper by injectLazy() private val chapterCache: ChapterCache by injectLazy() @@ -43,7 +42,6 @@ class SettingsAdvancedController : SettingsController() { @SuppressLint("BatteryLife") override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply { titleRes = R.string.pref_category_advanced - switchPreference { key = "acra.enable" titleRes = R.string.pref_enable_acra @@ -53,6 +51,7 @@ class SettingsAdvancedController : SettingsController() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { preference { + key = Keys.disableBatteryOptimization titleRes = R.string.pref_disable_battery_optimization summaryRes = R.string.pref_disable_battery_optimization_summary @@ -86,6 +85,7 @@ class SettingsAdvancedController : SettingsController() { onClick { clearChapterCache() } } preference { + key = Keys.clearDatabase titleRes = R.string.pref_clear_database summaryRes = R.string.pref_clear_database_summary @@ -101,6 +101,7 @@ class SettingsAdvancedController : SettingsController() { titleRes = R.string.label_network preference { + key = Keys.clearCookies titleRes = R.string.pref_clear_cookies onClick { @@ -120,11 +121,13 @@ class SettingsAdvancedController : SettingsController() { titleRes = R.string.label_library preference { + key = Keys.refreshLibraryCovers titleRes = R.string.pref_refresh_library_covers onClick { LibraryUpdateService.start(context, target = Target.COVERS) } } preference { + key = Keys.refreshLibraryTracking titleRes = R.string.pref_refresh_library_tracking summaryRes = R.string.pref_refresh_library_tracking_summary diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt index c42d21dfe3..d9ca82cb61 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt @@ -53,6 +53,7 @@ class SettingsBackupController : SettingsController() { titleRes = R.string.backup preference { + key = Keys.createBackup titleRes = R.string.pref_create_backup summaryRes = R.string.pref_create_backup_summ @@ -67,6 +68,7 @@ class SettingsBackupController : SettingsController() { } } preference { + key = Keys.restoreBackup titleRes = R.string.pref_restore_backup summaryRes = R.string.pref_restore_backup_summ diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt index e7feda39cf..fbe106e2cf 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt @@ -47,6 +47,7 @@ class SettingsGeneralController : SettingsController() { } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { preference { + key = Keys.manageNotifications titleRes = R.string.pref_manage_notifications onClick { val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt index 477d880e79..f4dd9869ca 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt @@ -50,6 +50,7 @@ class SettingsLibraryController : SettingsController() { titleRes = R.string.pref_category_display preference { + key = Keys.libraryColumns titleRes = R.string.pref_library_columns onClick { LibraryColumnsDialog().showDialog(router) @@ -83,6 +84,7 @@ class SettingsLibraryController : SettingsController() { titleRes = R.string.pref_category_library_categories preference { + key = Keys.actionEditCategories titleRes = R.string.action_edit_categories val catCount = dbCategories.size diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt index 9da5103ed6..527e1dc781 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt @@ -6,8 +6,6 @@ import androidx.preference.Preference import androidx.preference.PreferenceCategory import androidx.preference.PreferenceGroup import androidx.preference.PreferenceManager -import eu.kanade.tachiyomi.ui.browse.extension.ExtensionFilterController -import eu.kanade.tachiyomi.ui.browse.source.SourceFilterController import eu.kanade.tachiyomi.ui.more.AboutController import eu.kanade.tachiyomi.ui.setting.SettingsAdvancedController import eu.kanade.tachiyomi.ui.setting.SettingsBackupController @@ -41,8 +39,6 @@ object SettingsSearchHelper { SettingsReaderController::class, SettingsSecurityController::class, SettingsTrackingController::class, - ExtensionFilterController::class, - SourceFilterController::class, AboutController::class ) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f1d38f72b8..94172f369f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -411,6 +411,7 @@ Open source licenses Check for updates Updated to v%1$s + Resources Send crash reports From d53719b79e97b908fbdc2fcf1923d896c0cce858 Mon Sep 17 00:00:00 2001 From: mpm11011 Date: Sun, 30 Aug 2020 16:35:15 -0400 Subject: [PATCH 09/14] Limiting search to settings menu only, localized breadcrumb string, and code cleanup after code review. --- app/build.gradle | 2 - .../tachiyomi/ui/more/MoreController.kt | 36 ------------- .../ui/setting/SettingsMainController.kt | 2 +- .../settingssearch/SettingsSearchAdapter.kt | 5 +- .../SettingsSearchController.kt | 52 +++---------------- .../settingssearch/SettingsSearchHelper.kt | 32 +++++++++--- .../settingssearch/SettingsSearchHolder.kt | 5 +- .../settingssearch/SettingsSearchItem.kt | 18 ------- .../settingssearch/SettingsSearchPresenter.kt | 45 +++------------- 9 files changed, 46 insertions(+), 151 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index ac92590e6b..0223a00546 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -273,11 +273,9 @@ dependencies { testImplementation "org.robolectric:shadows-multidex:$robolectric_version" testImplementation "org.robolectric:shadows-play-services:$robolectric_version" - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$BuildPluginsVersion.KOTLIN" implementation "org.jetbrains.kotlin:kotlin-reflect:$BuildPluginsVersion.KOTLIN" final coroutines_version = '1.3.9' - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version" 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 f45b6ae7c7..7f357e727f 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,9 +2,6 @@ package eu.kanade.tachiyomi.ui.more import android.content.Context import android.util.AttributeSet -import android.view.Menu -import android.view.MenuInflater -import androidx.appcompat.widget.SearchView import androidx.preference.Preference import androidx.preference.PreferenceScreen import eu.kanade.tachiyomi.R @@ -18,7 +15,6 @@ import eu.kanade.tachiyomi.ui.category.CategoryController import eu.kanade.tachiyomi.ui.download.DownloadController import eu.kanade.tachiyomi.ui.setting.SettingsController import eu.kanade.tachiyomi.ui.setting.SettingsMainController -import eu.kanade.tachiyomi.ui.setting.settingssearch.SettingsSearchController import eu.kanade.tachiyomi.util.preference.add import eu.kanade.tachiyomi.util.preference.iconRes import eu.kanade.tachiyomi.util.preference.iconTint @@ -30,11 +26,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 kotlinx.coroutines.flow.filterIsInstance -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import reactivecircus.flowbinding.appcompat.QueryTextEvent -import reactivecircus.flowbinding.appcompat.queryTextEvents import rx.android.schedulers.AndroidSchedulers import uy.kohesive.injekt.injectLazy @@ -149,33 +140,6 @@ class MoreController : } } - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { - // Inflate menu - inflater.inflate(R.menu.settings_main, menu) - - // Initialize search option. - val searchItem = menu.findItem(R.id.action_search) - val searchView = searchItem.actionView as SearchView - searchView.maxWidth = Int.MAX_VALUE - - // Change hint to show global search. - searchView.queryHint = applicationContext?.getString(R.string.action_search_settings) - - // Create query listener which opens the global search view. - searchView.queryTextEvents() - .filterIsInstance() - .onEach { - performSettingsSearch(it.queryText.toString()) - } - .launchIn(scope) - } - - private fun performSettingsSearch(query: String) { - router.pushController( - SettingsSearchController(query).withFadeTransaction() - ) - } - companion object { private const val URL_HELP = "https://tachiyomi.org/help/" } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt index 71cd5537d4..4aebe5a922 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt @@ -115,7 +115,7 @@ class SettingsMainController : SettingsController() { private fun performSettingsSearch(query: String) { router.pushController( - SettingsSearchController(query).withFadeTransaction() + SettingsSearchController().withFadeTransaction() ) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchAdapter.kt index 75cfae28cc..a0a58e6207 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchAdapter.kt @@ -64,9 +64,8 @@ class SettingsSearchAdapter(val controller: SettingsSearchController) : */ private fun restoreHolderState(holder: RecyclerView.ViewHolder) { val key = "holder_${holder.bindingAdapterPosition}" - val holderState = bundle.getSparseParcelableArray(key) - if (holderState != null) { - holder.itemView.restoreHierarchyState(holderState) + bundle.getSparseParcelableArray(key)?.let { + holder.itemView.restoreHierarchyState(it) bundle.remove(key) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt index 44b06597e7..6648e340e8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt @@ -17,13 +17,10 @@ import eu.kanade.tachiyomi.ui.setting.SettingsController /** * This controller shows and manages the different search result in settings search. - * This controller should only handle UI actions, IO actions should be done by [SettingsSearchPresenter] - * [SettingsSearchAdapter.WhatListener] called when preference is clicked in settings search + * [SettingsSearchAdapter.OnTitleClickListener] called when preference is clicked in settings search */ -open class SettingsSearchController( - protected val initialQuery: String? = null, - protected val extensionFilter: String? = null -) : NucleusController(), +class SettingsSearchController : + NucleusController(), SettingsSearchAdapter.OnTitleClickListener { /** @@ -57,7 +54,7 @@ open class SettingsSearchController( * @return instance of [SettingsSearchPresenter] */ override fun createPresenter(): SettingsSearchPresenter { - return SettingsSearchPresenter(initialQuery, extensionFilter) + return SettingsSearchPresenter() } /** @@ -108,11 +105,6 @@ open class SettingsSearchController( }) } - /** - * Called when the view is created - * - * @param view view of controller - */ override fun onViewCreated(view: View) { super.onViewCreated(view) @@ -138,44 +130,14 @@ open class SettingsSearchController( adapter?.onRestoreInstanceState(savedViewState) } - /** - * Returns the view holder for the given preference. - * - * @param pref used to find holder containing source - * @return the holder of the preference or null if it's not bound. - */ -// private fun getHolder(pref: Preference): SettingsSearchHolder? { -// val adapter = adapter ?: return null -// -// adapter.allBoundViewHolders.forEach { holder -> -// val item = adapter.getItem(holder.bindingAdapterPosition) -// if (item != null && pref.key == item.pref.key) { -// return holder as SettingsSearchHolder -// } -// } -// -// return null -// } - /** * returns a list of `SettingsSearchItem` to be shown as search results */ fun getResultSet(query: String? = null): List { val list = mutableListOf() - if (query.isNullOrBlank()) { - SettingsSearchHelper.prefSearchResultList.forEach { - list.add(SettingsSearchItem(it, null)) - } - } else { - SettingsSearchHelper.prefSearchResultList - .filter { - val inTitle = it.title.contains(query, true) - val inSummary = it.summary.contains(query, true) - val inBreadcrumb = it.breadcrumb.contains(query, true) - - return@filter inTitle || inSummary || inBreadcrumb - } + if (!query.isNullOrBlank()) { + SettingsSearchHelper.getFilteredResults(query) .forEach { list.add(SettingsSearchItem(it, null)) } @@ -197,6 +159,6 @@ open class SettingsSearchController( * Opens a catalogue with the given search. */ override fun onTitleClick(ctrl: SettingsController) { - router.replaceTopController(ctrl.withFadeTransaction()) + router.pushController(ctrl.withFadeTransaction()) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt index 527e1dc781..6331bdcd6b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt @@ -2,11 +2,11 @@ package eu.kanade.tachiyomi.ui.setting.settingssearch import android.annotation.SuppressLint import android.content.Context +import android.content.res.Resources import androidx.preference.Preference import androidx.preference.PreferenceCategory import androidx.preference.PreferenceGroup import androidx.preference.PreferenceManager -import eu.kanade.tachiyomi.ui.more.AboutController import eu.kanade.tachiyomi.ui.setting.SettingsAdvancedController import eu.kanade.tachiyomi.ui.setting.SettingsBackupController import eu.kanade.tachiyomi.ui.setting.SettingsBrowseController @@ -18,6 +18,7 @@ import eu.kanade.tachiyomi.ui.setting.SettingsParentalControlsController import eu.kanade.tachiyomi.ui.setting.SettingsReaderController import eu.kanade.tachiyomi.ui.setting.SettingsSecurityController import eu.kanade.tachiyomi.ui.setting.SettingsTrackingController +import eu.kanade.tachiyomi.util.system.isLTR import kotlin.reflect.KClass import kotlin.reflect.full.createInstance @@ -38,8 +39,7 @@ object SettingsSearchHelper { SettingsParentalControlsController::class, SettingsReaderController::class, SettingsSecurityController::class, - SettingsTrackingController::class, - AboutController::class + SettingsTrackingController::class ) /** @@ -63,13 +63,23 @@ object SettingsSearchHelper { } } + fun getFilteredResults(query: String): List { + return prefSearchResultList.filter { + val inTitle = it.title.contains(query, true) + val inSummary = it.summary.contains(query, true) + val inBreadcrumb = it.breadcrumb.contains(query, true) + + return@filter inTitle || inSummary || inBreadcrumb + } + } + /** * Extracts the data needed from a `Preference` to create a `SettingsSearchResult`, and then adds it to `prefSearchResultList` */ private fun getSettingSearchResult(ctrl: SettingsController, pref: Preference, breadcrumbs: String = "") { when (pref) { is PreferenceGroup -> { - val breadcrumbsStr = breadcrumbs + " > ${pref.title}" + val breadcrumbsStr = addLocalizedBreadcrumb(breadcrumbs, "${pref.title}") for (x in 0 until pref.preferenceCount) { val subPref = pref.getPreference(x) @@ -77,7 +87,7 @@ object SettingsSearchHelper { } } is PreferenceCategory -> { - val breadcrumbsStr = breadcrumbs + " > ${pref.title}" + val breadcrumbsStr = addLocalizedBreadcrumb(breadcrumbs, "${pref.title}") for (x in 0 until pref.preferenceCount) { val subPref = pref.getPreference(x) @@ -88,7 +98,7 @@ object SettingsSearchHelper { // Is an actual preference val title = pref.title.toString() val summary = if (pref.summary != null) pref.summary.toString() else "" - val breadcrumbsStr = breadcrumbs + " > ${pref.title}" + val breadcrumbsStr = addLocalizedBreadcrumb(breadcrumbs, "${pref.title}") prefSearchResultList.add( SettingsSearchResult( @@ -103,6 +113,16 @@ object SettingsSearchHelper { } } + private fun addLocalizedBreadcrumb(path: String, node: String): String { + return if (Resources.getSystem().isLTR) { + // This locale reads left to right. + "$path > $node" + } else { + // This locale reads right to left. + "$node < $path" + } + } + data class SettingsSearchResult( val key: String?, val title: String, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHolder.kt index 7313fc9fef..469310eca1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHolder.kt @@ -3,7 +3,10 @@ package eu.kanade.tachiyomi.ui.setting.settingssearch import android.view.View import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder import kotlin.reflect.full.createInstance -import kotlinx.android.synthetic.main.settings_search_controller_card.* +import kotlinx.android.synthetic.main.settings_search_controller_card.search_result_pref_breadcrumb +import kotlinx.android.synthetic.main.settings_search_controller_card.search_result_pref_summary +import kotlinx.android.synthetic.main.settings_search_controller_card.search_result_pref_title +import kotlinx.android.synthetic.main.settings_search_controller_card.title_wrapper /** * Holder that binds the [SettingsSearchItem] containing catalogue cards. diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchItem.kt index f555abf9f3..cb6417472a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchItem.kt @@ -16,11 +16,6 @@ import eu.kanade.tachiyomi.R class SettingsSearchItem(val settingsSearchResult: SettingsSearchHelper.SettingsSearchResult, val results: List?) : AbstractFlexibleItem() { - /** - * Set view. - * - * @return id of view - */ override fun getLayoutRes(): Int { return R.layout.settings_search_controller_card } @@ -34,9 +29,6 @@ class SettingsSearchItem(val settingsSearchResult: SettingsSearchHelper.Settings return SettingsSearchHolder(view, adapter as SettingsSearchAdapter) } - /** - * Bind item to view. - */ override fun bindViewHolder( adapter: FlexibleAdapter>, holder: SettingsSearchHolder, @@ -46,11 +38,6 @@ class SettingsSearchItem(val settingsSearchResult: SettingsSearchHelper.Settings holder.bind(this) } - /** - * Used to check if two items are equal. - * - * @return items are equal? - */ override fun equals(other: Any?): Boolean { if (other is SettingsSearchItem) { return settingsSearchResult == settingsSearchResult @@ -58,11 +45,6 @@ class SettingsSearchItem(val settingsSearchResult: SettingsSearchHelper.Settings return false } - /** - * Return hash code of item. - * - * @return hashcode - */ override fun hashCode(): Int { return settingsSearchResult.hashCode() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchPresenter.kt index 8be02aea14..e3946eed9d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchPresenter.kt @@ -3,30 +3,16 @@ package eu.kanade.tachiyomi.ui.setting.settingssearch import android.os.Bundle import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.extension.ExtensionManager import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter -import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourcePresenter -import rx.Subscription import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get -import uy.kohesive.injekt.injectLazy /** * Presenter of [SettingsSearchController] * Function calls should be done from here. UI calls should be done from the controller. - * - * @param sourceManager manages the different sources. - * @param db manages the database calls. - * @param preferences manages the preference calls. */ -open class SettingsSearchPresenter( - val initialQuery: String? = "", - val initialExtensionFilter: String? = null, - val sourceManager: SourceManager = Injekt.get(), - val db: DatabaseHelper = Injekt.get(), - val preferences: PreferencesHelper = Injekt.get() -) : BasePresenter() { +open class SettingsSearchPresenter : BasePresenter() { /** * Query from the view. @@ -34,36 +20,17 @@ open class SettingsSearchPresenter( var query = "" private set - /** - * Fetches the different sources by user settings. - */ - private var fetchSourcesSubscription: Subscription? = null - - /** - * Subscription for fetching images of manga. - */ - private var fetchImageSubscription: Subscription? = null - - private val extensionManager by injectLazy() - - private var extensionFilter: String? = null + val sourceManager: SourceManager = Injekt.get() + val db: DatabaseHelper = Injekt.get() + val preferences: PreferencesHelper = Injekt.get() override fun onCreate(savedState: Bundle?) { super.onCreate(savedState) - - extensionFilter = savedState?.getString(SettingsSearchPresenter::extensionFilter.name) - ?: initialExtensionFilter - } - - override fun onDestroy() { - fetchSourcesSubscription?.unsubscribe() - fetchImageSubscription?.unsubscribe() - super.onDestroy() + query = savedState?.getString(SettingsSearchPresenter::query.name) ?: "" // TODO - Some way to restore previous query? } override fun onSave(state: Bundle) { - state.putString(BrowseSourcePresenter::query.name, query) - state.putString(SettingsSearchPresenter::extensionFilter.name, extensionFilter) + state.putString(SettingsSearchPresenter::query.name, query) super.onSave(state) } } From 29ab99aa1fe7141b9ec4f372d4f13620a1b7f170 Mon Sep 17 00:00:00 2001 From: lmj0011 <9396189+lmj0011@users.noreply.github.com> Date: Sun, 30 Aug 2020 22:21:32 -0500 Subject: [PATCH 10/14] - moved call to SettingsSearchHelper.initPreferenceSearchResultCollection() into SettingsSearchController --- .../ui/base/activity/BaseActivity.kt | 4 ---- .../SettingsSearchController.kt | 3 +++ .../settingssearch/SettingsSearchHelper.kt | 20 ++++++++++--------- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt index d2953c5dba..0ecde8b1d6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt @@ -10,8 +10,6 @@ import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate -import eu.kanade.tachiyomi.ui.setting.settingssearch.SettingsSearchHelper -import eu.kanade.tachiyomi.util.lang.launchNow import eu.kanade.tachiyomi.util.system.LocaleHelper import uy.kohesive.injekt.injectLazy @@ -78,8 +76,6 @@ abstract class BaseActivity : AppCompatActivity() { super.onCreate(savedInstanceState) secureActivityDelegate.onCreate() - - launchNow { SettingsSearchHelper.initPreferenceSearchResultCollection(this@BaseActivity) } } override fun onResume() { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt index 6648e340e8..9ce6098531 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt @@ -113,6 +113,9 @@ class SettingsSearchController : // Create recycler and set adapter. binding.recycler.layoutManager = LinearLayoutManager(view.context) binding.recycler.adapter = adapter + + // load all search results + SettingsSearchHelper.initPreferenceSearchResultCollection(presenter.preferences.context) } override fun onDestroyView(view: View) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt index 6331bdcd6b..9f7466e6f6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt @@ -18,6 +18,7 @@ import eu.kanade.tachiyomi.ui.setting.SettingsParentalControlsController import eu.kanade.tachiyomi.ui.setting.SettingsReaderController import eu.kanade.tachiyomi.ui.setting.SettingsSecurityController import eu.kanade.tachiyomi.ui.setting.SettingsTrackingController +import eu.kanade.tachiyomi.util.lang.launchNow import eu.kanade.tachiyomi.util.system.isLTR import kotlin.reflect.KClass import kotlin.reflect.full.createInstance @@ -48,17 +49,18 @@ object SettingsSearchHelper { @SuppressLint("RestrictedApi") fun initPreferenceSearchResultCollection(context: Context) { val preferenceManager = PreferenceManager(context) - prefSearchResultList.clear() - settingControllersList.forEach { kClass -> - val ctrl = kClass.createInstance() - val settingsPrefScreen = ctrl.setupPreferenceScreen(preferenceManager.createPreferenceScreen(context)) - val prefCount = settingsPrefScreen.preferenceCount - for (i in 0 until prefCount) { - val rootPref = settingsPrefScreen.getPreference(i) - if (rootPref.title == null) continue // no title, not a preference. (note: only info notes appear to not have titles) - getSettingSearchResult(ctrl, rootPref, "${settingsPrefScreen.title}") + launchNow { + settingControllersList.forEach { kClass -> + val ctrl = kClass.createInstance() + val settingsPrefScreen = ctrl.setupPreferenceScreen(preferenceManager.createPreferenceScreen(context)) + val prefCount = settingsPrefScreen.preferenceCount + for (i in 0 until prefCount) { + val rootPref = settingsPrefScreen.getPreference(i) + if (rootPref.title == null) continue // no title, not a preference. (note: only info notes appear to not have titles) + getSettingSearchResult(ctrl, rootPref, "${settingsPrefScreen.title}") + } } } } From a5098e5b5b3fdae129fd1a7beb2c867d6ae8cca7 Mon Sep 17 00:00:00 2001 From: mpm11011 Date: Sat, 5 Sep 2020 14:28:41 -0400 Subject: [PATCH 11/14] Code review cleanup and refactoring. --- .../ui/setting/SettingsController.kt | 16 ++-- .../ui/setting/SettingsMainController.kt | 10 +-- .../SettingsSearchController.kt | 12 +-- .../settingssearch/SettingsSearchPresenter.kt | 4 - .../settings_search_controller_card.xml | 79 +++++++++---------- app/src/main/res/values/dimens.xml | 4 - 6 files changed, 51 insertions(+), 74 deletions(-) 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 a6a3e11ff2..ff42364c6f 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 @@ -82,14 +82,14 @@ abstract class SettingsController : PreferenceController() { } private fun animatePreferenceHighlight(view: View) { - val duration = 500L - val repeat = 2 - - val colorAnimation = ValueAnimator.ofObject(ArgbEvaluator(), Color.TRANSPARENT, Color.WHITE) - colorAnimation.duration = duration - colorAnimation.repeatCount = repeat - colorAnimation.addUpdateListener { animator -> view.setBackgroundColor(animator.animatedValue as Int) } - colorAnimation.reverse() + ValueAnimator + .ofObject(ArgbEvaluator(), Color.TRANSPARENT, R.attr.rippleColor) + .apply { + duration = 500L + repeatCount = 2 + addUpdateListener { animator -> view.setBackgroundColor(animator.animatedValue as Int) } + reverse() + } } open fun getTitle(): String? { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt index 4aebe5a922..f4ad880e28 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt @@ -108,14 +108,10 @@ class SettingsMainController : SettingsController() { searchView.queryTextEvents() .filterIsInstance() .onEach { - performSettingsSearch(it.queryText.toString()) + router.pushController( + SettingsSearchController().withFadeTransaction() + ) } .launchIn(scope) } - - private fun performSettingsSearch(query: String) { - router.pushController( - SettingsSearchController().withFadeTransaction() - ) - } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt index 9ce6098531..3aeb4a54a3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt @@ -137,16 +137,12 @@ class SettingsSearchController : * returns a list of `SettingsSearchItem` to be shown as search results */ fun getResultSet(query: String? = null): List { - val list = mutableListOf() - - if (!query.isNullOrBlank()) { - SettingsSearchHelper.getFilteredResults(query) - .forEach { - list.add(SettingsSearchItem(it, null)) - } + if (!query.isNullOrBlank() && query.length >= 3) { + return SettingsSearchHelper.getFilteredResults(query) + .map { SettingsSearchItem(it, null) } } - return list + return mutableListOf() } /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchPresenter.kt index e3946eed9d..90e59ba001 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchPresenter.kt @@ -1,9 +1,7 @@ package eu.kanade.tachiyomi.ui.setting.settingssearch import android.os.Bundle -import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -20,8 +18,6 @@ open class SettingsSearchPresenter : BasePresenter() { var query = "" private set - val sourceManager: SourceManager = Injekt.get() - val db: DatabaseHelper = Injekt.get() val preferences: PreferencesHelper = Injekt.get() override fun onCreate(savedState: Bundle?) { diff --git a/app/src/main/res/layout/settings_search_controller_card.xml b/app/src/main/res/layout/settings_search_controller_card.xml index fe2dfda8ac..ada7639e7a 100644 --- a/app/src/main/res/layout/settings_search_controller_card.xml +++ b/app/src/main/res/layout/settings_search_controller_card.xml @@ -1,52 +1,45 @@ - + android:layout_marginStart="48dp" + android:layout_marginTop="16dp" + android:layout_marginBottom="16dp" + android:background="?attr/selectableItemBackground"> - + - + - + + - - - - - - diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 8b59b5c6cb..fd1c4105e1 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -23,8 +23,4 @@ 14sp 0dp - - 50dp - 20dp - 20dp From d37341d7d09021cf2ab10f58ad57e0bc700362d6 Mon Sep 17 00:00:00 2001 From: mpm11011 Date: Sat, 5 Sep 2020 16:20:45 -0400 Subject: [PATCH 12/14] Inlined non-reused key strings. --- .../data/preference/PreferenceKeys.kt | 42 ------------------- .../tachiyomi/ui/more/AboutController.kt | 21 +++++----- .../ui/setting/SettingsAdvancedController.kt | 10 ++--- .../ui/setting/SettingsBackupController.kt | 4 +- .../ui/setting/SettingsGeneralController.kt | 2 +- .../ui/setting/SettingsLibraryController.kt | 4 +- 6 files changed, 20 insertions(+), 63 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt index 410df4b2c6..2c7f66dcf1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt @@ -165,48 +165,6 @@ object PreferenceKeys { const val enableDoh = "enable_doh" - const val disableBatteryOptimization = "pref_disable_battery_optimization" - - const val clearDatabase = "pref_clear_database" - - const val clearCookies = "pref_clear_cookies" - - const val refreshLibraryCovers = "pref_refresh_library_covers" - - const val refreshLibraryTracking = "pref_refresh_library_tracking" - - const val createBackup = "pref_create_backup" - - const val restoreBackup = "pref_restore_backup" - - const val manageNotifications = "pref_manage_notifications" - - const val libraryColumns = "pref_library_columns" - - const val actionEditCategories = "pref_action_edit_categories" - - const val parentalControlsInfo = "pref_parental_controls_info" - - const val aboutVersion = "pref_about_version" - - const val aboutBuildTime = "pref_about_build_time" - - const val aboutCheckForUpdates = "pref_about_check_for_updates" - - const val aboutWhatsNew = "pref_about_whats_new" - - const val aboutNotices = "pref_about_notices" - - const val aboutWebsite = "pref_about_website" - - const val aboutDiscord = "pref_about_discord" - - const val aboutGitHub = "pref_about_github" - - const val aboutLabelExtensions = "pref_about_label_extensions" - - const val aboutLicenses = "pref_about_licenses" - fun trackUsername(syncId: Int) = "pref_mangasync_username_$syncId" fun trackPassword(syncId: Int) = "pref_mangasync_password_$syncId" diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt index 2c3fb84ad4..f33aad5dc8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt @@ -10,7 +10,6 @@ import com.afollestad.materialdialogs.MaterialDialog import com.mikepenz.aboutlibraries.LibsBuilder import eu.kanade.tachiyomi.BuildConfig import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys import eu.kanade.tachiyomi.data.updater.UpdateChecker import eu.kanade.tachiyomi.data.updater.UpdateResult import eu.kanade.tachiyomi.data.updater.UpdaterService @@ -46,7 +45,7 @@ class AboutController : SettingsController() { titleRes = R.string.pref_category_about preference { - key = Keys.aboutVersion + key = "pref_about_version" titleRes = R.string.version summary = if (BuildConfig.DEBUG) { "Preview r${BuildConfig.COMMIT_COUNT} (${BuildConfig.COMMIT_SHA})" @@ -57,20 +56,20 @@ class AboutController : SettingsController() { onClick { copyDebugInfo() } } preference { - key = Keys.aboutBuildTime + key = "pref_about_build_time" titleRes = R.string.build_time summary = getFormattedBuildTime() } if (isUpdaterEnabled) { preference { - key = Keys.aboutCheckForUpdates + key = "pref_about_check_for_updates" titleRes = R.string.check_for_updates onClick { checkVersion() } } } preference { - key = Keys.aboutWhatsNew + key = "pref_about_whats_new" titleRes = R.string.whats_new onClick { @@ -86,7 +85,7 @@ class AboutController : SettingsController() { } if (BuildConfig.DEBUG) { preference { - key = Keys.aboutNotices + key = "pref_about_notices" titleRes = R.string.notices onClick { @@ -100,7 +99,7 @@ class AboutController : SettingsController() { titleRes = R.string.about_resources preference { - key = Keys.aboutWebsite + key = "pref_about_website" titleRes = R.string.website val url = "https://tachiyomi.org" summary = url @@ -110,7 +109,7 @@ class AboutController : SettingsController() { } } preference { - key = Keys.aboutDiscord + key = "pref_about_discord" title = "Discord" val url = "https://discord.gg/tachiyomi" summary = url @@ -120,7 +119,7 @@ class AboutController : SettingsController() { } } preference { - key = Keys.aboutGitHub + key = "pref_about_github" title = "GitHub" val url = "https://github.com/inorichi/tachiyomi" summary = url @@ -130,7 +129,7 @@ class AboutController : SettingsController() { } } preference { - key = Keys.aboutLabelExtensions + key = "pref_about_label_extensions" titleRes = R.string.label_extensions val url = "https://github.com/inorichi/tachiyomi-extensions" summary = url @@ -140,7 +139,7 @@ class AboutController : SettingsController() { } } preference { - key = Keys.aboutLicenses + key = "pref_about_licenses" titleRes = R.string.licenses onClick { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt index 1b06065fc5..87b1142684 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt @@ -51,7 +51,7 @@ class SettingsAdvancedController : SettingsController() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { preference { - key = Keys.disableBatteryOptimization + key = "pref_disable_battery_optimization" titleRes = R.string.pref_disable_battery_optimization summaryRes = R.string.pref_disable_battery_optimization_summary @@ -85,7 +85,7 @@ class SettingsAdvancedController : SettingsController() { onClick { clearChapterCache() } } preference { - key = Keys.clearDatabase + key = "pref_clear_database" titleRes = R.string.pref_clear_database summaryRes = R.string.pref_clear_database_summary @@ -101,7 +101,7 @@ class SettingsAdvancedController : SettingsController() { titleRes = R.string.label_network preference { - key = Keys.clearCookies + key = "pref_clear_cookies" titleRes = R.string.pref_clear_cookies onClick { @@ -121,13 +121,13 @@ class SettingsAdvancedController : SettingsController() { titleRes = R.string.label_library preference { - key = Keys.refreshLibraryCovers + key = "pref_refresh_library_covers" titleRes = R.string.pref_refresh_library_covers onClick { LibraryUpdateService.start(context, target = Target.COVERS) } } preference { - key = Keys.refreshLibraryTracking + key = "pref_refresh_library_tracking" titleRes = R.string.pref_refresh_library_tracking summaryRes = R.string.pref_refresh_library_tracking_summary diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt index d9ca82cb61..459384fdb7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt @@ -53,7 +53,7 @@ class SettingsBackupController : SettingsController() { titleRes = R.string.backup preference { - key = Keys.createBackup + key = "pref_create_backup" titleRes = R.string.pref_create_backup summaryRes = R.string.pref_create_backup_summ @@ -68,7 +68,7 @@ class SettingsBackupController : SettingsController() { } } preference { - key = Keys.restoreBackup + key = "pref_restore_backup" titleRes = R.string.pref_restore_backup summaryRes = R.string.pref_restore_backup_summ diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt index fbe106e2cf..b28d74af28 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt @@ -47,7 +47,7 @@ class SettingsGeneralController : SettingsController() { } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { preference { - key = Keys.manageNotifications + key = "pref_manage_notifications" titleRes = R.string.pref_manage_notifications onClick { val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt index f4dd9869ca..4d83eaf83d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt @@ -50,7 +50,7 @@ class SettingsLibraryController : SettingsController() { titleRes = R.string.pref_category_display preference { - key = Keys.libraryColumns + key = "pref_library_columns" titleRes = R.string.pref_library_columns onClick { LibraryColumnsDialog().showDialog(router) @@ -84,7 +84,7 @@ class SettingsLibraryController : SettingsController() { titleRes = R.string.pref_category_library_categories preference { - key = Keys.actionEditCategories + key = "pref_action_edit_categories" titleRes = R.string.action_edit_categories val catCount = dbCategories.size From 381c061ebc56ba0284ec55a0dec9850384a90ff4 Mon Sep 17 00:00:00 2001 From: mpm11011 Date: Sun, 6 Sep 2020 11:32:03 -0400 Subject: [PATCH 13/14] Adding more UI polish, add comments for future enhancements. --- .../main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt | 2 -- .../eu/kanade/tachiyomi/ui/setting/SettingsController.kt | 3 ++- .../ui/setting/settingssearch/SettingsSearchController.kt | 5 ++++- .../ui/setting/settingssearch/SettingsSearchHelper.kt | 1 + 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt index f33aad5dc8..0bd61bbcde 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt @@ -96,8 +96,6 @@ class AboutController : SettingsController() { } preferenceCategory { - titleRes = R.string.about_resources - preference { key = "pref_about_website" titleRes = R.string.website 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 ff42364c6f..62414f7ef1 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 @@ -19,6 +19,7 @@ import com.bluelinelabs.conductor.ControllerChangeType 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.system.getResourceColor import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -83,7 +84,7 @@ abstract class SettingsController : PreferenceController() { private fun animatePreferenceHighlight(view: View) { ValueAnimator - .ofObject(ArgbEvaluator(), Color.TRANSPARENT, R.attr.rippleColor) + .ofObject(ArgbEvaluator(), Color.TRANSPARENT, view.context.getResourceColor(R.attr.rippleColor)) .apply { duration = 500L repeatCount = 2 diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt index 3aeb4a54a3..14b43f3744 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt @@ -86,6 +86,8 @@ class SettingsSearchController : } override fun onMenuItemActionCollapse(item: MenuItem?): Boolean { + searchView.onActionViewCollapsed() // Required to show the query in the view + router.popCurrentController() return true } }) @@ -135,9 +137,10 @@ class SettingsSearchController : /** * returns a list of `SettingsSearchItem` to be shown as search results + * Future update: should we add a minimum length to the query before displaying results? Consider other languages. */ fun getResultSet(query: String? = null): List { - if (!query.isNullOrBlank() && query.length >= 3) { + if (!query.isNullOrBlank()) { return SettingsSearchHelper.getFilteredResults(query) .map { SettingsSearchItem(it, null) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt index 9f7466e6f6..57fabdda6b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchHelper.kt @@ -77,6 +77,7 @@ object SettingsSearchHelper { /** * Extracts the data needed from a `Preference` to create a `SettingsSearchResult`, and then adds it to `prefSearchResultList` + * Future enhancement: make bold the text matched by the search query. */ private fun getSettingSearchResult(ctrl: SettingsController, pref: Preference, breadcrumbs: String = "") { when (pref) { From 18061d107772f2374263236197e120f0cb5c7eb7 Mon Sep 17 00:00:00 2001 From: lmj0011 <9396189+lmj0011@users.noreply.github.com> Date: Sun, 6 Sep 2020 23:59:41 -0500 Subject: [PATCH 14/14] - retain search query when navigating *away* from SettingsSearchController - keep `searchItem` in `expandActionView` state until user goes back (fixes the empty view in `SettingsSearchSearchController` issue) --- .../data/preference/PreferencesHelper.kt | 5 ++++ .../ui/setting/SettingsMainController.kt | 24 +++++++++---------- .../SettingsSearchController.kt | 16 +++++++------ 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt index 11bffb1863..9a83794ca0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt @@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.data.preference import android.content.Context import android.os.Environment +import androidx.core.content.edit import androidx.core.net.toUri import androidx.preference.PreferenceManager import com.tfcporciuncula.flow.FlowSharedPreferences @@ -249,4 +250,8 @@ class PreferencesHelper(val context: Context) { fun trustedSignatures() = flowPrefs.getStringSet("trusted_signatures", emptySet()) fun enableDoh() = prefs.getBoolean(Keys.enableDoh, false) + + fun lastSearchQuerySearchSettings() = prefs.getString("last_search_query", "") + + fun lastSearchQuerySearchSettings(query: String) = prefs.edit { putString("last_search_query", query) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt index f4ad880e28..a7794073f6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt @@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.setting import android.view.Menu import android.view.MenuInflater +import android.view.MenuItem import androidx.appcompat.widget.SearchView import androidx.preference.PreferenceScreen import eu.kanade.tachiyomi.R @@ -13,11 +14,6 @@ import eu.kanade.tachiyomi.util.preference.onClick import eu.kanade.tachiyomi.util.preference.preference import eu.kanade.tachiyomi.util.preference.titleRes import eu.kanade.tachiyomi.util.system.getResourceColor -import kotlinx.coroutines.flow.filterIsInstance -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import reactivecircus.flowbinding.appcompat.QueryTextEvent -import reactivecircus.flowbinding.appcompat.queryTextEvents class SettingsMainController : SettingsController() { @@ -104,14 +100,16 @@ class SettingsMainController : SettingsController() { // Change hint to show global search. searchView.queryHint = applicationContext?.getString(R.string.action_search_settings) - // Create query listener which opens the global search view. - searchView.queryTextEvents() - .filterIsInstance() - .onEach { - router.pushController( - SettingsSearchController().withFadeTransaction() - ) + searchItem.setOnActionExpandListener(object : MenuItem.OnActionExpandListener { + override fun onMenuItemActionExpand(item: MenuItem?): Boolean { + preferences.lastSearchQuerySearchSettings("") // reset saved search query + router.pushController(SettingsSearchController().withFadeTransaction()) + return true } - .launchIn(scope) + + override fun onMenuItemActionCollapse(item: MenuItem?): Boolean { + return true + } + }) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt index 14b43f3744..3c57e612cb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/settingssearch/SettingsSearchController.kt @@ -27,6 +27,7 @@ class SettingsSearchController : * Adapter containing search results grouped by lang. */ protected var adapter: SettingsSearchAdapter? = null + lateinit var searchView: SearchView init { setHasOptionsMenu(true) @@ -69,7 +70,7 @@ class SettingsSearchController : // Initialize search menu val searchItem = menu.findItem(R.id.action_search) - val searchView = searchItem.actionView as SearchView + searchView = searchItem.actionView as SearchView searchView.maxWidth = Int.MAX_VALUE // Change hint to show "search settings." @@ -80,22 +81,17 @@ class SettingsSearchController : searchItem.setOnActionExpandListener(object : MenuItem.OnActionExpandListener { override fun onMenuItemActionExpand(item: MenuItem?): Boolean { - searchView.onActionViewExpanded() // Required to show the query in the view - setItems(getResultSet()) return true } override fun onMenuItemActionCollapse(item: MenuItem?): Boolean { - searchView.onActionViewCollapsed() // Required to show the query in the view router.popCurrentController() - return true + return false } }) searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextSubmit(query: String?): Boolean { - searchItem.collapseActionView() - setTitle(query) // Update toolbar title setItems(getResultSet(query)) return false } @@ -105,6 +101,8 @@ class SettingsSearchController : return false } }) + + searchView.setQuery(presenter.preferences.lastSearchQuerySearchSettings(), true) } override fun onViewCreated(view: View) { @@ -161,6 +159,10 @@ class SettingsSearchController : * Opens a catalogue with the given search. */ override fun onTitleClick(ctrl: SettingsController) { + searchView.query.let { + presenter.preferences.lastSearchQuerySearchSettings(it.toString()) + } + router.pushController(ctrl.withFadeTransaction()) } }