Skip to content

Remove the obsolete standalone Duck.ai screen and its rollout flag - #9402

Merged
malmstein merged 4 commits into
developfrom
feature/david/remove_fullscreen_duckai_mode
Aug 7, 2026
Merged

Remove the obsolete standalone Duck.ai screen and its rollout flag#9402
malmstein merged 4 commits into
developfrom
feature/david/remove_fullscreen_duckai_mode

Conversation

@malmstein

@malmstein malmstein commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Task/Issue URL: https://app.asana.com/1/137249556945/project/1174433894299346/task/1217189225202021
Tech Design URL (if applicable):
API Proposals URL(s) (if applicable): None

Description

Stacked on #9394 (collapse InputModeWidget), which is stacked on #9392, which is stacked on #9391. Review and merge those first — this PR targets #9394's branch, so the diff here is only the fourth step.

Deletes the overlay-based fullscreen Duck.ai experience (DuckChatWebViewFragment/DuckChatWebViewViewModel, a fragment that slid in over the browser from the right) and the showFullScreenMode rollout flag that gated it. The flag's replacement — tab-based Duck.ai, opened via BrowserActivity.launchDuckAi()'s new-tab path — is already the only reachable behaviour once this lands; the flag defaulted INTERNAL and every non-internal caller already took that branch by the time this task was scoped, so there's no user-visible change.

Four commits:

  1. Delete DuckChatWebViewFragment/DuckChatWebViewViewModel and their layout/test. Nothing routes to them any more.
  2. Remove the flag and its infrastructureshowFullScreenMode/showFullScreenModeToggle off DuckAiFeatureState, DuckChatFeature.fullscreenMode(), the DUCK_CHAT_FULLSCREEN_MODE_SETTING preference and its accessors. isDuckChatFullScreenModeEnabled() is a distinct, still-live accessor (feeds DuckChatJSHelper's JS capability signalling) — it now tracks Duck.ai feature availability directly rather than the retired rollout computation, since that's the only gate left with any meaning once the fragment alternative is gone.
  3. Collapse every showFullScreenMode.value branch in :app to its true side: BrowserActivity.launchDuckAi()/CLOSE_DUCK_CHAT handling, BrowserViewModel.openDuckChat()/Command.OpenDuckChat, BrowserTabViewModel.evaluateDuckAIPage()/openDuckAiQuery()/openDuckAiChatById()/onDuckChatOmnibarButtonClicked(), TabSwitcherViewModel.onDuckAIButtonClicked(), and SpecialUrlDetector's ShouldLaunchDuckChatLink special-casing (only reachable when the flag was off). ViewTransitionAnimations.kt (bundled into commit 1) existed solely for the overlay's slide-in/out, so it goes with the last caller.
  4. Regenerate the app lint baseline (./gradlew :app:updateLintBaseline) to drop the stale NoImplImportsInAppModule entries for the deleted import and reconcile line numbers.

Deviations from the original task notes worth flagging in review

  • isDuckChatFullScreenModeEnabled()'s new definition (isDuckChatFeatureEnabled instead of the rollout-flag computation) wasn't in the task's listed steps — it fell out of removing fullscreenMode(), since this accessor is a separate, still-consumed concept from the showFullScreenMode StateFlow the task named.
  • The task's Step 5 said "two menu click handlers" checked the flag in BrowserTabFragment; only one still did (the other already called openNewDuckChat unconditionally) — the codebase moved since the task was scoped.
  • One pre-existing, previously-untested quirk surfaced once the true branch became unconditional: BrowserTabViewModel.openDuckAiQuery() fires onInputSubmitted() on browser-interaction plugins twice (once directly, once via the onUserSubmittedQuery() call it routes through). This predates the flag removal — it was already true whenever showFullScreenMode was on — so it's documented on the test rather than fixed here, to keep this PR a pure flag removal.
  • A prior attempt at this exact task (#8134, linked from the Asana task's "First attempt" subtask) hardcoded showNewDuckChatTabOption = false, breaking the live new-Duck.ai-tab feature instead of just the dead overlay — a mix-up between the fragment's own showFullScreenMode-gated branches and the unrelated, still-live hasSessionActive concept threaded through BrowserNav.openDuckChat(). This PR verified each branch's kept side against production before collapsing it, and left BrowserNav/AppBrowserNav/RealDuckChat/the widget shortcut call sites untouched.

Steps to test this PR

  • Tap the omnibar Duck.ai button (unfocused, browser tab): opens a new Duck.ai tab
  • Type in the omnibar, tap the Duck.ai chevron while focused: opens Duck.ai with the typed query pre-filled
  • New tab page, tap "Ask Duck.ai" / submit a query with the Duck.ai toggle selected: opens in a new tab, NTP tab itself is reused (not duplicated)
  • Tab switcher FAB → Duck.ai: opens a new Duck.ai tab and closes the switcher
  • Navigate to a duck.ai URL directly (address bar or link): loads normally in the tab, no special-cased redirect
  • Contextual sheet still opens from the omnibar when unfocused and not on NTP (unrelated showContextualMode path, untouched)
  • CLOSE_DUCK_CHAT intent (e.g. widget/notification action) while in a Duck.ai tab: closes the tab

UI changes

None.


Note

Medium Risk
Touches many Duck.ai navigation paths across browser and duckchat modules; regressions could affect how users open or close Duck.ai tabs, though behavior is intended to match the flag-on path already in production.

Overview
Removes the obsolete overlay fullscreen Duck.ai experience (DuckChatWebViewFragment / view model, layout, tests) and the showFullScreenMode rollout path, including DuckChatFeature.fullscreenMode(), the fullscreen preference, and showFullScreenMode / toggle fields on DuckAiFeatureState.

Duck.ai entry points in :app no longer branch on that flag: BrowserActivity.launchDuckAi() always opens a new Duck.ai tab, CLOSE_DUCK_CHAT closes the current tab when it is Duck.ai, and omnibar / NTP / tab-switcher handlers route through the new-tab navigation helpers in BrowserTabViewModel and BrowserTabViewModel. Overlay-only slide animations in ViewTransitionAnimations are deleted with the last caller.

isDuckChatFullScreenModeEnabled() remains for JS capability signalling in DuckChatJSHelper; it now mirrors Duck.ai feature availability instead of the retired rollout computation. App lint baseline is regenerated for deleted imports and line shifts.

No intended user-visible change: tab-based Duck.ai was already the effective behavior when the flag was on. A pre-existing double onInputSubmitted() call in openDuckAiQuery() is left as-is.

Reviewed by Cursor Bugbot for commit 69400c2. Bugbot is set up for automated code reviews on this repo. Configure here.

@malmstein malmstein changed the title Remove the fullscreen Duck.ai overlay and its rollout flag Remove the obsolete standalone Duck.ai screen and its rollout flag Aug 5, 2026
Base automatically changed from feature/david/collapse_input_mode_widget to develop August 6, 2026 08:50
@malmstein
malmstein force-pushed the feature/david/remove_fullscreen_duckai_mode branch from f4f3b14 to e17fdbb Compare August 6, 2026 09:11

@YoussefKeyrouz YoussefKeyrouz left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested. All looks good. Thanks for cleaning this.

malmstein and others added 4 commits August 7, 2026 13:08
DuckChatWebViewFragment/ViewModel implemented the original overlay-based
Duck.ai experience: a fragment that slid in over the browser. It has been
superseded by the tab-based fullscreen experience and the contextual
sheet; nothing in this PR's later commits routes to it any more. Its
layout was only ever inflated by this fragment.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
showFullScreenMode/showFullScreenModeToggle, the fullscreenMode() toggle,
the DUCK_CHAT_FULLSCREEN_MODE_SETTING preference and its user-setting
accessors are all dead weight now that the fragment they gated is gone
and the tab-based experience they were rolling out is the only one left.

isDuckChatFullScreenModeEnabled() (a distinct, still-live accessor consumed
by DuckChatJSHelper's JS capability signalling) now tracks Duck.ai feature
availability directly rather than the retired rollout flag/user-setting
computation, since that's the only gate left with any meaning once the
fragment-overlay alternative no longer exists.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Every showFullScreenMode.value check gated a true/false pair where the
true branch was already the tab-based experience and the false branch
routed to the now-deleted overlay fragment. With the flag gone, each site
collapses to the true branch, so the visible behaviour for every caller
is unchanged from what fullscreen-mode users already had:

- BrowserActivity: launchDuckAi() always opens a tab; the CLOSE_DUCK_CHAT
  intent always uses closeDuckChatFullScreen(). The overlay's fragment
  field, launch/restore/animate functions and back-press hook go with it,
  along with duckAiShouldAnimate/duckAiAnimDelayJob, which existed only to
  time the overlay's slide-in. ViewTransitionAnimations.kt (deleted in the
  prior commit) was that animation's only consumer.
- BrowserViewModel: openDuckChat()/Command.OpenDuckChat and the
  duckAiFullScreenMode view-state field are unused now that BrowserActivity
  never sends the command.
- BrowserTabViewModel: evaluateDuckAIPage(), openDuckAiQuery(),
  openDuckAiChatById() and onDuckChatOmnibarButtonClicked() drop their
  outer flag gate and legacy Intent-based fallback (the "else" branches
  that called duckChat.openDuckChat()/openDuckChatWithAutoPrompt()
  directly). onDuckChatMenuClicked() loses its only caller and goes too.
- TabSwitcherViewModel.onDuckAIButtonClicked(): same collapse, the FAB
  always opens a new Duck.ai tab now.
- SpecialUrlDetector: UrlType.ShouldLaunchDuckChatLink was only reachable
  when the flag was off; both call sites (the null-scheme branch gated on
  aiChatQueryDetectionFeature, and the http(s) scheme branch) are now dead
  and removed along with the injections that fed them.

Test changes follow the same pattern throughout: delete cases that
asserted the removed legacy branch, drop the flag stub from cases
asserting the kept branch. One pre-existing, previously-untested quirk
surfaced on the now-unconditional path: openDuckAiQuery() fires
onInputSubmitted() on browser-interaction plugins twice (once directly,
once via the onUserSubmittedQuery() it routes through) — documented on
the test rather than changed, since it predates this flag removal.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Rebased onto develop after PRs 9391/9392/9394 merged (squash), which
moved the baseline out from under the previous regen. Fresh run of
:app:updateLintBaseline against the new develop tip.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@malmstein
malmstein force-pushed the feature/david/remove_fullscreen_duckai_mode branch from e17fdbb to 69400c2 Compare August 7, 2026 11:08
@malmstein
malmstein merged commit 544d6ad into develop Aug 7, 2026
17 checks passed
@malmstein
malmstein deleted the feature/david/remove_fullscreen_duckai_mode branch August 7, 2026 11:23
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.

2 participants