diff --git a/.maestro/input_screen/input_screen_chat_mode.yaml b/.maestro/input_screen/input_screen_chat_mode.yaml
index 9bb47b39c6a4..feb1f9c6e0d3 100644
--- a/.maestro/input_screen/input_screen_chat_mode.yaml
+++ b/.maestro/input_screen/input_screen_chat_mode.yaml
@@ -14,9 +14,7 @@ tags:
# enable the Input Screen
- runFlow: ../shared/open_ai_settings_screen.yaml
- tapOn:
- id: "trailingSwitch"
- childOf:
- id: "duckAiInputScreenEnabledToggle"
+ id: "duckAiInputScreenToggleWithAiImage"
- action: back
- action: back
diff --git a/.maestro/input_screen/input_screen_preference_management.yaml b/.maestro/input_screen/input_screen_preference_management.yaml
index 9d4e82a240b3..2b9844dca081 100644
--- a/.maestro/input_screen/input_screen_preference_management.yaml
+++ b/.maestro/input_screen/input_screen_preference_management.yaml
@@ -20,9 +20,7 @@ tags:
# enable the Input Screen
- runFlow: ../shared/open_ai_settings_screen.yaml
- tapOn:
- id: "trailingSwitch"
- childOf:
- id: "duckAiInputScreenEnabledToggle"
+ id: "duckAiInputScreenToggleWithAiImage"
- action: back
- action: back
diff --git a/.maestro/input_screen/input_screen_search_mode.yaml b/.maestro/input_screen/input_screen_search_mode.yaml
index a9148cd59132..77312593f355 100644
--- a/.maestro/input_screen/input_screen_search_mode.yaml
+++ b/.maestro/input_screen/input_screen_search_mode.yaml
@@ -14,9 +14,7 @@ tags:
# enable the Input Screen
- runFlow: ../shared/open_ai_settings_screen.yaml
- tapOn:
- id: "trailingSwitch"
- childOf:
- id: "duckAiInputScreenEnabledToggle"
+ id: "duckAiInputScreenToggleWithAiImage"
- action: back
- action: back
diff --git a/common/common-ui/src/main/res/drawable/ic_check_accent_24.xml b/common/common-ui/src/main/res/drawable/ic_check_accent_24.xml
new file mode 100644
index 000000000000..2bbf0cf41b5a
--- /dev/null
+++ b/common/common-ui/src/main/res/drawable/ic_check_accent_24.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
diff --git a/common/common-ui/src/main/res/drawable/ic_shape_circle_disabled_24.xml b/common/common-ui/src/main/res/drawable/ic_shape_circle_disabled_24.xml
new file mode 100644
index 000000000000..9e1cde8e666e
--- /dev/null
+++ b/common/common-ui/src/main/res/drawable/ic_shape_circle_disabled_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/common/common-ui/src/main/res/values/design-experiments-colors.xml b/common/common-ui/src/main/res/values/design-experiments-colors.xml
index 9a1da601e848..3a8554671e45 100644
--- a/common/common-ui/src/main/res/values/design-experiments-colors.xml
+++ b/common/common-ui/src/main/res/values/design-experiments-colors.xml
@@ -21,6 +21,9 @@
+
+ @color/blue80
+
#27282A
#333538
@@ -47,6 +50,9 @@
#B8F9F9F9
+
+ @color/white
+
#F2F2F2
#F9F9F9
diff --git a/common/common-ui/src/main/res/values/design-experiments-theming.xml b/common/common-ui/src/main/res/values/design-experiments-theming.xml
index 694d1e0a58e0..e102c73a0266 100644
--- a/common/common-ui/src/main/res/values/design-experiments-theming.xml
+++ b/common/common-ui/src/main/res/values/design-experiments-theming.xml
@@ -40,6 +40,7 @@
- @color/controls_fill_primary_dark
- @color/controls_fill_secondary_dark
- @color/controls_fill_tertiary_dark
+ - @color/controls_decoration_tertiary_dark
- ?attr/daxColorBackground
@@ -83,6 +84,7 @@
- @color/controls_fill_primary_light
- @color/controls_fill_secondary_light
- @color/controls_fill_tertiary_light
+ - @color/controls_decoration_tertiary_light
- ?attr/daxColorBackground
diff --git a/common/common-ui/src/main/res/values/design-system-colors.xml b/common/common-ui/src/main/res/values/design-system-colors.xml
index 3c6e025e93a6..7ad9847e9c6c 100644
--- a/common/common-ui/src/main/res/values/design-system-colors.xml
+++ b/common/common-ui/src/main/res/values/design-system-colors.xml
@@ -60,6 +60,7 @@
+
@@ -74,6 +75,7 @@
+
@@ -191,6 +193,7 @@
#243969EF
#2B55CA
#1E42A4
+ #14307E
#D6000000
#99000000
diff --git a/common/common-ui/src/main/res/values/design-system-theming.xml b/common/common-ui/src/main/res/values/design-system-theming.xml
index b9652a4ea36e..bfeadbe25b27 100644
--- a/common/common-ui/src/main/res/values/design-system-theming.xml
+++ b/common/common-ui/src/main/res/values/design-system-theming.xml
@@ -181,6 +181,7 @@
- @color/white9
- @color/blue30
- @color/yellow50
+ - @color/accent_content_primary_dark
- @color/white12
- @color/white
- @color/blue30_20
@@ -289,6 +290,7 @@
- @color/black9
- @color/blue50
- @color/yellow50
+ - @color/accent_content_primary_light
- @color/black6
- @color/gray85
- @color/blue50_20
diff --git a/duckchat/duckchat-impl/src/main/AndroidManifest.xml b/duckchat/duckchat-impl/src/main/AndroidManifest.xml
index ae960da40092..d653e3642d66 100644
--- a/duckchat/duckchat-impl/src/main/AndroidManifest.xml
+++ b/duckchat/duckchat-impl/src/main/AndroidManifest.xml
@@ -18,10 +18,15 @@
+
+ viewModel.onShowDuckChatInMenuToggled(isChecked)
+ }
+
+ private val addressBarToggleListener =
+ CompoundButton.OnCheckedChangeListener { _, isChecked ->
+ viewModel.onShowDuckChatInAddressBarToggled(isChecked)
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ setContentView(binding.root)
+
+ setupToolbar(binding.includeToolbar.toolbar)
+
+ observeViewModel()
+ }
+
+ private fun observeViewModel() {
+ viewModel.viewState
+ .flowWithLifecycle(lifecycle, Lifecycle.State.RESUMED)
+ .onEach { renderViewState(it) }
+ .launchIn(lifecycleScope)
+ }
+
+ private fun renderViewState(viewState: ViewState) {
+ binding.showDuckAiInMenuToggle.apply {
+ quietlySetIsChecked(viewState.showInBrowserMenu, menuToggleListener)
+ }
+ binding.showDuckAiInAddressBarToggle.apply {
+ isVisible = viewState.shouldShowAddressBarToggle
+ quietlySetIsChecked(viewState.showInAddressBar, addressBarToggleListener)
+ }
+ }
+}
diff --git a/duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/ui/settings/DuckAiShortcutSettingsViewModel.kt b/duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/ui/settings/DuckAiShortcutSettingsViewModel.kt
new file mode 100644
index 000000000000..b311c74fcab5
--- /dev/null
+++ b/duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/ui/settings/DuckAiShortcutSettingsViewModel.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2025 DuckDuckGo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.duckduckgo.duckchat.impl.ui.settings
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.duckduckgo.anvil.annotations.ContributesViewModel
+import com.duckduckgo.di.scopes.ActivityScope
+import com.duckduckgo.duckchat.impl.DuckChatInternal
+import javax.inject.Inject
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.launch
+
+@ContributesViewModel(ActivityScope::class)
+class DuckAiShortcutSettingsViewModel @Inject constructor(
+ private val duckChat: DuckChatInternal,
+) : ViewModel() {
+
+ data class ViewState(
+ val showInBrowserMenu: Boolean = false,
+ val showInAddressBar: Boolean = false,
+ val shouldShowAddressBarToggle: Boolean = false,
+ )
+
+ val viewState = combine(
+ duckChat.observeShowInBrowserMenuUserSetting(),
+ duckChat.observeShowInAddressBarUserSetting(),
+ ) { showInBrowserMenu, showInAddressBar ->
+ ViewState(
+ showInBrowserMenu = showInBrowserMenu,
+ showInAddressBar = showInAddressBar,
+ shouldShowAddressBarToggle = duckChat.isAddressBarEntryPointEnabled(),
+ )
+ }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), ViewState())
+
+ fun onShowDuckChatInMenuToggled(checked: Boolean) {
+ viewModelScope.launch {
+ duckChat.setShowInBrowserMenuUserSetting(checked)
+ }
+ }
+
+ fun onShowDuckChatInAddressBarToggled(checked: Boolean) {
+ viewModelScope.launch {
+ duckChat.setShowInAddressBarUserSetting(checked)
+ }
+ }
+}
diff --git a/duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/ui/DuckChatSettingsActivity.kt b/duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/ui/settings/DuckChatSettingsActivity.kt
similarity index 52%
rename from duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/ui/DuckChatSettingsActivity.kt
rename to duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/ui/settings/DuckChatSettingsActivity.kt
index 1a03b4843d30..28cd6736cc84 100644
--- a/duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/ui/DuckChatSettingsActivity.kt
+++ b/duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/ui/settings/DuckChatSettingsActivity.kt
@@ -14,12 +14,16 @@
* limitations under the License.
*/
-package com.duckduckgo.duckchat.impl.ui
+package com.duckduckgo.duckchat.impl.ui.settings
+import android.content.Intent
+import android.content.res.Configuration
import android.os.Bundle
import android.view.View
import android.widget.CompoundButton
+import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
+import androidx.core.view.updatePadding
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
@@ -27,9 +31,11 @@ import com.duckduckgo.anvil.annotations.ContributeToActivityStarter
import com.duckduckgo.anvil.annotations.InjectWith
import com.duckduckgo.app.statistics.pixels.Pixel
import com.duckduckgo.app.tabs.BrowserNav
+import com.duckduckgo.browser.api.ui.BrowserScreens.FeedbackActivityWithEmptyParams
import com.duckduckgo.browser.api.ui.BrowserScreens.WebViewActivityWithParams
import com.duckduckgo.common.ui.DuckDuckGoActivity
import com.duckduckgo.common.ui.spans.DuckDuckGoClickableSpan
+import com.duckduckgo.common.ui.store.AppTheme
import com.duckduckgo.common.ui.view.addClickableSpan
import com.duckduckgo.common.ui.view.gone
import com.duckduckgo.common.ui.view.show
@@ -39,7 +45,8 @@ import com.duckduckgo.duckchat.api.DuckChatSettingsNoParams
import com.duckduckgo.duckchat.impl.R
import com.duckduckgo.duckchat.impl.databinding.ActivityDuckChatSettingsBinding
import com.duckduckgo.duckchat.impl.pixel.DuckChatPixelName.DUCK_CHAT_SETTINGS_DISPLAYED
-import com.duckduckgo.duckchat.impl.ui.DuckChatSettingsViewModel.ViewState
+import com.duckduckgo.duckchat.impl.ui.settings.DuckChatSettingsViewModel.ViewState
+import com.duckduckgo.mobile.android.R as CommonR
import com.duckduckgo.navigation.api.GlobalActivityStarter
import javax.inject.Inject
import kotlinx.coroutines.flow.launchIn
@@ -57,21 +64,6 @@ class DuckChatSettingsActivity : DuckDuckGoActivity() {
viewModel.onDuckChatUserEnabledToggled(isChecked)
}
- private val inputScreenToggleListener =
- CompoundButton.OnCheckedChangeListener { _, isChecked ->
- viewModel.onDuckAiInputScreenToggled(isChecked)
- }
-
- private val menuToggleListener =
- CompoundButton.OnCheckedChangeListener { _, isChecked ->
- viewModel.onShowDuckChatInMenuToggled(isChecked)
- }
-
- private val addressBarToggleListener =
- CompoundButton.OnCheckedChangeListener { _, isChecked ->
- viewModel.onShowDuckChatInAddressBarToggled(isChecked)
- }
-
@Inject
lateinit var globalActivityStarter: GlobalActivityStarter
@@ -81,6 +73,9 @@ class DuckChatSettingsActivity : DuckDuckGoActivity() {
@Inject
lateinit var pixel: Pixel
+ @Inject
+ lateinit var appTheme: AppTheme
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -107,21 +102,42 @@ class DuckChatSettingsActivity : DuckDuckGoActivity() {
private fun renderViewState(viewState: ViewState) {
if (viewState.isRebrandingAiFeaturesEnabled) {
+ binding.includeToolbar.toolbar.title = getString(R.string.duck_chat_title_rebranding)
+ binding.duckChatSettingsIcon.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_ai_128))
binding.userEnabledDuckChatToggleRebranding.quietlySetIsChecked(viewState.isDuckChatUserEnabled, userEnabledDuckChatToggleListener)
binding.duckChatSettingsTitle.setText(R.string.duck_chat_title_rebranding)
binding.userEnabledDuckChatToggle.gone()
binding.userEnabledDuckChatToggleRebranding.show()
- binding.duckChatToggleSettingsTitle.setText(R.string.duck_chat_show_in_heading_rebranding)
binding.showDuckChatSearchSettingsLink.setPrimaryText(getString(R.string.duck_chat_assist_settings_title_rebranding))
binding.showDuckChatSearchSettingsLink.setSecondaryText(getString(R.string.duck_chat_assist_settings_description_rebranding))
+
+ // align content with the main Duck.ai toggle's text
+ val offset = resources.getDimensionPixelSize(CommonR.dimen.listItemImageContainerSize) +
+ resources.getDimensionPixelSize(CommonR.dimen.keyline_4)
+ val orientation = resources.configuration.orientation
+ binding.duckAiInputScreenToggleContainer.updatePadding(
+ left = if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ 0
+ } else {
+ offset
+ },
+ )
+ binding.duckAiInputScreenDescription.updatePadding(left = offset)
+ binding.duckAiShortcuts.updatePadding(left = offset)
} else {
+ binding.includeToolbar.toolbar.title = getString(R.string.duck_ai_paid_settings_title)
+ binding.duckChatSettingsIcon.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.chat_private_128))
binding.userEnabledDuckChatToggle.quietlySetIsChecked(viewState.isDuckChatUserEnabled, userEnabledDuckChatToggleListener)
binding.duckChatSettingsTitle.setText(R.string.duck_chat_title)
binding.userEnabledDuckChatToggle.show()
binding.userEnabledDuckChatToggleRebranding.gone()
- binding.duckChatToggleSettingsTitle.setText(R.string.duck_chat_show_in_heading)
binding.showDuckChatSearchSettingsLink.setPrimaryText(getString(R.string.duck_chat_assist_settings_title))
binding.showDuckChatSearchSettingsLink.setSecondaryText(getString(R.string.duck_chat_assist_settings_description))
+
+ val offset = 0
+ binding.duckAiInputScreenToggleContainer.updatePadding(left = offset)
+ binding.duckAiInputScreenDescription.updatePadding(left = offset)
+ binding.duckAiShortcuts.updatePadding(left = offset)
}
binding.duckChatSettingsText.addClickableSpan(
@@ -139,24 +155,38 @@ class DuckChatSettingsActivity : DuckDuckGoActivity() {
),
)
- binding.duckAiInputScreenEnabledToggle.apply {
- isVisible = viewState.shouldShowInputScreenToggle
- quietlySetIsChecked(viewState.isInputScreenEnabled, inputScreenToggleListener)
- }
+ binding.duckAiInputScreenToggleContainer.isVisible = viewState.shouldShowInputScreenToggle
+ configureInputScreenToggle(
+ withoutAi = InputScreenToggleButton.WithoutAi(isActive = !viewState.isInputScreenEnabled, appTheme.isLightModeEnabled()),
+ withAi = InputScreenToggleButton.WithAi(isActive = viewState.isInputScreenEnabled, appTheme.isLightModeEnabled()),
+ )
- binding.duckChatToggleSettingsTitle.isVisible = viewState.isDuckChatUserEnabled
+ binding.duckAiInputScreenDescription.isVisible = viewState.shouldShowInputScreenToggle
+ binding.duckAiInputScreenDescription.addClickableSpan(
+ textSequence = getText(R.string.input_screen_user_pref_description),
+ spans = listOf(
+ "share_feedback" to object : DuckDuckGoClickableSpan() {
+ override fun onClick(widget: View) {
+ viewModel.duckAiInputScreenShareFeedbackClicked()
+ }
+ },
+ ),
+ )
- binding.showDuckChatInMenuToggle.apply {
- isVisible = viewState.shouldShowAddressBarToggle
- quietlySetIsChecked(viewState.showInBrowserMenu, menuToggleListener)
- }
- binding.showDuckChatInAddressBarToggle.apply {
- isVisible = viewState.shouldShowAddressBarToggle
- quietlySetIsChecked(viewState.showInAddressBar, addressBarToggleListener)
+ binding.duckAiShortcuts.isVisible = viewState.shouldShowShortcuts
+ binding.duckAiShortcuts.setOnClickListener {
+ viewModel.onDuckAiShortcutsClicked()
}
+
binding.showDuckChatSearchSettingsLink.setOnClickListener {
viewModel.duckChatSearchAISettingsClicked()
}
+ binding.duckAiInputScreenWithoutAiContainer.setOnClickListener {
+ viewModel.onDuckAiInputScreenWithoutAiSelected()
+ }
+ binding.duckAiInputScreenWithAiContainer.setOnClickListener {
+ viewModel.onDuckAiInputScreenWithAiSelected()
+ }
}
private fun processCommand(command: DuckChatSettingsViewModel.Command) {
@@ -173,6 +203,55 @@ class DuckChatSettingsActivity : DuckDuckGoActivity() {
is DuckChatSettingsViewModel.Command.OpenLinkInNewTab -> {
startActivity(browserNav.openInNewTab(this@DuckChatSettingsActivity, command.link))
}
+
+ is DuckChatSettingsViewModel.Command.OpenShortcutSettings -> {
+ val intent = Intent(this, DuckAiShortcutSettingsActivity::class.java)
+ startActivity(intent)
+ }
+
+ is DuckChatSettingsViewModel.Command.LaunchFeedback -> {
+ globalActivityStarter.start(this, FeedbackActivityWithEmptyParams)
+ }
+ }
+ }
+
+ private fun configureInputScreenToggle(
+ withoutAi: InputScreenToggleButton,
+ withAi: InputScreenToggleButton,
+ ) = with(binding) {
+ val context = this@DuckChatSettingsActivity
+ duckAiInputScreenToggleWithoutAiImage.setImageDrawable(ContextCompat.getDrawable(context, withoutAi.imageRes))
+ duckAiInputScreenToggleWithoutAiCheck.setImageDrawable(ContextCompat.getDrawable(context, withoutAi.checkRes))
+
+ duckAiInputScreenToggleWithAiImage.setImageDrawable(ContextCompat.getDrawable(context, withAi.imageRes))
+ duckAiInputScreenToggleWithAiCheck.setImageDrawable(ContextCompat.getDrawable(context, withAi.checkRes))
+ }
+
+ private sealed class InputScreenToggleButton(isActive: Boolean) {
+ abstract val imageRes: Int
+
+ val checkRes: Int = if (isActive) {
+ CommonR.drawable.ic_check_accent_24
+ } else {
+ CommonR.drawable.ic_shape_circle_disabled_24
+ }
+
+ class WithoutAi(isActive: Boolean, isLightMode: Boolean) : InputScreenToggleButton(isActive) {
+ override val imageRes: Int = when {
+ isActive && isLightMode -> R.drawable.searchbox_withoutai_active
+ isActive && !isLightMode -> R.drawable.searchbox_withoutai_active_dark
+ !isActive && isLightMode -> R.drawable.searchbox_withoutai_inactive
+ else -> R.drawable.searchbox_withoutai_inactive_dark
+ }
+ }
+
+ class WithAi(isActive: Boolean, isLightMode: Boolean) : InputScreenToggleButton(isActive) {
+ override val imageRes: Int = when {
+ isActive && isLightMode -> R.drawable.searchbox_withai_active
+ isActive && !isLightMode -> R.drawable.searchbox_withai_active_dark
+ !isActive && isLightMode -> R.drawable.searchbox_withai_inactive
+ else -> R.drawable.searchbox_withai_inactive_dark
+ }
}
}
}
diff --git a/duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/ui/DuckChatSettingsViewModel.kt b/duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/ui/settings/DuckChatSettingsViewModel.kt
similarity index 76%
rename from duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/ui/DuckChatSettingsViewModel.kt
rename to duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/ui/settings/DuckChatSettingsViewModel.kt
index 6c0fd7ed984b..2a8ec919d589 100644
--- a/duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/ui/DuckChatSettingsViewModel.kt
+++ b/duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/ui/settings/DuckChatSettingsViewModel.kt
@@ -14,18 +14,18 @@
* limitations under the License.
*/
-package com.duckduckgo.duckchat.impl.ui
+package com.duckduckgo.duckchat.impl.ui.settings
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.duckduckgo.anvil.annotations.ContributesViewModel
import com.duckduckgo.app.statistics.pixels.Pixel
-import com.duckduckgo.common.ui.experiments.visual.store.ExperimentalThemingDataStore
import com.duckduckgo.di.scopes.ActivityScope
import com.duckduckgo.duckchat.impl.DuckChatInternal
import com.duckduckgo.duckchat.impl.pixel.DuckChatPixelName
-import com.duckduckgo.duckchat.impl.ui.DuckChatSettingsViewModel.Command.OpenLink
-import com.duckduckgo.duckchat.impl.ui.DuckChatSettingsViewModel.Command.OpenLinkInNewTab
+import com.duckduckgo.duckchat.impl.ui.settings.DuckChatSettingsViewModel.Command.OpenLink
+import com.duckduckgo.duckchat.impl.ui.settings.DuckChatSettingsViewModel.Command.OpenLinkInNewTab
+import com.duckduckgo.duckchat.impl.ui.settings.DuckChatSettingsViewModel.Command.OpenShortcutSettings
import com.duckduckgo.subscriptions.api.SubscriptionRebrandingFeatureToggle
import javax.inject.Inject
import kotlinx.coroutines.channels.BufferOverflow.DROP_OLDEST
@@ -40,7 +40,6 @@ import kotlinx.coroutines.launch
class DuckChatSettingsViewModel @Inject constructor(
private val duckChat: DuckChatInternal,
private val pixel: Pixel,
- private val experimentalThemingDataStore: ExperimentalThemingDataStore,
private val rebrandingAiFeaturesEnabled: SubscriptionRebrandingFeatureToggle,
) : ViewModel() {
@@ -50,28 +49,20 @@ class DuckChatSettingsViewModel @Inject constructor(
data class ViewState(
val isDuckChatUserEnabled: Boolean = false,
val isInputScreenEnabled: Boolean = false,
- val showInBrowserMenu: Boolean = false,
- val showInAddressBar: Boolean = false,
+ val shouldShowShortcuts: Boolean = false,
val shouldShowInputScreenToggle: Boolean = false,
- val shouldShowBrowserMenuToggle: Boolean = false,
- val shouldShowAddressBarToggle: Boolean = false,
val isRebrandingAiFeaturesEnabled: Boolean = false,
)
val viewState = combine(
duckChat.observeEnableDuckChatUserSetting(),
duckChat.observeInputScreenUserSettingEnabled(),
- duckChat.observeShowInBrowserMenuUserSetting(),
- duckChat.observeShowInAddressBarUserSetting(),
- ) { isDuckChatUserEnabled, isInputScreenEnabled, showInBrowserMenu, showInAddressBar ->
+ ) { isDuckChatUserEnabled, isInputScreenEnabled ->
ViewState(
isDuckChatUserEnabled = isDuckChatUserEnabled,
isInputScreenEnabled = isInputScreenEnabled,
- showInBrowserMenu = showInBrowserMenu,
- showInAddressBar = showInAddressBar,
+ shouldShowShortcuts = isDuckChatUserEnabled,
shouldShowInputScreenToggle = isDuckChatUserEnabled && duckChat.isInputScreenFeatureAvailable(),
- shouldShowBrowserMenuToggle = isDuckChatUserEnabled,
- shouldShowAddressBarToggle = isDuckChatUserEnabled && duckChat.isAddressBarEntryPointEnabled(),
isRebrandingAiFeaturesEnabled = rebrandingAiFeaturesEnabled.isAIFeaturesRebrandingEnabled(),
)
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), ViewState())
@@ -79,6 +70,8 @@ class DuckChatSettingsViewModel @Inject constructor(
sealed class Command {
data class OpenLink(val link: String) : Command()
data class OpenLinkInNewTab(val link: String) : Command()
+ data object OpenShortcutSettings : Command()
+ data object LaunchFeedback : Command()
}
fun onDuckChatUserEnabledToggled(checked: Boolean) {
@@ -92,17 +85,6 @@ class DuckChatSettingsViewModel @Inject constructor(
}
}
- fun onDuckAiInputScreenToggled(checked: Boolean) {
- viewModelScope.launch {
- if (checked) {
- pixel.fire(DuckChatPixelName.DUCK_CHAT_EXPERIMENTAL_ADDRESS_BAR_SETTING_ON)
- } else {
- pixel.fire(DuckChatPixelName.DUCK_CHAT_EXPERIMENTAL_ADDRESS_BAR_SETTING_OFF)
- }
- duckChat.setInputScreenUserSetting(checked)
- }
- }
-
fun onShowDuckChatInMenuToggled(checked: Boolean) {
viewModelScope.launch {
if (checked) {
@@ -138,6 +120,32 @@ class DuckChatSettingsViewModel @Inject constructor(
}
}
+ fun onDuckAiShortcutsClicked() {
+ viewModelScope.launch {
+ commandChannel.send(OpenShortcutSettings)
+ }
+ }
+
+ fun onDuckAiInputScreenWithoutAiSelected() {
+ viewModelScope.launch {
+ pixel.fire(DuckChatPixelName.DUCK_CHAT_EXPERIMENTAL_ADDRESS_BAR_SETTING_OFF)
+ duckChat.setInputScreenUserSetting(enabled = false)
+ }
+ }
+
+ fun onDuckAiInputScreenWithAiSelected() {
+ viewModelScope.launch {
+ pixel.fire(DuckChatPixelName.DUCK_CHAT_EXPERIMENTAL_ADDRESS_BAR_SETTING_ON)
+ duckChat.setInputScreenUserSetting(enabled = true)
+ }
+ }
+
+ fun duckAiInputScreenShareFeedbackClicked() {
+ viewModelScope.launch {
+ commandChannel.send(Command.LaunchFeedback)
+ }
+ }
+
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"
diff --git a/duckchat/duckchat-impl/src/main/res/drawable/ic_ai_128.xml b/duckchat/duckchat-impl/src/main/res/drawable/ic_ai_128.xml
new file mode 100644
index 000000000000..e25a2f97b39c
--- /dev/null
+++ b/duckchat/duckchat-impl/src/main/res/drawable/ic_ai_128.xml
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/duckchat/duckchat-impl/src/main/res/drawable/searchbox_withai_active.xml b/duckchat/duckchat-impl/src/main/res/drawable/searchbox_withai_active.xml
new file mode 100644
index 000000000000..0b17064478f7
--- /dev/null
+++ b/duckchat/duckchat-impl/src/main/res/drawable/searchbox_withai_active.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/duckchat/duckchat-impl/src/main/res/drawable/searchbox_withai_active_dark.xml b/duckchat/duckchat-impl/src/main/res/drawable/searchbox_withai_active_dark.xml
new file mode 100644
index 000000000000..8ca722a7cc17
--- /dev/null
+++ b/duckchat/duckchat-impl/src/main/res/drawable/searchbox_withai_active_dark.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/duckchat/duckchat-impl/src/main/res/drawable/searchbox_withai_inactive.xml b/duckchat/duckchat-impl/src/main/res/drawable/searchbox_withai_inactive.xml
new file mode 100644
index 000000000000..3c548419585f
--- /dev/null
+++ b/duckchat/duckchat-impl/src/main/res/drawable/searchbox_withai_inactive.xml
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/duckchat/duckchat-impl/src/main/res/drawable/searchbox_withai_inactive_dark.xml b/duckchat/duckchat-impl/src/main/res/drawable/searchbox_withai_inactive_dark.xml
new file mode 100644
index 000000000000..caba46f7a00b
--- /dev/null
+++ b/duckchat/duckchat-impl/src/main/res/drawable/searchbox_withai_inactive_dark.xml
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/duckchat/duckchat-impl/src/main/res/drawable/searchbox_withoutai_active.xml b/duckchat/duckchat-impl/src/main/res/drawable/searchbox_withoutai_active.xml
new file mode 100644
index 000000000000..d1131427e889
--- /dev/null
+++ b/duckchat/duckchat-impl/src/main/res/drawable/searchbox_withoutai_active.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/duckchat/duckchat-impl/src/main/res/drawable/searchbox_withoutai_active_dark.xml b/duckchat/duckchat-impl/src/main/res/drawable/searchbox_withoutai_active_dark.xml
new file mode 100644
index 000000000000..08c42a5f0e41
--- /dev/null
+++ b/duckchat/duckchat-impl/src/main/res/drawable/searchbox_withoutai_active_dark.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/duckchat/duckchat-impl/src/main/res/drawable/searchbox_withoutai_inactive.xml b/duckchat/duckchat-impl/src/main/res/drawable/searchbox_withoutai_inactive.xml
new file mode 100644
index 000000000000..7b31f00c4752
--- /dev/null
+++ b/duckchat/duckchat-impl/src/main/res/drawable/searchbox_withoutai_inactive.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/duckchat/duckchat-impl/src/main/res/drawable/searchbox_withoutai_inactive_dark.xml b/duckchat/duckchat-impl/src/main/res/drawable/searchbox_withoutai_inactive_dark.xml
new file mode 100644
index 000000000000..fafb85ee5911
--- /dev/null
+++ b/duckchat/duckchat-impl/src/main/res/drawable/searchbox_withoutai_inactive_dark.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/duckchat/duckchat-impl/src/main/res/layout/activity_duck_ai_shortcut_settings.xml b/duckchat/duckchat-impl/src/main/res/layout/activity_duck_ai_shortcut_settings.xml
new file mode 100644
index 000000000000..f05eb94cea8d
--- /dev/null
+++ b/duckchat/duckchat-impl/src/main/res/layout/activity_duck_ai_shortcut_settings.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/layout/activity_duck_chat_settings.xml b/duckchat/duckchat-impl/src/main/res/layout/activity_duck_chat_settings.xml
index ff7563496e5a..329910efbc6a 100644
--- a/duckchat/duckchat-impl/src/main/res/layout/activity_duck_chat_settings.xml
+++ b/duckchat/duckchat-impl/src/main/res/layout/activity_duck_chat_settings.xml
@@ -19,7 +19,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
- tools:context=".ui.DuckChatSettingsActivity">
+ tools:context=".ui.settings.DuckChatSettingsActivity">
-
+ android:layout_marginTop="@dimen/keyline_4"
+ android:layout_marginHorizontal="@dimen/keyline_4">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+ android:layout_marginHorizontal="@dimen/keyline_4"
+ android:layout_marginTop="@dimen/keyline_2"
+ android:layout_marginBottom="@dimen/keyline_4"
+ android:text="@string/input_screen_user_pref_description"
+ app:textType="secondary"
+ app:typography="body2" />
-
+ android:visibility="gone"
+ app:primaryText="@string/duck_ai_shortcut_settings_title"
+ app:secondaryText="@string/duck_ai_shortcut_settings_description" />
Duck.ai е незадължителна функция, чрез която можете да разговаряте анонимно с популярни AI чат модели от трети страни. Чатовете Ви не се използват за обучение на AI.\nНаучете повече
Активиране на Duck.ai
- Бързи Връзки
Меню на браузъра
Адресна лента
Настройки на Assist
@@ -50,8 +49,6 @@
Търсене или въвеждане на адрес
Duck.ai
Попитай Duck.ai
- Експериментална адресна лента
- Потърсете в мрежата или попитайте Duck.ai директно от адресната лента
Duck.ai
@@ -64,8 +61,6 @@
Функции с изкуствен интелект
Функциите на DuckDuckGo AI са поверителни и незадължителни.Вашите данни не се използват за обучение на AI.\nНаучете повече
Duck.ai
- Анонимен чат с популярни AI модели на трети страни
- Преки пътища за Duck.ai
Настройки за Assist при търсене
Изберете колко често искате да се появяват отговори, подпомагани от изкуствен интелект, в търсенето
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/values-cs/strings-duckchat.xml b/duckchat/duckchat-impl/src/main/res/values-cs/strings-duckchat.xml
index 0c4e95df7165..5ef8d96db45e 100644
--- a/duckchat/duckchat-impl/src/main/res/values-cs/strings-duckchat.xml
+++ b/duckchat/duckchat-impl/src/main/res/values-cs/strings-duckchat.xml
@@ -39,7 +39,6 @@
Duck.ai je volitelná funkce, která umožňuje anonymně chatovat s populárními AI chatovacími modely třetích stran. Tvoje chaty neslouží k trénování umělé inteligence.\nDalší informace
Povolit službu Duck.ai
- Zkratky
Menu prohlížeče
Adresní řádek
Nastavení funkce Assist
@@ -50,8 +49,6 @@
Vyhledejte nebo zadejte adresu
Duck.ai
Zeptej se Duck.ai
- Experimentální adresní řádek
- Hledej na webu nebo se zeptej Duck.ai přímo v adresním řádku.
Duck.ai
@@ -64,8 +61,6 @@
Funkce AI
Funkce AI na DuckDuckGo jsou soukromé a volitelné.Tvoje data se nepoužívají k trénování umělé inteligence.\nDalší informace
Duck.ai
- S populárními AI modely třetích stran můžeš chatovat anonymně
- Zkratky Duck.ai
Nastavení vyhledávání s funkcí Assist
Vyber, jak často chceš, aby se odpovědi s podporou umělé inteligence zobrazovaly ve tvých vyhledáváních
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/values-da/strings-duckchat.xml b/duckchat/duckchat-impl/src/main/res/values-da/strings-duckchat.xml
index ee21ac651ae9..da48fa695fe5 100644
--- a/duckchat/duckchat-impl/src/main/res/values-da/strings-duckchat.xml
+++ b/duckchat/duckchat-impl/src/main/res/values-da/strings-duckchat.xml
@@ -39,7 +39,6 @@
Duck.ai er en valgfri funktion, der giver dig mulighed for at chatte anonymt med populære tredjeparts AI-chatmodeller. Dine chats bruges ikke til at træne AI.\nLæs mere
Aktiver Duck.ai
- Genveje
Browsermenu
Adresselinje
Assist-indstillinger
@@ -50,8 +49,6 @@
Søg eller indtast adresse
Duck.ai
Spørg Duck.ai
- Eksperimentel adresselinje
- Søg på nettet eller spørg Duck.ai direkte fra adresselinjen
Duck.ai
@@ -64,8 +61,6 @@
AI-funktioner
DuckDuckGo AI-funktioner er private og valgfrie.\nDine data bruges ikke til at træne AI.\nLæs mere
Duck.ai
- Chat anonymt med populære tredjeparts AI-chatmodeller
- Duck.ai-genveje
Indstillinger for Search Assist
Vælg, hvor ofte du vil have AI-assisterede svar til at optræde i dine søgninger
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/values-de/strings-duckchat.xml b/duckchat/duckchat-impl/src/main/res/values-de/strings-duckchat.xml
index d8fce7407d23..6f47e9c615bc 100644
--- a/duckchat/duckchat-impl/src/main/res/values-de/strings-duckchat.xml
+++ b/duckchat/duckchat-impl/src/main/res/values-de/strings-duckchat.xml
@@ -39,7 +39,6 @@
Duck.ai ist eine optionale Funktion, mit der du anonym mit beliebten KI-Chatmodellen von Drittanbietern chatten kannst. Deine Chats werden nicht zum Trainieren von KI verwendet.\nMehr erfahren
Aktiviere Duck.ai
- Shortcuts
Browsermenü
Adresszeile
Assist-Einstellungen
@@ -50,8 +49,6 @@
Adresse suchen oder eingeben
Duck.ai
Frag Duck.ai
- Experimentelle Adressleiste
- Suche im Web oder frag Duck.ai direkt über die Adressleiste
Duck.ai
@@ -64,8 +61,6 @@
KI-Funktionen
Die KI-Funktionen von DuckDuckGo sind privat und optional.\nIhre Daten werden nicht zum Trainieren von KI verwendet.\nMehr erfahren
Duck.ai
- Chatte anonym mit beliebten KI-Chatmodellen von Drittanbietern
- Duck.ai-Shortcuts
Such-Assist-Einstellungen
Du kannst auswählen, wie oft KI-gestützte Antworten in deinen Suchergebnissen angezeigt werden sollen.
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/values-el/strings-duckchat.xml b/duckchat/duckchat-impl/src/main/res/values-el/strings-duckchat.xml
index a9a32a6729a3..f9dfe1e6fe78 100644
--- a/duckchat/duckchat-impl/src/main/res/values-el/strings-duckchat.xml
+++ b/duckchat/duckchat-impl/src/main/res/values-el/strings-duckchat.xml
@@ -39,7 +39,6 @@
Το Duck.ai αποτελεί προαιρετική λειτουργία που σας επιτρέπει να συνομιλείτε ανώνυμα με δημοφιλή μοντέλα τρίτων για συνομιλία μέσω τεχνητής νοημοσύνης. Οι συνομιλίες σας δεν χρησιμοποιούνται για την εκπαίδευση τεχνητής συνομιλίας.\nΜάθετε περισσότερα
Ενεργοποίηση του Duck.ai
- Συντομευσεις
Μενού προγράμματος περιήγησης
Γραμμή διευθύνσεων
Ρυθμίσεις Assist
@@ -50,8 +49,6 @@
Αναζήτηση ή εισαγωγή διεύθυνσης
Duck.ai
Ρωτήστε το Duck.ai
- Πειραματική γραμμή διευθύνσεων
- Κάντε αναζήτηση στο διαδίκτυο ή ρωτήστε το Duck.ai απευθείας από τη Γραμμή διευθύνσεων
Duck.ai
@@ -64,8 +61,6 @@
Λειτουργίες τεχνητής νοημοσύνης
Οι λειτουργίες τεχνητής νοημοσύνης του DuckDuckGo είναι ιδιωτικές και προαιρετικές.Τα δεδομένα σας δεν χρησιμοποιούνται για εκπαίδευση της τεχνητής νοημοσύνης.\nΜάθετε περισσότερα
Duck.ai
- Συνομίλησε ανώνυμα με δημοφιλή μοντέλα συνομιλίας μέσω τεχνητής νοημοσύνης, τρίτων μερών
- Συντομεύσεις Duck.ai
Ρυθμίσεις αναζήτησης Assist
Επιλέξτε πόσο συχνά θέλετε να εμφανίζονται οι απαντήσεις που υποστηρίζονται από τεχνητή νοημοσύνη στις αναζητήσεις σας
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/values-es/strings-duckchat.xml b/duckchat/duckchat-impl/src/main/res/values-es/strings-duckchat.xml
index d01cb3e678b6..07b538032318 100644
--- a/duckchat/duckchat-impl/src/main/res/values-es/strings-duckchat.xml
+++ b/duckchat/duckchat-impl/src/main/res/values-es/strings-duckchat.xml
@@ -39,7 +39,6 @@
Duck.ai es una función opcional que te permite chatear de forma anónima con modelos populares de chat de IA de terceros. Tus chats no se utilizan para entrenar la IA.\nMás información
Activa Duck.ai
- Accesos directos
Menú del navegador
Barra de direcciones
Ajustes de Assist
@@ -50,8 +49,6 @@
Buscar o introducir dirección
Duck.ai
Pregúntale a Duck.ai
- Barra de direcciones experimental
- Busca en la web o pregúntale a Duck.ai directamente desde la barra de direcciones
Duck.ai
@@ -64,8 +61,6 @@
Características de la IA
Las funciones de IA de DuckDuckGo son privadas y opcionales.Tus datos no se utilizan para entrenar la IA.\nMás información
Duck.ai
- Chatea de forma anónima con modelos de chat de IA populares de terceros
- Atajos de Duck.ai
Configuración de Asistente de búsqueda
Elige con qué frecuencia deseas que las respuestas asistidas por IA aparezcan en tus búsquedas
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/values-et/strings-duckchat.xml b/duckchat/duckchat-impl/src/main/res/values-et/strings-duckchat.xml
index 6e60eb7c3c32..0f5c674e2233 100644
--- a/duckchat/duckchat-impl/src/main/res/values-et/strings-duckchat.xml
+++ b/duckchat/duckchat-impl/src/main/res/values-et/strings-duckchat.xml
@@ -39,7 +39,6 @@
Duck.ai on valikuline funktsioon, mis võimaldab anonüümselt vestelda populaarsete kolmanda poole AI vestlusmudelitega. Teie vestlusi ei kasutata tehisintellekti treenimiseks.\nLisateave
Luba Duck.ai
- Otseteed
Brauseri menüü
Aadressiriba
Assisti seaded
@@ -50,8 +49,6 @@
Otsi või sisesta aadress
Duck.ai
Küsi Duck.ai käest
- Eksperimentaalne aadressiriba
- Otsi veebist või küsi Duck.ai-lt otse aadressiribal
Duck.ai
@@ -64,8 +61,6 @@
AI funktsioonid
DuckDuckGo tehisintellekti funktsioonid on privaatsed ja valikulised.Sinu andmeid ei kasutata tehisintellekti treenimiseks.\nLisateave
Duck.ai
- Vestle anonüümselt populaarsete kolmanda osapoole tehisintellekti vestlusmudelitega
- Duck.ai otseteed
Otsingu Assist seaded
Vali, kui tihti soovid, et AI-toega vastused ilmuksid sinu otsingutesse
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/values-fi/strings-duckchat.xml b/duckchat/duckchat-impl/src/main/res/values-fi/strings-duckchat.xml
index 63323c07bf4a..ff2966177f6f 100644
--- a/duckchat/duckchat-impl/src/main/res/values-fi/strings-duckchat.xml
+++ b/duckchat/duckchat-impl/src/main/res/values-fi/strings-duckchat.xml
@@ -39,7 +39,6 @@
Duck.ai on valinnainen ominaisuus, jonka avulla voit keskustella anonyymisti suosittujen kolmannen osapuolen tekoälykeskustelumallien kanssa. Keskustelujasi ei käytetä tekoälyn kouluttamiseen.\nLue lisää
Ota Duck.ai käyttöön
- Pikavalinnat
Selainvalikko
Osoitekenttä
Assist-asetukset
@@ -50,8 +49,6 @@
Hae tai anna osoite
Duck.ai
Kysy Duck.ai:lta
- Kokeellinen osoitekenttä
- Hae verkosta tai kysy Duck.ai:lta kirjoittamalla suoraan osoiteriville
Duck.ai
@@ -64,8 +61,6 @@
Tekoälyominaisuudet
DuckDuckGon tekoälyominaisuudet ovat yksityisiä ja valinnaisia.\nTietojasi ei käytetä tekoälyn kouluttamiseen.\nLue lisää
Duck.ai
- Keskustele nimettömästi suosittujen kolmannen osapuolen tekoälykeskustelumallien kanssa
- Duck.ai-pikakuvakkeet
Search Assist -asetukset
Valitse, kuinka usein haluat tekoälyavusteisten vastausten näkyvän hauissasi
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/values-fr/strings-duckchat.xml b/duckchat/duckchat-impl/src/main/res/values-fr/strings-duckchat.xml
index 669f5a3b10b0..3b7956d3a77b 100644
--- a/duckchat/duckchat-impl/src/main/res/values-fr/strings-duckchat.xml
+++ b/duckchat/duckchat-impl/src/main/res/values-fr/strings-duckchat.xml
@@ -39,7 +39,6 @@
Duck.ai est une fonctionnalité optionnelle qui vous permet de discuter anonymement avec des modèles de chat IA tiers populaires. Vos discussions ne servent pas à entraîner l’IA.\nEn savoir plus
Activer Duck.ai
- Raccourcis
Menu du navigateur
Barre d\'adresse
Paramètres d\'Assist
@@ -50,8 +49,6 @@
Rechercher ou saisir une adresse
Duck.ai
Demandez à Duck.ai
- Barre d\'adresse expérimentale
- Effectuez une recherche sur le Web ou interrogez Duck.ai directement à partir de la barre d’adresse
Duck.ai
@@ -64,8 +61,6 @@
Fonctionnalités de l\'IA
Les fonctionnalités de DuckDuckGo AI sont privées et facultatives.Vos données ne servent pas à entraîner l’IA.\nEn savoir plus
Duck.ai
- Discutez anonymement avec des modèles de chat IA tiers populaires
- Raccourcis Duck.ai
Paramètres de recherche Assist
Choisissez la fréquence à laquelle vous souhaitez que les réponses assistées par l\'IA apparaissent dans vos recherches
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/values-hr/strings-duckchat.xml b/duckchat/duckchat-impl/src/main/res/values-hr/strings-duckchat.xml
index c7b1b8be5efe..8b716c3fab42 100644
--- a/duckchat/duckchat-impl/src/main/res/values-hr/strings-duckchat.xml
+++ b/duckchat/duckchat-impl/src/main/res/values-hr/strings-duckchat.xml
@@ -39,7 +39,6 @@
Duck.ai izborna je značajka koja ti omogućuje anonimno čavrljanje s popularnim AI modelima \'chata\' trećih strana. Tvoja čavrljanja se ne koriste za obuku AI-a.\nSaznaj više
Omogući Duck.ai
- Prečaci
Izbornik preglednika
Adresna traka
Postavke Assista
@@ -50,8 +49,6 @@
Pretraži ili unesi adresu
Duck.ai
Pitaj Duck.ai
- Eksperimentalna adresna traka
- Pretraži mrežu ili pitaj Duck.ai izravno iz adresne trake
Duck.ai
@@ -64,8 +61,6 @@
AI značajke
DuckDuckGo AI značajke privatne su i neobavezne.Tvoji podaci se ne koriste za obuku umjetne inteligencije.\nSaznaj više
Duck.ai
- Anonimno čavrljaj s popularnim modelima umjetne inteligencije trećih strana
- Duck.ai prečaci
Pretraži postavke Assista
Odaberi koliko često želiš da se odgovori potpomognuti umjetnom inteligencijom pojavljuju u tvojim pretraživanjima
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/values-hu/strings-duckchat.xml b/duckchat/duckchat-impl/src/main/res/values-hu/strings-duckchat.xml
index 24988ad2940f..2ce86c4e1f6f 100644
--- a/duckchat/duckchat-impl/src/main/res/values-hu/strings-duckchat.xml
+++ b/duckchat/duckchat-impl/src/main/res/values-hu/strings-duckchat.xml
@@ -39,7 +39,6 @@
A Duck.ai egy opcionális funkció, amely lehetővé teszi a harmadik féltől származó népszerű AI-csevegési modellekkel való névtelen csevegést. A csevegéseidet nem használjuk fel az AI tanítására.\nTovábbi részletek
Duck.ai engedélyezése
- Gyorsparancsok
Böngészési menü
Címsor
Assist-beállítások
@@ -50,8 +49,6 @@
Keresés vagy cím megadása
Duck.ai
Duck.ai kérdezése
- Kísérleti címsor
- Keresés a weben vagy a Duck.ai megkérdezése közvetlenül a címsorból
Duck.ai
@@ -64,8 +61,6 @@
AI funkciók
A DuckDuckGo AI-funkciói privátak és opcionálisak.\nAz adataidat nem használjuk fel az AI tanítására.\nTovábbi részletek
Duck.ai
- Névtelen csevegés harmadik féltől származó népszerű AI-modellekkel
- Duck.ai-gyorsparancsok
Keresési asszisztens beállításai
Válaszd ki, milyen gyakran szeretnél mesterséges intelligenciával generált válaszokat látni a kereséseid során
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/values-it/strings-duckchat.xml b/duckchat/duckchat-impl/src/main/res/values-it/strings-duckchat.xml
index f4c6e7ad86aa..2efad85de650 100644
--- a/duckchat/duckchat-impl/src/main/res/values-it/strings-duckchat.xml
+++ b/duckchat/duckchat-impl/src/main/res/values-it/strings-duckchat.xml
@@ -39,7 +39,6 @@
Duck.ai è una funzionalità opzionale che consente di chattare in forma anonima con i più diffusi modelli di chat AI di terze parti. Le chat non vengono usate per addestrare l\'IA.\nScopri di più
Abilita Duck.ai
- Scorciatoie
Menu del browser
Barra degli indirizzi
Impostazioni di Assist
@@ -50,8 +49,6 @@
Cerca o digita l\'indirizzo
Duck.ai
Chiedi a Duck.ai
- Barra degli indirizzi sperimentale
- Cerca sul web o chiedi a Duck.ai direttamente dalla barra degli indirizzi
Duck.ai
@@ -64,8 +61,6 @@
Funzionalità IA
Le funzionalità AI di DuckDuckGo sono private e opzionali.I tuoi dati non vengono usati per addestrare l\'IA.\nScopri di più
Duck.ai
- Chatta in forma anonima con i più diffusi modelli di chat AI di terze parti
- Scorciatoie Duck.ai
Impostazioni di Search Assist
Scegli la frequenza con cui vuoi che le risposte assistite dall\'intelligenza artificiale appaiano nelle tue ricerche
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/values-lt/strings-duckchat.xml b/duckchat/duckchat-impl/src/main/res/values-lt/strings-duckchat.xml
index 3d587326ae12..6e2e71c86755 100644
--- a/duckchat/duckchat-impl/src/main/res/values-lt/strings-duckchat.xml
+++ b/duckchat/duckchat-impl/src/main/res/values-lt/strings-duckchat.xml
@@ -39,7 +39,6 @@
„Duck.ai“ yra pasirenkama funkcija, leidžianti anonimiškai kalbėtis su populiariais trečiųjų šalių DI pokalbių modeliais. Tavo pokalbiai nenaudojami dirbtinio intelekto mokymui.\nSužinok daugiau
Įjungti „Duck.ai“
- Šaukiniai
Naršyklės meniu
Adreso juosta
„Assist“ nustatymai
@@ -50,8 +49,6 @@
Ieškoti arba įvesti adresą
Duck.ai
Paklausk „Duck.ai“
- Eksperimentinė adreso juosta
- Ieškok internete arba klausk „Duck.ai“ tiesiai iš adreso juostos
Duck.ai
@@ -64,8 +61,6 @@
DI funkcijos
„DuckDuckGo“ DI funkcijos yra privačios ir neprivalomos.Nenaudojame jūsų duomenų dirbtinio intelekto mokymui.\nSužinokite daugiau
Duck.ai
- Kalbėkitės anonimiškai su populiariais trečiųjų šalių DI pokalbių modeliais
- „Duck.ai“ spartieji klavišai
„Assist“ paieškos nustatymai
Pasirink, kaip dažnai nori, kad tavo paieškose būtų rodomi DI generuojami atsakymai
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/values-lv/strings-duckchat.xml b/duckchat/duckchat-impl/src/main/res/values-lv/strings-duckchat.xml
index 3f0300297722..e9434cc1bcf5 100644
--- a/duckchat/duckchat-impl/src/main/res/values-lv/strings-duckchat.xml
+++ b/duckchat/duckchat-impl/src/main/res/values-lv/strings-duckchat.xml
@@ -39,7 +39,6 @@
Duck.ai ir papildu līdzeklis, kas ļauj anonīmi tērzēt ar populāriem trešo pušu Ml tērzēšanas modeļiem. Tavas tērzēšanas sarunas netiek izmantotas AMI apmācībai.\nUzzini vairāk
Iespējot Duck.ai
- Saīsnes
Pārlūka izvēlne
Adreses josla
Assist iestatījumi
@@ -50,8 +49,6 @@
Meklē vai ievadi adresi
Duck.ai
Pajautā Duck.ai
- Eksperimentālā adreses josla
- Meklē tīmeklī vai jautā Duck.ai tieši adrešu joslā
Duck.ai
@@ -64,8 +61,6 @@
Mākslīgā intelekta funkcijas
DuckDuckGo MI funkcijas ir privātas un nav obligātas.Tavi dati netiek izmantoti mākslīgā intelekta apmācībai.\nUzzini vairāk
Duck.ai
- Tērzē anonīmi ar populāriem trešo personu MI tērzēšanas modeļiem
- Duck.ai īsceļi
Meklēšanas Assist iestatījumi
Izvēlies, cik bieži tu vēlies, lai MI atbalstītās atbildes parādītos tavos meklējumos.
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/values-nb/strings-duckchat.xml b/duckchat/duckchat-impl/src/main/res/values-nb/strings-duckchat.xml
index f1b37dafc657..cb89f9793bd6 100644
--- a/duckchat/duckchat-impl/src/main/res/values-nb/strings-duckchat.xml
+++ b/duckchat/duckchat-impl/src/main/res/values-nb/strings-duckchat.xml
@@ -39,7 +39,6 @@
Duck.ai er en valgfri funksjon der du kan chatte anonymt med populære tredjeparts AI-chat-modeller. Chattene dine brukes ikke til å trene AI.\nLes mer
Aktiver Duck.ai
- Snarveier
Nettlesermeny
Adressefelt
Assist-innstillinger
@@ -50,8 +49,6 @@
Søk eller skriv inn adresse
Duck.ai
Spør Duck.ai
- Eksperimentell adresselinje
- Søk på nettet eller spør Duck.ai direkte fra adressefeltet
Duck.ai
@@ -64,8 +61,6 @@
AI-funksjoner
AI-funksjonene i DuckDuckGo er private og valgfrie.\nDataene dine brukes ikke til å trene AI.\nLes mer
Duck.ai
- Chat anonymt med populære tredjeparts AI-chat-modeller
- Duck.ai-snarveier
Innstillinger for Search Assist
Velg hvor ofte du vil at AI-assisterte svar skal vises i søkene dine
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/values-nl/strings-duckchat.xml b/duckchat/duckchat-impl/src/main/res/values-nl/strings-duckchat.xml
index 7064e0d30285..f03d8a563bf5 100644
--- a/duckchat/duckchat-impl/src/main/res/values-nl/strings-duckchat.xml
+++ b/duckchat/duckchat-impl/src/main/res/values-nl/strings-duckchat.xml
@@ -39,7 +39,6 @@
Duck.ai is een optionele functie waarmee je anoniem kunt chatten met populaire AI-chatmodellen van derden. Je chats worden niet gebruikt om AI te trainen.\nMeer informatie
Duck.ai inschakelen
- Sneltoetsen
Browsermenu
Adresbalk
Assist-instellingen
@@ -50,8 +49,6 @@
Zoek of voer een adres in
Duck.ai
Vraag stellen aan Duck.ai
- Experimentele adresbalk
- Zoeken op het web of direct een vraag stellen aan Duck.ai vanuit de adresbalk
Duck.ai
@@ -64,8 +61,6 @@
AI-functies
DuckDuckGo AI-functies zijn privé en optioneel.\nJe gegevens worden niet gebruikt om AI te trainen.\nMeer informatie
Duck.ai
- Chat anoniem met populaire AI-chatmodellen van derden
- Duck.ai-snelkoppelingen
Instellingen voor zoek Assist
Kies hoe vaak antwoorden op basis van AI in je zoekresultaten moeten worden weergegeven
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/values-pl/strings-duckchat.xml b/duckchat/duckchat-impl/src/main/res/values-pl/strings-duckchat.xml
index 9c51c94543f1..93ce8c3afe11 100644
--- a/duckchat/duckchat-impl/src/main/res/values-pl/strings-duckchat.xml
+++ b/duckchat/duckchat-impl/src/main/res/values-pl/strings-duckchat.xml
@@ -39,7 +39,6 @@
Duck.ai to opcjonalna funkcja, która umożliwia prowadzenie anonimowych rozmów z popularnymi modelami czatu AI innych firm. Twoje czaty nie są używane do trenowania AI.\nDowiedz się więcej
Włącz Duck.ai
- Skróty
Menu przeglądarki
Pasek adresu
Ustawienia Assist
@@ -50,8 +49,6 @@
Wyszukaj lub wprowadź adres
Duck.ai
Zapytaj Duck.ai
- Eksperymentalny Pasek Adresu
- Wyszukaj w Internecie lub zapytaj Duck.ai bezpośrednio z paska adresu
Duck.ai
@@ -64,8 +61,6 @@
Funkcje AI
Funkcje sztucznej inteligencji DuckDuckGo są prywatne i opcjonalne.Twoje dane nie są używane do trenowania AI.\nDowiedz się więcej
Duck.ai
- Czatuj anonimowo z popularnymi modelami czatu AI innych firm
- Skróty Duck.ai
Ustawienia wyszukiwania Assist
Wybierz, jak często w wyszukiwaniach mają pojawiać się odpowiedzi wspomagane przez sztuczną inteligencję
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/values-pt/strings-duckchat.xml b/duckchat/duckchat-impl/src/main/res/values-pt/strings-duckchat.xml
index 1c341262469a..7b5cc8ecb1f6 100644
--- a/duckchat/duckchat-impl/src/main/res/values-pt/strings-duckchat.xml
+++ b/duckchat/duckchat-impl/src/main/res/values-pt/strings-duckchat.xml
@@ -39,7 +39,6 @@
O Duck.ai é uma funcionalidade opcional que te permite conversar anonimamente com modelos de chat de IA populares de terceiros. As tuas conversas não são utilizadas para treinar a IA.\nSabe mais
Ativar Duck.ai
- Atalhos
Menu do navegador
Barra de endereço
Definições do Assist
@@ -50,8 +49,6 @@
Pesquisar ou inserir endereço
Duck.ai
Pergunta ao Duck.ai
- Barra de endereços experimental
- Pesquise na web ou pergunte diretamente ao Duck.ai na barra de endereços
Duck.ai
@@ -64,8 +61,6 @@
Funcionalidades de IA
As funcionalidades de IA do DuckDuckGo são privadas e opcionais.Os teus dados não são utilizados para treinar a IA.\nSabe mais
Duck.ai
- Conversa anonimamente com modelos de chat com IA populares de terceiros
- Atalhos Duck.ai
Definições do Assist de pesquisa
Escolhe a frequência com que queres que as respostas assistidas por IA apareçam nas suas pesquisas
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/values-ro/strings-duckchat.xml b/duckchat/duckchat-impl/src/main/res/values-ro/strings-duckchat.xml
index f991e1a26a1c..802af54372ab 100644
--- a/duckchat/duckchat-impl/src/main/res/values-ro/strings-duckchat.xml
+++ b/duckchat/duckchat-impl/src/main/res/values-ro/strings-duckchat.xml
@@ -39,7 +39,6 @@
Duck.ai este o caracteristică opțională care îți permite să discuți anonim cu modele populare de chat AI de la terțe părți. Chaturile tale nu sunt folosite pentru a antrena AI.\nAflă mai multe
Activează Duck.ai
- Scurtături
Meniu browser
Bara de adrese
Setări Assist
@@ -50,8 +49,6 @@
Caută sau introdu adresa
Duck.ai
Întreabă Duck.ai
- Bară de adrese experimentală
- Caută pe web sau întreabă Duck.ai direct din bara de adrese
Duck.ai
@@ -64,8 +61,6 @@
Caracteristici AI
Funcțiile IA ale DuckDuckGo sunt private și opționale.Datele tale nu sunt folosite pentru a antrena IA.\nAflă mai multe
Duck.ai
- Discută anonim cu modele populare de chat IA de la terțe părți
- Comenzi rapide Duck.ai
Setări Search Assist
Alege cât de des vrei să apară răspunsurile asistate de IA în căutările tale
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/values-ru/strings-duckchat.xml b/duckchat/duckchat-impl/src/main/res/values-ru/strings-duckchat.xml
index 560313e2685a..9ad4a742345d 100644
--- a/duckchat/duckchat-impl/src/main/res/values-ru/strings-duckchat.xml
+++ b/duckchat/duckchat-impl/src/main/res/values-ru/strings-duckchat.xml
@@ -39,7 +39,6 @@
Duck.ai — дополнительная функция, позволяющая анонимно беседовать с популярными сторонними чат-моделями на базе искусственного интеллекта. Содержимое чатов не применяется для обучения ИИ.\nПодробнее...
Включить Duck.ai
- Ярлыки
Меню браузера
Адресная строка
Настройки Assist
@@ -50,8 +49,6 @@
Введите поисковый запрос или адрес сайта
Duck.ai
Спросить у Duck.ai
- Пробная адресная строка
- Выполнить поиск в интернете или задать вопрос ИИ-ассистенту Duck.ai можно прямо из адресной строки.
Duck.ai
@@ -64,8 +61,6 @@
Функции ИИ
DuckDuckGo AI — дополнительный конфиденциальный сервис.\nВаши данные не применяются для обучения ИИ.\nПодробнее...
Duck.ai
- Анонимные чаты с популярными сторонними ИИ-моделями
- Ярлыки Duck.ai
Настройки Search Assist
Выберите, как часто вы хотите видеть ответы от ИИ в результатах поиска.
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/values-sk/strings-duckchat.xml b/duckchat/duckchat-impl/src/main/res/values-sk/strings-duckchat.xml
index f9fe93028250..052f7286a283 100644
--- a/duckchat/duckchat-impl/src/main/res/values-sk/strings-duckchat.xml
+++ b/duckchat/duckchat-impl/src/main/res/values-sk/strings-duckchat.xml
@@ -39,7 +39,6 @@
Duck.ai je voliteľná funkcia, ktorá ti umožňuje anonymne chatovať s obľúbenými modelmi chatu s umelou inteligenciou tretích strán. Tvoje chaty sa nepoužívajú na trénovanie AI.\nViac informácií
Povoliť Duck.ai
- Skratky
Ponuka prehliadača
Riadok adresy
Nastavenia Assist
@@ -50,8 +49,6 @@
Vyhľadajte alebo zadajte adresu
Duck.ai
Spýtaj sa Duck.ai
- Experimentálny riadok adresy
- Vyhľadaj na webe alebo sa opýtaj Duck.ai priamo z riadku pre adresu
Duck.ai
@@ -64,8 +61,6 @@
Funkcie AI
Funkcie DuckDuckGo AI sú súkromné a voliteľné.\nTvoje údaje sa nepoužívajú na trénovanie umelej inteligencie.\nViac informácií
Duck.ai
- Chatuj anonymne s populárnymi AI modelmi chatu tretích strán
- Skratky Duck.ai
Nastavenia Assist vyhľadávania
Vyber, ako často chceš, aby sa vo vyhľadávaní zobrazovali odpovede podporované AI
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/values-sl/strings-duckchat.xml b/duckchat/duckchat-impl/src/main/res/values-sl/strings-duckchat.xml
index 2e6928bfbabb..0157be7f17e8 100644
--- a/duckchat/duckchat-impl/src/main/res/values-sl/strings-duckchat.xml
+++ b/duckchat/duckchat-impl/src/main/res/values-sl/strings-duckchat.xml
@@ -39,7 +39,6 @@
Duck.ai je izbirna funkcija, ki vam omogoča anonimen klepet s priljubljenimi modeli za klepet z umetno inteligenco drugih ponudnikov. Vaši klepeti se ne uporabljajo za usposabljanje umetne inteligence.\nVeč o tem
Omogoči Duck.ai
- Bližnjice
Meni brskalnika
Naslovna vrstica
Nastavitve modula Assist
@@ -50,8 +49,6 @@
Poišči ali vnesi naslov
Duck.ai
Vprašajte Duck.ai
- Eksperimentalna naslovna vrstica
- Išči po spletu ali vprašaj Duck.ai neposredno iz naslovne vrstice
Duck.ai
@@ -64,8 +61,6 @@
Lastnosti UI
Funkcije umetne inteligence DuckDuckGo so zasebne in izbirne.\nVaši podatki se ne uporabljajo za usposabljanje umetne inteligence.\nVeč o tem
Duck.ai
- Anonimno klepetajte s priljubljenimi modeli umetne inteligence tretjih oseb
- Bližnjice do Duck.ai
Nastavitve modula Search Assist
Izberite, kako pogosto želite, da se odgovori s pomočjo umetne inteligence prikazujejo v vaših iskanjih
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/values-sv/strings-duckchat.xml b/duckchat/duckchat-impl/src/main/res/values-sv/strings-duckchat.xml
index 83744e1fd950..cabcab2935e4 100644
--- a/duckchat/duckchat-impl/src/main/res/values-sv/strings-duckchat.xml
+++ b/duckchat/duckchat-impl/src/main/res/values-sv/strings-duckchat.xml
@@ -39,7 +39,6 @@
Duck.ai är en valfri funktion som låter dig chatta anonymt med populära AI-chattmodeller från tredje part. Dina chattar används inte för att träna AI.\nLäs mer
Aktivera Duck.ai
- Genvägar
Webbläsarmeny
Adressfält
Assist-inställningar
@@ -50,8 +49,6 @@
Sök eller ange adress
Duck.ai
Fråga Duck.ai
- Experimentell adressfält
- Sök på webben eller fråga Duck.ai direkt i adressfältet
Duck.ai
@@ -64,8 +61,6 @@
AI-funktioner
DuckDuckGos AI-funktioner är privata och valfria.\nDina data används inte för att träna AI.\nLäs mer
Duck.ai
- Chatta anonymt med populära AI-chattmodeller från tredje part
- Duck.ai-genvägar
Inställningar för Search Assist
Välj hur ofta du vill att AI-assisterade svar ska visas i dina sökningar
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/values-sw600dp/dimens.xml b/duckchat/duckchat-impl/src/main/res/values-sw600dp/dimens.xml
new file mode 100644
index 000000000000..440a2c1ae035
--- /dev/null
+++ b/duckchat/duckchat-impl/src/main/res/values-sw600dp/dimens.xml
@@ -0,0 +1,19 @@
+
+
+
+ 160dp
+
diff --git a/duckchat/duckchat-impl/src/main/res/values-tr/strings-duckchat.xml b/duckchat/duckchat-impl/src/main/res/values-tr/strings-duckchat.xml
index 1bae6aa12af8..29d7fbfee455 100644
--- a/duckchat/duckchat-impl/src/main/res/values-tr/strings-duckchat.xml
+++ b/duckchat/duckchat-impl/src/main/res/values-tr/strings-duckchat.xml
@@ -39,7 +39,6 @@
Duck.ai, popüler 3. taraf yapay zeka sohbet modelleriyle anonim olarak sohbet etmenizi sağlayan isteğe bağlı bir özelliktir. Sohbetler yapay zekayı eğitmek için kullanılmaz.\nDaha Fazla Bilgi
Duck.ai\'ı etkinleştir
- Kısayollar
Tarayıcı menüsü
Adres Çubuğu
Assist Ayarları
@@ -50,8 +49,6 @@
Adres ara veya gir
Duck.ai
Duck.ai\'a sor
- Deneysel Adres Çubuğu
- Web\'de arama yapın veya doğrudan Adres Çubuğundan Duck.ai\'a sorun
Duck.ai
@@ -64,8 +61,6 @@
AI Özellikleri
DuckDuckGo AI özellikleri gizli ve isteğe bağlıdır.\nVerileriniz yapay zekayı eğitmek için kullanılmaz.\nDaha Fazla Bilgi
Duck.ai
- Popüler üçüncü taraf AI sohbet modelleriyle anonim olarak sohbet edin
- Duck.ai Kısayolları
Search Assist Ayarları
Yapay zeka destekli yanıtların aramalarınızda ne sıklıkta görünmesini istediğinizi seçin
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/values/dimens.xml b/duckchat/duckchat-impl/src/main/res/values/dimens.xml
index 1d31b9523d65..67f1d03b2f99 100644
--- a/duckchat/duckchat-impl/src/main/res/values/dimens.xml
+++ b/duckchat/duckchat-impl/src/main/res/values/dimens.xml
@@ -19,4 +19,5 @@
34dp
2dp
5dp
+ 16dp
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/main/res/values/strings-duckchat.xml b/duckchat/duckchat-impl/src/main/res/values/strings-duckchat.xml
index 70fc8c42e654..a9e4102e8c2f 100644
--- a/duckchat/duckchat-impl/src/main/res/values/strings-duckchat.xml
+++ b/duckchat/duckchat-impl/src/main/res/values/strings-duckchat.xml
@@ -38,19 +38,21 @@
Duck.ai is an optional feature that lets you chat anonymously with popular 3rd-party Al chat models. Your chats are not used to train AI.\nLearn More
Enable Duck.ai
- Shortcuts
Browser Menu
Address Bar
Assist Settings
Choose how often you want AI-assisted answers to appear in your searches
+ Duck.ai Shortcuts
+ Choose which Duck.ai shortcuts to display
Search
Search or enter address
Duck.ai
Ask Duck.ai
- Experimental Address Bar
- Search the web or ask Duck.ai directly from the Address Bar
+ Search Only\n(Default)
+ Search & Duck.ai\n(Experimental)
+ Try our experimental option to ask Duck.ai directly from the Address Bar. Share Feedback
Duck.ai
@@ -63,8 +65,7 @@
AI Features
DuckDuckGo AI features are private and optional.\nYour data is not used to train AI.\nLearn More
Duck.ai
- Chat anonymously with popular 3rd-party AI chat models
- Duck.ai Shortcuts
+ Chat privately with popular 3rd-party AI models
Search Assist Settings
Choose how often you want AI-Assisted answers to appear in your searches
\ No newline at end of file
diff --git a/duckchat/duckchat-impl/src/test/kotlin/com/duckduckgo/duckchat/impl/ui/settings/DuckAiShortcutSettingsViewModelTest.kt b/duckchat/duckchat-impl/src/test/kotlin/com/duckduckgo/duckchat/impl/ui/settings/DuckAiShortcutSettingsViewModelTest.kt
new file mode 100644
index 000000000000..cfa5409cb2ee
--- /dev/null
+++ b/duckchat/duckchat-impl/src/test/kotlin/com/duckduckgo/duckchat/impl/ui/settings/DuckAiShortcutSettingsViewModelTest.kt
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2025 DuckDuckGo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.duckduckgo.duckchat.impl.ui.settings
+
+import app.cash.turbine.test
+import com.duckduckgo.common.test.CoroutineTestRule
+import com.duckduckgo.duckchat.impl.DuckChatInternal
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.test.runTest
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
+
+class DuckAiShortcutSettingsViewModelTest {
+
+ @get:Rule
+ @Suppress("unused")
+ val coroutineRule = CoroutineTestRule()
+
+ private lateinit var testee: DuckAiShortcutSettingsViewModel
+
+ private val duckChat: DuckChatInternal = mock()
+
+ @Before
+ fun setUp() = runTest {
+ whenever(duckChat.observeShowInBrowserMenuUserSetting()).thenReturn(flowOf(false))
+ whenever(duckChat.observeShowInAddressBarUserSetting()).thenReturn(flowOf(false))
+ testee = DuckAiShortcutSettingsViewModel(duckChat)
+ }
+
+ @Test
+ fun whenViewModelIsCreatedAndShowInBrowserIsEnabledThenEmitEnabled() = runTest {
+ whenever(duckChat.observeShowInBrowserMenuUserSetting()).thenReturn(flowOf(true))
+ testee = DuckAiShortcutSettingsViewModel(duckChat)
+
+ testee.viewState.test {
+ assertTrue(awaitItem().showInBrowserMenu)
+ }
+ }
+
+ @Test
+ fun whenViewModelIsCreatedAndShowInBrowserIsDisabledThenEmitDisabled() = runTest {
+ whenever(duckChat.observeShowInBrowserMenuUserSetting()).thenReturn(flowOf(false))
+ testee = DuckAiShortcutSettingsViewModel(duckChat)
+
+ testee.viewState.test {
+ assertFalse(awaitItem().showInBrowserMenu)
+ }
+ }
+
+ @Test
+ fun whenViewModelIsCreatedAndShowInAddressBarIsEnabledThenEmitEnabled() = runTest {
+ whenever(duckChat.observeShowInAddressBarUserSetting()).thenReturn(flowOf(true))
+ testee = DuckAiShortcutSettingsViewModel(duckChat)
+
+ testee.viewState.test {
+ assertTrue(awaitItem().showInAddressBar)
+ }
+ }
+
+ @Test
+ fun whenViewModelIsCreatedAndShowInAddressBarIsDisabledThenEmitDisabled() = runTest {
+ whenever(duckChat.observeShowInAddressBarUserSetting()).thenReturn(flowOf(false))
+ testee = DuckAiShortcutSettingsViewModel(duckChat)
+
+ testee.viewState.test {
+ assertFalse(awaitItem().showInAddressBar)
+ }
+ }
+
+ @Test
+ fun whenAddressBarEntryPointEnabledTogglesShown() = runTest {
+ whenever(duckChat.isAddressBarEntryPointEnabled()).thenReturn(true)
+ testee = DuckAiShortcutSettingsViewModel(duckChat)
+
+ testee.viewState.test {
+ val state = awaitItem()
+ assertTrue(state.shouldShowAddressBarToggle)
+ cancelAndIgnoreRemainingEvents()
+ }
+ }
+
+ @Test
+ fun whenAddressBarEntryPointDisabledThenToggleHidden() = runTest {
+ whenever(duckChat.isAddressBarEntryPointEnabled()).thenReturn(false)
+ testee = DuckAiShortcutSettingsViewModel(duckChat)
+
+ testee.viewState.test {
+ val state = awaitItem()
+ assertFalse(state.shouldShowAddressBarToggle)
+ }
+ }
+}
diff --git a/duckchat/duckchat-impl/src/test/kotlin/com/duckduckgo/duckchat/impl/ui/DuckChatSettingsViewModelTest.kt b/duckchat/duckchat-impl/src/test/kotlin/com/duckduckgo/duckchat/impl/ui/settings/DuckChatSettingsViewModelTest.kt
similarity index 66%
rename from duckchat/duckchat-impl/src/test/kotlin/com/duckduckgo/duckchat/impl/ui/DuckChatSettingsViewModelTest.kt
rename to duckchat/duckchat-impl/src/test/kotlin/com/duckduckgo/duckchat/impl/ui/settings/DuckChatSettingsViewModelTest.kt
index 52dd1761b9c9..96434520a6b0 100644
--- a/duckchat/duckchat-impl/src/test/kotlin/com/duckduckgo/duckchat/impl/ui/DuckChatSettingsViewModelTest.kt
+++ b/duckchat/duckchat-impl/src/test/kotlin/com/duckduckgo/duckchat/impl/ui/settings/DuckChatSettingsViewModelTest.kt
@@ -14,16 +14,17 @@
* limitations under the License.
*/
-package com.duckduckgo.duckchat.impl.ui
+package com.duckduckgo.duckchat.impl.ui.settings
import app.cash.turbine.test
import com.duckduckgo.app.statistics.pixels.Pixel
import com.duckduckgo.common.test.CoroutineTestRule
-import com.duckduckgo.common.ui.experiments.visual.store.ExperimentalThemingDataStore
import com.duckduckgo.duckchat.impl.DuckChatInternal
import com.duckduckgo.duckchat.impl.pixel.DuckChatPixelName
-import com.duckduckgo.duckchat.impl.ui.DuckChatSettingsViewModel.Command.OpenLink
-import com.duckduckgo.duckchat.impl.ui.DuckChatSettingsViewModel.Command.OpenLinkInNewTab
+import com.duckduckgo.duckchat.impl.ui.settings.DuckChatSettingsViewModel.Command.LaunchFeedback
+import com.duckduckgo.duckchat.impl.ui.settings.DuckChatSettingsViewModel.Command.OpenLink
+import com.duckduckgo.duckchat.impl.ui.settings.DuckChatSettingsViewModel.Command.OpenLinkInNewTab
+import com.duckduckgo.duckchat.impl.ui.settings.DuckChatSettingsViewModel.Command.OpenShortcutSettings
import com.duckduckgo.subscriptions.api.SubscriptionRebrandingFeatureToggle
import junit.framework.TestCase.assertEquals
import kotlinx.coroutines.flow.flowOf
@@ -47,7 +48,6 @@ class DuckChatSettingsViewModelTest {
private val duckChat: DuckChatInternal = mock()
private val mockPixel: Pixel = mock()
- private val mockExperimentalThemingDataStore: ExperimentalThemingDataStore = mock()
private val mockRebrandingFeatureToggle: SubscriptionRebrandingFeatureToggle = mock()
@Before
@@ -56,7 +56,7 @@ class DuckChatSettingsViewModelTest {
whenever(duckChat.observeShowInBrowserMenuUserSetting()).thenReturn(flowOf(false))
whenever(duckChat.observeShowInAddressBarUserSetting()).thenReturn(flowOf(false))
whenever(duckChat.observeInputScreenUserSettingEnabled()).thenReturn(flowOf(false))
- testee = DuckChatSettingsViewModel(duckChat, mockPixel, mockExperimentalThemingDataStore, mockRebrandingFeatureToggle)
+ testee = DuckChatSettingsViewModel(duckChat, mockPixel, mockRebrandingFeatureToggle)
}
@Test
@@ -96,89 +96,21 @@ class DuckChatSettingsViewModelTest {
}
@Test
- fun `when onDuckAiInputScreen enabled then set user setting`() = runTest {
- testee.onDuckAiInputScreenToggled(true)
+ fun `when onDuckAiInputScreenWithAiSelected selected then set user setting`() = runTest {
+ testee.onDuckAiInputScreenWithAiSelected()
verify(duckChat).setInputScreenUserSetting(true)
}
@Test
- fun `when onDuckAiInputScreen disabled then set user setting`() = runTest {
- testee.onDuckAiInputScreenToggled(false)
+ fun `when onDuckAiInputScreenWithoutAiSelected selected then set user setting`() = runTest {
+ testee.onDuckAiInputScreenWithoutAiSelected()
verify(duckChat).setInputScreenUserSetting(false)
}
- @Test
- fun whenViewModelIsCreatedAndShowInBrowserIsEnabledThenEmitEnabled() = runTest {
- whenever(duckChat.observeShowInBrowserMenuUserSetting()).thenReturn(flowOf(true))
- testee = DuckChatSettingsViewModel(duckChat, mockPixel, mockExperimentalThemingDataStore, mockRebrandingFeatureToggle)
-
- testee.viewState.test {
- assertTrue(awaitItem().showInBrowserMenu)
- }
- }
-
- @Test
- fun whenViewModelIsCreatedAndShowInBrowserIsDisabledThenEmitDisabled() = runTest {
- whenever(duckChat.observeShowInBrowserMenuUserSetting()).thenReturn(flowOf(false))
- testee = DuckChatSettingsViewModel(duckChat, mockPixel, mockExperimentalThemingDataStore, mockRebrandingFeatureToggle)
-
- testee.viewState.test {
- assertFalse(awaitItem().showInBrowserMenu)
- }
- }
-
- @Test
- fun whenViewModelIsCreatedAndShowInAddressBarIsEnabledThenEmitEnabled() = runTest {
- whenever(duckChat.observeShowInAddressBarUserSetting()).thenReturn(flowOf(true))
- testee = DuckChatSettingsViewModel(duckChat, mockPixel, mockExperimentalThemingDataStore, mockRebrandingFeatureToggle)
-
- testee.viewState.test {
- assertTrue(awaitItem().showInAddressBar)
- }
- }
-
- @Test
- fun whenViewModelIsCreatedAndShowInAddressBarIsDisabledThenEmitDisabled() = runTest {
- whenever(duckChat.observeShowInAddressBarUserSetting()).thenReturn(flowOf(false))
- testee = DuckChatSettingsViewModel(duckChat, mockPixel, mockExperimentalThemingDataStore, mockRebrandingFeatureToggle)
-
- testee.viewState.test {
- assertFalse(awaitItem().showInAddressBar)
- }
- }
-
- @Test
- fun whenDuckChatEnabledAndAddressBarEntryPointEnabledThenBothSubTogglesShown() = runTest {
- whenever(duckChat.observeEnableDuckChatUserSetting()).thenReturn(flowOf(true))
- whenever(duckChat.isAddressBarEntryPointEnabled()).thenReturn(true)
- testee = DuckChatSettingsViewModel(duckChat, mockPixel, mockExperimentalThemingDataStore, mockRebrandingFeatureToggle)
-
- testee.viewState.test {
- val state = awaitItem()
- assertTrue(state.shouldShowBrowserMenuToggle)
- assertTrue(state.shouldShowAddressBarToggle)
- cancelAndIgnoreRemainingEvents()
- }
- }
-
- @Test
- fun whenDuckChatEnabledAndAddressBarEntryPointDisabledThenOnlyBrowserToggleShown() = runTest {
- whenever(duckChat.observeInputScreenUserSettingEnabled()).thenReturn(flowOf(false))
- whenever(duckChat.observeEnableDuckChatUserSetting()).thenReturn(flowOf(true))
- whenever(duckChat.isAddressBarEntryPointEnabled()).thenReturn(false)
- testee = DuckChatSettingsViewModel(duckChat, mockPixel, mockExperimentalThemingDataStore, mockRebrandingFeatureToggle)
-
- testee.viewState.test {
- val state = awaitItem()
- assertTrue(state.shouldShowBrowserMenuToggle)
- assertFalse(state.shouldShowAddressBarToggle)
- }
- }
-
@Test
fun `input screen - user preference enabled then set correct state`() = runTest {
whenever(duckChat.observeInputScreenUserSettingEnabled()).thenReturn(flowOf(true))
- testee = DuckChatSettingsViewModel(duckChat, mockPixel, mockExperimentalThemingDataStore, mockRebrandingFeatureToggle)
+ testee = DuckChatSettingsViewModel(duckChat, mockPixel, mockRebrandingFeatureToggle)
testee.viewState.test {
assertTrue(awaitItem().isInputScreenEnabled)
@@ -188,7 +120,7 @@ class DuckChatSettingsViewModelTest {
@Test
fun `input screen - user preference disabled then set correct state`() = runTest {
whenever(duckChat.observeInputScreenUserSettingEnabled()).thenReturn(flowOf(false))
- testee = DuckChatSettingsViewModel(duckChat, mockPixel, mockExperimentalThemingDataStore, mockRebrandingFeatureToggle)
+ testee = DuckChatSettingsViewModel(duckChat, mockPixel, mockRebrandingFeatureToggle)
testee.viewState.test {
assertFalse(awaitItem().isInputScreenEnabled)
@@ -199,7 +131,7 @@ class DuckChatSettingsViewModelTest {
fun `input screen - when duck chat enabled and flag enabled, then emit enabled`() = runTest {
whenever(duckChat.observeEnableDuckChatUserSetting()).thenReturn(flowOf(true))
whenever(duckChat.isInputScreenFeatureAvailable()).thenReturn(true)
- testee = DuckChatSettingsViewModel(duckChat, mockPixel, mockExperimentalThemingDataStore, mockRebrandingFeatureToggle)
+ testee = DuckChatSettingsViewModel(duckChat, mockPixel, mockRebrandingFeatureToggle)
testee.viewState.test {
val state = awaitItem()
@@ -211,7 +143,7 @@ class DuckChatSettingsViewModelTest {
fun `input screen - when flag disabled, then emit disabled`() = runTest {
whenever(duckChat.observeEnableDuckChatUserSetting()).thenReturn(flowOf(true))
whenever(duckChat.isInputScreenFeatureAvailable()).thenReturn(false)
- testee = DuckChatSettingsViewModel(duckChat, mockPixel, mockExperimentalThemingDataStore, mockRebrandingFeatureToggle)
+ testee = DuckChatSettingsViewModel(duckChat, mockPixel, mockRebrandingFeatureToggle)
testee.viewState.test {
val state = awaitItem()
@@ -222,14 +154,11 @@ class DuckChatSettingsViewModelTest {
@Test
fun whenDuckChatDisabledThenNoSubTogglesShown() = runTest {
whenever(duckChat.observeEnableDuckChatUserSetting()).thenReturn(flowOf(false))
- whenever(duckChat.isAddressBarEntryPointEnabled()).thenReturn(true)
whenever(duckChat.observeInputScreenUserSettingEnabled()).thenReturn(flowOf(true))
- testee = DuckChatSettingsViewModel(duckChat, mockPixel, mockExperimentalThemingDataStore, mockRebrandingFeatureToggle)
+ testee = DuckChatSettingsViewModel(duckChat, mockPixel, mockRebrandingFeatureToggle)
testee.viewState.test {
val state = awaitItem()
- assertFalse(state.shouldShowBrowserMenuToggle)
- assertFalse(state.shouldShowAddressBarToggle)
assertFalse(state.shouldShowInputScreenToggle)
}
}
@@ -285,14 +214,14 @@ class DuckChatSettingsViewModelTest {
}
@Test
- fun `when onDuckAiInputScreenToggled true then on pixel fired`() = runTest {
- testee.onDuckAiInputScreenToggled(true)
+ fun `when onDuckAiInputScreenWithAiSelected true then on pixel fired`() = runTest {
+ testee.onDuckAiInputScreenWithAiSelected()
verify(mockPixel).fire(DuckChatPixelName.DUCK_CHAT_EXPERIMENTAL_ADDRESS_BAR_SETTING_ON)
}
@Test
- fun `when onDuckAiInputScreenToggled false then off pixel fired`() = runTest {
- testee.onDuckAiInputScreenToggled(false)
+ fun `when onDuckAiInputScreenWithoutAiSelected false then off pixel fired`() = runTest {
+ testee.onDuckAiInputScreenWithoutAiSelected()
verify(mockPixel).fire(DuckChatPixelName.DUCK_CHAT_EXPERIMENTAL_ADDRESS_BAR_SETTING_OFF)
}
@@ -319,4 +248,26 @@ class DuckChatSettingsViewModelTest {
testee.onShowDuckChatInAddressBarToggled(false)
verify(mockPixel).fire(DuckChatPixelName.DUCK_CHAT_SEARCHBAR_SETTING_OFF)
}
+
+ @Test
+ fun `when Duck ai shortcuts clicked, then dispatch launch command`() = runTest {
+ testee.onDuckAiShortcutsClicked()
+
+ testee.commands.test {
+ val command = awaitItem()
+ assertTrue(command is OpenShortcutSettings)
+ cancelAndIgnoreRemainingEvents()
+ }
+ }
+
+ @Test
+ fun `when input toggle share feedback clicked, then dispatch launch command`() = runTest {
+ testee.duckAiInputScreenShareFeedbackClicked()
+
+ testee.commands.test {
+ val command = awaitItem()
+ assertTrue(command is LaunchFeedback)
+ cancelAndIgnoreRemainingEvents()
+ }
+ }
}