Skip to content

Conversation

@Catrya
Copy link
Member

@Catrya Catrya commented Aug 14, 2025

  • Implement comprehensive filtering logic for currencies, payment methods, premium/discount, and reputation
  • Implement real-time order filtering based on Nostr event tags
  • Convert rating filter to range-based selection with min/max values
  • Integrate dynamic data sources from exchange service and payment methods providers
  • Apply consistent Material Design styling across all filter components
  • Add proper async data handling with loading and error states
  • Ensure visual consistency with app theme and touch interactions
image

Summary by CodeRabbit

  • New Features

    • New filter options: currency, payment methods, rating range, and premium/discount range with Apply and Clear actions.
  • UI

    • Tappable filter card opens a dialog (ripple feedback); multi-selects show styled pills and custom dropdowns; separate live sliders for rating and premium; offers count updates live; loading/error fallbacks.
  • Internationalization

    • Added filter-related translations for English, Spanish, and Italian.
  • Refactor

    • Consolidated filtering to apply all selected criteria before showing results.

  - Implement comprehensive filtering logic for currencies, payment methods, premium/discount, and reputation
  - Implement real-time order filtering based on Nostr event tags
  - Convert rating filter to range-based selection with min/max values
  - Integrate dynamic data sources from exchange service and payment methods providers
  - Apply consistent Material Design styling across all filter components
  - Add proper async data handling with loading and error states
  - Ensure visual consistency with app theme and touch interactions
@Catrya Catrya requested a review from grunch August 14, 2025 23:11
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 14, 2025

Walkthrough

Adds Riverpod-backed UI filters (currency, payment method, rating, premium range), refactors filteredOrdersProvider to consume them, replaces HomeScreen filter control with an interactive InkWell that opens an OrderFilter dialog, and converts OrderFilter to a ConsumerStatefulWidget with async data, multi-selects, and range sliders.

Changes

Cohort / File(s) Summary
Order filtering providers
lib/features/home/providers/home_order_providers.dart
Added currencyFilterProvider, paymentMethodFilterProvider, ratingFilterProvider, premiumRangeFilterProvider; refactored filteredOrdersProvider to read these providers and apply staged filters (currency, payment method, rating, premium) using a mutable set-based flow.
Home screen filter trigger
lib/features/home/screens/home_screen.dart
Replaced static filter control with Material + InkWell that shows a Dialog containing OrderFilter; moved padding into InkWell, added ripple/highlight feedback, preserved offers count display.
Localization (ARB files)
lib/l10n/intl_en.arb, lib/l10n/intl_es.arb, lib/l10n/intl_it.arb
Added apply and multiple filter-related i18n keys and metadata (rating, reputation, premiumRange, discount, premium, clear, min, max, loading keys); EN also adds timeout messages.
OrderFilter widget
lib/shared/widgets/order_filter.dart
Converted to ConsumerStatefulWidget/ConsumerState; loads currencies/payment methods from providers with loading/error fallbacks; staged local selections; enhanced MultiSelectAutocomplete and pills; added premium/discount and reputation RangeSliders; added Apply (writes providers) and Clear (resets providers) actions; full i18n integration.

Sequence Diagram(s)

sequenceDiagram
  participant U as User
  participant HS as HomeScreen
  participant D as Dialog
  participant OF as OrderFilter
  participant RP as Riverpod Providers
  participant FO as filteredOrdersProvider

  U->>HS: Tap filter control
  HS->>D: showDialog(OrderFilter)
  D->>OF: build
  OF->>RP: watch(currencyCodesProvider, paymentMethodsDataProvider, filter providers)
  RP-->>OF: async data + current filter state
  U->>OF: change selections/ranges
  U->>OF: tap Apply
  OF->>RP: update(filter providers)
  RP->>FO: trigger recompute
  FO-->>HS: updated filtered list
  HS-->>U: updated offers count/list
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Possibly related PRs

Suggested reviewers

  • grunch
  • chebizarro

Poem

I twitch my whiskers at options bright,
Coins and methods dancing in soft light,
I nudge the sliders, press Apply with glee,
Clear scatters seeds — selections spring free,
A filtered meadow of offers — hop, delight! 🥕✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch filter

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

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

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@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: 8

🔭 Outside diff range comments (2)
lib/features/home/screens/home_screen.dart (1)

34-36: Fix RefreshIndicator callback: refreshing the wrong provider and returning wrong type.

  • ref.refresh(filteredOrdersProvider) returns a List, not a Future; returning it from onRefresh is incorrect.
  • You should invalidate/refresh the source orders provider instead.

Apply this diff:

-                    onRefresh: () async {
-                      return await ref.refresh(filteredOrdersProvider);
-                    },
+                    onRefresh: () async {
+                      // Re-fetch the underlying source; filtered list will update automatically.
+                      ref.invalidate(orderEventsProvider);
+                    },
lib/shared/widgets/order_filter.dart (1)

31-37: Fix: avoid double-managed TextEditingController (leak) in MultiSelectAutocomplete

You create a controller in initState and then replace it with the one provided by Autocomplete. The provided controller is owned/disposed by Autocomplete; the extra one you created leaks. Make the field nullable, don’t instantiate it yourself, and null-check when clearing.

Apply this diff:

-class MultiSelectAutocompleteState extends State<MultiSelectAutocomplete> {
-  late TextEditingController _controller;
+class MultiSelectAutocompleteState extends State<MultiSelectAutocomplete> {
+  TextEditingController? _controller;
@@
   @override
   void initState() {
     super.initState();
-    _controller = TextEditingController();
   }
@@
   @override
   void dispose() {
-    //_controller.dispose();
     super.dispose();
   }
@@
           onSelected: (String selection) {
             final updated = List<String>.from(widget.selectedValues)
               ..add(selection);
             widget.onChanged(updated);
-            _controller.clear();
+            _controller?.clear();
           },

Also applies to: 39-43, 111-116

🧹 Nitpick comments (4)
lib/features/home/providers/home_order_providers.dart (1)

29-71: Non-blocking: avoid mutating the source orders list before reversing.

sort mutates allOrders. If other consumers share the same instance, consider copying before sorting for isolation.

Outside this range, consider:

final sorted = [...allOrders]..sort((o1, o2) => o1.expirationDate.compareTo(o2.expirationDate));
var filtered = sorted.reversed
    .where((o) => o.orderType == orderType)
    .where((o) => o.status == Status.pending);
lib/shared/widgets/order_filter.dart (3)

71-110: Autocomplete options dropdown may overflow on small screens; make width responsive

Hard-coding maxWidth: 300 can clip or overflow in narrow layouts. Prefer a width derived from screen size.

Apply this diff:

-                child: ConstrainedBox(
-                  constraints: const BoxConstraints(maxHeight: 200, maxWidth: 300),
+                child: ConstrainedBox(
+                  constraints: BoxConstraints(
+                    maxHeight: 200,
+                    maxWidth: MediaQuery.of(context).size.width - 48,
+                  ),

209-227: Accessibility: use IconButton with semantics for chip removal

GestureDetector on a small tap target isn’t accessible. Use IconButton with tooltip for better a11y and focus handling.

Apply this diff:

-                                GestureDetector(
-                                  onTap: () {
+                                IconButton(
+                                  onPressed: () {
                                     final updated = List<String>.from(widget.selectedValues)
                                       ..remove(value);
                                     widget.onChanged(updated);
                                   },
-                                  child: Container(
-                                    padding: const EdgeInsets.all(2),
-                                    decoration: BoxDecoration(
-                                      color: AppTheme.textSecondary.withOpacity(0.2),
-                                      shape: BoxShape.circle,
-                                    ),
-                                    child: const Icon(
-                                      Icons.close,
-                                      size: 14,
-                                      color: AppTheme.textSecondary,
-                                    ),
-                                  ),
+                                  constraints: const BoxConstraints(minWidth: 24, minHeight: 24),
+                                  padding: const EdgeInsets.all(2),
+                                  tooltip: S.of(context)!.clear,
+                                  icon: const Icon(Icons.close, size: 14, color: AppTheme.textSecondary),

259-274: Robustness: remove “Other” by ID or case-insensitive match

If upstream localizes “Other” or changes casing, this removal will fail. Better to filter by a stable ID or normalize case.

Example:

-    allMethods.remove('Other');
+    allMethods.removeWhere((m) => m.toLowerCase() == 'other');

Ideally remove by a canonical ID provided by the API, not the display label.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ad6b014 and 007b656.

📒 Files selected for processing (6)
  • lib/features/home/providers/home_order_providers.dart (1 hunks)
  • lib/features/home/screens/home_screen.dart (2 hunks)
  • lib/l10n/intl_en.arb (1 hunks)
  • lib/l10n/intl_es.arb (1 hunks)
  • lib/l10n/intl_it.arb (1 hunks)
  • lib/shared/widgets/order_filter.dart (7 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
lib/features/*/providers/**

📄 CodeRabbit Inference Engine (CLAUDE.md)

Providers are organized by feature in features/{feature}/providers/

Files:

  • lib/features/home/providers/home_order_providers.dart
lib/features/*/{screens,providers,notifiers,widgets}/**

📄 CodeRabbit Inference Engine (CLAUDE.md)

Feature-based organization: features/{feature}/{screens|providers|notifiers|widgets}/

Files:

  • lib/features/home/providers/home_order_providers.dart
  • lib/features/home/screens/home_screen.dart
lib/**/*.dart

📄 CodeRabbit Inference Engine (CLAUDE.md)

lib/**/*.dart: Use S.of(context).yourKey for all user-facing strings
Always check mounted before using context after async operations

Files:

  • lib/features/home/providers/home_order_providers.dart
  • lib/features/home/screens/home_screen.dart
  • lib/shared/widgets/order_filter.dart
**/*.dart

📄 CodeRabbit Inference Engine (CLAUDE.md)

**/*.dart: Remove unused imports and dependencies
Use const constructors where possible

Files:

  • lib/features/home/providers/home_order_providers.dart
  • lib/features/home/screens/home_screen.dart
  • lib/shared/widgets/order_filter.dart
lib/shared/**

📄 CodeRabbit Inference Engine (CLAUDE.md)

Shared utilities and widgets must be placed in shared/

Files:

  • lib/shared/widgets/order_filter.dart
lib/l10n/*.arb

📄 CodeRabbit Inference Engine (CLAUDE.md)

lib/l10n/*.arb: Internationalization ARB files must be located in lib/l10n/
Add new localization keys to all three ARB files (en, es, it)
Use proper ARB metadata for parameterized strings

Files:

  • lib/l10n/intl_it.arb
  • lib/l10n/intl_es.arb
  • lib/l10n/intl_en.arb
🧠 Learnings (1)
📚 Learning: 2025-08-03T09:43:38.727Z
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-03T09:43:38.727Z
Learning: Applies to lib/l10n/*.arb : Add new localization keys to all three ARB files (en, es, it)

Applied to files:

  • lib/l10n/intl_it.arb
  • lib/l10n/intl_es.arb
  • lib/l10n/intl_en.arb
🪛 RuboCop (1.76.1)
lib/l10n/intl_it.arb

[warning] 837-837: Duplicated key in hash literal.

(Lint/DuplicateHashKey)


[warning] 838-838: Duplicated key in hash literal.

(Lint/DuplicateHashKey)


[warning] 845-845: Duplicated key in hash literal.

(Lint/DuplicateHashKey)


[warning] 846-846: Duplicated key in hash literal.

(Lint/DuplicateHashKey)

lib/l10n/intl_es.arb

[warning] 829-829: Duplicated key in hash literal.

(Lint/DuplicateHashKey)


[warning] 830-830: Duplicated key in hash literal.

(Lint/DuplicateHashKey)


[warning] 837-837: Duplicated key in hash literal.

(Lint/DuplicateHashKey)


[warning] 838-838: Duplicated key in hash literal.

(Lint/DuplicateHashKey)

lib/l10n/intl_en.arb

[warning] 804-804: Duplicated key in hash literal.

(Lint/DuplicateHashKey)


[warning] 805-805: Duplicated key in hash literal.

(Lint/DuplicateHashKey)


[warning] 812-812: Duplicated key in hash literal.

(Lint/DuplicateHashKey)


[warning] 813-813: Duplicated key in hash literal.

(Lint/DuplicateHashKey)

⏰ 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). (1)
  • GitHub Check: build
🔇 Additional comments (6)
lib/features/home/providers/home_order_providers.dart (2)

10-15: Good addition: dedicated filter state providers.

The providers are typed and scoped appropriately for filter state. Records for ranges are a clean choice.


29-32: Confirm that filtering to Status.pending only is intended.

Current logic excludes non-pending orders (e.g., Active). If the “order book” should include other visible statuses, adjust here.

Would you like me to update this to a configurable set (e.g., {pending, active})?

lib/features/home/screens/home_screen.dart (2)

241-263: LGTM: localized label and count in the filter button.

Using S.of(context)!.filter and offersCount aligns with the localization guideline. Ripple feedback with InkWell is a nice UX touch.


220-223: Fix const mismatch: make OrderFilter const inside Dialog

Dialog is declared const but its child isn't — this is a compile error. OrderFilter already exposes a const constructor at lib/shared/widgets/order_filter.dart:243, so make the child a const expression.

  • Files to change:
    • lib/features/home/screens/home_screen.dart — around lines 220–223
    • lib/shared/widgets/order_filter.dart — confirms const constructor at line 243

Suggested fix (apply the child as const):

-                    return const Dialog(
-                      child: OrderFilter(),
-                    );
+                    return const Dialog(
+                      child: const OrderFilter(),
+                    );
⛔ Skipped due to learnings
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-03T09:43:38.727Z
Learning: Applies to **/*.dart : Use `const` constructors where possible
lib/shared/widgets/order_filter.dart (2)

242-249: LGTM: Solid Riverpod integration and provider updates on Apply/Clear

  • Correct use of ConsumerStatefulWidget and ref.watch/ref.read.
  • Apply and Clear correctly propagate to providers and close the dialog.
  • UI theming is consistent with AppTheme.

Also applies to: 299-301, 637-721


130-151: Keep withValues(...) — repo already standardises on the new API; do not apply the localized withOpacity() diffs

I searched the codebase: Color.withValues(...) is used widely (examples below) and CLAUDE.md documents preferring latest APIs (withValues). Replacing only the snippets in order_filter.dart would introduce inconsistency.

  • Examples of confirmed occurrences (partial):
    • lib/shared/widgets/order_filter.dart — lines: 133, 140, 193, 218, 309, 344, 386, 462, 531, 603, 665
    • lib/shared/widgets/mostro_app_bar.dart — line 80
    • lib/core/app_theme.dart — lines ~222–230
    • many other files under lib/features/* and lib/shared/widgets/* (repo-wide)

Action: Remove/ignore the suggested diffs in the original comment. If you intend to support older Flutter channels instead of following the repository standard, apply a repo-wide, consistent replacement (not a per-file patch) and verify the minimum Flutter/Dart SDK in pubspec.yaml.

Likely an incorrect or invalid review comment.

Copy link
Contributor

@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: 1

🔭 Outside diff range comments (1)
lib/shared/widgets/order_filter.dart (1)

31-31: Fix controller lifecycle: don’t create or dispose a controller you don’t own; clear safely

RawAutocomplete owns the TextEditingController provided to fieldViewBuilder. Creating your own controller (and then not disposing it) leaks memory; disposing it risks double-dispose. Keep only a nullable reference to the controller handed in by Autocomplete and never dispose it. Clear it safely on selection.

-class MultiSelectAutocompleteState extends State<MultiSelectAutocomplete> {
-  late TextEditingController _controller;
+class MultiSelectAutocompleteState extends State<MultiSelectAutocomplete> {
+  TextEditingController? _controller;
@@
-  @override
-  void initState() {
-    super.initState();
-    _controller = TextEditingController();
-  }
+  // No initState needed; RawAutocomplete provides the controller
@@
-  @override
-  void dispose() {
-    //_controller.dispose();
-    super.dispose();
-  }
+  // Do not dispose _controller; RawAutocomplete owns it
@@
           onSelected: (String selection) {
             final updated = List<String>.from(widget.selectedValues)
               ..add(selection);
             widget.onChanged(updated);
-            _controller.clear();
+            _controller?.clear();
           },

Also applies to: 33-37, 39-43, 111-116

♻️ Duplicate comments (5)
lib/shared/widgets/order_filter.dart (5)

276-295: Guard post-frame setState with mounted; destructure typed rating record instead of legacy double handling

As previously noted, the post-frame callback can run after disposal, causing “setState() called after dispose()”. Also, ratingFilterProvider is a typed record; remove the legacy double handling and destructure the record.

     WidgetsBinding.instance.addPostFrameCallback((_) {
       final currencies = ref.read(currencyFilterProvider);
       final paymentMethods = ref.read(paymentMethodFilterProvider);
       final currentRatingRange = ref.read(ratingFilterProvider);
       final currentPremiumRange = ref.read(premiumRangeFilterProvider);
-      
-      setState(() {
+      if (!mounted) return;
+      setState(() {
         selectedFiatCurrencies = List.from(currencies);
         selectedPaymentMethods = List.from(paymentMethods);
-        ratingMin = currentRatingRange is double ? 0.0 : currentRatingRange.min;
-        ratingMax = currentRatingRange is double ? currentRatingRange as double : currentRatingRange.max;
+        final (min: rMin, max: rMax) = currentRatingRange;
+        ratingMin = rMin;
+        ratingMax = rMax;
         premiumMin = currentPremiumRange.min;
         premiumMax = currentPremiumRange.max;
       });
     });

390-397: Localize “Loading currencies…” per i18n guideline

User-facing strings must use S.of(context). Replace the hardcoded loading label.

-                  child: const Center(
-                    child: Text(
-                      'Loading currencies...',
-                      style: TextStyle(
-                        color: AppTheme.textInactive,
-                        fontSize: 14,
-                      ),
-                    ),
-                  ),
+                  child: Center(
+                    child: Text(
+                      S.of(context)!.loadingCurrencies,
+                      style: const TextStyle(
+                        color: AppTheme.textInactive,
+                        fontSize: 14,
+                      ),
+                    ),
+                  ),

466-473: Localize “Loading payment methods…” per i18n guideline

Same as currencies — use localized string.

-                  child: const Center(
-                    child: Text(
-                      'Loading payment methods...',
-                      style: TextStyle(
-                        color: AppTheme.textInactive,
-                        fontSize: 14,
-                      ),
-                    ),
-                  ),
+                  child: Center(
+                    child: Text(
+                      S.of(context)!.loadingPaymentMethods,
+                      style: const TextStyle(
+                        color: AppTheme.textInactive,
+                        fontSize: 14,
+                      ),
+                    ),
+                  ),

578-590: Localize “Min/Max” labels for reputation slider

Use localized keys for “Min”/“Max”.

-                  Text(
-                    "Min: ${ratingMin.toInt()}",
+                  Text(
+                    "${S.of(context)!.min}: ${ratingMin.toInt()}",
@@
-                  Text(
-                    "Max: ${ratingMax.toInt()}",
+                  Text(
+                    "${S.of(context)!.max}: ${ratingMax.toInt()}",

479-482: Localize fallback payment method labels and prefer canonical IDs to avoid mismatches

These hardcoded English labels violate i18n and risk not matching provider/emitted IDs used in filtering. At minimum, localize them; ideally, use canonical method IDs and map to localized labels at render-time.

Minimal i18n fix:

-              options: ['Bank Transfer', 'Cash in person', 'PayPal', 'Zelle'], // Fallback options
+              options: [
+                S.of(context)!.bankTransfer,
+                S.of(context)!.cashInPerson,
+                S.of(context)!.paypal,
+                S.of(context)!.zelle,
+              ], // Fallback options

Stronger recommendation (follow-up): have paymentMethodsDataProvider expose canonical IDs (e.g., "BANK_TRANSFER") and pass options as IDs; extend MultiSelectAutocomplete to accept a String Function(String id) labelFor to render localized labels. I can provide a patch if you want to go this route.

🧹 Nitpick comments (3)
lib/shared/widgets/order_filter.dart (3)

8-8: Remove unused import to satisfy repo guidelines and avoid warnings

The exchange_service_provider.dart import is not used in this file.

-import 'package:mostro_mobile/shared/providers/exchange_service_provider.dart';

259-274: Strengthen types for payment method aggregation to catch errors at compile time

Using Map<String, dynamic> and runtime casts hides shape mismatches. Prefer Map<String, List<String>>.

-  List<String> _getAllPaymentMethods(Map<String, dynamic> paymentMethodsData) {
+  List<String> _getAllPaymentMethods(Map<String, List<String>> paymentMethodsData) {
     final Set<String> allMethods = {};
-    
-    // Add all payment methods from all currencies
-    for (final methods in paymentMethodsData.values) {
-      if (methods is List) {
-        allMethods.addAll(methods.cast<String>());
-      }
-    }
+    // Add all payment methods from all currencies
+    for (final List<String> methods in paymentMethodsData.values) {
+      allMethods.addAll(methods);
+    }
     
     // Remove "Other" since it's for custom input, not filtering
     allMethods.remove('Other');
     
     final sortedMethods = allMethods.toList()..sort();
     return sortedMethods;
   }

If the provider currently returns a looser shape, I can help adjust its typing and usages first.


303-305: Make dialog width responsive to avoid overflows on narrow devices

Hard-coding width: 320 can overflow on very small screens. Use a maxWidth constraint instead so it shrinks if needed.

-    return Container(
-      width: 320,
+    return Container(
+      constraints: const BoxConstraints(maxWidth: 320),
       padding: const EdgeInsets.all(20),
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 007b656 and f80a5a3.

📒 Files selected for processing (1)
  • lib/shared/widgets/order_filter.dart (7 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
lib/shared/**

📄 CodeRabbit Inference Engine (CLAUDE.md)

Shared utilities and widgets must be placed in shared/

Files:

  • lib/shared/widgets/order_filter.dart
lib/**/*.dart

📄 CodeRabbit Inference Engine (CLAUDE.md)

lib/**/*.dart: Use S.of(context).yourKey for all user-facing strings
Always check mounted before using context after async operations

Files:

  • lib/shared/widgets/order_filter.dart
**/*.dart

📄 CodeRabbit Inference Engine (CLAUDE.md)

**/*.dart: Remove unused imports and dependencies
Use const constructors where possible

Files:

  • lib/shared/widgets/order_filter.dart
🧠 Learnings (1)
📚 Learning: 2025-08-03T09:43:38.727Z
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-03T09:43:38.727Z
Learning: Applies to lib/**/*.dart : Use `S.of(context).yourKey` for all user-facing strings

Applied to files:

  • lib/shared/widgets/order_filter.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). (1)
  • GitHub Check: build

Copy link
Contributor

@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: 0

🔭 Outside diff range comments (1)
lib/l10n/intl_en.arb (1)

799-816: Action required — remove duplicate ARB keys in lib/l10n

All new keys are present in intl_en.arb, intl_es.arb and intl_it.arb, but duplicate top-level keys were detected. Please remove/merge the duplicates before merging.

Files with duplicates:

  • lib/l10n/intl_en.arb — forAmount, createdOn, proofOfWork, yourSharedKey
  • lib/l10n/intl_es.arb — createdOn, proofOfWork, cancelPendingButton, completePurchaseButton, forAmount, @forAmount
  • lib/l10n/intl_it.arb — createdOn, proofOfWork, yourSharedKey, cancelPendingButton, completePurchaseButton, forAmount, @forAmount

Recommended fix:

  • Remove duplicate root-level entries so each message key appears only once (also dedupe any duplicated metadata keys that start with '@').
  • Ensure message keys and their corresponding "@key" metadata are present exactly once and correctly paired.
  • Regenerate localization artifacts after editing the ARB files.
♻️ Duplicate comments (1)
lib/l10n/intl_en.arb (1)

803-810: Duplicate keys resolved in the filter block — good cleanup

The previously duplicated keys (fiatCurrencies, paymentMethods, noneSelected, typeToAdd) are no longer redefined here. Thanks for fixing.

🧹 Nitpick comments (1)
lib/l10n/intl_en.arb (1)

799-799: Use uppercase casing for action labels to match existing UI buttons

Most action buttons are uppercase (e.g., CLOSE, TAKE, BACK, RATE). Consider aligning Apply for consistency.

Apply this diff:

-  "apply": "Apply",
+  "apply": "APPLY",
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f80a5a3 and b3e603c.

📒 Files selected for processing (3)
  • lib/l10n/intl_en.arb (1 hunks)
  • lib/l10n/intl_es.arb (1 hunks)
  • lib/l10n/intl_it.arb (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/l10n/intl_it.arb
  • lib/l10n/intl_es.arb
🧰 Additional context used
📓 Path-based instructions (1)
lib/l10n/*.arb

📄 CodeRabbit Inference Engine (CLAUDE.md)

lib/l10n/*.arb: Internationalization ARB files must be located in lib/l10n/
Add new localization keys to all three ARB files (en, es, it)
Use proper ARB metadata for parameterized strings

Files:

  • lib/l10n/intl_en.arb
🧠 Learnings (1)
📚 Learning: 2025-08-03T09:43:38.727Z
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-03T09:43:38.727Z
Learning: Applies to lib/l10n/*.arb : Add new localization keys to all three ARB files (en, es, it)

Applied to files:

  • lib/l10n/intl_en.arb
⏰ 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). (1)
  • GitHub Check: build
🔇 Additional comments (1)
lib/l10n/intl_en.arb (1)

811-815: Timeout message keys added — LGTM

The new timeout-related strings are clear, concise, and consistent with existing tone and spelling (“canceled”). No issues found.

Copy link
Contributor

@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: 0

🔭 Outside diff range comments (1)
lib/shared/widgets/order_filter.dart (1)

33-43: Avoid allocating your own TextEditingController (leak/double-dispose risk)

Autocomplete supplies and disposes its own controller via fieldViewBuilder. Creating another in initState leaks it, and disposing the provided one can cause double-dispose. Remove the manual init and keep not disposing.

Apply this diff:

   @override
   void initState() {
     super.initState();
-    _controller = TextEditingController();
+    // Controller is provided by Autocomplete's fieldViewBuilder; no manual init.
   }

   @override
   void dispose() {
-    //_controller.dispose();
+    // Do not dispose _controller here — Autocomplete owns it.
     super.dispose();
   }
♻️ Duplicate comments (3)
lib/shared/widgets/order_filter.dart (3)

482-491: Fallback payment method labels should be localized or derived from canonical IDs

Hardcoded English labels violate i18n and risk mismatch with provider data. Prefer localized strings (ARB keys) or derive from canonical method IDs.

Apply this diff once the ARB keys exist:

-            error: (error, stack) => MultiSelectAutocomplete(
-              label: S.of(context)!.paymentMethods,
-              options: ['Bank Transfer', 'Cash in person', 'PayPal', 'Zelle'], // Fallback options
+            error: (error, stack) => MultiSelectAutocomplete(
+              label: S.of(context)!.paymentMethods,
+              options: [
+                S.of(context)!.paymentMethodBankTransfer,
+                S.of(context)!.paymentMethodCashInPerson,
+                S.of(context)!.paymentMethodPayPal,
+                S.of(context)!.paymentMethodZelle,
+              ], // Localized fallback options

Would you like me to add these ARB keys and translations? Also, if the provider returns canonical IDs, we can map IDs -> localized strings instead.

To confirm what we need, run this to inspect payment_methods_provider for available IDs:

#!/bin/bash
set -euo pipefail
rg -n -C3 --type=dart "paymentMethodsDataProvider|payment_method|method" || true

133-135: Replace Color.withValues(...) with withOpacity(...) to avoid SDK incompatibility

Color.withValues isn’t available on stable Flutter channels (and no local extension exists per prior scan). This will break builds. Use withOpacity.

Apply this diff:

-                    color: Colors.white.withValues(alpha: 0.2),
+                    color: Colors.white.withOpacity(0.2),
@@
-                    color: Colors.white.withValues(alpha: 0.2),
+                    color: Colors.white.withOpacity(0.2),
@@
-                                color: AppTheme.textSecondary.withValues(alpha: 0.6),
+                                color: AppTheme.textSecondary.withOpacity(0.6),
@@
-                                      color: AppTheme.textSecondary.withValues(alpha: 0.2),
+                                      color: AppTheme.textSecondary.withOpacity(0.2),
@@
-          color: Colors.white.withValues(alpha: 0.1),
+          color: Colors.white.withOpacity(0.1),
@@
-                  backgroundColor: Colors.white.withValues(alpha: 0.1),
+                  backgroundColor: Colors.white.withOpacity(0.1),
@@
-                      color: Colors.white.withValues(alpha: 0.2),
+                      color: Colors.white.withOpacity(0.2),
@@
-                      color: Colors.white.withValues(alpha: 0.2),
+                      color: Colors.white.withOpacity(0.2),
@@
-                  overlayColor: AppTheme.textSecondary.withValues(alpha: 0.2),
+                  overlayColor: AppTheme.textSecondary.withOpacity(0.2),
@@
-                  overlayColor: AppTheme.textSecondary.withValues(alpha: 0.2),
+                  overlayColor: AppTheme.textSecondary.withOpacity(0.2),
@@
-                        color: AppTheme.textSecondary.withValues(alpha: 0.3),
+                        color: AppTheme.textSecondary.withOpacity(0.3),

Also applies to: 140-142, 193-195, 218-221, 312-314, 347-348, 389-391, 465-467, 534-535, 606-607, 668-670


394-401: Localize remaining user-facing strings (“Loading…”, “Min:”, “Max:”)

Per guidelines and retrieved learnings, use S.of(context) for all user-visible text.

Apply these diffs:

-                  child: const Center(
-                    child: Text(
-                      'Loading currencies...',
-                      style: TextStyle(
+                  child: Center(
+                    child: Text(
+                      S.of(context)!.loadingCurrencies,
+                      style: const TextStyle(
                         color: AppTheme.textInactive,
                         fontSize: 14,
                       ),
                     ),
                   ),
-                  child: const Center(
-                    child: Text(
-                      'Loading payment methods...',
-                      style: TextStyle(
+                  child: Center(
+                    child: Text(
+                      S.of(context)!.loadingPaymentMethods,
+                      style: const TextStyle(
                         color: AppTheme.textInactive,
                         fontSize: 14,
                       ),
                     ),
                   ),
-                  Text(
-                    "Min: ${ratingMin.toInt()}",
+                  Text(
+                    "${S.of(context)!.min}: ${ratingMin.toInt()}",
-                  Text(
-                    "Max: ${ratingMax.toInt()}",
+                  Text(
+                    "${S.of(context)!.max}: ${ratingMax.toInt()}",

If these ARB keys aren’t present yet, I can add them (en/es/it).

Also applies to: 470-476, 583-583, 592-592

🧹 Nitpick comments (5)
lib/shared/widgets/order_filter.dart (5)

72-110: Avoid repeatedly traversing Iterable options; convert to a List once

The ListView uses options.length and options.elementAt(index) on an Iterable, which can be O(n) per call. Convert to a list once for performance and clarity.

Apply this diff:

-          optionsViewBuilder: (context, onSelected, options) {
-            return Align(
+          optionsViewBuilder: (context, onSelected, options) {
+            final items = options.toList(growable: false);
+            return Align(
               alignment: Alignment.topLeft,
               child: Material(
                 color: AppTheme.backgroundCard,
                 elevation: 8,
                 borderRadius: BorderRadius.circular(8),
                 child: ConstrainedBox(
                   constraints: const BoxConstraints(maxHeight: 200, maxWidth: 300),
                   child: ListView.builder(
                     padding: const EdgeInsets.all(4),
                     shrinkWrap: true,
-                    itemCount: options.length,
+                    itemCount: items.length,
                     itemBuilder: (context, index) {
-                      final option = options.elementAt(index);
+                      final option = items[index];
                       return InkWell(
                         onTap: () => onSelected(option),

259-274: Flatten nested payment-method structures and avoid relying on the display label “Other”

If paymentMethodsData is nested (e.g., by country/currency/provider), only handling List values will miss entries. Also, filtering “Other” by label is brittle.

Apply this diff to collect recursively and skip “Other” case-insensitively:

-  List<String> _getAllPaymentMethods(Map<String, dynamic> paymentMethodsData) {
-    final Set<String> allMethods = {};
-    
-    // Add all payment methods from all currencies
-    for (final methods in paymentMethodsData.values) {
-      if (methods is List) {
-        allMethods.addAll(methods.cast<String>());
-      }
-    }
-    
-    // Remove "Other" since it's for custom input, not filtering
-    allMethods.remove('Other');
-    
-    final sortedMethods = allMethods.toList()..sort();
-    return sortedMethods;
-  }
+  List<String> _getAllPaymentMethods(Map<String, dynamic> paymentMethodsData) {
+    final Set<String> allMethods = {};
+    void collect(dynamic node) {
+      if (node is List) {
+        allMethods.addAll(node.cast<String>());
+      } else if (node is Map) {
+        for (final v in node.values) {
+          collect(v);
+        }
+      }
+    }
+    collect(paymentMethodsData);
+    allMethods.removeWhere((m) => m.toLowerCase() == 'other');
+    final sortedMethods = allMethods.toList()..sort();
+    return sortedMethods;
+  }

If the provider exposes canonical method IDs, prefer filtering/removal by ID not by localized label. I can adjust once we verify the provider shape.


305-311: Avoid fixed width; constrain to maxWidth for smaller screens

A hard-coded width: 320 can overflow on compact devices. Prefer a maxWidth constraint so the dialog remains responsive.

Apply this diff:

-    return Container(
-      width: 320,
+    return Container(
+      constraints: const BoxConstraints(maxWidth: 320),
       padding: const EdgeInsets.all(20),

209-227: Use IconButton for the “remove” affordance to improve accessibility and tap feedback

GestureDetector + Container + Icon lacks semantics/tooltip and ink ripple in Material contexts. IconButton is better for a11y and consistency.

Apply this diff:

-                                GestureDetector(
-                                  onTap: () {
+                                IconButton(
+                                  onPressed: () {
                                     final updated = List<String>.from(widget.selectedValues)
                                       ..remove(value);
                                     widget.onChanged(updated);
                                   },
-                                  child: Container(
-                                    padding: const EdgeInsets.all(2),
-                                    decoration: BoxDecoration(
-                                      color: AppTheme.textSecondary.withOpacity(0.2),
-                                      shape: BoxShape.circle,
-                                    ),
-                                    child: const Icon(
-                                      Icons.close,
-                                      size: 14,
-                                      color: AppTheme.textSecondary,
-                                    ),
-                                  ),
+                                  icon: const Icon(Icons.close, size: 14, color: AppTheme.textSecondary),
+                                  tooltip: S.of(context)!.remove, // add ARB key if missing
+                                  style: IconButton.styleFrom(
+                                    padding: const EdgeInsets.all(2),
+                                    backgroundColor: AppTheme.textSecondary.withOpacity(0.2),
+                                    minimumSize: const Size(28, 28),
+                                    shape: const CircleBorder(),
+                                  ),
                                 ),

I can add the S.remove key if needed.


331-337: Avoid uppercasing localized strings (locale-insensitive)

toUpperCase() isn’t locale-aware and can produce odd results (e.g., Turkish). Prefer styling (letterSpacing/weight) without forcing uppercase, or provide already-uppercased variants in translations.

-                    S.of(context)!.filter.toUpperCase(),
+                    S.of(context)!.filter,
@@
-                      S.of(context)!.clear.toUpperCase(),
+                      S.of(context)!.clear,
@@
-                      S.of(context)!.apply.toUpperCase(),
+                      S.of(context)!.apply,

If uppercase is a design requirement, consider having translators provide the desired casing per locale.

Also applies to: 676-683, 714-719

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f942b3a and 08386db.

📒 Files selected for processing (2)
  • lib/features/home/providers/home_order_providers.dart (1 hunks)
  • lib/shared/widgets/order_filter.dart (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/features/home/providers/home_order_providers.dart
🧰 Additional context used
📓 Path-based instructions (3)
lib/shared/**

📄 CodeRabbit Inference Engine (CLAUDE.md)

Shared utilities and widgets must be placed in shared/

Files:

  • lib/shared/widgets/order_filter.dart
lib/**/*.dart

📄 CodeRabbit Inference Engine (CLAUDE.md)

lib/**/*.dart: Use S.of(context).yourKey for all user-facing strings
Always check mounted before using context after async operations

Files:

  • lib/shared/widgets/order_filter.dart
**/*.dart

📄 CodeRabbit Inference Engine (CLAUDE.md)

**/*.dart: Remove unused imports and dependencies
Use const constructors where possible

Files:

  • lib/shared/widgets/order_filter.dart
🧠 Learnings (1)
📚 Learning: 2025-08-03T09:43:38.727Z
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-03T09:43:38.727Z
Learning: Applies to lib/**/*.dart : Use `S.of(context).yourKey` for all user-facing strings

Applied to files:

  • lib/shared/widgets/order_filter.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). (1)
  • GitHub Check: build
🔇 Additional comments (1)
lib/shared/widgets/order_filter.dart (1)

242-256: Solid Riverpod integration and typed record usage

Good move converting OrderFilter to ConsumerStatefulWidget, reading/writing through providers, and using typed records for rating/premium ranges. Initialization via a post-frame callback with mounted guard is correct.

Also applies to: 300-304

Copy link
Contributor

@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: 3

🔭 Outside diff range comments (1)
lib/shared/widgets/order_filter.dart (1)

31-37: Avoid leaking a TextEditingController; don’t create/dispose controllers owned by Autocomplete

You create an extra controller in initState and never dispose it; later you reassign _controller to Autocomplete’s controller (which you shouldn’t dispose). Make _controller nullable, don’t instantiate one yourself, and use null-aware clear.

Apply this diff:

-class MultiSelectAutocompleteState extends State<MultiSelectAutocomplete> {
-  late TextEditingController _controller;
+class MultiSelectAutocompleteState extends State<MultiSelectAutocomplete> {
+  TextEditingController? _controller;
@@
   @override
   void initState() {
     super.initState();
-    _controller = TextEditingController();
   }
@@
   @override
   void dispose() {
-    //_controller.dispose();
     super.dispose();
   }
@@
             widget.onChanged(updated);
-            _controller.clear();
+            _controller?.clear();

Also applies to: 39-43, 115-116

♻️ Duplicate comments (1)
lib/shared/widgets/order_filter.dart (1)

482-491: Fallback payment method labels should be localized (or derived from canonical IDs)

These strings are user-facing. Prior discussion deferred this to a follow-up PR; leaving a note to track.

Non-blocking for this PR.

🧹 Nitpick comments (1)
lib/shared/widgets/order_filter.dart (1)

259-274: Consider removing “Other” by canonical ID rather than label

Relying on the literal "Other" can break if upstream data localizes or changes casing. If the provider exposes stable IDs, filter by ID; otherwise, make the comparison case-insensitive.

Example:

// If labels only, guard against casing
allMethods.removeWhere((m) => m.toLowerCase() == 'other');
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 08386db and 845e632.

📒 Files selected for processing (4)
  • lib/l10n/intl_en.arb (1 hunks)
  • lib/l10n/intl_es.arb (1 hunks)
  • lib/l10n/intl_it.arb (1 hunks)
  • lib/shared/widgets/order_filter.dart (7 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
lib/shared/**

📄 CodeRabbit Inference Engine (CLAUDE.md)

Shared utilities and widgets must be placed in shared/

Files:

  • lib/shared/widgets/order_filter.dart
lib/**/*.dart

📄 CodeRabbit Inference Engine (CLAUDE.md)

lib/**/*.dart: Use S.of(context).yourKey for all user-facing strings
Always check mounted before using context after async operations

Files:

  • lib/shared/widgets/order_filter.dart
**/*.dart

📄 CodeRabbit Inference Engine (CLAUDE.md)

**/*.dart: Remove unused imports and dependencies
Use const constructors where possible

Files:

  • lib/shared/widgets/order_filter.dart
lib/l10n/*.arb

📄 CodeRabbit Inference Engine (CLAUDE.md)

lib/l10n/*.arb: Internationalization ARB files must be located in lib/l10n/
Add new localization keys to all three ARB files (en, es, it)
Use proper ARB metadata for parameterized strings

Files:

  • lib/l10n/intl_es.arb
  • lib/l10n/intl_en.arb
  • lib/l10n/intl_it.arb
🧠 Learnings (5)
📚 Learning: 2025-08-03T09:43:38.727Z
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-03T09:43:38.727Z
Learning: Applies to lib/**/*.dart : Use `S.of(context).yourKey` for all user-facing strings

Applied to files:

  • lib/shared/widgets/order_filter.dart
📚 Learning: 2025-08-15T01:37:12.194Z
Learnt from: Catrya
PR: MostroP2P/mobile#270
File: lib/shared/widgets/order_filter.dart:133-135
Timestamp: 2025-08-15T01:37:12.194Z
Learning: The MostroP2P/mobile project requires Flutter >=3.27.0 as specified in pubspec.yaml, which supports the Color.withValues() method, so usage of withValues() throughout the codebase is valid and should not be flagged as a compatibility issue.

Applied to files:

  • lib/shared/widgets/order_filter.dart
📚 Learning: 2025-08-03T09:43:38.727Z
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-03T09:43:38.727Z
Learning: All changes should pass `flutter analyze` before commit

Applied to files:

  • lib/shared/widgets/order_filter.dart
📚 Learning: 2025-08-03T09:43:38.727Z
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-03T09:43:38.727Z
Learning: Zero `flutter analyze` issues must be maintained

Applied to files:

  • lib/shared/widgets/order_filter.dart
📚 Learning: 2025-08-03T09:43:38.727Z
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-03T09:43:38.727Z
Learning: Applies to lib/l10n/*.arb : Add new localization keys to all three ARB files (en, es, it)

Applied to files:

  • lib/l10n/intl_es.arb
  • lib/l10n/intl_en.arb
  • lib/l10n/intl_it.arb
🪛 RuboCop (1.76.1)
lib/l10n/intl_es.arb

[warning] 835-835: Duplicated key in hash literal.

(Lint/DuplicateHashKey)


[warning] 836-836: Duplicated key in hash literal.

(Lint/DuplicateHashKey)

lib/l10n/intl_en.arb

[warning] 810-810: Duplicated key in hash literal.

(Lint/DuplicateHashKey)


[warning] 811-811: Duplicated key in hash literal.

(Lint/DuplicateHashKey)

lib/l10n/intl_it.arb

[warning] 843-843: Duplicated key in hash literal.

(Lint/DuplicateHashKey)


[warning] 844-844: Duplicated key in hash literal.

(Lint/DuplicateHashKey)

⏰ 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). (1)
  • GitHub Check: build
🔇 Additional comments (7)
lib/l10n/intl_es.arb (1)

826-827: Added "apply" key looks good

The new "apply" translation aligns with UI usage in OrderFilter.

lib/l10n/intl_it.arb (1)

834-835: Added "apply" key looks good

Matches new UI action text and parity with EN/ES.

lib/l10n/intl_en.arb (2)

798-800: Added "apply" key is correct

This supports the new Apply button in the filter dialog.


815-820: Timeout message additions look consistent

New timeout strings align with usage and mirror ES/IT entries.

lib/shared/widgets/order_filter.dart (3)

276-298: Good: post-frame setState guarded by mounted; record destructuring for rating

This avoids “setState() called after dispose()” and uses typed range values cleanly.


358-405: Nice: currencies async handling with localized loading state

Loading skeleton uses S.of(context)!.loadingCurrencies and consistent styling. Looks good.


446-481: Nice: payment methods async handling with localized loading text

Consistent with currencies block and app theme.

… action buttons

and remove duplicate ARB keys for loading messages
Copy link
Contributor

@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: 0

🔭 Outside diff range comments (2)
lib/shared/widgets/order_filter.dart (2)

41-41: Fix potential memory leak: uncomment controller disposal

The TextEditingController disposal is commented out, which will cause a memory leak. Controllers must be disposed when the widget is destroyed.

Apply this diff to fix the memory leak:

   @override
   void dispose() {
-    //_controller.dispose();
+    _controller.dispose();
     super.dispose();
   }

117-120: Avoid reassigning the field-built controller

The _controller member is reassigned to the field-built controller on line 119, which interferes with the controller lifecycle management. The field builder provides its own controller that shouldn't be stored in the state.

Remove the reassignment to prevent lifecycle issues:

   fieldViewBuilder:
       (context, textEditingController, focusNode, onFieldSubmitted) {
-    _controller = textEditingController;
     return TextFormField(
       controller: textEditingController,

Since you need to clear the field after selection, modify the onSelected callback instead:

   onSelected: (String selection) {
     final updated = List<String>.from(widget.selectedValues)
       ..add(selection);
     widget.onChanged(updated);
-    _controller.clear();
+    // Field will auto-clear after selection
   },
♻️ Duplicate comments (1)
lib/shared/widgets/order_filter.dart (1)

488-497: Consider using provider's fallback data instead of hardcoded options

When the payment methods provider fails, consider using cached data or deriving fallback options from the currencies provider rather than hardcoding English payment method names.

This aligns with the previous review comment about localizing or deriving fallback payment method labels from canonical IDs.

🧹 Nitpick comments (1)
lib/shared/widgets/order_filter.dart (1)

425-426: Remove duplicate label parameter in error state

The MultiSelectAutocomplete widget already receives the label through the parent Column's Text widget. The duplicate label parameter in line 426 is redundant.

                 MultiSelectAutocomplete(
-                  label: S.of(context)!.fiatCurrencies,
                   options: ['USD', 'EUR', 'VES'], // Fallback options
                   selectedValues: selectedFiatCurrencies,
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 845e632 and 1b9a2df.

📒 Files selected for processing (4)
  • lib/l10n/intl_en.arb (1 hunks)
  • lib/l10n/intl_es.arb (1 hunks)
  • lib/l10n/intl_it.arb (1 hunks)
  • lib/shared/widgets/order_filter.dart (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • lib/l10n/intl_es.arb
  • lib/l10n/intl_it.arb
  • lib/l10n/intl_en.arb
🧰 Additional context used
📓 Path-based instructions (3)
lib/shared/**

📄 CodeRabbit Inference Engine (CLAUDE.md)

Shared utilities and widgets must be placed in shared/

Files:

  • lib/shared/widgets/order_filter.dart
lib/**/*.dart

📄 CodeRabbit Inference Engine (CLAUDE.md)

lib/**/*.dart: Use S.of(context).yourKey for all user-facing strings
Always check mounted before using context after async operations

Files:

  • lib/shared/widgets/order_filter.dart
**/*.dart

📄 CodeRabbit Inference Engine (CLAUDE.md)

**/*.dart: Remove unused imports and dependencies
Use const constructors where possible

Files:

  • lib/shared/widgets/order_filter.dart
🧠 Learnings (4)
📚 Learning: 2025-08-03T09:43:38.727Z
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-03T09:43:38.727Z
Learning: Applies to lib/**/*.dart : Use `S.of(context).yourKey` for all user-facing strings

Applied to files:

  • lib/shared/widgets/order_filter.dart
📚 Learning: 2025-08-15T01:37:12.194Z
Learnt from: Catrya
PR: MostroP2P/mobile#270
File: lib/shared/widgets/order_filter.dart:133-135
Timestamp: 2025-08-15T01:37:12.194Z
Learning: The MostroP2P/mobile project requires Flutter >=3.27.0 as specified in pubspec.yaml, which supports the Color.withValues() method, so usage of withValues() throughout the codebase is valid and should not be flagged as a compatibility issue.

Applied to files:

  • lib/shared/widgets/order_filter.dart
📚 Learning: 2025-08-03T09:43:38.727Z
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-03T09:43:38.727Z
Learning: All changes should pass `flutter analyze` before commit

Applied to files:

  • lib/shared/widgets/order_filter.dart
📚 Learning: 2025-08-03T09:43:38.727Z
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-03T09:43:38.727Z
Learning: Zero `flutter analyze` issues must be maintained

Applied to files:

  • lib/shared/widgets/order_filter.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). (1)
  • GitHub Check: build
🔇 Additional comments (5)
lib/shared/widgets/order_filter.dart (5)

259-274: LGTM! Clean helper method for aggregating payment methods

The implementation correctly aggregates payment methods from all currencies, removes the "Other" option (which is for custom input), and returns a sorted list. Good separation of concerns.


276-298: LGTM! Proper lifecycle management with mounted check

The implementation correctly uses addPostFrameCallback to access providers after the first frame, includes the mounted check before setState to prevent calling setState after disposal, and properly destructures the rating range tuple. This addresses the previous review comment about guarding setState with mounted.


365-375: LGTM! Well-structured async data handling

The implementation properly handles the async state with loading and error states, providing appropriate fallbacks. The localized label and sorting of currency options enhance usability.


657-674: LGTM! Clear action properly resets all filters

The clear button implementation correctly resets both local state and all provider states to their defaults, then closes the dialog. Good UX pattern.


704-712: LGTM! Apply action correctly syncs state to providers

The apply button properly updates all filter providers with the current local state values before closing the dialog. The state management flow is clean and follows React/Flutter patterns.

Copy link
Member

@grunch grunch left a comment

Choose a reason for hiding this comment

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

Pero que lindo! 🥇

tACK

@grunch grunch merged commit ebaba4a into main Aug 15, 2025
2 checks passed
@grunch grunch deleted the filter branch August 15, 2025 13:18
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.

3 participants