1
0
Fork 0

For #9425 - Handle undo for custom search engines

On undo, get the template that the user entered for that engine and then
re-add it to the `CustomSearchEngineStore`
master
Mihai Branescu 2020-04-16 18:18:35 +03:00
parent c5034fa770
commit 46c1c130da
3 changed files with 63 additions and 24 deletions

View File

@ -135,24 +135,28 @@ open class FenixSearchEngineProvider(
return installedSearchEngines(context) return installedSearchEngines(context)
} }
fun installSearchEngine(context: Context, searchEngine: SearchEngine) = runBlocking { fun installSearchEngine(context: Context, searchEngine: SearchEngine, isCustom: Boolean = false) = runBlocking {
val installedIdentifiers = installedSearchEngineIdentifiers(context).toMutableSet() if (isCustom) {
installedIdentifiers.add(searchEngine.identifier) val searchUrl = searchEngine.getSearchTemplate()
prefs(context).edit().putStringSet(localeAwareInstalledEnginesKey(), installedIdentifiers).apply() CustomSearchEngineStore.addSearchEngine(context, searchEngine.name, searchUrl)
reload()
} else {
val installedIdentifiers = installedSearchEngineIdentifiers(context).toMutableSet()
installedIdentifiers.add(searchEngine.identifier)
prefs(context).edit()
.putStringSet(localeAwareInstalledEnginesKey(), installedIdentifiers).apply()
}
} }
fun uninstallSearchEngine(context: Context, searchEngine: SearchEngine) = runBlocking { fun uninstallSearchEngine(context: Context, searchEngine: SearchEngine, isCustom: Boolean = false) = runBlocking {
val isCustom = CustomSearchEngineStore.isCustomSearchEngine(context, searchEngine.identifier)
if (isCustom) { if (isCustom) {
CustomSearchEngineStore.removeSearchEngine(context, searchEngine.identifier) CustomSearchEngineStore.removeSearchEngine(context, searchEngine.identifier)
reload()
} else { } else {
val installedIdentifiers = installedSearchEngineIdentifiers(context).toMutableSet() val installedIdentifiers = installedSearchEngineIdentifiers(context).toMutableSet()
installedIdentifiers.remove(searchEngine.identifier) installedIdentifiers.remove(searchEngine.identifier)
prefs(context).edit().putStringSet(localeAwareInstalledEnginesKey(), installedIdentifiers).apply() prefs(context).edit().putStringSet(localeAwareInstalledEnginesKey(), installedIdentifiers).apply()
} }
reload()
} }
fun reload() { fun reload() {

View File

@ -18,7 +18,10 @@ import androidx.core.view.isVisible
import androidx.navigation.Navigation import androidx.navigation.Navigation
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceViewHolder import androidx.preference.PreferenceViewHolder
import kotlinx.android.synthetic.main.search_engine_radio_button.view.* import kotlinx.android.synthetic.main.search_engine_radio_button.view.engine_icon
import kotlinx.android.synthetic.main.search_engine_radio_button.view.engine_text
import kotlinx.android.synthetic.main.search_engine_radio_button.view.overflow_menu
import kotlinx.android.synthetic.main.search_engine_radio_button.view.radio_button
import kotlinx.coroutines.MainScope import kotlinx.coroutines.MainScope
import mozilla.components.browser.search.SearchEngine import mozilla.components.browser.search.SearchEngine
import mozilla.components.browser.search.provider.SearchEngineList import mozilla.components.browser.search.provider.SearchEngineList
@ -167,7 +170,7 @@ abstract class SearchEngineListPreference @JvmOverloads constructor(
val initialEngineList = searchEngineList.copy() val initialEngineList = searchEngineList.copy()
val initialDefaultEngine = searchEngineList.default val initialDefaultEngine = searchEngineList.default
context.components.search.provider.uninstallSearchEngine(context, engine) context.components.search.provider.uninstallSearchEngine(context, engine, isCustomSearchEngine)
MainScope().allowUndo( MainScope().allowUndo(
view = context.getRootView()!!, view = context.getRootView()!!,
@ -175,7 +178,7 @@ abstract class SearchEngineListPreference @JvmOverloads constructor(
.getString(R.string.search_delete_search_engine_success_message, engine.name), .getString(R.string.search_delete_search_engine_success_message, engine.name),
undoActionTitle = context.getString(R.string.snackbar_deleted_undo), undoActionTitle = context.getString(R.string.snackbar_deleted_undo),
onCancel = { onCancel = {
context.components.search.provider.installSearchEngine(context, engine) context.components.search.provider.installSearchEngine(context, engine, isCustomSearchEngine)
searchEngineList = initialEngineList.copy( searchEngineList = initialEngineList.copy(
default = initialDefaultEngine default = initialDefaultEngine

View File

@ -3,6 +3,14 @@ package org.mozilla.fenix.components.searchengine
import android.content.Context import android.content.Context
import io.mockk.every import io.mockk.every
import io.mockk.mockk import io.mockk.mockk
import android.graphics.Bitmap
import io.mockk.Runs
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.every
import io.mockk.just
import io.mockk.mockk
import io.mockk.mockkObject
import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Deferred import kotlinx.coroutines.Deferred
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
@ -27,6 +35,12 @@ class FenixSearchEngineProviderTest {
@Before @Before
fun before() { fun before() {
fenixSearchEngineProvider = FakeFenixSearchEngineProvider(testContext) fenixSearchEngineProvider = FakeFenixSearchEngineProvider(testContext)
mockkObject(CustomSearchEngineStore)
fenixSearchEngineProvider.let {
every { CustomSearchEngineStore.loadCustomSearchEngines(testContext) } returns listOf(
(it as FakeFenixSearchEngineProvider).mockSearchEngine("my custom site", "my custom site")
)
}
} }
/* /*
@ -37,6 +51,28 @@ class FenixSearchEngineProviderTest {
- the above after adding/removing - the above after adding/removing
*/ */
@Suppress("DEPRECATION")
@Test
fun `add custom engine`() = runBlockingTest {
val engineName = "Ecosia"
val engineQuery = "www.ecosia.com/%s"
val searchEngine: SearchEngine = mockk(relaxed = true)
every { searchEngine.getSearchTemplate() } returns engineQuery
every { searchEngine.name } returns engineName
mockkObject(CustomSearchEngineStore)
coEvery {
CustomSearchEngineStore.addSearchEngine(
testContext,
engineName,
engineQuery
)
} just Runs
fenixSearchEngineProvider.installSearchEngine(testContext, searchEngine, true)
coVerify { CustomSearchEngineStore.addSearchEngine(testContext, engineName, engineQuery) }
}
@Test @Test
fun `GIVEN sharedprefs does not contain installed engines WHEN installedSearchEngineIdentifiers THEN defaultEngines + customEngines ids are returned`() = runBlockingTest { fun `GIVEN sharedprefs does not contain installed engines WHEN installedSearchEngineIdentifiers THEN defaultEngines + customEngines ids are returned`() = runBlockingTest {
val expectedDefaults = fenixSearchEngineProvider.baseSearchEngines.toIdSet() val expectedDefaults = fenixSearchEngineProvider.baseSearchEngines.toIdSet()
@ -96,21 +132,17 @@ class FakeFenixSearchEngineProvider(context: Context) : FenixSearchEngineProvide
) )
) )
override var customSearchEngines: Deferred<SearchEngineList> override var customSearchEngines: Deferred<SearchEngineList> = CompletableDeferred(
get() { SearchEngineList(
return CompletableDeferred( listOf(
SearchEngineList( mockSearchEngine("my custom site", "my custom site")
listOf( ), default = null
mockSearchEngine("my custom site", "my custom site") )
), default = null )
)
)
}
set(_) = throw NotImplementedError("Setting not currently supported on this fake")
override fun updateBaseSearchEngines() { } override fun updateBaseSearchEngines() { }
private fun mockSearchEngine( fun mockSearchEngine(
id: String, id: String,
n: String = id n: String = id
): SearchEngine { ): SearchEngine {