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
parent
c5034fa770
commit
46c1c130da
|
@ -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() {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue