Skip to content

Fix: attachment issues #913

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

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open

Fix: attachment issues #913

wants to merge 10 commits into from

Conversation

abdou6666
Copy link
Member

@abdou6666 abdou6666 commented Apr 11, 2025

Motivation

This PR addresses the issue of console widget crushing when an attachment in attachment block gets deleted & subscriber has that attachment in their conversation history
Fixes #895

Type of change:

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)

Checklist:

  • I have performed a self-review of my own code

Summary by CodeRabbit

  • New Features

    • Introduced a dedicated endpoint for "Not Found" scenarios that returns a clear error message.
    • Enhanced media error feedback, providing specific notifications for missing images, audio, video, and files.
    • Integrated attachment handling improvements for more robust message management.
  • Bug Fixes

    • Streamlined error handling by returning fallback content instead of unexpected crashes.
    • Corrected wording for unknown media types and updated translations for improved clarity.
  • Style

    • Added refined styling for error messages to enhance visual consistency.

@abdou6666 abdou6666 self-assigned this Apr 11, 2025
Copy link

coderabbitai bot commented Apr 11, 2025

"""

Walkthrough

This pull request introduces several enhancements across the codebase. In the API layer, the ChannelHandler.getPublicUrl method now returns fallback URLs instead of throwing exceptions when attachments are missing or invalid, and a new 404 handler has been added to the webhook controller. The chat module now imports and provides attachment-related services, and the message service includes an event handler to clean up messages linked to deleted attachments. In the frontend and widget layers, new error messages have been added for missing media, and components have been updated to handle media load failures with clear UI feedback.

Changes

File(s) Change Summary
api/src/channel/lib/Handler.ts Updated getPublicUrl to return fallback URLs instead of throwing exceptions for missing/invalid attachments and added logging for resource lookup failures.
api/src/channel/webhook.controller.ts Added handleNotFound method with @Roles('public') to return a 404 JSON response for unreachable channels.
api/src/chat/chat.module.ts, api/src/chat/services/message.service.ts Integrated attachment dependencies into the chat module and added handleDeleteImage event handler to clean up messages linked to deleted attachments; updated constructor to inject AttachmentService.
frontend/public/locales/{en,fr}/translation.json, widget/src/translations/{en,fr}/translation.json Introduced new error message keys (image_error, file_error, audio_error, video_error) for enhanced media error reporting in localization files.
frontend/src/components/inbox/components/AttachmentViewer.tsx, widget/src/components/messages/FileMessage.tsx Enhanced error state handling and UI feedback in components for media load failures, including state management for images, audio, and video errors, and added early return for unknown file types.
widget/src/components/messages/FileMessage.scss Added new CSS class .error-message to style error messages in file message components.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant ChannelHandler
    participant Logger

    Client->>ChannelHandler: getPublicUrl(attachment)
    alt Attachment missing or invalid
        ChannelHandler-->>Client: Return fallback URL
    else Attachment provided
        ChannelHandler->>ChannelHandler: Lookup resource
        alt Resource found
            ChannelHandler-->>Client: Return constructed download URL
        else Resource missing
            ChannelHandler->>Logger: Log warning
            ChannelHandler-->>Client: Return fallback URL
        end
    end
Loading
sequenceDiagram
    participant Event
    participant MessageService
    participant AttachmentService
    participant MessageRepository
    participant Logger

    Event->>MessageService: handleDeleteImage(query, criteria)
    MessageService->>AttachmentService: find(criteria)
    alt Attachment exists
        MessageService->>MessageRepository: updateMultiple (set payload.id to null)
        MessageRepository-->>MessageService: Update result
    else Attachment not found or error
        MessageService->>Logger: Log error
    end
Loading

Assessment against linked issues

Objective Addressed Explanation
Fix error handling for missing attachments (#895)

Poem

I'm a rabbit hopping through the code,
Finding bugs and easing every load.
Fallbacks now replace the crash,
Error messages in a flash.
With every fix, I skip with glee—
A merry code trail for you and me! 🐰
Hop on to a smoother legacy!
"""

Tip

⚡💬 Agentic Chat (Pro Plan, General Availability)
  • We're introducing multi-step agentic chat in review comments and issue comments, within and outside of PR's. This feature enhances review and issue discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments and add commits to existing pull requests.
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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

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

🧹 Nitpick comments (5)
api/src/setting/services/setting.service.ts (1)

50-68: Consider finalizing or removing commented code for avatar setup.

The commented-out code appears to be an implementation for setting up a default avatar image. If this functionality is needed, it should be properly implemented and the code uncommented. Otherwise, consider removing it to maintain code cleanliness.

