For #1216: Add voice search
parent
c0e4056c16
commit
011a9e7d96
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 -->
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue