Skip to content

Consolidate desktop browser promo screens into one shared module - #9565

Draft
catalinradoiu wants to merge 1 commit into
developfrom
chore/cradoiu/consolidate-desktop-browser-promotion-activities
Draft

Consolidate desktop browser promo screens into one shared module#9565
catalinradoiu wants to merge 1 commit into
developfrom
chore/cradoiu/consolidate-desktop-browser-promotion-activities

Conversation

@catalinradoiu

@catalinradoiu catalinradoiu commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Task/Issue URL: https://app.asana.com/1/137249556945/task/1213509274333252
Tech Design URL (if applicable): https://app.asana.com/1/137249556945/project/481882893211075/task/1217673178631250
API Proposals URL(s) (if applicable): TBD

Description

Three separate activities promoted the DuckDuckGo desktop browser — GetDesktopBrowserActivity (app), SyncGetOnOtherPlatformsActivity (sync-impl) and ImportPasswordsGetDesktopAppActivity (autofill-impl) — each with its own ViewModel, layout, strings and pixel set.

This replaces them with one configuration-driven screen in a new desktop-app-promotion module.

How callers configure it. Everything the screen shows, and every pixel it may fire, comes from DesktopAppPromotionParams. Content fields are nullable and fall back to the module's own translated defaults, so Settings passes only its URL, dismiss-button flag, pixels and handler id; Sync and Autofill override the copy they don't share. The shared screen contains no per-caller branching and no caller-identity enum.

Side effects stay with their owner. The Settings "Complete your setup" card is hidden once the user engages with the promo screen, which means writing SettingsDataStore — not something a shared module can reach. The screen instead reports what the user did through a new DesktopAppPromotionInteractionHandler plugin point, and app contributes the handler that persists the dismissal. Handlers are resolved by an exact handlerId match, so Sync and Autofill launches (which pass no handler) can never touch a Settings preference. Share completion — as opposed to merely opening the chooser — still arrives via a broadcast receiver, now owned by the shared module and routed by the same key.

Steps to test this PR

Settings — "Complete your setup" card

  • Fresh install, open Settings; confirm the "Get Desktop Browser" card is shown and tap it
  • Confirm the toolbar title, copy, illustration and duckduckgo.com/browser URL match the screen before this change
  • Tap "No Thanks"; confirm the screen closes and the card is gone from Settings
  • Repeat from a fresh install, tap the URL instead; confirm the "Link copied" snackbar (API ≤32) and that the card is gone on return
  • Repeat from a fresh install, tap "Share Download Link" and complete a share; confirm the card is gone on return. Cancel the chooser instead and confirm the card is still there

Settings — bottom "Get Desktop Browser" item

  • Open Settings → bottom "Get Desktop Browser" item; confirm no "No Thanks" button is shown
  • Tap the URL, confirm copy works and the Complete-setup card is dismissed on return

Sync & Backup

  • Sync & Backup → "Get DuckDuckGo on Other Devices"; confirm the Sync copy, toolbar title "Get DuckDuckGo", ic_app_download_128 illustration and no dismiss button
  • Confirm share and copy work, and that the Settings Complete-setup card is still shown afterwards

Passwords & Autofill

  • Passwords → "Sync with desktop" → "Get Desktop Browser"; confirm the Autofill copy and toolbar title "Get Desktop App"
  • Tap "Share Download Link"; confirm the share sheet carries the longer marketing message, not just the URL
  • Confirm the Settings Complete-setup card is still shown afterwards

Pixels

  • With pixel logging on, confirm each entry point fires exactly the pixels it fired before this change — including that Settings fires no screen-impression pixel and Sync still sends its source parameter

Localisation and deeplink

  • Switch the device to a non-English locale and confirm the toolbar titles and "Link copied" snackbar are translated
  • Deeplink to the getDesktopBrowser screen name and confirm it opens with the default configuration

UI changes

Before After
No UI changes No UI changes

Three separate activities promoted the desktop browser — one each in app,
sync-impl and autofill-impl — so every change to the screen had to be made
three times, and one of them was missed entirely last time it changed.

Replace them with a single configuration-driven screen in a new
desktop-app-promotion module. Callers supply their own copy, URL and pixel
names; content fields left null fall back to the module's own translated
defaults, which is also what the existing getDesktopBrowser deeplink now
resolves to. Side effects stay with whoever owns them: the Settings
"Complete your setup" dismissal is persisted by a handler contributed from
app through the DesktopAppPromotionInteractionHandler plugin point, keyed so
Sync and Autofill launches can never trigger it.

Pixel names, parameters and attribution origins are unchanged, and Sync's
own multi-platform screen stays for the newDesktopBrowserSettingEnabled
off path.

https://app.asana.com/1/137249556945/task/1213509274333252

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Copy link
Copy Markdown
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ API Proposal reminder

This PR changes the public surface of one or more -api modules, but the API Proposals field of the PR description is empty. This is a non-blocking reminder — please double-check whether a proposal is needed.

Changed -api source files:

  • desktop-app-promotion/desktop-app-promotion-api/src/main/java/com/duckduckgo/desktopapppromotion/api/DesktopAppPromotionInteractionHandler.kt
  • desktop-app-promotion/desktop-app-promotion-api/src/main/java/com/duckduckgo/desktopapppromotion/api/DesktopAppPromotionParams.kt

To clear this reminder, edit the PR description and either:

  • add the approved API Proposal link(s) in the API Proposals field (one per line), or
  • write None there if this PR does not change the public API (e.g. KDoc, comments, tests).

See the API Proposals section in .claude/docs/contributions.md for details.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant