Skip to content

fix: attachment collapsed state resets after switching channels#40359

Open
rafaelcunha02 wants to merge 2 commits intoRocketChat:developfrom
mariajvieira:fix/persist-attachment-collapsed-state
Open

fix: attachment collapsed state resets after switching channels#40359
rafaelcunha02 wants to merge 2 commits intoRocketChat:developfrom
mariajvieira:fix/persist-attachment-collapsed-state

Conversation

@rafaelcunha02
Copy link
Copy Markdown

@rafaelcunha02 rafaelcunha02 commented May 1, 2026

Proposed changes

Message attachments (images, GIFs, videos, audio, files) store their collapsed/expanded state only in React component state. When a user switches channels, the message list unmounts and all in-memory state is lost — so every manually collapsed attachment re-expands on return.

This fix replaces the in-memory toggle in useCollapse with useState backed by sessionStorage, keyed on the attachment ID. On mount the hook reads the stored value; every toggle writes it back. The user's collapse choice now survives channel switches for the duration of the browser session.

Files changed: useCollapse, MessageCollapsible, ImageAttachment, VideoAttachment, AudioAttachment, GenericFileAttachment, DefaultAttachment.

Issue(s)

Closes #40337

Steps to test or reproduce

  1. Post a message with an image or GIF in any channel.
  2. Click the collapse arrow on the attachment - it hides.
  3. Switch to another channel, then switch back.
  4. Before: attachment re-expands. After: attachment stays collapsed.

Further comments

sessionStorage was chosen over localStorage so the state does not persist across browser sessions or bleed between different users on the same machine.

Summary by CodeRabbit

  • New Features
    • Attachment collapse/expand state is now persisted across channel navigation, so previously collapsed images and media remain collapsed when returning.
    • Collapse state is tracked per attachment (by identifier) and stored in session storage, so each attachment maintains its own persisted state.

@rafaelcunha02 rafaelcunha02 requested a review from a team as a code owner May 1, 2026 10:14
@dionisio-bot
Copy link
Copy Markdown
Contributor

dionisio-bot Bot commented May 1, 2026

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

  • 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

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 1, 2026

🦋 Changeset detected

Latest commit: fc32cd2

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

This PR includes changesets to release 41 packages
Name Type
@rocket.chat/meteor Patch
@rocket.chat/core-typings Patch
@rocket.chat/rest-typings Patch
@rocket.chat/uikit-playground Patch
@rocket.chat/api-client Patch
@rocket.chat/apps Patch
@rocket.chat/core-services Patch
@rocket.chat/cron Patch
@rocket.chat/ddp-client Patch
@rocket.chat/fuselage-ui-kit Patch
@rocket.chat/gazzodown Patch
@rocket.chat/http-router Patch
@rocket.chat/livechat Patch
@rocket.chat/model-typings Patch
@rocket.chat/models Patch
@rocket.chat/ui-avatar Patch
@rocket.chat/ui-client Patch
@rocket.chat/ui-contexts Patch
@rocket.chat/ui-voip Patch
@rocket.chat/web-ui-registration Patch
@rocket.chat/account-service Patch
@rocket.chat/authorization-service Patch
@rocket.chat/ddp-streamer Patch
@rocket.chat/omnichannel-transcript Patch
@rocket.chat/presence-service Patch
@rocket.chat/queue-worker Patch
@rocket.chat/abac Patch
@rocket.chat/federation-matrix Patch
@rocket.chat/license Patch
@rocket.chat/media-calls Patch
@rocket.chat/omnichannel-services Patch
@rocket.chat/pdf-worker Patch
@rocket.chat/presence Patch
rocketchat-services Patch
@rocket.chat/network-broker Patch
@rocket.chat/omni-core-ee Patch
@rocket.chat/mock-providers Patch
@rocket.chat/instance-status Patch
@rocket.chat/omni-core Patch
@rocket.chat/server-fetch Patch
@rocket.chat/ui-video-conf 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

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 1, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7e149c8d-8396-4839-a7f7-76e4e1ff218f

📥 Commits

Reviewing files that changed from the base of the PR and between 86644b5 and fc32cd2.

📒 Files selected for processing (2)
  • apps/meteor/client/components/message/content/attachments/DefaultAttachment.tsx
  • apps/meteor/client/components/message/hooks/useCollapse.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/meteor/client/components/message/content/attachments/DefaultAttachment.tsx
  • apps/meteor/client/components/message/hooks/useCollapse.tsx
📜 Recent review details
⏰ 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). (1)
  • GitHub Check: cubic · AI code reviewer

Walkthrough

Adds session-level persistence for attachment collapse state using sessionStorage keyed per attachment; components and the collapse hook were updated to accept and use an optional storageKey so collapsed state survives channel navigation within the same browser session.

Changes

Cohort / File(s) Summary
Changesets
.changeset/fiery-cows-rhyme.md
Adds a changeset documenting the patch-level behavior change for @rocket.chat/meteor regarding attachment collapse persistence.
Core Hook
apps/meteor/client/components/message/hooks/useCollapse.tsx
useCollapse now accepts an optional storageKey?: string, initializes state from sessionStorage under rc_attachment_collapsed_<key>, and persists toggles to sessionStorage (replaces prior useToggle approach).
Collapse Component
apps/meteor/client/components/message/MessageCollapsible.tsx
MessageCollapsibleProps gains optional storageKey?: string; prop is forwarded into useCollapse to key persisted state.
Attachment Default Logic
apps/meteor/client/components/message/content/attachments/DefaultAttachment.tsx
Derives storageKey from attachment.id (falls back to undefined) and passes it to useCollapse so collapse state can be keyed per attachment id.
Attachment Variants
apps/meteor/client/components/message/content/attachments/file/AudioAttachment.tsx, apps/meteor/client/components/message/content/attachments/file/GenericFileAttachment.tsx, apps/meteor/client/components/message/content/attachments/file/ImageAttachment.tsx, apps/meteor/client/components/message/content/attachments/file/VideoAttachment.tsx
Each component now destructures id from props and forwards it as storageKey={id} to MessageCollapsible, enabling per-attachment session persistence of collapsed state.

Sequence Diagram

sequenceDiagram
    actor User
    participant ImageAttachment as ImageAttachment (Component)
    participant MessageCollapsible as MessageCollapsible (Component)
    participant useCollapse as useCollapse (Hook)
    participant sessionStorage as sessionStorage (Browser)

    User->>ImageAttachment: Mount with id
    ImageAttachment->>MessageCollapsible: Pass storageKey=id
    MessageCollapsible->>useCollapse: Call useCollapse(isCollapsed, storageKey)
    useCollapse->>sessionStorage: Read "rc_attachment_collapsed_<id>"
    sessionStorage-->>useCollapse: Return stored value or undefined
    useCollapse-->>MessageCollapsible: Return collapsed state + toggleFn
    MessageCollapsible-->>ImageAttachment: Render with collapsed state

    User->>ImageAttachment: Click collapse toggle
    ImageAttachment->>MessageCollapsible: Invoke toggleFn
    MessageCollapsible->>useCollapse: toggleCollapsed()
    useCollapse->>useCollapse: Update state
    useCollapse->>sessionStorage: Write "rc_attachment_collapsed_<id>" = true/false
    useCollapse-->>MessageCollapsible: Updated collapsed state
    MessageCollapsible-->>ImageAttachment: Re-render

    User->>User: Navigate away and back
    ImageAttachment->>useCollapse: Re-mount with same storageKey
    useCollapse->>sessionStorage: Read "rc_attachment_collapsed_<id>"
    sessionStorage-->>useCollapse: Return persisted value
    useCollapse-->>ImageAttachment: Render with persisted collapsed state
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

type: bug

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: fixing attachment collapsed state persistence across channel navigation, which is the primary objective of the changeset.
Linked Issues check ✅ Passed The PR implements sessionStorage-based persistence of attachment collapse state keyed by attachment ID, directly addressing issue #40337's requirement to persist the collapsed state across channel switches for the session duration.
Out of Scope Changes check ✅ Passed All changes are scoped to implementing sessionStorage-based attachment collapse state persistence: modifications to useCollapse hook, MessageCollapsible component, and attachment components to pass storage keys. No unrelated changes detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

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

Copy link
Copy Markdown
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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@apps/meteor/client/components/message/content/attachments/DefaultAttachment.tsx`:
- Around line 30-31: The current storageKey uses attachment.title_link which can
collide across messages; change how storageKey is derived in DefaultAttachment
by only using a stable unique id (attachment.id) or, if you need persistence for
attachments without an id, build a composite key that includes the message
identity (e.g., combine message.id and attachment.id) so the key is unique per
attachment-instance; update the storageKey assignment used by useCollapse
(storageKey, useCollapse, collapsed, collapse) to stop falling back to
attachment.title_link and ensure keys are undefined when no stable identifier
exists.

In `@apps/meteor/client/components/message/hooks/useCollapse.tsx`:
- Around line 13-16: Guard all sessionStorage reads/writes in the useCollapse
hook by wrapping calls to sessionStorage.getItem and sessionStorage.setItem
(where SESSION_STORAGE_PREFIX and storageKey are used) in try-catch blocks; on
read (e.g., the block that returns stored === 'true') catch and fall back to the
existing collapseByDefault value, and on write (where attachmentCollapsed/state
updates persist) catch and no-op so the in-memory state is preserved; update the
useCollapse hook and any helper functions that reference
SESSION_STORAGE_PREFIX/storageKey to use these safe reads/writes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6cce4a73-3c4b-4b0a-9afd-8d1c41c12d24

📥 Commits

Reviewing files that changed from the base of the PR and between d33009a and 86644b5.

📒 Files selected for processing (8)
  • .changeset/fiery-cows-rhyme.md
  • apps/meteor/client/components/message/MessageCollapsible.tsx
  • apps/meteor/client/components/message/content/attachments/DefaultAttachment.tsx
  • apps/meteor/client/components/message/content/attachments/file/AudioAttachment.tsx
  • apps/meteor/client/components/message/content/attachments/file/GenericFileAttachment.tsx
  • apps/meteor/client/components/message/content/attachments/file/ImageAttachment.tsx
  • apps/meteor/client/components/message/content/attachments/file/VideoAttachment.tsx
  • apps/meteor/client/components/message/hooks/useCollapse.tsx
📜 Review details
⏰ 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). (1)
  • GitHub Check: cubic · AI code reviewer
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

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

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/client/components/message/content/attachments/file/ImageAttachment.tsx
  • apps/meteor/client/components/message/content/attachments/file/GenericFileAttachment.tsx
  • apps/meteor/client/components/message/content/attachments/DefaultAttachment.tsx
  • apps/meteor/client/components/message/content/attachments/file/AudioAttachment.tsx
  • apps/meteor/client/components/message/MessageCollapsible.tsx
  • apps/meteor/client/components/message/content/attachments/file/VideoAttachment.tsx
  • apps/meteor/client/components/message/hooks/useCollapse.tsx
🧠 Learnings (9)
📓 Common learnings
Learnt from: rodrigok
Repo: RocketChat/Rocket.Chat PR: 38623
File: apps/meteor/app/lib/server/functions/cleanRoomHistory.ts:146-149
Timestamp: 2026-04-18T12:32:53.425Z
Learning: In `apps/meteor/app/lib/server/functions/cleanRoomHistory.ts` (PR `#38623`), the read-receipt cleanup (both `ReadReceipts.removeByMessageIds` and `ReadReceiptsArchive.removeByMessageIds`) is intentionally only performed in the limited prune path (`limit && selectedMessageIds`). The unlimited/delete-all path (`limit === 0`) deliberately skips cleaning up orphaned read receipts in both hot and cold storage — this is by design. Do not flag this as a bug or missing cleanup in future reviews.
Learnt from: smirk-dev
Repo: RocketChat/Rocket.Chat PR: 39625
File: apps/meteor/app/api/server/v1/push.ts:85-97
Timestamp: 2026-03-14T14:58:58.834Z
Learning: In RocketChat/Rocket.Chat, the `push.token` POST/DELETE endpoints in `apps/meteor/app/api/server/v1/push.ts` were already migrated to the chained router API pattern on `develop` prior to PR `#39625`. `cleanTokenResult` (which strips `authToken` and returns `PushTokenResult`) and `isPushTokenPOSTProps`/`isPushTokenDELETEProps` validators already exist on `develop`. PR `#39625` only migrates `push.get` and `push.info` to the chained pattern. Do not flag `cleanTokenResult` or `PushTokenResult` as newly introduced behavior-breaking changes when reviewing this PR.
📚 Learning: 2026-04-17T23:32:07.223Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 38357
File: apps/meteor/app/apps/server/converters/messages.ts:348-352
Timestamp: 2026-04-17T23:32:07.223Z
Learning: In `apps/meteor/app/apps/server/converters/messages.ts`, the `timestamp` handler inside `_convertAttachmentsToApp` uses a non-null assertion (`attachment.ts!`) intentionally. The `ts` property on `MessageAttachment` is optional only to accommodate MessageAttachment creation-time scenarios; by the time `_convertAttachmentsToApp` is called, the message has already been stored and the attachment is guaranteed to have a `ts` value. Do not flag this non-null assertion as unsafe during code review.

