Skip to content

Conversation

@erskingardner
Copy link
Member

@erskingardner erskingardner commented Nov 11, 2025

Note

Adds a blocking/non-blocking toggle to user-related Rust/Dart APIs and switches many UI flows to non-blocking for performance while using blocking in critical paths.

  • Rust/FFI API:
    • Extend get_user, user_metadata, user_relays, user_has_key_package to accept blocking_data_sync; route to UserSyncMode::{Blocking,Background}.
    • Regenerate FFI bindings (lib/src/rust/frb_generated.dart, rust/src/frb_generated.rs) to pass the new flag.
    • Update whitenoise crate revision.
  • Dart API/Provider:
    • Update wn_users_api wrappers in lib/src/rust/api/users.dart to require blockingDataSync.
    • Enhance UserProfileNotifier to accept blockingDataSync in getUserProfile/getUser and plumb through.
  • Call-site updates (performance vs freshness):
    • Use non-blocking in chat/message lists and avatars: group_messages_provider, group_provider (_loadUserMetadata), chat_list_active_account_avatar, switch_profile_bottom_sheet, start_chat_bottom_sheet (key package check).
    • Use blocking where freshness is needed: QR scan, user search, welcome/invite sheets, notifications (message_sync_service), background metadata refresh, create-group key package filter.
  • Background/Services:
    • Pass blockingDataSync: true in background sync and notification name resolution.
  • Tests:
    • Adjust mocks/signatures in group_messages_provider_test.dart and user_profile_provider_test.dart for blockingDataSync.

Written by Cursor Bugbot for commit d8d19e8. This will update automatically on new commits. Configure here.

Summary by CodeRabbit

Release Notes

  • Refactor
    • Enhanced data synchronization controls across user data operations, enabling non-blocking fetches in performance-critical UI flows such as profile switching and chat lists, while ensuring fresh data in operations like group management and QR code scanning.
    • Updated backend sync operations to use controlled synchronization modes for improved efficiency and data consistency.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 11, 2025

Walkthrough

This PR introduces a blockingDataSync boolean parameter to user profile and metadata fetching APIs across Dart and Rust layers. The parameter controls whether data synchronization occurs immediately (blocking) or in the background (non-blocking), propagating through FFI bindings and affecting how user data is fetched in group messaging, profile switching, and sync operations.

Changes

Cohort / File(s) Summary
Rust FFI Dependency & Core Implementation
rust/Cargo.toml, rust/src/api/users.rs, rust/src/frb_generated.rs
Updated whitenoise dependency revision; extended get_user, user_metadata, user_relays, and user_has_key_package to accept blocking_data_sync parameter and compute sync_mode; FFI deserialization updated to decode and propagate the new parameter.
Dart Rust Bindings
lib/src/rust/api/users.dart, lib/src/rust/frb_generated.dart
Added blockingDataSync parameter (required) to getUser, userMetadata, userRelays, and userHasKeyPackage methods; forwarded parameter through RustLib FFI calls and serialization.
Provider Layer
lib/config/providers/user_profile_provider.dart, lib/config/providers/group_messages_provider.dart, lib/config/providers/group_provider.dart, lib/config/providers/create_group_provider.dart, lib/config/providers/welcomes_provider.dart
Extended _wnApiGetUser type and added optional blockingDataSync parameter (default true) to getUserProfile and getUser; calls to userHasKeyPackage now pass blockingDataSync; added documentation comments on blocking/non-blocking fetch intent.
Service Layer
lib/domain/services/background_sync_service.dart, lib/domain/services/message_sync_service.dart
Updated metadata refresh calls to pass blockingDataSync: true in group metadata and sender metadata fetches; no changes to error handling or control flow.
UI Layer — Comments & Blocking Fetches
lib/ui/chat/chat_management/add_to_group_screen.dart, lib/ui/settings/profile/share_profile_qr_scan_screen.dart, lib/ui/user_profile_list/new_chat_bottom_sheet.dart
Added documentation comments clarifying blocking fetch intent for group operations and QR scans; no functional changes.
UI Layer — Non-Blocking Fetches
lib/ui/settings/profile/switch_profile_bottom_sheet.dart, lib/ui/user_profile_list/widgets/chat_list_active_account_avatar.dart
Changed getUserProfile calls to pass blockingDataSync: false for concurrent profile retrieval; includes comments on non-blocking intent.
UI Layer — Blocking Metadata Updates
lib/ui/user_profile_list/group_welcome_invitation_sheet.dart, lib/ui/user_profile_list/start_chat_bottom_sheet.dart
Updated userMetadata and userHasKeyPackage calls to explicitly pass blockingDataSync: true or false; ensures synchronous data sync before usage.
Test Utilities
test/config/providers/group_messages_provider_test.dart, test/config/providers/user_profile_provider_test.dart
Updated MockUserProfileNotifier.getUserProfile and MockWnUsersApi.getUser signatures to include blockingDataSync parameter.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • lib/src/rust/frb_generated.dart — FFI serialization and deserialization logic across multiple methods; requires tracing argument propagation through the Dart–Rust bridge
  • rust/src/api/users.rs — Core sync_mode computation and conditional logic; verify correct mapping of blockingDataSync to UserSyncMode values
  • lib/config/providers/user_profile_provider.dart — Provider signature changes and optional parameter forwarding; confirm default behavior (blockingDataSync: true) is correct
  • Pattern consistency — Verify that blocking vs. non-blocking choices across UI files (switch_profile_bottom_sheet, group_welcome_invitation_sheet, start_chat_bottom_sheet, etc.) are intentional and correct
  • Rust dependency update — Review Cargo.toml revision change for any breaking API changes in whitenoise

