Skip to content

feat(ui-message-list): add message attachments - #43725

Draft
gabriellsh wants to merge 12 commits into
message-list/03-contexts-and-contentfrom
message-list/04-attachments
Draft

gabriellsh wants to merge 12 commits into
message-list/03-contexts-and-contentfrom
message-list/04-attachments

Conversation

@gabriellsh

@gabriellsh gabriellsh commented Nov 13, 2026 •

Copy link
Copy Markdown
Member

Proposed changes (including videos or screenshots)

Adds the message attachment components to @rocket.chat/ui-message-list (file, image, audio, video, generic, encrypted download, PDF, quote, default and action attachments, the map) and the media value of MessagesProvider: the shared audio player, downloads through the service worker, the encrypted PDF opener and the desktop document viewer. Every consumer switches to the package parts and the app's copies are deleted: the room, thread and system message variants, the forward, pin and report dialogs, the composer's quote, contact history, moderation, the share-location modal and MediaPlayerProvider.

Twelve commits. The first two code commits sit below the feature: a fix (downloading an encrypted file a second time) and a refactor of the encrypted PDF opener, which now keeps one blob, one request and one download id per file even though the provider shares the opener.

Spacing in the package's attachments uses the spacing scale tokens, except two 2px values: the bottom margin of AttachmentRow and the gap of a row in DefaultAttachment. Their entries in scripts/spacing-scale/baseline.json move from the app paths to the package paths; the entries of the other deleted app attachments go. The spec develop added in #43386 for the action attachment's mutation moves into the package.

This is part 04 of the stack (00 to 09). Review it against its base branch message-list/03-contexts-and-content, not against develop.

Stack

Visible changes

.changeset/encrypted-attachment-downloads-again.md, '@rocket.chat/meteor': patch: an encrypted file can be downloaded a second time from the same button, in a message and in the room's files list. Before, only the first download saved the file.

Known differences from develop

  • The encrypted PDF opener keeps the five most recent blobs. A blob can be released while its viewer still shows it, once five newer files are opened.
  • The audio control can lag the shared player by one frame. Only audio attachments render again with the player's progress.
  • Quoted messages keep the app's current hover styling.

Issue(s)

Steps to test or reproduce

In a room:

  • an image, a video, an audio message, a generic file, a markdown file, a PDF, a quote with nested attachments, and a file in an E2EE room;
  • play audio, switch rooms, and confirm it keeps playing in the sidebar card;
  • collapse an image, scroll it away and back: it stays collapsed;
  • download an encrypted file twice from the same button;
  • open an encrypted PDF (the desktop viewer when it is there, a download otherwise).

Elsewhere:

  • forward, pin and report a message with an attachment (no toolbar in these dialogs);
  • quote a message with an attachment in the composer;
  • open the contact history of an omnichannel contact with files;
  • open a reported message in moderation;
  • share a location.

Further comments

Decisions to check

  • Two 2px attachment values. AttachmentRow's bottom margin and the row gap in DefaultAttachment stay 2px, as on develop, with entries in the spacing scale baseline instead of a token.
  • Changesets for @rocket.chat/ui-message-list. This PR adds none for the private package; parts 08 and 09 of the stack do. The repo versions private packages (other private packages carry changesets), so 08 and 09 follow the repo, and 03 to 07 may need changesets too. Undecided.

Not run

  • The e2e suites, and the app in a browser.
  • Checks ran on the branch tip only, not commit by commit.
  • The moderation and contact-history mounts are covered only by this manual pass.

🤖 Generated with Claude Code

@changeset-bot

changeset-bot Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: dc00db2

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@rocket.chat/meteor Patch
@rocket.chat/core-typings Patch
@rocket.chat/rest-typings Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@dionisio-bot

dionisio-bot Bot commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

Looks like this PR is not ready to merge, because of the following issues:

  • This PR is still a draft
  • This PR is missing the 'stat: QA assured' label
  • This PR is missing the required milestone or project

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@coderabbitai

coderabbitai Bot commented Nov 13, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@codecov

codecov Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.88146% with 30 lines in your changes missing coverage. Please review.
✅ Project coverage is 71.48%. Comparing base (5917e63) to head (dc00db2).

Additional details and impacted files

Impacted file tree graph

