Skip to content

Commit 691e34f

Browse files
authored
update Duck.ai icon (omnibar) click behavior (#6724)
Task/Issue URL: https://app.asana.com/1/137249556945/project/1208671518894266/task/1210888855345532?focus=true ### Description Simplifies behavior of the Duck.ai button in the omnibar. If the button is clicked while the omnibar has focus, start a new chat and auto-prompt Duck.ai with contents of the omnibar. If the buttons is clicked withe the omnibar doesn't have focus, open existing chat if within 60 minutes of starting it, otherwise, open a new empty chat. The only exception is New Tab Page which still opens the existing chat (if within 60 minutes since starting it) when omnibar is focused and empty. ### Steps to test this PR - [x] Open Duck.ai and start a new chat. - [ ] Go to New Tab Page. - [x] While omnibar bar **is** focused, click Duck.ai button and verify that the previous chat is opened. - [x] While omnibar **is not** focused, click Duck.ai button and verify that the previous chat is opened. - [x] Type anything into the omnibar and while omnibar bar **is** focused, click Duck.ai button and verify that a new chat is opened with auto-prompt. - [x] Go to SERP. - [x] While omnibar bar **is** focused, click Duck.ai button and verify that a new chat is opened with auto-prompt. - [x] While omnibar bar **is not** focused, click Duck.ai button and verify that the previous chat is opened. - [x] Go to a website. - [x] While omnibar bar **is** focused, click Duck.ai button and verify that a new chat is opened with auto-prompt. - [x] While omnibar bar **is not** focused, click Duck.ai button and verify that the previous chat is opened. - [x] (optional) Change device's time to > 1 hour into the future. - [x] While omnibar bar **is not** focused, click Duck.ai button and verify that a new empty chat is opened.
1 parent 412ca7f commit 691e34f

File tree

3 files changed

+58
-219
lines changed

3 files changed

+58
-219
lines changed

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

Lines changed: 45 additions & 167 deletions
Original file line numberDiff line numberDiff line change
@@ -6217,9 +6217,51 @@ class BrowserTabViewModelTest {
62176217
}
62186218

62196219
@Test
6220-
fun whenOnDuckChatOmnibarButtonClickedThenOpenDuckChat() {
6221-
testee.onDuckChatOmnibarButtonClicked("example")
6222-
verify(mockDuckChat).openDuckChatWithAutoPrompt("example")
6220+
fun whenOnDuckChatOmnibarButtonClickedWithFocusThenOpenDuckChatWithAutoPrompt() {
6221+
testee.onDuckChatOmnibarButtonClicked(query = "example", hasFocus = true, isNtp = false)
6222+
verify(mockDuckChat).openDuckChatWithAutoPrompt(query = "example")
6223+
}
6224+
6225+
@Test
6226+
fun whenOnDuckChatOmnibarButtonClickedWithoutFocusThenOpenDuckChat() {
6227+
testee.onDuckChatOmnibarButtonClicked(query = "example", hasFocus = false, isNtp = false)
6228+
verify(mockDuckChat).openDuckChat()
6229+
}
6230+
6231+
@Test
6232+
fun whenOnDuckChatOmnibarButtonClickedWithNullQueryAndFocusThenOpenDuckChatWithAutoPrompt() {
6233+
testee.onDuckChatOmnibarButtonClicked(query = null, hasFocus = true, isNtp = false)
6234+
verify(mockDuckChat).openDuckChatWithAutoPrompt(query = "")
6235+
}
6236+
6237+
@Test
6238+
fun whenOnDuckChatOmnibarButtonClickedWithNullQueryWithoutFocusThenOpenDuckChat() {
6239+
testee.onDuckChatOmnibarButtonClicked(query = null, hasFocus = false, isNtp = false)
6240+
verify(mockDuckChat).openDuckChat()
6241+
}
6242+
6243+
@Test
6244+
fun whenOnDuckChatOmnibarButtonClickedWhenOnNtpWithNullQueryAndWithFocusThenOpenDuckChat() {
6245+
testee.onDuckChatOmnibarButtonClicked(query = null, hasFocus = true, isNtp = true)
6246+
verify(mockDuckChat).openDuckChat()
6247+
}
6248+
6249+
@Test
6250+
fun whenOnDuckChatOmnibarButtonClickedWhenOnNtpWithBlankQueryAndWithFocusThenOpenDuckChat() {
6251+
testee.onDuckChatOmnibarButtonClicked(query = " ", hasFocus = true, isNtp = true)
6252+
verify(mockDuckChat).openDuckChat()
6253+
}
6254+
6255+
@Test
6256+
fun whenOnDuckChatOmnibarButtonClickedWhenOnNtpWithQueryAndWithFocusThenOpenDuckChatWithAutoPrompt() {
6257+
testee.onDuckChatOmnibarButtonClicked(query = "example", hasFocus = true, isNtp = true)
6258+
verify(mockDuckChat).openDuckChatWithAutoPrompt(query = "example")
6259+
}
6260+
6261+
@Test
6262+
fun whenOnDuckChatOmnibarButtonClickedWhenOnNtpWithQueryAndWithoutFocusThenOpenDuckChat() {
6263+
testee.onDuckChatOmnibarButtonClicked(query = "example", hasFocus = false, isNtp = true)
6264+
verify(mockDuckChat).openDuckChat()
62236265
}
62246266

62256267
@Test
@@ -6483,91 +6525,6 @@ class BrowserTabViewModelTest {
64836525
verify(mockSiteHttpErrorHandler).assignErrorsAndClearCache(site)
64846526
}
64856527

6486-
@Test
6487-
fun whenOpenDuckChatWithNonEmptyQueryThenOpenWithAutoPrompt() = runTest {
6488-
val query = "example"
6489-
6490-
testee.openDuckChat("example")
6491-
6492-
verify(mockDuckChat).openDuckChatWithAutoPrompt(query)
6493-
verify(mockDuckChat, never()).openDuckChat()
6494-
}
6495-
6496-
@Test
6497-
fun whenOpenDuckChatWithEmptyStringQueryThenOpenDuckChat() = runTest {
6498-
testee.openDuckChat("")
6499-
6500-
verify(mockDuckChat).openDuckChat()
6501-
verify(mockDuckChat, never()).openDuckChatWithAutoPrompt(any())
6502-
}
6503-
6504-
@Test
6505-
fun whenOpenDuckChatWithNullQueryThenOpenDuckChat() = runTest {
6506-
testee.openDuckChat(null)
6507-
6508-
verify(mockDuckChat).openDuckChat()
6509-
verify(mockDuckChat, never()).openDuckChatWithAutoPrompt(any())
6510-
}
6511-
6512-
@Test
6513-
fun whenOpenDuckChatWithQueryEqualToUrlThenOpenDuckChat() = runTest {
6514-
val url = "https://example.com"
6515-
loadUrl(url)
6516-
6517-
testee.openDuckChat(url)
6518-
6519-
verify(mockDuckChat).openDuckChat()
6520-
verify(mockDuckChat, never()).openDuckChatWithAutoPrompt(any())
6521-
}
6522-
6523-
@Test
6524-
fun whenOpenDuckChatWithLastSubmittedUserQueryThenOpenDuckChatWithQuery() = runTest {
6525-
val query = "example"
6526-
testee.setLastSubmittedUserQuery(query)
6527-
6528-
testee.openDuckChat(query)
6529-
6530-
verify(mockDuckChat).openDuckChatWithPrefill(query)
6531-
verify(mockDuckChat, never()).openDuckChat()
6532-
verify(mockDuckChat, never()).openDuckChatWithAutoPrompt(any())
6533-
}
6534-
6535-
@Test
6536-
fun whenLastSubmittedUserQueryIsNullAndOmnibarHasSameTextThenOpenDuckChatWithAutoPrompt() = runTest {
6537-
val query = "example"
6538-
testee.omnibarViewState.value = omnibarViewState().copy(omnibarText = "example", queryOrFullUrl = "example")
6539-
6540-
testee.openDuckChat(query)
6541-
6542-
verify(mockDuckChat).openDuckChatWithPrefill(query)
6543-
verify(mockDuckChat, never()).openDuckChatWithAutoPrompt(any())
6544-
}
6545-
6546-
@Test
6547-
fun whenLastSubmittedUserQueryIsNullAndOmnibarHasNewTextThenOpenDuckChatWithAutoPrompt() = runTest {
6548-
val query = "example"
6549-
testee.omnibarViewState.value = omnibarViewState().copy(omnibarText = "foo", queryOrFullUrl = "foo")
6550-
6551-
testee.openDuckChat(query)
6552-
6553-
verify(mockDuckChat).openDuckChatWithAutoPrompt(query)
6554-
verify(mockDuckChat, never()).openDuckChat()
6555-
}
6556-
6557-
@Test
6558-
fun whenLastSubmittedUserQueryDiffersFromNewQueryThenOpenWithAutoPrompt() = runTest {
6559-
val query = "example"
6560-
testee.setLastSubmittedUserQuery("foo")
6561-
testee.setLastSubmittedUserChatQuery("foo")
6562-
testee.omnibarViewState.value = omnibarViewState().copy(omnibarText = "")
6563-
6564-
testee.openDuckChat(query)
6565-
6566-
verify(mockDuckChat).openDuckChatWithAutoPrompt(query)
6567-
verify(mockDuckChat, never()).openDuckChat()
6568-
verify(mockDuckChat, never()).openDuckChatWithPrefill(query)
6569-
}
6570-
65716528
@Test
65726529
fun whenProcessJsCallbackMessageForSubscriptionsThenSendCommand() = runTest {
65736530
val jsCallbackData = JsCallbackData(JSONObject(), "", "", "")
@@ -6770,85 +6727,6 @@ class BrowserTabViewModelTest {
67706727
assertFalse(loadingViewState().isLoading)
67716728
}
67726729

6773-
@Test
6774-
fun whenOpeningDuckChatWithMatchingQueryOrFullUrlValueThenOpenDuckChat() = runTest {
6775-
val query = "example"
6776-
testee.omnibarViewState.value = omnibarViewState().copy(omnibarText = query, queryOrFullUrl = query)
6777-
6778-
testee.openDuckChat(query)
6779-
6780-
verify(mockDuckChat).openDuckChatWithPrefill(query)
6781-
verify(mockDuckChat, never()).openDuckChat()
6782-
verify(mockDuckChat, never()).openDuckChatWithAutoPrompt(any())
6783-
}
6784-
6785-
@Test
6786-
fun whenOpeningDuckChatWithDifferentQueryOrFullUrlValueThenOpenDuckChatWithAutoPrompt() = runTest {
6787-
val query = "example"
6788-
testee.omnibarViewState.value = omnibarViewState().copy(omnibarText = "something else", queryOrFullUrl = "something else")
6789-
testee.setLastSubmittedUserQuery("test")
6790-
testee.setLastSubmittedUserChatQuery("test")
6791-
6792-
testee.openDuckChat(query)
6793-
6794-
verify(mockDuckChat).openDuckChatWithAutoPrompt(query)
6795-
verify(mockDuckChat, never()).openDuckChatWithPrefill(any())
6796-
verify(mockDuckChat, never()).openDuckChat()
6797-
}
6798-
6799-
@Test
6800-
fun whenOpeningDuckChatWithoutSubmittingAPreviousSearchThenOpenDuckChatWithPrefill() = runTest {
6801-
val query = "example"
6802-
testee.omnibarViewState.value = omnibarViewState().copy(omnibarText = "example", queryOrFullUrl = "example")
6803-
6804-
testee.openDuckChat(query)
6805-
6806-
verify(mockDuckChat).openDuckChatWithPrefill(query)
6807-
verify(mockDuckChat, never()).openDuckChatWithAutoPrompt(any())
6808-
verify(mockDuckChat, never()).openDuckChat()
6809-
}
6810-
6811-
@Test
6812-
fun whenOpeningDuckChatChangingOmnibarThenOpenDuckChatWithAutoPrompt() = runTest {
6813-
val query = "example"
6814-
testee.omnibarViewState.value = omnibarViewState().copy(omnibarText = "something else", queryOrFullUrl = "something else")
6815-
6816-
testee.openDuckChat(query)
6817-
6818-
verify(mockDuckChat).openDuckChatWithAutoPrompt(query)
6819-
verify(mockDuckChat, never()).openDuckChatWithPrefill(any())
6820-
verify(mockDuckChat, never()).openDuckChat()
6821-
}
6822-
6823-
@Test
6824-
fun whenOpeningDuckChatAfterSubmittingASearchThenOpenDuckChatWithPrefill() = runTest {
6825-
val query = "example"
6826-
testee.omnibarViewState.value = omnibarViewState().copy(omnibarText = "example", queryOrFullUrl = "example")
6827-
6828-
testee.setLastSubmittedUserQuery("test")
6829-
6830-
testee.openDuckChat(query)
6831-
6832-
verify(mockDuckChat).openDuckChatWithPrefill(query)
6833-
verify(mockDuckChat, never()).openDuckChatWithAutoPrompt(any())
6834-
verify(mockDuckChat, never()).openDuckChat()
6835-
}
6836-
6837-
@Test
6838-
fun whenOpeningDuckChatAfterSubmittingASearchAndChatThenOpenDuckChatWithAutoPrompt() = runTest {
6839-
val query = "example"
6840-
testee.omnibarViewState.value = omnibarViewState().copy(omnibarText = "example", queryOrFullUrl = "example")
6841-
6842-
testee.setLastSubmittedUserQuery("test")
6843-
testee.setLastSubmittedUserChatQuery("test")
6844-
6845-
testee.openDuckChat(query)
6846-
6847-
verify(mockDuckChat).openDuckChatWithAutoPrompt(query)
6848-
verify(mockDuckChat, never()).openDuckChatWithPrefill(any())
6849-
verify(mockDuckChat, never()).openDuckChat()
6850-
}
6851-
68526730
@Test
68536731
fun whenNavigatingThenQueryOrFullUrlIsPreserved() = runTest {
68546732
loadUrl(EXAMPLE_URL)

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,8 +1208,8 @@ class BrowserTabFragment :
12081208
voiceSearchLauncher.launch(requireActivity())
12091209
}
12101210

1211-
private fun onOmnibarDuckChatPressed(query: String) {
1212-
viewModel.onDuckChatOmnibarButtonClicked(query)
1211+
private fun onOmnibarDuckChatPressed(query: String, hasFocus: Boolean, isNtp: Boolean) {
1212+
viewModel.onDuckChatOmnibarButtonClicked(query = query, hasFocus = hasFocus, isNtp = isNtp)
12131213
}
12141214

12151215
private fun configureCustomTab() {
@@ -2897,7 +2897,9 @@ class BrowserTabFragment :
28972897
pixel.fire(DuckChatPixelName.DUCK_CHAT_EXPERIMENTAL_LEGACY_OMNIBAR_AICHAT_BUTTON_PRESSED)
28982898
pixel.fire(DuckChatPixelName.DUCK_CHAT_EXPERIMENTAL_LEGACY_OMNIBAR_AICHAT_BUTTON_PRESSED_DAILY, type = Daily())
28992899
}
2900-
onOmnibarDuckChatPressed(omnibar.getText())
2900+
val hasFocus = omnibar.omnibarTextInput.hasFocus()
2901+
val isNtp = omnibar.viewMode == ViewMode.NewTab
2902+
onOmnibarDuckChatPressed(query = omnibar.getText(), hasFocus = hasFocus, isNtp = isNtp)
29012903
}
29022904
},
29032905
)
@@ -2990,7 +2992,6 @@ class BrowserTabFragment :
29902992
}
29912993

29922994
private fun userEnteredQuery(query: String) {
2993-
viewModel.setLastSubmittedUserQuery(query)
29942995
viewModel.onUserSubmittedQuery(query)
29952996
}
29962997

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

Lines changed: 8 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -581,8 +581,6 @@ class BrowserTabViewModel @Inject constructor(
581581
private var isProcessingTrackingLink = false
582582
private var isLinkOpenedInNewTab = false
583583
private var allowlistRefreshTriggerJob: Job? = null
584-
private var lastSubmittedUserQuery: String? = null
585-
private var lastSubmittedChatQuery: String? = null
586584

587585
private val fireproofWebsitesObserver = Observer<List<FireproofWebsiteEntity>> {
588586
browserViewState.value = currentBrowserViewState().copy(isFireproofWebsite = isFireproofWebsite())
@@ -4218,34 +4216,20 @@ class BrowserTabViewModel @Inject constructor(
42184216
fun onDuckChatMenuClicked() {
42194217
viewModelScope.launch {
42204218
command.value = HideKeyboardForChat
4219+
val params = duckChat.createWasUsedBeforePixelParams()
4220+
pixel.fire(DuckChatPixelName.DUCK_CHAT_OPEN_BROWSER_MENU, parameters = params)
42214221
}
4222-
openDuckChat(pixelName = DuckChatPixelName.DUCK_CHAT_OPEN_BROWSER_MENU)
4222+
duckChat.openDuckChat()
42234223
}
42244224

4225-
fun onDuckChatOmnibarButtonClicked(query: String?) {
4225+
fun onDuckChatOmnibarButtonClicked(query: String?, hasFocus: Boolean, isNtp: Boolean) {
42264226
viewModelScope.launch {
42274227
command.value = HideKeyboardForChat
42284228
}
4229-
query?.let {
4230-
openDuckChat(query = query)
4231-
} ?: openDuckChat()
4232-
}
4233-
4234-
private fun openDuckChat(
4235-
pixelName: Pixel.PixelName? = null,
4236-
query: String? = null,
4237-
) {
4238-
viewModelScope.launch {
4239-
if (pixelName != null) {
4240-
val params = duckChat.createWasUsedBeforePixelParams()
4241-
pixel.fire(pixelName, parameters = params)
4242-
}
4243-
4244-
if (query?.isNotEmpty() == true) {
4245-
duckChat.openDuckChatWithAutoPrompt(query)
4246-
} else {
4247-
duckChat.openDuckChat()
4248-
}
4229+
when {
4230+
hasFocus && isNtp && query.isNullOrBlank() -> duckChat.openDuckChat()
4231+
hasFocus -> duckChat.openDuckChatWithAutoPrompt(query ?: "")
4232+
else -> duckChat.openDuckChat()
42494233
}
42504234
}
42514235

@@ -4287,30 +4271,6 @@ class BrowserTabViewModel @Inject constructor(
42874271
}
42884272
}
42894273

4290-
fun openDuckChat(query: String?) {
4291-
when {
4292-
query.isNullOrBlank() || query == url -> duckChat.openDuckChat()
4293-
lastSubmittedUserQuery == null && (query != omnibarViewState.value?.queryOrFullUrl) -> duckChat.openDuckChatWithAutoPrompt(query)
4294-
lastSubmittedUserQuery == null && (query == omnibarViewState.value?.queryOrFullUrl) -> duckChat.openDuckChatWithPrefill(query)
4295-
lastSubmittedChatQuery == null -> duckChat.openDuckChatWithPrefill(query)
4296-
lastSubmittedChatQuery != lastSubmittedUserQuery -> duckChat.openDuckChatWithPrefill(query)
4297-
query == lastSubmittedUserQuery -> duckChat.openDuckChatWithPrefill(query)
4298-
4299-
else -> duckChat.openDuckChatWithAutoPrompt(query)
4300-
}
4301-
if (query != null) {
4302-
setLastSubmittedUserChatQuery(query)
4303-
}
4304-
}
4305-
4306-
fun setLastSubmittedUserQuery(query: String) {
4307-
lastSubmittedUserQuery = query
4308-
}
4309-
4310-
fun setLastSubmittedUserChatQuery(query: String) {
4311-
lastSubmittedChatQuery = query
4312-
}
4313-
43144274
fun onUserSelectedOnboardingDialogOption(
43154275
cta: Cta,
43164276
index: Int?,

0 commit comments

Comments
 (0)