Possibly related PRs

  • Change bridge to match new methods #530: Extends the initial users API functions (getUser, userMetadata, userRelays, userHasKeyPackage) by adding the blockingDataSync parameter and FFI bindings.
  • Fix/get user #555: Modifies rust/src/api/users.rs get_user implementation logic; overlaps with main PR's sync-mode handling.
  • Patch background notification #730: Updates message and background sync code paths; directly uses the blockingDataSync flag introduced in this PR for sync operations.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately reflects the main changes: updating the Rust crate dependency and adding blockingDataSync parameter throughout to enable selective blocking/non-blocking user data fetches.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch no-cache-fast-users

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

❤️ Share

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

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

🧹 Nitpick comments (4)
lib/ui/chat/chat_management/add_to_group_screen.dart (1)

160-162: Explicitly pass blockingDataSync: true for clarity.

The blocking fetch is indeed enabled via the default parameter (blockingDataSync = true in getUserProfile). However, to make the intent explicit and protect against future default changes, update line 162 to:

userProfileToAdd = await userProfileNotifier.getUserProfile(widget.userNpub, blockingDataSync: true);
test/config/providers/group_messages_provider_test.dart (1)

20-26: Mock API signature updated to accept blockingDataSync with safe default

The override mirrors provider API and keeps default true to preserve existing tests. Consider adding an expectation that GroupMessagesNotifier passes blockingDataSync: false on its non-blocking path to prevent regressions.

lib/config/providers/user_profile_provider.dart (1)

25-33: Public API now supports blocking vs non-blocking fetch; default preserves old behavior

  • getUserProfile/getUser accept blockingDataSync with default true and forward it to FFI.
  • Naming mirrors cross-layer API; keep for consistency despite non-verb boolean guideline.
    Optionally, add small doc comments clarifying when to pass false (e.g., background flows).
lib/src/rust/api/users.dart (1)

42-48: userHasKeyPackage: param propagation complete

No issues; consider adding thin convenience wrappers (e.g., getUserBlocking / getUserNonBlocking) in higher layers if callsites repeatedly pass the same flag.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5a86fbf and d8d19e8.

⛔ Files ignored due to path filters (1)
  • rust/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (21)
  • lib/config/providers/create_group_provider.dart (1 hunks)
  • lib/config/providers/group_messages_provider.dart (1 hunks)
  • lib/config/providers/group_provider.dart (2 hunks)
  • lib/config/providers/user_profile_provider.dart (2 hunks)
  • lib/config/providers/welcomes_provider.dart (1 hunks)
  • lib/domain/services/background_sync_service.dart (1 hunks)
  • lib/domain/services/message_sync_service.dart (4 hunks)
  • lib/src/rust/api/users.dart (1 hunks)
  • lib/src/rust/frb_generated.dart (9 hunks)
  • lib/ui/chat/chat_management/add_to_group_screen.dart (1 hunks)
  • lib/ui/settings/profile/share_profile_qr_scan_screen.dart (1 hunks)
  • lib/ui/settings/profile/switch_profile_bottom_sheet.dart (1 hunks)
  • lib/ui/user_profile_list/group_welcome_invitation_sheet.dart (3 hunks)
  • lib/ui/user_profile_list/new_chat_bottom_sheet.dart (2 hunks)
  • lib/ui/user_profile_list/start_chat_bottom_sheet.dart (1 hunks)
  • lib/ui/user_profile_list/widgets/chat_list_active_account_avatar.dart (1 hunks)
  • rust/Cargo.toml (1 hunks)
  • rust/src/api/users.rs (2 hunks)
  • rust/src/frb_generated.rs (4 hunks)
  • test/config/providers/group_messages_provider_test.dart (2 hunks)
  • test/config/providers/user_profile_provider_test.dart (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.dart

📄 CodeRabbit inference engine (.cursor/rules/flutter.mdc)

**/*.dart: Always declare the type of each variable and function (parameters and return value)
Avoid using dynamic and Object without justification
Create necessary types instead of overusing primitives or dynamic
One export per file
Use PascalCase for classes
Use camelCase for variables, functions, and methods
Avoid magic numbers and define constants
Start each function name with a verb
Use verbs for boolean variables (e.g., isLoading, hasError, canDelete)
Write short functions with a single purpose (under ~20 instructions)
Name functions with a verb plus context; for booleans use isX/hasX/canX; for void use executeX/saveX
Avoid deep nesting via early returns and extraction to utility functions
Use higher-order functions (map, where/filter, reduce) to avoid nesting
Use arrow functions for simple functions (under ~3 statements); use named functions otherwise
Use default parameter values instead of null checks
Reduce function parameters using RO-RO: pass/return parameter objects with declared types
Maintain a single level of abstraction within functions
Encapsulate data in composite types; avoid overusing primitives
Prefer validating data within classes rather than in functions
Prefer immutability; use final for runtime constants and const for compile-time constants
Use const constructors and const literals where possible
Follow SOLID principles
Prefer composition over inheritance
Declare interfaces (abstract classes) to define contracts
Write small classes with a single purpose (under ~200 instructions, <10 public methods, <10 properties)
Use exceptions for unexpected errors
Only catch exceptions to fix expected problems or add context; otherwise use a global handler

Files:

  • lib/ui/settings/profile/switch_profile_bottom_sheet.dart
  • lib/config/providers/create_group_provider.dart
  • lib/ui/user_profile_list/widgets/chat_list_active_account_avatar.dart
  • lib/ui/chat/chat_management/add_to_group_screen.dart
  • lib/ui/user_profile_list/start_chat_bottom_sheet.dart
  • lib/ui/settings/profile/share_profile_qr_scan_screen.dart
  • test/config/providers/group_messages_provider_test.dart
  • lib/domain/services/background_sync_service.dart
  • lib/src/rust/api/users.dart
  • lib/domain/services/message_sync_service.dart
  • lib/config/providers/group_provider.dart
  • test/config/providers/user_profile_provider_test.dart
  • lib/ui/user_profile_list/new_chat_bottom_sheet.dart
  • lib/config/providers/user_profile_provider.dart
  • lib/ui/user_profile_list/group_welcome_invitation_sheet.dart
  • lib/config/providers/welcomes_provider.dart
  • lib/src/rust/frb_generated.dart
  • lib/config/providers/group_messages_provider.dart
lib/**/*.dart

📄 CodeRabbit inference engine (.cursor/rules/flutter.mdc)

lib/**/*.dart: Use flutter_rust_bridge to access core app functionality
Use Riverpod for state management; prefer StreamProviders for Rust API streams; use keepAlive if needed
Use freezed to model/manage UI states
Controllers should expose methods as inputs and update UI state that drives the UI
Use AutoRoute for navigation and use extras to pass data between pages
Use Dart extensions to manage reusable code
Use ThemeData to manage themes
Use AppLocalizations for translations
Use constants to manage constant values
Avoid deeply nested widget trees; aim for a flatter widget structure for performance and readability
Break down large widgets into smaller, focused, reusable components
Keep the widget tree shallow to simplify state management and data flow
Utilize const constructors and const widgets wherever possible to reduce rebuilds

Files:

  • lib/ui/settings/profile/switch_profile_bottom_sheet.dart
  • lib/config/providers/create_group_provider.dart
  • lib/ui/user_profile_list/widgets/chat_list_active_account_avatar.dart
  • lib/ui/chat/chat_management/add_to_group_screen.dart
  • lib/ui/user_profile_list/start_chat_bottom_sheet.dart
  • lib/ui/settings/profile/share_profile_qr_scan_screen.dart
  • lib/domain/services/background_sync_service.dart
  • lib/src/rust/api/users.dart
  • lib/domain/services/message_sync_service.dart
  • lib/config/providers/group_provider.dart
  • lib/ui/user_profile_list/new_chat_bottom_sheet.dart
  • lib/config/providers/user_profile_provider.dart
  • lib/ui/user_profile_list/group_welcome_invitation_sheet.dart
  • lib/config/providers/welcomes_provider.dart
  • lib/src/rust/frb_generated.dart
  • lib/config/providers/group_messages_provider.dart
test/**/*.dart

📄 CodeRabbit inference engine (.cursor/rules/flutter.mdc)

test/**/*.dart: Follow Arrange-Act-Assert in tests
Name test variables clearly using inputX, mockX, actualX, expectedX
Write unit tests for each public function; use test doubles for dependencies (except cheap third-party)
Use standard Flutter widget testing

Files:

  • test/config/providers/group_messages_provider_test.dart
  • test/config/providers/user_profile_provider_test.dart
**/*.rs

📄 CodeRabbit inference engine (.cursor/rules/flutter.mdc)

Use the whitenoise Rust crate (via flutter_rust_bridge) as the sole data source and change trigger

Files:

  • rust/src/frb_generated.rs
  • rust/src/api/users.rs
🧠 Learnings (22)
📓 Common learnings
Learnt from: josefinalliende
Repo: parres-hq/whitenoise_flutter PR: 594
File: lib/src/rust/api/utils.dart:12-16
Timestamp: 2025-09-07T02:15:31.931Z
Learning: The lingering PublicKey references in lib/config/providers/auth_provider.dart, lib/config/providers/group_provider.dart, and rust_builder/cargokit/build_tool/lib/src/options.dart identified during the utils.dart API cleanup were fixed in PR #597 in the whitenoise_flutter codebase.
Learnt from: Quwaysim
Repo: parres-hq/whitenoise_flutter PR: 642
File: lib/ui/contact_list/new_chat_bottom_sheet.dart:324-336
Timestamp: 2025-09-16T07:24:07.489Z
Learning: In the whitenoise_flutter project, the user Quwaysim prefers to handle security improvements incrementally across different PRs rather than bundling them all together. Input trimming for search functionality was handled in PR #613, and private key security measures are planned for PR #505.
Learnt from: CR
Repo: parres-hq/whitenoise_flutter PR: 0
File: .cursor/rules/flutter.mdc:0-0
Timestamp: 2025-10-12T22:44:49.606Z
Learning: Applies to **/*.rs : Use the whitenoise Rust crate (via flutter_rust_bridge) as the sole data source and change trigger
Learnt from: josefinalliende
Repo: parres-hq/whitenoise_flutter PR: 597
File: lib/config/providers/group_provider.dart:311-314
Timestamp: 2025-09-07T13:10:16.542Z
Learning: In the whitenoise_flutter codebase, the User class used in group_provider.dart (and similar contexts) is presentational only, not the actual user class from the Rust API. There are plans to remove this User class and replace it with UserProfileData, similar to the planned consolidation with ContactModel.
Learnt from: josefinalliende
Repo: parres-hq/whitenoise_flutter PR: 594
File: lib/domain/models/contact_model.dart:36-41
Timestamp: 2025-09-07T02:08:09.199Z
Learning: The issue of ContactModel.publicKey potentially being set to an empty string when pubkey.toNpub() conversion fails (causing collision/lookup issues) is being addressed in PR #597 in the whitenoise_flutter codebase.
📚 Learning: 2025-09-07T13:10:16.542Z
Learnt from: josefinalliende
Repo: parres-hq/whitenoise_flutter PR: 597
File: lib/config/providers/group_provider.dart:311-314
Timestamp: 2025-09-07T13:10:16.542Z
Learning: In the whitenoise_flutter codebase, the User class used in group_provider.dart (and similar contexts) is presentational only, not the actual user class from the Rust API. There are plans to remove this User class and replace it with UserProfileData, similar to the planned consolidation with ContactModel.

Applied to files:

  • lib/ui/settings/profile/switch_profile_bottom_sheet.dart
  • lib/config/providers/create_group_provider.dart
  • lib/ui/user_profile_list/widgets/chat_list_active_account_avatar.dart
  • lib/ui/chat/chat_management/add_to_group_screen.dart
  • lib/ui/user_profile_list/start_chat_bottom_sheet.dart
  • test/config/providers/group_messages_provider_test.dart
  • lib/src/rust/api/users.dart
  • lib/config/providers/group_provider.dart
  • test/config/providers/user_profile_provider_test.dart
  • rust/src/api/users.rs
  • lib/ui/user_profile_list/new_chat_bottom_sheet.dart
  • lib/config/providers/user_profile_provider.dart
  • lib/ui/user_profile_list/group_welcome_invitation_sheet.dart
  • lib/src/rust/frb_generated.dart
  • lib/config/providers/group_messages_provider.dart
📚 Learning: 2025-09-07T02:15:31.931Z
Learnt from: josefinalliende
Repo: parres-hq/whitenoise_flutter PR: 594
File: lib/src/rust/api/utils.dart:12-16
Timestamp: 2025-09-07T02:15:31.931Z
Learning: The lingering PublicKey references in lib/config/providers/auth_provider.dart, lib/config/providers/group_provider.dart, and rust_builder/cargokit/build_tool/lib/src/options.dart identified during the utils.dart API cleanup were fixed in PR #597 in the whitenoise_flutter codebase.

Applied to files:

  • lib/config/providers/create_group_provider.dart
  • lib/ui/user_profile_list/start_chat_bottom_sheet.dart
  • rust/Cargo.toml
  • lib/ui/settings/profile/share_profile_qr_scan_screen.dart
  • test/config/providers/group_messages_provider_test.dart
  • lib/src/rust/api/users.dart
  • lib/domain/services/message_sync_service.dart
  • lib/config/providers/group_provider.dart
  • rust/src/frb_generated.rs
  • test/config/providers/user_profile_provider_test.dart
  • rust/src/api/users.rs
  • lib/config/providers/user_profile_provider.dart
  • lib/ui/user_profile_list/group_welcome_invitation_sheet.dart
  • lib/config/providers/welcomes_provider.dart
  • lib/src/rust/frb_generated.dart
  • lib/config/providers/group_messages_provider.dart
📚 Learning: 2025-11-11T10:47:12.755Z
Learnt from: Quwaysim
Repo: parres-hq/whitenoise_flutter PR: 826
File: lib/ui/settings/developer/developer_settings_screen.dart:41-42
Timestamp: 2025-11-11T10:47:12.755Z
Learning: In lib/ui/settings/developer/developer_settings_screen.dart, the `_isAnyOperationInProgress` getter intentionally excludes `_isLoading` (used for per-item key package deletion) because individual key package deletions should not block main operations (Publish, Inspect, Delete All). This allows users to delete individual packages while still being able to trigger main operations concurrently.

Applied to files:

  • lib/config/providers/create_group_provider.dart
📚 Learning: 2025-10-28T07:11:05.836Z
Learnt from: Quwaysim
Repo: parres-hq/whitenoise_flutter PR: 759
File: lib/ui/settings/profile/edit_profile_screen.dart:126-145
Timestamp: 2025-10-28T07:11:05.836Z
Learning: In lib/ui/settings/profile/edit_profile_screen.dart, the edit icon on the profile avatar is intentionally positioned with `left: 1.sw * 0.5` rather than being centered. This positioning is by design and should not be flagged as a centering issue.

Applied to files:

  • lib/ui/user_profile_list/widgets/chat_list_active_account_avatar.dart
  • lib/ui/settings/profile/share_profile_qr_scan_screen.dart
📚 Learning: 2025-10-15T02:08:41.843Z
Learnt from: josefinalliende
Repo: parres-hq/whitenoise_flutter PR: 721
File: lib/ui/chat/widgets/chat_input.dart:80-87
Timestamp: 2025-10-15T02:08:41.843Z
Learning: In `lib/ui/chat/widgets/chat_input.dart`, the `_toggleMediaSelector()` method correctly reads `chatInputState` before toggling and checks `!chatInputState.showMediaSelector` to unfocus when opening the selector. This matches the design requirement where the input should be unfocused when the media selector is shown.

Applied to files:

  • lib/ui/user_profile_list/widgets/chat_list_active_account_avatar.dart
📚 Learning: 2025-10-13T06:31:48.305Z
Learnt from: Quwaysim
Repo: parres-hq/whitenoise_flutter PR: 719
File: lib/domain/services/avatar_color_service.dart:88-139
Timestamp: 2025-10-13T06:31:48.305Z
Learning: In the whitenoise_flutter project (lib/domain/services/avatar_color_service.dart), avatar colors should be locally randomized (Signal-style) where different devices see different colors for the same user. Colors are persistent per device but NOT deterministic across devices. This is an intentional design choice per issue #299 discussion with vladimir-krstic.

Applied to files:

  • lib/ui/user_profile_list/widgets/chat_list_active_account_avatar.dart
📚 Learning: 2025-08-12T11:21:53.640Z
Learnt from: josefinalliende
Repo: parres-hq/whitenoise_flutter PR: 455
File: lib/ui/settings/profile/switch_profile_bottom_sheet.dart:0-0
Timestamp: 2025-08-12T11:21:53.640Z
Learning: In the whitenoise_flutter codebase, ContactModel.publicKey can be stored in either npub format (from metadata cache) or hex format (from account storage). The activeAccountProvider may return either format depending on how the account was originally stored, so normalization to hex format is required when comparing with other hex-normalized keys in sorting logic.

Applied to files:

  • lib/ui/user_profile_list/widgets/chat_list_active_account_avatar.dart
  • lib/ui/user_profile_list/start_chat_bottom_sheet.dart
📚 Learning: 2025-11-10T11:47:07.246Z
Learnt from: Quwaysim
Repo: parres-hq/whitenoise_flutter PR: 719
File: lib/ui/user_profile_list/widgets/chat_list_item_tile.dart:63-82
Timestamp: 2025-11-10T11:47:07.246Z
Learning: In the whitenoise_flutter codebase, group members' User.publicKey field is always stored in npub format. The group_provider.dart explicitly converts all member pubkeys to npub using toNpub() before constructing User objects (lines 348-362, 373-378, 452-457), unlike ContactModel.publicKey which can be in either hex or npub format.

Applied to files:

  • lib/ui/user_profile_list/widgets/chat_list_active_account_avatar.dart
  • lib/ui/user_profile_list/start_chat_bottom_sheet.dart
  • lib/src/rust/api/users.dart
  • lib/config/providers/group_provider.dart
  • rust/src/api/users.rs
  • lib/config/providers/user_profile_provider.dart
  • lib/config/providers/group_messages_provider.dart
📚 Learning: 2025-09-14T21:22:00.962Z
Learnt from: Quwaysim
Repo: parres-hq/whitenoise_flutter PR: 634
File: lib/config/providers/group_provider.dart:1130-1132
Timestamp: 2025-09-14T21:22:00.962Z
Learning: In the whitenoise_flutter codebase, the _updateGroupInfo method in GroupsNotifier performs optimistic updates that directly modify Group objects in the provider state (groups list and groupsMap). For non-DM groups, the display name comes from group.name, so updating the Group object directly is sufficient to reflect name changes in the UI without needing to refresh the separate display name cache.

Applied to files:

  • lib/ui/chat/chat_management/add_to_group_screen.dart
  • test/config/providers/group_messages_provider_test.dart
  • lib/domain/services/background_sync_service.dart
  • lib/config/providers/group_provider.dart
  • lib/ui/user_profile_list/group_welcome_invitation_sheet.dart
  • lib/config/providers/group_messages_provider.dart
📚 Learning: 2025-09-16T06:28:24.648Z
Learnt from: Quwaysim
Repo: parres-hq/whitenoise_flutter PR: 640
File: lib/ui/chat/services/chat_dialog_service.dart:21-25
Timestamp: 2025-09-16T06:28:24.648Z
Learning: In lib/ui/core/ui/wn_bottom_sheet.dart, the WnBottomSheet.show method has barrierDismissible parameter that defaults to false, not true.

Applied to files:

  • lib/ui/user_profile_list/start_chat_bottom_sheet.dart
📚 Learning: 2025-09-04T17:54:09.162Z
Learnt from: josefinalliende
Repo: parres-hq/whitenoise_flutter PR: 594
File: lib/ui/chat/chat_info/dm_chat_info.dart:0-0
Timestamp: 2025-09-04T17:54:09.162Z
Learning: In the whitenoise_flutter codebase, pubkey conversion from hex to npub format is handled using a .toNpub() extension method on String, which eliminates the need for manual format checking or calling npubFromHexPubkey() function directly.

Applied to files:

  • lib/ui/user_profile_list/start_chat_bottom_sheet.dart
📚 Learning: 2025-09-03T20:57:53.202Z
Learnt from: josefinalliende
Repo: parres-hq/whitenoise_flutter PR: 594
File: lib/config/providers/user_profile_data_provider.dart:0-0
Timestamp: 2025-09-03T20:57:53.202Z
Learning: In the whitenoise_flutter codebase, pubkey normalization (npub/hex format handling) is implemented in a pubkey validations extension rather than being imported directly into individual providers like user_profile_data_provider.dart.

Applied to files:

  • lib/ui/user_profile_list/start_chat_bottom_sheet.dart
  • test/config/providers/group_messages_provider_test.dart
  • lib/src/rust/api/users.dart
  • test/config/providers/user_profile_provider_test.dart
  • lib/config/providers/user_profile_provider.dart
📚 Learning: 2025-10-12T22:44:49.606Z
Learnt from: CR
Repo: parres-hq/whitenoise_flutter PR: 0
File: .cursor/rules/flutter.mdc:0-0
Timestamp: 2025-10-12T22:44:49.606Z
Learning: Applies to **/*.rs : Use the whitenoise Rust crate (via flutter_rust_bridge) as the sole data source and change trigger

Applied to files:

  • rust/Cargo.toml
  • rust/src/api/users.rs
  • lib/src/rust/frb_generated.dart
📚 Learning: 2025-09-08T17:39:13.711Z
Learnt from: josefinalliende
Repo: parres-hq/whitenoise_flutter PR: 599
File: test/ui/contact_list/start_chat_bottom_sheet_test.dart:173-176
Timestamp: 2025-09-08T17:39:13.711Z
Learning: In the whitenoise Flutter app, the followProvider uses followsProvider behind the scenes, so mocking followsProvider with MockFollowsNotifier effectively controls what followProvider sees in tests.

Applied to files:

  • test/config/providers/group_messages_provider_test.dart
  • test/config/providers/user_profile_provider_test.dart
📚 Learning: 2025-09-26T10:34:09.809Z
Learnt from: Quwaysim
Repo: parres-hq/whitenoise_flutter PR: 693
File: lib/domain/services/notification_service.dart:6-7
Timestamp: 2025-09-26T10:34:09.809Z
Learning: In Dart, explicit type annotations are not required for static final fields when the type can be clearly inferred from the initialization, such as `static final _logger = Logger('ServiceName')` and `static final _plugin = SomePlugin()`.

Applied to files:

  • lib/domain/services/message_sync_service.dart
📚 Learning: 2025-09-01T14:56:50.988Z
Learnt from: josefinalliende
Repo: parres-hq/whitenoise_flutter PR: 568
File: lib/ui/core/ui/wn_image.dart:1-2
Timestamp: 2025-09-01T14:56:50.988Z
Learning: The whitenoise_flutter project does not target web platforms and any future web version would be in a separate repository, so dart:io imports and file system operations are acceptable in this codebase.

Applied to files:

  • lib/domain/services/message_sync_service.dart
📚 Learning: 2025-10-12T22:44:49.606Z
Learnt from: CR
Repo: parres-hq/whitenoise_flutter PR: 0
File: .cursor/rules/flutter.mdc:0-0
Timestamp: 2025-10-12T22:44:49.606Z
Learning: Applies to lib/**/*.dart : Use Dart extensions to manage reusable code

Applied to files:

  • lib/domain/services/message_sync_service.dart
📚 Learning: 2025-10-12T22:44:49.606Z
Learnt from: CR
Repo: parres-hq/whitenoise_flutter PR: 0
File: .cursor/rules/flutter.mdc:0-0
Timestamp: 2025-10-12T22:44:49.606Z
Learning: Applies to lib/**/*.dart : Use Riverpod for state management; prefer StreamProviders for Rust API streams; use keepAlive if needed

Applied to files:

  • lib/domain/services/message_sync_service.dart
📚 Learning: 2025-10-12T22:44:49.606Z
Learnt from: CR
Repo: parres-hq/whitenoise_flutter PR: 0
File: .cursor/rules/flutter.mdc:0-0
Timestamp: 2025-10-12T22:44:49.606Z
Learning: Applies to lib/**/*.dart : Use constants to manage constant values

Applied to files:

  • lib/domain/services/message_sync_service.dart
📚 Learning: 2025-10-12T22:44:49.606Z
Learnt from: CR
Repo: parres-hq/whitenoise_flutter PR: 0
File: .cursor/rules/flutter.mdc:0-0
Timestamp: 2025-10-12T22:44:49.606Z
Learning: Applies to lib/**/*.dart : Use AppLocalizations for translations

Applied to files:

  • lib/domain/services/message_sync_service.dart
📚 Learning: 2025-10-12T22:44:49.606Z
Learnt from: CR
Repo: parres-hq/whitenoise_flutter PR: 0
File: .cursor/rules/flutter.mdc:0-0
Timestamp: 2025-10-12T22:44:49.606Z
Learning: Applies to lib/**/*.dart : Use flutter_rust_bridge to access core app functionality

Applied to files:

  • lib/src/rust/frb_generated.dart
🧬 Code graph analysis (1)
rust/src/frb_generated.rs (1)
rust/src/api/users.rs (4)
  • get_user (29-42)
  • user_has_key_package (83-98)
  • user_metadata (45-60)
  • user_relays (63-80)
⏰ 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). (2)
  • GitHub Check: Flutter CI
  • GitHub Check: Cursor Bugbot
🔇 Additional comments (35)
rust/Cargo.toml (1)

32-32: Manual verification required for whitenoise revision.

The web search and sandbox tools cannot access the git history of the parres-hq/whitenoise repository to confirm that revision 823309eaca19fd7b67f024b4bd5bd4d8e94ca15a exists or to verify that it includes the blockingDataSync parameter changes referenced in the PR objective.

Manually verify by:

  1. Visiting https://github.com/parres-hq/whitenoise/commit/823309eaca19fd7b67f024b4bd5bd4d8e94ca15a to confirm the commit exists and inspect the changeset
  2. Confirming the commit includes API changes for the blockingDataSync parameter in user profile and metadata fetching
lib/config/providers/create_group_provider.dart (1)

192-195: LGTM - Appropriate use of blocking fetch.

Using blockingDataSync: true here is correct. This is a critical pre-flight check before group creation where you need fresh key package data to make the right decision about which users can be included in the group.

test/config/providers/user_profile_provider_test.dart (1)

39-39: LGTM - Test mock properly updated.

The mock signature correctly reflects the new blockingDataSync parameter requirement, maintaining consistency with the updated API interface.

lib/ui/settings/profile/share_profile_qr_scan_screen.dart (1)

209-210: LGTM - Clear documentation of intent.

The comment helpfully documents that blocking fetch is used here to ensure fresh metadata when scanning QR codes, which is appropriate for this user-initiated action.

lib/ui/user_profile_list/start_chat_bottom_sheet.dart (1)

43-43: LGTM - Good performance trade-off.

Using blockingDataSync: false here prioritizes UI responsiveness in the bottom sheet. The graceful fallback to showing an invite option (when key package is missing) makes this trade-off acceptable.

lib/config/providers/welcomes_provider.dart (1)

141-142: LGTM - Clear documentation of intent.

The comment effectively documents that blocking fetch is used for invite flows to ensure fresh metadata, which is appropriate for this critical user interaction.

lib/config/providers/group_provider.dart (1)

437-458: LGTM - Well-designed performance optimization.

Switching to non-blocking fetch (blockingDataSync: false) for loading group member metadata improves chat list performance. The existing retry logic and fallback mechanisms ensure graceful handling of any stale data issues.

lib/ui/user_profile_list/new_chat_bottom_sheet.dart (2)

156-157: LGTM - Clear documentation of intent.

The comment effectively documents that blocking fetch is used for user search to ensure fresh metadata, which is appropriate when users are actively searching for someone to chat with.


263-266: LGTM - Clear documentation of intent.

The comment effectively documents that blocking fetch is used for the support user to ensure fresh metadata, which is appropriate for this critical user support flow.

lib/ui/user_profile_list/widgets/chat_list_active_account_avatar.dart (1)

