Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,15 @@ import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class DuckChatSettingsViewModel @AssistedInject constructor(
@Assisted duckChatActivityParams: GlobalActivityStarter.ActivityParams,
private val duckChat: DuckChatInternal,
private val pixel: Pixel,
private val inputScreenDiscoveryFunnel: InputScreenDiscoveryFunnel,
private val settingsPageFeature: SettingsPageFeature,
dispatcherProvider: DispatcherProvider,
private val dispatcherProvider: DispatcherProvider,
) : ViewModel() {
private val commandChannel = Channel<Command>(capacity = 1, onBufferOverflow = DROP_OLDEST)
val commands = commandChannel.receiveAsFlow()
Expand Down Expand Up @@ -142,11 +143,19 @@ class DuckChatSettingsViewModel @AssistedInject constructor(

fun duckChatSearchAISettingsClicked() {
viewModelScope.launch {
val hideAiGeneratedImagesOptionEnabled = withContext(dispatcherProvider.io()) {
settingsPageFeature.hideAiGeneratedImagesOption().isEnabled()
}

if (settingsPageFeature.embeddedSettingsWebView().isEnabled()) {
commandChannel.send(
OpenLink(
link = DUCK_CHAT_SEARCH_AI_SETTINGS_LINK_EMBEDDED,
titleRes = if (settingsPageFeature.hideAiGeneratedImagesOption().isEnabled()) {
link = if (hideAiGeneratedImagesOptionEnabled) {
DUCK_CHAT_SEARCH_AI_SETTINGS_LINK_EMBEDDED
} else {
LEGACY_DUCK_CHAT_SEARCH_AI_SETTINGS_LINK_EMBEDDED
},
titleRes = if (hideAiGeneratedImagesOptionEnabled) {
R.string.duckAiSerpSettingsTitle
} else {
R.string.duck_chat_assist_settings_title
Expand Down Expand Up @@ -220,7 +229,10 @@ class DuckChatSettingsViewModel @AssistedInject constructor(
companion object {
const val DUCK_CHAT_LEARN_MORE_LINK = "https://duckduckgo.com/duckduckgo-help-pages/aichat/"
const val DUCK_CHAT_SEARCH_AI_SETTINGS_LINK = "https://duckduckgo.com/settings?ko=-1#aifeatures"
const val DUCK_CHAT_SEARCH_AI_SETTINGS_LINK_EMBEDDED = "https://duckduckgo.com/settings?ko=-1&embedded=1&highlight=kbe#aifeatures"
const val DUCK_CHAT_HIDE_GENERATED_IMAGES_LINK_EMBEDDED = "https://duckduckgo.com/settings?ko=-1&embedded=1&highlight=kbj#aifeatures"
const val LEGACY_DUCK_CHAT_SEARCH_AI_SETTINGS_LINK_EMBEDDED = "https://duckduckgo.com/settings?ko=-1&embedded=1&highlight=kbe#aifeatures"
const val DUCK_CHAT_SEARCH_AI_SETTINGS_LINK_EMBEDDED =
"https://duckduckgo.com/settings?ko=-1&embedded=1&highlight=kbe&hideduckai=1#aifeatures"
const val DUCK_CHAT_HIDE_GENERATED_IMAGES_LINK_EMBEDDED =
"https://duckduckgo.com/settings?ko=-1&embedded=1&highlight=kbj&hideduckai=1#aifeatures"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -285,10 +285,12 @@ class DuckChatSettingsViewModelTest {
}

@Test
fun whenDuckChatSearchAISettingsClickedAndSaveAndExitEnabledThenOpenSettingsLinkWithReturnParamEmitted() =
fun whenDuckChatSearchAISettingsClickedAndEmbeddedEnabledAndHideAiGeneratedImagesDisabledThenOpenSettingsLinkWithLegacyLink() =
runTest {
@Suppress("DenyListedApi")
settingsPageFeature.embeddedSettingsWebView().setRawStoredState(State(enable = true))
@Suppress("DenyListedApi")
settingsPageFeature.hideAiGeneratedImagesOption().setRawStoredState(State(enable = false))

testee.duckChatSearchAISettingsClicked()

Expand All @@ -297,14 +299,46 @@ class DuckChatSettingsViewModelTest {
assertTrue(command is OpenLink)
command as OpenLink
assertEquals(
DuckChatSettingsViewModel.DUCK_CHAT_SEARCH_AI_SETTINGS_LINK_EMBEDDED,
DuckChatSettingsViewModel.LEGACY_DUCK_CHAT_SEARCH_AI_SETTINGS_LINK_EMBEDDED,
command.link,
)
assertEquals(R.string.duck_chat_assist_settings_title, command.titleRes)
cancelAndIgnoreRemainingEvents()
}
}

@Test
fun whenDuckChatSearchAISettingsClickedAndEmbeddedEnabledAndHideAiGeneratedImagesEnabledThenOpenSettingsLinkWithNewLink() =
runTest {
@Suppress("DenyListedApi")
settingsPageFeature.embeddedSettingsWebView().setRawStoredState(State(enable = true))
@Suppress("DenyListedApi")
settingsPageFeature.hideAiGeneratedImagesOption().setRawStoredState(State(enable = true))

testee = DuckChatSettingsViewModel(
duckChatActivityParams = DuckChatSettingsNoParams,
duckChat = duckChat,
pixel = mockPixel,
inputScreenDiscoveryFunnel = mockInputScreenDiscoveryFunnel,
settingsPageFeature = settingsPageFeature,
dispatcherProvider = coroutineRule.testDispatcherProvider,
)

testee.duckChatSearchAISettingsClicked()

testee.commands.test {
val command = awaitItem()
assertTrue(command is OpenLink)
command as OpenLink
assertEquals(
DuckChatSettingsViewModel.DUCK_CHAT_SEARCH_AI_SETTINGS_LINK_EMBEDDED,
command.link,
)
assertEquals(R.string.duckAiSerpSettingsTitle, command.titleRes)
cancelAndIgnoreRemainingEvents()
}
}

@Test
fun `when onDuckChatUserEnabledToggled true then enabled pixel fired`() =
runTest {
Expand Down Expand Up @@ -557,4 +591,22 @@ class DuckChatSettingsViewModelTest {
testee.onDuckAiHideAiGeneratedImagesClicked()
verify(mockPixel).fire(DuckChatPixelName.SERP_SETTINGS_OPEN_HIDE_AI_GENERATED_IMAGES)
}

@Test
fun `when onDuckAiHideAiGeneratedImagesClicked then OpenLink command with correct link is emitted`() =
runTest {
testee.onDuckAiHideAiGeneratedImagesClicked()

testee.commands.test {
val command = awaitItem()
assertTrue(command is OpenLink)
command as OpenLink
assertEquals(
DuckChatSettingsViewModel.DUCK_CHAT_HIDE_GENERATED_IMAGES_LINK_EMBEDDED,
command.link,
)
assertEquals(R.string.duckAiSerpSettingsTitle, command.titleRes)
cancelAndIgnoreRemainingEvents()
}
}
}
Loading