Skip to content

TF-4644 SSOT Part 3.5 — Apply Riverpod SSOT to Advanced Search#4694

Open
dab246 wants to merge 4 commits into
features/ssot-searchfrom
fix/tf-4644-ssot-3.5-apply-riverpod-for-advanced-search
Open

TF-4644 SSOT Part 3.5 — Apply Riverpod SSOT to Advanced Search#4694
dab246 wants to merge 4 commits into
features/ssot-searchfrom
fix/tf-4644-ssot-3.5-apply-riverpod-for-advanced-search

Conversation

@dab246

@dab246 dab246 commented Jul 8, 2026

Copy link
Copy Markdown
Member

Closes #4644

Summary

Move Advanced Search filter state to the committed searchFilterProvider so the form, result chips, quick-search chips, and search execution read from the same source of truth.

Changes

  • Replaced Advanced Search controller-owned filter fields with Consumer reads and SearchFilterNotifier mutations.
  • Derived sender and recipient tag lists from searchFilterProvider instead of maintaining duplicate mutable lists.
  • Added explicit single-field mutation helpers and typed filter input wrappers to keep update intent clear and reduce primitive-heavy APIs.
  • Removed dead Advanced Search synchronization and label update extension code.
  • Added and updated unit/widget tests for notifier mutations, controller behavior, checkbox interactions, and SSOT mirror behavior.

Summary by CodeRabbit

  • New Features

    • Advanced email search now keeps filter selections in sync more reliably across the search panel.
    • Search criteria like sender, recipient, date range, labels, sorting, and status filters are handled more consistently.
  • Bug Fixes

    • Fixed issues where clearing or reopening advanced search could lose selected values.
    • Improved behavior for checkbox, autocomplete, and date-range changes so applied filters match what users selected.

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b17cf2c8-c99a-43b7-b04c-23dbe4ad0f53

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/tf-4644-ssot-3.5-apply-riverpod-for-advanced-search

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.

@dab246 dab246 added the search label Jul 8, 2026
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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_filter_form_bottom_view.dart (1)

73-95: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Move this FocusNode out of build(). Creating it inline allocates a new node on every rebuild and never disposes the old one. KeyboardListener also only sees Tab when its node has focus, so keep it long-lived and give it focus when this handler should run.

🤖 Prompt for 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.

In
`@lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_filter_form_bottom_view.dart`
around lines 73 - 95, Move the inline FocusNode used by KeyboardListener in
advanced_search_filter_form_bottom_view out of build() and make it a long-lived
member so it is not recreated on every rebuild or left undisposed. Update the
widget state/class that contains the search button and _onClickSearchButton flow
to own and dispose this node properly, then use that stored node in
KeyboardListener. If Tab handling should run here, request focus on that node
when needed so KeyboardListener can actually receive the key events.
🧹 Nitpick comments (2)
test/features/search/email/domain/notifier/search_filter_notifier_test.dart (1)

82-98: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add a test case for setHasAttachment(false.asSearchFilterToggle()).

setHasAttachment uses exactOption (returns Some(false) for unselected), while setUnread and setNotIncludeEvents use enabledOnlyOption (returns None()). This is a distinct code path — Some(false) vs None() — but only the true case is tested for setHasAttachment. A regression where setHasAttachment(false) accidentally uses enabledOnlyOption would go undetected.

🧪 Suggested test addition
     notifierOf().setHasAttachment(true.asSearchFilterToggle());
     notifierOf().setUnread(true.asSearchFilterToggle());
     notifierOf().setNotIncludeEvents(true.asSearchFilterToggle());
     notifierOf().setSortOrder(EmailSortOrderType.oldest);

     expect(stateOf().hasAttachment, isTrue);
     expect(stateOf().unread, isTrue);
     expect(stateOf().notIncludeEvents, isTrue);
     expect(stateOf().sortOrderType, EmailSortOrderType.oldest);

+    notifierOf().setHasAttachment(false.asSearchFilterToggle());
     notifierOf().setUnread(false.asSearchFilterToggle());
     notifierOf().setNotIncludeEvents(false.asSearchFilterToggle());

+    expect(stateOf().hasAttachment, isFalse);
     expect(stateOf().unread, isFalse);
     expect(stateOf().notIncludeEvents, isFalse);
🤖 Prompt for 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.

In `@test/features/search/email/domain/notifier/search_filter_notifier_test.dart`
around lines 82 - 98, Add a test case in search_filter_notifier_test.dart
covering setHasAttachment(false.asSearchFilterToggle()) alongside the existing
boolean and sort helpers test. The current test in search_filter_notifier_test
only verifies the true path for setHasAttachment, so extend the
notifierOf()/stateOf() assertions to confirm that calling setHasAttachment with
false updates hasAttachment to false and exercises the exactOption path used by
setHasAttachment. Keep the existing checks for setUnread and setNotIncludeEvents
unchanged.
test/features/mailbox_dashboard/presentation/controller/advanced_filter_controller_test.dart (1)

536-586: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Prefer stable keys over index-based checkbox lookups. The starred, unread, and notIncludeEvents tests in test/features/mailbox_dashboard/presentation/controller/advanced_filter_controller_test.dart use find.byType(CustomIconLabeledCheckbox).at(index), while the has-attachment checkbox already uses a ValueKey. Add keys to the remaining checkboxes in lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_filter_form_bottom_view.dart and switch the tests to find.byKey so reordering or inserting a checkbox does not target the wrong field.

🤖 Prompt for 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.

In
`@test/features/mailbox_dashboard/presentation/controller/advanced_filter_controller_test.dart`
around lines 536 - 586, The starred, unread, and notIncludeEvents tests are
using index-based checkbox lookup, which is fragile if the checkbox order
changes. Add stable ValueKey identifiers to the corresponding checkbox widgets
in advanced_search_filter_form_bottom_view and update the related tests to use
find.byKey instead of find.byType(CustomIconLabeledCheckbox).at(...). Keep the
existing has-attachment key pattern as the reference for locating the correct
checkbox widgets.
🤖 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/domain/model/search_filter_input.dart`:
- Around line 40-44: The commaSeparatedSetOption getter currently trims and
deduplicates comma-separated values but still allows empty strings into the Set,
so update the mapping chain to filter out empty results before building the set.
Use the commaSeparatedSetOption symbol in SearchFilterInput and add a
where/exclude-empty step after splitting and trimming so inputs like
"apple,,banana" or "apple, ," do not produce a "" entry.

---

Outside diff comments:
In
`@lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_filter_form_bottom_view.dart`:
- Around line 73-95: Move the inline FocusNode used by KeyboardListener in
advanced_search_filter_form_bottom_view out of build() and make it a long-lived
member so it is not recreated on every rebuild or left undisposed. Update the
widget state/class that contains the search button and _onClickSearchButton flow
to own and dispose this node properly, then use that stored node in
KeyboardListener. If Tab handling should run here, request focus on that node
when needed so KeyboardListener can actually receive the key events.

---

Nitpick comments:
In
`@test/features/mailbox_dashboard/presentation/controller/advanced_filter_controller_test.dart`:
- Around line 536-586: The starred, unread, and notIncludeEvents tests are using
index-based checkbox lookup, which is fragile if the checkbox order changes. Add
stable ValueKey identifiers to the corresponding checkbox widgets in
advanced_search_filter_form_bottom_view and update the related tests to use
find.byKey instead of find.byType(CustomIconLabeledCheckbox).at(...). Keep the
existing has-attachment key pattern as the reference for locating the correct
checkbox widgets.

In `@test/features/search/email/domain/notifier/search_filter_notifier_test.dart`:
- Around line 82-98: Add a test case in search_filter_notifier_test.dart
covering setHasAttachment(false.asSearchFilterToggle()) alongside the existing
boolean and sort helpers test. The current test in search_filter_notifier_test
only verifies the true path for setHasAttachment, so extend the
notifierOf()/stateOf() assertions to confirm that calling setHasAttachment with
false updates hasAttachment to false and exercises the exactOption path used by
setHasAttachment. Keep the existing checks for setUnread and setNotIncludeEvents
unchanged.
🪄 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: 3f8c08ba-3575-406d-b3bb-444e6a783134

📥 Commits

Reviewing files that changed from the base of the PR and between e44f474 and d6903e5.

📒 Files selected for processing (12)
  • lib/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart
  • lib/features/mailbox_dashboard/presentation/controller/search_controller.dart
  • lib/features/mailbox_dashboard/presentation/extensions/advanced_search/update_label_in_advanced_search_extension.dart
  • lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_filter_form_bottom_view.dart
  • lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_input_form.dart
  • lib/features/mailbox_dashboard/presentation/widgets/advanced_search/icon_open_advanced_search_widget.dart
  • lib/features/search/email/domain/model/search_filter_input.dart
  • lib/features/search/email/domain/notifier/search_filter_mutation.dart
  • lib/features/search/email/domain/notifier/search_filter_notifier.dart
  • test/features/mailbox_dashboard/presentation/controller/advanced_filter_controller_test.dart
  • test/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller_test.dart
  • test/features/search/email/domain/notifier/search_filter_notifier_test.dart
💤 Files with no reviewable changes (1)
  • lib/features/mailbox_dashboard/presentation/extensions/advanced_search/update_label_in_advanced_search_extension.dart

Comment thread lib/features/search/email/domain/model/search_filter_input.dart
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

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

@@ -172,19 +196,28 @@ void main() {
group('applyAdvancedSearchFilter::test', () {
test('SHOULD make sure memory search filter and search filter should be the same after applying', () async {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

we should update the name of test more precise

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

fixed

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

idem, now we dont have MemorySearchFilter

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

fixed

import 'package:tmail_ui_user/features/search/email/domain/notifier/search_filter_notifier.dart';
import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart';

void main() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

please add test for

  • setMailbox
  • toggleLabel
  • setHasAttachment for the false branch

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

added

@hoangdat

hoangdat commented Jul 9, 2026

Copy link
Copy Markdown
Member
  • please add the group test for specific cases which relate to draft filter but not commited, IMO widget tests are ok?

dab246 added 2 commits July 9, 2026 18:26
Signed-off-by: dab246 <tdvu@linagora.com>
…etHasAttachment false branch

Signed-off-by: dab246 <tdvu@linagora.com>

@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 (1 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
advanced_search_input_form.dart 9.16 → 10.00 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 commented Jul 9, 2026

Copy link
Copy Markdown
Member Author
  • please add the group test for specific cases which relate to draft filter but not commited, IMO widget tests are ok?

added

@dab246 dab246 requested a review from hoangdat July 9, 2026 11:28
@Arsnael

Arsnael commented Jul 9, 2026

Copy link
Copy Markdown
Member

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

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.

4 participants