54-57: LGTM - Appropriate performance optimization.

Using blockingDataSync: false for the chat list avatar is a good choice to improve UI responsiveness. The avatar will display cached data initially and update when fresh data arrives, which provides a smooth user experience.

lib/ui/settings/profile/switch_profile_bottom_sheet.dart (1)

115-123: LGTM! Non-blocking fetch improves profile list performance.

Using blockingDataSync: false with Future.wait enables concurrent profile fetches, which significantly improves loading time when multiple accounts exist. This is an appropriate optimization for a UI list where stale data is acceptable and will be updated in the background.

lib/domain/services/background_sync_service.dart (1)

245-245: LGTM! Blocking sync is appropriate for background metadata refresh.

Using blockingDataSync: true in the background metadata refresh task ensures that the metadata is fully synchronized before the task completes. This is correct behavior for a scheduled job whose explicit purpose is to refresh user metadata.

lib/domain/services/message_sync_service.dart (3)

135-143: LGTM! Blocking sync ensures accurate notification content.

Using blockingDataSync: true when fetching sender metadata for notifications is correct. Notifications are critical user-facing features that require accurate, up-to-date display names to avoid confusion.


285-293: LGTM! Blocking sync ensures accurate invite notifications.

Using blockingDataSync: true for welcomer metadata ensures invite notifications display the correct inviter information, which is essential for users to make informed decisions about accepting or declining invites.


