Skip to content

Conversation

@grunch
Copy link
Member

@grunch grunch commented Aug 1, 2025

  • Fix NostrService relay update mechanism to prevent empty relay list errors during order publishing
  • Enhance relay validation with fallback WebSocket connectivity testing
  • Add proper error handling and state management in NostrService updateSettings()
  • Implement defensive checks in publishEvent() to prevent assertion failures
  • Add comprehensive localization support for relay-related UI messages
  • Update all tests to maintain coverage with new method signatures
  • Resolve BuildContext async gap warnings in relay selector

This resolves the issue where users could add new relays through the settings screen but then encounter "relaysUrl.isNotEmpty" assertion failures when trying to publish orders.

Fix #244

Summary by CodeRabbit

  • New Features

    • Enhanced relay management with comprehensive URL validation, normalization, and connectivity testing before adding relays.
    • User interface improvements for adding relays, including input hints, loading indicators, and detailed success or error messages.
    • Relay health status is now checked and displayed after validation.
  • Localization

    • Added new localized messages for relay validation errors and statuses in English, Spanish, and Italian.
  • Bug Fixes

    • Improved error handling and validation when updating relay settings and publishing events.
  • Tests

    • Introduced extensive unit and widget tests for relay validation, relay selector dialog, and related notifier logic.
    • Expanded mock support for relays and settings in tests.
  • Chores

    • Minor adjustments to test setup and mock initialization for consistency.

- Fix NostrService relay update mechanism to prevent empty relay list errors during order publishing
- Enhance relay validation with fallback WebSocket connectivity testing
- Add proper error handling and state management in NostrService updateSettings()
- Implement defensive checks in publishEvent() to prevent assertion failures
- Add comprehensive localization support for relay-related UI messages
- Update all tests to maintain coverage with new method signatures
- Resolve BuildContext async gap warnings in relay selector

This resolves the issue where users could add new relays through the settings screen
but then encounter "relaysUrl.isNotEmpty" assertion failures when trying to publish orders.
@grunch grunch requested a review from Catrya August 1, 2025 14:04
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 1, 2025

Warning

Rate limit exceeded

@grunch has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 11 minutes and 57 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 01e678f and dbe6614.

📒 Files selected for processing (4)
  • lib/features/relays/widgets/relay_selector.dart (2 hunks)
  • lib/l10n/intl_en.arb (1 hunks)
  • lib/l10n/intl_es.arb (1 hunks)
  • lib/l10n/intl_it.arb (1 hunks)

Walkthrough

This update introduces advanced relay URL validation, normalization, and connectivity testing to the relay management logic. It enhances the relay addition dialog with real-time validation and user feedback, adds new localization strings for relay operations in English, Spanish, and Italian, and strengthens the Nostr service's relay management and error handling. Comprehensive unit and widget tests are added for the new logic, with expanded mocking support.

Changes

Cohort / File(s) Change Summary
Relay Validation Logic & Health
lib/features/relays/relays_notifier.dart
Introduces robust relay URL normalization, domain validation, connectivity testing, and health refresh logic. Adds RelayValidationResult and multiple new validation methods. Updates relay addition and health refresh to use these checks.
Relay Selector Widget
lib/features/relays/widgets/relay_selector.dart
Upgrades the add relay dialog with async validation, loading feedback, localized error/success messages, and improved user interaction.
Nostr Service Improvements
lib/services/nostr_service.dart
Refactors settings management, relay initialization, event publishing, and relay updating with stronger validation, error handling, and logging.
Localization (English, Spanish, Italian)
lib/l10n/intl_en.arb, lib/l10n/intl_es.arb, lib/l10n/intl_it.arb
Adds new localization strings for relay validation errors, testing, and user feedback in three languages.
YAML Formatting
l10n.yaml
Removes trailing newline; no semantic impact.
Relay Notifier Unit Tests
test/features/relays/relays_notifier_test.dart
Adds comprehensive tests for relay URL normalization, domain validation, and smart relay addition logic, including network tests.
Relay Selector Widget Tests
test/features/relays/widgets/relay_selector_test.dart
Adds detailed widget tests for the relay selector dialog, covering UI, validation, error handling, and user interaction.
Test Mocks Expansion
test/mocks.dart, test/mocks.mocks.dart
Adds and updates mocks for RelaysNotifier, refactors MockSettingsNotifier initialization, and updates import aliases.
Settings Provider Test Initialization
test/notifiers/add_order_notifier_test.dart, test/notifiers/take_order_notifier_test.dart
Refactors mock settings provider initialization to use property assignment instead of constructor arguments.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant RelaySelectorWidget
  participant RelaysNotifier
  participant NostrService

  User->>RelaySelectorWidget: Open add relay dialog
  User->>RelaySelectorWidget: Enter relay URL and tap Add
  RelaySelectorWidget->>RelaysNotifier: addRelayWithSmartValidation(input, error messages)
  RelaysNotifier->>RelaysNotifier: normalizeRelayUrl(input)
  alt Invalid URL
    RelaysNotifier-->>RelaySelectorWidget: RelayValidationResult (error)
    RelaySelectorWidget-->>User: Show error dialog
  else Valid URL
    RelaysNotifier->>RelaysNotifier: testRelayConnectivity(url)
    alt Relay reachable
      RelaysNotifier-->>RelaySelectorWidget: RelayValidationResult (success, healthy)
      RelaySelectorWidget-->>User: Close dialog, show success snackbar
      RelaySelectorWidget->>NostrService: (Relay added to settings)
    else Relay unreachable
      RelaysNotifier-->>RelaySelectorWidget: RelayValidationResult (success, not healthy)
      RelaySelectorWidget-->>User: Close dialog, show partial success snackbar
    end
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • Catrya

Poem

🐇✨
I hopped through relays, checked each one,
With webs and sockets, tests were spun.
Now only healthy links are found,
With error messages all around.
Three tongues now speak my relay song—
Add, test, connect, you can't go wrong!
🕸️🌐

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/relay-addition-and-order-publishing

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.
    • Explain this complex logic.
    • 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. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • 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 src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

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

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

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

Documentation and Community

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

🧹 Nitpick comments (2)
l10n.yaml (1)

6-6: Add missing newline at end of file.

The file is missing a trailing newline character, which violates POSIX standards and triggers YAMLlint errors.

-synthetic-package: false
+synthetic-package: false
lib/features/relays/relays_notifier.dart (1)

156-160: Consider using async primitives instead of busy waiting.

The busy-wait loop for connection establishment could be more efficient.

Consider using a Completer or StreamController to await the connection event:

final connectionCompleter = Completer<bool>();
// In onRelayConnectionDone callback:
connectionCompleter.complete(true);
// In onRelayConnectionError callback:
connectionCompleter.complete(false);

// Wait for connection
final connected = await connectionCompleter.future
    .timeout(const Duration(seconds: 5), onTimeout: () => false);
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 733ea90 and 4ff4cb4.

📒 Files selected for processing (13)
  • l10n.yaml (1 hunks)
  • lib/features/relays/relays_notifier.dart (2 hunks)
  • lib/features/relays/widgets/relay_selector.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/services/nostr_service.dart (3 hunks)
  • test/features/relays/relays_notifier_test.dart (1 hunks)
  • test/features/relays/widgets/relay_selector_test.dart (1 hunks)
  • test/mocks.dart (2 hunks)
  • test/mocks.mocks.dart (21 hunks)
  • test/notifiers/add_order_notifier_test.dart (1 hunks)
  • test/notifiers/take_order_notifier_test.dart (4 hunks)
🧰 Additional context used
📓 Path-based instructions (12)
test/**/*.dart

📄 CodeRabbit Inference Engine (CLAUDE.md)

Unit tests must be placed in the test/ directory

Files:

  • test/notifiers/add_order_notifier_test.dart
  • test/notifiers/take_order_notifier_test.dart
  • test/mocks.dart
  • test/features/relays/relays_notifier_test.dart
  • test/mocks.mocks.dart
  • test/features/relays/widgets/relay_selector_test.dart
**/*.dart

📄 CodeRabbit Inference Engine (CLAUDE.md)

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

Files:

  • test/notifiers/add_order_notifier_test.dart
  • test/notifiers/take_order_notifier_test.dart
  • test/mocks.dart
  • test/features/relays/relays_notifier_test.dart
  • lib/features/relays/widgets/relay_selector.dart
  • test/mocks.mocks.dart
  • test/features/relays/widgets/relay_selector_test.dart
  • lib/services/nostr_service.dart
  • lib/features/relays/relays_notifier.dart
test/mocks*.dart

📄 CodeRabbit Inference Engine (CLAUDE.md)

Mocks must be generated using Mockito in test/mocks.dart and test/mocks.mocks.dart

Files:

  • test/mocks.dart
  • test/mocks.mocks.dart
lib/l10n/*.arb

📄 CodeRabbit Inference Engine (CLAUDE.md)

lib/l10n/*.arb: Internationalization must use flutter_intl with ARB files in lib/l10n/
Use proper ARB metadata for parameterized strings

Files:

  • lib/l10n/intl_es.arb
  • lib/l10n/intl_it.arb
  • lib/l10n/intl_en.arb
lib/l10n/intl_{en,es,it}.arb

📄 CodeRabbit Inference Engine (CLAUDE.md)

Add new localization keys to all three ARB files (en, es, it)

Files:

  • lib/l10n/intl_es.arb
  • lib/l10n/intl_it.arb
  • lib/l10n/intl_en.arb
lib/features/*/{screens,providers,notifiers,widgets}/**/*.dart

📄 CodeRabbit Inference Engine (CLAUDE.md)

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

Files:

  • lib/features/relays/widgets/relay_selector.dart
lib/**/*.dart

📄 CodeRabbit Inference Engine (CLAUDE.md)

lib/**/*.dart: Use S.of(context).yourKey for all user-facing strings
Always use localized strings instead of hardcoded text
Pass BuildContext to methods that need localization
Always use latest APIs (e.g., withValues() instead of withOpacity())
Always check mounted before using context after async operations

Files:

  • lib/features/relays/widgets/relay_selector.dart
  • lib/services/nostr_service.dart
  • lib/features/relays/relays_notifier.dart
test/mocks.mocks.dart

📄 CodeRabbit Inference Engine (CLAUDE.md)

test/mocks.mocks.dart: The generated file test/mocks.mocks.dart is auto-generated by Mockito and must not be manually edited
Do not add individual // ignore: must_be_immutable comments to classes in test/mocks.mocks.dart
Never manually edit test/mocks.mocks.dart - it's auto-generated by Mockito
Mock files must have file-level // ignore_for_file: must_be_immutable and must not add more

Files:

  • test/mocks.mocks.dart
{lib/generated/**/*.dart,**/*.g.dart,**/*.mocks.dart}

📄 CodeRabbit Inference Engine (CLAUDE.md)

Never manually edit generated files (*.g.dart, *.mocks.dart, lib/generated/)

Files:

  • test/mocks.mocks.dart
{**/*.g.dart,**/*.mocks.dart}

📄 CodeRabbit Inference Engine (CLAUDE.md)

{**/*.g.dart,**/*.mocks.dart}: Never add ignore comments to generated files (*.g.dart, *.mocks.dart)
Never add ignore comments to generated files (*.g.dart, *.mocks.dart)

Files:

  • test/mocks.mocks.dart
{**/*.g.dart,**/*.mocks.dart,lib/generated/**/*.dart}

📄 CodeRabbit Inference Engine (CLAUDE.md)

{**/*.g.dart,**/*.mocks.dart,lib/generated/**/*.dart}: If analyzer issues exist in generated files, regenerate them instead of adding ignores
If analyzer issues exist in generated files, regenerate them instead of adding ignores

Files:

  • test/mocks.mocks.dart
lib/services/nostr_service.dart

📄 CodeRabbit Inference Engine (CLAUDE.md)

lib/services/nostr_service.dart: All Nostr protocol interactions must go through services/nostr_service.dart
Custom timeAgoWithLocale() method must be implemented in the NostrEvent extension

Files:

  • lib/services/nostr_service.dart
🧠 Learnings (35)
📚 Learning: applies to {lib/generated/**/*.dart,**/*.g.dart,**/*.mocks.dart} : never manually edit generated fil...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to {lib/generated/**/*.dart,**/*.g.dart,**/*.mocks.dart} : Never manually edit generated files (`*.g.dart`, `*.mocks.dart`, `lib/generated/`)

Applied to files:

  • l10n.yaml
  • test/mocks.dart
  • test/mocks.mocks.dart
  • test/features/relays/widgets/relay_selector_test.dart
📚 Learning: regenerate generated files using `dart run build_runner build -d`...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Regenerate generated files using `dart run build_runner build -d`

Applied to files:

  • l10n.yaml
📚 Learning: after modifying arb files, run `dart run build_runner build -d` to regenerate localization files...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: After modifying ARB files, run `dart run build_runner build -d` to regenerate localization files

Applied to files:

  • l10n.yaml
📚 Learning: applies to **/*.dart : remove unused imports and dependencies...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to **/*.dart : Remove unused imports and dependencies

Applied to files:

  • l10n.yaml
  • test/mocks.dart
📚 Learning: applies to lib/**/*.dart : always use localized strings instead of hardcoded text...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to lib/**/*.dart : Always use localized strings instead of hardcoded text

Applied to files:

  • l10n.yaml
  • lib/features/relays/widgets/relay_selector.dart
📚 Learning: applies to test/mocks.mocks.dart : the generated file `test/mocks.mocks.dart` is auto-generated by m...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to test/mocks.mocks.dart : The generated file `test/mocks.mocks.dart` is auto-generated by Mockito and must not be manually edited

Applied to files:

  • l10n.yaml
  • test/notifiers/add_order_notifier_test.dart
  • test/notifiers/take_order_notifier_test.dart
  • test/mocks.dart
  • test/features/relays/relays_notifier_test.dart
  • test/mocks.mocks.dart
  • test/features/relays/widgets/relay_selector_test.dart
📚 Learning: applies to {**/*.g.dart,**/*.mocks.dart} : never add ignore comments to generated files (`*.g.dart`,...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to {**/*.g.dart,**/*.mocks.dart} : Never add ignore comments to generated files (`*.g.dart`, `*.mocks.dart`)

Applied to files:

  • l10n.yaml
  • test/mocks.dart
📚 Learning: applies to {**/*.g.dart,**/*.mocks.dart,lib/generated/**/*.dart} : if analyzer issues exist in gener...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to {**/*.g.dart,**/*.mocks.dart,lib/generated/**/*.dart} : If analyzer issues exist in generated files, regenerate them instead of adding ignores

Applied to files:

  • l10n.yaml
  • test/mocks.dart
📚 Learning: applies to test/mocks.mocks.dart : never manually edit `test/mocks.mocks.dart` - it's auto-generated...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to test/mocks.mocks.dart : Never manually edit `test/mocks.mocks.dart` - it's auto-generated by Mockito

Applied to files:

  • test/notifiers/add_order_notifier_test.dart
  • test/notifiers/take_order_notifier_test.dart
  • test/mocks.dart
  • test/features/relays/relays_notifier_test.dart
  • test/mocks.mocks.dart
  • test/features/relays/widgets/relay_selector_test.dart
📚 Learning: applies to test/mocks.mocks.dart : do not add individual `// ignore: must_be_immutable` comments to ...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to test/mocks.mocks.dart : Do not add individual `// ignore: must_be_immutable` comments to classes in `test/mocks.mocks.dart`

Applied to files:

  • test/notifiers/add_order_notifier_test.dart
  • test/notifiers/take_order_notifier_test.dart
  • test/mocks.dart
  • test/features/relays/relays_notifier_test.dart
  • test/mocks.mocks.dart
  • test/features/relays/widgets/relay_selector_test.dart
📚 Learning: applies to test/mocks.mocks.dart : mock files must have file-level `// ignore_for_file: must_be_immu...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to test/mocks.mocks.dart : Mock files must have file-level `// ignore_for_file: must_be_immutable` and must not add more

Applied to files:

  • test/notifiers/add_order_notifier_test.dart
  • test/notifiers/take_order_notifier_test.dart
  • test/mocks.dart
  • test/features/relays/relays_notifier_test.dart
  • test/mocks.mocks.dart
  • test/features/relays/widgets/relay_selector_test.dart
📚 Learning: applies to test/mocks*.dart : mocks must be generated using mockito in `test/mocks.dart` and `test/m...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to test/mocks*.dart : Mocks must be generated using Mockito in `test/mocks.dart` and `test/mocks.mocks.dart`

Applied to files:

  • test/notifiers/add_order_notifier_test.dart
  • test/notifiers/take_order_notifier_test.dart
  • test/mocks.dart
  • test/features/relays/relays_notifier_test.dart
  • test/mocks.mocks.dart
  • test/features/relays/widgets/relay_selector_test.dart
📚 Learning: mostroservice methods like takebuyorder() and takesellorder() return future and trigger side e...
Learnt from: chebizarro
PR: MostroP2P/mobile#110
File: test/notifiers/take_order_notifier_test.dart:72-74
Timestamp: 2025-06-04T19:35:20.209Z
Learning: MostroService methods like takeBuyOrder() and takeSellOrder() return Future<void> and trigger side effects through other mechanisms rather than direct return values. When testing these methods, focus on verifying method calls and testing state changes through the provider system rather than mocking return values.

Applied to files:

  • test/notifiers/add_order_notifier_test.dart
  • test/notifiers/take_order_notifier_test.dart
  • test/mocks.mocks.dart
📚 Learning: applies to lib/features/*/providers/**/*.dart : providers are organized by feature in `features/{fea...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to lib/features/*/providers/**/*.dart : Providers are organized by feature in `features/{feature}/providers/`

Applied to files:

  • test/notifiers/add_order_notifier_test.dart
  • test/notifiers/take_order_notifier_test.dart
  • test/mocks.dart
  • test/features/relays/widgets/relay_selector_test.dart
📚 Learning: in abstractmostronotifier, state updates occur for all messages regardless of timestamp to hydrate t...
Learnt from: chebizarro
PR: MostroP2P/mobile#127
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:45-54
Timestamp: 2025-06-26T15:03:23.529Z
Learning: In AbstractMostroNotifier, state updates occur for all messages regardless of timestamp to hydrate the OrderNotifier from MostroStorage during sync, while handleEvent is only called for recent messages (within 60 seconds) to prevent re-triggering side effects like notifications and navigation for previously handled messages. This design prevents displaying stale notifications when the app is reopened or brought to the foreground.

Applied to files:

  • test/notifiers/add_order_notifier_test.dart
  • test/notifiers/take_order_notifier_test.dart
📚 Learning: applies to lib/features/*/{screens,providers,notifiers,widgets}/**/*.dart : feature-based organizati...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to lib/features/*/{screens,providers,notifiers,widgets}/**/*.dart : Feature-based organization: `features/{feature}/{screens|providers|notifiers|widgets}/`

Applied to files:

  • test/notifiers/add_order_notifier_test.dart
  • test/notifiers/take_order_notifier_test.dart
  • test/mocks.dart
  • test/features/relays/widgets/relay_selector_test.dart
📚 Learning: in the mostro mobile codebase, `eventstorageprovider` is exported from `package:mostro_mobile/shared...
Learnt from: chebizarro
PR: MostroP2P/mobile#74
File: lib/services/mostro_service.dart:70-76
Timestamp: 2025-05-06T15:49:26.443Z
Learning: In the Mostro Mobile codebase, `eventStorageProvider` is exported from `package:mostro_mobile/shared/providers/mostro_service_provider.dart` and not from a separate `event_storage_provider.dart` file.

Applied to files:

  • test/notifiers/add_order_notifier_test.dart
  • test/notifiers/take_order_notifier_test.dart
  • test/mocks.dart
  • test/mocks.mocks.dart
📚 Learning: applies to lib/shared/providers/mostro_database_provider.dart : database initialization must occur i...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to lib/shared/providers/mostro_database_provider.dart : Database initialization must occur in `shared/providers/mostro_database_provider.dart`

Applied to files:

  • test/notifiers/add_order_notifier_test.dart
  • test/notifiers/take_order_notifier_test.dart
  • test/mocks.dart
  • test/mocks.mocks.dart
  • lib/services/nostr_service.dart
📚 Learning: in the mostro mobile codebase, riverpod code generation is used with `@riverpod` annotations. provid...
Learnt from: chebizarro
PR: MostroP2P/mobile#74
File: lib/services/mostro_service.dart:70-76
Timestamp: 2025-05-06T15:49:26.443Z
Learning: In the Mostro Mobile codebase, Riverpod code generation is used with `@Riverpod` annotations. Providers like `eventStorageProvider` are generated in `.g.dart` files from annotated functions in the main provider files. These providers are accessible by importing the main provider file (e.g., `mostro_service_provider.dart`), not by importing a separate provider file.

Applied to files:

  • test/notifiers/add_order_notifier_test.dart
  • test/notifiers/take_order_notifier_test.dart
  • test/mocks.dart
  • test/mocks.mocks.dart
📚 Learning: applies to test/**/*.dart : unit tests must be placed in the `test/` directory...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to test/**/*.dart : Unit tests must be placed in the `test/` directory

Applied to files:

  • test/notifiers/take_order_notifier_test.dart
  • test/features/relays/relays_notifier_test.dart
  • test/features/relays/widgets/relay_selector_test.dart
📚 Learning: applies to lib/data/models.dart : models must be exported through `data/models.dart`...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to lib/data/models.dart : Models must be exported through `data/models.dart`

Applied to files:

  • test/mocks.dart
  • test/mocks.mocks.dart
📚 Learning: applies to lib/data/repositories/**/*.dart : all data access must go through repository classes in `...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to lib/data/repositories/**/*.dart : All data access must go through repository classes in `data/repositories/`

Applied to files:

  • test/mocks.dart
  • test/mocks.mocks.dart
📚 Learning: applies to lib/services/nostr_service.dart : all nostr protocol interactions must go through `servic...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to lib/services/nostr_service.dart : All Nostr protocol interactions must go through `services/nostr_service.dart`

Applied to files:

  • test/mocks.dart
  • test/features/relays/relays_notifier_test.dart
  • test/mocks.mocks.dart
  • lib/services/nostr_service.dart
  • lib/features/relays/relays_notifier.dart
📚 Learning: applies to lib/shared/**/*.dart : shared utilities and widgets must be placed in `shared/`...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to lib/shared/**/*.dart : Shared utilities and widgets must be placed in `shared/`

Applied to files:

  • test/mocks.dart
📚 Learning: applies to lib/l10n/intl_{en,es,it}.arb : add new localization keys to all three arb files (en, es, ...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to lib/l10n/intl_{en,es,it}.arb : Add new localization keys to all three ARB files (en, es, it)

Applied to files:

  • lib/l10n/intl_es.arb
  • lib/l10n/intl_it.arb
  • lib/l10n/intl_en.arb
📚 Learning: applies to lib/l10n/*.arb : use proper arb metadata for parameterized strings...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to lib/l10n/*.arb : Use proper ARB metadata for parameterized strings

Applied to files:

  • lib/l10n/intl_es.arb
  • lib/l10n/intl_it.arb
  • lib/l10n/intl_en.arb
📚 Learning: applies to integration_test/**/*.dart : integration tests must be placed in the `integration_test/` ...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to integration_test/**/*.dart : Integration tests must be placed in the `integration_test/` directory

Applied to files:

  • test/features/relays/relays_notifier_test.dart
  • test/features/relays/widgets/relay_selector_test.dart
📚 Learning: applies to lib/l10n/*.arb : internationalization must use `flutter_intl` with arb files in `lib/l10n...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to lib/l10n/*.arb : Internationalization must use `flutter_intl` with ARB files in `lib/l10n/`

Applied to files:

  • lib/l10n/intl_en.arb
📚 Learning: use riverpod for all state management...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Use Riverpod for all state management

Applied to files:

  • test/mocks.mocks.dart
  • lib/features/relays/relays_notifier.dart
📚 Learning: applies to lib/services/nostr_service.dart : custom `timeagowithlocale()` method must be implemented...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to lib/services/nostr_service.dart : Custom `timeAgoWithLocale()` method must be implemented in the NostrEvent extension

Applied to files:

  • test/mocks.mocks.dart
  • lib/services/nostr_service.dart
📚 Learning: in the nostr protocol, event.id will never be null in events returned by relay subscriptions, so nul...
Learnt from: chebizarro
PR: MostroP2P/mobile#74
File: lib/notifications/notification_service.dart:54-59
Timestamp: 2025-05-08T16:31:29.582Z
Learning: In the Nostr protocol, event.id will never be null in events returned by relay subscriptions, so null safety checks for this property are unnecessary.

Applied to files:

  • test/mocks.mocks.dart
  • lib/services/nostr_service.dart
  • lib/features/relays/relays_notifier.dart
📚 Learning: in abstractmostronotifier, the handleevent method is synchronous and returns void, not future....
Learnt from: Catrya
PR: MostroP2P/mobile#215
File: lib/features/order/notfiers/order_notifier.dart:0-0
Timestamp: 2025-07-20T23:33:17.689Z
Learning: In AbstractMostroNotifier, the handleEvent method is synchronous and returns void, not Future<void>. Do not suggest adding await to super.handleEvent() calls as this would cause compilation errors.

Applied to files:

  • test/mocks.mocks.dart
📚 Learning: applies to lib/core/mostro_fsm.dart : order state transitions must be managed by `core/mostro_fsm.da...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to lib/core/mostro_fsm.dart : Order state transitions must be managed by `core/mostro_fsm.dart`

Applied to files:

  • test/mocks.mocks.dart
📚 Learning: all changes should pass `flutter analyze` before commit...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: All changes should pass `flutter analyze` before commit

Applied to files:

  • test/features/relays/widgets/relay_selector_test.dart
📚 Learning: applies to lib/**/*.dart : always check `mounted` before using context after async operations...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to lib/**/*.dart : Always check `mounted` before using context after async operations

Applied to files:

  • test/features/relays/widgets/relay_selector_test.dart
🪛 YAMLlint (1.37.1)
l10n.yaml

[error] 6-6: no new line character at the end of file

(new-line-at-end-of-file)

🔇 Additional comments (19)
test/notifiers/add_order_notifier_test.dart (1)

83-87: LGTM! Mock initialization pattern updated correctly.

The change from constructor-based initialization to property assignment after instantiation aligns with the MockSettingsNotifier refactoring. This standardizes the mock initialization pattern across the test suite.

lib/l10n/intl_it.arb (1)

694-703: ✅ Relay localization keys consistent across all ARB files

Verified that all 12 relay-related keys from lib/l10n/intl_it.arb (relayAddedSuccessfully, relayAddedUnreachable, relayErrorAlreadyExists, relayErrorConnectionTimeout, relayErrorInvalidDomain, relayErrorNoHttp, relayErrorNotValid, relayErrorOnlySecure, relayTestingMessage, relayUrl, relays, and relaysInfoText) are also present in lib/l10n/intl_en.arb and lib/l10n/intl_es.arb. No discrepancies found—everything is in sync. LGTM, ready to merge.

lib/l10n/intl_en.arb (1)

656-683: LGTM! Comprehensive English relay localization entries.

The new relay management localization strings provide excellent user feedback covering all validation scenarios, testing states, and success conditions. The proper ARB metadata with placeholders ensures dynamic content can be displayed correctly.

These entries form the foundation for the enhanced relay validation and connectivity testing features mentioned in the PR objectives.

test/notifiers/take_order_notifier_test.dart (4)

123-132: LGTM! New mock pattern correctly implemented.

The updated settingsProvider override properly follows the new MockSettingsNotifier pattern - instantiating without parameters and explicitly setting the state. The Settings object maintains the same configuration as before.


192-202: LGTM! Consistent implementation of mock pattern.

The settingsProvider override correctly uses the new MockSettingsNotifier pattern with explicit state setting. The different mostroPublicKey value appears intentional for this test scenario.


260-270: Pattern correctly applied.

The settingsProvider override maintains consistency with the new mock instantiation pattern and provides appropriate Settings configuration for the test.


315-325: Excellent consistency across all test methods.

The final settingsProvider override correctly implements the new mock pattern, maintaining consistency with all other test methods in the file. This ensures reliable test behavior across the entire test suite.

test/mocks.dart (2)

37-37: LGTM! RelaysNotifier correctly added to mock generation.

The addition of RelaysNotifier to the @GenerateMocks annotation is necessary to support testing of the new relay validation functionality introduced in this PR.


42-50: Excellent refactoring of MockSettingsNotifier constructor.

The simplified constructor design improves separation of concerns by:

  • Removing parameter dependencies
  • Explicitly setting state with sensible defaults
  • Making mock usage more predictable and easier to customize in tests

This aligns perfectly with the updated usage pattern seen in test files throughout the PR.

lib/features/relays/widgets/relay_selector.dart (1)

122-237: Excellent async implementation with proper BuildContext safety.

This refactoring demonstrates excellent Flutter async patterns:

Proper async handling: Loading states, error handling, and success feedback
BuildContext safety: Localized strings captured before async operations
Comprehensive UX: Different success messages based on relay health status
Error differentiation: Specific error dialogs for various validation failures
Integration: Seamless use of the new addRelayWithSmartValidation method

The implementation follows coding guidelines by using localized strings and checking mounted before using context after async operations.

test/features/relays/relays_notifier_test.dart (1)

1-213: Excellent comprehensive test suite for RelaysNotifier.

This test file demonstrates outstanding test engineering practices:

Comprehensive Coverage: Tests URL normalization, domain validation, error scenarios, and real connectivity
Proper Organization: Logical grouping with descriptive names makes tests easy to understand and maintain
Network Test Safety: Real connectivity tests use appropriate timeouts and test against known working relays
Edge Case Handling: Thorough testing of various domain formats and invalid inputs
Clear Assertions: Descriptive reason parameters make test failures easy to debug
Mock Integration: Properly uses MockSettingsNotifier from the established mocking system

The tests provide excellent validation of the new relay management functionality and will help ensure reliability of the enhanced relay validation logic.

test/features/relays/widgets/relay_selector_test.dart (1)

1-336: LGTM! Comprehensive widget test coverage.

The test file provides excellent coverage for the RelaySelector dialog, including:

  • UI element verification
  • Validation error handling
  • Loading state management
  • Success and error scenarios
  • Edge cases like empty/whitespace input

The tests are well-structured and properly use mocks to isolate the widget behavior.

test/mocks.mocks.dart (1)

1-2411: Auto-generated file - no manual review needed.

This is a Mockito-generated file that should not be manually edited. The new MockRelaysNotifier and related fakes are properly generated to support the new relay validation functionality.

lib/services/nostr_service.dart (3)

21-27: Good defensive programming with the safe getter.

The nullable _settings field with a safe getter that returns a default instance is a good pattern. This prevents null reference errors while the service is being initialized.


75-111: Excellent error handling and state management in updateSettings.

The implementation correctly:

  • Compares relay lists to avoid unnecessary updates
  • Validates non-empty relay lists
  • Handles failures by attempting to restore previous state
  • Provides detailed logging for debugging

124-144: Well-implemented defensive checks in publishEvent.

The defensive check for empty relay lists and the enhanced error message for the assertion error provide much better developer experience. This directly addresses the PR objective of fixing the "relaysUrl.isNotEmpty" assertion failure.

lib/features/relays/relays_notifier.dart (3)

9-21: Well-designed result class for relay validation.

The RelayValidationResult class properly encapsulates all possible outcomes of relay validation, making it easy for the UI to handle different scenarios.


56-93: Excellent URL normalization and domain validation.

The implementation correctly:

  • Handles various input formats
  • Enforces secure WebSocket usage
  • Validates domain format while rejecting IP addresses
  • Uses proper regex for domain validation

267-326: Comprehensive relay validation implementation.

The addRelayWithSmartValidation method excellently integrates all validation steps:

  1. URL normalization with specific error messages
  2. Duplicate checking
  3. Connectivity testing
  4. Only adds healthy relays

This implementation directly addresses the PR objectives by ensuring only valid, reachable relays are added.

In order to avoid potential conflicts
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

♻️ Duplicate comments (1)
lib/features/relays/relays_notifier.dart (1)

115-118: Potential issue with Nostr instance creation.

The comment indicates creating an "isolated instance for testing," but Nostr() constructor may not actually create a separate instance if the library uses internal singletons. This could lead to interference with the main app's Nostr operations.

Based on the past review comment, this issue was already identified. The concern about using Nostr() vs Nostr.instance for isolation remains valid and should be verified against the dart_nostr library documentation.

🧹 Nitpick comments (3)
lib/features/relays/relays_notifier.dart (3)

55-68: Security-conscious URL normalization with minor enhancement opportunity.

The method correctly rejects insecure protocols and normalizes URLs appropriately. However, consider adding validation for maximum URL length to prevent potential DoS attacks.

 String? normalizeRelayUrl(String input) {
   input = input.trim().toLowerCase();
+  
+  // Prevent excessively long URLs
+  if (input.length > 2048) return null;

   if (!isValidDomainFormat(input)) return null;

154-159: Consider making connection timeout configurable.

The hardcoded 5-second timeout and polling interval might not be optimal for all network conditions, especially on slower mobile connections.

Consider making the connection timeout configurable:

     // Wait for connection establishment (max 5 seconds)
     int connectionWaitCount = 0;
-    while (!isConnected && connectionWaitCount < 50) {
+    const maxWaitMs = 5000; // Make this configurable if needed
+    const pollIntervalMs = 100;
+    while (!isConnected && connectionWaitCount < (maxWaitMs / pollIntervalMs)) {
       await Future.delayed(const Duration(milliseconds: 100));
       connectionWaitCount++;
     }

180-185: Timeout values could be more flexible.

The 8-second total timeout for EVENT/EOSE responses might be too long for mobile users expecting quick feedback, but could be too short for slower relays.

Consider making response timeouts configurable based on the use case (quick validation vs thorough testing):

     // Wait for EVENT or EOSE responses (max 8 seconds total)
+    const responseTimeoutMs = 3000; // Shorter for better UX
     int waitCount = 0;
-    while (!receivedEvent && !receivedEose && waitCount < 80) {
+    while (!receivedEvent && !receivedEose && waitCount < (responseTimeoutMs / 100)) {
       await Future.delayed(const Duration(milliseconds: 100));
       waitCount++;
     }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 4ff4cb4 and 01e678f.

📒 Files selected for processing (1)
  • lib/features/relays/relays_notifier.dart (2 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
lib/**/*.dart

📄 CodeRabbit Inference Engine (CLAUDE.md)

lib/**/*.dart: Use S.of(context).yourKey for all user-facing strings
Always use localized strings instead of hardcoded text
Pass BuildContext to methods that need localization
Always use latest APIs (e.g., withValues() instead of withOpacity())
Always check mounted before using context after async operations

Files:

  • lib/features/relays/relays_notifier.dart
**/*.dart

📄 CodeRabbit Inference Engine (CLAUDE.md)

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

Files:

  • lib/features/relays/relays_notifier.dart
🧠 Learnings (9)
📚 Learning: in the nostr protocol, event.id will never be null in events returned by relay subscriptions, so nul...
Learnt from: chebizarro
PR: MostroP2P/mobile#74
File: lib/notifications/notification_service.dart:54-59
Timestamp: 2025-05-08T16:31:29.582Z
Learning: In the Nostr protocol, event.id will never be null in events returned by relay subscriptions, so null safety checks for this property are unnecessary.

Applied to files:

  • lib/features/relays/relays_notifier.dart
📚 Learning: applies to lib/services/nostr_service.dart : all nostr protocol interactions must go through `servic...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to lib/services/nostr_service.dart : All Nostr protocol interactions must go through `services/nostr_service.dart`

Applied to files:

  • lib/features/relays/relays_notifier.dart
📚 Learning: applies to test/mocks.mocks.dart : do not add individual `// ignore: must_be_immutable` comments to ...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to test/mocks.mocks.dart : Do not add individual `// ignore: must_be_immutable` comments to classes in `test/mocks.mocks.dart`

Applied to files:

  • lib/features/relays/relays_notifier.dart
📚 Learning: applies to test/mocks.mocks.dart : never manually edit `test/mocks.mocks.dart` - it's auto-generated...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to test/mocks.mocks.dart : Never manually edit `test/mocks.mocks.dart` - it's auto-generated by Mockito

Applied to files:

  • lib/features/relays/relays_notifier.dart
📚 Learning: applies to lib/services/nostr_service.dart : custom `timeagowithlocale()` method must be implemented...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to lib/services/nostr_service.dart : Custom `timeAgoWithLocale()` method must be implemented in the NostrEvent extension

Applied to files:

  • lib/features/relays/relays_notifier.dart
📚 Learning: in abstractmostronotifier, the handleevent method is synchronous and returns void, not future....
Learnt from: Catrya
PR: MostroP2P/mobile#215
File: lib/features/order/notfiers/order_notifier.dart:0-0
Timestamp: 2025-07-20T23:33:17.689Z
Learning: In AbstractMostroNotifier, the handleEvent method is synchronous and returns void, not Future<void>. Do not suggest adding await to super.handleEvent() calls as this would cause compilation errors.

Applied to files:

  • lib/features/relays/relays_notifier.dart
📚 Learning: applies to lib/**/*.dart : always use localized strings instead of hardcoded text...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Applies to lib/**/*.dart : Always use localized strings instead of hardcoded text

Applied to files:

  • lib/features/relays/relays_notifier.dart
📚 Learning: all changes should pass `flutter analyze` before commit...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: All changes should pass `flutter analyze` before commit

Applied to files:

  • lib/features/relays/relays_notifier.dart
📚 Learning: use riverpod for all state management...
Learnt from: CR
PR: MostroP2P/mobile#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-30T14:10:43.895Z
Learning: Use Riverpod for all state management

Applied to files:

  • lib/features/relays/relays_notifier.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 (6)
lib/features/relays/relays_notifier.dart (6)

1-4: New imports look appropriate for the enhanced functionality.

The added imports support the new connectivity testing and validation features. The dart:io import is needed for WebSocket operations, and the ease.dart import provides Nostr protocol message types.


9-21: Well-structured validation result class.

The RelayValidationResult class provides a clean interface for returning detailed validation outcomes. The optional fields and default values are appropriate for the different validation scenarios.


70-92: Robust domain validation with comprehensive protocol handling.

The domain validation logic correctly handles multiple protocol prefixes and uses appropriate regex patterns. The IP address rejection is a good security practice for relay URLs.


205-252: Well-implemented fallback connectivity test.

The WebSocket fallback test provides a good alternative when the full Nostr protocol test fails. The timeout handling and response validation are appropriate.


263-323: Comprehensive relay validation with good error categorization.

The smart validation method provides excellent user experience by categorizing different types of validation failures. The connectivity requirement ensures only working relays are added.


325-335: Improved relay health refresh with actual connectivity testing.

The updated method now performs real connectivity tests instead of just marking all relays as healthy. This provides accurate health status for the UI.

Comment on lines +196 to +202
try {
await _cleanupTestConnection(Nostr.instance);
} catch (_) {
// Ignore cleanup errors
}
return false;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Inconsistent Nostr instance usage in error handling.

Line 197 uses Nostr.instance in the cleanup, but line 117 creates a new Nostr() instance. This inconsistency could lead to cleanup of the wrong instance.

     } catch (e) {
       // Protocol test failed with error
       try {
-        await _cleanupTestConnection(Nostr.instance);
+        // Note: testNostr is out of scope here, consider restructuring
+        // or storing the instance for proper cleanup
       } catch (_) {
         // Ignore cleanup errors
       }

Consider restructuring the error handling to properly clean up the correct Nostr instance, or use a try-finally block to ensure proper cleanup.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try {
await _cleanupTestConnection(Nostr.instance);
} catch (_) {
// Ignore cleanup errors
}
return false;
}
try {
// Note: testNostr is out of scope here, consider restructuring
// or storing the instance for proper cleanup
} catch (_) {
// Ignore cleanup errors
}
return false;
}
🤖 Prompt for AI Agents
In lib/features/relays/relays_notifier.dart around lines 196 to 202, the cleanup
uses Nostr.instance while earlier code at line 117 creates a new Nostr()
instance, causing inconsistent instance usage. To fix this, ensure the same
Nostr instance is used for both operations by storing the created instance in a
variable and referencing it in the cleanup. Alternatively, restructure the code
with a try-finally block to guarantee cleanup of the correct Nostr instance
regardless of errors.

grunch added 2 commits August 1, 2025 11:28
Replace hardcoded English hintText in relay input field with localized string.
Add relayUrlHint key to all ARB files (en, es, it) with appropriate translations:
- English: 'relay.example.com or wss://relay.example.com'
- Spanish: 'relay.ejemplo.com o wss://relay.ejemplo.com'
- Italian: 'relay.esempio.com o wss://relay.esempio.com'

This ensures the relay input field hint text supports multiple languages
and complies with the project's localization guidelines.
Add required metadata blocks for relayAddedSuccessfully and relayAddedUnreachable
in Spanish and Italian ARB files to properly describe the {url} parameter:

Spanish (intl_es.arb):
- Add @relayAddedSuccessfully metadata with Spanish descriptions
- Add @relayAddedUnreachable metadata with Spanish descriptions

Italian (intl_it.arb):
- Add @relayAddedSuccessfully metadata with Italian descriptions
- Add @relayAddedUnreachable metadata with Italian descriptions

This ensures proper localization handling of parameterized strings and maintains
consistency with the English ARB file metadata structure.
Copy link
Member

@Catrya Catrya left a comment

Choose a reason for hiding this comment

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

No me permite usar mi relay local ws://localhost:7000
solo wss://

@grunch grunch merged commit c6b682e into main Aug 1, 2025
2 checks passed
@grunch grunch deleted the fix/relay-addition-and-order-publishing branch August 1, 2025 18:41
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.

Add relay button is not working properly

3 participants