1
0
Fork 0

Issue #7877: Add SearchActionProvider for faster responses that mirror entered text.

master
Sebastian Kaspari 2020-07-21 12:21:02 +02:00 committed by Emily Kager
parent c08d375c18
commit 96121a79fa
2 changed files with 106 additions and 72 deletions

View File

@ -0,0 +1,53 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.search.awesomebar
import mozilla.components.browser.search.SearchEngine
import mozilla.components.browser.session.Session
/**
* Interface for the AwesomeBarView Interactor. This interface is implemented by objects that want
* to respond to user interaction on the AwesomebarView
*/
interface AwesomeBarInteractor {
/**
* Called whenever a suggestion containing a URL is tapped
* @param url the url the suggestion was providing
*/
fun onUrlTapped(url: String)
/**
* Called whenever a search engine suggestion is tapped
* @param searchTerms the query contained by the search suggestion
*/
fun onSearchTermsTapped(searchTerms: String)
/**
* Called whenever a search engine shortcut is tapped
* @param searchEngine the searchEngine that was selected
*/
fun onSearchShortcutEngineSelected(searchEngine: SearchEngine)
/**
* Called whenever the "Search Engine Settings" item is tapped
*/
fun onClickSearchEngineSettings()
/**
* Called whenever an existing session is selected from the sessionSuggestionProvider
*/
fun onExistingSessionSelected(session: Session)
/**
* Called whenever an existing session is selected from the sessionSuggestionProvider
*/
fun onExistingSessionSelected(tabId: String)
/**
* Called whenever the Shortcuts button is clicked
*/
fun onSearchShortcutsButtonClicked()
}

View File

@ -16,6 +16,7 @@ import mozilla.components.concept.awesomebar.AwesomeBar
import mozilla.components.concept.engine.EngineSession import mozilla.components.concept.engine.EngineSession
import mozilla.components.feature.awesomebar.provider.BookmarksStorageSuggestionProvider import mozilla.components.feature.awesomebar.provider.BookmarksStorageSuggestionProvider
import mozilla.components.feature.awesomebar.provider.HistoryStorageSuggestionProvider import mozilla.components.feature.awesomebar.provider.HistoryStorageSuggestionProvider
import mozilla.components.feature.awesomebar.provider.SearchActionProvider
import mozilla.components.feature.awesomebar.provider.SearchSuggestionProvider import mozilla.components.feature.awesomebar.provider.SearchSuggestionProvider
import mozilla.components.feature.awesomebar.provider.SessionSuggestionProvider import mozilla.components.feature.awesomebar.provider.SessionSuggestionProvider
import mozilla.components.feature.search.SearchUseCases import mozilla.components.feature.search.SearchUseCases
@ -29,51 +30,6 @@ import org.mozilla.fenix.ext.components
import org.mozilla.fenix.search.SearchEngineSource import org.mozilla.fenix.search.SearchEngineSource
import org.mozilla.fenix.search.SearchFragmentState import org.mozilla.fenix.search.SearchFragmentState
/**
* Interface for the AwesomeBarView Interactor. This interface is implemented by objects that want
* to respond to user interaction on the AwesomebarView
*/
interface AwesomeBarInteractor {
/**
* Called whenever a suggestion containing a URL is tapped
* @param url the url the suggestion was providing
*/
fun onUrlTapped(url: String)
/**
* Called whenever a search engine suggestion is tapped
* @param searchTerms the query contained by the search suggestion
*/
fun onSearchTermsTapped(searchTerms: String)
/**
* Called whenever a search engine shortcut is tapped
* @param searchEngine the searchEngine that was selected
*/
fun onSearchShortcutEngineSelected(searchEngine: SearchEngine)
/**
* Called whenever the "Search Engine Settings" item is tapped
*/
fun onClickSearchEngineSettings()
/**
* Called whenever an existing session is selected from the sessionSuggestionProvider
*/
fun onExistingSessionSelected(session: Session)
/**
* Called whenever an existing session is selected from the sessionSuggestionProvider
*/
fun onExistingSessionSelected(tabId: String)
/**
* Called whenever the Shortcuts button is clicked
*/
fun onSearchShortcutsButtonClicked()
}
/** /**
* View that contains and configures the BrowserAwesomeBar * View that contains and configures the BrowserAwesomeBar
*/ */
@ -88,7 +44,8 @@ class AwesomeBarView(
private val shortcutsEnginePickerProvider: ShortcutsSuggestionProvider private val shortcutsEnginePickerProvider: ShortcutsSuggestionProvider
private val bookmarksStorageSuggestionProvider: BookmarksStorageSuggestionProvider private val bookmarksStorageSuggestionProvider: BookmarksStorageSuggestionProvider
private val defaultSearchSuggestionProvider: SearchSuggestionProvider private val defaultSearchSuggestionProvider: SearchSuggestionProvider
private val searchSuggestionProviderMap: MutableMap<SearchEngine, SearchSuggestionProvider> private val defaultSearchActionProvider: SearchActionProvider
private val searchSuggestionProviderMap: MutableMap<SearchEngine, List<AwesomeBar.SuggestionProvider>>
private var providersInUse = mutableSetOf<AwesomeBar.SuggestionProvider>() private var providersInUse = mutableSetOf<AwesomeBar.SuggestionProvider>()
private val loadUrlUseCase = object : SessionUseCases.LoadUrlUseCase { private val loadUrlUseCase = object : SessionUseCases.LoadUrlUseCase {
@ -141,7 +98,8 @@ class AwesomeBarView(
val draw = getDrawable(context, R.drawable.ic_link)!! val draw = getDrawable(context, R.drawable.ic_link)!!
draw.colorFilter = createBlendModeColorFilterCompat(primaryTextColor, SRC_IN) draw.colorFilter = createBlendModeColorFilterCompat(primaryTextColor, SRC_IN)
val engineForSpeculativeConnects = if (!isBrowsingModePrivate()) components.core.engine else null val engineForSpeculativeConnects =
if (!isBrowsingModePrivate()) components.core.engine else null
sessionProvider = sessionProvider =
SessionSuggestionProvider( SessionSuggestionProvider(
context.resources, context.resources,
@ -167,8 +125,9 @@ class AwesomeBarView(
engineForSpeculativeConnects engineForSpeculativeConnects
) )
val searchDrawable = getDrawable(context, R.drawable.ic_search)!! val searchBitmap = getDrawable(context, R.drawable.ic_search)!!.apply {
searchDrawable.colorFilter = createBlendModeColorFilterCompat(primaryTextColor, SRC_IN) colorFilter = createBlendModeColorFilterCompat(primaryTextColor, SRC_IN)
}.toBitmap()
defaultSearchSuggestionProvider = defaultSearchSuggestionProvider =
SearchSuggestionProvider( SearchSuggestionProvider(
@ -178,9 +137,20 @@ class AwesomeBarView(
fetchClient = components.core.client, fetchClient = components.core.client,
mode = SearchSuggestionProvider.Mode.MULTIPLE_SUGGESTIONS, mode = SearchSuggestionProvider.Mode.MULTIPLE_SUGGESTIONS,
limit = 3, limit = 3,
icon = searchDrawable.toBitmap(), icon = searchBitmap,
showDescription = false, showDescription = false,
engine = engineForSpeculativeConnects engine = engineForSpeculativeConnects,
filterExactMatch = true
)
defaultSearchActionProvider =
SearchActionProvider(
searchEngineGetter = suspend {
components.search.searchEngineManager.getDefaultSearchEngineAsync(context)
},
searchUseCase = searchUseCase,
icon = searchBitmap,
showDescription = false
) )
shortcutsEnginePickerProvider = shortcutsEnginePickerProvider =
@ -248,9 +218,7 @@ class AwesomeBarView(
} }
if (state.showSearchSuggestions) { if (state.showSearchSuggestions) {
getSelectedSearchSuggestionProvider(state)?.let { providersToAdd.addAll(getSelectedSearchSuggestionProvider(state))
providersToAdd.add(it)
}
} }
if (!isBrowsingModePrivate()) { if (!isBrowsingModePrivate()) {
@ -274,9 +242,7 @@ class AwesomeBarView(
} }
if (!state.showSearchSuggestions) { if (!state.showSearchSuggestions) {
getSelectedSearchSuggestionProvider(state)?.let { providersToRemove.addAll(getSelectedSearchSuggestionProvider(state))
providersToRemove.add(it)
}
} }
if (isBrowsingModePrivate()) { if (isBrowsingModePrivate()) {
@ -291,9 +257,12 @@ class AwesomeBarView(
?: false ?: false
} }
private fun getSelectedSearchSuggestionProvider(state: SearchFragmentState): SearchSuggestionProvider? { private fun getSelectedSearchSuggestionProvider(state: SearchFragmentState): List<AwesomeBar.SuggestionProvider> {
return when (state.searchEngineSource) { return when (state.searchEngineSource) {
is SearchEngineSource.Default -> defaultSearchSuggestionProvider is SearchEngineSource.Default -> listOf(
defaultSearchActionProvider,
defaultSearchSuggestionProvider
)
is SearchEngineSource.Shortcut -> getSuggestionProviderForEngine( is SearchEngineSource.Shortcut -> getSuggestionProviderForEngine(
state.searchEngineSource.searchEngine state.searchEngineSource.searchEngine
) )
@ -307,26 +276,38 @@ class AwesomeBarView(
view.addProviders(shortcutsEnginePickerProvider) view.addProviders(shortcutsEnginePickerProvider)
} }
private fun getSuggestionProviderForEngine(engine: SearchEngine): SearchSuggestionProvider? { private fun getSuggestionProviderForEngine(engine: SearchEngine): List<AwesomeBar.SuggestionProvider> {
return searchSuggestionProviderMap.getOrPut(engine) { return searchSuggestionProviderMap.getOrPut(engine) {
val context = container.context val context = container.context
val components = context.components val components = context.components
val primaryTextColor = context.getColorFromAttr(R.attr.primaryText) val primaryTextColor = context.getColorFromAttr(R.attr.primaryText)
val draw = getDrawable(context, R.drawable.ic_search) val searchBitmap = getDrawable(context, R.drawable.ic_search)?.apply {
draw?.colorFilter = createBlendModeColorFilterCompat(primaryTextColor, SRC_IN) colorFilter = createBlendModeColorFilterCompat(primaryTextColor, SRC_IN)
}?.toBitmap()
val engineForSpeculativeConnects = if (!isBrowsingModePrivate()) components.core.engine else null val engineForSpeculativeConnects =
if (!isBrowsingModePrivate()) components.core.engine else null
SearchSuggestionProvider( val searchEngine =
components.search.provider.installedSearchEngines(context).list.find { it.name == engine.name } components.search.provider.installedSearchEngines(context).list.find { it.name == engine.name }
?: components.search.provider.getDefaultEngine(context), ?: components.search.provider.getDefaultEngine(context)
shortcutSearchUseCase,
components.core.client, listOf(
limit = 3, SearchActionProvider(
mode = SearchSuggestionProvider.Mode.MULTIPLE_SUGGESTIONS, searchEngineGetter = suspend { searchEngine },
icon = draw?.toBitmap(), searchUseCase = shortcutSearchUseCase,
engine = engineForSpeculativeConnects icon = searchBitmap
),
SearchSuggestionProvider(
searchEngine,
shortcutSearchUseCase,
components.core.client,
limit = 3,
mode = SearchSuggestionProvider.Mode.MULTIPLE_SUGGESTIONS,
icon = searchBitmap,
engine = engineForSpeculativeConnects,
filterExactMatch = true
)
) )
} }
} }