Applied to files:

  • apps/meteor/client/components/message/content/attachments/file/ImageAttachment.tsx
  • apps/meteor/client/components/message/content/attachments/file/GenericFileAttachment.tsx
  • apps/meteor/client/components/message/content/attachments/DefaultAttachment.tsx
  • apps/meteor/client/components/message/content/attachments/file/AudioAttachment.tsx
  • apps/meteor/client/components/message/content/attachments/file/VideoAttachment.tsx
📚 Learning: 2026-04-10T22:42:05.539Z
Learnt from: dougfabris
Repo: RocketChat/Rocket.Chat PR: 40075
File: apps/meteor/client/views/room/modals/FileUploadModal/FileUploadModal.tsx:69-71
Timestamp: 2026-04-10T22:42:05.539Z
Learning: In `apps/meteor/client/views/room/modals/FileUploadModal/FileUploadModal.tsx`, the submit handler converts an empty/whitespace-only description to `undefined` (`description?.trim() || undefined`) intentionally. All downstream image-rendering components (`AttachmentImage`, `ImagePreview`, `ImageItem`, `ImageGallery`) default `undefined` alt to `''`, so the `<img alt="">` attribute is always present. Do not flag this `undefined` conversion as a bug preventing alt text from being cleared.

Applied to files:

  • apps/meteor/client/components/message/content/attachments/file/ImageAttachment.tsx
  • apps/meteor/client/components/message/content/attachments/file/GenericFileAttachment.tsx
  • apps/meteor/client/components/message/content/attachments/DefaultAttachment.tsx
  • apps/meteor/client/components/message/content/attachments/file/AudioAttachment.tsx
  • apps/meteor/client/components/message/content/attachments/file/VideoAttachment.tsx
📚 Learning: 2026-03-11T18:15:53.272Z
Learnt from: dougfabris
Repo: RocketChat/Rocket.Chat PR: 39425
File: apps/meteor/app/api/server/v1/rooms.ts:294-296
Timestamp: 2026-03-11T18:15:53.272Z
Learning: In Rocket.Chat's `rooms.mediaConfirm/:rid/:fileId` endpoint (apps/meteor/app/api/server/v1/rooms.ts), updating `file.name` from `bodyParams.fileName` without updating `file.path` is intentionally safe. The file path is keyed by `_id` (not by filename), so the stored path remains valid regardless of a rename. `file.name` only affects the display name in the message attachment; do not flag this as a path-divergence issue.