Note that if you do uncomment and implement this code, you'll need to:

  1. Import necessary dependencies (fs, path)
  2. Inject the attachmentService in the constructor
  3. Import the required types (AttachmentAccess, AttachmentCreatedByRef, AttachmentResourceRef)
widget/src/components/messages/FileMessage.scss (2)

13-21: New CSS Error Message Styling Introduced

The new .error-message class adds a clear style for error feedback within file messages with appropriate margin, padding, border-radius, color, width, and display properties. Ensure that its design aligns with the overall UI/UX guidelines and that the consumption of this class in the React component (FileMessage.tsx) is updated accordingly.


77-85: Legacy Commented-Out Styling Block

A previously used or alternative version of the .error-message class is still present but commented out. If this code is no longer needed, please consider removing it to keep the stylesheet clean; otherwise, add a clarifying comment as to why it remains in the file.

api/src/channel/lib/Handler.ts (1)

333-336: Remove commented-out code.

The code now correctly returns a fallback URL, but there's a commented-out exception throw that should be removed as it's no longer needed and could cause confusion during future maintenance.

  return buildURL(config.apiBaseUrl, `/webhook/${name}/not-found`);

-  // throw new TypeError('Unable to resolve the attachment public URL.');
api/src/chat/services/message.service.ts (1)

159-166: Consider the performance implications of the updateMany operation.

The current implementation uses updateMany to update all messages that reference the deleted attachment. Depending on the volume of messages, this could be an expensive operation.

If message volume is high, consider adding an index on message.attachment.payload.id to improve query performance, or implementing a batched update approach for very large message collections.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between aed32e8 and 8bd778d.

