|
|
@ -22,8 +22,8 @@ import android.view.View
|
|
|
|
import android.view.ViewGroup
|
|
|
|
import android.view.ViewGroup
|
|
|
|
import android.view.ViewStub
|
|
|
|
import android.view.ViewStub
|
|
|
|
import android.view.WindowManager
|
|
|
|
import android.view.WindowManager
|
|
|
|
import android.view.inputmethod.InputMethodManager
|
|
|
|
|
|
|
|
import android.view.accessibility.AccessibilityEvent
|
|
|
|
import android.view.accessibility.AccessibilityEvent
|
|
|
|
|
|
|
|
import android.view.inputmethod.InputMethodManager
|
|
|
|
import androidx.appcompat.app.AlertDialog
|
|
|
|
import androidx.appcompat.app.AlertDialog
|
|
|
|
import androidx.appcompat.app.AppCompatDialogFragment
|
|
|
|
import androidx.appcompat.app.AppCompatDialogFragment
|
|
|
|
import androidx.appcompat.content.res.AppCompatResources
|
|
|
|
import androidx.appcompat.content.res.AppCompatResources
|
|
|
@ -39,9 +39,9 @@ import kotlinx.android.synthetic.main.fragment_search_dialog.*
|
|
|
|
import kotlinx.android.synthetic.main.fragment_search_dialog.view.*
|
|
|
|
import kotlinx.android.synthetic.main.fragment_search_dialog.view.*
|
|
|
|
import kotlinx.android.synthetic.main.search_suggestions_hint.view.*
|
|
|
|
import kotlinx.android.synthetic.main.search_suggestions_hint.view.*
|
|
|
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|
|
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|
|
|
import kotlinx.coroutines.launch
|
|
|
|
|
|
|
|
import kotlinx.coroutines.flow.collect
|
|
|
|
import kotlinx.coroutines.flow.collect
|
|
|
|
import kotlinx.coroutines.flow.map
|
|
|
|
import kotlinx.coroutines.flow.map
|
|
|
|
|
|
|
|
import kotlinx.coroutines.launch
|
|
|
|
import mozilla.components.browser.toolbar.BrowserToolbar
|
|
|
|
import mozilla.components.browser.toolbar.BrowserToolbar
|
|
|
|
import mozilla.components.concept.storage.HistoryStorage
|
|
|
|
import mozilla.components.concept.storage.HistoryStorage
|
|
|
|
import mozilla.components.feature.qr.QrFeature
|
|
|
|
import mozilla.components.feature.qr.QrFeature
|
|
|
@ -62,7 +62,6 @@ import org.mozilla.fenix.R
|
|
|
|
import org.mozilla.fenix.components.metrics.Event
|
|
|
|
import org.mozilla.fenix.components.metrics.Event
|
|
|
|
import org.mozilla.fenix.components.toolbar.ToolbarPosition
|
|
|
|
import org.mozilla.fenix.components.toolbar.ToolbarPosition
|
|
|
|
import org.mozilla.fenix.ext.components
|
|
|
|
import org.mozilla.fenix.ext.components
|
|
|
|
import org.mozilla.fenix.ext.isKeyboardVisible
|
|
|
|
|
|
|
|
import org.mozilla.fenix.ext.requireComponents
|
|
|
|
import org.mozilla.fenix.ext.requireComponents
|
|
|
|
import org.mozilla.fenix.ext.settings
|
|
|
|
import org.mozilla.fenix.ext.settings
|
|
|
|
import org.mozilla.fenix.search.awesomebar.AwesomeBarView
|
|
|
|
import org.mozilla.fenix.search.awesomebar.AwesomeBarView
|
|
|
@ -83,15 +82,14 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler {
|
|
|
|
private val qrFeature = ViewBoundFeatureWrapper<QrFeature>()
|
|
|
|
private val qrFeature = ViewBoundFeatureWrapper<QrFeature>()
|
|
|
|
private val speechIntent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
|
|
|
|
private val speechIntent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
|
|
|
|
|
|
|
|
|
|
|
|
private var keyboardVisible: Boolean = false
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
override fun onStart() {
|
|
|
|
override fun onStart() {
|
|
|
|
super.onStart()
|
|
|
|
super.onStart()
|
|
|
|
// https://github.com/mozilla-mobile/fenix/issues/14279
|
|
|
|
// https://github.com/mozilla-mobile/fenix/issues/14279
|
|
|
|
// To prevent GeckoView from resizing we're going to change the softInputMode to not adjust
|
|
|
|
// To prevent GeckoView from resizing we're going to change the softInputMode to not adjust
|
|
|
|
// the size of the window.
|
|
|
|
// the size of the window.
|
|
|
|
requireActivity().window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING)
|
|
|
|
requireActivity().window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING)
|
|
|
|
if (keyboardVisible) {
|
|
|
|
// Refocus the toolbar editing and show keyboard if the QR fragment isn't showing
|
|
|
|
|
|
|
|
if (childFragmentManager.findFragmentByTag(QR_FRAGMENT_TAG) == null) {
|
|
|
|
toolbarView.view.edit.focus()
|
|
|
|
toolbarView.view.edit.focus()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -101,7 +99,6 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler {
|
|
|
|
// https://github.com/mozilla-mobile/fenix/issues/14279
|
|
|
|
// https://github.com/mozilla-mobile/fenix/issues/14279
|
|
|
|
// Let's reset back to the default behavior after we're done searching
|
|
|
|
// Let's reset back to the default behavior after we're done searching
|
|
|
|
requireActivity().window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
|
|
|
|
requireActivity().window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
|
|
|
|
keyboardVisible = toolbarView.view.isKeyboardVisible()
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
|
@ -150,7 +147,7 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler {
|
|
|
|
metrics = requireComponents.analytics.metrics,
|
|
|
|
metrics = requireComponents.analytics.metrics,
|
|
|
|
dismissDialog = { dismissAllowingStateLoss() },
|
|
|
|
dismissDialog = { dismissAllowingStateLoss() },
|
|
|
|
clearToolbarFocus = {
|
|
|
|
clearToolbarFocus = {
|
|
|
|
toolbarView.view.hideKeyboardAndSave()
|
|
|
|
toolbarView.view.hideKeyboard()
|
|
|
|
toolbarView.view.clearFocus()
|
|
|
|
toolbarView.view.clearFocus()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
@ -172,7 +169,7 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler {
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
view.awesome_bar.setOnTouchListener { _, _ ->
|
|
|
|
view.awesome_bar.setOnTouchListener { _, _ ->
|
|
|
|
view.hideKeyboardAndSave()
|
|
|
|
view.hideKeyboard()
|
|
|
|
false
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -214,7 +211,7 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler {
|
|
|
|
// When displayed above browser, dismisses dialog on clicking scrim area
|
|
|
|
// When displayed above browser, dismisses dialog on clicking scrim area
|
|
|
|
if (findNavController().previousBackStackEntry?.destination?.id == R.id.browserFragment) {
|
|
|
|
if (findNavController().previousBackStackEntry?.destination?.id == R.id.browserFragment) {
|
|
|
|
search_wrapper.setOnClickListener {
|
|
|
|
search_wrapper.setOnClickListener {
|
|
|
|
it.hideKeyboardAndSave()
|
|
|
|
it.hideKeyboard()
|
|
|
|
dismissAllowingStateLoss()
|
|
|
|
dismissAllowingStateLoss()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -335,17 +332,9 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
override fun onResume() {
|
|
|
|
|
|
|
|
super.onResume()
|
|
|
|
|
|
|
|
resetFocus()
|
|
|
|
|
|
|
|
toolbarView.view.edit.focus()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
override fun onPause() {
|
|
|
|
override fun onPause() {
|
|
|
|
super.onPause()
|
|
|
|
super.onPause()
|
|
|
|
qr_scan_button.isChecked = false
|
|
|
|
|
|
|
|
view?.hideKeyboard()
|
|
|
|
view?.hideKeyboard()
|
|
|
|
toolbarView.view.requestFocus()
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
@ -353,9 +342,12 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler {
|
|
|
|
* is also dismissing. For example, when clicking a top site on home while this dialog is showing.
|
|
|
|
* is also dismissing. For example, when clicking a top site on home while this dialog is showing.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
private fun hideDeviceKeyboard() {
|
|
|
|
private fun hideDeviceKeyboard() {
|
|
|
|
val imm =
|
|
|
|
// If the controller has handled a search event itself, it will clear the focus.
|
|
|
|
requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
|
|
|
if (toolbarView.view.hasFocus()) {
|
|
|
|
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0)
|
|
|
|
val imm =
|
|
|
|
|
|
|
|
requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
|
|
|
|
|
|
|
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
override fun onDismiss(dialog: DialogInterface) {
|
|
|
|
override fun onDismiss(dialog: DialogInterface) {
|
|
|
@ -380,7 +372,7 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler {
|
|
|
|
true
|
|
|
|
true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else -> {
|
|
|
|
else -> {
|
|
|
|
view?.hideKeyboardAndSave()
|
|
|
|
view?.hideKeyboard()
|
|
|
|
dismissAllowingStateLoss()
|
|
|
|
dismissAllowingStateLoss()
|
|
|
|
true
|
|
|
|
true
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -500,15 +492,6 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler {
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Used to save keyboard status on stop/sleep, to be restored later.
|
|
|
|
|
|
|
|
* See #14559
|
|
|
|
|
|
|
|
* */
|
|
|
|
|
|
|
|
private fun View.hideKeyboardAndSave() {
|
|
|
|
|
|
|
|
keyboardVisible = false
|
|
|
|
|
|
|
|
this.hideKeyboard()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private fun launchVoiceSearch() {
|
|
|
|
private fun launchVoiceSearch() {
|
|
|
|
// Note if a user disables speech while the app is on the search fragment
|
|
|
|
// Note if a user disables speech while the app is on the search fragment
|
|
|
|
// the voice button will still be available and *will* cause a crash if tapped,
|
|
|
|
// the voice button will still be available and *will* cause a crash if tapped,
|
|
|
@ -574,6 +557,7 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
companion object {
|
|
|
|
companion object {
|
|
|
|
|
|
|
|
private const val QR_FRAGMENT_TAG = "MOZAC_QR_FRAGMENT"
|
|
|
|
private const val REQUEST_CODE_CAMERA_PERMISSIONS = 1
|
|
|
|
private const val REQUEST_CODE_CAMERA_PERMISSIONS = 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|