Skip to content

Commit 0d6d280

Browse files
authored
Handle user entering empty query by not dismissing the keyboard (#164)
1 parent 3cc477f commit 0d6d280

File tree

3 files changed

+70
-49
lines changed

3 files changed

+70
-49
lines changed

app/src/androidTest/java/com/duckduckgo/app/browser/BrowserViewModelTest.kt

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,10 @@ import org.junit.Assert.*
4949
import org.junit.Before
5050
import org.junit.Rule
5151
import org.junit.Test
52-
import org.mockito.ArgumentCaptor
53-
import org.mockito.ArgumentMatchers
54-
import org.mockito.Mock
52+
import org.mockito.*
53+
import org.mockito.ArgumentCaptor.forClass
5554
import org.mockito.Mockito.never
5655
import org.mockito.Mockito.verify
57-
import org.mockito.MockitoAnnotations
5856

5957
class BrowserViewModelTest {
6058

@@ -78,7 +76,7 @@ class BrowserViewModelTest {
7876
lateinit var mockQueryObserver: Observer<String>
7977

8078
@Mock
81-
lateinit var mockNavigationObserver: Observer<Command>
79+
lateinit var mockCommandObserver: Observer<Command>
8280

8381
@Mock
8482
lateinit var mockTermsOfServiceStore: TermsOfServiceStore
@@ -121,7 +119,7 @@ class BrowserViewModelTest {
121119
appConfigurationDao = appConfigurationDao)
122120

123121
testee.url.observeForever(mockQueryObserver)
124-
testee.command.observeForever(mockNavigationObserver)
122+
testee.command.observeForever(mockCommandObserver)
125123

126124
whenever(mockOmnibarConverter.convertQueryToUri(any())).thenReturn(Uri.parse("duckduckgo.com"))
127125

@@ -132,7 +130,7 @@ class BrowserViewModelTest {
132130
testee.onCleared()
133131
db.close()
134132
testee.url.removeObserver(mockQueryObserver)
135-
testee.command.removeObserver(mockNavigationObserver)
133+
testee.command.removeObserver(mockCommandObserver)
136134
}
137135

138136
@Test
@@ -242,8 +240,8 @@ class BrowserViewModelTest {
242240
@Test
243241
fun whenSharedTextReceivedThenNavigationTriggered() {
244242
testee.onSharedTextReceived("http://example.com")
245-
val captor: ArgumentCaptor<Command> = ArgumentCaptor.forClass(Command::class.java)
246-
verify(mockNavigationObserver, times(2)).onChanged(captor.capture())
243+
val captor: ArgumentCaptor<Command> = forClass(Command::class.java)
244+
verify(mockCommandObserver, times(2)).onChanged(captor.capture())
247245
assertNotNull(captor.value)
248246
assertTrue(captor.value is Navigate)
249247
}
@@ -263,13 +261,13 @@ class BrowserViewModelTest {
263261
@Test
264262
fun whenUserDismissesKeyboardBeforeBrowserShownThenShouldNavigateToLandingPage() {
265263
testee.userDismissedKeyboard()
266-
verify(mockNavigationObserver).onChanged(ArgumentMatchers.any(LandingPage::class.java))
264+
verify(mockCommandObserver).onChanged(ArgumentMatchers.any(LandingPage::class.java))
267265
}
268266

269267
@Test
270268
fun whenUserDismissesKeyboardAfterBrowserShownThenShouldNotNavigateToLandingPage() {
271269
testee.urlChanged("")
272-
verify(mockNavigationObserver, never()).onChanged(ArgumentMatchers.any(LandingPage::class.java))
270+
verify(mockCommandObserver, never()).onChanged(ArgumentMatchers.any(LandingPage::class.java))
273271
}
274272

275273
@Test
@@ -387,4 +385,18 @@ class BrowserViewModelTest {
387385
testee.onOmnibarInputStateChanged("", true)
388386
assertFalse(testee.viewState.value!!.showAutoCompleteSuggestions)
389387
}
388+
389+
@Test
390+
fun whenEnteringEmptyQueryThenHideKeyboardCommandNotIssued() {
391+
testee.onUserSubmittedQuery("")
392+
verify(mockCommandObserver, never()).onChanged(Mockito.any(Command.HideKeyboard.javaClass))
393+
}
394+
395+
@Test
396+
fun whenEnteringNonEmptyQueryThenHideKeyboardCommandIssued() {
397+
val captor = ArgumentCaptor.forClass(BrowserViewModel.Command::class.java)
398+
testee.onUserSubmittedQuery("foo")
399+
verify(mockCommandObserver, Mockito.atLeastOnce()).onChanged(captor.capture())
400+
assertTrue(captor.value == Command.HideKeyboard)
401+
}
390402
}

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

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import android.widget.Toast
4141
import com.duckduckgo.app.bookmarks.ui.BookmarkAddEditDialogFragment
4242
import com.duckduckgo.app.bookmarks.ui.BookmarkAddEditDialogFragment.BookmarkDialogCreationListener
4343
import com.duckduckgo.app.bookmarks.ui.BookmarksActivity
44+
import com.duckduckgo.app.browser.BrowserViewModel.Command
4445
import com.duckduckgo.app.browser.autoComplete.BrowserAutoCompleteSuggestionsAdapter
4546
import com.duckduckgo.app.browser.omnibar.OnBackKeyListener
4647
import com.duckduckgo.app.global.DuckDuckGoActivity
@@ -129,38 +130,45 @@ class BrowserActivity : DuckDuckGoActivity(), BookmarkDialogCreationListener {
129130
})
130131

131132
viewModel.command.observe(this, Observer {
132-
when (it) {
133-
is BrowserViewModel.Command.Refresh -> webView.reload()
134-
is BrowserViewModel.Command.Navigate -> {
135-
focusDummy.requestFocus()
136-
webView.loadUrl(it.url)
137-
}
138-
is BrowserViewModel.Command.LandingPage -> finishActivityAnimated()
139-
is BrowserViewModel.Command.DialNumber -> {
140-
val intent = Intent(Intent.ACTION_DIAL)
141-
intent.data = Uri.parse("tel:${it.telephoneNumber}")
142-
launchExternalActivity(intent)
143-
}
144-
is BrowserViewModel.Command.SendEmail -> {
145-
val intent = Intent(Intent.ACTION_SENDTO)
146-
intent.data = Uri.parse(it.emailAddress)
147-
launchExternalActivity(intent)
148-
}
149-
is BrowserViewModel.Command.SendSms -> {
150-
val intent = Intent(Intent.ACTION_SENDTO, Uri.parse("smsto:${it.telephoneNumber}"))
151-
startActivity(intent)
152-
}
153-
is BrowserViewModel.Command.ShowKeyboard -> {
154-
Timber.i("Command: showing keyboard")
155-
omnibarTextInput.postDelayed({omnibarTextInput.showKeyboard()}, 300)
156-
}
157-
is BrowserViewModel.Command.ReinitialiseWebView -> {
158-
webView.clearHistory()
159-
}
160-
}
133+
processCommand(it)
161134
})
162135
}
163136

137+
private fun processCommand(it: Command?) {
138+
when (it) {
139+
Command.Refresh -> webView.reload()
140+
is Command.Navigate -> {
141+
focusDummy.requestFocus()
142+
webView.loadUrl(it.url)
143+
}
144+
Command.LandingPage -> finishActivityAnimated()
145+
is Command.DialNumber -> {
146+
val intent = Intent(Intent.ACTION_DIAL)
147+
intent.data = Uri.parse("tel:${it.telephoneNumber}")
148+
launchExternalActivity(intent)
149+
}
150+
is Command.SendEmail -> {
151+
val intent = Intent(Intent.ACTION_SENDTO)
152+
intent.data = Uri.parse(it.emailAddress)
153+
launchExternalActivity(intent)
154+
}
155+
is Command.SendSms -> {
156+
val intent = Intent(Intent.ACTION_SENDTO, Uri.parse("smsto:${it.telephoneNumber}"))
157+
startActivity(intent)
158+
}
159+
Command.ShowKeyboard -> {
160+
omnibarTextInput.postDelayed({omnibarTextInput.showKeyboard()}, 300)
161+
}
162+
Command.HideKeyboard -> {
163+
omnibarTextInput.hideKeyboard()
164+
focusDummy.requestFocus()
165+
}
166+
Command.ReinitialiseWebView -> {
167+
webView.clearHistory()
168+
}
169+
}
170+
}
171+
164172
private fun configureAutoComplete() {
165173
autoCompleteSuggestionsList.layoutManager = LinearLayoutManager(this)
166174
autoCompleteSuggestionsAdapter = BrowserAutoCompleteSuggestionsAdapter(
@@ -288,8 +296,6 @@ class BrowserActivity : DuckDuckGoActivity(), BookmarkDialogCreationListener {
288296
}
289297

290298
private fun userEnteredQuery(query: String) {
291-
omnibarTextInput.hideKeyboard()
292-
focusDummy.requestFocus()
293299
viewModel.onUserSubmittedQuery(query)
294300
}
295301

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

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,15 @@ class BrowserViewModel(
7777
)
7878

7979
sealed class Command {
80-
class LandingPage : Command()
81-
class Refresh : Command()
80+
object LandingPage : Command()
81+
object Refresh : Command()
8282
class Navigate(val url: String) : Command()
8383
class DialNumber(val telephoneNumber: String) : Command()
8484
class SendSms(val telephoneNumber: String) : Command()
8585
class SendEmail(val emailAddress: String) : Command()
86-
class ShowKeyboard : Command()
87-
class ReinitialiseWebView : Command()
86+
object ShowKeyboard : Command()
87+
object HideKeyboard : Command()
88+
object ReinitialiseWebView : Command()
8889
}
8990

9091
/* Observable data for Activity to subscribe to */
@@ -109,7 +110,7 @@ class BrowserViewModel(
109110
private var appConfigurationDownloaded = false
110111

111112
init {
112-
command.value = Command.ShowKeyboard()
113+
command.value = Command.ShowKeyboard
113114
viewState.value = ViewState(canAddBookmarks = false)
114115
appConfigurationObservable.observeForever(appConfigurationObserver)
115116

@@ -150,6 +151,8 @@ class BrowserViewModel(
150151
return
151152
}
152153

154+
command.value = Command.HideKeyboard
155+
153156
val trimmedInput = input.trim()
154157
url.value = buildUrl(trimmedInput)
155158
viewState.value = currentViewState().copy(
@@ -294,14 +297,14 @@ class BrowserViewModel(
294297
*/
295298
fun userDismissedKeyboard(): Boolean {
296299
if (!currentViewState().browserShowing) {
297-
command.value = Command.LandingPage()
300+
command.value = Command.LandingPage
298301
return true
299302
}
300303
return false
301304
}
302305

303306
fun receivedDashboardResult(resultCode: Int) {
304-
if (resultCode == RELOAD_RESULT_CODE) command.value = Command.Refresh()
307+
if (resultCode == RELOAD_RESULT_CODE) command.value = Command.Refresh
305308
}
306309

307310
@WorkerThread

0 commit comments

Comments
 (0)