make some tests go happy

This commit is contained in:
Half-Shot
2025-04-08 11:59:11 +01:00
parent 35503035e2
commit 2b6151f678
17 changed files with 505 additions and 348 deletions

View File

@@ -14,7 +14,7 @@ import type { EncryptedFile } from "matrix-js-sdk/src/types";
import type { EmptyObject } from "matrix-js-sdk/src/matrix";
import type { DeviceClientInformation } from "../utils/device/types.ts";
import type { UserWidget } from "../utils/WidgetUtils-types.ts";
import { MediaPreviewConfig } from "./media_preview.ts";
import { type MediaPreviewConfig } from "./media_preview.ts";
// Extend Matrix JS SDK types via Typescript declaration merging to support unspecced event fields and types

View File

@@ -1,3 +1,10 @@
/*
Copyright 2025 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
export enum MediaPreviewValue {
On = "on",
Private = "private",

View File

@@ -52,7 +52,7 @@ export const transformTags: NonNullable<IOptions["transformTags"]> = {
// images" preference is disabled. Future work might expose some UI to reveal them
// like standalone image events have.
// TODO: Is this a private room?
if (!src || SettingsStore.getValue("mediaPreviewConfig").media_previews !== MediaPreviewValue.On ) {
if (!src || SettingsStore.getValue("mediaPreviewConfig").media_previews !== MediaPreviewValue.On) {
return { tagName, attribs: {} };
}

View File

@@ -1,8 +1,15 @@
import React, { ChangeEventHandler } from "react";
/*
Copyright 2025 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import React, { type ChangeEventHandler, useCallback } from "react";
import { Field, HelpMessage, InlineField, Label, RadioInput, Root } from "@vector-im/compound-web";
import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
import { useCallback } from "react";
import { MediaPreviewConfig, MediaPreviewValue } from "../../../../../@types/media_preview";
import { type MediaPreviewConfig, MediaPreviewValue } from "../../../../../@types/media_preview";
import { _t } from "../../../../../languageHandler";
import { useSettingValue } from "../../../../../hooks/useSettings";
import SettingsStore from "../../../../../settings/SettingsStore";
@@ -15,7 +22,7 @@ export function MediaPreviewAccountSettings() {
(c: boolean) => {
const newValue = {
...currentMediaPreview,
// N.B. Switch is inverted. "Hide avatars..."
// Switch is inverted. "Hide avatars..."
invite_avatars: c ? MediaPreviewValue.Off : MediaPreviewValue.On,
} satisfies MediaPreviewConfig;
SettingsStore.setValue("mediaPreviewConfig", null, SettingLevel.ACCOUNT, newValue);

View File

@@ -6,12 +6,12 @@ Please see LICENSE files in the repository root for full details.
*/
import { useCallback, useMemo } from "react";
import { JoinRule } from "matrix-js-sdk/src/matrix";
import { SettingLevel } from "../settings/SettingLevel";
import { useSettingValue } from "./useSettings";
import SettingsStore from "../settings/SettingsStore";
import { useMatrixClientContext } from "../contexts/MatrixClientContext";
import { JoinRule } from "matrix-js-sdk/src/matrix";
import { MediaPreviewValue } from "../@types/media_preview";
const PRIVATE_JOIN_RULES: JoinRule[] = [JoinRule.Invite, JoinRule.Knock, JoinRule.Restricted];
@@ -36,18 +36,19 @@ export function useMediaVisible(eventId: string, roomId: string): [boolean, (vis
);
const roomIsPrivate = useMemo(() => {
const joinRule = client.getRoom(roomId)?.getJoinRule();
const joinRule = client?.getRoom(roomId)?.getJoinRule();
if (PRIVATE_JOIN_RULES.includes(joinRule as JoinRule)) {
return true;
} else { // All other join rules, and unknown will default to hiding.
} else {
// All other join rules, and unknown will default to hiding.
return false;
}
}, [client, roomId])
}, [client, roomId]);
const explicitEventVisiblity = eventVisibility[eventId];
// Always prefer the explicit per-event user preference here.
if (eventVisibility[eventId]) {
return [true, setMediaVisible];
if (explicitEventVisiblity !== undefined) {
return [explicitEventVisiblity, setMediaVisible];
} else if (mediaPreviewSetting.media_previews === MediaPreviewValue.Off) {
return [false, setMediaVisible];
} else if (mediaPreviewSetting.media_previews === MediaPreviewValue.On) {
@@ -59,5 +60,4 @@ export function useMediaVisible(eventId: string, roomId: string): [boolean, (vis
console.warn("Invalid media visibility setting", mediaPreviewSetting.media_previews);
return [false, setMediaVisible];
}
}

View File

@@ -9,8 +9,8 @@ Please see LICENSE files in the repository root for full details.
import React, { type ReactNode } from "react";
import { UNSTABLE_MSC4133_EXTENDED_PROFILES } from "matrix-js-sdk/src/matrix";
import { MediaPreviewConfig } from "../@types/media_preview.ts";
import { type MediaPreviewConfig } from "../@types/media_preview.ts";
import { _t, _td, type TranslationKey } from "../languageHandler";
import DeviceIsolationModeController from "./controllers/DeviceIsolationModeController.ts";
import {

View File

@@ -374,6 +374,10 @@ export default class SettingsStore {
roomId: string | null = null,
excludeDefault = false,
): Settings[S]["default"] | undefined {
if (settingName === "mediaPreviewConfig") {
console.log("GET VALUE", SETTINGS[settingName]);
}
// Verify that the setting is actually a setting
if (!SETTINGS[settingName]) {
throw new Error("Setting '" + settingName + "' does not appear to be a setting.");
@@ -382,6 +386,7 @@ export default class SettingsStore {
const setting = SETTINGS[settingName];
const levelOrder = getLevelOrder(setting);
return SettingsStore.getValueAt(levelOrder[0], settingName, roomId, false, excludeDefault);
}
@@ -728,8 +733,9 @@ export default class SettingsStore {
const showImages = handler.getValue("showImages", null);
const showAvatarsOnInvites = handler.getValue("showAvatarsOnInvites", null);
const AccountHandler = LEVEL_HANDLERS[SettingLevel.ACCOUNT];
if (showImages !== null || showAvatarsOnInvites !== null) {
this.setValue("mediaPreviewConfig", null, SettingLevel.ACCOUNT, {
AccountHandler.setValue("mediaPreviewConfig", null, {
invite_avatars: showAvatarsOnInvites === false ? MediaPreviewValue.Off : MediaPreviewValue.On,
media_previews: showImages === false ? MediaPreviewValue.Off : MediaPreviewValue.On,
});

View File

@@ -5,11 +5,15 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { ClientEvent, MatrixEvent, type MatrixClient } from "matrix-js-sdk/src/matrix";
import { AccountDataEvents } from "matrix-js-sdk/src/types";
import { MEDIA_PREVIEW_ACCOUNT_DATA_TYPE, MediaPreviewConfig, MediaPreviewValue } from "../../@types/media_preview.ts";
import { ClientEvent, type MatrixEvent, type MatrixClient } from "matrix-js-sdk/src/matrix";
import { type AccountDataEvents } from "matrix-js-sdk/src/types";
import { SettingLevel } from "../SettingLevel.ts";
import {
MEDIA_PREVIEW_ACCOUNT_DATA_TYPE,
type MediaPreviewConfig,
MediaPreviewValue,
} from "../../@types/media_preview.ts";
import { type SettingLevel } from "../SettingLevel.ts";
import MatrixClientBackedController from "./MatrixClientBackedController.ts";
/**
@@ -62,12 +66,6 @@ export default class MediaPreviewConfigController extends MatrixClientBackedCont
public getValueOverride(level: SettingLevel, roomId: string | null): MediaPreviewConfig {
// TODO: Use SettingLevel?
if (roomId) {
console.log(
"MediaPreviewConfigController",
"getValueOverride",
this.getRoomValue(roomId),
this.globalSetting,
);
// Use globals for any undefined setting
return {
...this.getRoomValue(roomId),
@@ -96,7 +94,7 @@ export default class MediaPreviewConfigController extends MatrixClientBackedCont
});
return true;
}
await this.client.setAccountDataRaw(MEDIA_PREVIEW_ACCOUNT_DATA_TYPE, newValue);
await this.client.setAccountData(MEDIA_PREVIEW_ACCOUNT_DATA_TYPE, newValue);
return true;
}

View File

@@ -70,7 +70,6 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa
const val = event.getContent()["enabled"];
this.watchers.notifyUpdate("recent_emoji", null, SettingLevel.ACCOUNT, val);
} else if (event.getType() === MEDIA_PREVIEW_ACCOUNT_DATA_TYPE) {
console.log("notifyupdate");
this.watchers.notifyUpdate("mediaPreviewConfig", null, SettingLevel.ROOM_ACCOUNT, event.getContent());
}
};

View File

@@ -58,7 +58,6 @@ export default class RoomAccountSettingsHandler extends MatrixClientBackedSettin
} else if (event.getType() === ALLOWED_WIDGETS_EVENT_TYPE) {
this.watchers.notifyUpdate("allowedWidgets", roomId, SettingLevel.ROOM_ACCOUNT, event.getContent());
} else if (event.getType() === MEDIA_PREVIEW_ACCOUNT_DATA_TYPE) {
console.log("notifyupdate");
this.watchers.notifyUpdate("mediaPreviewConfig", roomId, SettingLevel.ROOM_ACCOUNT, event.getContent());
}
};

View File

@@ -18,10 +18,11 @@ import { LocalRoom } from "../../../../../src/models/LocalRoom";
import * as AvatarModule from "../../../../../src/Avatar";
import { DirectoryMember } from "../../../../../src/utils/direct-messages";
import SettingsStore from "../../../../../src/settings/SettingsStore";
import { SettingLevel } from "../../../../../src/settings/SettingLevel";
import { MediaPreviewValue } from "../../../../../src/@types/media_preview";
describe("RoomAvatar", () => {
let client: MatrixClient;
let showAvatarsSetting: MediaPreviewValue = MediaPreviewValue.On;
filterConsole(
// unrelated for this test
@@ -34,6 +35,13 @@ describe("RoomAvatar", () => {
jest.spyOn(dmRoomMap, "getUserIdForRoomId");
jest.spyOn(DMRoomMap, "shared").mockReturnValue(dmRoomMap);
jest.spyOn(AvatarModule, "defaultAvatarUrlForString");
const origFn = SettingsStore.getValue;
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting, ...args) => {
if (setting === "mediaPreviewConfig") {
return { invite_avatars: showAvatarsSetting, media_previews: MediaPreviewValue.Off};
}
return origFn(setting, ...args);
});
});
afterAll(() => {
@@ -43,12 +51,6 @@ describe("RoomAvatar", () => {
afterEach(() => {
mocked(DMRoomMap.shared().getUserIdForRoomId).mockReset();
mocked(AvatarModule.defaultAvatarUrlForString).mockClear();
SettingsStore.setValue(
"showAvatarsOnInvites",
null,
SettingLevel.ACCOUNT,
SettingsStore.getDefaultValue("showAvatarsOnInvites"),
);
});
it("should render as expected for a Room", () => {
@@ -73,7 +75,6 @@ describe("RoomAvatar", () => {
expect(render(<RoomAvatar room={localRoom} />).container).toMatchSnapshot();
});
it("should render an avatar for a room the user is invited to", () => {
SettingsStore.setValue("showAvatarsOnInvites", null, SettingLevel.ACCOUNT, true);
const room = new Room("!room:example.com", client, client.getSafeUserId());
jest.spyOn(room, "getMxcAvatarUrl").mockImplementation(() => "mxc://example.com/foobar");
room.name = "test room";
@@ -81,7 +82,7 @@ describe("RoomAvatar", () => {
expect(render(<RoomAvatar room={room} />).container).toMatchSnapshot();
});
it("should not render an invite avatar if the user has disabled it", () => {
SettingsStore.setValue("showAvatarsOnInvites", null, SettingLevel.ACCOUNT, false);
showAvatarsSetting = MediaPreviewValue.Off;
const room = new Room("!room:example.com", client, client.getSafeUserId());
room.name = "test room";
room.updateMyMembership("invite");

View File

@@ -14,14 +14,15 @@ import { HideActionButton } from "../../../../../src/components/views/messages/H
import SettingsStore from "../../../../../src/settings/SettingsStore";
import { SettingLevel } from "../../../../../src/settings/SettingLevel";
import type { Settings } from "../../../../../src/settings/Settings";
import { MediaPreviewValue } from "../../../../../src/@types/media_preview";
function mockSetting(
showImages: Settings["showImages"]["default"],
mediaPreviews: MediaPreviewValue,
showMediaEventIds: Settings["showMediaEventIds"]["default"],
) {
jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName) => {
if (settingName === "showImages") {
return showImages;
if (settingName === "mediaPreviewConfig") {
return { media_previews: mediaPreviews, invite_avatars: MediaPreviewValue.Off };
} else if (settingName === "showMediaEventIds") {
return showMediaEventIds;
}
@@ -29,8 +30,10 @@ function mockSetting(
});
}
const EVENT_ID = "$foo:bar";
const event = new MatrixEvent({
event_id: "$foo:bar",
event_id: EVENT_ID,
room_id: "!room:id",
sender: "@user:id",
type: "m.room.message",
@@ -46,22 +49,22 @@ describe("HideActionButton", () => {
jest.restoreAllMocks();
});
it("should show button when event is visible by showMediaEventIds setting", async () => {
mockSetting(false, { "$foo:bar": true });
mockSetting(MediaPreviewValue.Off, { [EVENT_ID]: true });
render(<HideActionButton mxEvent={event} />);
expect(screen.getByRole("button")).toBeVisible();
});
it("should show button when event is visible by showImages setting", async () => {
mockSetting(true, {});
it("should show button when event is visible by mediaPreviewConfig setting", async () => {
mockSetting(MediaPreviewValue.On, {});
render(<HideActionButton mxEvent={event} />);
expect(screen.getByRole("button")).toBeVisible();
});
it("should hide button when event is hidden by showMediaEventIds setting", async () => {
jest.spyOn(SettingsStore, "getValue").mockReturnValue({ "$foo:bar": false });
mockSetting(MediaPreviewValue.Off, { [EVENT_ID]: false });
render(<HideActionButton mxEvent={event} />);
expect(screen.queryByRole("button")).toBeNull();
});
it("should hide button when event is hidden by showImages setting", async () => {
mockSetting(false, {});
mockSetting(MediaPreviewValue.Off, {});
render(<HideActionButton mxEvent={event} />);
expect(screen.queryByRole("button")).toBeNull();
});

View File

@@ -24,10 +24,12 @@ import {
mockClientMethodsDevice,
mockClientMethodsServer,
mockClientMethodsUser,
withClientContextRenderOptions,
} from "../../../../test-utils";
import { MediaEventHelper } from "../../../../../src/utils/MediaEventHelper";
import SettingsStore from "../../../../../src/settings/SettingsStore";
import { SettingLevel } from "../../../../../src/settings/SettingLevel";
import { MediaPreviewValue } from "../../../../../src/@types/media_preview";
jest.mock("matrix-encrypt-attachment", () => ({
decryptAttachment: jest.fn(),
@@ -42,6 +44,7 @@ describe("<MImageBody/>", () => {
...mockClientMethodsDevice(deviceId),
...mockClientMethodsCrypto(),
getRooms: jest.fn().mockReturnValue([]),
getRoom: jest.fn(),
getIgnoredUsers: jest.fn(),
getVersions: jest.fn().mockResolvedValue({
unstable_features: {
@@ -136,19 +139,17 @@ describe("<MImageBody/>", () => {
describe("with image previews/thumbnails disabled", () => {
beforeEach(() => {
act(() => {
SettingsStore.setValue("showImages", null, SettingLevel.DEVICE, false);
const origFn = SettingsStore.getValue;
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting, ...args) => {
if (setting === "mediaPreviewConfig") {
return { invite_avatars: MediaPreviewValue.Off, media_previews: MediaPreviewValue.Off};
}
return origFn(setting, ...args);
});
});
afterEach(() => {
act(() => {
SettingsStore.setValue(
"showImages",
null,
SettingLevel.DEVICE,
SettingsStore.getDefaultValue("showImages"),
);
SettingsStore.setValue(
"showMediaEventIds",
null,
@@ -167,6 +168,7 @@ describe("<MImageBody/>", () => {
mxEvent={encryptedMediaEvent}
mediaEventHelper={new MediaEventHelper(encryptedMediaEvent)}
/>,
withClientContextRenderOptions(cli)
);
expect(screen.getByText("Show image")).toBeInTheDocument();
@@ -183,6 +185,7 @@ describe("<MImageBody/>", () => {
mxEvent={encryptedMediaEvent}
mediaEventHelper={new MediaEventHelper(encryptedMediaEvent)}
/>,
withClientContextRenderOptions(cli)
);
expect(screen.getByText("Show image")).toBeInTheDocument();

View File

@@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
*/
import React, { act } from "react";
import { EventType, getHttpUriForMxc, type IContent, MatrixEvent } from "matrix-js-sdk/src/matrix";
import { EventType, getHttpUriForMxc, type IContent, MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix";
import { fireEvent, render, screen, type RenderResult } from "jest-matrix-react";
import fetchMock from "fetch-mock-jest";
@@ -20,11 +20,14 @@ import {
mockClientMethodsDevice,
mockClientMethodsServer,
mockClientMethodsUser,
withClientContextRenderOptions,
} from "../../../../test-utils";
import MVideoBody from "../../../../../src/components/views/messages/MVideoBody";
import type { IBodyProps } from "../../../../../src/components/views/messages/IBodyProps";
import { SettingLevel } from "../../../../../src/settings/SettingLevel";
import SettingsStore from "../../../../../src/settings/SettingsStore";
import { MediaPreviewValue } from "../../../../../src/@types/media_preview";
import { MockedObject } from "jest-mock";
// Needed so we don't throw an error about failing to decrypt.
jest.mock("matrix-encrypt-attachment", () => ({
@@ -36,13 +39,15 @@ describe("MVideoBody", () => {
const deviceId = "DEADB33F";
const thumbUrl = "https://server/_matrix/media/v3/download/server/encrypted-poster";
let cli: MockedObject<MatrixClient>;
beforeEach(() => {
const cli = getMockClientWithEventEmitter({
cli = getMockClientWithEventEmitter({
...mockClientMethodsUser(userId),
...mockClientMethodsServer(),
...mockClientMethodsDevice(deviceId),
...mockClientMethodsCrypto(),
getRoom: jest.fn(),
getRooms: jest.fn().mockReturnValue([]),
getIgnoredUsers: jest.fn(),
getVersions: jest.fn().mockResolvedValue({
@@ -99,19 +104,17 @@ describe("MVideoBody", () => {
describe("with video previews/thumbnails disabled", () => {
beforeEach(() => {
act(() => {
SettingsStore.setValue("showImages", null, SettingLevel.DEVICE, false);
const origFn = SettingsStore.getValue;
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting, ...args) => {
if (setting === "mediaPreviewConfig") {
return { invite_avatars: MediaPreviewValue.Off, media_previews: MediaPreviewValue.Off};
}
return origFn(setting, ...args);
});
});
afterEach(() => {
act(() => {
SettingsStore.setValue(
"showImages",
null,
SettingLevel.DEVICE,
SettingsStore.getDefaultValue("showImages"),
);
SettingsStore.setValue(
"showMediaEventIds",
null,
@@ -119,6 +122,7 @@ describe("MVideoBody", () => {
SettingsStore.getDefaultValue("showMediaEventIds"),
);
});
jest.restoreAllMocks();
});
it("should not download video", async () => {
@@ -129,6 +133,7 @@ describe("MVideoBody", () => {
mxEvent={encryptedMediaEvent}
mediaEventHelper={new MediaEventHelper(encryptedMediaEvent)}
/>,
withClientContextRenderOptions(cli)
);
expect(screen.getByText("Show video")).toBeInTheDocument();
@@ -144,6 +149,7 @@ describe("MVideoBody", () => {
mxEvent={encryptedMediaEvent}
mediaEventHelper={new MediaEventHelper(encryptedMediaEvent)}
/>,
withClientContextRenderOptions(cli)
);
const placeholderButton = screen.getByRole("button", { name: "Show video" });
@@ -191,6 +197,7 @@ function makeMVideoBody(w: number, h: number): RenderResult {
const mockClient = getMockClientWithEventEmitter({
mxcUrlToHttp: jest.fn(),
getRoom: jest.fn(),
});
return render(

View File

@@ -44,9 +44,13 @@ describe("RoomPreviewCard", () => {
client.reEmitter.reEmit(room, [RoomStateEvent.Events]);
enabledFeatures = [];
jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName): any =>
enabledFeatures.includes(settingName) ? true : undefined,
);
const origFn = SettingsStore.getValue;
jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName): any => {
if (enabledFeatures.includes(settingName)) {
return true;
}
return origFn(settingName);
});
});
afterEach(() => {

View File

@@ -95,33 +95,6 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
/>
</div>
</div>
<div
class="mx_SettingsFlag"
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_QgU2PomxwKpa"
>
<span
class="mx_SettingsFlag_labelText"
>
Show avatars of rooms you have been invited to
</span>
</label>
<div
aria-checked="true"
aria-disabled="true"
aria-label="Show avatars of rooms you have been invited to"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
id="mx_SettingsFlag_QgU2PomxwKpa"
role="switch"
tabindex="0"
>
<div
class="mx_ToggleSwitch_ball"
/>
</div>
</div>
</div>
</div>
<div
@@ -144,7 +117,7 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_6hpi3YEetmBG"
for="mx_SettingsFlag_QgU2PomxwKpa"
>
<span
class="mx_SettingsFlag_labelText"
@@ -162,7 +135,7 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
aria-disabled="true"
aria-label="Show all rooms in Home"
class="mx_AccessibleButton mx_ToggleSwitch"
id="mx_SettingsFlag_6hpi3YEetmBG"
id="mx_SettingsFlag_QgU2PomxwKpa"
role="switch"
tabindex="0"
>
@@ -212,7 +185,7 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_4yVCeEefiPqp"
for="mx_SettingsFlag_6hpi3YEetmBG"
>
<span
class="mx_SettingsFlag_labelText"
@@ -225,7 +198,7 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
aria-disabled="true"
aria-label="Use Ctrl + F to search timeline"
class="mx_AccessibleButton mx_ToggleSwitch"
id="mx_SettingsFlag_4yVCeEefiPqp"
id="mx_SettingsFlag_6hpi3YEetmBG"
role="switch"
tabindex="0"
>
@@ -285,7 +258,7 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_MRMwbPDmfGtm"
for="mx_SettingsFlag_4yVCeEefiPqp"
>
<span
class="mx_SettingsFlag_labelText"
@@ -298,6 +271,33 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
aria-disabled="true"
aria-label="Show timestamps in 12 hour format (e.g. 2:30pm)"
class="mx_AccessibleButton mx_ToggleSwitch"
id="mx_SettingsFlag_4yVCeEefiPqp"
role="switch"
tabindex="0"
>
<div
class="mx_ToggleSwitch_ball"
/>
</div>
</div>
<div
class="mx_SettingsFlag"
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_MRMwbPDmfGtm"
>
<span
class="mx_SettingsFlag_labelText"
>
Always show message timestamps
</span>
</label>
<div
aria-checked="false"
aria-disabled="true"
aria-label="Always show message timestamps"
class="mx_AccessibleButton mx_ToggleSwitch"
id="mx_SettingsFlag_MRMwbPDmfGtm"
role="switch"
tabindex="0"
@@ -313,33 +313,6 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_GQvdMWe954DV"
>
<span
class="mx_SettingsFlag_labelText"
>
Always show message timestamps
</span>
</label>
<div
aria-checked="false"
aria-disabled="true"
aria-label="Always show message timestamps"
class="mx_AccessibleButton mx_ToggleSwitch"
id="mx_SettingsFlag_GQvdMWe954DV"
role="switch"
tabindex="0"
>
<div
class="mx_ToggleSwitch_ball"
/>
</div>
</div>
<div
class="mx_SettingsFlag"
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_IAu5CsiHRD7n"
>
<span
class="mx_SettingsFlag_labelText"
@@ -352,7 +325,7 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
aria-disabled="true"
aria-label="Publish timezone on public profile"
class="mx_AccessibleButton mx_ToggleSwitch"
id="mx_SettingsFlag_IAu5CsiHRD7n"
id="mx_SettingsFlag_GQvdMWe954DV"
role="switch"
tabindex="0"
>
@@ -392,7 +365,7 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_yrA2ohjWVJIP"
for="mx_SettingsFlag_IAu5CsiHRD7n"
>
<span
class="mx_SettingsFlag_labelText"
@@ -405,7 +378,7 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
aria-disabled="true"
aria-label="Send read receipts"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
id="mx_SettingsFlag_yrA2ohjWVJIP"
id="mx_SettingsFlag_IAu5CsiHRD7n"
role="switch"
tabindex="0"
>
@@ -419,7 +392,7 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_auy1OmnTidX4"
for="mx_SettingsFlag_yrA2ohjWVJIP"
>
<span
class="mx_SettingsFlag_labelText"
@@ -432,7 +405,7 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
aria-disabled="true"
aria-label="Send typing notifications"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
id="mx_SettingsFlag_auy1OmnTidX4"
id="mx_SettingsFlag_yrA2ohjWVJIP"
role="switch"
tabindex="0"
>
@@ -463,7 +436,7 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_ePDS0OpWwAHG"
for="mx_SettingsFlag_auy1OmnTidX4"
>
<span
class="mx_SettingsFlag_labelText"
@@ -476,7 +449,7 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
aria-disabled="true"
aria-label="Automatically replace plain text Emoji"
class="mx_AccessibleButton mx_ToggleSwitch"
id="mx_SettingsFlag_ePDS0OpWwAHG"
id="mx_SettingsFlag_auy1OmnTidX4"
role="switch"
tabindex="0"
>
@@ -490,7 +463,7 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_75JNTNkNU64r"
for="mx_SettingsFlag_ePDS0OpWwAHG"
>
<span
class="mx_SettingsFlag_labelText"
@@ -514,6 +487,33 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
aria-disabled="true"
aria-label="Enable Markdown"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
id="mx_SettingsFlag_ePDS0OpWwAHG"
role="switch"
tabindex="0"
>
<div
class="mx_ToggleSwitch_ball"
/>
</div>
</div>
<div
class="mx_SettingsFlag"
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_75JNTNkNU64r"
>
<span
class="mx_SettingsFlag_labelText"
>
Enable Emoji suggestions while typing
</span>
</label>
<div
aria-checked="true"
aria-disabled="true"
aria-label="Enable Emoji suggestions while typing"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
id="mx_SettingsFlag_75JNTNkNU64r"
role="switch"
tabindex="0"
@@ -533,14 +533,14 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
<span
class="mx_SettingsFlag_labelText"
>
Enable Emoji suggestions while typing
Use Ctrl + Enter to send a message
</span>
</label>
<div
aria-checked="true"
aria-checked="false"
aria-disabled="true"
aria-label="Enable Emoji suggestions while typing"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
aria-label="Use Ctrl + Enter to send a message"
class="mx_AccessibleButton mx_ToggleSwitch"
id="mx_SettingsFlag_aTLcRsQRlYy7"
role="switch"
tabindex="0"
@@ -560,13 +560,13 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
<span
class="mx_SettingsFlag_labelText"
>
Use Ctrl + Enter to send a message
Surround selected text when typing special characters
</span>
</label>
<div
aria-checked="false"
aria-disabled="true"
aria-label="Use Ctrl + Enter to send a message"
aria-label="Surround selected text when typing special characters"
class="mx_AccessibleButton mx_ToggleSwitch"
id="mx_SettingsFlag_5nfv5bOEPN1s"
role="switch"
@@ -587,14 +587,14 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
<span
class="mx_SettingsFlag_labelText"
>
Surround selected text when typing special characters
Show stickers button
</span>
</label>
<div
aria-checked="false"
aria-checked="true"
aria-disabled="true"
aria-label="Surround selected text when typing special characters"
class="mx_AccessibleButton mx_ToggleSwitch"
aria-label="Show stickers button"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
id="mx_SettingsFlag_u1JYVtOyR5kb"
role="switch"
tabindex="0"
@@ -610,33 +610,6 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_u3pEwuLn9Enn"
>
<span
class="mx_SettingsFlag_labelText"
>
Show stickers button
</span>
</label>
<div
aria-checked="true"
aria-disabled="true"
aria-label="Show stickers button"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
id="mx_SettingsFlag_u3pEwuLn9Enn"
role="switch"
tabindex="0"
>
<div
class="mx_ToggleSwitch_ball"
/>
</div>
</div>
<div
class="mx_SettingsFlag"
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_YuxfFEpOsztW"
>
<span
class="mx_SettingsFlag_labelText"
@@ -649,7 +622,7 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
aria-disabled="true"
aria-label="Insert a trailing colon after user mentions at the start of a message"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
id="mx_SettingsFlag_YuxfFEpOsztW"
id="mx_SettingsFlag_u3pEwuLn9Enn"
role="switch"
tabindex="0"
>
@@ -680,7 +653,7 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_hQkBerF1ejc4"
for="mx_SettingsFlag_YuxfFEpOsztW"
>
<span
class="mx_SettingsFlag_labelText"
@@ -693,6 +666,33 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
aria-disabled="true"
aria-label="Enable automatic language detection for syntax highlighting"
class="mx_AccessibleButton mx_ToggleSwitch"
id="mx_SettingsFlag_YuxfFEpOsztW"
role="switch"
tabindex="0"
>
<div
class="mx_ToggleSwitch_ball"
/>
</div>
</div>
<div
class="mx_SettingsFlag"
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_hQkBerF1ejc4"
>
<span
class="mx_SettingsFlag_labelText"
>
Expand code blocks by default
</span>
</label>
<div
aria-checked="false"
aria-disabled="true"
aria-label="Expand code blocks by default"
class="mx_AccessibleButton mx_ToggleSwitch"
id="mx_SettingsFlag_hQkBerF1ejc4"
role="switch"
tabindex="0"
@@ -708,33 +708,6 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_GFes1UFzOK2n"
>
<span
class="mx_SettingsFlag_labelText"
>
Expand code blocks by default
</span>
</label>
<div
aria-checked="false"
aria-disabled="true"
aria-label="Expand code blocks by default"
class="mx_AccessibleButton mx_ToggleSwitch"
id="mx_SettingsFlag_GFes1UFzOK2n"
role="switch"
tabindex="0"
>
<div
class="mx_ToggleSwitch_ball"
/>
</div>
</div>
<div
class="mx_SettingsFlag"
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_vfGFMldL2r2v"
>
<span
class="mx_SettingsFlag_labelText"
@@ -747,7 +720,7 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
aria-disabled="true"
aria-label="Show line numbers in code blocks"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
id="mx_SettingsFlag_vfGFMldL2r2v"
id="mx_SettingsFlag_GFes1UFzOK2n"
role="switch"
tabindex="0"
>
@@ -778,7 +751,7 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_bsSwicmKUiOB"
for="mx_SettingsFlag_vfGFMldL2r2v"
>
<span
class="mx_SettingsFlag_labelText"
@@ -791,6 +764,33 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
aria-disabled="true"
aria-label="Enable inline URL previews by default"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
id="mx_SettingsFlag_vfGFMldL2r2v"
role="switch"
tabindex="0"
>
<div
class="mx_ToggleSwitch_ball"
/>
</div>
</div>
<div
class="mx_SettingsFlag"
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_bsSwicmKUiOB"
>
<span
class="mx_SettingsFlag_labelText"
>
Autoplay GIFs
</span>
</label>
<div
aria-checked="false"
aria-disabled="true"
aria-label="Autoplay GIFs"
class="mx_AccessibleButton mx_ToggleSwitch"
id="mx_SettingsFlag_bsSwicmKUiOB"
role="switch"
tabindex="0"
@@ -806,33 +806,6 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_dvqsxEaZtl3A"
>
<span
class="mx_SettingsFlag_labelText"
>
Autoplay GIFs
</span>
</label>
<div
aria-checked="false"
aria-disabled="true"
aria-label="Autoplay GIFs"
class="mx_AccessibleButton mx_ToggleSwitch"
id="mx_SettingsFlag_dvqsxEaZtl3A"
role="switch"
tabindex="0"
>
<div
class="mx_ToggleSwitch_ball"
/>
</div>
</div>
<div
class="mx_SettingsFlag"
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_NIiWzqsApP1c"
>
<span
class="mx_SettingsFlag_labelText"
@@ -845,34 +818,7 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
aria-disabled="true"
aria-label="Autoplay videos"
class="mx_AccessibleButton mx_ToggleSwitch"
id="mx_SettingsFlag_NIiWzqsApP1c"
role="switch"
tabindex="0"
>
<div
class="mx_ToggleSwitch_ball"
/>
</div>
</div>
<div
class="mx_SettingsFlag"
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_q1SIAPqLMVXh"
>
<span
class="mx_SettingsFlag_labelText"
>
Show previews/thumbnails for images
</span>
</label>
<div
aria-checked="true"
aria-disabled="true"
aria-label="Show previews/thumbnails for images"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
id="mx_SettingsFlag_q1SIAPqLMVXh"
id="mx_SettingsFlag_dvqsxEaZtl3A"
role="switch"
tabindex="0"
>
@@ -903,7 +849,7 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_dXFDGgBsKXay"
for="mx_SettingsFlag_NIiWzqsApP1c"
>
<span
class="mx_SettingsFlag_labelText"
@@ -916,6 +862,60 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
aria-disabled="true"
aria-label="Show typing notifications"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
id="mx_SettingsFlag_NIiWzqsApP1c"
role="switch"
tabindex="0"
>
<div
class="mx_ToggleSwitch_ball"
/>
</div>
</div>
<div
class="mx_SettingsFlag"
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_q1SIAPqLMVXh"
>
<span
class="mx_SettingsFlag_labelText"
>
Show a placeholder for removed messages
</span>
</label>
<div
aria-checked="true"
aria-disabled="true"
aria-label="Show a placeholder for removed messages"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
id="mx_SettingsFlag_q1SIAPqLMVXh"
role="switch"
tabindex="0"
>
<div
class="mx_ToggleSwitch_ball"
/>
</div>
</div>
<div
class="mx_SettingsFlag"
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_dXFDGgBsKXay"
>
<span
class="mx_SettingsFlag_labelText"
>
Show read receipts sent by other users
</span>
</label>
<div
aria-checked="true"
aria-disabled="true"
aria-label="Show read receipts sent by other users"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
id="mx_SettingsFlag_dXFDGgBsKXay"
role="switch"
tabindex="0"
@@ -935,13 +935,13 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
<span
class="mx_SettingsFlag_labelText"
>
Show a placeholder for removed messages
Show join/leave messages (invites/removes/bans unaffected)
</span>
</label>
<div
aria-checked="true"
aria-disabled="true"
aria-label="Show a placeholder for removed messages"
aria-label="Show join/leave messages (invites/removes/bans unaffected)"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
id="mx_SettingsFlag_7Az0xw4Bs4Tt"
role="switch"
@@ -962,13 +962,13 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
<span
class="mx_SettingsFlag_labelText"
>
Show read receipts sent by other users
Show display name changes
</span>
</label>
<div
aria-checked="true"
aria-disabled="true"
aria-label="Show read receipts sent by other users"
aria-label="Show display name changes"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
id="mx_SettingsFlag_8jmzPIlPoBCv"
role="switch"
@@ -989,13 +989,13 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
<span
class="mx_SettingsFlag_labelText"
>
Show join/leave messages (invites/removes/bans unaffected)
Show chat effects (animations when receiving e.g. confetti)
</span>
</label>
<div
aria-checked="true"
aria-disabled="true"
aria-label="Show join/leave messages (invites/removes/bans unaffected)"
aria-label="Show chat effects (animations when receiving e.g. confetti)"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
id="mx_SettingsFlag_enFRaTjdsFou"
role="switch"
@@ -1016,13 +1016,13 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
<span
class="mx_SettingsFlag_labelText"
>
Show display name changes
Show profile picture changes
</span>
</label>
<div
aria-checked="true"
aria-disabled="true"
aria-label="Show display name changes"
aria-label="Show profile picture changes"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
id="mx_SettingsFlag_bfwnd5rz4XNX"
role="switch"
@@ -1043,13 +1043,13 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
<span
class="mx_SettingsFlag_labelText"
>
Show chat effects (animations when receiving e.g. confetti)
Show avatars in user, room and event mentions
</span>
</label>
<div
aria-checked="true"
aria-disabled="true"
aria-label="Show chat effects (animations when receiving e.g. confetti)"
aria-label="Show avatars in user, room and event mentions"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
id="mx_SettingsFlag_gs5uWEzYzZrS"
role="switch"
@@ -1070,13 +1070,13 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
<span
class="mx_SettingsFlag_labelText"
>
Show profile picture changes
Enable big emoji in chat
</span>
</label>
<div
aria-checked="true"
aria-disabled="true"
aria-label="Show profile picture changes"
aria-label="Enable big emoji in chat"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
id="mx_SettingsFlag_qWg7OgID1yRR"
role="switch"
@@ -1097,13 +1097,13 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
<span
class="mx_SettingsFlag_labelText"
>
Show avatars in user, room and event mentions
Jump to the bottom of the timeline when you send a message
</span>
</label>
<div
aria-checked="true"
aria-disabled="true"
aria-label="Show avatars in user, room and event mentions"
aria-label="Jump to the bottom of the timeline when you send a message"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
id="mx_SettingsFlag_pOPewl7rtMbV"
role="switch"
@@ -1124,14 +1124,14 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
<span
class="mx_SettingsFlag_labelText"
>
Enable big emoji in chat
Show current profile picture and name for users in message history
</span>
</label>
<div
aria-checked="true"
aria-checked="false"
aria-disabled="true"
aria-label="Enable big emoji in chat"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
aria-label="Show current profile picture and name for users in message history"
class="mx_AccessibleButton mx_ToggleSwitch"
id="mx_SettingsFlag_cmt3PZSyNp3v"
role="switch"
tabindex="0"
@@ -1141,60 +1141,157 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
/>
</div>
</div>
<div
class="mx_SettingsFlag"
</div>
</div>
<div
class="mx_SettingsSubsection"
>
<div
class="mx_SettingsSubsectionHeading"
>
<h3
class="mx_Heading_h4 mx_SettingsSubsectionHeading_heading"
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_dJJz3lHUv9XX"
Moderation and safety
</h3>
</div>
<div
class="mx_SettingsSubsection_content"
>
<form
class="_root_19upo_16"
>
<div
class="mx_SettingsFlag"
>
<span
class="mx_SettingsFlag_labelText"
class="mx_SettingsFlag_label"
>
Jump to the bottom of the timeline when you send a message
<div
id="mx_LabelledToggleSwitch_dJJz3lHUv9XX"
>
Hide avatars of room and inviter
</div>
</span>
</label>
<div
aria-checked="true"
aria-disabled="true"
aria-label="Jump to the bottom of the timeline when you send a message"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
id="mx_SettingsFlag_dJJz3lHUv9XX"
role="switch"
tabindex="0"
>
<div
class="mx_ToggleSwitch_ball"
/>
aria-checked="false"
aria-disabled="false"
aria-labelledby="mx_LabelledToggleSwitch_dJJz3lHUv9XX"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_enabled"
role="switch"
tabindex="0"
>
<div
class="mx_ToggleSwitch_ball"
/>
</div>
</div>
</div>
<div
class="mx_SettingsFlag"
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_SBSSOZDRlzlA"
<div
class="_field_19upo_26"
role="radiogroup"
>
<label
class="_label_19upo_59"
for="radix-:r8:"
>
Show media in timeline
</label>
<span
class="mx_SettingsFlag_labelText"
class="_message_19upo_85 _help-message_19upo_91"
id="radix-:r9:"
>
Show current profile picture and name for users in message history
A hidden media can always be shown by tapping on it
</span>
</label>
<div
aria-checked="false"
aria-disabled="true"
aria-label="Show current profile picture and name for users in message history"
class="mx_AccessibleButton mx_ToggleSwitch"
id="mx_SettingsFlag_SBSSOZDRlzlA"
role="switch"
tabindex="0"
>
<div
class="mx_ToggleSwitch_ball"
/>
class="_inline-field_19upo_32"
>
<div
class="_inline-field-control_19upo_44"
>
<div
class="_container_1e0uz_10"
>
<input
class="_input_1e0uz_18"
type="radio"
/>
<div
class="_ui_1e0uz_19"
/>
</div>
</div>
<div
class="_inline-field-body_19upo_38"
>
<label
class="_label_19upo_59"
for="radix-:ra:"
>
Always hide
</label>
</div>
</div>
<div
class="_inline-field_19upo_32"
>
<div
class="_inline-field-control_19upo_44"
>
<div
class="_container_1e0uz_10"
>
<input
class="_input_1e0uz_18"
type="radio"
/>
<div
class="_ui_1e0uz_19"
/>
</div>
</div>
<div
class="_inline-field-body_19upo_38"
>
<label
class="_label_19upo_59"
for="radix-:rb:"
>
In private rooms
</label>
</div>
</div>
<div
class="_inline-field_19upo_32"
>
<div
class="_inline-field-control_19upo_44"
>
<div
class="_container_1e0uz_10"
>
<input
checked=""
class="_input_1e0uz_18"
type="radio"
/>
<div
class="_ui_1e0uz_19"
/>
</div>
</div>
<div
class="_inline-field-body_19upo_38"
>
<label
class="_label_19upo_59"
for="radix-:rc:"
>
Always show
</label>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
<div
@@ -1217,7 +1314,7 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_FLEpLCb0jpp6"
for="mx_SettingsFlag_SBSSOZDRlzlA"
>
<span
class="mx_SettingsFlag_labelText"
@@ -1230,7 +1327,7 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
aria-disabled="true"
aria-label="Show NSFW content"
class="mx_AccessibleButton mx_ToggleSwitch"
id="mx_SettingsFlag_FLEpLCb0jpp6"
id="mx_SettingsFlag_SBSSOZDRlzlA"
role="switch"
tabindex="0"
>
@@ -1261,7 +1358,7 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
>
<label
class="mx_SettingsFlag_label"
for="mx_SettingsFlag_NQFWldEwbV3q"
for="mx_SettingsFlag_FLEpLCb0jpp6"
>
<span
class="mx_SettingsFlag_labelText"
@@ -1274,7 +1371,7 @@ exports[`PreferencesUserSettingsTab should render 1`] = `
aria-disabled="true"
aria-label="Prompt before sending invites to potentially invalid matrix IDs"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
id="mx_SettingsFlag_NQFWldEwbV3q"
id="mx_SettingsFlag_FLEpLCb0jpp6"
role="switch"
tabindex="0"
>

View File

@@ -6,48 +6,74 @@ Please see LICENSE files in the repository root for full details.
*/
import { act, renderHook, waitFor } from "jest-matrix-react";
import { JoinRule, type MatrixClient, type Room } from "matrix-js-sdk/src/matrix";
import { useMediaVisible } from "../../../src/hooks/useMediaVisible";
import SettingsStore from "../../../src/settings/SettingsStore";
import { SettingLevel } from "../../../src/settings/SettingLevel";
import { createTestClient, mkStubRoom, withClientContextRenderOptions } from "../../test-utils";
import { type MediaPreviewConfig, MediaPreviewValue } from "../../../src/@types/media_preview";
import MediaPreviewConfigController from "../../../src/settings/controllers/MediaPreviewConfigController";
const EVENT_ID = "$fibble:example.org";
function render() {
return renderHook(() => useMediaVisible(EVENT_ID));
}
const ROOM_ID = "!foobar:example.org";
describe("useMediaVisible", () => {
afterEach(() => {
// Using act here as otherwise React warns about state updates not being wrapped.
act(() => {
SettingsStore.setValue(
"showMediaEventIds",
null,
SettingLevel.DEVICE,
SettingsStore.getDefaultValue("showMediaEventIds"),
);
SettingsStore.setValue(
"showImages",
null,
SettingLevel.DEVICE,
SettingsStore.getDefaultValue("showImages"),
);
let matrixClient: MatrixClient;
let room: Room;
const mediaPreviewConfig: MediaPreviewConfig = MediaPreviewConfigController.default;
function render() {
return renderHook(() => useMediaVisible(EVENT_ID, ROOM_ID), withClientContextRenderOptions(matrixClient));
}
beforeEach(() => {
matrixClient = createTestClient();
room = mkStubRoom(ROOM_ID, undefined, matrixClient);
matrixClient.getRoom = jest.fn().mockReturnValue(room);
const origFn = SettingsStore.getValue;
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting, ...args) => {
if (setting === "mediaPreviewConfig") {
return mediaPreviewConfig;
}
return origFn(setting, ...args);
});
});
it("should display images by default", async () => {
afterEach(() => {
jest.restoreAllMocks();
});
it("should display media by default", async () => {
const { result } = render();
expect(result.current[0]).toEqual(true);
});
it("should hide images when the default is changed", async () => {
SettingsStore.setValue("showImages", null, SettingLevel.DEVICE, false);
it("should hide media when media previews are Off", async () => {
mediaPreviewConfig.media_previews = MediaPreviewValue.Off;
const { result } = render();
expect(result.current[0]).toEqual(false);
});
it("should hide images after function is called", async () => {
it.each([[JoinRule.Invite], [JoinRule.Knock], [JoinRule.Restricted]])(
"should display media when media previews are Private and the join rule is %s",
async (rule) => {
mediaPreviewConfig.media_previews = MediaPreviewValue.Private;
room.getJoinRule = jest.fn().mockReturnValue(rule);
const { result } = render();
expect(result.current[0]).toEqual(true);
},
);
it.each([[JoinRule.Public], ["anything_else"]])(
"should hide media when media previews are Private and the join rule is %s",
async (rule) => {
mediaPreviewConfig.media_previews = MediaPreviewValue.Private;
room.getJoinRule = jest.fn().mockReturnValue(rule);
const { result } = render();
expect(result.current[0]).toEqual(false);
},
);
it("should hide media after function is called", async () => {
const { result } = render();
expect(result.current[0]).toEqual(true);
act(() => {
@@ -57,8 +83,8 @@ describe("useMediaVisible", () => {
expect(result.current[0]).toEqual(false);
});
});
it("should show images after function is called", async () => {
SettingsStore.setValue("showImages", null, SettingLevel.DEVICE, false);
it("should show media after function is called", async () => {
mediaPreviewConfig.media_previews = MediaPreviewValue.Off;
const { result } = render();
expect(result.current[0]).toEqual(false);
act(() => {