Skip to content

Conversation

@kushkumarkashyap7280
Copy link

@kushkumarkashyap7280 kushkumarkashyap7280 commented Jan 27, 2026

Proposed changes (including videos or screenshots)

This PR implements the requested feature to enable or disable Link Previews (OEmbed) on a per-channel basis. Previously, this setting was only available globally via the Administration settings.

Summary of Changes:

  1. Database/Typings: Added optional linksEmbed boolean property to the IRoom interface in packages/core-typings.
  2. UI: Added a "Enable Link Previews" toggle switch to the Edit Room contextual bar (EditRoomInfo.tsx).
  3. API/Security: Updated saveRoomSettings server method to whitelist and validate the linksEmbed field so it can be saved to the database.
  4. Backend Logic: Modified the rocketUrlParser (OEmbed service) to check the room's linksEmbed setting. If set to false, it skips fetching metadata for that specific message.

Proof of Fix:
toggle button added in fronted
screenshot
image

video

Screencast.From.2026-01-27.14-39-19.mp4

Issue(s)

Closes #7734

Steps to test or reproduce

  1. Go to any channel (e.g., #general).
  2. Open Room Information (click the 'i' icon) -> Click Edit.
  3. Scroll down to the "Enable Link Previews" toggle.
  4. Test 1 (Disable): Turn the toggle OFF and click Save.
  5. Post a link (e.g., https://google.com) in the chat.
    • Expected Result: The link appears as plain text. No preview card is generated.
  6. Test 2 (Enable): Go back to Edit, turn the toggle ON, and click Save.
  7. Post a link (e.g., https://github.com) in the chat.
    • Expected Result: The preview card (OEmbed) is generated and displayed.

Further comments

This implementation defaults to true (enabled) if the setting is undefined in the database, ensuring backward compatibility with existing rooms. It strictly respects the Global Setting first (if Global is OFF, this switch does nothing).

Summary by CodeRabbit

  • New Features

    • Per-channel link preview control: a toggle in Advanced Channel Settings to enable/disable link previews for each channel.
    • Channel-level setting overrides the global link-preview preference when messages are processed; previews are suppressed if disabled.
    • Toggle is disabled for federated rooms; initial state reflects the channel’s current setting or the global default.
  • Localization

    • Added label for the new setting: "Enable Link Previews".

✏️ Tip: You can customize this high-level summary in your review settings.

@kushkumarkashyap7280 kushkumarkashyap7280 requested review from a team as code owners January 27, 2026 09:17
@dionisio-bot
Copy link
Contributor

dionisio-bot bot commented Jan 27, 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

changeset-bot bot commented Jan 27, 2026

🦋 Changeset detected

Latest commit: db2d8e9

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

This PR includes changesets to release 40 packages
Name Type
@rocket.chat/core-typings Patch
@rocket.chat/meteor 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/rest-typings 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/models Patch
@rocket.chat/ui-video-conf Patch
@rocket.chat/instance-status Patch
@rocket.chat/omni-core 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

@CLAassistant
Copy link

CLAassistant commented Jan 27, 2026

CLA assistant check
All committers have signed the CLA.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 27, 2026

Walkthrough

Adds a per-room "Enable Link Previews" setting: new room field, UI toggle in EditRoomInfo, persistence in room settings saver, and a check in the OEmbed post-save hook to skip previews when the room disables them.

Changes

Cohort / File(s) Summary
Type Definitions
packages/core-typings/src/IRoom.ts
Added optional linksEmbed?: boolean to IRoom and IRoomWithRetentionPolicy.
Room Settings Backend
apps/meteor/app/channel-settings/server/methods/saveRoomSettings.ts
Added linksEmbed to RoomSettings, extended saver signature, and implemented saver to update Rooms.updateOne({ _id: rid }, { $set: { linksEmbed: value } }).
Frontend UI & Form
apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx, apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/useEditRoomInitialValues.ts
Added "Enable Link Previews" toggle (disabled for federated rooms) and initialized linksEmbed from room.linksEmbed (defaults to true unless explicitly false).
Message Processing Hook
apps/meteor/server/services/messages/hooks/AfterSaveOEmbed.ts
After global checks, fetches room by message.rid and returns early (skips embedding) if room.linksEmbed === false.
Changeset & i18n
.changeset/cold-vans-suffer.md, packages/i18n/src/locales/en.i18n.json
Added changeset describing the feature and i18n key Enable_Link_Previews.

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant UI as EditRoomInfo UI
    participant Server as Settings API
    participant DB as Rooms DB
    participant Hook as AfterSaveOEmbed Hook

    User->>UI: Toggle "Enable Link Previews"
    UI->>Server: Save settings (linksEmbed)
    Server->>DB: updateOne Rooms { _id:rid } $set linksEmbed
    DB-->>Server: update OK
    Server-->>UI: saved

    User->>UI: Send message containing URL
    UI->>Hook: message saved event
    Hook->>DB: fetch Room by message.rid
    DB-->>Hook: return room (linksEmbed)
    alt linksEmbed is false
        Hook-->>Hook: skip embedding, leave message without preview
    else linksEmbed true/undefined
        Hook->>Hook: process embedding, attach preview
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

stat: ready to merge, stat: QA assured

Suggested reviewers

  • KevLehman
  • ggazzo
  • rodrigok

Poem

🐰 I nudged a toggle, small and bright,
A twitch, a hop — previews dim or light,
Channels hush where links once peeped,
RSS corners now gently keep,
Hooray for calm rooms tonight. ✨

🚥 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: adding a per-channel link preview setting feature to channel settings.
Linked Issues check ✅ Passed The PR fully implements the feature requested in issue #7734: per-channel link preview control with UI toggle, backend persistence, and enforcement logic.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the per-channel link preview setting feature; no unrelated or out-of-scope modifications 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.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

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

Copy link
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.

No issues found across 5 files

Copy link
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: 1

🤖 Fix all issues with AI agents
In
`@apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx`:
- Around line 495-513: Replace the hardcoded label text and remove the inline
JSX comments: change FieldLabel htmlFor={linksEmbedField} content from "Enable
Link Previews" to use the i18n helper t('Enable_Link_Previews') (or the
appropriate key used in the codebase) so the string goes through translation,
and delete the surrounding {/* START OF NEW LINK PREVIEW TOGGLE */} and {/* END
OF NEW LINK PREVIEW TOGGLE */} comment nodes; leave the Controller
(name='linksEmbed') and ToggleSwitch usage (id={linksEmbedField},
checked={value}, disabled={isFederated}) unchanged.
🧹 Nitpick comments (1)
apps/meteor/server/services/messages/hooks/AfterSaveOEmbed.ts (1)

11-11: Avoid a room lookup when the message has no URLs.
This reduces DB traffic in the hot path and keeps the hook cheap; also remove the new inline comments per guidelines.

♻️ Suggested refactor
-	// 1. Keep the Global Check
 	if (!settings.get('API_Embed')) {
 		return message;
 	}
 
-	// 2. NEW: Check the Per-Channel Setting
-	// We fetch the room to see if the user disabled previews for this specific channel.
-	const room = await Rooms.findOneById(message.rid, { projection: { linksEmbed: 1 } });
-	if (room?.linksEmbed === false) {
-		return message; // STOP here if the room says "No Previews"
-	}
-
-	// 3. Keep the rest of the existing checks...
 	if (!Array.isArray(message.urls)) {
 		return message;
 	}
+
+	const room = await Rooms.findOneById(message.rid, { projection: { linksEmbed: 1 } });
+	if (room?.linksEmbed === false) {
+		return message;
+	}

Also applies to: 334-347

Copy link
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: 1

🤖 Fix all issues with AI agents
In
`@apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx`:
- Around line 496-512: The linksEmbed toggle (Controller for name='linksEmbed',
id linksEmbedField, rendering ToggleSwitch) needs a FieldHint added to match
other toggles and should be rendered conditionally using the same
permission-guard pattern as the other fields; wrap the existing <Field> block in
the same permission check used for the other toggles (e.g., the canView... guard
pattern) and add a <FieldHint> with the appropriate translation key (e.g.,
t('Links_Previews_Hint') or similar) to explain linksEmbed behavior so it
matches the UI/permission consistency of readOnly/archived/reactWhenReadOnly.
🧹 Nitpick comments (2)
apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx (1)

231-233: Minor: Remove extra blank lines for consistency.

The other useId() declarations are consecutive without blank lines between them.

🔧 Suggested cleanup
 	const retentionIgnoreThreads = useId();
-     
-	
 	const linksEmbedField = useId();
apps/meteor/server/services/messages/hooks/AfterSaveOEmbed.ts (1)

335-351: Remove inline comments per coding guidelines.

The added comments violate the coding guideline: "Avoid code comments in the implementation" for TypeScript files. The code is self-explanatory and doesn't require these comments.

♻️ Suggested refactor
 const rocketUrlParser = async function (message: IMessage): Promise<IMessage> {
 	log.debug({ msg: 'Parsing message URLs' });

-	// 1. Global Check stays at the top
 	if (!settings.get('API_Embed')) {
 		return message;
 	}

-	// 2. CHECK URLs FIRST (Optimization)
-	// If the message has no URLs, we stop here. We don't bother the database.
 	if (!Array.isArray(message.urls)) {
 		return message;
 	}

-	// 3. NOW check the Room Setting
-	// We only fetch the room data if we know we actually need to process URLs.
 	const room = await Rooms.findOneById(message.rid, { projection: { linksEmbed: 1 } });
 	if (room?.linksEmbed === false) {
 		return message;
 	}

As per coding guidelines, avoid code comments in TypeScript implementations.

Comment on lines 496 to 512
<Field>
<FieldRow>
<FieldLabel htmlFor={linksEmbedField}>{t('Enable_Link_Previews')}</FieldLabel>
<Controller
control={control}
name='linksEmbed'
render={({ field: { value, ...field } }) => (
<ToggleSwitch
id={linksEmbedField}
{...field}
checked={value}
disabled={isFederated}
/>
)}
/>
</FieldRow>
</Field>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, let's check the file structure and find the relevant context
cat -n apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx | sed -n '480,530p'

Repository: RocketChat/Rocket.Chat

Length of output: 2007


🏁 Script executed:

# Check for permission checks on other toggles in the same file
rg -n 'canView|Permission' apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx -B2 -A2

Repository: RocketChat/Rocket.Chat

Length of output: 2560


🏁 Script executed:

# Search for linksEmbed references to understand permission handling
rg -n 'linksEmbed' apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/ -r . --type ts -C3

Repository: RocketChat/Rocket.Chat

Length of output: 4133


🏁 Script executed:

# Check the useEditRoomPermissions hook or similar to understand the permission pattern
rg -n 'useEditRoomPermissions\|const.*Permission.*=' apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx -A3

Repository: RocketChat/Rocket.Chat

Length of output: 48


🏁 Script executed:

# Find and read the useEditRoomPermissions file
fd -n 'useEditRoomPermissions.ts' apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/

Repository: RocketChat/Rocket.Chat

Length of output: 296


🏁 Script executed:

# Read the useEditRoomPermissions file to see all available permissions
cat -n apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/useEditRoomPermissions.ts

Repository: RocketChat/Rocket.Chat

Length of output: 3580


🏁 Script executed:

# Check if LINKS_EMBED or similar setting exists in RoomSettingsEnum
rg -n 'LINKS_EMBED|RoomSettingsEnum' apps/meteor --type ts | grep -i 'links\|embed'

Repository: RocketChat/Rocket.Chat

Length of output: 48


🏁 Script executed:

# Search for RoomSettingsEnum definition to see all available settings
fd 'RoomSettingsEnum' --type ts

Repository: RocketChat/Rocket.Chat

Length of output: 235


🏁 Script executed:

# Search for RoomSettingsEnum definition
find . -name '*RoomSettingsEnum*' -type f

Repository: RocketChat/Rocket.Chat

Length of output: 48


🏁 Script executed:

# Search for LINKS_EMBED in definition directory
rg 'LINKS_EMBED|linksEmbed' definition/ --max-count 20

Repository: RocketChat/Rocket.Chat

Length of output: 117


🏁 Script executed:

# Search for IRoomTypeConfig file mentioned in imports
find . -name 'IRoomTypeConfig*' -type f

Repository: RocketChat/Rocket.Chat

Length of output: 109


🏁 Script executed:

# Read the IRoomTypeConfig.ts file to find RoomSettingsEnum
cat -n ./apps/meteor/definition/IRoomTypeConfig.ts

Repository: RocketChat/Rocket.Chat

Length of output: 4798


🏁 Script executed:

# Also check if linksEmbed is mentioned in any permission or settings context
rg 'linksEmbed' apps/meteor --max-count 30

Repository: RocketChat/Rocket.Chat

Length of output: 1480


🏁 Script executed:

# Search for global "Embed Link Previews" or similar admin setting
rg 'Embed.*Link|linksEmbed.*admin|Link.*Previews.*setting' apps/meteor --max-count 20

Repository: RocketChat/Rocket.Chat

Length of output: 774


🏁 Script executed:

# Check the PR or recent commits mentioning linksEmbed to understand PR objectives
git log --oneline --all --grep='linksEmbed\|link.*preview' | head -20

Repository: RocketChat/Rocket.Chat

Length of output: 711


🏁 Script executed:

# Look for FieldHint usage patterns in the same file
rg -A3 '<FieldHint' apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx

Repository: RocketChat/Rocket.Chat

Length of output: 1148


Add a FieldHint to explain the linksEmbed behavior and consider adding a permission check for consistency.

The linksEmbed toggle lacks a FieldHint, while all other toggles in this section (readOnly, archived, reactWhenReadOnly) have explanatory hints. Additionally, linksEmbed is rendered unconditionally, unlike the other toggles which all check permission guards (canViewReadOnly, canViewArchived, canViewJoinCode, canViewHideSysMes). Consider whether this field should follow the same permission pattern established by the rest of the section.

🔧 Suggested improvement with hint
 <Field>
 	<FieldRow>
 		<FieldLabel htmlFor={linksEmbedField}>{t('Enable_Link_Previews')}</FieldLabel>
 		<Controller
 			control={control}
 			name='linksEmbed'
 			render={({ field: { value, ...field } }) => (
 				<ToggleSwitch
 					id={linksEmbedField}
 					{...field}
 					checked={value}
 					disabled={isFederated}
+					aria-describedby={`${linksEmbedField}-hint`}
 				/>
 			)}
 		/>
 	</FieldRow>
+	<FieldHint id={`${linksEmbedField}-hint`}>
+		{t('Enable_Link_Previews_Description')}
+	</FieldHint>
 </Field>
🤖 Prompt for AI Agents
In
`@apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx`
around lines 496 - 512, The linksEmbed toggle (Controller for name='linksEmbed',
id linksEmbedField, rendering ToggleSwitch) needs a FieldHint added to match
other toggles and should be rendered conditionally using the same
permission-guard pattern as the other fields; wrap the existing <Field> block in
the same permission check used for the other toggles (e.g., the canView... guard
pattern) and add a <FieldHint> with the appropriate translation key (e.g.,
t('Links_Previews_Hint') or similar) to explain linksEmbed behavior so it
matches the UI/permission consistency of readOnly/archived/reactWhenReadOnly.

@dougfabris dougfabris changed the title feat(channel-settings): add per-channel link preview setting (#7734) feat(channel-settings): add per-channel link preview setting Jan 27, 2026
@dougfabris dougfabris added area: ui Touches the code on client side area: backend Touches the code on backend side type: feature Pull requests that introduces new feature labels Jan 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: backend Touches the code on backend side area: ui Touches the code on client side type: feature Pull requests that introduces new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Embed Link Previews by channel

3 participants