Bug 1807573 - Add field to set custom search engine suggestion URL

fenix/117.0
Andy Hall 11 months ago committed by mergify[bot]
parent a19d1ce4a5
commit 054f4cf6ce

@ -76,11 +76,13 @@ class SaveSearchEngineFragment : Fragment(R.layout.fragment_save_search_engine)
searchEngine?.let {
val url = it.resultUrls[0]
val suggestUrl = it.suggestUrl ?: ""
binding.editEngineName.setText(it.name)
binding.editSearchString.setText(url.toEditableUrl())
binding.editSuggestString.setText(suggestUrl.toEditableUrl())
}
binding.customSearchEnginesLearnMoreWrapper.setOnClickListener {
val learnMoreListener: (View) -> Unit = {
(activity as HomeActivity).openToBrowserAndLoad(
searchTermOrURL = SupportUtils.getSumoURLForTopic(
requireContext(),
@ -90,6 +92,8 @@ class SaveSearchEngineFragment : Fragment(R.layout.fragment_save_search_engine)
from = BrowserDirection.FromSaveSearchEngineFragment,
)
}
binding.customSearchEnginesLearnMoreWrapper.setOnClickListener(learnMoreListener)
binding.customSearchSuggestionsLearnMoreWrapper.setOnClickListener(learnMoreListener)
}
override fun onResume() {
@ -110,68 +114,86 @@ class SaveSearchEngineFragment : Fragment(R.layout.fragment_save_search_engine)
private fun createCustomEngine() {
binding.customSearchEngineNameField.error = ""
binding.customSearchEngineSearchStringField.error = ""
binding.customSearchEngineSuggestStringField.error = ""
val name = binding.editEngineName.text?.toString()?.trim() ?: ""
val searchString = binding.editSearchString.text?.toString() ?: ""
val suggestString = binding.editSuggestString.text?.toString() ?: ""
if (checkForErrors(name, searchString)) {
if (checkForErrors(name, searchString, suggestString)) {
return
}
viewLifecycleOwner.lifecycleScope.launch(Main) {
val result = withContext(IO) {
val searchStringResult = withContext(IO) {
SearchStringValidator.isSearchStringValid(
requireComponents.core.client,
searchString,
)
}
if (searchStringResult == SearchStringValidator.Result.CannotReach) {
binding.customSearchEngineSearchStringField.error = resources
.getString(R.string.search_add_custom_engine_error_cannot_reach, name)
}
when (result) {
SearchStringValidator.Result.CannotReach -> {
binding.customSearchEngineSearchStringField.error = resources
.getString(R.string.search_add_custom_engine_error_cannot_reach, name)
val suggestStringResult = if (suggestString.isBlank()) {
SearchStringValidator.Result.Success
} else {
withContext(IO) {
SearchStringValidator.isSearchStringValid(
requireComponents.core.client,
suggestString,
)
}
}
if (suggestStringResult == SearchStringValidator.Result.CannotReach) {
binding.customSearchEngineSuggestStringField.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()),
icon = requireComponents.core.icons.loadIcon(IconRequest(searchString))
if ((searchStringResult == SearchStringValidator.Result.Success) &&
(suggestStringResult == SearchStringValidator.Result.Success)
) {
val update = searchEngine?.copy(
name = name,
resultUrls = listOf(searchString.toSearchUrl()),
icon = requireComponents.core.icons.loadIcon(IconRequest(searchString))
.await().bitmap,
suggestUrl = suggestString.toSearchUrl(),
) ?: run {
createSearchEngine(
name,
searchString.toSearchUrl(),
requireComponents.core.icons.loadIcon(IconRequest(searchString))
.await().bitmap,
) ?: run {
createSearchEngine(
name,
searchString.toSearchUrl(),
requireComponents.core.icons.loadIcon(IconRequest(searchString))
.await().bitmap,
isGeneral = true,
)
}
requireComponents.useCases.searchUseCases.addSearchEngine(update)
val successMessage = if (searchEngine != null) {
resources.getString(R.string.search_edit_custom_engine_success_message, name)
} else {
resources.getString(R.string.search_add_custom_engine_success_message, name)
}
view?.also {
FenixSnackbar.make(
view = it,
duration = FenixSnackbar.LENGTH_SHORT,
isDisplayedWithBrowserToolbar = false,
)
.setText(successMessage)
.show()
}
findNavController().popBackStack()
suggestUrl = suggestString.toSearchUrl(),
isGeneral = true,
)
}
requireComponents.useCases.searchUseCases.addSearchEngine(update)
val successMessage = if (searchEngine != null) {
resources.getString(R.string.search_edit_custom_engine_success_message, name)
} else {
resources.getString(R.string.search_add_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 {
private fun checkForErrors(name: String, searchString: String, suggestString: String): Boolean {
return when {
name.isEmpty() -> {
binding.customSearchEngineNameField.error = resources
@ -188,6 +210,11 @@ class SaveSearchEngineFragment : Fragment(R.layout.fragment_save_search_engine)
resources.getString(R.string.search_add_custom_engine_error_missing_template)
true
}
suggestString.isNotBlank() && !suggestString.contains("%s") -> {
binding.customSearchEngineSuggestStringField.error =
resources.getString(R.string.search_add_custom_engine_error_missing_template)
true
}
else -> false
}
}

@ -99,6 +99,59 @@
app:layout_constraintTop_toBottomOf="@id/exceptions_empty_message" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:text="@string/search_add_custom_engine_suggest_url_label"
android:textColor="?attr/textSecondary"
android:textFontWeight="@integer/font_weight_light"
android:textSize="12sp"
tools:targetApi="p" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/custom_search_engine_suggest_string_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:hintTextColor="?attr/textSecondary"
android:textColorHint="?attr/textSecondary"
app:hintTextAppearance="@style/EngineTextField"
app:hintEnabled="false"
app:errorEnabled="true">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/edit_suggest_string"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="@dimen/accessibility_min_height"
android:hint="@string/search_add_custom_engine_suggest_string_hint"
android:inputType="text"/>
</com.google.android.material.textfield.TextInputLayout>
<LinearLayout
android:id="@+id/custom_search_suggestions_learn_more_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:minHeight="@dimen/accessibility_min_height"
android:paddingBottom="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/search_add_custom_engine_suggest_string_example"
app:lineHeight="18sp"
android:labelFor="@id/edit_search_string"
android:textColor="@android:color/tertiary_text_dark"/>
<org.mozilla.fenix.utils.LinkTextView
android:id="@+id/custom_search_suggestions_learn_more"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/exceptions_empty_message_learn_more_link"
android:textColor="?accent"
android:visibility="visible"
app:layout_constraintTop_toBottomOf="@id/exceptions_empty_message"
android:paddingBottom="16dp"/>
</LinearLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/save_button"
style="@style/PositiveButton"

@ -1835,6 +1835,12 @@
<string name="search_add_custom_engine_search_string_example" formatted="false">Replace query with “%s”. Example:\nhttps://www.google.com/search?q=%s</string>
<!-- Accessibility description for the form in which details about the custom search engine are entered -->
<string name="search_add_custom_engine_form_description">Custom search engine details</string>
<!-- Label for the TextField in which user enters custom search engine suggestion URL -->
<string name="search_add_custom_engine_suggest_url_label">Search suggestion API (optional)</string>
<!-- Placeholder text shown in the Search Suggestion String TextField before a user enters text -->
<string name="search_add_custom_engine_suggest_string_hint">Search suggestion API URL</string>
<!-- Description text for the Search Suggestion String TextField. The %s is part of the string -->
<string name="search_add_custom_engine_suggest_string_example" formatted="false">Replace query with “%s”. Example:\nhttp://suggestqueries.google.com/complete/search?client=firefox&amp;q=%s</string>
<!-- The text for the "Save" button for saving a custom search engine -->
<string name="search_custom_engine_save_button">Save</string>

Loading…
Cancel
Save