Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
0a58125
Add feature toggle
joshliebe Sep 7, 2026
d8b31cf
Add showAskDuckAi to feature state
joshliebe Sep 7, 2026
5d01d18
Rename showAskDuckAi to showDuckAiTextSelectionAction
joshliebe Sep 7, 2026
43d202e
Rename feature
joshliebe Sep 7, 2026
7510bba
Rename showDuckAiTextSelectionAction to showTextSelectionAction
joshliebe Sep 7, 2026
d780879
Add text selection menu action copy
joshliebe Sep 7, 2026
a6d5dfa
Add text selection attachment
joshliebe Sep 7, 2026
b31e3c2
Move strings to duck-chat module
joshliebe Sep 7, 2026
5e4ed60
Open contextual via BrowserNav
joshliebe Sep 7, 2026
9d3824b
Update suggestions catalog
joshliebe Sep 7, 2026
5fb4275
Update manifest
joshliebe Sep 7, 2026
a21089f
Add title string
joshliebe Sep 7, 2026
50451a8
Attach selections json param
joshliebe Sep 7, 2026
704166d
Add selections to contextual
joshliebe Sep 7, 2026
f3fe6db
Resolve text selection suggestions
joshliebe Sep 7, 2026
a20b138
Add text selection store
joshliebe Sep 7, 2026
4c8dc17
Add text selection to openDuckChat
joshliebe Sep 7, 2026
474d0a8
Add SelectedTextDuckAiActivity
joshliebe Sep 7, 2026
cbaa67c
Fix concurrency bug in store
joshliebe Sep 7, 2026
bf295cf
Add pending text selection to BrowserActivity
joshliebe Sep 7, 2026
fc36a77
Add text selection to BrowserTabFragment
joshliebe Sep 7, 2026
e1208b3
Add text selections container to attachment view
joshliebe Sep 7, 2026
acefb17
Update view model
joshliebe Sep 7, 2026
63c4f2d
Remove redundant comment
joshliebe Sep 7, 2026
a3cae19
Refactor
joshliebe Sep 7, 2026
bc3b6a9
Update tests
joshliebe Sep 7, 2026
5b99e74
Add payload builder
joshliebe Sep 7, 2026
2269220
Add TextSelectionToggler
joshliebe Sep 7, 2026
aa7c89e
Update tests
joshliebe Sep 7, 2026
5430183
Add text selection to DuckChatContextual
joshliebe Sep 7, 2026
f69b712
Update impl
joshliebe Sep 7, 2026
6b9e86f
Wire up manager
joshliebe Sep 7, 2026
742c8fa
Add selections to widget
joshliebe Sep 7, 2026
01948e4
Update entry dialog
joshliebe Sep 7, 2026
8652764
Wire up contextual manager
joshliebe Sep 7, 2026
ff79df1
Update suggestions logic
joshliebe Sep 7, 2026
a5de447
Fix tests
joshliebe Sep 7, 2026
516f689
Disable submission for selections without a prompt
joshliebe Sep 8, 2026
3991bdd
Fix launch source issue
joshliebe Sep 8, 2026
1758548
Refactor
joshliebe Sep 8, 2026
4975d72
Refactor
joshliebe Sep 8, 2026
8d81334
Fix bug
joshliebe Sep 8, 2026
d4b3be9
Remove redundant setTextSelections
joshliebe Sep 8, 2026
519d8da
Rename variable
joshliebe Sep 8, 2026
e27da5d
Add missing tests
joshliebe Sep 8, 2026
d02c168
Add missing tests
joshliebe Sep 8, 2026
3cece73
Refactor
joshliebe Sep 8, 2026
cb78830
Update chip display logic
joshliebe Sep 8, 2026
809b907
Use correct icon
joshliebe Sep 8, 2026
b82d3e1
Scroll to end when adding a new selection
joshliebe Sep 8, 2026
3faae84
Fix bug where selection is not attached in current contextual chat
joshliebe Sep 8, 2026
c742e5b
Add additional check for isContextualNativeInputEnabled
joshliebe Sep 8, 2026
22748e1
Update attachment logic
joshliebe Sep 8, 2026
fb7ca68
Fix submission bug
joshliebe Sep 8, 2026
004fdd9
Fix scroll bug
joshliebe Sep 8, 2026
dd142b6
Move 'Ask Duck.ai' to first position in DDG menu
joshliebe Sep 9, 2026
667784a
Add initialized check
joshliebe Sep 9, 2026
6d1f1de
Fix submission bug
joshliebe Sep 9, 2026
df6115a
Fix wrong URL issue
joshliebe Sep 9, 2026
899aee6
Fix attachment bug
joshliebe Sep 9, 2026
6496eea
Fix submission bug
joshliebe Sep 9, 2026
e15610f
Finish action mode when tapping action
joshliebe Sep 9, 2026
05e3a56
Hide action on Duck.ai tab
joshliebe Sep 9, 2026
d647d15
Update comment
joshliebe Sep 9, 2026
576219e
Remove unnecessary flag change
joshliebe Sep 9, 2026
9d23ae0
Add limit error
joshliebe Sep 9, 2026
2315aee
Handle null calling package
joshliebe Sep 9, 2026
77cac63
Fix limit issue
joshliebe Sep 9, 2026
b6612b5
Add store test
joshliebe Sep 9, 2026
c663ffe
Rename store to repository
joshliebe Sep 9, 2026
1146d7d
Hide suggestions for more than one attachment
joshliebe Sep 10, 2026
e2f5056
Rename isContextual to forceLaunchContextual
joshliebe Sep 10, 2026
3c6a38e
Fix test after rebase
joshliebe Sep 17, 2026
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
15 changes: 15 additions & 0 deletions app/src/main/java/com/duckduckgo/app/browser/BrowserActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,12 @@ open class BrowserActivity : DuckDuckGoActivity() {
}