⛔ Files ignored due to path filters (1)
  • api/assets/hexavatar.png is excluded by !**/*.png
📒 Files selected for processing (14)
  • api/src/attachment/controllers/attachment.controller.ts (1 hunks)
  • api/src/attachment/types/index.ts (1 hunks)
  • api/src/channel/lib/Handler.ts (2 hunks)
  • api/src/channel/webhook.controller.ts (1 hunks)
  • api/src/chat/chat.module.ts (4 hunks)
  • api/src/chat/services/message.service.ts (3 hunks)
  • api/src/setting/services/setting.service.ts (1 hunks)
  • frontend/public/locales/en/translation.json (1 hunks)
  • frontend/public/locales/fr/translation.json (1 hunks)
  • frontend/src/components/inbox/components/AttachmentViewer.tsx (4 hunks)
  • widget/src/components/messages/FileMessage.scss (2 hunks)
  • widget/src/components/messages/FileMessage.tsx (4 hunks)
  • widget/src/translations/en/translation.json (1 hunks)
  • widget/src/translations/fr/translation.json (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
api/src/channel/webhook.controller.ts (1)
frontend/src/components/roles/index.tsx (1)
  • Roles (38-162)
api/src/chat/chat.module.ts (1)
api/src/attachment/schemas/attachment.schema.ts (1)
  • AttachmentModel (168-171)
frontend/src/components/inbox/components/AttachmentViewer.tsx (1)
api/src/i18n/services/i18n.service.ts (1)
  • t (27-57)
🪛 Biome (1.9.4)
api/src/attachment/controllers/attachment.controller.ts

[error] 136-136: This is an unexpected use of the debugger statement.

Unsafe fix: Remove debugger statement

(lint/suspicious/noDebugger)

⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Frontend Tests
  • GitHub Check: API-Tests
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (30)
api/src/channel/webhook.controller.ts (1)

91-96: Good addition of a 'not-found' error handling endpoint.

This new endpoint appropriately returns a 404 status with a clear error message, which will help with graceful handling of cases where a channel is not found. The public role ensures it's accessible to external services.

api/src/attachment/types/index.ts (1)

18-18: Good addition of 'System' to AttachmentCreatedByRef enum.

This enhancement allows for system-generated attachments, which is a valuable addition for distinguishing between user, subscriber, and system-created content.

frontend/public/locales/en/translation.json (1)

119-123: New Error Message Keys Added

Four new keys—"image_error", "file_error", "audio_error", and "video_error"—have been introduced to provide clear error messages for missing media attachments. Verify that these keys are consistently referenced in the UI components and that the trailing commas maintain valid JSON syntax.

widget/src/translations/en/translation.json (1)

20-24: Consistent Enhancement of Error Messaging

The addition of error message keys within the "file_message" object (i.e., "image_error", "file_error", "audio_error", and "video_error") aligns well with the attachment issue being fixed. Confirm that the UI components refer to these keys for displaying error messages.

frontend/public/locales/fr/translation.json (1)

120-123: New French Error Message Keys Added

The new keys for attachment issues—"image_error", "file_error", "audio_error", and "video_error"—are now provided in French. Ensure that these keys are used throughout the French UI and that they match the keys in the English version for consistency.

widget/src/translations/fr/translation.json (1)

119-124: Enhanced Error Messaging in French

This update adds localized error messages for attachments under the "file_message" block. The new keys ("image_error", "file_error", "audio_error", "video_error") are clearly translated and should improve the user experience when media-related issues arise.

api/src/chat/chat.module.ts (4)

2-2: LGTM: Updated copyright year.

The copyright year has been updated to 2025.


14-16: LGTM: Added necessary imports for attachment functionality.

These imports are required for the attachment integration in the chat module.


64-64: LGTM: Added AttachmentModel to MongooseModule.forFeature.

This change allows MongoDB to recognize and manage the Attachment schema.


100-101: LGTM: Added attachment services to providers.

AttachmentService and AttachmentRepository are now properly registered as providers, making them available for dependency injection within the module.

frontend/src/components/inbox/components/AttachmentViewer.tsx (6)

11-11: LGTM: Updated import to include useState.

The useState hook is now properly imported for managing error states.


33-38: LGTM: Added error handling for image attachments.

This change improves user experience by displaying an appropriate error message when an image fails to load or when no URL is provided.


43-43: LGTM: Added error event handling for images.

The onError event handler now sets the imageErrored state when an image fails to load.


68-77: LGTM: Implemented error handling for audio attachments.

This change introduces robust error handling for audio playback failures, showing a user-friendly error message when appropriate.


82-84: LGTM: Added URL validation for file attachments.

This validation ensures a meaningful error message is displayed when a file URL is missing.


106-119: LGTM: Added error handling for video attachments.

Similar to other media types, video playback now has proper error handling to improve user experience when videos cannot be loaded.

api/src/channel/lib/Handler.ts (3)

311-311: LGTM: Simplified variable declaration.

The code now uses destructuring to extract just the name from the split result, ignoring the suffix.


313-315: LGTM: Added null check for attachment.

This change prevents potential errors by checking if the attachment or its ID exists before proceeding, returning a fallback URL if not.


320-322: LGTM: Improved error handling for missing attachments.

Rather than throwing an exception, the code now logs a warning and returns a fallback URL, making the application more resilient.

widget/src/components/messages/FileMessage.tsx (9)

2-2: LGTM: Updated copyright year.

The copyright year has been updated to 2025.


9-9: LGTM: Updated import to include useState.

The useState hook is properly imported for managing error states.


25-27: LGTM: Added state variables for error handling.

These state variables enable tracking of loading errors for different media types.


32-34: LGTM: Added handling for unknown file types.

This provides a user-friendly message when a file type is unknown, improving the user experience.


42-43: LGTM: Fixed typo in error message.

The error message spelling has been corrected from "Uknown" to "Unknown".


55-71: LGTM: Implemented error handling for image display.

This change adds robust error handling for images, showing a styled error message when an image fails to load.


76-89: LGTM: Added error handling for audio playback.

Similar to the image implementation, this adds proper error handling for audio elements.


94-108: LGTM: Added error handling for video playback.

The code now properly handles video loading errors, displaying a styled error message when appropriate.


119-133: LGTM: Added URL validation for file downloads.

This validation ensures users receive a clear error message when a file URL is missing instead of getting a broken download link.

api/src/chat/services/message.service.ts (2)

14-21: Import dependencies are correctly structured for the new attachment handling feature.

The new imports are appropriately added to support the attachment deletion functionality. The OnEvent decorator from NestJS event emitter will allow the service to respond to attachment deletion events.


48-48: Constructor properly injects the AttachmentService dependency.

The AttachmentService is correctly injected as a private field, maintaining the existing pattern of dependency injection in the class.

Comment on lines 138 to 173
@OnEvent('hook:attachment:preDelete')
async handleDeleteImage(
_query: Query<
DeleteResult,
Document<Attachment, any, any>,
unknown,
Attachment,
'deleteOne' | 'deleteMany'
>,
criteria: TFilterQuery<Attachment>,
) {
// todo: handle deleteMany
try {
this.logger.log(
'deleting attachment messages containing deleted images',
criteria,
);
const foundAttachment = await this.attachmentService.findOne(criteria);
if (!foundAttachment) {
return;
}
await this.updateMany(
{
'message.attachment.payload.id': criteria._id,
},
{
['message.attachment.payload.id' as any]: null,
},
);
} catch (error) {
this.logger.error(
'Unable to cleanup old messages with attachment ids',
error,
);
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

The new event handler addresses attachment deletion, but has several improvement opportunities.

The handleDeleteImage method correctly handles cleaning up messages when attachments are deleted, but there are a few issues to address:

  1. The TODO comment indicates incomplete functionality for handling multiple deletions
  2. The _query parameter is unused but still present
  3. There's a type casting to any that could be improved
  4. Error handling just logs errors without any recovery mechanism

Consider these improvements:

@OnEvent('hook:attachment:preDelete')
async handleDeleteImage(
-  _query: Query<
+  query: Query<
    DeleteResult,
    Document<Attachment, any, any>,
    unknown,
    Attachment,
    'deleteOne' | 'deleteMany'
  >,
  criteria: TFilterQuery<Attachment>,
) {
-  // todo: handle deleteMany
+  // Handle both single and batch deletions
  try {
    this.logger.log(
      'deleting attachment messages containing deleted images',
      criteria,
    );
    const foundAttachment = await this.attachmentService.findOne(criteria);
    if (!foundAttachment) {
      return;
    }
    await this.updateMany(
      {
        'message.attachment.payload.id': criteria._id,
      },
      {
-        ['message.attachment.payload.id' as any]: null,
+        $set: { 'message.attachment.payload.id': null },
      },
    );
  } catch (error) {
    this.logger.error(
      'Unable to cleanup old messages with attachment ids',
      error,
    );
+    // Consider adding metrics or alerts for monitoring these failures
  }
}
📝 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
@OnEvent('hook:attachment:preDelete')
async handleDeleteImage(
_query: Query<
DeleteResult,
Document<Attachment, any, any>,
unknown,
Attachment,
'deleteOne' | 'deleteMany'
>,
criteria: TFilterQuery<Attachment>,
) {
// todo: handle deleteMany
try {
this.logger.log(
'deleting attachment messages containing deleted images',
criteria,
);
const foundAttachment = await this.attachmentService.findOne(criteria);
if (!foundAttachment) {
return;
}
await this.updateMany(
{
'message.attachment.payload.id': criteria._id,
},
{
['message.attachment.payload.id' as any]: null,
},
);
} catch (error) {
this.logger.error(
'Unable to cleanup old messages with attachment ids',
error,
);
}
}
@OnEvent('hook:attachment:preDelete')
async handleDeleteImage(
query: Query<
DeleteResult,
Document<Attachment, any, any>,
unknown,
Attachment,
'deleteOne' | 'deleteMany'
>,
criteria: TFilterQuery<Attachment>,
) {
// Handle both single and batch deletions
try {
this.logger.log(
'deleting attachment messages containing deleted images',
criteria,
);
const foundAttachment = await this.attachmentService.findOne(criteria);
if (!foundAttachment) {
return;
}
await this.updateMany(
{
'message.attachment.payload.id': criteria._id,
},
{
$set: { 'message.attachment.payload.id': null },
},
);
} catch (error) {
this.logger.error(
'Unable to cleanup old messages with attachment ids',
error,
);
// Consider adding metrics or alerts for monitoring these failures
}
}

@abdou6666 abdou6666 marked this pull request as draft April 14, 2025 15:48
@abdou6666 abdou6666 marked this pull request as ready for review April 14, 2025 16:03
Copy link
Collaborator

@IkbelTalebHssan IkbelTalebHssan left a comment

Choose a reason for hiding this comment

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

Hi @abdou6666
I noticed this behavior when triggering an attachment block missing an attachment.
Screencast from 04-16-2025 02:19:13 PM.webm

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ba729de and bc0a9d5.

📒 Files selected for processing (1)
  • widget/src/components/messages/FileMessage.tsx (4 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
widget/src/components/messages/FileMessage.tsx

[error] 41-42: There is a suspicious semicolon in the JSX element.

This is usually the result of a typo or some refactor gone wrong.
Remove the semicolon, or move it inside a JSX element.

(lint/suspicious/noSuspiciousSemicolonInJsx)

⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: API-Tests
  • GitHub Check: Frontend Tests
🔇 Additional comments (7)
widget/src/components/messages/FileMessage.tsx (7)

9-9: Import of useState correctly added

Adding useState is necessary to support the new error state variables for tracking media loading failures.


25-27: Good addition of error state tracking

These state variables provide a clean way to track loading errors for different media types, which is essential for the robust error handling being implemented.


52-52: Typo correction in error message

Fixed typo from "Uknown" to "Unknown" in the error message, improving code clarity.


65-81: Robust error handling for images

This implementation correctly handles image loading failures by:

  1. Setting an error state when the image fails to load
  2. Displaying a user-friendly error message with appropriate styling
  3. Maintaining consistent styling with the parent component

This addresses the PR objective of preventing crashes when attachments are deleted.


86-99: Robust error handling for audio

The audio error handling implementation follows the same pattern as images - capturing the error event and showing a localized error message.


104-118: Robust error handling for videos

The video error handling follows the consistent pattern established for other media types, with proper error state management and user feedback.


129-143: Proper URL validation for file downloads

This change correctly handles missing URLs for file downloads, showing an error message instead of trying to create a download link to an invalid resource, which aligns perfectly with the PR objective of fixing attachment issues.

Copy link
Collaborator

@IkbelTalebHssan IkbelTalebHssan left a comment

Choose a reason for hiding this comment

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

LGTM
image

@MohamedAliBouhaouala
Copy link
Contributor

Screenshot from 2025-04-16 15-54-06
Screenshot from 2025-04-16 16-19-20
LGTM!
Just quick observation: I think event-based unit testing logic at the base repository level should be addressed in the future.

@MohamedAliBouhaouala MohamedAliBouhaouala self-requested a review April 16, 2025 15:23
Comment on lines 32 to 46
if (message.data.type === "unknown") {
return (
<div
className="sc-message--file"
style={{
color: colors.text,
backgroundColor: colors.bg,
}}
>
<p className="error-message">
{t("messages.file_message.unsupported_file_type")}
</p>
</div>
);
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Hi @abdou6666, I suggest to create a function to handle the message.data.type values.
The intent is to centralize the check in one place.
Please, don't hesitate to ask if you have any questions.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
widget/src/components/messages/FileMessage.tsx (2)

108-124: Consider adding a browser fallback message for audio.

While you've added good error handling for audio elements, consider adding a browser compatibility message similar to what you've done for video (line 140).

 <audio controls onError={() => setAudioErrored(true)}>
   <source src={hasUrl(message) ? message.data.url : ""} />
+  {t("messages.file_message.browser_audio_unsupport")}
 </audio>

17-168: Consider refactoring repeated error styling patterns.

There's some duplication in how error messages are styled across different media types. Consider extracting a reusable error message component to reduce duplication.

// Example of a reusable error component
const MediaErrorMessage = ({ 
  message, 
  backgroundColor 
}: { 
  message: string, 
  backgroundColor: string 
}) => (
  <p
    className="error-message"
    style={{
      backgroundColor,
    }}
  >
    {message}
  </p>
);

// Then usage would be:
{imageErrored ? (
  <MediaErrorMessage 
    message={t("messages.file_message.image_error")} 
    backgroundColor={colors.bg} 
  />
) : (
  <img ... />
)}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 19a073f and 2be7be6.

📒 Files selected for processing (1)
  • widget/src/components/messages/FileMessage.tsx (3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Frontend Tests
  • GitHub Check: API-Tests
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (9)
widget/src/components/messages/FileMessage.tsx (9)

2-2: Verify the copyright year update.

The copyright year has been updated to 2025. Please verify if this is intentional, as we're currently in 2024.


9-9: Good addition of useState import.

Adding the useState import is necessary for the new error state management you've implemented.


17-35: Well-structured type safety function implementation.

The getFileMessageType function provides robust type checking with clear error handling, addressing the previous reviewer's suggestion to centralize file type checking. It properly validates allowed types and handles unknown types gracefully.


36-48: Excellent type guard implementation.

The hasUrl function uses type guards effectively to ensure safe access to the URL property, preventing runtime errors when attachments are deleted or invalid. This directly addresses the core issue in this PR.


58-61: Good implementation of error state management.

Adding dedicated state variables for each media type's error state allows for granular error handling, improving the user experience when media fails to load.


63-77: Effective early return pattern for unknown file types.

Using an early return pattern for handling unknown file types is a good practice that improves code readability and provides a clear error message to users.


87-106: Robust image error handling implementation.

The conditional rendering based on the imageErrored state effectively prevents the component from crashing when image attachments are missing or invalid.


126-143: Good video error handling with browser compatibility message.

The video element now properly handles errors and includes a fallback message for browsers that don't support the video format.


145-168: Effective file download error handling.

The conditional rendering for file downloads prevents errors when the file URL is missing, providing a clear error message instead of attempting to create a broken download link.

@abdou6666 abdou6666 marked this pull request as draft April 21, 2025 10:03
@abdou6666
Copy link
Member Author

While testing a different PR I realized that we need to handle List Block / Custom Plugins might have stale attachment Id in the messages)

@abdou6666 abdou6666 marked this pull request as ready for review April 23, 2025 09:43
@medchedli medchedli added this to the v2.2.6 milestone Apr 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants