-
Notifications
You must be signed in to change notification settings - Fork 14
Feat/media reply preview #770
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughThis PR refactors the chat reply preview UI by extracting a new Changes
Sequence Diagram(s)sequenceDiagram
participant MW as MessageWidget
participant MRB as MessageReplyBox
participant CIRP as ChatInputReplyPreview
participant MMT as MessageMediaTile
MW->>MRB: render(replyingTo)
activate MRB
MRB->>MRB: check replyingTo.mediaAttachments
alt has media attachments
MRB->>MMT: render first attachment
activate MMT
MMT-->>MRB: media tile widget
deactivate MMT
end
MRB->>MRB: display sender name & content
MRB-->>MW: reply preview widget
deactivate MRB
Note over CIRP: Row layout (new)<br/>Media | Text | Close
CIRP->>MMT: conditional render
alt media exists
MMT-->>CIRP: first attachment tile
end
CIRP->>CIRP: Expanded column for text
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
2b994ce to
c71342d
Compare
c71342d to
2c77d05
Compare
2c77d05 to
a131973
Compare
There was a problem hiding this 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 (1)
test/ui/chat/widgets/message_reply_box_test.dart (1)
10-33: LGTM! Consistent test setup.The test user and media file helper follow the same pattern as chat_input_reply_preview_test.dart, ensuring consistent testing approach across components.
The
createTestMediaFilehelper is duplicated between this file and chat_input_reply_preview_test.dart. Consider extracting it to a shared test utilities file for reusability:// test/ui/chat/widgets/test_helpers.dart MediaFile createTestMediaFile({required String id}) { return MediaFile( id: id, mlsGroupId: 'group-id', accountPubkey: 'pubkey', filePath: '/test/path/$id.jpg', fileHash: 'hash-$id', mimeType: 'image/jpeg', mediaType: 'image', blossomUrl: 'https://example.com/$id.jpg', nostrKey: 'key-$id', fileMetadata: const FileMetadata(), createdAt: DateTime.now(), ); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
lib/ui/chat/widgets/chat_input_reply_preview.dart(2 hunks)lib/ui/chat/widgets/media_preview.dart(1 hunks)lib/ui/chat/widgets/message_reply_box.dart(1 hunks)lib/ui/chat/widgets/message_widget.dart(2 hunks)test/ui/chat/widgets/chat_input_reply_preview_test.dart(1 hunks)test/ui/chat/widgets/message_reply_box_test.dart(1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.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/chat/widgets/chat_input_reply_preview.dartlib/ui/chat/widgets/message_reply_box.dartlib/ui/chat/widgets/message_widget.dartlib/ui/chat/widgets/media_preview.darttest/ui/chat/widgets/message_reply_box_test.darttest/ui/chat/widgets/chat_input_reply_preview_test.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/chat/widgets/chat_input_reply_preview.dartlib/ui/chat/widgets/message_reply_box.dartlib/ui/chat/widgets/message_widget.dartlib/ui/chat/widgets/media_preview.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/ui/chat/widgets/message_reply_box_test.darttest/ui/chat/widgets/chat_input_reply_preview_test.dart
🧠 Learnings (12)
📓 Common learnings
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.
📚 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/chat/widgets/chat_input_reply_preview.dartlib/ui/chat/widgets/media_preview.darttest/ui/chat/widgets/chat_input_reply_preview_test.dart
📚 Learning: 2025-08-23T11:02:28.308Z
Learnt from: Quwaysim
Repo: parres-hq/whitenoise_flutter PR: 527
File: lib/ui/core/ui/wn_avatar.dart:1-6
Timestamp: 2025-08-23T11:02:28.308Z
Learning: In the whitenoise_flutter codebase, flutter_screenutil is re-exported through lib/ui/core/themes/src/app_theme.dart, so files that import app_theme.dart do not need to directly import flutter_screenutil to use .w, .h, .sp extensions.
Applied to files:
lib/ui/chat/widgets/chat_input_reply_preview.dartlib/ui/chat/widgets/message_widget.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/ui/chat/widgets/chat_input_reply_preview.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 test/**/*.dart : Use standard Flutter widget testing
Applied to files:
lib/ui/chat/widgets/chat_input_reply_preview.darttest/ui/chat/widgets/message_reply_box_test.darttest/ui/chat/widgets/chat_input_reply_preview_test.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/ui/chat/widgets/chat_input_reply_preview.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 freezed to model/manage UI states
Applied to files:
lib/ui/chat/widgets/chat_input_reply_preview.dart
📚 Learning: 2025-09-24T17:59:53.850Z
Learnt from: josefinalliende
Repo: parres-hq/whitenoise_flutter PR: 688
File: lib/ui/contact_list/chat_list_screen.dart:284-293
Timestamp: 2025-09-24T17:59:53.850Z
Learning: In Flutter apps using Riverpod, complex list processing logic (sorting, filtering, separating) should be extracted to dedicated provider classes rather than embedded in widget build methods. This improves testability, maintainability, and separation of concerns. Create providers like ChatListProcessor to handle business logic and keep widgets focused on UI rendering.
Applied to files:
lib/ui/chat/widgets/message_widget.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/chat/widgets/media_preview.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 test/**/*.dart : Write unit tests for each public function; use test doubles for dependencies (except cheap third-party)
Applied to files:
test/ui/chat/widgets/message_reply_box_test.darttest/ui/chat/widgets/chat_input_reply_preview_test.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 test/**/*.dart : Follow Arrange-Act-Assert in tests
Applied to files:
test/ui/chat/widgets/message_reply_box_test.darttest/ui/chat/widgets/chat_input_reply_preview_test.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 integration_test/**/*.dart : Use integration tests for each API module
Applied to files:
test/ui/chat/widgets/chat_input_reply_preview_test.dart
🔇 Additional comments (19)
lib/ui/chat/widgets/media_preview.dart (1)
93-93: LGTM! Padding adjustments align with design.The reduced horizontal and vertical padding values improve the visual alignment for media previews in reply contexts.
test/ui/chat/widgets/chat_input_reply_preview_test.dart (4)
10-33: LGTM! Well-structured test setup.The test user and media file helper are properly defined with clear naming and all required fields.
35-88: LGTM! Comprehensive coverage for messages without media.The test group properly validates that reply previews without media display user name and content without showing a media tile.
90-145: LGTM! Proper validation for single media attachment.The test group correctly verifies that reply previews with one media attachment display both text content and the media tile.
147-220: LGTM! Excellent validation for multiple media attachments.The test group properly verifies that when multiple media attachments exist, exactly one media tile is shown and it's specifically the first attachment (lines 205-219). This directly validates the PR objective.
lib/ui/chat/widgets/message_widget.dart (2)
12-12: LGTM! Clean import of extracted component.The import correctly references the new MessageReplyBox widget from its dedicated file.
132-136: LGTM! Proper usage of extracted MessageReplyBox.The component replacement maintains the same API contract with replyingTo and onTap parameters.
lib/ui/chat/widgets/chat_input_reply_preview.dart (4)
5-5: LGTM! Import supports media tile rendering.The MessageMediaTile import is necessary for displaying media attachments in the reply preview.
40-50: LGTM! Media tile properly renders first attachment.The horizontal layout correctly displays the first media attachment when available. The conditional check ensures
mediaAttachments.isNotEmptybefore accessing.first(line 46), preventing runtime errors.
51-82: LGTM! Well-structured text content layout.The nested Expanded/Row/Column structure provides proper flexible sizing, and text content correctly handles null cases with localized fallbacks. The single-line truncation with ellipsis ensures the preview doesn't overflow.
83-96: LGTM! Cancel button properly implemented.The close icon is correctly wired to the onCancel callback with proper sizing and theming.
lib/ui/chat/widgets/message_reply_box.dart (5)
11-14: LGTM! Clean widget API.The MessageReplyBox properly extends ConsumerWidget with well-typed optional parameters for flexibility.
17-22: LGTM! Proper localization handling and early return.The widget correctly watches locale changes for dynamic updates and efficiently returns an empty widget when there's no reply context.
23-38: LGTM! Proper Material Design hierarchy.The widget structure (Material > InkWell > Container) correctly enables tap feedback while maintaining proper styling with theme colors and responsive sizing.
39-49: LGTM! Consistent media tile implementation.The media rendering correctly displays the first attachment when available, matching the implementation in chat_input_reply_preview.dart with consistent sizing (32.w).
50-77: LGTM! Well-structured text content display.The text layout properly uses MessageUtils.getDisplayName for consistent name display and handles null content gracefully. Single-line truncation prevents overflow.
test/ui/chat/widgets/message_reply_box_test.dart (3)
35-88: LGTM! Thorough coverage for messages without media.The test group properly validates MessageReplyBox behavior when no media attachments are present, ensuring user name and content display correctly without a media tile.
90-145: LGTM! Proper validation for single media attachment.The test group correctly verifies that MessageReplyBox displays both text content and the media tile when one attachment is present.
147-220: LGTM! Excellent validation for multiple media attachments.The test group thoroughly validates that MessageReplyBox shows exactly one media tile for the first attachment when multiple exist (lines 205-219), directly confirming the PR objective.
untreu2
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Description
This PR shows first image in the reply preview of message bubble and in the reply preview of chat input.
https://www.figma.com/design/dGJqv6m6pchdcwxJEwxxzB/White-Noise---Design-System?node-id=3536-43262&t=ZyUC6TcDAvCeNV3t-0
Commit by commit:
Type of Change
Checklist
just precommitto ensure that formatting and linting are correctjust check-flutter-coverageto ensure that flutter coverage rules are passingCHANGELOG.mdfile with your changes (if they affect the user experience)Summary by CodeRabbit
Style
Tests