Applied to files:

  • apps/meteor/client/components/message/content/attachments/file/ImageAttachment.tsx
  • apps/meteor/client/components/message/content/attachments/file/GenericFileAttachment.tsx
  • .changeset/fiery-cows-rhyme.md
  • apps/meteor/client/components/message/content/attachments/file/VideoAttachment.tsx
📚 Learning: 2026-03-11T18:17:53.972Z
Learnt from: dougfabris
Repo: RocketChat/Rocket.Chat PR: 39425
File: apps/meteor/client/lib/chats/flows/processMessageUploads.ts:112-119
Timestamp: 2026-03-11T18:17:53.972Z
Learning: In `apps/meteor/client/lib/chats/flows/processMessageUploads.ts`, when sending multiple file uploads, each file is confirmed via its own `/rooms.mediaConfirm/${rid}/${fileId}` call and produces a separate message. Only the first file's confirm payload carries the composed message text (`msg`); all subsequent files receive `msg: ''`. This one-message-per-file behavior is intentional by design — do not flag it as a bug or suggest batching into a single message.

Applied to files:

  • apps/meteor/client/components/message/content/attachments/file/ImageAttachment.tsx
📚 Learning: 2026-03-27T14:52:56.865Z
Learnt from: dougfabris
Repo: RocketChat/Rocket.Chat PR: 39892
File: apps/meteor/client/views/room/contextualBar/Threads/Thread.tsx:150-155
Timestamp: 2026-03-27T14:52:56.865Z
Learning: In Rocket.Chat, there are two different `ModalBackdrop` components with different prop APIs. During review, confirm the import source: (1) `rocket.chat/fuselage` `ModalBackdrop` uses `ModalBackdropProps` based on `BoxProps` (so it supports `onClick` and other Box/DOM props) and does not have an `onDismiss` prop; (2) `rocket.chat/ui-client` `ModalBackdrop` uses a narrower props interface like `{ children?: ReactNode; onDismiss?: () => void }` and handles Escape keypress and outside mouse-up, and it does not forward arbitrary DOM props such as `onClick`. Flag mismatched props (e.g., `onDismiss` passed to the fuselage component or `onClick` passed to the ui-client component) and ensure the usage matches the correct component being imported.

Applied to files:

  • apps/meteor/client/components/message/content/attachments/file/ImageAttachment.tsx
  • apps/meteor/client/components/message/content/attachments/file/GenericFileAttachment.tsx
  • apps/meteor/client/components/message/content/attachments/DefaultAttachment.tsx
  • apps/meteor/client/components/message/content/attachments/file/AudioAttachment.tsx
  • apps/meteor/client/components/message/MessageCollapsible.tsx
  • apps/meteor/client/components/message/content/attachments/file/VideoAttachment.tsx
  • apps/meteor/client/components/message/hooks/useCollapse.tsx
📚 Learning: 2026-02-24T19:05:56.710Z
Learnt from: ahmed-n-abdeltwab
Repo: RocketChat/Rocket.Chat PR: 0
File: :0-0
Timestamp: 2026-02-24T19:05:56.710Z
Learning: Rocket.Chat repo context: When a workspace manifest on develop already pins a dependency version (e.g., packages/web-ui-registration → "rocket.chat/ui-contexts": "27.0.1"), a lockfile change in a feature PR that upgrades only that dependency’s resolution is considered a manifest-driven sync and can be kept, preferably as a small "chore: sync yarn.lock with manifests" commit.

Applied to files:

  • .changeset/fiery-cows-rhyme.md
📚 Learning: 2026-02-24T19:09:09.561Z
Learnt from: ahmed-n-abdeltwab
Repo: RocketChat/Rocket.Chat PR: 38974
File: apps/meteor/app/api/server/v1/im.ts:220-221
Timestamp: 2026-02-24T19:09:09.561Z
Learning: In RocketChat/Rocket.Chat OpenAPI migration PRs for apps/meteor/app/api/server/v1 endpoints, maintainers prefer to avoid any logic changes; style-only cleanups (like removing inline comments) may be deferred to follow-ups to keep scope tight.

