-
Notifications
You must be signed in to change notification settings - Fork 35
Add different configuration variants for Browsing Menu Sheet #2691
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add different configuration variants for Browsing Menu Sheet #2691
Conversation
0fde166 to
2638cec
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds configuration variants for the Browsing Menu Sheet presentation, enabling A/B testing of different menu layouts. The changes introduce a protocol-based architecture where menu building logic is extracted into reusable methods and variant-specific builders control menu structure.
Key Changes
- Introduces
BrowsingMenuVariantBuilderprotocol with three concrete implementations (A, B, C) offering different menu organizations - Extracts menu entry building logic into separate
build*methods inTabViewControllerthat implement theBrowsingMenuEntryBuildingprotocol - Adds
BrowsingMenuSheetCapabilityto manage feature availability and variant selection, restricted to internal users and iOS 17+
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| BrowsingMenuVariantBuilder.swift | Defines protocols for variant builders and entry building; includes shared AI chat menu implementation |
| BrowsingMenuVariantABuilder.swift | Variant A implementation using existing production menu structure |
| BrowsingMenuVariantBBuilder.swift | Variant B implementation with "Easy Shortcuts" layout |
| BrowsingMenuVariantCBuilder.swift | Variant C implementation with "Easy Privacy Tools" layout |
| BrowsingMenuSheetCapability.swift | Manages feature availability, enablement, and variant persistence |
| BrowsingMenuSheetView.swift | Updates to support new model structure with header/footer/sections and tag-based highlighting |
| TabViewControllerMenuBuilderExtension.swift | Extracts inline menu building into reusable methods; implements BrowsingMenuEntryBuilding protocol |
| MainViewController.swift | Adds variant selection logic and separates sheet vs default menu launching |
| SettingsViewModel.swift | Adds browsing menu capability dependency and variant binding |
| SettingsState.swift | Adds sheetMenuVariant state property |
| SettingsAppearanceView.swift | Adds UI for variant selection in settings |
| ListExtension.swift | New utility extension for compact section spacing on iOS 17+ |
| BrowsingMenuViewController.swift | Adds isSeparator convenience property to BrowsingMenuEntry |
| BrowsingMenuVariantBuilderTests.swift | Comprehensive test coverage for variant builders with mock implementations |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
iOS/DuckDuckGo/BrowsingMenu/SheetPresentationMenu/BrowsingMenuVariantCBuilder.swift
Outdated
Show resolved
Hide resolved
iOS/DuckDuckGo/BrowsingMenu/SheetPresentationMenu/BrowsingMenuVariantBBuilder.swift
Outdated
Show resolved
Hide resolved
iOS/DuckDuckGo/BrowsingMenu/SheetPresentationMenu/BrowsingMenuSheetCapability.swift
Outdated
Show resolved
Hide resolved
iOS/DuckDuckGo/BrowsingMenu/SheetPresentationMenu/BrowsingMenuSheetCapability.swift
Outdated
Show resolved
Hide resolved
iOS/DuckDuckGo/BrowsingMenu/SheetPresentationMenu/BrowsingMenuVariantBuilder.swift
Show resolved
Hide resolved
iOS/DuckDuckGo/BrowsingMenu/SheetPresentationMenu/BrowsingMenuVariantABuilder.swift
Show resolved
Hide resolved
iOS/DuckDuckGo/BrowsingMenu/SheetPresentationMenu/BrowsingMenuSheetView.swift
Show resolved
Hide resolved
74412b8 to
77a4244
Compare
iOS/DuckDuckGoTests/BrowsingMenuSheet/BrowsingMenuVariantBuilderTests.swift
Outdated
Show resolved
Hide resolved
f41be66 to
6509e25
Compare
iOS/DuckDuckGo/BrowsingMenu/SheetPresentationMenu/BrowsingMenuVariantABuilder.swift
Show resolved
Hide resolved
9203c71 to
a4a2dc4
Compare
c37c7e1 to
70ffee2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Incorrect @State initialization may break highlight feature
The @State properties highlightTag and actionToPerform are initialized using self.highlightTag = highlightRowWithTag instead of the proper SwiftUI pattern _highlightTag = State(initialValue: highlightRowWithTag). This is a known SwiftUI anti-pattern that can cause the initial value to be ignored because SwiftUI's State storage is initialized before the init body runs. The codebase consistently uses the underscore syntax elsewhere (e.g., DaxDialogView.swift, SettingsRootView.swift). The highlight animation for the "Add Favorite" onboarding flow may fail to appear as a result.
Please tell me if this was useful or not with a 👍 or 👎.
iOS/DuckDuckGo/BrowsingMenu/SheetPresentationMenu/BrowsingMenuSheetView.swift#L43-L49
apple-browsers/iOS/DuckDuckGo/BrowsingMenu/SheetPresentationMenu/BrowsingMenuSheetView.swift
Lines 43 to 49 in a4a2dc4
| init(model: BrowsingMenuModel, highlightRowWithTag: BrowsingMenuModel.Entry.Tag? = nil, onDismiss: @escaping () -> Void) { | |
| self.model = model | |
| self.onDismiss = onDismiss | |
| self.highlightTag = highlightRowWithTag | |
| self.actionToPerform = { } | |
| } |
70ffee2 to
54253a2
Compare
a4a2dc4 to
075984d
Compare
brindy
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM - tested the various variants and production menu and they seem to work fine.
<!-- Note: This template is a reminder of our Engineering Expectations and Definition of Done. Remove sections that don't apply to your changes.⚠️ If you're an external contributor, please file an issue before working on a PR. Discussing your changes beforehand will help ensure they align with our roadmap and that your time is well spent. --> Task/Issue URL: https://app.asana.com/1/137249556945/task/1212219459510183?focus=true Tech Design URL: CC: ### Description This PR adds a foundation for being able to produce multiple variants of Sheet browsing menu using existing entries. In order to allow this the following changes has been made: * Prepare a new protocol to use in sheet variants of the new menu. * Use `BrowsingMenuContext` in MainViewController to encapsulate MVC logic. * Create "A" variant of the menu which is a verbatim version of production. * Add an Appearance Setting and local storage for selecting variant option of the sheet menu (internal only). * Update the model used in `BrowsingMenuSheetView` and improve UI. ### Testing Steps 1. Turn off internal user flag, there should be no additional options in Appearance Settings 2. Do a smoke check around BrowsingMenu - how it looks in different "contexts": NTP, Duck.ai, browsing. 3. Do a general smoke check of Browsing menu. <!-- ### Testability Challenges If you encountered issues writing tests due to any class in the codebase, please report it in the [Testability Challenges Document](https://app.asana.com/1/137249556945/project/1204186595873227/task/1211703869786699) 1. **Check the Document:** First, check the **Testability Challenges Table** to see if the class you encountered is listed. 2. **If the Class Exists:** - Update the **Encounter Count** by increasing it by 1. 4. **If the Class Does Not Exist:** - Add a new entry --> ### Impact and Risks Medium: Could disrupt specific features or user flows #### What could go wrong? 1. Browsing menu does not look properly in different contexts (NTP, browsing, etc.) - this is not likely because the logic was encapsulated and used 1:1 comparing to previous state. 2. Additional options in Appearance Settings are visible for non-internal users - was checked in previous PR and this builds in top of existing state. ### Quality Considerations <!-- Focus on what matters for your changes: - What edge cases exist? - How does this affect performance? - What monitoring have you added? - What documentation needs updating? - How does this impact privacy/security? --> ### Notes to Reviewer There will be a follow-up PR containing additional menu variants: #2691 --- ###### Internal references: [Definition of Done](https://app.asana.com/0/1202500774821704/1207634633537039/f) | [Engineering Expectations](https://app.asana.com/0/59792373528535/199064865822552) | [Tech Design Template](https://app.asana.com/0/59792373528535/184709971311943) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Introduces a builder-driven sheet Browsing Menu (variants A–D) with internal-only toggle and variant picker, refactors menu construction and integrates sheet presentation across contexts. > > - **Browsing Menu Sheet Capability & Variants** > - Add `BrowsingMenuSheetCapability` (internal-only, iOS ≥17) with enable/disable and persisted `BrowsingMenuClusteringVariant` (A–D). > - Define `BrowsingMenuVariantBuilder` protocol and implementations: `BrowsingMenuVariantABuilder/B/C/DBuilder`. > - Introduce `BrowsingMenuContext` and `BrowsingMenuEntryBuilding` to decouple menu entry construction. > - **SwiftUI Sheet Menu UI** > - Create `BrowsingMenuModel` and refactor `BrowsingMenuSheetView` to use header/sections/footer, optional row highlight, and floating toolbar; add `List.compactSectionSpacingIfAvailable`. > - **Integration** > - Main flow: determine context (NTP/AI tab/website) and launch either classic or new sheet menu; add favorite-row highlighting via tag. > - Pass capability into `SettingsViewModel`; instantiate capability in `MainViewController`. > - `TabViewController`: expose entry-making methods and `buildSheetBrowsingMenu` using selected variant; factor helpers (share, reload, report, etc.). > - **Settings** > - Add Appearance section controls (internal users): toggle "Sheet menu presentation" and pick "Menu variant"; wire bindings (`showMenuInSheet`, `sheetMenuVariant`). > - Extend `SettingsState` with `showMenuInSheet` and `sheetMenuVariant`; update `SettingsViewModel` init/bindings. > - **Misc** > - Minor utility: `BrowsingMenuEntry.isSeparator` extension; project adds new Swift files and build phases. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit e3ddb2f. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- Note: This template is a reminder of our Engineering Expectations and Definition of Done. Remove sections that don't apply to your changes.⚠️ If you're an external contributor, please file an issue before working on a PR. Discussing your changes beforehand will help ensure they align with our roadmap and that your time is well spent. --> Task/Issue URL: https://app.asana.com/1/137249556945/task/1212219459510183?focus=true Tech Design URL: CC: ### Description This PR adds a foundation for being able to produce multiple variants of Sheet browsing menu using existing entries. In order to allow this the following changes has been made: * Prepare a new protocol to use in sheet variants of the new menu. * Use `BrowsingMenuContext` in MainViewController to encapsulate MVC logic. * Create "A" variant of the menu which is a verbatim version of production. * Add an Appearance Setting and local storage for selecting variant option of the sheet menu (internal only). * Update the model used in `BrowsingMenuSheetView` and improve UI. ### Testing Steps 1. Turn off internal user flag, there should be no additional options in Appearance Settings 2. Do a smoke check around BrowsingMenu - how it looks in different "contexts": NTP, Duck.ai, browsing. 3. Do a general smoke check of Browsing menu. <!-- ### Testability Challenges If you encountered issues writing tests due to any class in the codebase, please report it in the [Testability Challenges Document](https://app.asana.com/1/137249556945/project/1204186595873227/task/1211703869786699) 1. **Check the Document:** First, check the **Testability Challenges Table** to see if the class you encountered is listed. 2. **If the Class Exists:** - Update the **Encounter Count** by increasing it by 1. 4. **If the Class Does Not Exist:** - Add a new entry --> ### Impact and Risks Medium: Could disrupt specific features or user flows #### What could go wrong? 1. Browsing menu does not look properly in different contexts (NTP, browsing, etc.) - this is not likely because the logic was encapsulated and used 1:1 comparing to previous state. 2. Additional options in Appearance Settings are visible for non-internal users - was checked in previous PR and this builds in top of existing state. ### Quality Considerations <!-- Focus on what matters for your changes: - What edge cases exist? - How does this affect performance? - What monitoring have you added? - What documentation needs updating? - How does this impact privacy/security? --> ### Notes to Reviewer There will be a follow-up PR containing additional menu variants: #2691 --- ###### Internal references: [Definition of Done](https://app.asana.com/0/1202500774821704/1207634633537039/f) | [Engineering Expectations](https://app.asana.com/0/59792373528535/199064865822552) | [Tech Design Template](https://app.asana.com/0/59792373528535/184709971311943) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Introduces a builder-driven sheet Browsing Menu (variants A–D) with internal-only toggle and variant picker, refactors menu construction and integrates sheet presentation across contexts. > > - **Browsing Menu Sheet Capability & Variants** > - Add `BrowsingMenuSheetCapability` (internal-only, iOS ≥17) with enable/disable and persisted `BrowsingMenuClusteringVariant` (A–D). > - Define `BrowsingMenuVariantBuilder` protocol and implementations: `BrowsingMenuVariantABuilder/B/C/DBuilder`. > - Introduce `BrowsingMenuContext` and `BrowsingMenuEntryBuilding` to decouple menu entry construction. > - **SwiftUI Sheet Menu UI** > - Create `BrowsingMenuModel` and refactor `BrowsingMenuSheetView` to use header/sections/footer, optional row highlight, and floating toolbar; add `List.compactSectionSpacingIfAvailable`. > - **Integration** > - Main flow: determine context (NTP/AI tab/website) and launch either classic or new sheet menu; add favorite-row highlighting via tag. > - Pass capability into `SettingsViewModel`; instantiate capability in `MainViewController`. > - `TabViewController`: expose entry-making methods and `buildSheetBrowsingMenu` using selected variant; factor helpers (share, reload, report, etc.). > - **Settings** > - Add Appearance section controls (internal users): toggle "Sheet menu presentation" and pick "Menu variant"; wire bindings (`showMenuInSheet`, `sheetMenuVariant`). > - Extend `SettingsState` with `showMenuInSheet` and `sheetMenuVariant`; update `SettingsViewModel` init/bindings. > - **Misc** > - Minor utility: `BrowsingMenuEntry.isSeparator` extension; project adds new Swift files and build phases. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit e3ddb2f. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
Task/Issue URL: https://app.asana.com/1/137249556945/project/1206226850447395/task/1212001840997427?focus=true
Tech Design URL:
CC:
Description
Testing Steps
Impact and Risks
Medium: Could disrupt specific features or user flows
What could go wrong?
Modified menus does not function properly. This was tested multiple times and code was extracted to functions with least modifications possible.
Quality Considerations
Notes to Reviewer
Internal references:
Definition of Done | Engineering Expectations | Tech Design Template
Note
Adds new Browsing Menu Sheet configurations (B/C/D), introduces a floating footer toolbar, and refactors menu entry construction to support variant-specific builders.
BrowsingMenuClusteringVariantwithb/c/dand descriptions.BrowsingMenuVariantBBuilder,BrowsingMenuVariantCBuilder,BrowsingMenuVariantDBuilderimplementing custom header/section/footer compositions.BrowsingMenuSheetCapabilityand factory; expose variant selection/storage.floatingToolbarfooter (safe area inset) renderingmodel.footerItems; initializehighlightTagviaState; defaultactionToPerformclosure.makeVariantBuilderandbuildSheetBrowsingMenu.BrowsingMenuEntryBuildingto support builders.Written by Cursor Bugbot for commit ca4f5d5. This will update automatically on new commits. Configure here.