Skip to content

TF-4229 Add a new field in search#4230

Merged
hoangdat merged 8 commits intomasterfrom
features/tf-4229-add-a-new-field-in-search
Jan 22, 2026
Merged

TF-4229 Add a new field in search#4230
hoangdat merged 8 commits intomasterfrom
features/tf-4229-add-a-new-field-in-search

Conversation

@dab246
Copy link
Member

@dab246 dab246 commented Jan 2, 2026

Issue

#4229

Resolved

  • Web:
Screen.Recording.2026-01-02.at.18.03.07.mov
  • Mobile:
demo-mobile.webm

Summary by CodeRabbit

Release Notes

  • New Features

    • Added label-based email filtering in search and advanced search views.
    • Users can now select labels to filter and search emails by tags.
  • Bug Fixes

    • Improved label color handling to ensure consistent fallback behavior.
  • Chores

    • Enhanced integration test infrastructure for label-related testing scenarios.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 2, 2026

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.

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

Walkthrough

This PR introduces comprehensive label-based email filtering and management capabilities. It adds new lifecycle hooks to the base test scenario framework, provisions label and email test data through new mixins and models, implements label selection UI components in advanced search and quick search filters, extends the email search filter pipeline to support label-based filtering, updates email views to leverage new label availability logic, adds keyword support to email creation, and includes integration tests for searching emails by labels. The changes span test infrastructure, domain models, presentation controllers, UI widgets, and localization resources.

Possibly related PRs

  • TF-4179 Display tag list in sidebar #4181: Modifies label capability and availability logic in MailboxDashBoardController, aligning with this PR's refactoring of label availability checks across controllers and views.
  • TF-4193 [Label] Config Label in Setting #4194: Updates label setting and capability handling in email and mailbox views, directly overlapping with this PR's modifications to isLabelCapabilitySupported and isLabelAvailable logic.
  • TF-4178 Create a new label #4182: Introduces label creation APIs and the CreateNewLabelInteractor that this PR depends on for label provisioning in integration tests.

Suggested reviewers

  • hoangdat
  • tddang-linagora
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Add a new field in search' is vague and does not clearly convey the main change, which involves adding label-based search filtering across multiple components. Consider a more descriptive title like 'Add label search field and filtering support' or 'Implement label-based email search across web and mobile' to better communicate the primary change.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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 and usage tips.

@github-actions
Copy link

github-actions bot commented Jan 2, 2026

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

@dab246
Copy link
Member Author

dab246 commented Jan 7, 2026

  • Add integration test for mobile

The integration test results may be inaccurate due to an error in the Email/query. We have raised the issue here. linagora/tmail-backend#2039 (comment)

@chibenwa
Copy link
Member

chibenwa commented Jan 7, 2026

@coderabbitai can you please review this?

@coderabbitai
Copy link

coderabbitai bot commented Jan 7, 2026

@chibenwa: I'll review the changes in this PR.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (2)
lib/features/composer/presentation/model/create_email_request.dart (1)

117-118: Pre-existing issue: duplicate references in props.

Lines 117-118 both list references, but line 117 should likely be messageId based on the field declaration at line 41. This affects the Equatable equality comparison.

🔧 Suggested fix
     unsubscribeEmailId,
-    references,
+    messageId,
     references,
lib/features/base/widget/popup_menu/popup_menu_item_action_widget.dart (1)

224-239: Add missing isSelected check for non-RTL selected icon rendering.

The selectedIconWidget rendering is asymmetric between RTL and non-RTL layouts:

  • Line 176: Shows with isSelected check
  • Line 224 (non-RTL): Shows without isSelected check
  • Line 239 (RTL): Shows with isSelected check

This asymmetry affects real actions that override isArrangeRTL => false (e.g., PopupMenuItemLabelTypeAction), causing the selected icon to display regardless of selection state in non-RTL mode. Either add isSelected && to line 224 to match the other paths, or document why this path intentionally differs.

🤖 Fix all issues with AI agents
In @lib/features/base/widget/context_menu/context_menu_dialog_item.dart:
- Around line 91-92: The non-RTL branch is rendering selectedIconWidget without
checking isSelected, causing asymmetry with the RTL branch; update the
conditional to require isSelected as well (i.e., change the check to
!isArrangeRTL && isSelected && selectedIconWidget != null so selectedIconWidget
only renders when the item is selected). Apply the same change in the popup menu
widget where a similar pattern exists (wrap the non-RTL selectedIconWidget
render with isSelected && in addition to the existing checks).

In
@lib/features/mailbox_dashboard/presentation/model/search/search_email_filter.dart:
- Around line 154-155: The code unconditionally creates an EmailFilterCondition
using label!.keyword?.value which can be null; update the condition construction
in search_email_filter.dart so you first read the keyword (e.g., final kw =
label?.keyword?.value) and only add EmailFilterCondition(hasKeyword: kw) when kw
is non-null (and non-empty if desired), replacing the current if (label != null)
EmailFilterCondition(...) usage to guard against null/empty keyword values.
🧹 Nitpick comments (7)
lib/features/manage_account/domain/model/preferences/label_config.dart (1)

13-14: Verify that PlatformInfo.isIntegrationTesting reliably detects the integration test environment.

The logic correctly enables labels by default during integration tests. However, ensure that PlatformInfo.isIntegrationTesting accurately identifies the integration test environment across all test scenarios and doesn't inadvertently enable labels in unintended contexts.

Consider adding a brief comment explaining why the default behavior differs based on the test environment:

// Enable labels by default in integration tests to support test scenarios
factory LabelConfig.initial() =>
    LabelConfig(isEnabled: PlatformInfo.isIntegrationTesting);
lib/features/base/widget/context_menu/context_menu_dialog_item.dart (1)

79-80: Potential spacing inconsistency in non-RTL layouts.

The leadingWidget provides a 24-width spacer when isArrangeRTL is true and iconWidget is null, ensuring consistent leading spacing. However, when isArrangeRTL is false and iconWidget is null, leadingWidget becomes null, which may result in inconsistent left alignment/padding for non-RTL menu items without icons.

Consider using a spacer for non-RTL mode as well to maintain uniform spacing.

♻️ Proposed fix to ensure consistent spacing
-    final leadingWidget =
-        iconWidget ?? (isArrangeRTL ? const SizedBox(width: 24) : null);
+    final leadingWidget = iconWidget ?? const SizedBox(width: 24);
lib/features/mailbox/presentation/base_mailbox_view.dart (1)

27-27: Centralizing label-list visibility on isLabelAvailable is reasonable

Using mailboxDashBoardController.isLabelAvailable (via the new extension import) keeps the “should we show the label list?” logic in one place and makes buildLabelsList simpler. The remaining use of isLabelCapabilitySupported and isLabelSettingEnabled in buildLabelsBar is acceptable, but if you ever need identical gating semantics for bar and list, consider reusing isLabelAvailable there as well to avoid drift.

Also applies to: 383-409

lib/features/mailbox_dashboard/presentation/extensions/select_search_filter_action_extension.dart (1)

37-46: Consider renaming or documenting the method's scope.

The method deleteQuickSearchFilter is named generically but currently only handles QuickSearchFilter.labels. This creates an inconsistency with the existing dedicated methods (deleteStarredSearchFilter, deleteUnreadSearchFilter).

Consider either:

  1. Renaming to deleteLabelSearchFilter for consistency with existing methods
  2. Adding documentation explaining why some filters have dedicated methods while others use the generic handler
  3. Migrating starred/unread handling into this method for consistency

The switch pattern suggests future extensibility, but the current design makes the handling strategy unclear.

integration_test/scenarios/search/search_email_with_tag_scenario.dart (1)

75-85: Consider adding a brief comment explaining the subject-based verification.

The test verifies email filtering by checking if the email's subject contains the tag display name. This works because buildEmailsForLabel presumably includes the tag name in the email subject. A brief comment would make this relationship clearer for future maintainers.

💡 Suggested comment
   Future<void> _expectEmailListDisplayedCorrectByTag({
     required String tagDisplayName,
     required int emailCount,
   }) async {
+    // Emails provisioned by buildEmailsForLabel include the tag name in the subject
     final listEmailTileWithTag = $.tester.widgetList<EmailTileBuilder>(
       $(EmailTileBuilder).which<EmailTileBuilder>((widget) =>
           widget.presentationEmail.subject?.contains(tagDisplayName) == true),
     );

     expect(listEmailTileWithTag.length, greaterThanOrEqualTo(emailCount));
   }
lib/features/mailbox_dashboard/presentation/model/search/quick_search_filter.dart (1)

95-96: Consider icon selection consistency.

Unlike other quick search filters (hasAttachment, starred, unread), the labels case doesn't use the isSelected parameter to show different icons. Other filters show icSelectedSB when selected.

Is this intentional? If labels should follow the same pattern:

♻️ Optional refactor for consistency
       case QuickSearchFilter.labels:
-        return imagePaths.icTag;
+        return isSelected ? imagePaths.icSelectedSB : imagePaths.icTag;
integration_test/mixin/provisioning_label_scenario_mixin.dart (1)

