Skip to content

Conversation

@pull
Copy link

@pull pull bot commented Aug 19, 2021

See Commits and Changes for more details.


Created by pull[bot]

Can you help keep this open source service alive? 💖 Please sponsor : )

malmstein and others added 22 commits September 18, 2025 16:04
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1157893581871903/task/1211256632737934?focus=true

### Description
Rename common-ui to what it actually is, the design system
Task/Issue URL:
https://app.asana.com/0/488551667048375/1211415368280024/f

 ----- 
- Automated content scope scripts dependency update

This PR updates the content scope scripts dependency to the latest
available version and copies the necessary files.

Tests will only run if something has changed in the
`node_modules/@duckduckgo/content-scope-scripts` folder.

If only the package version has changed, there is no need to run the
tests.

If tests have failed, see
https://app.asana.com/0/1202561462274611/1203986899650836/f for further
information on what to do next.

_`content-scope-scripts` folder update_
- [x] All tests must pass
- [x] Privacy tests must pass

_Only `content-scope-scripts` package update_
- [x] All tests must pass
- [ ] Privacy tests do not need to run

Co-authored-by: daxmobile <daxmobile@users.noreply.github.com>
Task/Issue URL:
https://app.asana.com/0/488551667048375/1211422522828613/f

 ----- 
- Automated content scope scripts dependency update

This PR updates the content scope scripts dependency to the latest
available version and copies the necessary files.

Tests will only run if something has changed in the
`node_modules/@duckduckgo/content-scope-scripts` folder.

If only the package version has changed, there is no need to run the
tests.

If tests have failed, see
https://app.asana.com/0/1202561462274611/1203986899650836/f for further
information on what to do next.

_`content-scope-scripts` folder update_
- [ ] All tests must pass
- [ ] Privacy tests must pass

_Only `content-scope-scripts` package update_
- [ ] All tests must pass
- [ ] Privacy tests do not need to run

Co-authored-by: daxmobile <daxmobile@users.noreply.github.com>
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1202552961248957/task/1211407136075484?focus=true

### Description
Re-enable ADS demo screen


### Steps to test this PR

_ADS Demo_
- [x] Install Internal flavour
- [x] Navigate to Settings and verify ADS Demo is visible
- [x] Open it and verify it works
Task/Issue URL:
https://app.asana.com/1/137249556945/project/488551667048375/task/1210978319570196?focus=true

### Description

- Animates the logo when moving between search and Duck.ai on the Input
Screen

### Steps to test this PR

_Empty state_
- [ ] Open the Input Screen
- [ ] Swipe between tabs
- [ ] Verify that the logo and tab indicator animate as expected
- [ ] Tap the tabs
- [ ] Verify that the logo animates as expected

_Favorites_
- [ ] Add some favorites
- [ ] Open the Input Screen
- [ ] Swipe between tabs
- [ ] Verify that the Duck.ai logo fades in (no animation)
- [ ] Tap the tabs
- [ ] Verify that the Duck.ai logo fades in (no animation)

### UI changes


https://github.com/user-attachments/assets/e2459857-34a0-4274-87f8-31e4ab6c9835


https://github.com/user-attachments/assets/a0d75565-44bc-4a3a-91f7-bc69871f5937
Task/Issue URL: https://app.asana.com/1/137249556945/task/1211197011841474?focus=true 

### Description
Defines a feature flag for being able to import bookmarks from Google

### Steps to test this PR
- QA optional
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1202552961248957/task/1211418384396819?focus=true

### Description
In #6808 we bubbled up the
`ForegroundServiceStartNotAllowedException` to notifyVpnStart function,
when calling `startForeground` method.

This didn't get rid of the crashes but was a bit of an improvement.

This PR will try-catch the startForeground call and return the
appropriate error so that the error path can be executed. The error path
sends a pixel (m_vpn_ev_notify_start_failed_c/d) are expected to
increase and will also stop the service showing the disabled
notification. Which is a better UX

### Steps to test this PR

Smoke test the VPN and AppTP
Task/Issue URL:
https://app.asana.com/1/137249556945/task/1210561963620629?focus=true

### Description
Add VPN menu item in New Tab page for UK users

### Steps to test this PR

_Pre-steps_
- [x] Apply PPro patch ->
https://app.asana.com/1/137249556945/project/1209991789468715/task/1210448620621729?focus=true
- [x] Change remote config URL to
https://jsonblob.com/api/1419726762371375104
- [x] Set device language to English (United Kingdom)

_Not Subscribed_
- [x] Fresh install
- [x] Open a new tab page
- [x] Check you see the new VPN menu item with pill "TRY FOR FREE"

_Subscribed & Active_
- [x] Tap on VPN menu item
- [x] Subscription paywall is opened with origin
"funnel_appmenu_android" (you can check this in the logcat filtering by
"origin"
- [x] Purchase a subscription
- [x] Once the purchase is finished, go back to new tab page
- [x] Open overflow menu
- [x] Check VPN menu item is there with off indicator

_Subscribed & Not Active_
- [x] Tap on VPN menu item
- [x] Check it navigates to VPN management screen
- [x] Enable VPN
- [x] Go back to new tab page
- [x] Open overflow menu
- [x] Check VPN menu item is there with on indicator

_Browser Menu_
- [x] Make a search
- [x] Open overflow menu
- [x] Check VPN menu item is not there
- [x] Go to a website
- [x] Check VPN menu item is not there either

_Not en-GB_
- [x] Switch your device language to something other than English
(United Kingdom)
- [x] Go back to the browser
- [x] Open a new tab
- [x] Open overflow menu
- [x] Check VPN is not there, as user it is not eligible

_FF disabled_
- [x] Go to https://jsonblob.com/1419726762371375104 and disable
"vpnMenuItem" sub-feature
- [x] Set device language back to English (United Kingdom)
- [x] Go to a new tab page
- [x] Check VPN menu item is not shown

### UI changes
| Not Subscribed  | Subscribed & Active | Subscribed & Not Active | 
| ------ | ----- | ----- |
<img width="380" height="844" alt="vpn-menu-not-subscribed"
src="https://github.com/user-attachments/assets/1339ce10-0414-42bb-9774-b67a3200bb39"
/>|<img width="374" height="840" alt="vpn-menu-subscribed-active"
src="https://github.com/user-attachments/assets/691f6618-164e-4e21-906b-ed955758d32c"
/>|<img width="378" height="845" alt="vpn-menu-subscribed-not-active"
src="https://github.com/user-attachments/assets/25ef2aba-277c-4c0c-8acd-c338afda4ec7"
/>|
…unfocused to focused Input Screen state (#6834)

Task/Issue URL:
https://app.asana.com/1/137249556945/project/72649045549333/task/1211437241434767?focus=true

### Description
Fixes an issue where Dax icon wasn't in sync when transitioning from
unfocused to focused Input Screen state

### Steps to test this PR

- [ ] Open Input Screen from NTP without favorites (Dax visible).
- [ ] Verify Dax transitions smoothly between the screens.

_before_


https://github.com/user-attachments/assets/a1b1549f-ad52-496d-9d59-4723bc8f4b7d

_after_



https://github.com/user-attachments/assets/0799810a-e35a-49f3-801d-47d29cf98414
…6820)

Task/Issue URL: https://app.asana.com/1/137249556945/project/608920331025315/task/1211197010246723?focus=true 

### Description
Adds ability to parse a Google Takeout zip file containing exported bookmarks. This PR only adds underlying logic and dev settings to test it; prod UI isn't changed.

### Steps to test this PR

### Importing a valid file
- [x] Generate a Takeout zip file containing bookmarks. See "Instructions for generating a Takeout zip file" below.
- [x] Fresh install of `internal` build type
- [x] launch `Autofill Dev Settings`, and scroll to `Import Bookmarks` dev settings 🆕
- [x] tap `Choose zip file (downloaded from Takeout)` and choose the Takeout zip; verify the bookmarks imported using the `View Bookmarks` button

### Importing an invalid file
- [x] tap `Choose zip file (downloaded from Takeout)` and choose a random other file (either not a Takeout zip or one that doesn't contain bookmarks) and verify it just reports it as invalid as a snackbar


#### Instructions for generating a Takeout zip file
Tap `Launch Google Takeout (normal tab)` from `Autofill Dev Settings` and use this to generate a zip file for testing:
     - [ ] sign in
     - [ ] Tap on `Deselect All`
     - [ ] Scroll down to `Chrome`, and check it
     - [ ] Optionally, Tap on `All Chrome data included` and choose only bookmarks
     - [ ] Scroll all the way down to the bottom and tap `Next step`
     - [ ] Leave all settings as is, and choose `Create export`
     - [ ] Wait a few seconds, then refresh the page until you see `Your latest export` shows the export you just created (at the top of the page)
     - [ ] Tap `Download` and confirm you want to save it
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1198194956794324/task/1211398949646942?focus=true

### Description
Remove dead code from the old omnibar

### Steps to test this PR
QA optional, just removing dead code
Task/Issue URL:
https://app.asana.com/1/137249556945/project/488551667048375/task/1211427333122830?focus=true

### Description

- Adds a pixel if the New Address Bar Option dialog is cancelled (i.e.
by swiping or hardware back)

### Steps to test this PR

- [x] Fresh install the app
- [x] Complete onboarding (Use "I’ve been here before", **not** “Skip
Onboarding”) and kill the app
- [x] When the New Address Bar Option Dialog shows, swipe back
- [x] Verify pixel sent: `m_aichat_new_address_bar_picker_cancelled`
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1202552961248957/task/1211047862448590?focus=true

### Description
Update a couple of translations in Polish after review

### Steps to test this PR 
- [ ] Make sure the Polish update is an actual improvement and that it
make sense.

### No UI changes
Task/Issue URL:
https://app.asana.com/1/137249556945/project/488551667048375/task/1211438741846582?focus=true

### Description

- Checks `supportFragmentManager.isStateSaved` once the transition has
completed to avoid `IllegalStateException`

### Steps to test this PR

- [ ] Open Duck.ai
- [ ] Close Duck.ai
- [ ] Verify that the fragment animates out and hides
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1108686900785972/task/1211317222307614?focus=true

### Description
Removed the DaxPromptDuckPlayer feature from the dax-prompts module.
This includes removing all related code, UI components, and
functionality associated with the Duck Player variant in the
reactivation experiment.

### Steps to test this PR

Code review, check it still works. Test scenario in
https://app.asana.com/1/137249556945/project/1108686900785972/task/1211425509026704?focus=true.

### NO UI changes

---------

Co-authored-by: Dax The Translator <daxmobile@duckduckgo.com>
### Description

This PR adds Jetpack Compose support to the app by:

- Enabling Compose build features in app and common-ui modules
- Setting Kotlin compiler extension version to 1.5.14
- Adding Compose dependencies (foundation, material3, runtime, UI)
- Adding Coil for Compose image loading
- Adding Compose lint checks
- Enabling strong skipping for better Compose performance
- Updating Gradle properties to support Compose with Lint version 8.8.2
- Add lint checks to stop use of Compose in production until we're ready

Additionally, this PR fixes nullable Intent handling in `BrowserActivity` and `SystemSearchActivity` by:

- Updating method signatures to use non-nullable Intent parameters
- Adding null safety check when launching bookmarks
joshliebe and others added 30 commits November 4, 2025 12:17
Task/Issue URL:
https://app.asana.com/1/137249556945/project/488551667048375/task/1211821550799922?focus=true

### Description
- Intercepts duck.ai domain in order to prevent a blank page when
navigating back

### Steps to test this PR

- [x] Type in duck.ai
- [x] After Duck.ai has opened go back
- [x] Verify that the WebView is not blank

### UI changes
Before


https://github.com/user-attachments/assets/d80ec8c0-e4ec-4e21-a699-bd34c68d2183

After


https://github.com/user-attachments/assets/75241851-9b46-402e-9228-e611549b05cf
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1207908166761516/task/1211794252593377?focus=true

### Description

Added support for launching DuckChat settings with native settings only.
This PR introduces:

1. A new `DuckChatNativeSettingsNoParams` activity parameter to launch
DuckChat settings with search section hidden
2. Updated the `DuckChatSettingsViewModel` to use assisted injection for
configuring visibility of the search section
3. Modified the `OpenNativeSettingsHandler` to use the new parameter
when launching AI features settings
4. Refactored the settings activity to properly handle both parameter
types

### Steps to test this PR

See Asana
[task](https://app.asana.com/1/137249556945/project/1207908166761516/task/1211806457933769?focus=true)

### UI changes

Search section hidden when accessed from SERP

|  |
| --- |
|
![Screenshot_20251031_175815.png](https://app.graphite.dev/user-attachments/assets/93145292-db11-46c8-91fe-f07497dbac56.png)<br>
|
|
![Screenshot_20251031_175804.png](https://app.graphite.dev/user-attachments/assets/40423756-eae0-4e87-b92b-5fb6d5002b39.png)<br>
|
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1207418217763355/task/1211586528616250?focus=true

### Description

This PR adds translations for new string resources used in the split
omnibar project.

### Steps to test this PR

QA-optional

---------

Co-authored-by: Dax The Translator <daxmobile@duckduckgo.com>
Task/Issue URL:
https://app.asana.com/1/137249556945/project/72649045549333/task/1210985220483936?focus=true

### Description
Implement switch feature in Subscription Settings

### Steps to test this PR
_Pre steps_

- [x] Apply patch from
https://app.asana.com/1/137249556945/project/1209991789468715/task/1210448620621729?focus=true

_Free Trial_
- [x] Install from branch
- [x] Purchase a test monthly subscription (Free Trial)
- [x] Go to Subscription Settings Screen
- [x] Check switch option is not available

_Upgrade_
- [x] Cancel and wait until Free Trial expires **OR** wait until free
trial is renewed to a paid monthly subscription
- [x] If expired after canceled, purchase a monthly subscription again
- [x] Go to Subscription Settings
- [x] Check Switch option is there with updated text "Switch to Yearly
and Save 16%"
- [x] Check "Manage Plan and Payment Options" item is also updated
- [x] Select Switch option
- [x] Check copy/price/currency is correct for upgrade option
- [x] Test closing dialog and selecting "Keep monthly plan" dismiss
dialog
- [x] Select "Switch to Yearly.."
- [x] Check switch is done correctly
- [x] Check subscription settings screen data is updated as soon as
switch is success

_Downgrade_
- [x] Now, you see yearly data in Subscription Settings screen
- [x] Check Switch updated text is just "Switch plan"
- [x] Select Switch option
- [x] Check copy/price/currency is correct for downgrade option
- [x] Test closing dialog and selecting "Keep Yearly Plan" dismiss
dialog
- [x] Select "Switch to Monthly.."
- [x] Check switch is done correctly
- [x] Check subscription settings screen data is updated as soon as
switch is success

_Dynamic currency_
- [x] Open switch dialog
- [x] Check currency matches your Google Play account ($, £, €, etc.)

_Expired_
- [x] Cancel subscription and wait for it to expire
- [x] Go to Subscription Settings
- [x] Check switch option is not available anymore

_FF disabled_
- [x] Purchase a new subscription
- [x] Go to Settings > Feature Flag Inventory
- [x] Disable `supportsSwitchSubscription` FF
- [x] Go back to Subscription Settings screen
- [x] Check Switch option is not available

### UI changes
| Before  | After |
| ------ | ----- |
<img width="378" height="845" alt="Screenshot 2025-10-31 at 13 29 05"
src="https://github.com/user-attachments/assets/2fec2709-89a1-477d-9e53-98692e008d41"
/>|<img width="381" height="845" alt="Screenshot 2025-10-30 at 14 47 37"
src="https://github.com/user-attachments/assets/f8d56e39-5c17-44ec-a862-fe0c580553e1"
/>|

| Upgrade  | Downgrade |
| ------ | ----- |
<img width="378" height="835" alt="Screenshot 2025-10-30 at 14 40 11"
src="https://github.com/user-attachments/assets/d8ce6907-dd6e-41bd-bf4a-4ff6e7963215"
/>|<img width="379" height="841" alt="Screenshot 2025-10-30 at 14 47 47"
src="https://github.com/user-attachments/assets/19537c2f-c07c-4b09-80eb-e2054a6a9012"
/>|

---------

Co-authored-by: Lukasz Macionczyk <lukasz.macionczyk@gmail.com>
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1200204095367872/task/1211816347754330?focus=true

### Description

- Removes `JobInfoSchedulerService` from the manifest merger

### Steps to test this PR

- [ ] Testing steps in task
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1207418217763355/task/1211565479656355?focus=true

### Description

This PR adds the last integration of the split omnibar to the address
bar:
- When the split omnibar type is selected, the top omnibar buttons are
hidden
- The mock toolbar must show the split omnibar when loading

### Steps to test this PR

_Omnibar button_
- [ ] Enable the `splitOmnibar` flag 
- [ ] Go to Settings -> Appearance
- [ ] Select the split omnibar
- [ ] Go back to the browser
- [ ] Notice the buttons next to the address bar are gone

_Mock split toolbar_
- [ ] Restart the app
- [ ] While the app is loading, notice the mock top bar and bottom
navigation bar are displayed until the app's loaded
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1207418217763355/task/1211819634741598?focus=true

### Description

This PR removes the `newToolbarFeature` feature flag and all the
associated logic.

### Steps to test this PR

_Top omnibar_
- [ ] Set the omnibar position to TOP
- [ ] Go to the tab switcher
- [ ] Verify all the buttons work as expected
- [ ] Verify the menu items work as expected
- [ ] Verify the selection mode works (tap on Select tabs in the menu)
as expected
- [ ] Verify the tab scrolling works as expected (create many tabs in
the developer mode)

_Bottom omnibar_
- [ ] Set the omnibar position to BOTTOM
- [ ] Go to the tab switcher
- [ ] Verify all the buttons work as expected
- [ ] Verify the menu items work as expected
- [ ] Verify the selection mode works (tap on Select tabs in the menu)
as expected
- [ ] Verify the tab scrolling works as expected (create many tabs in
the developer mode)
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1202552961248957/task/1211716560268930?focus=true

### Description
Move all ADS related modules under the same folder

### Steps to test this PR

_Smoke tests_
- [x] Open the app installing the Play flavour
- [x] Play around to verify nothing is broken

_Play Flavour_
- [x] Open the app installing the Play flavour
- [x] Navigate to settings
- [x] Verify that the ADS Preview feature is not visible

_Internal Flavour_
- [x] Open the app installing the Internal flavour
- [x] Navigate to settings
- [x] Verify that the ADS Preview feature is visible
Task/Issue URL:
https://app.asana.com/1/137249556945/project/488551667048375/task/1211766964402360?focus=true

### Description
Adds error handling for when PIR encrypted database fails to decrypt and
we can't access the data.

### Steps to test this PR
See
https://app.asana.com/1/137249556945/task/1211824590968188?focus=true

### UI changes
A new error dialog when opening PIR. See
https://app.asana.com/1/137249556945/task/1211824590968188?focus=true
Task/Issue URL: https://app.asana.com/1/137249556945/project/72649045549333/task/1211755269770778?focus=true 

### Description

### Steps to test this PR

_Feature 1_
- [ ] Apply [patch](https://duckduckgo-my.sharepoint.com/:u:/p/cbarreiro/EQzRDGHt8VVNicoRG-pU560BBVo07vUHvuprNNcneF9Qgg?e=SJ0f8h)
- [ ] Fresh install
- [ ] Filter logs by "Cris"
- [ ] Load http://privacy-test-pages.site/security/badware/malware-download.html and refresh page
- [ ] Check logs for
    - [ ] `Blob downloads listener received WebViewCompat message: webViewCompat Ping:http://privacy-test-pages.site/security/badware/malware-download.html 10ms`. Validates `jsSendsInitialPing` and `jsInitialPingDelay`
    - [ ] `delaying response by 10 ms`. Validates `initialPingDelay`
    - [ ] `Posting response Pong from Native`. Validates `replyToInitialPing`
    - [ ] `Sending message PageStarted using reply proxy`. Validates `sendMessageOnPageStarted` and `sendMessagesUsingReplyProxy`
    - [ ] `Blob downloads listener received WebViewCompat message: webViewCompat PageStarted from ddgBlobDownloadObj`. Validates `useBlobDownloadsMessageListener` and `jsRepliesToNativeMessages`
- [ ] Open context menu
- [ ] Check logs for
    - [ ] `Sending message ContextMenuOpened using reply proxy`. Validates `sendMessageOnContextMenuOpen`
    - [ ] `Blob downloads listener received WebViewCompat message: webViewCompat ContextMenuOpened from ddgBlobDownloadObj`. Validates `useBlobDownloadsMessageListener` and `jsRepliesToNativeMessages`
- [ ] Test blob downloads still work

_Feature 2_
- [ ] Apply [patch
](https://duckduckgo-my.sharepoint.com/:u:/p/cbarreiro/EeK6GQN0aK9Fola1TnxLnnABPCzKOQpmcEN5jd5JUNSDuQ?e=xdS2SB)
- [ ] Fresh install
- [ ] Filter logs by "Cris"
- [ ] Load http://privacy-test-pages.site/security/badware/malware-download.html and refresh page
- [ ] Check logs for
    - [ ] `webViewCompat message received: webViewCompat Ping:http://privacy-test-pages.site/security/badware/malware-download.html 10ms`. Validates `initialPingDelay` 10ms, `jsSendsInitialPing` enabled,  and `useBlobDownloadsMessageListener` disabled
    - [ ] No log for `delaying response by 10 ms` nor `Posting response Pong from Native`. Validates `replyToInitialPing` disabled
    - [ ] No log for `Sending message PageStarted...`. Validates `sendMessageOnPageStarted` disabled
- [ ] Open context menu
- [ ] Check no logs for `Sending message ContextMenuOpened...`. Validates `sendMessageOnContextMenuOpen` disabled

_Feature 3_
- [ ] Apply [patch](https://duckduckgo-my.sharepoint.com/:u:/p/cbarreiro/EZsVUIl3CNVFkgn4cJYwuLQBdrNHa8ONEHu_264GHUYoVg?e=ZMA438)
- [ ] Fresh install
- [ ] Filter logs by "Cris"
- [ ] Load http://privacy-test-pages.site/security/badware/malware-download.html and refresh page
- [ ] Check logs for
    - [ ] `webViewCompat message received: webViewCompat Ping:http://privacy-test-pages.site/security/badware/malware-download.html 10ms`. Validates `initialPingDelay` 10ms, `jsSendsInitialPing` enabled,  and `useBlobDownloadsMessageListener` disabled
    - [ ] No log for `delaying response by 10 ms` nor `Posting response Pong from Native`. Validates `replyToInitialPing` disabled
    - [ ] No log for `Sending message PageStarted...`. Validates `sendMessageOnPageStarted` disabled
- [ ] Open context menu
- [ ] Check logs for `Sending message ContextMenuOpened not using reply proxy`. Validates `sendMessageOnContextMenuOpen` enabled and `sendMessagesUsingReplyProxy` disabled

### UI changes
| Before  | After |
| ------ | ----- |
!(Upload before screenshot)|(Upload after screenshot)|
… features (#7061)

Task/Issue URL:
https://app.asana.com/1/137249556945/project/72649045549333/task/1211819474504985?focus=true

### Description
Adds a daily pixel that report WebView support for `MULTI_PROFILE` and
`DELETE_BROWSING_DATA` features.

### Steps to test this PR

- [ ] Set your logcat to filter for: `message:webview_capabilities`
- [ ] Launch the app.
- [ ] Verify that `webview_capabilities` pixel is not sent.
- [ ] Go to developer settings and enable `reportWebViewCapabilities`.
- [ ] Force close and restart the app.
- [ ] Verify that `webview_capabilities` pixel is sent with params:
`version={your webview version}, multi_profile={true/false},
delete_browsing_data={true/false}, petal=true`
- [ ] Background and reopen the app.
- [ ] Verify that `webview_capabilities` pixel is ignored.
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1202552961248957/task/1211852239322423?focus=true

### Description

### Steps to test this PR

- [x] Tests should pass
- [ ]

### No UI changes
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1174433894299346/task/1211834986565997?focus=true

### Description
This PR adds a FF for the new full screen mode. No functionality has
been added to it.

### Steps to test this PR

_Internal flavour_
- [x] Install internal flavour
- [x] Navigate to AI Features
- [x] Verify “Full Screen Mode” toggle is visible

_Play flavour_
- [x] Install Play flavour
- [x] Navigate to AI Features
- [x] Verify “Full Screen Mode” toggle is not visible
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1207908166761516/task/1211756086814103?focus=true

### Description

Added support for sending subscription events to ContentScopeScripts.
This enables real-time updates to the SERP settings when DuckChat
settings change. The implementation includes:

- Created a new `ContentScopeScriptsSubscriptionEventPlugin` interface
to allow features to provide subscription event data
- Added a plugin point for subscription event plugins
- Implemented a DuckChat-specific plugin that sends the enabled state to
Content Scope Scripts
- Added subscription event channels and flows in both
BrowserTabViewModel and SettingsWebViewViewModel
- Set up observers in BrowserTabFragment and SettingsWebViewActivity to
send events to Content Scope Scripts

### Steps to test this PR

_DuckChat Settings Sync_ _from_ _Browser_

- [x] Enable `serpSettingsSync`​ feature toggle
- [x] Do a search e.g. "FPL"
- [x] Open Settings -> AI Features
- [x] Disable/enable Duck.AI
- [x] Navigate back to SERP
- [x] Verify that the subscription event is sent to Content Scope
Scripts (check logs for "SERP-Settings: Sending subscription event
data") with the correct state
- [x] Open Settings -> AI Features
- [x] Disable/enable Duck.AI
- [x] Verify that the subscription event is sent to Content Scope
Scripts (check logs for "SERP-Settings: Sending subscription event
data") with the correct state

_DuckChat Settings Sync_ _from_ _SettingsWebView_

- [x] Enable `serpSettingsSync`​ feature toggle
- [x] Open Settings -> AI Features
- [x] Note the current state of Duck.AI
- [x] Click "Search Assist Settings"
- [x] Press back
- [x] Verify that the subscription event is sent to Content Scope
Scripts (check logs for "SERP-Settings: Sending subscription event
data") with the correct state
- [x] Disable/enable Duck.AI
- [x] Click "Search Assist Settings"
- [x] Press back
- [x] Verify that the subscription event is sent to Content Scope
Scripts (check logs for "SERP-Settings: Sending subscription event
data") with the correct state



### UI changes

N/A
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1210594645151737/task/1211375666072192?focus=true

### Description
Removes `webTrackingProtectionsGrid` feature flag / killswitch that has
been enabled by default since launching the feature in September

### Steps to test this PR

_Web Tracking Protection Grid_
- [x] Go to Settings -> Web Tracking Protection
- [x] Verify you see a grid of cards 

### UI changes
Removes the old UI variant

---------

Co-authored-by: Dax The Translator <daxmobile@duckduckgo.com>
Task/Issue URL:
https://app.asana.com/1/137249556945/project/488551667048375/task/1211841662615810?focus=true

### Description

- Moves `InputModeTabLayout` to the `browser-ui` module

### Steps to test this PR

- [ ] Open the Input Screen
- [ ] Verify that the Input Mode Widget renders correctly in light and
dark mode
Task/Issue URL:
https://app.asana.com/1/137249556945/project/488551667048375/task/1211841661898284?focus=true

### Description

- Adds the Input Mode toggle to voice search
- Respects the current tab when launched from the Input Screen
- Remembers last used mode everywhere else
- Adds a "Voice Search" setting to "Duck.ai Shortcuts" to enable/disable
the feature
- Adds a `duckAiVoiceSearch` feature toggle set to `INTERNAL`

### Steps to test this PR

_Unfocussed state_
- [ ] Enable Private Voice Search
- [ ] Tap the Voice Search icon in the omnibar on unfocussed state
- [ ] Verify that the toggle is set is set to Search
- [ ] Say something
- [ ] Verify that a Search is completed
- [ ] Tap the Voice Search icon in the omnibar
- [ ] Toggle to Duck.ai
- [ ] Say something
- [ ] Verify that a Duck.ai query is completed
- [ ] Tap the Voice Search icon in the omnibar
- [ ] Verify that Duck.ai is pre-selected

_Input Screen_
- [ ] Go to the Search tab on the Input Screen
- [ ] Tap the Voice Search button
- [ ] Verify that the toggle is set is set to Search
- [ ] Say something
- [ ] Verify that a Search is completed
- [ ] Switch to Duck.ai tab
- [ ] Tap the Voice Search button
- [ ] Verify that the toggle is set is set to Duck.ai
- [ ] Say something
- [ ] Verify that a Duck.ai query is completed
- [ ] While still on the Duck.ai tab, tap the Voice Search button
- [ ] Toggle to Search
- [ ] Say something
- [ ] Verify that a Search is completed

_Disabled_
- [ ] Disable “Voice Search” in “Duck.ai Shortcuts”
- [ ] Verify that the toggle is no longer visible
- [ ] Re-enable and disable Duck.ai
- [ ] Verify that the toggle is no longer visible

_playDebug_
- [ ] Build `playDebug`
- [ ] Verify that the “Voice Search" setting is not visible
- [ ] Verify that the toggle is not visible in voice search

### UI changes
| Before  | After |
| ------ | ----- |
<img width="1080" height="2340" alt="voice_disabled_dark"
src="https://github.com/user-attachments/assets/d7aeed84-ee78-4e13-8b75-539e25d41162"
/>|<img width="1080" height="2340" alt="voice_search_dark"
src="https://github.com/user-attachments/assets/afeb6637-f4bc-4a54-a1e9-6d889400a157"
/>

| Before  | After |
| ------ | ----- |
<img width="1080" height="2340" alt="Screenshot_20251106_153250"
src="https://github.com/user-attachments/assets/e385938f-d5ad-4d52-a5fd-f0088d501604"
/>|<img width="1080" height="2340" alt="voice_setting_dark"
src="https://github.com/user-attachments/assets/7c0331b5-017d-4463-9aa0-083b2977a2e6"
/>
Task/Issue URL:
https://app.asana.com/1/137249556945/project/488551667048375/task/1211863634389611?focus=true

### Description

- Adds pixels when completing a voice search using the Input Mode toggle
and canceling a voice search

### Steps to test this PR

- [ ] Submit a “Search” voice search
- [ ] Verify `Pixel sent: m_voice_search_serp_done with params:
{source=browser} {}`
- [ ] Submit a “Duck.ai” voice search
- [ ] Verify `Pixel sent: m_voice_search_aichat_done with params:
{source=browser} {}`
- [ ] Cancel a voice search
- [ ] Verify `Pixel sent: m_voice_search_cancelled with params:
{source=browser} {}`

_Disabled_
- [ ] Disable “Voice Search” in “Duck.ai Shortcuts"
- [ ] Go to the Input Screen
- [ ] Submit a “Search” voice search
- [ ] Verify not sent `Pixel sent: m_voice_search_serp_done with params:
{source=browser} {}`
- [ ] Submit a “Duck.ai” voice search
- [ ] Verify not sent `Pixel sent: m_voice_search_aichat_done with
params: {source=browser} {}`
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1207418217763355/task/1211869964241175?focus=true

### Description

Only show the keyboard when opening a tab for the first time.

### Steps to test this PR

- [ ] Create a new NTP
- [ ] Notice the keyboard pops up
- [ ] Switch to a different tab
- [ ] Come back to the NTP
- [ ] Notice the keyboard does not pop up
- [ ] While on a NTP, go to settings (or any other screen)
- [ ] Come back to the NTP
- [ ] Notice the keyboard does not pop up
- Automated content scope scripts dependency update

This PR updates the content scope scripts dependency to the latest
available version and copies the necessary files.

Tests will only run if something has changed in the
`node_modules/@duckduckgo/content-scope-scripts` folder.

If only the package version has changed, there is no need to run the
tests.

If tests have failed, see
https://app.asana.com/0/1202561462274611/1203986899650836/f for further
information on what to do next.

_`content-scope-scripts` folder update_
- [ ] All tests must pass
- [ ] Privacy tests must pass

_Only `content-scope-scripts` package update_
- [ ] All tests must pass
- [ ] Privacy tests do not need to run

Co-authored-by: daxmobile <daxmobile@users.noreply.github.com>
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1202552961248957/task/1211500171306010?focus=true

### Description
Scope
- Create attributed-metrics module
- Add database to store events
- Connect with FF: enable/disable client
- Connect with Atb, privacy config
- Handles initialization and returning users checks
- Handles expiry date to disable client

### Steps to test this PR

While testing this PR you need to add the following in your logcat
filter:
`tag~:"AttributedMetrics"`

_Feature 1_
- [x] We need fresh install (including removing DDG folder in file
system)
- [x] open the app
- [x] wait for privacy config download, since we need atb init
- [x] Detected new install not reinstall Log: `New install detected,
attributed metrics active`
- [x] Log: `Client status running: true...`
- [x] Skip onboarding and go to browser 
- [x] Access feature flag inventory
- [x] Disable `attributedMetrics` FF
- [x] restart the app
- [x] See in the log `Privacy config downloaded, attributed metrics
enabled: false` (that should disable the client)
- [x] and log `Client status running: false -> isActive: true,
isEnabled: false...`

_Feature 2_
- [x] fresh install but keep DDG folder
- [x] open the app
- [x] wait for privacy config download, since we need atb init
- [x] check logs for `App reinstall detected, attributed metrics will
not be active`
- [x] and `Client status running: false -> isActive: false, isEnabled:
true...`

### UI changes
| Before  | After |
| ------ | ----- |
!(Upload before screenshot)|(Upload after screenshot)|
…ling (#7081)

Task/Issue URL:
https://app.asana.com/1/137249556945/project/488551667048375/task/1211876763499720?focus=true

### Description
Moves the feature flag checks to `io` instead of `main`. This is
triggered from `MainProcessLifecycleObserver` so is an important hot
path for app launch / ANR prevention.

### Steps to test this PR
- QA optional
- [ ] [optional]: add a log statement to
`FirstPartyCookiesModifierWorker.doWork()` and make sure it continues to
fire with this change in place when the process is created
- [ ] [optional]: verify the `StrictMode` violation warning no longer
shows on app process creation

Co-authored-by: Craig Russell <1336281+CDRussell@users.noreply.github.com>
Task/Issue URL:
https://app.asana.com/1/137249556945/project/488551667048375/task/1210911336184715?focus=true

### Description
Remove rebranding banner in Subscription Settings and Toggle

### Steps to test this PR

_Pre steps_
- [x] Apply patch from
https://app.asana.com/1/137249556945/project/1209991789468715/task/1210448620621729?focus=true

_Rebranding banner_
- [x] Install from branch
- [x] If you have a subscription go to Subscription Settings and make
sure rebranding banner is not there
- [x] If not, purchase a test subscription
- [x] Go to Subscription Settings
- [x] Check rebranding banner is not there

### UI changes
| Before  | After |
| ------ | ----- |
<img width="388" height="599" alt="Screenshot 2025-11-06 at 12 58 52"
src="https://github.com/user-attachments/assets/1c84a45c-6833-436f-b230-c627fec7454d"
/>|<img width="381" height="468" alt="Screenshot 2025-11-06 at 12 58 28"
src="https://github.com/user-attachments/assets/5118afcc-d10e-41c7-974b-8d4324bbbc2f"
/>|
Task/Issue URL:
https://app.asana.com/1/137249556945/task/1211848096596151?focus=true

### Description
Added string resources to support dynamic savings %

### Steps to test this PR

- [ ] CI checks are green ✅ 

### No UI changes

---------

Co-authored-by: Dax The Translator <daxmobile@duckduckgo.com>
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1211755920811451/task/1211842214579233?focus=true

### Description
Calculate savings dynamically from product details fetched

### Steps to test this PR

_Pre steps_
- [ ] Apply patch from
https://app.asana.com/1/137249556945/project/1209991789468715/task/1210448620621729?focus=true

_Upgrade_
- [ ] Install from branch
- [ ] Purchase a test monthly subscription (Free Trial)
- [ ] Cancel and wait until Free Trial expires **OR** wait until free
trial is renewed to a paid monthly subscription
- [ ] If expired after canceled, purchase a monthly subscription again
- [ ] Go to Subscription Settings
- [ ] Check Switch option is there with updated text "Switch to Yearly
and Save 17%"
- [ ] Select Switch option
- [ ] Check copy for upgrade option is correct (17%)

_Downgrade_
- [ ] Switch to yearly
- [ ] Wait until screen refreshes
- [ ] Select switch option
- [ ] Check copy for downgrade option is correct (17%)

### No UI changes
Task/Issue URL:
https://app.asana.com/1/137249556945/project/715106103902962/task/1211861383768919?focus=true

### Description

This PR adds a ripple effect to the AI settings pictograms.

### Steps to test this PR

- [x] Go to Settings -> AI Features
- [x] Tap on the pictograms to select the AI mode
- [x] Notice the ripple effect is applied, matching the pictogram bounds

### UI changes


[Screen_recording_20251107_100953.webm](https://github.com/user-attachments/assets/0816015b-6c55-4fd8-ab74-99e8cc40c802)

---------

Co-authored-by: Josh Leibstein <joshliebe@gmail.com>
Task/Issue URL:
https://app.asana.com/1/137249556945/task/1211821284193228

### Description
This PR adds the new Duck.ai omnibar behind a feature flag

### Steps to test this PR

_Legacy Mode_
- [x] Fresh install the app and open AI Features
- [x] Enable Duck.ai, don’t enable Fullscreen mode
- [x] Open duck.ai
- [x] Verify old omnibar is visible

_Fullscreen Mode_
- [x] Fresh install the app and open AI Features
- [x] Enable Duck.ai, enable Fullscreen mode
- [x] Open duck.ai
- [x] Verify new omnibar is visible

### UI changes
| Before  | After |
| ------ | ----- |
<img width="1080" height="2400" alt="Screenshot_20251106_152046"
src="https://github.com/user-attachments/assets/6b2e1042-313c-4fc9-9ab8-c0595584875a"
/>|<img width="1080" height="2400" alt="Screenshot_20251106_152107"
src="https://github.com/user-attachments/assets/a156cd5e-a8ce-4b2f-a39c-470e968bc17a"
/>|




---
- To see the specific tasks where the Asana app for GitHub is being
used, see below:
  - https://app.asana.com/0/0/1211821284193228
Task/Issue URL:
https://app.asana.com/1/137249556945/project/488551667048375/task/1211863673169530?focus=true

### Description
- There are two feature flag checks happening on `main` thread in a hot
path for app launching
- This is likely contributing ANRs

Moves the two feature flag checks to `io` instead of happening on `main`

### Steps to test this PR

- [ ] Check that logic around
`waitForLocalPrivacyNotificationExperiment` and
`waitForLocalPrivacyOnboardingExperiment` are still working as expected

Co-authored-by: Craig Russell <1336281+CDRussell@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.