From 507b4aaf8b838a28df85ea6566302291c7c456d4 Mon Sep 17 00:00:00 2001 From: mcarare Date: Fri, 5 Feb 2021 16:26:10 +0200 Subject: [PATCH] [fenix] For https://github.com/mozilla-mobile/fenix/issues/16044: Suggest search engines based on typed text. --- .../fenix/search/SearchDialogController.kt | 9 ++++++++- .../fenix/search/SearchDialogFragment.kt | 7 ++++++- .../fenix/search/SearchDialogInteractor.kt | 4 ++++ .../search/awesomebar/AwesomeBarInteractor.kt | 5 +++++ .../fenix/search/awesomebar/AwesomeBarView.kt | 17 +++++++++++++++++ app/src/main/res/drawable/ic_search_with.xml | 16 ++++++++++++++++ app/src/main/res/values/strings.xml | 4 ++++ .../fenix/search/SearchDialogControllerTest.kt | 4 +++- 8 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 app/src/main/res/drawable/ic_search_with.xml diff --git a/app/src/main/java/org/mozilla/fenix/search/SearchDialogController.kt b/app/src/main/java/org/mozilla/fenix/search/SearchDialogController.kt index 6e87cf2cc4..4a4fe9c4f8 100644 --- a/app/src/main/java/org/mozilla/fenix/search/SearchDialogController.kt +++ b/app/src/main/java/org/mozilla/fenix/search/SearchDialogController.kt @@ -42,6 +42,7 @@ interface SearchController { fun handleExistingSessionSelected(tabId: String) fun handleSearchShortcutsButtonClicked() fun handleCameraPermissionsNeeded() + fun handleSearchEngineSuggestionClicked(searchEngine: SearchEngine) } @Suppress("TooManyFunctions", "LongParameterList") @@ -55,7 +56,8 @@ class SearchDialogController( private val metrics: MetricController, private val dismissDialog: () -> Unit, private val clearToolbarFocus: () -> Unit, - private val focusToolbar: () -> Unit + private val focusToolbar: () -> Unit, + private val clearToolbar: () -> Unit ) : SearchController { override fun handleUrlCommitted(url: String) { @@ -221,6 +223,11 @@ class SearchDialogController( dialog.show() } + override fun handleSearchEngineSuggestionClicked(searchEngine: SearchEngine) { + clearToolbar() + handleSearchShortcutEngineSelected(searchEngine) + } + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) fun buildDialog(): AlertDialog.Builder { return AlertDialog.Builder(activity).apply { diff --git a/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt b/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt index f1b5adcdba..34d2f3ccfd 100644 --- a/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt @@ -157,7 +157,12 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { toolbarView.view.hideKeyboard() toolbarView.view.clearFocus() }, - focusToolbar = { toolbarView.view.edit.focus() } + focusToolbar = { toolbarView.view.edit.focus() }, + clearToolbar = { + toolbarView.view + .findViewById(R.id.mozac_browser_toolbar_edit_url_view) + ?.setText("") + } ) ) diff --git a/app/src/main/java/org/mozilla/fenix/search/SearchDialogInteractor.kt b/app/src/main/java/org/mozilla/fenix/search/SearchDialogInteractor.kt index 9f82379d93..93d1068ba1 100644 --- a/app/src/main/java/org/mozilla/fenix/search/SearchDialogInteractor.kt +++ b/app/src/main/java/org/mozilla/fenix/search/SearchDialogInteractor.kt @@ -37,6 +37,10 @@ class SearchDialogInteractor( searchController.handleSearchTermsTapped(searchTerms) } + override fun onSearchEngineSuggestionSelected(searchEngine: SearchEngine) { + searchController.handleSearchEngineSuggestionClicked(searchEngine) + } + override fun onSearchShortcutEngineSelected(searchEngine: SearchEngine) { searchController.handleSearchShortcutEngineSelected(searchEngine) } diff --git a/app/src/main/java/org/mozilla/fenix/search/awesomebar/AwesomeBarInteractor.kt b/app/src/main/java/org/mozilla/fenix/search/awesomebar/AwesomeBarInteractor.kt index bb0c62a62a..75738eb79e 100644 --- a/app/src/main/java/org/mozilla/fenix/search/awesomebar/AwesomeBarInteractor.kt +++ b/app/src/main/java/org/mozilla/fenix/search/awesomebar/AwesomeBarInteractor.kt @@ -44,4 +44,9 @@ interface AwesomeBarInteractor { * Called whenever the Shortcuts button is clicked */ fun onSearchShortcutsButtonClicked() + + /** + * Called whenever search engine suggestion is tapped + */ + fun onSearchEngineSuggestionSelected(searchEngine: SearchEngine) } diff --git a/app/src/main/java/org/mozilla/fenix/search/awesomebar/AwesomeBarView.kt b/app/src/main/java/org/mozilla/fenix/search/awesomebar/AwesomeBarView.kt index cd9fa8c8b0..da4cc0612a 100644 --- a/app/src/main/java/org/mozilla/fenix/search/awesomebar/AwesomeBarView.kt +++ b/app/src/main/java/org/mozilla/fenix/search/awesomebar/AwesomeBarView.kt @@ -11,11 +11,13 @@ import androidx.core.graphics.drawable.toBitmap import mozilla.components.browser.awesomebar.BrowserAwesomeBar import mozilla.components.browser.search.DefaultSearchEngineProvider import mozilla.components.browser.state.search.SearchEngine +import mozilla.components.browser.state.state.searchEngines import mozilla.components.concept.awesomebar.AwesomeBar import mozilla.components.concept.engine.EngineSession import mozilla.components.feature.awesomebar.provider.BookmarksStorageSuggestionProvider import mozilla.components.feature.awesomebar.provider.HistoryStorageSuggestionProvider import mozilla.components.feature.awesomebar.provider.SearchActionProvider +import mozilla.components.feature.awesomebar.provider.SearchEngineSuggestionProvider import mozilla.components.feature.awesomebar.provider.SearchSuggestionProvider import mozilla.components.feature.awesomebar.provider.SessionSuggestionProvider import mozilla.components.feature.search.SearchUseCases @@ -51,6 +53,7 @@ class AwesomeBarView( private val syncedTabsStorageSuggestionProvider: SyncedTabsStorageSuggestionProvider private val defaultSearchSuggestionProvider: SearchSuggestionProvider private val defaultSearchActionProvider: SearchActionProvider + private val searchEngineSuggestionProvider: SearchEngineSuggestionProvider private val searchSuggestionProviderMap: MutableMap> private var providersInUse = mutableSetOf() @@ -143,6 +146,8 @@ class AwesomeBarView( colorFilter = createBlendModeColorFilterCompat(primaryTextColor, SRC_IN) }.toBitmap() + val searchWithBitmap = getDrawable(activity, R.drawable.ic_search_with)?.toBitmap() + defaultSearchSuggestionProvider = SearchSuggestionProvider( context = activity, @@ -173,6 +178,16 @@ class AwesomeBarView( selectShortcutEngineSettings = interactor::onClickSearchEngineSettings ) + searchEngineSuggestionProvider = + SearchEngineSuggestionProvider( + context = activity, + searchEnginesList = components.core.store.state.search.searchEngines, + selectShortcutEngine = interactor::onSearchEngineSuggestionSelected, + title = R.string.search_engine_suggestions_title, + description = activity.getString(R.string.search_engine_suggestions_description), + searchIcon = searchWithBitmap + ) + searchSuggestionProviderMap = HashMap() } @@ -242,6 +257,8 @@ class AwesomeBarView( providersToAdd.add(sessionProvider) } + providersToAdd.add(searchEngineSuggestionProvider) + return providersToAdd } diff --git a/app/src/main/res/drawable/ic_search_with.xml b/app/src/main/res/drawable/ic_search_with.xml new file mode 100644 index 0000000000..8ffacd9b66 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_with.xml @@ -0,0 +1,16 @@ + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 602b07df6b..19c22e14b6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -212,6 +212,10 @@ %s will share everything you type in the address bar with your default search engine. Learn more + + Search %s + + Search directly from the address bar diff --git a/app/src/test/java/org/mozilla/fenix/search/SearchDialogControllerTest.kt b/app/src/test/java/org/mozilla/fenix/search/SearchDialogControllerTest.kt index f8b79a0520..96218a32db 100644 --- a/app/src/test/java/org/mozilla/fenix/search/SearchDialogControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/search/SearchDialogControllerTest.kt @@ -50,6 +50,7 @@ class SearchDialogControllerTest { @MockK private lateinit var sessionManager: SessionManager @MockK(relaxed = true) private lateinit var clearToolbarFocus: () -> Unit @MockK(relaxed = true) private lateinit var focusToolbar: () -> Unit + @MockK(relaxed = true) private lateinit var clearToolbar: () -> Unit @MockK(relaxed = true) private lateinit var dismissDialog: () -> Unit private lateinit var controller: SearchDialogController @@ -81,7 +82,8 @@ class SearchDialogControllerTest { metrics = metrics, dismissDialog = dismissDialog, clearToolbarFocus = clearToolbarFocus, - focusToolbar = focusToolbar + focusToolbar = focusToolbar, + clearToolbar = clearToolbar ) }