if (intent.getBooleanExtra(OPEN_DUCK_CHAT, false)) {
val textSelection = intent.getStringExtra(DUCK_CHAT_TEXT_SELECTION)
if (intent.getBooleanExtra(DUCK_CHAT_CONTEXTUAL, false)) {
currentTab?.launchContextualDuckAi(textSelection)
return
}
pendingDuckChatTextSelection = textSelection
val sourceTabId = intent.getStringExtra(SOURCE_TAB_ID_EXTRA)
pendingDuckChatForceImageGeneration = intent.getBooleanExtra(DUCK_CHAT_FORCE_IMAGE_GENERATION, false)
intent.getStringExtra(DUCK_CHAT_ENTRY_POINT_EXTRA)?.let { source ->
Expand Down Expand Up @@ -1106,6 +1112,9 @@ open class BrowserActivity : DuckDuckGoActivity() {
globalActivityStarter.start(this, DownloadsScreenNoParams)
}

private var pendingDuckChatTextSelection: String? = null
fun consumePendingDuckChatTextSelection(): String? = pendingDuckChatTextSelection.also { pendingDuckChatTextSelection = null }

private fun launchDuckAi(url: String?, sourceTabId: String? = null) {
isDuckChatVisible = true
// The tab to return to when this Duck.ai tab is closed.
Expand Down Expand Up @@ -1315,6 +1324,8 @@ open class BrowserActivity : DuckDuckGoActivity() {
interstitialScreen: Boolean = false,
openExistingTabId: String? = null,
openDuckChat: Boolean = false,
duckChatContextual: Boolean = false,
duckChatTextSelection: String? = null,
closeDuckChat: Boolean = false,
duckChatUrl: String? = null,
duckChatSessionActive: Boolean = false,
Expand All @@ -1332,6 +1343,8 @@ open class BrowserActivity : DuckDuckGoActivity() {
intent.putExtra(LAUNCH_FROM_INTERSTITIAL_EXTRA, interstitialScreen)
intent.putExtra(OPEN_EXISTING_TAB_ID_EXTRA, openExistingTabId)
intent.putExtra(OPEN_DUCK_CHAT, openDuckChat)
intent.putExtra(DUCK_CHAT_CONTEXTUAL, duckChatContextual)
intent.putExtra(DUCK_CHAT_TEXT_SELECTION, duckChatTextSelection)
intent.putExtra(DUCK_CHAT_ENTRY_POINT_EXTRA, launchSource.toDuckChatEntryPoint()?.name)
intent.putExtra(CLOSE_DUCK_CHAT, closeDuckChat)
intent.putExtra(DUCK_CHAT_URL, duckChatUrl)
Expand Down Expand Up @@ -1369,6 +1382,8 @@ open class BrowserActivity : DuckDuckGoActivity() {
const val LAUNCH_SOURCE_PIXEL_VALUE = "LAUNCH_SOURCE_PIXEL_VALUE"

private const val OPEN_DUCK_CHAT = "OPEN_DUCK_CHAT_EXTRA"
private const val DUCK_CHAT_CONTEXTUAL = "DUCK_CHAT_CONTEXTUAL_EXTRA"
private const val DUCK_CHAT_TEXT_SELECTION = "DUCK_CHAT_TEXT_SELECTION_EXTRA"
private const val DUCK_CHAT_ENTRY_POINT_EXTRA = "DUCK_CHAT_ENTRY_POINT_EXTRA"
private const val CLOSE_DUCK_CHAT = "CLOSE_DUCK_CHAT_EXTRA"
private const val DUCK_CHAT_URL = "DUCK_CHAT_URL"
Expand Down
16 changes: 13 additions & 3 deletions app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1409,7 +1409,7 @@ class BrowserTabFragment :
}
}

private fun showNativeInput(query: String = "", forceImageGeneration: Boolean = false) {
private fun showNativeInput(query: String = "", forceImageGeneration: Boolean = false, textSelection: String? = null) {
nativeInputManager.showNativeInput(
tabId = tabId,
layoutInflater = layoutInflater,
Expand All @@ -1419,6 +1419,7 @@ class BrowserTabFragment :
query = query,
initialInputMode = viewModel.consumeInitialInputMode(),
forceImageGeneration = forceImageGeneration,
textSelection = textSelection,
callbacks = NativeInputCallbacks(
onSearchTextChanged = { text -> onUserEnteredText(text) },
onClearAutocomplete = {
Expand All @@ -1434,7 +1435,7 @@ class BrowserTabFragment :
}
},
onSearchSubmitted = { query -> onUserSubmittedText(query) },
onDuckAiChatSubmitted = { query, modelId, reasoningEffort, selectedTool, imagesJson, filesJson ->
onDuckAiChatSubmitted = { query, modelId, reasoningEffort, selectedTool, imagesJson, filesJson, selectionsJson ->
viewModel.onDuckAiChatPromptSubmitted()
contentScopeScripts.sendSubscriptionEvent(
SubscriptionEventData(
Expand Down Expand Up @@ -1465,6 +1466,9 @@ class BrowserTabFragment :
}
},
)
if (selectionsJson != null) {
put("selections", selectionsJson)
}
},
),
)
Expand Down Expand Up @@ -2443,7 +2447,7 @@ class BrowserTabFragment :
browserNavigationBarIntegration.configureDuckAIViewMode()
val forceImageGeneration = !nativeInputManager.isNativeInputShown() &&
(browserActivity?.consumeDuckChatForceImageGeneration() ?: false)
showNativeInput(forceImageGeneration = forceImageGeneration)
showNativeInput(forceImageGeneration = forceImageGeneration, textSelection = browserActivity?.consumePendingDuckChatTextSelection())
}

private fun showMaliciousWarning(
Expand Down Expand Up @@ -4027,6 +4031,12 @@ class BrowserTabFragment :
)
}

fun launchContextualDuckAi(textSelection: String? = null) {
viewLifecycleOwner.lifecycleScope.launch(dispatchers.main()) {
duckChatContextual.launch(tabId, webView?.url, webView, textSelection) { showDuckChatContextualSheet(tabId) }
}
}

private fun showDuckChatContextualSheet(tabId: String) {
binding.duckAiContextualFragmentContainer.show()

Expand Down
14 changes: 14 additions & 0 deletions app/src/main/java/com/duckduckgo/app/browser/DuckDuckGoWebView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import android.os.Message
import android.print.PrintDocumentAdapter
import android.util.AttributeSet
import android.util.SparseArray
import android.view.ActionMode
import android.view.MotionEvent
import android.view.WindowInsets
import android.view.autofill.AutofillValue
Expand All @@ -47,6 +48,7 @@ import com.duckduckgo.app.browser.navigation.safeCopyBackForwardList
import com.duckduckgo.app.browser.uilock.BrowserUiLockFeature
import com.duckduckgo.common.utils.DispatcherProvider
import com.duckduckgo.di.scopes.ViewScope
import com.duckduckgo.duckchat.api.DuckAiTextSelectionDecorator
import dagger.android.support.AndroidSupportInjection
import kotlinx.coroutines.isActive
import kotlinx.coroutines.withContext
Expand Down Expand Up @@ -91,6 +93,9 @@ class DuckDuckGoWebView :
@Inject
lateinit var browserUiLockFeature: BrowserUiLockFeature

@Inject
lateinit var duckAiTextSelectionDecorator: DuckAiTextSelectionDecorator

constructor(context: Context) : this(context, null)
constructor(
context: Context,
Expand All @@ -99,6 +104,15 @@ class DuckDuckGoWebView :
isNestedScrollingEnabled = true
}

override fun startActionMode(callback: ActionMode.Callback?): ActionMode? =
super.startActionMode(decorate(callback))

override fun startActionMode(callback: ActionMode.Callback?, type: Int): ActionMode? =
super.startActionMode(decorate(callback), type)

private fun decorate(callback: ActionMode.Callback?): ActionMode.Callback? =
if (::duckAiTextSelectionDecorator.isInitialized) duckAiTextSelectionDecorator.decorate(callback, pageUrl = url) else callback

override fun onAttachedToWindow() {
AndroidSupportInjection.inject(this)
super.onAttachedToWindow()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ class NativeInputCallbacks(
selectedTool: String?,
imagesJson: JSONArray?,
filesJson: JSONArray?,
selectionsJson: JSONArray?,
) -> Unit,
val onChatSuggestionSelected: (String) -> Unit,
val onDuckAiQuerySubmitted: (query: String, entryPoint: DuckChatEntryPoint) -> Unit = { _, _ -> },
Expand Down Expand Up @@ -148,6 +149,7 @@ interface NativeInputManager {
callbacks: NativeInputCallbacks,
initialInputMode: InputMode? = null,
forceImageGeneration: Boolean = false,
textSelection: String? = null,
)

fun hideNativeInput(animate: Boolean = true, isNavigation: Boolean = false): Boolean
Expand Down Expand Up @@ -588,6 +590,7 @@ class RealNativeInputManager @Inject constructor(
callbacks: NativeInputCallbacks,
initialInputMode: InputMode?,
forceImageGeneration: Boolean,
textSelection: String?,
) {
if (!isNativeInputFieldEnabled) return

Expand Down Expand Up @@ -657,7 +660,7 @@ class RealNativeInputManager @Inject constructor(
}
}
bindUrlCaching(widgetView)
attachWidget(widgetView, navBarView, isBottom, tabId, forceImageGeneration)
attachWidget(widgetView, navBarView, isBottom, tabId, forceImageGeneration, textSelection)
// Bottom omnibar: slide the nav bar in with open. Top omnibar: snap the bar so the enter
// morph can run from the omnibar while the buttons appear without animating — a concurrent
// top slide fights that morph (and was only needed for bottom chrome).
Expand Down Expand Up @@ -715,6 +718,7 @@ class RealNativeInputManager @Inject constructor(
widget.saveLastUsedTogglePosition(isChat = true)
val imagesJson = widget.getImageAttachmentsJson()
val filesJson = widget.getFileAttachmentsJson()
val selectionsJson = widget.getTextSelectionsJson()
widget.text = ""
widget.clearAttachments()
callbacks.onDuckAiChatSubmitted(
Expand All @@ -724,6 +728,7 @@ class RealNativeInputManager @Inject constructor(
widget.getSelectedTool(),
imagesJson,
filesJson,
selectionsJson,
)
widget.clearSelectedTool()
widget.onPromptSubmitted()
Expand Down Expand Up @@ -1231,7 +1236,14 @@ class RealNativeInputManager @Inject constructor(
)
}

private fun attachWidget(widgetView: View, navBarView: View?, isBottom: Boolean, tabId: String, forceImageGeneration: Boolean) {
private fun attachWidget(
widgetView: View,
navBarView: View?,
isBottom: Boolean,
tabId: String,
forceImageGeneration: Boolean,
textSelection: String?,
) {
// Inflated from a ?attr/actionBarSize height, so layoutParams carries the resolved nav bar height.
val navBarHeightPx = navBarView?.layoutParams?.height?.takeIf { it > 0 } ?: 0
this.navBarHeightPx = navBarHeightPx
Expand Down Expand Up @@ -1265,6 +1277,7 @@ class RealNativeInputManager @Inject constructor(
isBottom = isBottom,
forceImageGeneration = forceImageGeneration,
)
textSelection?.let { bindTextSelections(tabId, it) }
}

applyWindowChrome(widgetView, isBottom)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import android.content.Context
import android.content.Intent
import com.duckduckgo.app.browser.BrowserActivity
import com.duckduckgo.app.browser.mode.InAppNavigation
import com.duckduckgo.app.browser.mode.SelectedTextSearch
import com.duckduckgo.app.tabs.BrowserNav
import com.duckduckgo.di.scopes.AppScope
import com.squareup.anvil.annotations.ContributesBinding
Expand Down Expand Up @@ -55,14 +56,19 @@ class AppBrowserNav @Inject constructor() : BrowserNav {
hasSessionActive: Boolean,
duckChatUrl: String,
forceImageGeneration: Boolean,
forceLaunchContextual: Boolean,
textSelection: String?,
): Intent {
val isExternal = textSelection != null && !forceLaunchContextual
return BrowserActivity.intent(
context = context,
launchSource = InAppNavigation,
launchSource = if (isExternal) SelectedTextSearch else InAppNavigation,
openDuckChat = true,
duckChatContextual = forceLaunchContextual,
duckChatUrl = duckChatUrl,
duckChatSessionActive = hasSessionActive,
duckChatForceImageGeneration = forceImageGeneration,
duckChatTextSelection = textSelection,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ class RealNativeInputManagerTest {
callbacks = NativeInputCallbacks(
onSearchTextChanged = {},
onSearchSubmitted = {},
onDuckAiChatSubmitted = { _, _, _, _, _, _ -> },
onDuckAiChatSubmitted = { _, _, _, _, _, _, _ -> },
onChatSuggestionSelected = {},
onDuckAiQuerySubmitted = onDuckAiQuerySubmitted,
onClearAutocomplete = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,16 @@ interface BrowserNav {
* Returns an Intent that opens Duck.ai full screen in a new tab.
*
* @param forceImageGeneration when true, the new tab's native input preselects the image-generation tool.
* @param forceLaunchContextual when true, opens the contextual Duck.ai flow instead of a full screen tab.
* @param textSelection selected page text to attach to the contextual chat, if any.
*/
fun openDuckChat(
context: Context,
hasSessionActive: Boolean = false,
duckChatUrl: String,
forceImageGeneration: Boolean = false,
forceLaunchContextual: Boolean = false,
textSelection: String? = null,
): Intent
fun closeDuckChat(context: Context): Intent

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ interface DuckAiFeatureState {
*/
val showContextualMode: StateFlow<Boolean>

/**
* Indicates whether the "Ask Duck.ai" text selection menu item should be shown.
*/
val showTextSelectionAction: StateFlow<Boolean>

/**
* Indicates whether Duck.ai should be used as digital assistant
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2026 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.api

import android.view.ActionMode

/**
* Customizes the text selection menu.
*/
interface DuckAiTextSelectionDecorator {

/**
* Returns [callback] with "Ask Duck.ai" shown as a primary action rather than an overflow entry.
* The action is hidden for Duck.ai tabs.
*
* @param pageUrl the page the text was selected on.
*/
fun decorate(callback: ActionMode.Callback?, pageUrl: String?): ActionMode.Callback?
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ interface DuckChatContextual {
sourceTabId: String,
sourceUrl: String?,
anchor: View?,
textSelection: String? = null,
showChatSurface: () -> Unit,
)

Expand Down
16 changes: 16 additions & 0 deletions duckchat/duckchat-impl/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,22 @@
android:label="@string/duck_ai_edit_prompt_title"
android:windowSoftInputMode="stateVisible|adjustResize" />

<!--
Adds "Ask Duck.ai" to the text selection menu (in this app and other apps).
-->
<activity
android:name=".ui.nativeinput.textselection.SelectedTextDuckAiActivity"
android:enabled="false"
android:exported="true"
android:launchMode="singleTask"
android:label="@string/duckAiTextSelectionMenuItem">
<intent-filter>
<action android:name="android.intent.action.PROCESS_TEXT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>

<service
android:name=".ui.DuckChatVoiceMicrophoneService"
android:exported="false"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
"summarize-page": { "label": "Summarize this page", "icon": "summary", "prompt": "Summarize this page." },
"translate-page": { "label": "Translate this page", "icon": "translate", "prompt": "Translate this page into {language}.", "condition": "differentLanguage" },

"summarize-selection": { "label": "Summarize this selection", "icon": "summary", "prompt": "Summarize this selection." },
"translate-selection": { "label": "Translate this selection", "icon": "translate", "prompt": "Translate this selection into {language}.", "condition": "differentLanguage" },

"key-takeaways": { "label": "What are the key takeaways?", "icon": "summary", "prompt": "What are the key takeaways from this article?" },
"explain-simply": { "label": "Explain this simply", "prompt": "Explain this in simple, plain language." },
"counterarguments": { "label": "What are the counterarguments?", "prompt": "What are the main counterarguments or criticisms of this?" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,7 @@ class RealDuckChat @Inject constructor(
private val _showVoiceSearchToggle = MutableStateFlow(false)
private val _showVoiceChatEntry = MutableStateFlow(false)
private val _showContextualMode = MutableStateFlow(false)
private val _showTextSelectionAction = MutableStateFlow(false)
private val _allowDuckAiAsDigitalAssistant = MutableStateFlow(false)
private val _displayedMode = MutableStateFlow(InputMode.SEARCH)
private val _inputQuery = MutableStateFlow("")
Expand Down Expand Up @@ -726,6 +727,8 @@ class RealDuckChat @Inject constructor(

override val showContextualMode: StateFlow<Boolean> = _showContextualMode.asStateFlow()

override val showTextSelectionAction: StateFlow<Boolean> = _showTextSelectionAction.asStateFlow()

override val allowDuckAiAsDigitalAssistant: StateFlow<Boolean> = _allowDuckAiAsDigitalAssistant.asStateFlow()

override val nativeInputFieldEnabled: StateFlow<Boolean> = _nativeInputFieldEnabled.asStateFlow()
Expand Down Expand Up @@ -1155,6 +1158,12 @@ class RealDuckChat @Inject constructor(

contextualMenuAllChatsEnabled = contextualSheetRedesignEnabled && duckChatFeature.contextualMenuAllChats().isEnabled()

_showTextSelectionAction.emit(
contextualSheetRedesignEnabled &&
isContextualNativeInputEnabled &&
duckChatFeature.duckAiTextSelectionAction().isEnabled(),
)

isAutomaticContextAttachmentEnabled = isContextualModeEnabled &&
duckChatFeature.automaticContextAttachment()
.isEnabled() && duckChatFeatureRepository.isAutomaticPageContextAttachmentUserSettingEnabled()
Expand Down
Loading
Loading