Skip to content

Add tab group suggestions feature - #52

Open
ujjwal-devzy wants to merge 1 commit into
mainfrom
test/scale-6k-loc-review
Open

Add tab group suggestions feature#52
ujjwal-devzy wants to merge 1 commit into
mainfrom
test/scale-6k-loc-review

Conversation

@ujjwal-devzy

Copy link
Copy Markdown
Owner

Introduces a suggestion engine that recommends grouping a user's currently open tabs based on independent signals: shared domain, recency, visit frequency, and shared title keywords. Signals are scored with tunable weights, ranked, deduplicated and capped into a small set of suggestions.

Suggestions are surfaced as a dismissible card on the home screen and as a snackbar action from the tabs tray. Dismissed suggestions and an opt-out toggle persist across restarts via a DataStore-backed preferences store. Glean events record when a suggestion is shown, accepted, or dismissed.

Adds:

  • Domain/signal/scoring/ranking logic under org.mozilla.fenix.components.tabgroupsuggestions, with a lib-state Store/Action/Reducer/Middleware for UI-facing state.
  • Compose UI for the home screen card under org.mozilla.fenix.compose.tabgroupsuggestions.
  • Home screen and tabs tray integration points, plus a settings screen to toggle the feature and reset dismissed suggestions.
  • A tabGroupSuggestionsFeature flag, new Glean metrics, and new strings following existing conventions.
  • Unit tests for the engine, scorer, ranker, signals, repository, preferences, diffing and reducer.

Pull Request checklist

  • Tests: This PR includes thorough tests or an explanation of why it does not
  • Screenshots: This PR includes screenshots or GIFs of the changes made or an explanation of why it does not
  • Accessibility: The code in this PR follows accessibility best practices or does not include any user facing features. In addition, it includes a screenshot of a successful accessibility scan to ensure no new defects are added to the product.

QA

  • QA Needed

To download an APK when reviewing a PR (after all CI tasks finished running):

  1. Click on Checks at the top of the PR page.
  2. Click on the firefoxci-taskcluster group on the left to expand all tasks.
  3. Click on the build-debug task.
  4. Click on View task in Taskcluster in the new DETAILS section.
  5. The APK links should be on the right side of the screen, named for each CPU architecture.

GitHub Automation

Used by GitHub Actions.

Introduces a suggestion engine that recommends grouping a user's currently
open tabs based on independent signals: shared domain, recency, visit
frequency, and shared title keywords. Signals are scored with tunable
weights, ranked, deduplicated and capped into a small set of suggestions.

Suggestions are surfaced as a dismissible card on the home screen and as a
snackbar action from the tabs tray. Dismissed suggestions and an opt-out
toggle persist across restarts via a DataStore-backed preferences store.
Glean events record when a suggestion is shown, accepted, or dismissed.

Adds:
- Domain/signal/scoring/ranking logic under
  org.mozilla.fenix.components.tabgroupsuggestions, with a lib-state
  Store/Action/Reducer/Middleware for UI-facing state.
- Compose UI for the home screen card under
  org.mozilla.fenix.compose.tabgroupsuggestions.
- Home screen and tabs tray integration points, plus a settings screen to
  toggle the feature and reset dismissed suggestions.
- A tabGroupSuggestionsFeature flag, new Glean metrics, and new strings
  following existing conventions.
- Unit tests for the engine, scorer, ranker, signals, repository,
  preferences, diffing and reducer.
@neatcod-simulator-dev

neatcod-simulator-dev Bot commented Jul 28, 2026

Copy link
Copy Markdown

⚠️ Issues Identified — 1 Low = 1 Total

Severity File Description
🔵 Low …/components/Components.kt Unmanaged MainScope in singleton store middleware can leak w
📖 Walkthrough

