Disable URL previews per-message when the message provides a hint (#33775)
* Disable URL previews if the message requests it. * Use MSC4095 * Expose type * Document MSC * cleanup * cleanup
This commit is contained in:
@@ -1140,7 +1140,7 @@ export const SETTINGS: Settings = {
|
||||
"urlPreviewsEnabled": {
|
||||
// Enabled by default and client configurable as this setting only allows unencrypted
|
||||
// messages to be previewed.
|
||||
supportedLevels: [SettingLevel.DEVICE, SettingLevel.ACCOUNT, SettingLevel.CONFIG],
|
||||
supportedLevels: [SettingLevel.ROOM_DEVICE, SettingLevel.DEVICE, SettingLevel.ACCOUNT, SettingLevel.CONFIG],
|
||||
supportedLevelsAreOrdered: true,
|
||||
displayName: _td("settings|inline_url_previews_default"),
|
||||
default: true,
|
||||
|
||||
@@ -37,6 +37,8 @@ export const PREVIEW_WIDTH_PX = 478;
|
||||
export const PREVIEW_HEIGHT_PX = 200;
|
||||
export const MIN_PREVIEW_PX = 96;
|
||||
export const MIN_IMAGE_SIZE_BYTES = 8192;
|
||||
// From https://github.com/matrix-org/matrix-spec-proposals/pull/4095
|
||||
export const BUNDLED_LINK_PREVIEWS = "com.beeper.linkpreviews";
|
||||
|
||||
export enum PreviewVisibility {
|
||||
/**
|
||||
@@ -387,6 +389,18 @@ export class UrlPreviewGroupViewModel
|
||||
* for the previously-calculated links.
|
||||
*/
|
||||
private async computeSnapshot(): Promise<void> {
|
||||
// This uses MSC4095. If the sender has sent us an empty URL previews bundle
|
||||
// then they do not want to have URL previews be visible.
|
||||
const bundledLinkPreviews = this.props.mxEvent.getContent()[BUNDLED_LINK_PREVIEWS];
|
||||
if (Array.isArray(bundledLinkPreviews) && bundledLinkPreviews.length === 0) {
|
||||
return this.snapshot.merge({
|
||||
previews: [],
|
||||
totalPreviewCount: 0,
|
||||
previewsLimited: false,
|
||||
overPreviewLimit: false,
|
||||
});
|
||||
} // otherwise, we do not support bundled previews yet so will fallback to old behaviour.
|
||||
|
||||
const previews =
|
||||
this.visibility <= PreviewVisibility.UserHidden
|
||||
? []
|
||||
|
||||
@@ -9,7 +9,10 @@ import { expect } from "@jest/globals";
|
||||
|
||||
import type { MockedObject } from "jest-mock";
|
||||
import type { MatrixClient, IPreviewUrlResponse } from "matrix-js-sdk/src/matrix";
|
||||
import { UrlPreviewGroupViewModel } from "../../../src/viewmodels/message-body/UrlPreviewGroupViewModel";
|
||||
import {
|
||||
BUNDLED_LINK_PREVIEWS,
|
||||
UrlPreviewGroupViewModel,
|
||||
} from "../../../src/viewmodels/message-body/UrlPreviewGroupViewModel";
|
||||
import type { UrlPreview } from "@element-hq/web-shared-components";
|
||||
import { getMockClientWithEventEmitter, mkEvent } from "../../test-utils";
|
||||
|
||||
@@ -22,7 +25,9 @@ const BASIC_PREVIEW_OGDATA = {
|
||||
"og:site_name": "Example.org",
|
||||
};
|
||||
|
||||
function getViewModel({ mediaVisible, visible } = { mediaVisible: true, visible: true }): {
|
||||
function getViewModel(
|
||||
{ mediaVisible, visible, showPreview } = { mediaVisible: true, visible: true, showPreview: true },
|
||||
): {
|
||||
vm: UrlPreviewGroupViewModel;
|
||||
client: MockedObject<MatrixClient>;
|
||||
onImageClicked: jest.Mock<void, [UrlPreview]>;
|
||||
@@ -41,7 +46,9 @@ function getViewModel({ mediaVisible, visible } = { mediaVisible: true, visible:
|
||||
event: true,
|
||||
user: "@foo:bar",
|
||||
type: "m.room.message",
|
||||
content: {},
|
||||
content: {
|
||||
...(showPreview ? undefined : { [BUNDLED_LINK_PREVIEWS]: [] }),
|
||||
},
|
||||
id: "$id",
|
||||
}),
|
||||
});
|
||||
@@ -94,7 +101,7 @@ describe("UrlPreviewGroupViewModel", () => {
|
||||
]);
|
||||
});
|
||||
it("should hide preview when invisible", async () => {
|
||||
const { vm, client } = getViewModel({ visible: false, mediaVisible: true });
|
||||
const { vm, client } = getViewModel({ visible: false, mediaVisible: true, showPreview: true });
|
||||
const msg = document.createElement("div");
|
||||
msg.innerHTML = '<a href="https://example.org">Test</a>';
|
||||
await vm.updateEventElement(msg);
|
||||
@@ -152,7 +159,7 @@ describe("UrlPreviewGroupViewModel", () => {
|
||||
expect(vm.getSnapshot().previews[0].siteIcon).toBeTruthy();
|
||||
});
|
||||
it("should ignore media when mediaVisible is false", async () => {
|
||||
const { vm, client } = getViewModel({ mediaVisible: false, visible: true });
|
||||
const { vm, client } = getViewModel({ mediaVisible: false, visible: true, showPreview: true });
|
||||
client.getUrlPreview.mockResolvedValueOnce({
|
||||
"og:title": "This is an example!",
|
||||
"og:type": "document",
|
||||
@@ -225,6 +232,21 @@ describe("UrlPreviewGroupViewModel", () => {
|
||||
await vm.onShowClick();
|
||||
expect(vm.getSnapshot()).toMatchSnapshot();
|
||||
});
|
||||
it("should hide a preview if the message requests it", async () => {
|
||||
const { vm, client } = getViewModel({ showPreview: false, mediaVisible: true, visible: true });
|
||||
client.getUrlPreview.mockResolvedValueOnce(BASIC_PREVIEW_OGDATA);
|
||||
const msg = document.createElement("div");
|
||||
msg.innerHTML = '<a href="https://example.org">Test</a>';
|
||||
await vm.updateEventElement(msg);
|
||||
expect(vm.getSnapshot()).toMatchInlineSnapshot(`
|
||||
{
|
||||
"overPreviewLimit": false,
|
||||
"previews": [],
|
||||
"previewsLimited": false,
|
||||
"totalPreviewCount": 0,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
describe("calculates author", () => {
|
||||
it("should use the profile:username if provided", async () => {
|
||||
|
||||
Reference in New Issue
Block a user