Skip to content

Commit 7acbc31

Browse files
authored
Fix keyboard crashes in BrowserFragment (#5033)
Task/Issue URL: https://app.asana.com/0/414730916066338/1208339084893367/f ### Description We saw some keyboard crashes due to some recent refactoring of the Omnibar. The Omnibar was previously solely bound in onActivityCreated. It was never nulled out in `onDestroyView` so the Fragment held on to it, and when the delay concluded it would happily try to call show/hideKeyboard using the Omnibar without issue. Now, we’re using the FragmentViewBindingDelegate for the Omnibar, which gets nulled out in onDestroy, so when the delay concluded we tried calling show/hideKeyboard on a null object. To fix this we’re introducing new extension functions that follow the [recommended way](https://developer.android.com/develop/ui/views/touch-and-input/keyboard-input/visibility#kotlin) to show and hide the keyboard. ### Steps to test this PR _Run the following tests locally they should all pass_ - [x] `whenProtectionsAreDisabledRequestAreNotBlocked` - [x] `whenProtectionsAreDisabledSurrogatesAreNotLoaded` - [x] `whenProtectionsAreEnabledHttpsUpgradedCorrectly` - [x] `whenProtectionsAreEnabledRequestBlockedCorrectly` - [x] `whenProtectionsAreEnabledSurrogatesAreLoaded` - [x] `whenProtectionsAreFingerprintProtected` _Omnibar Keyboard_ - [x] Ensure keyboard shows when opening app with New Tab Page - [x] Generally play around with the Omnibar EditText and ensure keyboard is shown and hidden where appropriate ### UI changes N/A
1 parent a3a7ba0 commit 7acbc31

File tree

4 files changed

+50
-2
lines changed

4 files changed

+50
-2
lines changed

app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,9 @@ import com.duckduckgo.common.utils.ConflatedJob
268268
import com.duckduckgo.common.utils.DispatcherProvider
269269
import com.duckduckgo.common.utils.FragmentViewModelFactory
270270
import com.duckduckgo.common.utils.KeyboardVisibilityUtil
271+
import com.duckduckgo.common.utils.extensions.hideKeyboard
271272
import com.duckduckgo.common.utils.extensions.html
273+
import com.duckduckgo.common.utils.extensions.showKeyboard
272274
import com.duckduckgo.common.utils.extensions.toBinaryString
273275
import com.duckduckgo.common.utils.extensions.websiteFromGeoLocationsApiOrigin
274276
import com.duckduckgo.common.utils.extractDomain
@@ -3083,7 +3085,7 @@ class BrowserTabFragment :
30833085
private fun hideKeyboard() {
30843086
if (!isHidden) {
30853087
Timber.v("Keyboard now hiding")
3086-
binding.legacyOmnibar.omnibarTextInput.postDelayed(KEYBOARD_DELAY) { binding.legacyOmnibar.omnibarTextInput?.hideKeyboard() }
3088+
hideKeyboard(binding.legacyOmnibar.omnibarTextInput)
30873089
binding.focusDummy.requestFocus()
30883090
binding.legacyOmnibar.omniBarContainer.isPressed = false
30893091
}
@@ -3099,7 +3101,7 @@ class BrowserTabFragment :
30993101
private fun showKeyboard() {
31003102
if (!isHidden) {
31013103
Timber.v("Keyboard now showing")
3102-
binding.legacyOmnibar.omnibarTextInput.postDelayed(KEYBOARD_DELAY) { binding.legacyOmnibar.omnibarTextInput?.showKeyboard() }
3104+
showKeyboard(binding.legacyOmnibar.omnibarTextInput)
31033105
binding.legacyOmnibar.omniBarContainer.isPressed = true
31043106
}
31053107
}

common/common-ui/src/main/java/com/duckduckgo/common/ui/view/ViewExtension.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ fun View.gone(): View {
5858
}
5959

6060
/** Extension method to show a keyboard for View. */
61+
@Deprecated(
62+
"This may be unreliable. Use the showKeyboard() extension function from an Activity or Fragment instead.",
63+
ReplaceWith("Activity.showKeyboard(editText)"),
64+
)
6165
fun View.showKeyboard() {
6266
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
6367
this.requestFocus()
@@ -68,6 +72,10 @@ fun View.showKeyboard() {
6872
* Try to hide the keyboard and returns whether it worked
6973
* https://stackoverflow.com/questions/1109022/close-hide-the-android-soft-keyboard
7074
*/
75+
@Deprecated(
76+
"This may be unreliable. Use the hideKeyboard() extension function from an Activity or Fragment instead.",
77+
ReplaceWith("Activity.hideKeyboard(editText)"),
78+
)
7179
fun View.hideKeyboard(): Boolean {
7280
try {
7381
val inputMethodManager =

common/common-utils/src/main/java/com/duckduckgo/common/utils/extensions/ActivityExtensions.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,14 @@
1717
package com.duckduckgo.common.utils.extensions
1818

1919
import android.annotation.SuppressLint
20+
import android.app.Activity
2021
import android.content.Intent
2122
import android.net.Uri
2223
import android.provider.Settings
24+
import android.widget.EditText
2325
import androidx.appcompat.app.AppCompatActivity
26+
import androidx.core.view.WindowInsetsCompat
27+
import androidx.core.view.WindowInsetsControllerCompat
2428

2529
/**
2630
* Deep links to the application App Info settings
@@ -71,3 +75,13 @@ fun AppCompatActivity.launchIgnoreBatteryOptimizationSettings(): Boolean {
7175

7276
return true
7377
}
78+
79+
fun Activity.showKeyboard(editText: EditText) {
80+
editText.requestFocus()
81+
WindowInsetsControllerCompat(window, editText).show(WindowInsetsCompat.Type.ime())
82+
}
83+
84+
fun Activity.hideKeyboard(editText: EditText) {
85+
editText.requestFocus()
86+
WindowInsetsControllerCompat(window, editText).hide(WindowInsetsCompat.Type.ime())
87+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright (c) 2024 DuckDuckGo
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.duckduckgo.common.utils.extensions
18+
19+
import android.widget.EditText
20+
import androidx.fragment.app.Fragment
21+
22+
fun Fragment.showKeyboard(editText: EditText) = activity?.showKeyboard(editText)
23+
24+
fun Fragment.hideKeyboard(editText: EditText) = activity?.hideKeyboard(editText)

0 commit comments

Comments
 (0)