401-401: LGTM! Blocking sync ensures accurate DM display names.

Using blockingDataSync: true when resolving DM display names is appropriate to ensure accurate identification of conversation participants in notifications.

rust/src/api/users.rs (4)

29-42: LGTM! Clear implementation of blocking sync mode.

The addition of the blocking_data_sync parameter and its conversion to UserSyncMode is straightforward and correct. The conditional logic clearly maps the boolean to the appropriate enum variant.


45-60: LGTM! Consistent pattern for metadata fetching.

The implementation follows the same pattern as get_user, correctly converting blocking_data_sync to UserSyncMode and passing it to the underlying user lookup.


63-80: LGTM! Consistent implementation for relay fetching.

The function correctly accepts blocking_data_sync, converts it to UserSyncMode, and applies it when fetching the user before retrieving their relays.


83-98: LGTM! Consistent implementation for key package check.

The function follows the established pattern, correctly applying the sync mode when looking up the user before checking for key package existence.

lib/ui/user_profile_list/group_welcome_invitation_sheet.dart (3)

122-125: LGTM! Blocking sync ensures accurate inviter information.

Using blockingDataSync: true when fetching inviter metadata for group invitations is correct. Users need accurate inviter information to make informed decisions about accepting or declining group invites.


252-255: LGTM! Blocking sync ensures accurate avatar display.