12-45: LGTM! Well-structured label provisioning with proper null handling.

The mixin correctly uses getBinding<T>() which returns null when not found (no try/catch needed per GetX patterns). The concurrent label creation with Future.wait and filtering with whereType<Label>() handles partial failures gracefully.

One minor observation: if dashboardController is null, the code will still log and return early due to accountId being null. Consider adding dashboardController to the null-check message for clearer diagnostics:

💡 Optional: More descriptive logging
-    if (createLabelInteractor == null || accountId == null) {
+    if (dashboardController == null ||
+        createLabelInteractor == null ||
+        accountId == null) {
       log(
         'ProvisioningLabelScenarioMixin::provisionLabels '
-        'skipped: missing CreateNewLabelInteractor or accountId',
+        'skipped: missing dashboardController, CreateNewLabelInteractor, or accountId',
       );
       return [];
     }
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1967068 and 1802b90.

📒 Files selected for processing (51)
  • integration_test/base/base_test_scenario.dart
  • integration_test/mixin/provisioning_label_scenario_mixin.dart
  • integration_test/mixin/scenario_utils_mixin.dart
  • integration_test/models/provisioning_email.dart
  • integration_test/models/provisioning_label.dart
  • integration_test/robots/label_list_context_menu_robot.dart
  • integration_test/robots/label_robot.dart
  • integration_test/robots/search_robot.dart
  • integration_test/scenarios/search/search_email_with_tag_scenario.dart
  • integration_test/tests/search/search_email_with_tag_test.dart
  • labels/lib/extensions/label_extension.dart
  • labels/lib/extensions/list_label_extension.dart
  • lib/features/base/mixin/popup_context_menu_action_mixin.dart
  • lib/features/base/model/filter_filter.dart
  • lib/features/base/model/popup_menu_item_action.dart
  • lib/features/base/widget/context_menu/context_menu_dialog_item.dart
  • lib/features/base/widget/context_menu/context_menu_item_action.dart
  • lib/features/base/widget/popup_menu/popup_menu_item_action_widget.dart
  • lib/features/composer/presentation/extensions/create_email_request_extension.dart
  • lib/features/composer/presentation/model/create_email_request.dart
  • lib/features/email/presentation/email_view.dart
  • lib/features/mailbox/presentation/base_mailbox_view.dart
  • lib/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart
  • lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_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/extensions/labels/check_label_available_extension.dart
  • lib/features/mailbox_dashboard/presentation/extensions/labels/handle_logic_label_extension.dart
  • lib/features/mailbox_dashboard/presentation/extensions/select_search_filter_action_extension.dart
  • lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart
  • lib/features/mailbox_dashboard/presentation/model/search/quick_search_filter.dart
  • lib/features/mailbox_dashboard/presentation/model/search/search_email_filter.dart
  • lib/features/mailbox_dashboard/presentation/styles/label_drop_down_style.dart
  • lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_field_widget.dart
  • lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_input_form.dart
  • lib/features/mailbox_dashboard/presentation/widgets/advanced_search/label_drop_down_button.dart
  • lib/features/mailbox_dashboard/presentation/widgets/search_filters/search_filter_button.dart
  • lib/features/manage_account/domain/model/preferences/label_config.dart
  • lib/features/manage_account/presentation/manage_account_dashboard_controller.dart
  • lib/features/search/email/presentation/extension/update_search_filter_extension.dart
  • lib/features/search/email/presentation/mixin/search_label_filter_modal_mixin.dart
  • lib/features/search/email/presentation/model/context_item_label_type_action.dart
  • lib/features/search/email/presentation/model/popup_menu_item_label_type_action.dart
  • lib/features/search/email/presentation/search_email_controller.dart
  • lib/features/search/email/presentation/search_email_view.dart
  • lib/features/thread/presentation/thread_view.dart
  • lib/features/thread_detail/presentation/thread_detail_view.dart
  • lib/l10n/intl_messages.arb
  • lib/main/localizations/app_localizations.dart
  • test/features/composer/data/repository/composer_repository_impl_test.dart
  • test/features/composer/presentation/extensions/create_email_request_extension_test.dart
🧰 Additional context used
🧠 Learnings (13)
📓 Common learnings
Learnt from: dab246
Repo: linagora/tmail-flutter PR: 4204
File: lib/features/email/data/datasource_impl/email_hive_cache_datasource_impl.dart:579-582
Timestamp: 2025-12-12T07:56:31.877Z
Learning: In lib/features/email/data/datasource_impl/email_hive_cache_datasource_impl.dart, the addLabelToEmail method intentionally throws UnimplementedError because label synchronization with the email cache is handled separately via extension methods (e.g., _autoSyncLabelToSelectedEmailOnMemory in handle_label_for_email_extension.dart). Implementing it in the cache datasource would cause data conflicts. This differs from other keyword operations like markAsRead, markAsStar, markAsAnswered, and markAsForwarded, which are implemented directly in the cache datasource.
📚 Learning: 2025-12-12T09:03:05.962Z
Learnt from: dab246
Repo: linagora/tmail-flutter PR: 4204
File: lib/features/email/presentation/model/popup_menu_item_email_action.dart:34-35
Timestamp: 2025-12-12T09:03:05.962Z
Learning: In the tmail-flutter codebase, popup menu items intentionally use a consistent hoverIcon (imagePaths.icThumbsUp) across all popup item types (email actions, mailbox actions, profile settings, etc.), while actionIcon varies per action type. This is a deliberate UI/UX design choice.

Applied to files:

  • lib/features/base/model/popup_menu_item_action.dart
  • lib/features/search/email/presentation/model/context_item_label_type_action.dart
  • lib/features/base/widget/context_menu/context_menu_dialog_item.dart
  • lib/features/mailbox_dashboard/presentation/widgets/search_filters/search_filter_button.dart
  • lib/features/base/widget/context_menu/context_menu_item_action.dart
  • lib/features/search/email/presentation/mixin/search_label_filter_modal_mixin.dart
  • lib/features/search/email/presentation/model/popup_menu_item_label_type_action.dart
  • lib/features/base/widget/popup_menu/popup_menu_item_action_widget.dart
  • lib/features/base/mixin/popup_context_menu_action_mixin.dart
📚 Learning: 2025-12-09T09:36:45.349Z
Learnt from: dab246
Repo: linagora/tmail-flutter PR: 4194
File: lib/features/manage_account/presentation/manage_account_dashboard_controller.dart:174-176
Timestamp: 2025-12-09T09:36:45.349Z
Learning: In Dart/Flutter projects using GetX, do not wrap getBinding<T>() calls in try/catch since they return null when not found. Only wrap Get.find<T>() calls in try/catch because they throw if a dependency is unavailable. When a binding is optional, consider checking Get.isRegistered<T>() or handling the null/exception path gracefully instead of blindly catching, and document the expectation for failure modes where a dependency may not be registered.

Applied to files:

  • lib/features/base/model/popup_menu_item_action.dart
  • lib/features/mailbox_dashboard/presentation/extensions/advanced_search/update_label_in_advanced_search_extension.dart
  • lib/features/mailbox_dashboard/presentation/extensions/labels/check_label_available_extension.dart
  • integration_test/robots/search_robot.dart
  • lib/main/localizations/app_localizations.dart
  • lib/features/email/presentation/email_view.dart
  • lib/features/search/email/presentation/extension/update_search_filter_extension.dart
  • integration_test/tests/search/search_email_with_tag_test.dart
  • lib/features/search/email/presentation/model/context_item_label_type_action.dart
  • integration_test/models/provisioning_label.dart
  • integration_test/models/provisioning_email.dart
  • integration_test/scenarios/search/search_email_with_tag_scenario.dart
  • lib/features/mailbox_dashboard/presentation/extensions/select_search_filter_action_extension.dart
  • lib/features/composer/presentation/model/create_email_request.dart
  • test/features/composer/presentation/extensions/create_email_request_extension_test.dart
  • lib/features/base/widget/context_menu/context_menu_dialog_item.dart
  • lib/features/mailbox_dashboard/presentation/widgets/advanced_search/label_drop_down_button.dart
  • lib/features/mailbox_dashboard/presentation/extensions/labels/handle_logic_label_extension.dart
  • lib/features/mailbox_dashboard/presentation/widgets/search_filters/search_filter_button.dart
  • lib/features/base/widget/context_menu/context_menu_item_action.dart
  • lib/features/mailbox/presentation/base_mailbox_view.dart
  • lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_input_form.dart
  • lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_field_widget.dart
  • lib/features/search/email/presentation/mixin/search_label_filter_modal_mixin.dart
  • lib/features/mailbox_dashboard/presentation/model/search/search_email_filter.dart
  • lib/features/mailbox_dashboard/presentation/styles/label_drop_down_style.dart
  • lib/features/thread/presentation/thread_view.dart
  • lib/features/search/email/presentation/model/popup_menu_item_label_type_action.dart
  • test/features/composer/data/repository/composer_repository_impl_test.dart
  • lib/features/base/widget/popup_menu/popup_menu_item_action_widget.dart
  • lib/features/manage_account/domain/model/preferences/label_config.dart
  • lib/features/base/mixin/popup_context_menu_action_mixin.dart
  • lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart
  • lib/features/manage_account/presentation/manage_account_dashboard_controller.dart
  • labels/lib/extensions/label_extension.dart
  • integration_test/mixin/provisioning_label_scenario_mixin.dart
  • lib/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart
  • integration_test/mixin/scenario_utils_mixin.dart
  • lib/features/mailbox_dashboard/presentation/model/search/quick_search_filter.dart
  • integration_test/robots/label_robot.dart
  • lib/features/thread_detail/presentation/thread_detail_view.dart
  • integration_test/robots/label_list_context_menu_robot.dart
  • lib/features/base/model/filter_filter.dart
  • lib/features/composer/presentation/extensions/create_email_request_extension.dart
  • integration_test/base/base_test_scenario.dart
  • labels/lib/extensions/list_label_extension.dart
  • lib/features/mailbox_dashboard/presentation/controller/search_controller.dart
  • lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart
  • lib/features/search/email/presentation/search_email_controller.dart
  • lib/features/search/email/presentation/search_email_view.dart
📚 Learning: 2025-12-09T12:47:45.861Z
Learnt from: zatteo
Repo: linagora/tmail-flutter PR: 4196
File: scribe/lib/scribe/ai/data/datasource_impl/ai_datasource_impl.dart:34-35
Timestamp: 2025-12-09T12:47:45.861Z
Learning: In the tmail-flutter repository, avoid suggesting replacing DioError with DioException unless there is a codebase-wide migration. This pattern applies to all Dart files; when reviewing, only propose a DioError-safe change (e.g., compatible error handling or conversion) unless a global migration is in place. Ensure consistency of DioError usage across modules and flag any deviations for a repo-wide decision.

Applied to files:

  • lib/features/base/model/popup_menu_item_action.dart
  • lib/features/mailbox_dashboard/presentation/extensions/advanced_search/update_label_in_advanced_search_extension.dart
  • lib/features/mailbox_dashboard/presentation/extensions/labels/check_label_available_extension.dart
  • integration_test/robots/search_robot.dart
  • lib/main/localizations/app_localizations.dart
  • lib/features/email/presentation/email_view.dart
  • lib/features/search/email/presentation/extension/update_search_filter_extension.dart
  • integration_test/tests/search/search_email_with_tag_test.dart
  • lib/features/search/email/presentation/model/context_item_label_type_action.dart
  • integration_test/models/provisioning_label.dart
  • integration_test/models/provisioning_email.dart
  • integration_test/scenarios/search/search_email_with_tag_scenario.dart
  • lib/features/mailbox_dashboard/presentation/extensions/select_search_filter_action_extension.dart
  • lib/features/composer/presentation/model/create_email_request.dart
  • test/features/composer/presentation/extensions/create_email_request_extension_test.dart
  • lib/features/base/widget/context_menu/context_menu_dialog_item.dart
  • lib/features/mailbox_dashboard/presentation/widgets/advanced_search/label_drop_down_button.dart
  • lib/features/mailbox_dashboard/presentation/extensions/labels/handle_logic_label_extension.dart
  • lib/features/mailbox_dashboard/presentation/widgets/search_filters/search_filter_button.dart
  • lib/features/base/widget/context_menu/context_menu_item_action.dart
  • lib/features/mailbox/presentation/base_mailbox_view.dart
  • lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_input_form.dart
  • lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_field_widget.dart
  • lib/features/search/email/presentation/mixin/search_label_filter_modal_mixin.dart
  • lib/features/mailbox_dashboard/presentation/model/search/search_email_filter.dart
  • lib/features/mailbox_dashboard/presentation/styles/label_drop_down_style.dart
  • lib/features/thread/presentation/thread_view.dart
  • lib/features/search/email/presentation/model/popup_menu_item_label_type_action.dart
  • test/features/composer/data/repository/composer_repository_impl_test.dart
  • lib/features/base/widget/popup_menu/popup_menu_item_action_widget.dart
  • lib/features/manage_account/domain/model/preferences/label_config.dart
  • lib/features/base/mixin/popup_context_menu_action_mixin.dart
  • lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart
  • lib/features/manage_account/presentation/manage_account_dashboard_controller.dart
  • labels/lib/extensions/label_extension.dart
  • integration_test/mixin/provisioning_label_scenario_mixin.dart
  • lib/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart
  • integration_test/mixin/scenario_utils_mixin.dart
  • lib/features/mailbox_dashboard/presentation/model/search/quick_search_filter.dart
  • integration_test/robots/label_robot.dart
  • lib/features/thread_detail/presentation/thread_detail_view.dart
  • integration_test/robots/label_list_context_menu_robot.dart
  • lib/features/base/model/filter_filter.dart
  • lib/features/composer/presentation/extensions/create_email_request_extension.dart
  • integration_test/base/base_test_scenario.dart
  • labels/lib/extensions/list_label_extension.dart
  • lib/features/mailbox_dashboard/presentation/controller/search_controller.dart
  • lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart
  • lib/features/search/email/presentation/search_email_controller.dart
  • lib/features/search/email/presentation/search_email_view.dart
📚 Learning: 2025-12-12T04:54:11.121Z
Learnt from: dab246
Repo: linagora/tmail-flutter PR: 4191
File: lib/features/email/presentation/extensions/handle_email_action_extension.dart:37-80
Timestamp: 2025-12-12T04:54:11.121Z
Learning: In lib/features/email/presentation/extensions/handle_email_action_extension.dart, the mailboxDashBoardController.selectedEmail should only be synchronized when isMobileThreadDisabled is true. This is intentional behavior and should not be changed to update selectedEmail in non-mobile or thread-enabled contexts.

Applied to files:

  • lib/features/mailbox_dashboard/presentation/extensions/advanced_search/update_label_in_advanced_search_extension.dart
  • lib/features/mailbox_dashboard/presentation/extensions/labels/check_label_available_extension.dart
  • lib/features/email/presentation/email_view.dart
  • lib/features/search/email/presentation/extension/update_search_filter_extension.dart
  • lib/features/search/email/presentation/model/context_item_label_type_action.dart
  • lib/features/mailbox_dashboard/presentation/extensions/select_search_filter_action_extension.dart
  • test/features/composer/presentation/extensions/create_email_request_extension_test.dart
  • lib/features/mailbox_dashboard/presentation/extensions/labels/handle_logic_label_extension.dart
  • lib/features/mailbox_dashboard/presentation/widgets/search_filters/search_filter_button.dart
  • lib/features/mailbox/presentation/base_mailbox_view.dart
  • lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_input_form.dart
  • lib/features/mailbox_dashboard/presentation/model/search/search_email_filter.dart
  • lib/features/thread/presentation/thread_view.dart
  • lib/features/search/email/presentation/model/popup_menu_item_label_type_action.dart
  • lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart
  • lib/features/manage_account/presentation/manage_account_dashboard_controller.dart
  • lib/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart
  • integration_test/mixin/scenario_utils_mixin.dart
  • lib/features/mailbox_dashboard/presentation/model/search/quick_search_filter.dart
  • lib/features/thread_detail/presentation/thread_detail_view.dart
  • lib/features/composer/presentation/extensions/create_email_request_extension.dart
  • lib/features/mailbox_dashboard/presentation/controller/search_controller.dart
  • lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart
  • lib/features/search/email/presentation/search_email_controller.dart
  • lib/features/search/email/presentation/search_email_view.dart
📚 Learning: 2025-12-12T07:43:26.643Z
Learnt from: dab246
Repo: linagora/tmail-flutter PR: 4204
File: lib/features/email/presentation/extensions/handle_label_for_email_extension.dart:94-148
Timestamp: 2025-12-12T07:43:26.643Z
Learning: In lib/features/email/presentation/extensions/handle_label_for_email_extension.dart and similar keyword synchronization code, the addKeyword() function is the preferred method for adding keywords to emails. The resyncKeywords() pattern is being phased out and will be replaced in favor of addKeyword().

Applied to files:

  • lib/features/mailbox_dashboard/presentation/extensions/advanced_search/update_label_in_advanced_search_extension.dart
  • lib/features/mailbox_dashboard/presentation/extensions/labels/check_label_available_extension.dart
  • lib/features/email/presentation/email_view.dart
  • lib/features/search/email/presentation/extension/update_search_filter_extension.dart
  • integration_test/models/provisioning_email.dart
  • lib/features/mailbox_dashboard/presentation/extensions/select_search_filter_action_extension.dart
  • lib/features/composer/presentation/model/create_email_request.dart
  • test/features/composer/presentation/extensions/create_email_request_extension_test.dart
  • lib/features/mailbox_dashboard/presentation/widgets/advanced_search/label_drop_down_button.dart
  • lib/features/mailbox_dashboard/presentation/extensions/labels/handle_logic_label_extension.dart
  • lib/features/mailbox_dashboard/presentation/widgets/search_filters/search_filter_button.dart
  • lib/features/mailbox/presentation/base_mailbox_view.dart
  • lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_input_form.dart
  • lib/features/mailbox_dashboard/presentation/model/search/search_email_filter.dart
  • lib/features/thread/presentation/thread_view.dart
  • lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart
  • lib/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart
  • integration_test/mixin/scenario_utils_mixin.dart
  • lib/features/mailbox_dashboard/presentation/model/search/quick_search_filter.dart
  • lib/features/thread_detail/presentation/thread_detail_view.dart
  • lib/features/composer/presentation/extensions/create_email_request_extension.dart
  • labels/lib/extensions/list_label_extension.dart
  • lib/features/mailbox_dashboard/presentation/controller/search_controller.dart
  • lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart
  • lib/features/search/email/presentation/search_email_controller.dart
  • lib/features/search/email/presentation/search_email_view.dart
📚 Learning: 2025-12-12T07:56:31.877Z
Learnt from: dab246
Repo: linagora/tmail-flutter PR: 4204
File: lib/features/email/data/datasource_impl/email_hive_cache_datasource_impl.dart:579-582
Timestamp: 2025-12-12T07:56:31.877Z
Learning: In lib/features/email/data/datasource_impl/email_hive_cache_datasource_impl.dart, the addLabelToEmail method intentionally throws UnimplementedError because label synchronization with the email cache is handled separately via extension methods (e.g., _autoSyncLabelToSelectedEmailOnMemory in handle_label_for_email_extension.dart). Implementing it in the cache datasource would cause data conflicts. This differs from other keyword operations like markAsRead, markAsStar, markAsAnswered, and markAsForwarded, which are implemented directly in the cache datasource.

Applied to files:

  • lib/features/mailbox_dashboard/presentation/extensions/advanced_search/update_label_in_advanced_search_extension.dart
  • lib/features/mailbox_dashboard/presentation/extensions/labels/check_label_available_extension.dart
  • lib/features/email/presentation/email_view.dart
  • lib/features/search/email/presentation/extension/update_search_filter_extension.dart
  • lib/features/search/email/presentation/model/context_item_label_type_action.dart
  • integration_test/models/provisioning_email.dart
  • integration_test/scenarios/search/search_email_with_tag_scenario.dart
  • lib/features/mailbox_dashboard/presentation/extensions/select_search_filter_action_extension.dart
  • test/features/composer/presentation/extensions/create_email_request_extension_test.dart
  • lib/features/mailbox_dashboard/presentation/widgets/advanced_search/label_drop_down_button.dart
  • lib/features/mailbox_dashboard/presentation/extensions/labels/handle_logic_label_extension.dart
  • lib/features/mailbox_dashboard/presentation/widgets/search_filters/search_filter_button.dart
  • lib/features/mailbox/presentation/base_mailbox_view.dart
  • lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_input_form.dart
  • lib/features/search/email/presentation/mixin/search_label_filter_modal_mixin.dart
  • lib/features/mailbox_dashboard/presentation/model/search/search_email_filter.dart
  • lib/features/thread/presentation/thread_view.dart
  • lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart
  • integration_test/mixin/provisioning_label_scenario_mixin.dart
  • lib/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart
  • integration_test/mixin/scenario_utils_mixin.dart
  • lib/features/mailbox_dashboard/presentation/model/search/quick_search_filter.dart
  • lib/features/thread_detail/presentation/thread_detail_view.dart
  • lib/features/composer/presentation/extensions/create_email_request_extension.dart
  • labels/lib/extensions/list_label_extension.dart
  • lib/features/mailbox_dashboard/presentation/controller/search_controller.dart
  • lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart
  • lib/features/search/email/presentation/search_email_controller.dart
  • lib/features/search/email/presentation/search_email_view.dart
📚 Learning: 2025-12-23T05:27:10.887Z
Learnt from: dab246
Repo: linagora/tmail-flutter PR: 4210
File: model/lib/mailbox/presentation_mailbox.dart:22-34
Timestamp: 2025-12-23T05:27:10.887Z
Learning: In the tmail-flutter codebase, the Action Required folder (actionRequiredFolder) is a virtual folder that is AI-curated and contains emails with the keyword "needs-action". Unlike the Favorites folder, users should NOT be able to drag emails into the Action Required folder. The UI correctly prevents this by not wrapping the Action Required folder item in a DragTarget (see mailbox_item_widget.dart).

Applied to files:

  • lib/features/email/presentation/email_view.dart
  • lib/features/search/email/presentation/model/context_item_label_type_action.dart
  • lib/features/mailbox_dashboard/presentation/extensions/select_search_filter_action_extension.dart
  • test/features/composer/presentation/extensions/create_email_request_extension_test.dart
  • lib/features/mailbox_dashboard/presentation/widgets/search_filters/search_filter_button.dart
  • lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_input_form.dart
  • lib/features/thread/presentation/thread_view.dart
  • lib/features/search/email/presentation/model/popup_menu_item_label_type_action.dart
  • lib/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart
  • lib/features/thread_detail/presentation/thread_detail_view.dart
  • lib/features/search/email/presentation/search_email_controller.dart
  • lib/features/search/email/presentation/search_email_view.dart
📚 Learning: 2025-12-18T09:19:32.437Z
Learnt from: dab246
Repo: linagora/tmail-flutter PR: 4203
File: scribe/pubspec.yaml:37-37
Timestamp: 2025-12-18T09:19:32.437Z
Learning: In the tmail-flutter repository, json_annotation version 4.8.0 is the standardized version across modules and should not be upgraded without considering the standardization practice.

Applied to files:

  • test/features/composer/presentation/extensions/create_email_request_extension_test.dart
  • lib/features/manage_account/domain/model/preferences/label_config.dart
  • lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart
  • lib/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart
  • lib/features/mailbox_dashboard/presentation/model/search/quick_search_filter.dart
📚 Learning: 2025-12-23T05:27:40.476Z
Learnt from: dab246
Repo: linagora/tmail-flutter PR: 4210
File: lib/l10n/intl_messages.arb:5151-5182
Timestamp: 2025-12-23T05:27:40.476Z
Learning: In lib/l10n, translations for locale .arb files are updated automatically by an external workflow when new English keys are added to intl_messages.arb. Do not manually modify translated locale .arb files in pull requests; rely on the automated workflow to update translations. If manual edits are necessary, clearly reference the automation workflow and ensure translations remain consistent with the source English keys.

Applied to files:

  • lib/l10n/intl_messages.arb
📚 Learning: 2025-12-19T08:04:06.064Z
Learnt from: hoangdat
Repo: linagora/tmail-flutter PR: 4208
File: lib/l10n/intl_fr.arb:5209-5226
Timestamp: 2025-12-19T08:04:06.064Z
Learning: In all ARB localization files under lib/l10n, AI Scribe translation keys should only be present for the supported locales: en (default), fr, vi, and ru. Do not add AI Scribe keys to other locale files. Ensure fr, vi, and ru ARB files include the same AI Scribe keys as applicable, with en as the source/default. This pattern applies to any ARB file in the lib/l10n directory.

Applied to files:

  • lib/l10n/intl_messages.arb
📚 Learning: 2025-12-15T06:24:38.823Z
Learnt from: dab246
Repo: linagora/tmail-flutter PR: 4137
File: lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart:32-32
Timestamp: 2025-12-15T06:24:38.823Z
Learning: In lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart and lib/features/manage_account/presentation/manage_account_dashboard_controller.dart, the code calls SentryManager.instance.setUser() with PII fields (account ID, display name, username, email). This is privacy-sensitive. Review and ensure PII handling complies with policy: avoid sending unnecessary PII to Sentry, redact or hash sensitive fields if possible, or document explicit privacy policy and user consent for such data. If PII must be sent, ensure minimal data, secure handling, and add notes to the privacy policy. Consider adding tests or a lint rule to flag setUser calls that include PII.

Applied to files:

  • lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart
  • lib/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart
  • lib/features/mailbox_dashboard/presentation/controller/search_controller.dart
📚 Learning: 2025-12-15T06:24:50.369Z
Learnt from: dab246
Repo: linagora/tmail-flutter PR: 4137
File: lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart:32-32
Timestamp: 2025-12-15T06:24:50.369Z
Learning: In lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart and lib/features/manage_account/presentation/manage_account_dashboard_controller.dart, SentryManager.instance.setUser() intentionally sends PII (account ID, display name, username, email) to Sentry for error tracking. The team plans to document this in the app's privacy policy for transparency and compliance.

Applied to files:

  • lib/features/manage_account/presentation/manage_account_dashboard_controller.dart
  • lib/features/thread_detail/presentation/thread_detail_view.dart
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: Build web version and deploy
  • GitHub Check: analyze-test (rule_filter)
  • GitHub Check: analyze-test (server_settings)
  • GitHub Check: analyze-test (forward)
  • GitHub Check: analyze-test (fcm)
  • GitHub Check: analyze-test (email_recovery)
  • GitHub Check: analyze-test (core)
  • GitHub Check: analyze-test (model)
  • GitHub Check: analyze-test (default)
  • GitHub Check: analyze-test (contact)

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.

3 participants