From 229b949650467485b862c9e5ec6920d3535b378d Mon Sep 17 00:00:00 2001 From: Roger Yang Date: Thu, 26 May 2022 15:19:10 -0400 Subject: [PATCH] Issue #24301: Add Bookmarks to the search engine menu --- .experimenter.yaml | 2 +- .../java/org/mozilla/fenix/components/Core.kt | 9 ++++++- .../fenix/search/SearchDialogController.kt | 4 +++ .../fenix/search/SearchFragmentStore.kt | 21 ++++++++++++++++ .../fenix/search/awesomebar/AwesomeBarView.kt | 1 + .../main/res/drawable/ic_bookmarks_search.xml | 21 ++++++++++++++++ .../search/SearchDialogControllerTest.kt | 25 +++++++++++++++++++ .../fenix/search/SearchFragmentStoreTest.kt | 10 ++++++++ 8 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 app/src/main/res/drawable/ic_bookmarks_search.xml diff --git a/.experimenter.yaml b/.experimenter.yaml index 280988d4f7..e8d0a792f2 100644 --- a/.experimenter.yaml +++ b/.experimenter.yaml @@ -33,8 +33,8 @@ messaging: type: string description: What should be displayed when a control message is selected. enum: - - show-next-message - show-none + - show-next-message styles: type: json description: "A map of styles to configure message appearance.\n" diff --git a/app/src/main/java/org/mozilla/fenix/components/Core.kt b/app/src/main/java/org/mozilla/fenix/components/Core.kt index 6484f9857d..8a0f059ede 100644 --- a/app/src/main/java/org/mozilla/fenix/components/Core.kt +++ b/app/src/main/java/org/mozilla/fenix/components/Core.kt @@ -199,12 +199,18 @@ class Core( val applicationSearchEngines: List by lazyMonitored { listOf( + createApplicationSearchEngine( + id = BOOKMARKS_SEARCH_ENGINE_ID, + name = context.getString(R.string.library_bookmarks), + url = "", + icon = getDrawable(context, R.drawable.ic_bookmarks_search)?.toBitmap()!!, + ), createApplicationSearchEngine( id = HISTORY_SEARCH_ENGINE_ID, name = context.getString(R.string.library_history), url = "", icon = getDrawable(context, R.drawable.ic_history_search)?.toBitmap()!!, - ) + ), ) } @@ -514,6 +520,7 @@ class Core( const val HISTORY_METADATA_MAX_AGE_IN_MS = 14 * 24 * 60 * 60 * 1000 // 14 days private const val CONTILE_MAX_CACHE_AGE = 60L // 60 minutes const val HISTORY_SEARCH_ENGINE_ID = "history_search_engine_id" + const val BOOKMARKS_SEARCH_ENGINE_ID = "bookmarks_search_engine_id" // Maximum number of suggestions returned from the history search engine source. const val METADATA_HISTORY_SUGGESTION_LIMIT = 100 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 0272815990..c49d43c511 100644 --- a/app/src/main/java/org/mozilla/fenix/search/SearchDialogController.kt +++ b/app/src/main/java/org/mozilla/fenix/search/SearchDialogController.kt @@ -201,6 +201,10 @@ class SearchDialogController( searchEngine.type == SearchEngine.Type.APPLICATION && searchEngine.id == Core.HISTORY_SEARCH_ENGINE_ID -> { fragmentStore.dispatch(SearchFragmentAction.SearchHistoryEngineSelected(searchEngine)) } + searchEngine.type == SearchEngine.Type.APPLICATION + && searchEngine.id == Core.BOOKMARKS_SEARCH_ENGINE_ID -> { + fragmentStore.dispatch(SearchFragmentAction.SearchBookmarksEngineSelected(searchEngine)) + } searchEngine == store.state.search.selectedOrDefaultSearchEngine -> { fragmentStore.dispatch(SearchFragmentAction.SearchDefaultEngineSelected(searchEngine, settings)) } diff --git a/app/src/main/java/org/mozilla/fenix/search/SearchFragmentStore.kt b/app/src/main/java/org/mozilla/fenix/search/SearchFragmentStore.kt index 62dc90caf1..007b91e6fa 100644 --- a/app/src/main/java/org/mozilla/fenix/search/SearchFragmentStore.kt +++ b/app/src/main/java/org/mozilla/fenix/search/SearchFragmentStore.kt @@ -56,6 +56,11 @@ sealed class SearchEngineSource { * Search engine for history */ data class History(override val searchEngine: SearchEngine) : SearchEngineSource() + + /** + * Search engine for bookmarks + */ + data class Bookmarks(override val searchEngine: SearchEngine) : SearchEngineSource() } /** @@ -170,6 +175,11 @@ sealed class SearchFragmentAction : Action { */ data class SearchHistoryEngineSelected(val engine: SearchEngine) : SearchFragmentAction() + /** + * Action when bookmarks search engine is selected. + */ + data class SearchBookmarksEngineSelected(val engine: SearchEngine) : SearchFragmentAction() + /** * Action when search engine picker is selected. */ @@ -250,6 +260,17 @@ private fun searchStateReducer(state: SearchFragmentState, action: SearchFragmen showSyncedTabsSuggestions = false, showSessionSuggestions = false, ) + is SearchFragmentAction.SearchBookmarksEngineSelected -> + state.copy( + searchEngineSource = SearchEngineSource.Bookmarks(action.engine), + showSearchSuggestions = false, + showSearchShortcuts = false, + showClipboardSuggestions = false, + showHistorySuggestions = false, + showBookmarkSuggestions = true, + showSyncedTabsSuggestions = false, + showSessionSuggestions = false, + ) is SearchFragmentAction.ShowSearchShortcutEnginePicker -> state.copy(showSearchShortcuts = action.show && state.areShortcutsAvailable) is SearchFragmentAction.UpdateQuery -> 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 2c116f4c53..8ccf722520 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 @@ -284,6 +284,7 @@ class AwesomeBarView( state.searchEngineSource.searchEngine ) is SearchEngineSource.History -> emptyList() + is SearchEngineSource.Bookmarks -> emptyList() is SearchEngineSource.None -> emptyList() } } diff --git a/app/src/main/res/drawable/ic_bookmarks_search.xml b/app/src/main/res/drawable/ic_bookmarks_search.xml new file mode 100644 index 0000000000..33af69fd59 --- /dev/null +++ b/app/src/main/res/drawable/ic_bookmarks_search.xml @@ -0,0 +1,21 @@ + + + + + + + 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 f5243d6411..dd2c86374a 100644 --- a/app/src/test/java/org/mozilla/fenix/search/SearchDialogControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/search/SearchDialogControllerTest.kt @@ -382,6 +382,31 @@ class SearchDialogControllerTest { assertEquals("application", eventExtra["engine"]) } + @Test + fun `WHEN bookmarks search engine is selected THEN dispatch correct action`() { + val searchEngine: SearchEngine = mockk(relaxed = true) + every { searchEngine.type } returns SearchEngine.Type.APPLICATION + every { searchEngine.id } returns Core.BOOKMARKS_SEARCH_ENGINE_ID + + var focusToolbarInvoked = false + createController( + focusToolbar = { + focusToolbarInvoked = true + } + ).handleSearchShortcutEngineSelected(searchEngine) + + assertTrue(focusToolbarInvoked) + verify { store.dispatch(SearchFragmentAction.SearchBookmarksEngineSelected(searchEngine)) } + + assertTrue(SearchShortcuts.selected.testHasValue()) + val recordedEvents = SearchShortcuts.selected.testGetValue() + assertEquals(1, recordedEvents.size) + val eventExtra = recordedEvents.single().extra + assertNotNull(eventExtra) + assertTrue(eventExtra!!.containsKey("engine")) + assertEquals("application", eventExtra["engine"]) + } + @Test fun handleClickSearchEngineSettings() { val directions: NavDirections = actionGlobalSearchEngineFragment() diff --git a/app/src/test/java/org/mozilla/fenix/search/SearchFragmentStoreTest.kt b/app/src/test/java/org/mozilla/fenix/search/SearchFragmentStoreTest.kt index 4d6ad32cb4..08245b8b26 100644 --- a/app/src/test/java/org/mozilla/fenix/search/SearchFragmentStoreTest.kt +++ b/app/src/test/java/org/mozilla/fenix/search/SearchFragmentStoreTest.kt @@ -175,6 +175,16 @@ class SearchFragmentStoreTest { assertEquals(SearchEngineSource.History(searchEngine), store.state.searchEngineSource) } + @Test + fun `WHEN bookmarks engine selected action dispatched THEN update search engine source`() = runTest { + val initialState = emptyDefaultState() + val store = SearchFragmentStore(initialState) + + store.dispatch(SearchFragmentAction.SearchBookmarksEngineSelected(searchEngine)).join() + assertNotSame(initialState, store.state) + assertEquals(SearchEngineSource.Bookmarks(searchEngine), store.state.searchEngineSource) + } + @Test fun showSearchShortcutEnginePicker() = runTest { val initialState = emptyDefaultState()