This change introduces a feature-flagged “Tab Group Suggestions” system end-to-end: telemetry (shown/accepted/dismissed and section visibility), a scoring/ranking engine driven by multiple signals, persistence of dismissed/shown state via DataStore, and a Redux-style store with middleware to coordinate refresh/accept/dismiss/opt-out flows. It wires suggestions into Home and Tabs Tray UI (Compose card + snackbar) and adds a dedicated settings screen. Extensive unit tests cover signals, engine, diffing, persistence, and state transitions.

🔀 Sequence
sequenceDiagram
    participant BrowserStore
    participant TabGroupSuggestionFeature
    participant TabGroupSuggestionEngine
    participant TabGroupSuggestionStore
    participant Repository
    participant UI as Home/TabsTray UI
    participant Telemetry as Glean Telemetry

    BrowserStore->>TabGroupSuggestionFeature: Open tabs change event
    TabGroupSuggestionFeature->>TabGroupSuggestionEngine: Debounced refresh request
    TabGroupSuggestionEngine->>TabGroupSuggestionEngine: Score + rank via signals
    TabGroupSuggestionEngine->>TabGroupSuggestionStore: Dispatch Update/Refresh results
    TabGroupSuggestionStore->>Repository: Persist dismissed/shown/opt-out changes
    TabGroupSuggestionStore->>Telemetry: Record shown/accepted/dismissed + visibility
    TabGroupSuggestionStore->>UI: Expose state (loading/empty/content/top suggestion)
    UI->>TabGroupSuggestionStore: User accepts/dismisses/opts-out/reset dismissed
Loading
📂 File Changes

📊 Changes by Category (6 categories)

🔧 Tab Group Suggestions engine, scoring, and state management

Core implementation of tab group suggestions: feature wiring/components, ranking/scoring signals, suggestion model + diffing behavior, persistence of dismissed/last-shown data, and store (actions/reducer/middleware/state) to manage refresh/accept/dismiss/opt-out flows.

Files Summary
app/src/main/java/org/mozilla/fenix/components/Components.kt
app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/TabGroupSuggestionFeature.kt
app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/TabGroupSuggestionEngine.kt
Adds tab group suggestion feature components and wiring (preferences, repository, engine, store, middleware) and refreshes (debounced) on open tab changes to push updates into the store.
app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/SuggestionSignal.kt
app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/SuggestionScorer.kt
app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/SuggestionRanker.kt
app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/signals/DomainSimilaritySignal.kt
app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/signals/FrequencySignal.kt
app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/signals/RecencySignal.kt
app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/signals/TitleKeywordSignal.kt
Adds the tab group suggestion scoring/ranking pipeline and signals (domain similarity, frequency, recency, title keywords).
app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/TabGroupSuggestion.kt
app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/TabGroupSuggestionDiffing.kt
Adds TabGroupSuggestion model with stable ID derived from sorted tab IDs and diffing logic to drop dismissed suggestions while preserving timestamps when unchanged.
app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/TabGroupSuggestionPreferences.kt
app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/TabGroupSuggestionRepository.kt
app/src/main/java/org/mozilla/fenix/utils/Settings.kt
Adds DataStore-backed persistence and preferences wiring for tab group suggestions (dismissed IDs, last shown timestamps, and tabGroupSuggestionsEnabled enable/disable).
app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/store/TabGroupSuggestionAction.kt
app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/store/TabGroupSuggestionMiddleware.kt
app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/store/TabGroupSuggestionReducer.kt
app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/store/TabGroupSuggestionState.kt
app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/store/TabGroupSuggestionStore.kt
Adds tab group suggestions store layer (state/status, actions, reducer, middleware, store) to manage updates/accept/dismiss/opt-out/refresh, emit telemetry, and persist state changes.

🎨 User-facing surfaces (Home, Tabs Tray) and Compose presentation

Adds Compose UI components for rendering suggestions and integrates the feature into Home and Tabs Tray experiences (including preview/top suggestion selection, snackbar bindings, and acceptance/dismiss interactions).

Files Summary
app/src/main/java/org/mozilla/fenix/compose/tabgroupsuggestions/TabGroupSuggestionCard.kt
app/src/main/java/org/mozilla/fenix/compose/tabgroupsuggestions/TabGroupSuggestionDismissButton.kt
app/src/main/java/org/mozilla/fenix/compose/tabgroupsuggestions/TabGroupSuggestionEmptyState.kt
app/src/main/java/org/mozilla/fenix/compose/tabgroupsuggestions/TabGroupSuggestionRow.kt
Adds Compose UI for tab group suggestions including card (loading/empty/content), row with favicon handling, dismiss button, empty state, and previews.
app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt
app/src/main/java/org/mozilla/fenix/home/tabgroupsuggestions/TabGroupSuggestionsSectionUseCase.kt
app/src/main/java/org/mozilla/fenix/home/tabgroupsuggestions/TabGroupSuggestionsViewHolder.kt
Wires tab group suggestions into Home UI: bridges BrowserStore to TabGroupSuggestionStore, computes previews/top suggestion, and integrates Compose card via a store-backed view holder/interactor plus navigation helpers.
app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayFragment.kt
app/src/main/java/org/mozilla/fenix/tabstray/tabgroupsuggestions/TabGroupSuggestionsTrayBinding.kt
Adds feature-flagged tab group suggestions UI wiring in tabs tray, surfacing the top suggestion via snackbar bindings and enabling acceptance via snackbar action callbacks.

🎨 Settings controls and navigation for Tab Group Suggestions

Introduces a dedicated settings screen and navigation/strings/keys to enable/disable tab group suggestions and reset dismissed suggestions, with gating applied where appropriate.

Files Summary
app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt
app/src/main/java/org/mozilla/fenix/settings/TabGroupSuggestionSettingsFragment.kt
app/src/main/res/navigation/nav_graph.xml
app/src/main/res/values/preference_keys.xml
app/src/main/res/values/strings.xml
app/src/main/res/xml/preferences.xml
app/src/main/res/xml/tab_group_suggestions_preferences.xml
Adds tab group suggestions settings UI and navigation (new settings fragment/screen, enable switch + reset dismissed, strings/keys), and gates settings visibility behind a feature flag.

📊 Telemetry for Tab Group Suggestions

Defines and wires Glean telemetry for tab group suggestion events (shown/accepted/dismissed) and section visibility tracking.

Files Summary
app/metrics.yaml
app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/TabGroupSuggestionTelemetry.kt
Adds new tab_group_suggestions telemetry events (shown, accepted, dismissed) plus section visibility tracking, and wires logging via a Glean telemetry wrapper.

🔧 Feature flag gating by release channel

Adds a feature flag to gate tab group suggestions availability on nightly/beta channels.

Files Summary
app/src/main/java/org/mozilla/fenix/FeatureFlags.kt Adds tab group suggestions feature flag gated on nightly/beta channels.

🧪 Unit test coverage for engine, store, persistence, and ranking

Adds comprehensive unit tests covering the scoring/ranking pipeline, engine behavior, diffing/timestamp reuse logic, DataStore-backed preferences/repository, and reducer state transitions (refresh/update/accept/dismiss/opt-out).

Files Summary
app/src/test/java/org/mozilla/fenix/components/tabgroupsuggestions/SuggestionRankerTest.kt
app/src/test/java/org/mozilla/fenix/components/tabgroupsuggestions/SuggestionScorerTest.kt
app/src/test/java/org/mozilla/fenix/components/tabgroupsuggestions/TabGroupSuggestionEngineTest.kt
app/src/test/java/org/mozilla/fenix/components/tabgroupsuggestions/signals/DomainSimilaritySignalTest.kt
app/src/test/java/org/mozilla/fenix/components/tabgroupsuggestions/signals/FrequencySignalTest.kt
app/src/test/java/org/mozilla/fenix/components/tabgroupsuggestions/signals/RecencySignalTest.kt
app/src/test/java/org/mozilla/fenix/components/tabgroupsuggestions/signals/TitleKeywordSignalTest.kt
Adds extensive unit tests for scoring, ranking, engine behavior, and individual signals (including edge cases).
app/src/test/java/org/mozilla/fenix/components/tabgroupsuggestions/TabGroupSuggestionDiffingTest.kt Adds unit tests for tab group suggestion diffing and timestamp reuse logic.
app/src/test/java/org/mozilla/fenix/components/tabgroupsuggestions/TabGroupSuggestionPreferencesTest.kt
app/src/test/java/org/mozilla/fenix/components/tabgroupsuggestions/TabGroupSuggestionRepositoryTest.kt
Adds unit tests for tab group suggestion preferences/serializer and repository interactions.
app/src/test/java/org/mozilla/fenix/components/tabgroupsuggestions/store/TabGroupSuggestionReducerTest.kt Adds comprehensive unit tests for the TabGroupSuggestion reducer, covering refresh, updates, accept/dismiss, opt-out, and state transitions.