Using blockingDataSync: true for fetching inviter metadata to display their avatar in direct message invitations is appropriate, ensuring users can properly identify who is inviting them.


298-298: LGTM! Blocking sync ensures accurate invite card information.

Using blockingDataSync: true when fetching inviter metadata for the direct message invite card ensures all displayed information (name, nip05, public key) is accurate and up-to-date.

lib/config/providers/group_messages_provider.dart (1)

107-114: LGTM! Non-blocking fetch optimizes message list loading.

Using blockingDataSync: false with Future.wait enables concurrent fetching of user profiles for group members, significantly improving message list load times. This is an appropriate optimization since user profile data in message displays can tolerate slight staleness and will be updated in the background.

rust/src/frb_generated.rs (4)

2545-2556: FFI: user_has_key_package includes blockingDataSync consistently

Decoding and forwarding api_blocking_data_sync aligns with Rust users::user_has_key_package(pubkey, bool). No issues spotted.


2586-2596: FFI: user_metadata wiring matches updated Rust signature

Argument order and async wrapper are consistent; decode -> forward -> await. LGTM.


2625-2638: FFI: user_relays adds blockingDataSync after relay_type

Ordering pubkey, relay_type, blockingDataSync matches Dart side. Looks good.


1335-1345: FFI parameter order verified as correct—no legacy invocations found

The decode and forward order is correct (String pubkey, then bool blockingDataSync). All Dart callsites in the codebase are compatible with the generated stub signature and use proper parameter ordering. No legacy invocations remain.

lib/config/providers/user_profile_provider.dart (1)

8-19: Internal function type extended to include blockingDataSync

Type of _wnApiGetUser and constructor injection widened appropriately; defaulting to wn_users_api.getUser keeps behavior centralized. No issues.

lib/src/rust/api/users.dart (3)

16-22: Dart stub getUser now requires blockingDataSync; aligns with FRB wire args

Signature and forwarding to RustLib.instance.api.crateApiUsersGetUser are correct.


24-30: userMetadata: required blockingDataSync correctly propagated

Ordering and call target match the generated Rust bridge.


32-40: userRelays: added required bool maintains API symmetry

Consistent with Rust side (pubkey, relayType, blockingDataSync). LGTM.

lib/src/rust/frb_generated.dart (4)

222-225: blockingDataSync wired through getUser path

The new blockingDataSync parameter is carried from the abstract API through the encoder and TaskConstMeta, so the Dart/Rust contract stays in sync.

Also applies to: 1500-1523


344-347: userHasKeyPackage correctly encodes blocking flag

Signature, serializer call, and const metadata all reflect the extra boolean, keeping the bridge coherent.

Also applies to: 2529-2552


349-352: userMetadata update looks consistent

The bool is added everywhere it needs to be, ensuring the request/response contract matches the Rust side.

Also applies to: 2563-2586


354-358: userRelays argument order stays aligned

blockingDataSync joins the relay request after relayType, and the TaskConstMeta/argValues mirror that ordering, so serialization remains correct.

Also applies to: 2597-2625

Copy link
Contributor

@Quwaysim Quwaysim left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@josefinalliende josefinalliende left a comment

Choose a reason for hiding this comment

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

Thanks for making this change! 🫶 It worked perfect and smooth for login and search and scanning QR. The only place where I still see "Unknown user" is in invite notifications (#820)

  • ✅ Login with a nsec that already has a user profile picture, now shows the image in the profile avatar above in the chat lsit screen

  • ✅ Users search work fine, I don't see Unknown users anymore and now it finds the key package at first attempt. Before I needed to always close and try a second time to be able to start a chat

  • ✅ Scanning QR: Amazing, now I don't see Unknown user and also see the user image

  • 🤔 Invites notifications: I still receive an Unknown user there when I receive an invite from a user that I don't follow #820 But this is not a blocker, I'm approving. This PR is arleady a huge improvement compared to master! 🎉

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.

5 participants