|
|
|
@ -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()
|
|
|
|
|
}
|
|
|
|
|