1
0
Fork 0

For #1216: Add voice search

master
Sawyer Blatz 2020-05-14 10:47:13 -07:00
parent c0e4056c16
commit 011a9e7d96
7 changed files with 63 additions and 3 deletions

View File

@ -33,7 +33,6 @@ import mozilla.components.browser.session.Session
import mozilla.components.browser.session.SessionManager
import mozilla.components.browser.session.runWithSessionIdOrSelected
import mozilla.components.concept.engine.prompt.ShareData
import mozilla.components.feature.accounts.FxaCapability
import mozilla.components.feature.accounts.FxaWebChannelFeature
import mozilla.components.feature.app.links.AppLinksFeature
import mozilla.components.feature.contextmenu.ContextMenuCandidate
@ -482,7 +481,8 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
view.swipeRefresh.setOnChildScrollUpCallback { _, _ -> true }
}
@Suppress("ConstantConditionIf")
// @Suppress("ConstantConditionIf")
/*
if (!FeatureFlags.asFeatureWebChannelsDisabled) {
webchannelIntegration.set(
feature = FxaWebChannelFeature(
@ -499,6 +499,8 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
)
}
*/
initializeEngineView(toolbarHeight)
}
}

View File

@ -5,17 +5,22 @@
package org.mozilla.fenix.search
import android.Manifest
import android.app.Activity.RESULT_OK
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.graphics.Typeface.BOLD
import android.graphics.Typeface.ITALIC
import android.os.Bundle
import android.speech.RecognizerIntent
import android.speech.RecognizerIntent.EXTRA_RESULTS
import android.text.style.StyleSpan
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewStub
import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
@ -25,6 +30,7 @@ import kotlinx.android.synthetic.main.fragment_search.*
import kotlinx.android.synthetic.main.fragment_search.view.*
import kotlinx.android.synthetic.main.search_suggestions_onboarding.view.*
import kotlinx.coroutines.ExperimentalCoroutinesApi
import mozilla.components.browser.toolbar.BrowserToolbar
import mozilla.components.concept.storage.HistoryStorage
import mozilla.components.feature.qr.QrFeature
import mozilla.components.lib.state.ext.consumeFrom
@ -47,6 +53,7 @@ import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.search.awesomebar.AwesomeBarView
import org.mozilla.fenix.search.toolbar.ToolbarView
import org.mozilla.fenix.settings.SupportUtils
import org.mozilla.fenix.widget.VoiceSearchActivity.Companion.SPEECH_REQUEST_CODE
@Suppress("TooManyFunctions", "LargeClass")
class SearchFragment : Fragment(), UserInteractionHandler {
@ -127,6 +134,14 @@ class SearchFragment : Fragment(), UserInteractionHandler {
requireComponents.core.engine
)
toolbarView.view.addEditAction(
BrowserToolbar.Button(
ContextCompat.getDrawable(requireContext(), R.drawable.ic_microphone)!!,
requireContext().getString(R.string.voice_search_content_description),
visible = { requireContext().settings().shouldShowVoiceSearch },
listener = ::launchVoiceSearch
)
)
val urlView = toolbarView.view
.findViewById<InlineAutocompleteEditText>(R.id.mozac_browser_toolbar_edit_url_view)
urlView?.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO
@ -136,6 +151,14 @@ class SearchFragment : Fragment(), UserInteractionHandler {
return view
}
private fun launchVoiceSearch() {
val speechIntent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {
putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM)
putExtra(RecognizerIntent.EXTRA_PROMPT, requireContext().getString(R.string.voice_search_explainer))
}
startActivityForResult(speechIntent, SPEECH_REQUEST_CODE)
}
private fun clearToolbarFocus() {
toolbarView.view.clearFocus()
}
@ -274,7 +297,7 @@ class SearchFragment : Fragment(), UserInteractionHandler {
}
if (!permissionDidUpdate) {
toolbarView.view.requestFocus()
toolbarView.view.edit.focus()
}
updateClipboardSuggestion(
@ -286,6 +309,16 @@ class SearchFragment : Fragment(), UserInteractionHandler {
hideToolbar()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
if (requestCode == 0 && resultCode == RESULT_OK) {
intent?.getStringArrayListExtra(EXTRA_RESULTS)?.first()?.also {
toolbarView.view.edit.updateUrl(url = it, shouldHighlight = true)
searchInteractor.onTextChanged(it)
toolbarView.view.edit.focus()
}
}
}
override fun onPause() {
super.onPause()
toolbarView.view.clearFocus()
@ -295,6 +328,7 @@ class SearchFragment : Fragment(), UserInteractionHandler {
// Note: Actual navigation happens in `handleEditingCancelled` in SearchController
return when {
qrFeature.onBackPressed() -> {
toolbarView.view.edit.focus()
view?.search_scan_button?.isChecked = false
toolbarView.view.requestFocus()
}

View File

@ -60,6 +60,11 @@ class SearchEngineFragment : PreferenceFragmentCompat() {
val searchEngineListPreference =
findPreference<SearchEngineListPreference>(getPreferenceKey(R.string.pref_key_search_engine_list))
val showVoiceSearchPreference =
findPreference<SwitchPreference>(getPreferenceKey(R.string.pref_key_show_voice_search))?.apply {
isChecked = context.settings().shouldShowVoiceSearch
}
searchEngineListPreference?.reload(requireContext())
searchSuggestionsPreference?.onPreferenceChangeListener = SharedPreferenceUpdater()
showSearchShortcuts?.onPreferenceChangeListener = SharedPreferenceUpdater()
@ -67,6 +72,7 @@ class SearchEngineFragment : PreferenceFragmentCompat() {
showBookmarkSuggestions?.onPreferenceChangeListener = SharedPreferenceUpdater()
showClipboardSuggestions?.onPreferenceChangeListener = SharedPreferenceUpdater()
searchSuggestionsInPrivatePreference?.onPreferenceChangeListener = SharedPreferenceUpdater()
showVoiceSearchPreference?.onPreferenceChangeListener = SharedPreferenceUpdater()
searchSuggestionsPreference?.setOnPreferenceClickListener {
if (!searchSuggestionsPreference.isChecked) {

View File

@ -545,6 +545,11 @@ class Settings private constructor(
}
}
var shouldShowVoiceSearch by booleanPreference(
appContext.getPreferenceKey(R.string.pref_key_show_voice_search),
default = true
)
var shouldPromptToSaveLogins by booleanPreference(
appContext.getPreferenceKey(R.string.pref_key_save_logins),
default = true

View File

@ -87,6 +87,7 @@
<string name="pref_key_search_bookmarks" translatable="false">pref_key_search_bookmarks</string>
<string name="pref_key_show_search_suggestions_in_private" translatable="false">pref_key_show_search_suggestions_in_private</string>
<string name="pref_key_show_search_suggestions_in_private_onboarding" translatable="false">pref_key_show_search_suggestions_in_privateonboarding</string>
<string name="pref_key_show_voice_search" translatable="false">pref_key_show_voice_search</string>
<!-- Site Permissions Settings -->

View File

@ -248,6 +248,8 @@
<string name="preferences_show_search_shortcuts">Show search shortcuts</string>
<!-- Preference title for switch preference to show search suggestions -->
<string name="preferences_show_search_suggestions">Show search suggestions</string>
<!-- Preference title for switch preference to show voice search button -->
<string name="preferences_show_voice_search">Show voice search</string>
<!-- Preference title for switch preference to show search suggestions also in private mode -->
<string name="preferences_show_search_suggestions_in_private">Show in private sessions</string>
<!-- Preference title for switch preference to show a clipboard suggestion when searching -->
@ -1360,4 +1362,8 @@
<string name="edit">Edit</string>
<!-- The error message in edit login view when password field is blank. -->
<string name="saved_login_password_required">Password required</string>
<!-- Voice search button content description -->
<string name="voice_search_content_description">Voice search</string>
<!-- Voice search prompt description displayed after the user presses the voice search button -->
<string name="voice_search_explainer">Speak now</string>
</resources>

View File

@ -51,6 +51,12 @@
android:title="@string/preferences_show_search_suggestions"
app:iconSpaceReserved="false"
app:allowDividerAbove="false"/>
<SwitchPreference
android:defaultValue="true"
android:key="@string/pref_key_show_voice_search"
android:title="@string/preferences_show_voice_search"
app:iconSpaceReserved="false"
app:allowDividerAbove="false"/>
<CheckBoxPreference
android:defaultValue="false"
android:dependency="@string/pref_key_show_search_suggestions"