Applied to files:

  • .changeset/fiery-cows-rhyme.md
📚 Learning: 2026-03-16T21:50:37.589Z
Learnt from: amitb0ra
Repo: RocketChat/Rocket.Chat PR: 39676
File: .changeset/migrate-users-register-openapi.md:3-3
Timestamp: 2026-03-16T21:50:37.589Z
Learning: For changes related to OpenAPI migrations in Rocket.Chat/OpenAPI, when removing endpoint types and validators from rocket.chat/rest-typings (e.g., UserRegisterParamsPOST, /v1/users.register) document this as a minor changeset (not breaking) per RocketChat/Rocket.Chat-Open-API#150 Rule 7. Note that the endpoint type is re-exposed via a module augmentation .d.ts in the consuming package (e.g., packages/web-ui-registration/src/users-register.d.ts). In reviews, ensure the changeset clearly states: this is a non-breaking change, the major version should not be bumped, and the changeset reflects a minor version bump. Do not treat this as a breaking change during OpenAPI migrations.

Applied to files:

  • .changeset/fiery-cows-rhyme.md
🔇 Additional comments (6)
.changeset/fiery-cows-rhyme.md (1)

1-5: Changeset entry is aligned with the implementation scope.

Patch bump and release note text are consistent with the PR behavior.

apps/meteor/client/components/message/content/attachments/file/ImageAttachment.tsx (1)

28-28: storageKey wiring looks correct here.

Passing id through MessageCollapsible is consistent with the intended persisted-collapse behavior.

apps/meteor/client/components/message/content/attachments/file/GenericFileAttachment.tsx (1)

24-24: Looks good.

id extraction and storageKey forwarding are consistent and localized.

Also applies to: 72-72

apps/meteor/client/components/message/content/attachments/file/VideoAttachment.tsx (1)

11-11: storageKey integration is correct in VideoAttachment.

No concerns with this wiring change.

Also applies to: 26-26

apps/meteor/client/components/message/content/attachments/file/AudioAttachment.tsx (1)

10-10: LGTM for this segment.

The added id/storageKey flow is consistent with the shared collapsible-state strategy.

Also applies to: 25-25

apps/meteor/client/components/message/MessageCollapsible.tsx (1)

15-15: MessageCollapsible prop plumbing is clean and backward-compatible.

Optional storageKey forwarding to useCollapse looks correct.

Also applies to: 18-19

Comment thread apps/meteor/client/components/message/content/attachments/DefaultAttachment.tsx Outdated
Comment thread apps/meteor/client/components/message/hooks/useCollapse.tsx Outdated
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 8 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/meteor/client/components/message/hooks/useCollapse.tsx">

<violation number="1" location="apps/meteor/client/components/message/hooks/useCollapse.tsx:14">
P2: Direct `sessionStorage` access is unguarded, so attachment collapsing can crash in browsers that block Web Storage or throw on access.</violation>
</file>

<file name="apps/meteor/client/components/message/content/attachments/DefaultAttachment.tsx">

<violation number="1" location="apps/meteor/client/components/message/content/attachments/DefaultAttachment.tsx:30">
P2: Using `attachment.title_link` as a storage key fallback can cause collapse state to bleed between unrelated attachments that happen to share the same URL. Only use `attachment.id` (which is unique per attachment) as the key; fall back to `undefined` (no persistence) when `id` is absent.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread apps/meteor/client/components/message/hooks/useCollapse.tsx Outdated
Comment thread apps/meteor/client/components/message/content/attachments/DefaultAttachment.tsx Outdated
@coderabbitai coderabbitai Bot removed the type: bug label May 1, 2026
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.

Attachment collapse state is not persisted when switching channels

1 participant