Skip to content

feat(thread): show per-message To/Cc/Bcc recipients in thread view#12666

Open
sturlan wants to merge 5 commits intonextcloud:mainfrom
sturlan:feat/11305-thread-per-message-recipients
Open

feat(thread): show per-message To/Cc/Bcc recipients in thread view#12666
sturlan wants to merge 5 commits intonextcloud:mainfrom
sturlan:feat/11305-thread-per-message-recipients

Conversation

@sturlan
Copy link
Copy Markdown

@sturlan sturlan commented Mar 27, 2026

Summary

Closes #11305, #9311, #4258.

Recipients (To, Cc, Bcc) are already returned by the API for every message
in a thread but were never displayed in ThreadEnvelope. This PR surfaces
them in the expanded message header using the existing RecipientBubble
component (which provides the NcPopover contact card with reply/copy/add
contact actions).

Also removes the aggregate participant bubble list from the thread header
(Thread.vue) per the design spec in #4258 — per-message recipients in
the expanded view replace that approach.

Prior attempt: #4315 (2021, closed 2023).

Changes

  • ThreadEnvelope.vue: render To/Cc/Bcc as RecipientBubble rows when
    message is expanded; show sender email only when expanded; apply
    --color-text-maxcontrast to sender name in expanded state
  • Thread.vue: remove aggregate participant bubble header; remove unused
    currentAccountEmail prop
  • MailboxThread.vue: remove unused :current-account-email binding

Test plan

  • Open a thread with multiple messages
  • Expand a message → To/Cc/Bcc rows appear with clickable bubbles
  • Collapse the message → recipient rows disappear
  • Click a recipient bubble → NcPopover opens (reply, copy email, add contact)
  • npm run test:unit — all 220 tests pass
  • npm run lint — no errors

AI-assisted: Claude Code (claude-sonnet-4-6)

sturlan added 4 commits March 27, 2026 13:22
Closes nextcloud#11305, nextcloud#9311, nextcloud#4258. Recipients (To, Cc, Bcc) are already
returned by the API for every message in a thread but were never
displayed in ThreadEnvelope. Add RecipientBubble components in the
expanded message header for each recipient list, following the same
pattern used for per-message subject-change display.

AI-assisted: Claude Code (claude-sonnet-4-6)
Signed-off-by: Darko Sturlan <darko.sturlan@gmail.com>
…handling

RecipientBubble uses NcUserBubble which renders as an anchor tag.
Placing it inside the router-link's click handler caused navigation on
click instead of opening the contact popover. Move the recipients
section outside the router-link into its own envelope__recipients div.

AI-assisted: Claude Code (claude-sonnet-4-6)
Signed-off-by: Darko Sturlan <darko.sturlan@gmail.com>
Per ChristophWurst's Sept 2023 design spec:
- Hide sender email address in collapsed message state
- Apply --color-text-maxcontrast to sender name when expanded
- Remove thread-level participant bubble header from Thread.vue
  along with all associated dead code (participantsToDisplay,
  moreParticipantsString, updateParticipantsToDisplay, resize
  listener, RecipientBubble/NcPopover imports)

AI-assisted: Claude Code (claude-sonnet-4-6)
Signed-off-by: Darko Sturlan <darko.sturlan@gmail.com>
- Fix import order in ThreadEnvelope.vue (alphabetical: ConfirmationModal,
  Error, EventModal, RecipientBubble)
- Fix MessageLoadingSkeleton indentation (1 tab → 2 tabs)
- Remove extra blank lines in ThreadEnvelope.vue and Thread.vue CSS
- Fix SCSS unmatched brace in Thread.vue (leftover from avatar-header removal)
- Remove unused currentAccountEmail prop from Thread.vue and its
  corresponding binding in MailboxThread.vue

All 220 unit tests pass; webpack builds cleanly.

Signed-off-by: Darko Sturlan <darko.sturlan@gmail.com>
@sturlan sturlan force-pushed the feat/11305-thread-per-message-recipients branch from 7330563 to 98f2f88 Compare March 27, 2026 12:22
Copy link
Copy Markdown
Member

@ChristophWurst ChristophWurst left a comment

Choose a reason for hiding this comment

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

Thank you for the contribution!

Code looks good so far. Please provide before/after screenshots

inset-inline-start: var(--default-grid-baseline);
}

.envelope__recipients {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

style: this could be broken up into a nested scss structure


.envelope__recipients {
padding-inline: 60px 38px;
padding-block: 4px;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: magic numbers. ideally we can leverage the grid spacing var for this. See #9944.

- Nest .recipients inside .envelope__recipients (nested SCSS)
- Replace magic numbers (60px, 38px, 4px) with CSS variable expressions:
  padding-inline-start aligns with sender name via border-radius-container
  + avatar width (10 * grid-baseline) + gap (2 * grid-baseline);
  padding-inline-end mirrors the container border-radius;
  gaps and padding-block use --default-grid-baseline

Signed-off-by: sturlan <darko.sturlan@gmail.com>
@ChristophWurst ChristophWurst self-assigned this Mar 27, 2026
@sturlan
Copy link
Copy Markdown
Author

sturlan commented Mar 27, 2026

Thank you for the contribution!

Code looks good so far. Please provide before/after screenshots

Thank you for the feedback. Here are the screenshots requested.
Before:
before
After:
after

@ChristophWurst
Copy link
Copy Markdown
Member

Thanks 😎

Then I'm summoning our designer @nimishavijay for a quick design review :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Display all recipients and basic information for each individual email in the email view.

2 participants