Skip to content

TF-4645 SSOT Part 4 — Migrate mobile search to the central executor#4686

Open
dab246 wants to merge 4 commits into
features/ssot-searchfrom
fix/tf-4645-ssot-4-mobile-search-executor
Open

TF-4645 SSOT Part 4 — Migrate mobile search to the central executor#4686
dab246 wants to merge 4 commits into
features/ssot-searchfrom
fix/tf-4645-ssot-4-mobile-search-executor

Conversation

@dab246

@dab246 dab246 commented Jul 7, 2026

Copy link
Copy Markdown
Member

Closes #4645

What

Mobile search (SearchEmailController) now delegates execution to the central SearchEmailNotifier (searchEmailProvider) and reads its filter directly from the committed SSOT (searchFilterProvider) — no local filter copy. New search, load-more and the websocket refresh all run through the executor; pagination cursors leave the controller entirely.

Why

  • SearchEmailController owned its own searchEmailFilter.obs and ran interactors inline, duplicating the cursor branching that also lived in ThreadController. Delegating to the executor removes that duplication so pagination rules live only in its strategies.
  • Reading committed filter state straight from the SSOT removes a second source of truth: the old .obs copy had to be written on every edit and could diverge from the filter.

Behaviour changes to flag

  • Chips now always reflect the committed filter. Previously _searchEmailByQueryString / clearAllSearchFilterApplied reset the receive-time/sort display to defaults while leaving the filter untouched — a divergence the single-source refactor removes.
  • Websocket refresh replaces + syncs the current window instead of combine-merging it.

Mobile search flow

chips / date / sort / delete ─ update()/set() ─▶ SearchFilterNotifier
                                                  (searchFilterProvider)
                                                        │ watch (Consumer)
                                                        ▼
                                                  filter chips / menus (view)

_searchEmailAction     ─ NewSearchIntent     ─┐   reads committed; strategies own cursors
searchMoreEmailsAction ─ LoadMoreIntent      ─┼▶ SearchEmailNotifier.execute ─listen─▶ _handleSearchEmailResult
websocket refresh      ─ RefreshChangesIntent ┘                                              │
                                                                                            ▼
                                                                  listResultSearch (+ canSearchMore, view state)

Tests

  • Unit — search_email_controller_test (9 cases): new search delegates to the executor and bridges the first page; load-more delegates LoadMoreIntent with the lastEmailId anchor and appends; new-search failure clears the list and surfaces Left; load-more failure keeps the current page and completes searchMoreState; controller filter getters read the committed searchFilterProvider (single source); clearAllResultSearch resets the committed filter via notifier.set; a websocket message drives RefreshChangesIntent and replaces the rendered list; a websocket refresh failure keeps the rendered list (non-destructive); updateSimpleSearchFilter routes receive-time + date-range edits to searchFilterProvider. Executor pagination/cursor rules stay covered by search_email_notifier_test and search_pagination_strategy_test. dart analyze clean.
  • E2E — the [Cherry-pick v0.29.x → master] Fix some issue search #4651 search_email_sort_order_date_filter_not_leak scenario + runner are removed. They set up the leak by injecting cursors into the SSOT through the controller — the exact path this refactor deletes — so the check is no longer expressible and its assertions would be vacuous. The invariant it guarded (cursors never leak into the next query) is now structural and directly unit-tested: search_pagination_strategy_test ("stale cursors on the committed filter are never carried into a request"), search_email_notifier_test ("NewSearchIntent clears load-more cursors regardless of prior SSOT values"), search_filter_notifier_test ("set strips pagination cursors").
  • Manual mobile regression (DoD): live websocket refresh, load-more append, selection during load-more, and the filter chips reflecting the committed filter.

Summary by CodeRabbit

  • New Features
    • Added a visible “Clear filter” action in email search when filters are active.
  • Bug Fixes
    • Improved search behavior so filter changes (sorting/date range/folder/label) and load-more actions update consistently.
    • WebSocket-driven updates now refresh results while preserving the current list if refresh fails.
  • Tests
    • Added widget test coverage for search, filtering, load-more, and WebSocket refresh behavior.

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

This PR migrates mobile email search from GetX-owned filter mirrors and direct interactor calls to Riverpod-backed committed filter state and executor intents. SearchEmailController now reads from searchFilterProvider, dispatches new-search/load-more/refresh work through searchEmailProvider, and bridges results back into the existing view state. SearchEmailView now watches the committed filter for chip and menu state, a new clear-filter button was added, bindings were trimmed, controller tests were added, and obsolete integration search tests were removed.

Possibly related issues

Possibly related PRs

Suggested labels: search

Suggested reviewers: tddang-linagora, hoangdat, codescene-delta-analysis

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The controller refactor matches #4645, but SearchEmailView also gains Riverpod filter-state wiring, which the issue marks as out of scope. Remove the SearchEmailView Riverpod changes and keep the view GetX-fed by the controller bridge, or split that work into a follow-up PR.
Out of Scope Changes check ⚠️ Warning The diff adds Riverpod/Consumer logic to SearchEmailView, which is unrelated to the controller-only migration and explicitly out of scope. Limit this PR to the controller and bridge changes, or move the view migration into a separate follow-up change.
✅ Passed checks (3 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main refactor: mobile search moving to the central executor and SSOT.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/tf-4645-ssot-4-mobile-search-executor

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

codescene-delta-analysis[bot]

This comment was marked as outdated.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/features/search/email/presentation/search_email_controller.dart`:
- Around line 749-751: The doc comment on searchEmailController’s filter routing
is stale because it still references the removed GetX mirror and onInit syncing
back to `.obs` fields. Update the comment near the searchFilterProvider-related
getter/method to describe the current flow only: the view reads directly from
`searchFilterProvider` and there is no mirror or back-sync through GetX state
anymore.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9875c516-1bc3-42f2-ba15-72231de34249

📥 Commits

Reviewing files that changed from the base of the PR and between 872715c and 0196112.

📒 Files selected for processing (7)
  • integration_test/scenarios/search/search_email_sort_order_date_filter_not_leak_scenario.dart
  • integration_test/tests/search/search_email_sort_order_date_filter_not_leak_test.dart
  • lib/features/search/email/presentation/riverpod_widgets/clear_search_filter_button.dart
  • lib/features/search/email/presentation/search_email_bindings.dart
  • lib/features/search/email/presentation/search_email_controller.dart
  • lib/features/search/email/presentation/search_email_view.dart
  • test/features/search/email/presentation/search_email_controller_test.dart
💤 Files with no reviewable changes (3)
  • integration_test/tests/search/search_email_sort_order_date_filter_not_leak_test.dart
  • integration_test/scenarios/search/search_email_sort_order_date_filter_not_leak_scenario.dart
  • lib/features/search/email/presentation/search_email_bindings.dart

Comment thread lib/features/search/email/presentation/search_email_controller.dart Outdated
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

This PR has been deployed to https://linagora.github.io/tmail-flutter/4686.

@codescene-delta-analysis codescene-delta-analysis 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.

Code Health Improved (2 files improve in Code Health)

Our agent can fix these. Install it.

Gates Passed
3 Quality Gates Passed

View Improvements
File Code Health Impact Categories Improved
search_email_controller.dart 8.62 → 8.82 Complex Method
search_email_view.dart 8.81 → 9.23 Large Method

Quality Gate Profile: The Bare Minimum
Install CodeScene MCP: safeguard and uplift AI-generated code. Catch issues early with our IDE extension and CLI tool.

@dab246 dab246 added the search label Jul 7, 2026
@Arsnael

Arsnael commented Jul 7, 2026

Copy link
Copy Markdown
Member

Docker image published for this PR: linagora/tmail-web-pr:4686

@hoangdat hoangdat changed the base branch from master to features/ssot-search July 10, 2026 08:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SSOT Part 4 — Migrate mobile search to the central executor (SearchEmailController)

3 participants