@neatcod-simulator-dev

Copy link
Copy Markdown

🛡️ Security Analysis Report

✅ No Security Issues Found

This PR passed all automated security checks, and no additional model-identified security findings were observed.


Powered by Devzy Security Scanner - Detecting 90+ security patterns across OWASP Top 10, cloud secrets, and infrastructure security.

security-summary

@neatcod-simulator-dev neatcod-simulator-dev Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Review complete

DevzyAi finished this review for this commit. Feedback is in the inline review comments on this diff.

Commits Files that changed from the base of the PR and between 9f12e38 and 5e8de04 commits.
Files selected (50)
  • app/metrics.yaml (1)
  • app/src/main/java/org/mozilla/fenix/FeatureFlags.kt (1)
  • app/src/main/java/org/mozilla/fenix/components/Components.kt (3)
  • app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/SuggestionRanker.kt (1)
  • app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/SuggestionScorer.kt (1)
  • app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/SuggestionSignal.kt (1)
  • app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/TabGroupSuggestion.kt (1)
  • app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/TabGroupSuggestionDiffing.kt (1)
  • app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/TabGroupSuggestionEngine.kt (1)
  • app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/TabGroupSuggestionFeature.kt (1)
  • app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/TabGroupSuggestionPreferences.kt (1)
  • app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/TabGroupSuggestionRepository.kt (1)
  • app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/TabGroupSuggestionTelemetry.kt (1)
  • app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/signals/DomainSimilaritySignal.kt (1)
  • app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/signals/FrequencySignal.kt (1)
  • app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/signals/RecencySignal.kt (1)
  • app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/signals/TitleKeywordSignal.kt (1)
  • app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/store/TabGroupSuggestionAction.kt (1)
  • app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/store/TabGroupSuggestionMiddleware.kt (1)
  • app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/store/TabGroupSuggestionReducer.kt (1)
  • app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/store/TabGroupSuggestionState.kt (1)
  • app/src/main/java/org/mozilla/fenix/components/tabgroupsuggestions/store/TabGroupSuggestionStore.kt (1)
  • app/src/main/java/org/mozilla/fenix/compose/tabgroupsuggestions/TabGroupSuggestionCard.kt (1)
  • app/src/main/java/org/mozilla/fenix/compose/tabgroupsuggestions/TabGroupSuggestionDismissButton.kt (1)
  • app/src/main/java/org/mozilla/fenix/compose/tabgroupsuggestions/TabGroupSuggestionEmptyState.kt (1)
  • app/src/main/java/org/mozilla/fenix/compose/tabgroupsuggestions/TabGroupSuggestionRow.kt (1)
  • app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt (6)
  • app/src/main/java/org/mozilla/fenix/home/tabgroupsuggestions/TabGroupSuggestionsSectionUseCase.kt (1)
  • app/src/main/java/org/mozilla/fenix/home/tabgroupsuggestions/TabGroupSuggestionsViewHolder.kt (1)
  • app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt (2)
  • app/src/main/java/org/mozilla/fenix/settings/TabGroupSuggestionSettingsFragment.kt (1)
  • app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayFragment.kt (5)
  • app/src/main/java/org/mozilla/fenix/tabstray/tabgroupsuggestions/TabGroupSuggestionsTrayBinding.kt (1)
  • app/src/main/java/org/mozilla/fenix/utils/Settings.kt (1)
  • app/src/main/res/navigation/nav_graph.xml (2)
  • app/src/main/res/values/preference_keys.xml (1)
  • app/src/main/res/values/strings.xml (1)
  • app/src/main/res/xml/preferences.xml (1)
  • app/src/main/res/xml/tab_group_suggestions_preferences.xml (1)
  • app/src/test/java/org/mozilla/fenix/components/tabgroupsuggestions/SuggestionRankerTest.kt (1)
  • app/src/test/java/org/mozilla/fenix/components/tabgroupsuggestions/SuggestionScorerTest.kt (1)
  • app/src/test/java/org/mozilla/fenix/components/tabgroupsuggestions/TabGroupSuggestionDiffingTest.kt (1)
  • app/src/test/java/org/mozilla/fenix/components/tabgroupsuggestions/TabGroupSuggestionEngineTest.kt (1)
  • app/src/test/java/org/mozilla/fenix/components/tabgroupsuggestions/TabGroupSuggestionPreferencesTest.kt (1)
  • app/src/test/java/org/mozilla/fenix/components/tabgroupsuggestions/TabGroupSuggestionRepositoryTest.kt (1)
  • app/src/test/java/org/mozilla/fenix/components/tabgroupsuggestions/signals/DomainSimilaritySignalTest.kt (1)
  • app/src/test/java/org/mozilla/fenix/components/tabgroupsuggestions/signals/FrequencySignalTest.kt (1)
  • app/src/test/java/org/mozilla/fenix/components/tabgroupsuggestions/signals/RecencySignalTest.kt (1)
  • app/src/test/java/org/mozilla/fenix/components/tabgroupsuggestions/signals/TitleKeywordSignalTest.kt (1)
  • app/src/test/java/org/mozilla/fenix/components/tabgroupsuggestions/store/TabGroupSuggestionReducerTest.kt (1)
Review comments generated (1)
  • Review: 1
  • LGTM: 0

Tips

Chat with DevzyAi Bot (@DevzyAi)

  • Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
  • Invite the bot into a review comment chain by tagging @DevzyAi in a reply.
See More

Interact with @DevzyAi in any bot review thread (Files changed tab):

Command Description
@DevzyAi explain Get a detailed explanation of the code or issue
@DevzyAi fix Generate a code fix suggestion
@DevzyAi suggest Get alternative implementations
@DevzyAi ignore Mark this as a false positive
@DevzyAi review Trigger a full PR review (overrides ignore)
@DevzyAi test Generate unit tests for file(s)
@DevzyAi help Show this help message

Code suggestions

  • The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
  • You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.

Pausing incremental reviews

  • Add @DevzyAi: ignore anywhere in the PR description to pause further reviews from the bot.

Models: code-review → gpt-5.2 · summary → gpt-5-nano · security → claude-test-1782398442901-008bcaf53811e

Comment on lines +208 to +212
repository = tabGroupSuggestionRepository,
telemetry = TabGroupSuggestionTelemetry(),
scope = MainScope(),
),
),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 Low

Unmanaged MainScope in singleton store middleware can leak work beyond UI lifecycle

Components creates a new MainScope() for TabGroupSuggestionMiddleware but never stores/cancels it. Since Components is effectively process-long-lived, this scope can keep coroutines running even after the UI feature stops, and it’s not tied to any lifecycle. Cross-file, HomeFragment wires the feature with viewLifecycleOwner.lifecycleScope, implying lifecycle-bound work, but middleware work launched on MainScope() will outlive that.

Prefer injecting a managed, app-level scope (owned/cancellable) or reusing an existing scope that is explicitly cancelled, and avoid creating anonymous scopes inline.


↑ Back to Summary

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