From c9388f663360568d18aef9bbef105a11c41faf4f Mon Sep 17 00:00:00 2001 From: Jays2Kings Date: Sat, 24 Apr 2021 16:31:31 -0400 Subject: [PATCH] Open source from global search Along with other changes from upstream The difference as you'd expect: Not allowing the opening of a source on migration and from extension intent Also when moving up sources in global search after returning results. The incoming results for subsequent sources will go under the already returned results, instead of being alphabetical and shifting the top results (pinned sources still show on top though) Co-Authored-By: arkon <4098258+arkon@users.noreply.github.com> --- .../data/preference/PreferencesHelper.kt | 2 +- .../manga/design/PreMigrationController.kt | 2 +- .../tachiyomi/ui/source/BrowseController.kt | 3 +- .../tachiyomi/ui/source/SourcePresenter.kt | 5 +- .../source/browse/BrowseSourceController.kt | 55 ++++++++--------- .../ui/source/browse/BrowseSourcePresenter.kt | 5 ++ .../global_search/GlobalSearchAdapter.kt | 7 +++ .../global_search/GlobalSearchController.kt | 12 +++- .../global_search/GlobalSearchHolder.kt | 15 +++++ .../global_search/GlobalSearchPresenter.kt | 37 ++++++++--- .../util/view/ControllerExtensions.kt | 11 ++-- .../source_global_search_controller_card.xml | 61 +++++++++++++++---- 12 files changed, 155 insertions(+), 60 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 138c8f127c..bbafae4217 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 @@ -284,7 +284,7 @@ class PreferencesHelper(val context: Context) { fun hiddenSources() = flowPrefs.getStringSet("hidden_catalogues", mutableSetOf()) - fun pinnedCatalogues() = rxPrefs.getStringSet("pinned_catalogues", emptySet()) + fun pinnedCatalogues() = flowPrefs.getStringSet("pinned_catalogues", mutableSetOf()) fun downloadNew() = flowPrefs.getBoolean(Keys.downloadNew, false) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/design/PreMigrationController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/design/PreMigrationController.kt index 2a685e0391..fe926bf68d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/design/PreMigrationController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/design/PreMigrationController.kt @@ -177,7 +177,7 @@ class PreMigrationController(bundle: Bundle? = null) : val enabledSources = if (item.itemId == R.id.action_match_enabled) { prefs.hiddenSources().get().mapNotNull { it.toLongOrNull() } } else { - prefs.pinnedCatalogues().get()?.mapNotNull { it.toLongOrNull() } ?: emptyList() + prefs.pinnedCatalogues().get().mapNotNull { it.toLongOrNull() } ?: emptyList() } val items = adapter?.currentItems?.toList() ?: return true items.forEach { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/source/BrowseController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/source/BrowseController.kt index 0e60f31db3..5b796740c7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/source/BrowseController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/source/BrowseController.kt @@ -24,7 +24,6 @@ import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.items.IFlexible import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.databinding.BrowseControllerBinding import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.LocalSource @@ -390,7 +389,7 @@ class BrowseController : } private fun pinCatalogue(source: Source, isPinned: Boolean) { - val current = preferences.pinnedCatalogues().getOrDefault() + val current = preferences.pinnedCatalogues().get() if (isPinned) { preferences.pinnedCatalogues().set(current - source.id.toString()) } else { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/source/SourcePresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/source/SourcePresenter.kt index 1bf94d74d2..342a55a294 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/source/SourcePresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/source/SourcePresenter.kt @@ -1,7 +1,6 @@ package eu.kanade.tachiyomi.ui.source import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.source.SourceManager @@ -57,7 +56,7 @@ class SourcePresenter( private fun loadSources() { scope.launch { val pinnedSources = mutableListOf() - val pinnedCatalogues = preferences.pinnedCatalogues().getOrDefault() + val pinnedCatalogues = preferences.pinnedCatalogues().get() val map = TreeMap> { d1, d2 -> // Catalogues without a lang defined will be placed at the end @@ -105,7 +104,7 @@ class SourcePresenter( private fun getLastUsedSource(value: Long): SourceItem? { return (sourceManager.get(value) as? CatalogueSource)?.let { source -> - val pinnedCatalogues = preferences.pinnedCatalogues().getOrDefault() + val pinnedCatalogues = preferences.pinnedCatalogues().get() val isPinned = source.id.toString() in pinnedCatalogues if (isPinned) null else SourceItem(source, null, isPinned) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/source/browse/BrowseSourceController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/source/browse/BrowseSourceController.kt index ca17c12137..a5e865f0dd 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/source/browse/BrowseSourceController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/source/browse/BrowseSourceController.kt @@ -12,7 +12,6 @@ import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.google.android.material.snackbar.Snackbar -import com.jakewharton.rxbinding.support.v7.widget.queryTextChangeEvents import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.items.IFlexible import eu.kanade.tachiyomi.R @@ -29,6 +28,7 @@ import eu.kanade.tachiyomi.ui.main.FloatingSearchInterface import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.manga.MangaDetailsController import eu.kanade.tachiyomi.ui.source.BrowseController +import eu.kanade.tachiyomi.ui.source.global_search.GlobalSearchController import eu.kanade.tachiyomi.ui.webview.WebViewActivity import eu.kanade.tachiyomi.util.addOrRemoveToFavorites import eu.kanade.tachiyomi.util.system.connectivityManager @@ -37,6 +37,7 @@ import eu.kanade.tachiyomi.util.system.openInBrowser import eu.kanade.tachiyomi.util.view.gone import eu.kanade.tachiyomi.util.view.inflate import eu.kanade.tachiyomi.util.view.scrollViewWith +import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener import eu.kanade.tachiyomi.util.view.snack import eu.kanade.tachiyomi.util.view.updateLayoutParams import eu.kanade.tachiyomi.util.view.visible @@ -44,12 +45,8 @@ import eu.kanade.tachiyomi.util.view.visibleIf import eu.kanade.tachiyomi.util.view.withFadeTransaction import eu.kanade.tachiyomi.widget.AutofitRecyclerView import eu.kanade.tachiyomi.widget.EmptyView -import rx.Observable -import rx.Subscription -import rx.android.schedulers.AndroidSchedulers import timber.log.Timber import uy.kohesive.injekt.injectLazy -import java.util.concurrent.TimeUnit /** * Controller to manage the catalogues available in the app. @@ -105,11 +102,6 @@ open class BrowseSourceController(bundle: Bundle) : */ private var recycler: RecyclerView? = null - /** - * Subscription for the search view. - */ - private var searchViewSubscription: Subscription? = null - /** * Endless loading item. */ @@ -124,7 +116,7 @@ open class BrowseSourceController(bundle: Bundle) : } override fun createPresenter(): BrowseSourcePresenter { - return BrowseSourcePresenter(args.getLong(SOURCE_ID_KEY)) + return BrowseSourcePresenter(args.getLong(SOURCE_ID_KEY), args.getString(SEARCH_QUERY_KEY)) } override fun createBinding(inflater: LayoutInflater) = BrowseSourceControllerBinding.inflate(inflater) @@ -142,8 +134,6 @@ open class BrowseSourceController(bundle: Bundle) : } override fun onDestroyView(view: View) { - searchViewSubscription?.unsubscribe() - searchViewSubscription = null adapter = null snack = null recycler = null @@ -222,31 +212,40 @@ open class BrowseSourceController(bundle: Bundle) : val searchView = searchItem.actionView as SearchView val query = presenter.query - if (!query.isBlank()) { + if (query.isNotBlank()) { searchItem.expandActionView() searchView.setQuery(query, true) searchView.clearFocus() } - val searchEventsObservable = searchView.queryTextChangeEvents() - .skip(1) - .filter { router.backstack.lastOrNull()?.controller() == this@BrowseSourceController } - .share() - val writingObservable = searchEventsObservable - .filter { !it.isSubmitted } - .debounce(1250, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()) - val submitObservable = searchEventsObservable - .filter { it.isSubmitted } +// val searchEventsObservable = searchView.queryTextChangeEvents() +// .skip(1) +// .filter { router.backstack.lastOrNull()?.controller() == this@BrowseSourceController } +// .share() +// val writingObservable = searchEventsObservable +// .filter { !it.isSubmitted } +// .debounce(1250, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()) +// val submitObservable = searchEventsObservable +// .filter { it.isSubmitted } +// +// searchViewSubscription?.unsubscribe() +// searchViewSubscription = Observable.merge(writingObservable, submitObservable) +// .map { it.queryText().toString() } +// .subscribeUntilDestroy { searchWithQuery(it) } - searchViewSubscription?.unsubscribe() - searchViewSubscription = Observable.merge(writingObservable, submitObservable) - .map { it.queryText().toString() } - .subscribeUntilDestroy { searchWithQuery(it) } + setOnQueryTextChangeListener(searchView, onlyOnSubmit = true, hideKbOnSubmit = false) { + searchWithQuery(it ?: "") + true + } searchItem.fixExpand( onExpand = { invalidateMenuOnExpand() }, onCollapse = { - searchWithQuery("") + if (router.backstackSize >= 2 && router.backstack[router.backstackSize - 2].controller() is GlobalSearchController) { + router.popController(this) + } else { + searchWithQuery("") + } true } ) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/source/browse/BrowseSourcePresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/source/browse/BrowseSourcePresenter.kt index e5d4ab3546..1dd9d55dac 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/source/browse/BrowseSourcePresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/source/browse/BrowseSourcePresenter.kt @@ -48,6 +48,7 @@ import uy.kohesive.injekt.api.get */ open class BrowseSourcePresenter( sourceId: Long, + searchQuery: String? = null, sourceManager: SourceManager = Injekt.get(), val db: DatabaseHelper = Injekt.get(), private val prefs: PreferencesHelper = Injekt.get(), @@ -117,6 +118,10 @@ open class BrowseSourcePresenter( private var scope = CoroutineScope(Job() + Dispatchers.IO) + init { + query = searchQuery ?: "" + } + override fun onCreate(savedState: Bundle?) { super.onCreate(savedState) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/source/global_search/GlobalSearchAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/source/global_search/GlobalSearchAdapter.kt index c5e4c3c986..de739c8ffe 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/source/global_search/GlobalSearchAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/source/global_search/GlobalSearchAdapter.kt @@ -4,6 +4,7 @@ import android.os.Bundle import android.os.Parcelable import android.util.SparseArray import eu.davidea.flexibleadapter.FlexibleAdapter +import eu.kanade.tachiyomi.source.CatalogueSource /** * Adapter that holds the search cards. @@ -13,6 +14,8 @@ import eu.davidea.flexibleadapter.FlexibleAdapter class GlobalSearchAdapter(val controller: GlobalSearchController) : FlexibleAdapter(null, controller, true) { + val titleClickListener: OnTitleClickListener = controller + /** * Bundle where the view state of the holders is saved. */ @@ -67,6 +70,10 @@ class GlobalSearchAdapter(val controller: GlobalSearchController) : } } + interface OnTitleClickListener { + fun onTitleClick(source: CatalogueSource) + } + private companion object { const val HOLDER_BUNDLE_KEY = "holder_bundle" } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/source/global_search/GlobalSearchController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/source/global_search/GlobalSearchController.kt index 4eae8b19b3..3eb667b639 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/source/global_search/GlobalSearchController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/source/global_search/GlobalSearchController.kt @@ -18,6 +18,7 @@ import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.ui.main.FloatingSearchInterface import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.manga.MangaDetailsController +import eu.kanade.tachiyomi.ui.source.browse.BrowseSourceController import eu.kanade.tachiyomi.util.addOrRemoveToFavorites import eu.kanade.tachiyomi.util.view.activityBinding import eu.kanade.tachiyomi.util.view.scrollViewWith @@ -33,9 +34,10 @@ import uy.kohesive.injekt.injectLazy */ open class GlobalSearchController( protected val initialQuery: String? = null, - protected val extensionFilter: String? = null + val extensionFilter: String? = null ) : NucleusController(), FloatingSearchInterface, + GlobalSearchAdapter.OnTitleClickListener, GlobalSearchCardAdapter.OnMangaClickListener { /** @@ -82,6 +84,11 @@ open class GlobalSearchController( return GlobalSearchPresenter(initialQuery, extensionFilter) } + override fun onTitleClick(source: CatalogueSource) { + preferences.lastUsedCatalogueSource().set(source.id) + router.pushController(BrowseSourceController(source, presenter.query).withFadeTransaction()) + } + /** * Called when manga in global search is clicked, opens manga. * @@ -180,6 +187,9 @@ open class GlobalSearchController( customTitle = view.context?.getString(R.string.loading) setTitle() } + binding.recycler.post { + binding.recycler.scrollToPosition(0) + } } override fun onDestroyView(view: View) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/source/global_search/GlobalSearchHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/source/global_search/GlobalSearchHolder.kt index 13070ecc0e..112820dd4c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/source/global_search/GlobalSearchHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/source/global_search/GlobalSearchHolder.kt @@ -1,9 +1,13 @@ package eu.kanade.tachiyomi.ui.source.global_search import android.view.View +import androidx.core.view.isVisible import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.databinding.SourceGlobalSearchControllerCardBinding +import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder +import eu.kanade.tachiyomi.ui.migration.SearchController +import eu.kanade.tachiyomi.util.system.LocaleHelper import eu.kanade.tachiyomi.util.view.gone import eu.kanade.tachiyomi.util.view.visible @@ -30,6 +34,15 @@ class GlobalSearchHolder(view: View, val adapter: GlobalSearchAdapter) : binding.recycler.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(view.context, androidx.recyclerview.widget.LinearLayoutManager.HORIZONTAL, false) binding.recycler.adapter = mangaAdapter + + binding.titleMoreIcon.isVisible = adapter.controller !is SearchController && adapter.controller.extensionFilter == null + if (binding.titleMoreIcon.isVisible) { + binding.titleWrapper.setOnClickListener { + adapter.getItem(bindingAdapterPosition)?.let { + adapter.titleClickListener.onTitleClick(it.source) + } + } + } } /** @@ -46,6 +59,8 @@ class GlobalSearchHolder(view: View, val adapter: GlobalSearchAdapter) : // Set Title with country code if available. binding.title.text = titlePrefix + source.name + langSuffix + binding.subtitle.isVisible = source !is LocalSource + binding.subtitle.text = LocaleHelper.getDisplayName(source.lang) when { results == null -> { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/source/global_search/GlobalSearchPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/source/global_search/GlobalSearchPresenter.kt index 8bfcdae4ef..fb71a2a0aa 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/source/global_search/GlobalSearchPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/source/global_search/GlobalSearchPresenter.kt @@ -6,7 +6,6 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.extension.ExtensionManager import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.Source @@ -25,6 +24,7 @@ import timber.log.Timber import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy +import java.util.Date /** * Presenter of [GlobalSearchController] @@ -32,7 +32,7 @@ import uy.kohesive.injekt.injectLazy * * @param sourceManager manages the different sources. * @param db manages the database calls. - * @param preferencesHelper manages the preference calls. + * @param preferences manages the preference calls. */ open class GlobalSearchPresenter( private val initialQuery: String? = "", @@ -40,7 +40,7 @@ open class GlobalSearchPresenter( private val sourcesToUse: List? = null, val sourceManager: SourceManager = Injekt.get(), val db: DatabaseHelper = Injekt.get(), - private val preferencesHelper: PreferencesHelper = Injekt.get(), + private val preferences: PreferencesHelper = Injekt.get(), private val coverCache: CoverCache = Injekt.get() ) : BasePresenter() { @@ -60,6 +60,8 @@ open class GlobalSearchPresenter( */ private var fetchSourcesSubscription: Subscription? = null + private var loadTime = hashMapOf() + /** * Subject which fetches image of given manga. */ @@ -104,16 +106,16 @@ open class GlobalSearchPresenter( * @return list containing enabled sources. */ protected open fun getEnabledSources(): List { - val languages = preferencesHelper.enabledLanguages().get() - val hiddenCatalogues = preferencesHelper.hiddenSources().get() - val pinnedCatalogues = preferencesHelper.pinnedCatalogues().getOrDefault() + val languages = preferences.enabledLanguages().get() + val hiddenCatalogues = preferences.hiddenSources().get() + val pinnedCatalogues = preferences.pinnedCatalogues().get() val list = sourceManager.getCatalogueSources() .filter { it.lang in languages } .filterNot { it.id.toString() in hiddenCatalogues } .sortedBy { "(${it.lang}) ${it.name}" } - return if (preferencesHelper.onlySearchPinned().get()) { + return if (preferences.onlySearchPinned().get()) { list.filter { it.id.toString() in pinnedCatalogues } } else { list.sortedBy { it.id.toString() !in pinnedCatalogues } @@ -176,6 +178,8 @@ open class GlobalSearchPresenter( val initialItems = sources.map { createCatalogueSearchItem(it, null) } var items = initialItems + val pinnedSourceIds = preferences.pinnedCatalogues().get() + fetchSourcesSubscription?.unsubscribe() fetchSourcesSubscription = Observable.from(sources).flatMap( { source -> @@ -197,6 +201,9 @@ open class GlobalSearchPresenter( } // Convert to local manga. .doOnNext { fetchImage(it, source) } // Load manga covers. .map { + if (it.isNotEmpty() && !loadTime.containsKey(source.id)) { + loadTime[source.id] = Date().time + } createCatalogueSearchItem( source, it.map { GlobalSearchMangaItem(it) } @@ -204,10 +211,22 @@ open class GlobalSearchPresenter( } }, 5 - ).observeOn(AndroidSchedulers.mainThread()) + ) + .observeOn(AndroidSchedulers.mainThread()) // Update matching source with the obtained results .map { result -> - items.map { item -> if (item.source == result.source) result else item } + items + .map { item -> if (item.source == result.source) result else item } + .sortedWith( + compareBy( + // Bubble up sources that actually have results + { it.results.isNullOrEmpty() }, + // Same as initial sort, i.e. pinned first then alphabetically + { it.source.id.toString() !in pinnedSourceIds }, + { loadTime[it.source.id] ?: 0L }, + { "${it.source.name.toLowerCase()} (${it.source.lang})" } + ) + ) } // Update current state .doOnNext { items = it } diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/view/ControllerExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/view/ControllerExtensions.kt index 0e7c81a9a8..cbfebae19a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/view/ControllerExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/view/ControllerExtensions.kt @@ -42,6 +42,7 @@ import kotlin.random.Random fun Controller.setOnQueryTextChangeListener( searchView: SearchView, onlyOnSubmit: Boolean = false, + hideKbOnSubmit: Boolean = true, f: (text: String?) -> Boolean ) { searchView.setOnQueryTextListener( @@ -57,10 +58,12 @@ fun Controller.setOnQueryTextChangeListener( override fun onQueryTextSubmit(query: String?): Boolean { if (router.backstack.lastOrNull()?.controller() == this@setOnQueryTextChangeListener) { - val imm = - activity?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager - ?: return f(query) - imm.hideSoftInputFromWindow(searchView.windowToken, 0) + if (hideKbOnSubmit) { + val imm = + activity?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager + ?: return f(query) + imm.hideSoftInputFromWindow(searchView.windowToken, 0) + } return f(query) } return true diff --git a/app/src/main/res/layout/source_global_search_controller_card.xml b/app/src/main/res/layout/source_global_search_controller_card.xml index 322723251e..bc8bc6760c 100644 --- a/app/src/main/res/layout/source_global_search_controller_card.xml +++ b/app/src/main/res/layout/source_global_search_controller_card.xml @@ -6,18 +6,56 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> - + android:background="?attr/selectableItemBackground"> + + + + + + +