@@                           Coverage Diff                            @@
##           message-list/03-contexts-and-content   #43725      +/-   ##
========================================================================
+ Coverage                                 71.30%   71.48%   +0.17%     
========================================================================
  Files                                      5624     5618       -6     
  Lines                                    250477   250864     +387     
  Branches                                  46723    46990     +267     
========================================================================
+ Hits                                     178606   179327     +721     
+ Misses                                    67493    67190     -303     
+ Partials                                   4378     4347      -31     
Flag Coverage Δ
e2e 63.11% <53.73%> (+0.10%) ⬆️
e2e-api 49.49% <ø> (+0.03%) ⬆️
unit 70.39% <90.88%> (+0.26%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

gabriellsh and others added 12 commits November 13, 2026 18:10
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
The download result was awaited by a listener registered once per mounted
button, so only the first activation saved the file. Each activation now
registers its own result.

message-attachments R24

Co-Authored-By: Claude <noreply@anthropic.com>
…ds apart

The opener will be shared by every attachment under one provider. Each file
keeps its own blob and request, as each attachment did, so opening a file
never revokes another file's blob; only the blobs of the five most recently
opened files are kept; finished requests are dropped; and each download is
asked for under its own id, so pending downloads are each saved once under
their own title.

message-attachments R18

Co-Authored-By: Claude <noreply@anthropic.com>
Adds the attachment components (file, image, audio, video, generic and
encrypted files, PDF, quote, default attachments with fields and actions),
their hooks, stories and specs, copied from the reference, and exports
MessageAttachments, MessageQuoteAttachment, MessageMapView and
useMediaReloadOnError. The quote keeps develop's hover styling.

Departures from the reference: descriptions and quotes are drawn from their
parsed markdown alone, as in the app, so blocks the renderer does not know
show nothing and translated text is not cut from the original; the shared
player reaches the media context as a store that only audio attachments
subscribe to; the desktop viewer's open takes a title.

Spacings use the Fuselage tokens; the two that have none keep their value
and their entries in the spacing baseline.

message-attachments R1 to R13, R20

Co-Authored-By: Claude <noreply@anthropic.com>
MessagesProvider now gives the media context the shared audio player, as a
store only audio attachments subscribe to, downloads of encrypted files
through the service worker, the encrypted PDF opener, the desktop document
viewer and file sizes. The viewer still receives the attachment's title for
an encrypted PDF, an encrypted PDF is downloaded where there is no viewer,
and whether encrypted downloads are possible is read when a button renders.

message-attachments R14 to R20

Co-Authored-By: Claude <noreply@anthropic.com>
Room, thread and system messages, moderation's reported messages and the
omnichannel contact history render MessageAttachments instead of the app's
copy. Specs assert the attachments through each of these places.

message-attachments R21, R22

Co-Authored-By: Claude <noreply@anthropic.com>
…he ui-message-list quote

The forward and pin modals and the composer's quote render
MessageQuoteAttachment, aliased where the core-typings type of the same name
is imported. Specs assert through each place, without mocking the quote.

message-attachments R22

Co-Authored-By: Claude <noreply@anthropic.com>
The share-location modal previews the location with MessageMapView, and the
shared audio player recovers expired signed URLs with useMediaReloadOnError.

message-attachments R23, R25

Co-Authored-By: Claude <noreply@anthropic.com>
Removes the app's attachment components, collapsible parts, collapse hooks
and location map, which the ui-message-list package renders now. Nothing in
the app imports them. The specs of the deleted collapse hooks move to the
app's collapse state of the related-data value, which keeps it in the opened
room's store. The spec of the deleted action button mutation goes too: the
package proves which capability an action calls, and MessagesProvider's spec
how the app carries the capability out. The spacing baseline drops the
deleted files.

message-attachments R3, R21 to R23

Co-Authored-By: Claude <noreply@anthropic.com>
Fills the spec's Design, code and tests, marks the plan done, and updates the
notes of message-capabilities that waited for attachments. Records the
package's direct fetch in useReloadOnError as a known departure, and that
audio in the quotes of the forward and pin modals cannot play.

Co-Authored-By: Claude <noreply@anthropic.com>
@gabriellsh
gabriellsh force-pushed the message-list/04-attachments branch from 6a0aa8b to dc00db2 Compare November 14, 2026 14:29

This branch has not been deployed

No deployments
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.

1 participant