You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
iceraven-browser/app/src/main/java/org/mozilla/fenix/settings/search/EditCustomSearchEngineFragm...

174 lines
6.2 KiB
Kotlin

/* 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.settings.search
import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import kotlinx.android.synthetic.main.custom_search_engine.custom_search_engine_name_field
import kotlinx.android.synthetic.main.custom_search_engine.custom_search_engine_search_string_field
import kotlinx.android.synthetic.main.custom_search_engine.custom_search_engines_learn_more
import kotlinx.android.synthetic.main.custom_search_engine.edit_engine_name
import kotlinx.android.synthetic.main.custom_search_engine.edit_search_string
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import mozilla.components.browser.state.search.SearchEngine
import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.components.FenixSnackbar
import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.ext.showToolbar
import org.mozilla.fenix.settings.SupportUtils
/**
* Fragment to enter a custom search engine name and URL template.
*/
class EditCustomSearchEngineFragment : Fragment(R.layout.fragment_add_search_engine) {
private val args by navArgs<EditCustomSearchEngineFragmentArgs>()
private lateinit var searchEngine: SearchEngine
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
searchEngine = requireNotNull(
requireComponents.core.store.state.search.customSearchEngines.find { engine ->
engine.id == args.searchEngineIdentifier
}
)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val url = searchEngine.resultUrls[0]
edit_engine_name.setText(searchEngine.name)
edit_search_string.setText(url.toEditableUrl())
custom_search_engines_learn_more.setOnClickListener {
(activity as HomeActivity).openToBrowserAndLoad(
searchTermOrURL = SupportUtils.getSumoURLForTopic(
requireContext(),
SupportUtils.SumoTopic.CUSTOM_SEARCH_ENGINES
),
newTab = true,
from = BrowserDirection.FromEditCustomSearchEngineFragment
)
}
}
override fun onResume() {
super.onResume()
showToolbar(getString(R.string.search_engine_edit_custom_search_engine_title))
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.edit_custom_searchengine_menu, menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.save_button -> {
saveCustomEngine()
true
}
else -> super.onOptionsItemSelected(item)
}
}
@Suppress("LongMethod")
private fun saveCustomEngine() {
custom_search_engine_name_field.error = ""
custom_search_engine_search_string_field.error = ""
val name = edit_engine_name.text?.toString()?.trim() ?: ""
val searchString = edit_search_string.text?.toString() ?: ""
if (checkForErrors(name, searchString)) {
return
}
lifecycleScope.launch(Main) {
val result = withContext(IO) {
SearchStringValidator.isSearchStringValid(
requireComponents.core.client,
searchString
)
}
when (result) {
SearchStringValidator.Result.CannotReach -> {
custom_search_engine_search_string_field.error = resources
.getString(R.string.search_add_custom_engine_error_cannot_reach, name)
}
SearchStringValidator.Result.Success -> {
val update = searchEngine.copy(
name = name,
resultUrls = listOf(searchString.toSearchUrl())
)
requireComponents.useCases.searchUseCases.addSearchEngine(update)
val successMessage = resources
.getString(R.string.search_edit_custom_engine_success_message, name)
view?.also {
FenixSnackbar.make(
view = it,
duration = FenixSnackbar.LENGTH_SHORT,
isDisplayedWithBrowserToolbar = false
)
.setText(successMessage)
.show()
}
findNavController().popBackStack()
}
}
}
}
private fun checkForErrors(name: String, searchString: String): Boolean {
return when {
name.isEmpty() -> {
custom_search_engine_name_field.error = resources
.getString(R.string.search_add_custom_engine_error_empty_name)
true
}
searchString.isEmpty() -> {
custom_search_engine_search_string_field.error =
resources.getString(R.string.search_add_custom_engine_error_empty_search_string)
true
}
!searchString.contains("%s") -> {
custom_search_engine_search_string_field.error =
resources.getString(R.string.search_add_custom_engine_error_missing_template)
true
}
else -> false
}
}
}
private fun String.toEditableUrl(): String {
return replace("{searchTerms}", "%s")
}
private fun String.toSearchUrl(): String {
return replace("%s", "{searchTerms}")
}