Merge branch 'develop' into langleyd/fix_room_sumary_style

This commit is contained in:
David Langley
2025-04-16 17:34:06 +01:00
committed by GitHub
84 changed files with 502 additions and 1441 deletions

View File

@@ -11,7 +11,8 @@ jobs:
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
if: | if: |
contains(github.event.issue.assignees.*.login, 't3chguy') || contains(github.event.issue.assignees.*.login, 't3chguy') ||
contains(github.event.issue.assignees.*.login, 'andybalaam') || contains(github.event.issue.assignees.*.login, 'florianduros') ||
contains(github.event.issue.assignees.*.login, 'dbkr') ||
contains(github.event.issue.assignees.*.login, 'MidhunSureshR') contains(github.event.issue.assignees.*.login, 'MidhunSureshR')
steps: steps:
- uses: actions/add-to-project@main - uses: actions/add-to-project@main

View File

@@ -68,13 +68,13 @@
"postinstall": "patch-package" "postinstall": "patch-package"
}, },
"resolutions": { "resolutions": {
"**/pretty-format/react-is": "19.0.0", "**/pretty-format/react-is": "19.1.0",
"@playwright/test": "1.51.1", "@playwright/test": "1.51.1",
"@types/react": "19.0.10", "@types/react": "19.1.1",
"@types/react-dom": "19.0.4", "@types/react-dom": "19.1.2",
"oidc-client-ts": "3.2.0", "oidc-client-ts": "3.2.0",
"jwt-decode": "4.0.0", "jwt-decode": "4.0.0",
"caniuse-lite": "1.0.30001713", "caniuse-lite": "1.0.30001714",
"testcontainers": "10.24.2", "testcontainers": "10.24.2",
"wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0",
"wrap-ansi": "npm:wrap-ansi@^7.0.0" "wrap-ansi": "npm:wrap-ansi@^7.0.0"
@@ -138,7 +138,7 @@
"opus-recorder": "^8.0.3", "opus-recorder": "^8.0.3",
"pako": "^2.0.3", "pako": "^2.0.3",
"png-chunks-extract": "^1.0.0", "png-chunks-extract": "^1.0.0",
"posthog-js": "1.157.2", "posthog-js": "1.236.1",
"qrcode": "1.5.4", "qrcode": "1.5.4",
"re-resizable": "6.11.2", "re-resizable": "6.11.2",
"react": "^19.0.0", "react": "^19.0.0",
@@ -185,6 +185,7 @@
"@peculiar/webcrypto": "^1.4.3", "@peculiar/webcrypto": "^1.4.3",
"@playwright/test": "^1.50.1", "@playwright/test": "^1.50.1",
"@principalstudio/html-webpack-inject-preload": "^1.2.7", "@principalstudio/html-webpack-inject-preload": "^1.2.7",
"@rrweb/types": "^2.0.0-alpha.18",
"@sentry/webpack-plugin": "^3.0.0", "@sentry/webpack-plugin": "^3.0.0",
"@stylistic/eslint-plugin": "^4.0.0", "@stylistic/eslint-plugin": "^4.0.0",
"@svgr/webpack": "^8.0.0", "@svgr/webpack": "^8.0.0",
@@ -211,9 +212,9 @@
"@types/node-fetch": "^2.6.2", "@types/node-fetch": "^2.6.2",
"@types/pako": "^2.0.0", "@types/pako": "^2.0.0",
"@types/qrcode": "^1.3.5", "@types/qrcode": "^1.3.5",
"@types/react": "19.0.10", "@types/react": "19.1.1",
"@types/react-beautiful-dnd": "^13.0.0", "@types/react-beautiful-dnd": "^13.0.0",
"@types/react-dom": "19.0.4", "@types/react-dom": "19.1.2",
"@types/react-transition-group": "^4.4.0", "@types/react-transition-group": "^4.4.0",
"@types/sanitize-html": "2.15.0", "@types/sanitize-html": "2.15.0",
"@types/semver": "^7.5.8", "@types/semver": "^7.5.8",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -20,10 +20,6 @@
&:hover { &:hover {
background-color: var(--cpd-color-bg-action-secondary-hovered); background-color: var(--cpd-color-bg-action-secondary-hovered);
.mx_RoomListItemView_content {
padding-right: var(--cpd-space-1-5x);
}
} }
.mx_RoomListItemView_container { .mx_RoomListItemView_container {

View File

@@ -29,7 +29,6 @@ import type LegacyCallHandler from "../LegacyCallHandler";
import type UserActivity from "../UserActivity"; import type UserActivity from "../UserActivity";
import { type ModalWidgetStore } from "../stores/ModalWidgetStore"; import { type ModalWidgetStore } from "../stores/ModalWidgetStore";
import { type WidgetLayoutStore } from "../stores/widgets/WidgetLayoutStore"; import { type WidgetLayoutStore } from "../stores/widgets/WidgetLayoutStore";
import type VoipUserMapper from "../VoipUserMapper";
import { type SpaceStoreClass } from "../stores/spaces/SpaceStore"; import { type SpaceStoreClass } from "../stores/spaces/SpaceStore";
import type TypingStore from "../stores/TypingStore"; import type TypingStore from "../stores/TypingStore";
import { type EventIndexPeg } from "../indexing/EventIndexPeg"; import { type EventIndexPeg } from "../indexing/EventIndexPeg";
@@ -113,7 +112,6 @@ declare global {
mxLegacyCallHandler: LegacyCallHandler; mxLegacyCallHandler: LegacyCallHandler;
mxUserActivity: UserActivity; mxUserActivity: UserActivity;
mxModalWidgetStore: ModalWidgetStore; mxModalWidgetStore: ModalWidgetStore;
mxVoipUserMapper: VoipUserMapper;
mxSpaceStore: SpaceStoreClass; mxSpaceStore: SpaceStoreClass;
mxVoiceRecordingStore: VoiceRecordingStore; mxVoiceRecordingStore: VoiceRecordingStore;
mxTypingStore: TypingStore; mxTypingStore: TypingStore;

View File

@@ -39,14 +39,12 @@ import { WidgetMessagingStore } from "./stores/widgets/WidgetMessagingStore";
import { ElementWidgetActions } from "./stores/widgets/ElementWidgetActions"; import { ElementWidgetActions } from "./stores/widgets/ElementWidgetActions";
import { UIFeature } from "./settings/UIFeature"; import { UIFeature } from "./settings/UIFeature";
import { Action } from "./dispatcher/actions"; import { Action } from "./dispatcher/actions";
import VoipUserMapper from "./VoipUserMapper";
import { addManagedHybridWidget, isManagedHybridWidgetEnabled } from "./widgets/ManagedHybrid"; import { addManagedHybridWidget, isManagedHybridWidgetEnabled } from "./widgets/ManagedHybrid";
import SdkConfig from "./SdkConfig"; import SdkConfig from "./SdkConfig";
import { ensureDMExists } from "./createRoom"; import { ensureDMExists } from "./createRoom";
import { Container, WidgetLayoutStore } from "./stores/widgets/WidgetLayoutStore"; import { Container, WidgetLayoutStore } from "./stores/widgets/WidgetLayoutStore";
import IncomingLegacyCallToast, { getIncomingLegacyCallToastKey } from "./toasts/IncomingLegacyCallToast"; import IncomingLegacyCallToast, { getIncomingLegacyCallToastKey } from "./toasts/IncomingLegacyCallToast";
import ToastStore from "./stores/ToastStore"; import ToastStore from "./stores/ToastStore";
import Resend from "./Resend";
import { type ViewRoomPayload } from "./dispatcher/payloads/ViewRoomPayload"; import { type ViewRoomPayload } from "./dispatcher/payloads/ViewRoomPayload";
import { InviteKind } from "./components/views/dialogs/InviteDialogTypes"; import { InviteKind } from "./components/views/dialogs/InviteDialogTypes";
import { type OpenInviteDialogPayload } from "./dispatcher/payloads/OpenInviteDialogPayload"; import { type OpenInviteDialogPayload } from "./dispatcher/payloads/OpenInviteDialogPayload";
@@ -59,8 +57,6 @@ import { Jitsi } from "./widgets/Jitsi.ts";
export const PROTOCOL_PSTN = "m.protocol.pstn"; export const PROTOCOL_PSTN = "m.protocol.pstn";
export const PROTOCOL_PSTN_PREFIXED = "im.vector.protocol.pstn"; export const PROTOCOL_PSTN_PREFIXED = "im.vector.protocol.pstn";
export const PROTOCOL_SIP_NATIVE = "im.vector.protocol.sip_native";
export const PROTOCOL_SIP_VIRTUAL = "im.vector.protocol.sip_virtual";
const CHECK_PROTOCOLS_ATTEMPTS = 3; const CHECK_PROTOCOLS_ATTEMPTS = 3;
@@ -107,27 +103,9 @@ const debuglog = (...args: any[]): void => {
} }
}; };
interface ThirdpartyLookupResponseFields {
/* eslint-disable camelcase */
// im.vector.sip_native
virtual_mxid?: string;
is_virtual?: boolean;
// im.vector.sip_virtual
native_mxid?: string;
is_native?: boolean;
// common
lookup_success?: boolean;
/* eslint-enable camelcase */
}
interface ThirdpartyLookupResponse { interface ThirdpartyLookupResponse {
userid: string; userid: string;
protocol: string; protocol: string;
fields: ThirdpartyLookupResponseFields;
} }
export enum LegacyCallHandlerEvent { export enum LegacyCallHandlerEvent {
@@ -158,7 +136,6 @@ export default class LegacyCallHandler extends TypedEventEmitter<LegacyCallHandl
private transferees = new Map<string, MatrixCall>(); // callId (target) -> call (transferee) private transferees = new Map<string, MatrixCall>(); // callId (target) -> call (transferee)
private supportsPstnProtocol: boolean | null = null; private supportsPstnProtocol: boolean | null = null;
private pstnSupportPrefixed: boolean | null = null; // True if the server only support the prefixed pstn protocol private pstnSupportPrefixed: boolean | null = null; // True if the server only support the prefixed pstn protocol
private supportsSipNativeVirtual: boolean | null = null; // im.vector.protocol.sip_virtual and im.vector.protocol.sip_native
// Map of the asserted identity users after we've looked them up using the API. // Map of the asserted identity users after we've looked them up using the API.
// We need to be be able to determine the mapped room synchronously, so we // We need to be be able to determine the mapped room synchronously, so we
@@ -179,8 +156,7 @@ export default class LegacyCallHandler extends TypedEventEmitter<LegacyCallHandl
} }
/* /*
* Gets the user-facing room associated with a call (call.roomId may be the call "virtual room" * Gets the user-facing room associated with a call
* if a voip_mxid_translate_pattern is set in the config)
*/ */
public roomIdForCall(call?: MatrixCall): string | null { public roomIdForCall(call?: MatrixCall): string | null {
if (!call) return null; if (!call) return null;
@@ -195,7 +171,7 @@ export default class LegacyCallHandler extends TypedEventEmitter<LegacyCallHandl
} }
} }
return VoipUserMapper.sharedInstance().nativeRoomForVirtualRoom(call.roomId) ?? call.roomId ?? null; return call.roomId ?? null;
} }
public start(): void { public start(): void {
@@ -278,12 +254,6 @@ export default class LegacyCallHandler extends TypedEventEmitter<LegacyCallHandl
this.supportsPstnProtocol = null; this.supportsPstnProtocol = null;
} }
if (protocols[PROTOCOL_SIP_NATIVE] !== undefined && protocols[PROTOCOL_SIP_VIRTUAL] !== undefined) {
this.supportsSipNativeVirtual = Boolean(
protocols[PROTOCOL_SIP_NATIVE] && protocols[PROTOCOL_SIP_VIRTUAL],
);
}
this.emit(LegacyCallHandlerEvent.ProtocolSupport); this.emit(LegacyCallHandlerEvent.ProtocolSupport);
} catch (e) { } catch (e) {
if (maxTries === 1) { if (maxTries === 1) {
@@ -305,10 +275,6 @@ export default class LegacyCallHandler extends TypedEventEmitter<LegacyCallHandl
return this.supportsPstnProtocol ?? false; return this.supportsPstnProtocol ?? false;
} }
public getSupportsVirtualRooms(): boolean | null {
return this.supportsSipNativeVirtual;
}
public async pstnLookup(phoneNumber: string): Promise<ThirdpartyLookupResponse[]> { public async pstnLookup(phoneNumber: string): Promise<ThirdpartyLookupResponse[]> {
try { try {
return await MatrixClientPeg.safeGet().getThirdpartyUser( return await MatrixClientPeg.safeGet().getThirdpartyUser(
@@ -323,28 +289,6 @@ export default class LegacyCallHandler extends TypedEventEmitter<LegacyCallHandl
} }
} }
public async sipVirtualLookup(nativeMxid: string): Promise<ThirdpartyLookupResponse[]> {
try {
return await MatrixClientPeg.safeGet().getThirdpartyUser(PROTOCOL_SIP_VIRTUAL, {
native_mxid: nativeMxid,
});
} catch (e) {
logger.warn("Failed to query SIP identity for user", e);
return Promise.resolve([]);
}
}
public async sipNativeLookup(virtualMxid: string): Promise<ThirdpartyLookupResponse[]> {
try {
return await MatrixClientPeg.safeGet().getThirdpartyUser(PROTOCOL_SIP_NATIVE, {
virtual_mxid: virtualMxid,
});
} catch (e) {
logger.warn("Failed to query identity for SIP user", e);
return Promise.resolve([]);
}
}
private onCallIncoming = (call: MatrixCall): void => { private onCallIncoming = (call: MatrixCall): void => {
// if the runtime env doesn't do VoIP, stop here. // if the runtime env doesn't do VoIP, stop here.
if (!MatrixClientPeg.get()?.supportsVoip()) { if (!MatrixClientPeg.get()?.supportsVoip()) {
@@ -537,24 +481,16 @@ export default class LegacyCallHandler extends TypedEventEmitter<LegacyCallHandl
} }
const newAssertedIdentity = call.getRemoteAssertedIdentity()?.id; const newAssertedIdentity = call.getRemoteAssertedIdentity()?.id;
let newNativeAssertedIdentity = newAssertedIdentity;
if (newAssertedIdentity) {
const response = await this.sipNativeLookup(newAssertedIdentity);
if (response.length && response[0].fields.lookup_success) {
newNativeAssertedIdentity = response[0].userid;
}
}
logger.log(`Asserted identity ${newAssertedIdentity} mapped to ${newNativeAssertedIdentity}`);
if (newNativeAssertedIdentity) { if (newAssertedIdentity) {
this.assertedIdentityNativeUsers.set(call.callId, newNativeAssertedIdentity); this.assertedIdentityNativeUsers.set(call.callId, newAssertedIdentity);
// If we don't already have a room with this user, make one. This will be slightly odd // If we don't already have a room with this user, make one. This will be slightly odd
// if they called us because we'll be inviting them, but there's not much we can do about // if they called us because we'll be inviting them, but there's not much we can do about
// this if we want the actual, native room to exist (which we do). This is why it's // this if we want the actual, native room to exist (which we do). This is why it's
// important to only obey asserted identity in trusted environments, since anyone you're // important to only obey asserted identity in trusted environments, since anyone you're
// on a call with can cause you to send a room invite to someone. // on a call with can cause you to send a room invite to someone.
await ensureDMExists(MatrixClientPeg.safeGet(), newNativeAssertedIdentity); await ensureDMExists(MatrixClientPeg.safeGet(), newAssertedIdentity);
const newMappedRoomId = this.roomIdForCall(call); const newMappedRoomId = this.roomIdForCall(call);
logger.log(`Old room ID: ${mappedRoomId}, new room ID: ${newMappedRoomId}`); logger.log(`Old room ID: ${mappedRoomId}, new room ID: ${newMappedRoomId}`);
@@ -810,24 +746,10 @@ export default class LegacyCallHandler extends TypedEventEmitter<LegacyCallHandl
private async placeMatrixCall(roomId: string, type: CallType, transferee?: MatrixCall): Promise<void> { private async placeMatrixCall(roomId: string, type: CallType, transferee?: MatrixCall): Promise<void> {
const cli = MatrixClientPeg.safeGet(); const cli = MatrixClientPeg.safeGet();
const mappedRoomId = (await VoipUserMapper.sharedInstance().getOrCreateVirtualRoomForRoom(roomId)) || roomId;
logger.debug("Mapped real room " + roomId + " to room ID " + mappedRoomId);
// If we're using a virtual room nd there are any events pending, try to resend them,
// otherwise the call will fail and because its a virtual room, the user won't be able
// to see it to either retry or clear the pending events. There will only be call events
// in this queue, and since we're about to place a new call, they can only be events from
// previous calls that are probably stale by now, so just cancel them.
if (mappedRoomId !== roomId) {
const mappedRoom = cli.getRoom(mappedRoomId);
if (mappedRoom?.getPendingEvents().length) {
Resend.cancelUnsentEvents(mappedRoom);
}
}
const timeUntilTurnCresExpire = cli.getTurnServersExpiry() - Date.now(); const timeUntilTurnCresExpire = cli.getTurnServersExpiry() - Date.now();
logger.log("Current turn creds expire in " + timeUntilTurnCresExpire + " ms"); logger.log("Current turn creds expire in " + timeUntilTurnCresExpire + " ms");
const call = cli.createCall(mappedRoomId)!; const call = cli.createCall(roomId)!;
try { try {
this.addCallForRoom(roomId, call); this.addCallForRoom(roomId, call);
@@ -978,19 +900,7 @@ export default class LegacyCallHandler extends TypedEventEmitter<LegacyCallHandl
} }
const userId = results[0].userid; const userId = results[0].userid;
// Now check to see if this is a virtual user, in which case we should find the const roomId = await ensureDMExists(MatrixClientPeg.safeGet(), userId);
// native user
let nativeUserId;
if (this.getSupportsVirtualRooms()) {
const nativeLookupResults = await this.sipNativeLookup(userId);
const lookupSuccess = nativeLookupResults.length > 0 && nativeLookupResults[0].fields.lookup_success;
nativeUserId = lookupSuccess ? nativeLookupResults[0].userid : userId;
logger.log("Looked up " + number + " to " + userId + " and mapped to native user " + nativeUserId);
} else {
nativeUserId = userId;
}
const roomId = await ensureDMExists(MatrixClientPeg.safeGet(), nativeUserId);
if (!roomId) { if (!roomId) {
throw new Error("Failed to ensure DM exists for dialing number"); throw new Error("Failed to ensure DM exists for dialing number");
} }

View File

@@ -43,8 +43,6 @@ import { isPushNotifyDisabled } from "./settings/controllers/NotificationControl
import UserActivity from "./UserActivity"; import UserActivity from "./UserActivity";
import { mediaFromMxc } from "./customisations/Media"; import { mediaFromMxc } from "./customisations/Media";
import ErrorDialog from "./components/views/dialogs/ErrorDialog"; import ErrorDialog from "./components/views/dialogs/ErrorDialog";
import LegacyCallHandler from "./LegacyCallHandler";
import VoipUserMapper from "./VoipUserMapper";
import { SdkContextClass } from "./contexts/SDKContext"; import { SdkContextClass } from "./contexts/SDKContext";
import { localNotificationsAreSilenced, createLocalNotificationSettingsIfNeeded } from "./utils/notifications"; import { localNotificationsAreSilenced, createLocalNotificationSettingsIfNeeded } from "./utils/notifications";
import { getIncomingCallToastKey, IncomingCallToast } from "./toasts/IncomingCallToast"; import { getIncomingCallToastKey, IncomingCallToast } from "./toasts/IncomingCallToast";
@@ -447,14 +445,7 @@ class NotifierClass extends TypedEventEmitter<keyof EmittedEvents, EmittedEvents
// XXX: exported for tests // XXX: exported for tests
public evaluateEvent(ev: MatrixEvent): void { public evaluateEvent(ev: MatrixEvent): void {
let roomId = ev.getRoomId()!; const roomId = ev.getRoomId()!;
if (LegacyCallHandler.instance.getSupportsVirtualRooms()) {
// Attempt to translate a virtual room to a native one
const nativeRoomId = VoipUserMapper.sharedInstance().nativeRoomForVirtualRoom(roomId);
if (nativeRoomId) {
roomId = nativeRoomId;
}
}
const room = MatrixClientPeg.safeGet().getRoom(roomId); const room = MatrixClientPeg.safeGet().getRoom(roomId);
if (!room) { if (!room) {
// e.g we are in the process of joining a room. // e.g we are in the process of joining a room.

View File

@@ -52,7 +52,6 @@ import SlashCommandHelpDialog from "./components/views/dialogs/SlashCommandHelpD
import { shouldShowComponent } from "./customisations/helpers/UIComponents"; import { shouldShowComponent } from "./customisations/helpers/UIComponents";
import { TimelineRenderingType } from "./contexts/RoomContext"; import { TimelineRenderingType } from "./contexts/RoomContext";
import { type ViewRoomPayload } from "./dispatcher/payloads/ViewRoomPayload"; import { type ViewRoomPayload } from "./dispatcher/payloads/ViewRoomPayload";
import VoipUserMapper from "./VoipUserMapper";
import { htmlSerializeFromMdIfNeeded } from "./editor/serialize"; import { htmlSerializeFromMdIfNeeded } from "./editor/serialize";
import { leaveRoomBehaviour } from "./utils/leave-behaviour"; import { leaveRoomBehaviour } from "./utils/leave-behaviour";
import { MatrixClientPeg } from "./MatrixClientPeg"; import { MatrixClientPeg } from "./MatrixClientPeg";
@@ -743,28 +742,6 @@ export const Commands = [
}, },
category: CommandCategories.advanced, category: CommandCategories.advanced,
}), }),
new Command({
command: "tovirtual",
description: _td("slash_command|tovirtual"),
category: CommandCategories.advanced,
isEnabled(cli): boolean {
return !!LegacyCallHandler.instance.getSupportsVirtualRooms() && !isCurrentLocalRoom(cli);
},
runFn: (cli, roomId) => {
return success(
(async (): Promise<void> => {
const room = await VoipUserMapper.sharedInstance().getVirtualRoomForRoom(roomId);
if (!room) throw new UserFriendlyError("slash_command|tovirtual_not_found");
dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom,
room_id: room.roomId,
metricsTrigger: "SlashCommand",
metricsViaKeyboard: true,
});
})(),
);
},
}),
new Command({ new Command({
command: "query", command: "query",
description: _td("slash_command|query"), description: _td("slash_command|query"),

View File

@@ -1,150 +0,0 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2021 The Matrix.org Foundation C.I.C.
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 { type Room, EventType } from "matrix-js-sdk/src/matrix";
import { KnownMembership } from "matrix-js-sdk/src/types";
import { logger } from "matrix-js-sdk/src/logger";
import { ensureVirtualRoomExists } from "./createRoom";
import { MatrixClientPeg } from "./MatrixClientPeg";
import DMRoomMap from "./utils/DMRoomMap";
import LegacyCallHandler from "./LegacyCallHandler";
import { VIRTUAL_ROOM_EVENT_TYPE } from "./call-types";
import { findDMForUser } from "./utils/dm/findDMForUser";
// Functions for mapping virtual users & rooms. Currently the only lookup
// is sip virtual: there could be others in the future.
export default class VoipUserMapper {
// We store mappings of virtual -> native room IDs here until the local echo for the
// account data arrives.
private virtualToNativeRoomIdCache = new Map<string, string>();
public static sharedInstance(): VoipUserMapper {
if (window.mxVoipUserMapper === undefined) window.mxVoipUserMapper = new VoipUserMapper();
return window.mxVoipUserMapper;
}
private async userToVirtualUser(userId: string): Promise<string | null> {
const results = await LegacyCallHandler.instance.sipVirtualLookup(userId);
if (results.length === 0 || !results[0].fields.lookup_success) return null;
return results[0].userid;
}
private async getVirtualUserForRoom(roomId: string): Promise<string | null> {
const userId = DMRoomMap.shared().getUserIdForRoomId(roomId);
if (!userId) return null;
const virtualUser = await this.userToVirtualUser(userId);
if (!virtualUser) return null;
return virtualUser;
}
public async getOrCreateVirtualRoomForRoom(roomId: string): Promise<string | null> {
const virtualUser = await this.getVirtualUserForRoom(roomId);
if (!virtualUser) return null;
const cli = MatrixClientPeg.safeGet();
const virtualRoomId = await ensureVirtualRoomExists(cli, virtualUser, roomId);
cli.setRoomAccountData(virtualRoomId!, VIRTUAL_ROOM_EVENT_TYPE, {
native_room: roomId,
});
this.virtualToNativeRoomIdCache.set(virtualRoomId!, roomId);
return virtualRoomId;
}
/**
* Gets the ID of the virtual room for a room, or null if the room has no
* virtual room
*/
public async getVirtualRoomForRoom(roomId: string): Promise<Room | undefined> {
const virtualUser = await this.getVirtualUserForRoom(roomId);
if (!virtualUser) return undefined;
return findDMForUser(MatrixClientPeg.safeGet(), virtualUser);
}
public nativeRoomForVirtualRoom(roomId: string): string | null {
const cachedNativeRoomId = this.virtualToNativeRoomIdCache.get(roomId);
if (cachedNativeRoomId) {
logger.log(
"Returning native room ID " + cachedNativeRoomId + " for virtual room ID " + roomId + " from cache",
);
return cachedNativeRoomId;
}
const cli = MatrixClientPeg.safeGet();
const virtualRoom = cli.getRoom(roomId);
if (!virtualRoom) return null;
const virtualRoomEvent = virtualRoom.getAccountData(VIRTUAL_ROOM_EVENT_TYPE);
if (!virtualRoomEvent || !virtualRoomEvent.getContent()) return null;
const nativeRoomID = virtualRoomEvent.getContent()["native_room"];
const nativeRoom = cli.getRoom(nativeRoomID);
if (!nativeRoom || nativeRoom.getMyMembership() !== KnownMembership.Join) return null;
return nativeRoomID;
}
public isVirtualRoom(room: Room): boolean {
if (this.nativeRoomForVirtualRoom(room.roomId)) return true;
if (this.virtualToNativeRoomIdCache.has(room.roomId)) return true;
// also look in the create event for the claimed native room ID, which is the only
// way we can recognise a virtual room we've created when it first arrives down
// our stream. We don't trust this in general though, as it could be faked by an
// inviter: our main source of truth is the DM state.
const roomCreateEvent = room.currentState.getStateEvents(EventType.RoomCreate, "");
if (!roomCreateEvent || !roomCreateEvent.getContent()) return false;
// we only look at this for rooms we created (so inviters can't just cause rooms
// to be invisible)
if (roomCreateEvent.getSender() !== MatrixClientPeg.safeGet().getUserId()) return false;
const claimedNativeRoomId = roomCreateEvent.getContent()[VIRTUAL_ROOM_EVENT_TYPE];
return Boolean(claimedNativeRoomId);
}
public async onNewInvitedRoom(invitedRoom: Room): Promise<void> {
if (!LegacyCallHandler.instance.getSupportsVirtualRooms()) return;
const inviterId = invitedRoom.getDMInviter();
if (!inviterId) {
logger.error("Could not find DM inviter for room id: " + invitedRoom.roomId);
}
logger.log(`Checking virtual-ness of room ID ${invitedRoom.roomId}, invited by ${inviterId}`);
const result = await LegacyCallHandler.instance.sipNativeLookup(inviterId!);
if (result.length === 0) {
return;
}
if (result[0].fields.is_virtual) {
const cli = MatrixClientPeg.safeGet();
const nativeUser = result[0].userid;
const nativeRoom = findDMForUser(cli, nativeUser);
if (nativeRoom) {
// It's a virtual room with a matching native room, so set the room account data. This
// will make sure we know where how to map calls and also allow us know not to display
// it in the future.
cli.setRoomAccountData(invitedRoom.roomId, VIRTUAL_ROOM_EVENT_TYPE, {
native_room: nativeRoom.roomId,
});
// also auto-join the virtual room if we have a matching native room
// (possibly we should only join if we've also joined the native room, then we'd also have
// to make sure we joined virtual rooms on joining a native one)
cli.joinRoom(invitedRoom.roomId);
// also put this room in the virtual room ID cache so isVirtualRoom return the right answer
// in however long it takes for the echo of setAccountData to come down the sync
this.virtualToNativeRoomIdCache.set(invitedRoom.roomId, nativeRoom.roomId);
}
}
}
}

View File

@@ -6,10 +6,6 @@ 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. Please see LICENSE files in the repository root for full details.
*/ */
// Event type for room account data and room creation content used to mark rooms as virtual rooms
// (and store the ID of their native room)
export const VIRTUAL_ROOM_EVENT_TYPE = "im.vector.is_virtual_room";
export const JitsiCallMemberEventType = "io.element.video.member"; export const JitsiCallMemberEventType = "io.element.video.member";
export interface JitsiCallMemberContent { export interface JitsiCallMemberContent {

View File

@@ -120,8 +120,6 @@ import { isVideoRoom } from "../../utils/video-rooms";
import { SDKContext } from "../../contexts/SDKContext"; import { SDKContext } from "../../contexts/SDKContext";
import { RoomSearchView } from "./RoomSearchView"; import { RoomSearchView } from "./RoomSearchView";
import eventSearch, { type SearchInfo, SearchScope } from "../../Searching"; import eventSearch, { type SearchInfo, SearchScope } from "../../Searching";
import VoipUserMapper from "../../VoipUserMapper";
import { isCallEvent } from "./LegacyCallEventGrouper";
import { WidgetType } from "../../widgets/WidgetType"; import { WidgetType } from "../../widgets/WidgetType";
import WidgetUtils from "../../utils/WidgetUtils"; import WidgetUtils from "../../utils/WidgetUtils";
import { shouldEncryptRoomWithSingle3rdPartyInvite } from "../../utils/room/shouldEncryptRoomWithSingle3rdPartyInvite"; import { shouldEncryptRoomWithSingle3rdPartyInvite } from "../../utils/room/shouldEncryptRoomWithSingle3rdPartyInvite";
@@ -165,7 +163,6 @@ export { MainSplitContentType };
export interface IRoomState { export interface IRoomState {
room?: Room; room?: Room;
virtualRoom?: Room;
roomId?: string; roomId?: string;
roomAlias?: string; roomAlias?: string;
roomLoading: boolean; roomLoading: boolean;
@@ -1344,12 +1341,6 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
return this.messagePanel.canResetTimeline(); return this.messagePanel.canResetTimeline();
}; };
private loadVirtualRoom = async (room?: Room): Promise<void> => {
const virtualRoom = room?.roomId && (await VoipUserMapper.sharedInstance().getVirtualRoomForRoom(room?.roomId));
this.setState({ virtualRoom: virtualRoom || undefined });
};
// called when state.room is first initialised (either at initial load, // called when state.room is first initialised (either at initial load,
// after a successful peek, or after we join the room). // after a successful peek, or after we join the room).
private onRoomLoaded = (room: Room): void => { private onRoomLoaded = (room: Room): void => {
@@ -1362,7 +1353,6 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
this.calculateRecommendedVersion(room); this.calculateRecommendedVersion(room);
this.updatePermissions(room); this.updatePermissions(room);
this.checkWidgets(room); this.checkWidgets(room);
this.loadVirtualRoom(room);
this.updateRoomEncrypted(room); this.updateRoomEncrypted(room);
if ( if (
@@ -2444,8 +2434,6 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
<TimelinePanel <TimelinePanel
ref={this.gatherTimelinePanelRef} ref={this.gatherTimelinePanelRef}
timelineSet={this.state.room.getUnfilteredTimelineSet()} timelineSet={this.state.room.getUnfilteredTimelineSet()}
overlayTimelineSet={this.state.virtualRoom?.getUnfilteredTimelineSet()}
overlayTimelineSetFilter={isCallEvent}
showReadReceipts={this.state.showReadReceipts} showReadReceipts={this.state.showReadReceipts}
manageReadReceipts={!this.state.isPeeking} manageReadReceipts={!this.state.isPeeking}
sendReadReceiptOnLoad={!this.state.wasContextSwitch} sendReadReceiptOnLoad={!this.state.wasContextSwitch}

View File

@@ -30,7 +30,7 @@ import {
ThreadEvent, ThreadEvent,
ReceiptType, ReceiptType,
} from "matrix-js-sdk/src/matrix"; } from "matrix-js-sdk/src/matrix";
import { debounce, findLastIndex } from "lodash"; import { debounce } from "lodash";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import SettingsStore from "../../settings/SettingsStore"; import SettingsStore from "../../settings/SettingsStore";
@@ -73,25 +73,12 @@ const debuglog = (...args: any[]): void => {
} }
}; };
const overlaysBefore = (overlayEvent: MatrixEvent, mainEvent: MatrixEvent): boolean =>
overlayEvent.localTimestamp < mainEvent.localTimestamp;
const overlaysAfter = (overlayEvent: MatrixEvent, mainEvent: MatrixEvent): boolean =>
overlayEvent.localTimestamp >= mainEvent.localTimestamp;
interface IProps { interface IProps {
// The js-sdk EventTimelineSet object for the timeline sequence we are // The js-sdk EventTimelineSet object for the timeline sequence we are
// representing. This may or may not have a room, depending on what it's // representing. This may or may not have a room, depending on what it's
// a timeline representing. If it has a room, we maintain RRs etc for // a timeline representing. If it has a room, we maintain RRs etc for
// that room. // that room.
timelineSet: EventTimelineSet; timelineSet: EventTimelineSet;
// overlay events from a second timelineset on the main timeline
// added to support virtual rooms
// events from the overlay timeline set will be added by localTimestamp
// into the main timeline
overlayTimelineSet?: EventTimelineSet;
// filter events from overlay timeline
overlayTimelineSetFilter?: (event: MatrixEvent) => boolean;
showReadReceipts?: boolean; showReadReceipts?: boolean;
// Enable managing RRs and RMs. These require the timelineSet to have a room. // Enable managing RRs and RMs. These require the timelineSet to have a room.
manageReadReceipts?: boolean; manageReadReceipts?: boolean;
@@ -251,7 +238,6 @@ class TimelinePanel extends React.Component<IProps, IState> {
private readonly messagePanel = createRef<MessagePanel>(); private readonly messagePanel = createRef<MessagePanel>();
private dispatcherRef?: string; private dispatcherRef?: string;
private timelineWindow?: TimelineWindow; private timelineWindow?: TimelineWindow;
private overlayTimelineWindow?: TimelineWindow;
private unmounted = false; private unmounted = false;
private readReceiptActivityTimer: Timer | null = null; private readReceiptActivityTimer: Timer | null = null;
private readMarkerActivityTimer: Timer | null = null; private readMarkerActivityTimer: Timer | null = null;
@@ -349,16 +335,12 @@ class TimelinePanel extends React.Component<IProps, IState> {
const differentEventId = prevProps.eventId != this.props.eventId; const differentEventId = prevProps.eventId != this.props.eventId;
const differentHighlightedEventId = prevProps.highlightedEventId != this.props.highlightedEventId; const differentHighlightedEventId = prevProps.highlightedEventId != this.props.highlightedEventId;
const differentAvoidJump = prevProps.eventScrollIntoView && !this.props.eventScrollIntoView; const differentAvoidJump = prevProps.eventScrollIntoView && !this.props.eventScrollIntoView;
const differentOverlayTimeline = prevProps.overlayTimelineSet !== this.props.overlayTimelineSet;
if (differentEventId || differentHighlightedEventId || differentAvoidJump) { if (differentEventId || differentHighlightedEventId || differentAvoidJump) {
logger.log( logger.log(
`TimelinePanel switching to eventId ${this.props.eventId} (was ${prevProps.eventId}), ` + `TimelinePanel switching to eventId ${this.props.eventId} (was ${prevProps.eventId}), ` +
`scrollIntoView: ${this.props.eventScrollIntoView} (was ${prevProps.eventScrollIntoView})`, `scrollIntoView: ${this.props.eventScrollIntoView} (was ${prevProps.eventScrollIntoView})`,
); );
this.initTimeline(this.props); this.initTimeline(this.props);
} else if (differentOverlayTimeline) {
logger.log(`TimelinePanel updating overlay timeline.`);
this.initTimeline(this.props);
} }
} }
@@ -509,24 +491,9 @@ class TimelinePanel extends React.Component<IProps, IState> {
// this particular event should be the first or last to be unpaginated. // this particular event should be the first or last to be unpaginated.
const eventId = scrollToken; const eventId = scrollToken;
// The event in question could belong to either the main timeline or
// overlay timeline; let's check both
const mainEvents = this.timelineWindow!.getEvents(); const mainEvents = this.timelineWindow!.getEvents();
const overlayEvents = this.overlayTimelineWindow?.getEvents() ?? [];
let marker = mainEvents.findIndex((ev) => ev.getId() === eventId); const marker = mainEvents.findIndex((ev) => ev.getId() === eventId);
let overlayMarker: number;
if (marker === -1) {
// The event must be from the overlay timeline instead
overlayMarker = overlayEvents.findIndex((ev) => ev.getId() === eventId);
marker = backwards
? findLastIndex(mainEvents, (ev) => overlaysAfter(overlayEvents[overlayMarker], ev))
: mainEvents.findIndex((ev) => overlaysBefore(overlayEvents[overlayMarker], ev));
} else {
overlayMarker = backwards
? findLastIndex(overlayEvents, (ev) => overlaysBefore(ev, mainEvents[marker]))
: overlayEvents.findIndex((ev) => overlaysAfter(ev, mainEvents[marker]));
}
// The number of events to unpaginate from the main timeline // The number of events to unpaginate from the main timeline
let count: number; let count: number;
@@ -536,24 +503,11 @@ class TimelinePanel extends React.Component<IProps, IState> {
count = backwards ? marker + 1 : mainEvents.length - marker; count = backwards ? marker + 1 : mainEvents.length - marker;
} }
// The number of events to unpaginate from the overlay timeline
let overlayCount: number;
if (overlayMarker === -1) {
overlayCount = 0;
} else {
overlayCount = backwards ? overlayMarker + 1 : overlayEvents.length - overlayMarker;
}
if (count > 0) { if (count > 0) {
debuglog("Unpaginating", count, "in direction", dir); debuglog("Unpaginating", count, "in direction", dir);
this.timelineWindow!.unpaginate(count, backwards); this.timelineWindow!.unpaginate(count, backwards);
} }
if (overlayCount > 0) {
debuglog("Unpaginating", count, "from overlay timeline in direction", dir);
this.overlayTimelineWindow!.unpaginate(overlayCount, backwards);
}
const { events, liveEvents } = this.getEvents(); const { events, liveEvents } = this.getEvents();
this.buildLegacyCallEventGroupers(events); this.buildLegacyCallEventGroupers(events);
this.setState({ this.setState({
@@ -610,10 +564,6 @@ class TimelinePanel extends React.Component<IProps, IState> {
return false; return false;
} }
if (this.overlayTimelineWindow) {
await this.extendOverlayWindowToCoverMainWindow();
}
debuglog("paginate complete backwards:" + backwards + "; success:" + r); debuglog("paginate complete backwards:" + backwards + "; success:" + r);
const { events, liveEvents } = this.getEvents(); const { events, liveEvents } = this.getEvents();
@@ -705,10 +655,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
data: IRoomTimelineData, data: IRoomTimelineData,
): void => { ): void => {
// ignore events for other timeline sets // ignore events for other timeline sets
if ( if (data.timeline.getTimelineSet() !== this.props.timelineSet) {
data.timeline.getTimelineSet() !== this.props.timelineSet &&
data.timeline.getTimelineSet() !== this.props.overlayTimelineSet
) {
return; return;
} }
@@ -748,69 +695,60 @@ class TimelinePanel extends React.Component<IProps, IState> {
// timeline window. // timeline window.
// //
// see https://github.com/vector-im/vector-web/issues/1035 // see https://github.com/vector-im/vector-web/issues/1035
this.timelineWindow!.paginate(EventTimeline.FORWARDS, 1, false) this.timelineWindow!.paginate(EventTimeline.FORWARDS, 1, false).then(() => {
.then(() => { if (this.unmounted) {
if (this.overlayTimelineWindow) { return;
return this.overlayTimelineWindow.paginate(EventTimeline.FORWARDS, 1, false); }
const { events, liveEvents } = this.getEvents();
this.buildLegacyCallEventGroupers(events);
const lastLiveEvent = liveEvents[liveEvents.length - 1];
const updatedState: Partial<IState> = {
events,
liveEvents,
};
let callRMUpdated = false;
if (this.props.manageReadMarkers) {
// when a new event arrives when the user is not watching the
// window, but the window is in its auto-scroll mode, make sure the
// read marker is visible.
//
// We ignore events we have sent ourselves; we don't want to see the
// read-marker when a remote echo of an event we have just sent takes
// more than the timeout on userActiveRecently.
//
const myUserId = MatrixClientPeg.safeGet().credentials.userId;
callRMUpdated = false;
if (ev.getSender() !== myUserId && !UserActivity.sharedInstance().userActiveRecently()) {
updatedState.readMarkerVisible = true;
} else if (lastLiveEvent && this.getReadMarkerPosition() === 0) {
// we know we're stuckAtBottom, so we can advance the RM
// immediately, to save a later render cycle
this.setReadMarker(lastLiveEvent.getId() ?? null, lastLiveEvent.getTs(), true);
updatedState.readMarkerVisible = false;
updatedState.readMarkerEventId = lastLiveEvent.getId();
callRMUpdated = true;
} }
}) }
.then(() => {
if (this.unmounted) { this.setState(updatedState as IState, () => {
return; this.messagePanel.current?.updateTimelineMinHeight();
if (callRMUpdated) {
this.props.onReadMarkerUpdated?.();
} }
const { events, liveEvents } = this.getEvents();
this.buildLegacyCallEventGroupers(events);
const lastLiveEvent = liveEvents[liveEvents.length - 1];
const updatedState: Partial<IState> = {
events,
liveEvents,
};
let callRMUpdated = false;
if (this.props.manageReadMarkers) {
// when a new event arrives when the user is not watching the
// window, but the window is in its auto-scroll mode, make sure the
// read marker is visible.
//
// We ignore events we have sent ourselves; we don't want to see the
// read-marker when a remote echo of an event we have just sent takes
// more than the timeout on userActiveRecently.
//
const myUserId = MatrixClientPeg.safeGet().credentials.userId;
callRMUpdated = false;
if (ev.getSender() !== myUserId && !UserActivity.sharedInstance().userActiveRecently()) {
updatedState.readMarkerVisible = true;
} else if (lastLiveEvent && this.getReadMarkerPosition() === 0) {
// we know we're stuckAtBottom, so we can advance the RM
// immediately, to save a later render cycle
this.setReadMarker(lastLiveEvent.getId() ?? null, lastLiveEvent.getTs(), true);
updatedState.readMarkerVisible = false;
updatedState.readMarkerEventId = lastLiveEvent.getId();
callRMUpdated = true;
}
}
this.setState(updatedState as IState, () => {
this.messagePanel.current?.updateTimelineMinHeight();
if (callRMUpdated) {
this.props.onReadMarkerUpdated?.();
}
});
}); });
});
}; };
private hasTimelineSetFor(roomId: string | undefined): boolean { private hasTimelineSetFor(roomId: string | undefined): boolean {
return ( return roomId !== undefined && roomId === this.props.timelineSet.room?.roomId;
(roomId !== undefined && roomId === this.props.timelineSet.room?.roomId) ||
roomId === this.props.overlayTimelineSet?.room?.roomId
);
} }
private onRoomTimelineReset = (room: Room | undefined, timelineSet: EventTimelineSet): void => { private onRoomTimelineReset = (room: Room | undefined, timelineSet: EventTimelineSet): void => {
if (timelineSet !== this.props.timelineSet && timelineSet !== this.props.overlayTimelineSet) return; if (timelineSet !== this.props.timelineSet) return;
if (this.canResetTimeline()) { if (this.canResetTimeline()) {
this.loadTimeline(); this.loadTimeline();
@@ -1475,48 +1413,6 @@ class TimelinePanel extends React.Component<IProps, IState> {
}); });
} }
private async extendOverlayWindowToCoverMainWindow(): Promise<void> {
const mainWindow = this.timelineWindow!;
const overlayWindow = this.overlayTimelineWindow!;
const mainEvents = mainWindow.getEvents();
if (mainEvents.length > 0) {
let paginationRequests: Promise<unknown>[];
// Keep paginating until the main window is covered
do {
paginationRequests = [];
const overlayEvents = overlayWindow.getEvents();
if (
overlayWindow.canPaginate(EventTimeline.BACKWARDS) &&
(overlayEvents.length === 0 ||
overlaysAfter(overlayEvents[0], mainEvents[0]) ||
!mainWindow.canPaginate(EventTimeline.BACKWARDS))
) {
// Paginating backwards could reveal more events to be overlaid in the main window
paginationRequests.push(
this.onPaginationRequest(overlayWindow, EventTimeline.BACKWARDS, PAGINATE_SIZE),
);
}
if (
overlayWindow.canPaginate(EventTimeline.FORWARDS) &&
(overlayEvents.length === 0 ||
overlaysBefore(overlayEvents.at(-1)!, mainEvents.at(-1)!) ||
!mainWindow.canPaginate(EventTimeline.FORWARDS))
) {
// Paginating forwards could reveal more events to be overlaid in the main window
paginationRequests.push(
this.onPaginationRequest(overlayWindow, EventTimeline.FORWARDS, PAGINATE_SIZE),
);
}
await Promise.all(paginationRequests);
} while (paginationRequests.length > 0);
}
}
/** /**
* (re)-load the event timeline, and initialise the scroll state, centered * (re)-load the event timeline, and initialise the scroll state, centered
* around the given event. * around the given event.
@@ -1536,9 +1432,6 @@ class TimelinePanel extends React.Component<IProps, IState> {
private loadTimeline(eventId?: string, pixelOffset?: number, offsetBase?: number, scrollIntoView = true): void { private loadTimeline(eventId?: string, pixelOffset?: number, offsetBase?: number, scrollIntoView = true): void {
const cli = MatrixClientPeg.safeGet(); const cli = MatrixClientPeg.safeGet();
this.timelineWindow = new TimelineWindow(cli, this.props.timelineSet, { windowLimit: this.props.timelineCap }); this.timelineWindow = new TimelineWindow(cli, this.props.timelineSet, { windowLimit: this.props.timelineCap });
this.overlayTimelineWindow = this.props.overlayTimelineSet
? new TimelineWindow(cli, this.props.overlayTimelineSet, { windowLimit: this.props.timelineCap })
: undefined;
const onLoaded = (): void => { const onLoaded = (): void => {
if (this.unmounted) return; if (this.unmounted) return;
@@ -1554,14 +1447,8 @@ class TimelinePanel extends React.Component<IProps, IState> {
this.setState( this.setState(
{ {
canBackPaginate: canBackPaginate: this.timelineWindow?.canPaginate(EventTimeline.BACKWARDS) ?? false,
(this.timelineWindow?.canPaginate(EventTimeline.BACKWARDS) || canForwardPaginate: this.timelineWindow?.canPaginate(EventTimeline.FORWARDS) ?? false,
this.overlayTimelineWindow?.canPaginate(EventTimeline.BACKWARDS)) ??
false,
canForwardPaginate:
(this.timelineWindow?.canPaginate(EventTimeline.FORWARDS) ||
this.overlayTimelineWindow?.canPaginate(EventTimeline.FORWARDS)) ??
false,
timelineLoading: false, timelineLoading: false,
}, },
() => { () => {
@@ -1636,7 +1523,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
// This is a hot-path optimization by skipping a promise tick // This is a hot-path optimization by skipping a promise tick
// by repeating a no-op sync branch in // by repeating a no-op sync branch in
// TimelineSet.getTimelineForEvent & MatrixClient.getEventTimeline // TimelineSet.getTimelineForEvent & MatrixClient.getEventTimeline
if (this.props.timelineSet.getTimelineForEvent(eventId) && !this.overlayTimelineWindow) { if (this.props.timelineSet.getTimelineForEvent(eventId)) {
// if we've got an eventId, and the timeline exists, we can skip // if we've got an eventId, and the timeline exists, we can skip
// the promise tick. // the promise tick.
this.timelineWindow.load(eventId, INITIAL_SIZE); this.timelineWindow.load(eventId, INITIAL_SIZE);
@@ -1645,14 +1532,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
return; return;
} }
const prom = this.timelineWindow.load(eventId, INITIAL_SIZE).then(async (): Promise<void> => { const prom = this.timelineWindow.load(eventId, INITIAL_SIZE);
if (this.overlayTimelineWindow) {
// TODO: use timestampToEvent to load the overlay timeline
// with more correct position when main TL eventId is truthy
await this.overlayTimelineWindow.load(undefined, INITIAL_SIZE);
await this.extendOverlayWindowToCoverMainWindow();
}
});
this.buildLegacyCallEventGroupers(); this.buildLegacyCallEventGroupers();
this.setState({ this.setState({
events: [], events: [],
@@ -1683,38 +1563,9 @@ class TimelinePanel extends React.Component<IProps, IState> {
this.reloadEvents(); this.reloadEvents();
} }
// get the list of events from the timeline windows and the pending event list // get the list of events from the timeline window and the pending event list
private getEvents(): Pick<IState, "events" | "liveEvents"> { private getEvents(): Pick<IState, "events" | "liveEvents"> {
const mainEvents = this.timelineWindow!.getEvents(); const events = this.timelineWindow!.getEvents();
let overlayEvents = this.overlayTimelineWindow?.getEvents() ?? [];
if (this.props.overlayTimelineSetFilter !== undefined) {
overlayEvents = overlayEvents.filter(this.props.overlayTimelineSetFilter);
}
// maintain the main timeline event order as returned from the HS
// merge overlay events at approximately the right position based on local timestamp
const events = overlayEvents.reduce(
(acc: MatrixEvent[], overlayEvent: MatrixEvent) => {
// find the first main tl event with a later timestamp
const index = acc.findIndex((event) => overlaysBefore(overlayEvent, event));
// insert overlay event into timeline at approximately the right place
// if it's beyond the edge of the main window, hide it so that expanding
// the main window doesn't cause new events to pop in and change its position
if (index === -1) {
if (!this.timelineWindow!.canPaginate(EventTimeline.FORWARDS)) {
acc.push(overlayEvent);
}
} else if (index === 0) {
if (!this.timelineWindow!.canPaginate(EventTimeline.BACKWARDS)) {
acc.unshift(overlayEvent);
}
} else {
acc.splice(index, 0, overlayEvent);
}
return acc;
},
[...mainEvents],
);
// We want the last event to be decrypted first // We want the last event to be decrypted first
const client = MatrixClientPeg.safeGet(); const client = MatrixClientPeg.safeGet();

View File

@@ -66,12 +66,18 @@ export function useRoomListItemViewModel(room: Room): RoomListItemViewState {
const roomTags = useEventEmitterState(room, RoomEvent.Tags, () => room.tags); const roomTags = useEventEmitterState(room, RoomEvent.Tags, () => room.tags);
const isArchived = Boolean(roomTags[DefaultTagID.Archived]); const isArchived = Boolean(roomTags[DefaultTagID.Archived]);
const showHoverMenu =
hasAccessToOptionsMenu(room) || hasAccessToNotificationMenu(room, matrixClient.isGuest(), isArchived);
const notificationState = useMemo(() => RoomNotificationStateStore.instance.getRoomState(room), [room]); const notificationState = useMemo(() => RoomNotificationStateStore.instance.getRoomState(room), [room]);
const invited = notificationState.invited;
const a11yLabel = getA11yLabel(room, notificationState); const a11yLabel = getA11yLabel(room, notificationState);
const isBold = notificationState.hasAnyNotificationOrActivity; const isBold = notificationState.hasAnyNotificationOrActivity;
// We don't want to show the hover menu if
// - there is an invitation for this room
// - the user doesn't have access to both notification and more options menus
const showHoverMenu =
!invited &&
(hasAccessToOptionsMenu(room) || hasAccessToNotificationMenu(room, matrixClient.isGuest(), isArchived));
// Video room // Video room
const isVideoRoom = room.isElementVideoRoom() || room.isCallRoom(); const isVideoRoom = room.isElementVideoRoom() || room.isCallRoom();
// EC video call or video room // EC video call or video room

View File

@@ -10,6 +10,7 @@ import MentionIcon from "@vector-im/compound-design-tokens/assets/web/icons/ment
import ErrorIcon from "@vector-im/compound-design-tokens/assets/web/icons/error-solid"; import ErrorIcon from "@vector-im/compound-design-tokens/assets/web/icons/error-solid";
import NotificationOffIcon from "@vector-im/compound-design-tokens/assets/web/icons/notifications-off-solid"; import NotificationOffIcon from "@vector-im/compound-design-tokens/assets/web/icons/notifications-off-solid";
import VideoCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/video-call-solid"; import VideoCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/video-call-solid";
import EmailIcon from "@vector-im/compound-design-tokens/assets/web/icons/email-solid";
import { UnreadCounter, Unread } from "@vector-im/compound-web"; import { UnreadCounter, Unread } from "@vector-im/compound-web";
import { Flex } from "../../utils/Flex"; import { Flex } from "../../utils/Flex";
@@ -56,7 +57,7 @@ export function NotificationDecoration({
> >
{isUnsetMessage && <ErrorIcon width="20px" height="20px" fill="var(--cpd-color-icon-critical-primary)" />} {isUnsetMessage && <ErrorIcon width="20px" height="20px" fill="var(--cpd-color-icon-critical-primary)" />}
{hasVideoCall && <VideoCallIcon width="20px" height="20px" fill="var(--cpd-color-icon-accent-primary)" />} {hasVideoCall && <VideoCallIcon width="20px" height="20px" fill="var(--cpd-color-icon-accent-primary)" />}
{invited && <UnreadCounter count={1} />} {invited && <EmailIcon width="20px" height="20px" fill="var(--cpd-color-icon-accent-primary)" />}
{isMention && <MentionIcon width="20px" height="20px" fill="var(--cpd-color-icon-accent-primary)" />} {isMention && <MentionIcon width="20px" height="20px" fill="var(--cpd-color-icon-accent-primary)" />}
{(isMention || isNotification) && <UnreadCounter count={count || null} />} {(isMention || isNotification) && <UnreadCounter count={count || null} />}
{isActivityNotification && <Unread />} {isActivityNotification && <Unread />}

View File

@@ -28,7 +28,6 @@ import { _t, UserFriendlyError } from "./languageHandler";
import dis from "./dispatcher/dispatcher"; import dis from "./dispatcher/dispatcher";
import * as Rooms from "./Rooms"; import * as Rooms from "./Rooms";
import { getAddressType } from "./UserAddress"; import { getAddressType } from "./UserAddress";
import { VIRTUAL_ROOM_EVENT_TYPE } from "./call-types";
import SpaceStore from "./stores/spaces/SpaceStore"; import SpaceStore from "./stores/spaces/SpaceStore";
import { makeSpaceParentEvent } from "./utils/space"; import { makeSpaceParentEvent } from "./utils/space";
import { JitsiCall, ElementCall } from "./models/Call"; import { JitsiCall, ElementCall } from "./models/Call";
@@ -423,36 +422,6 @@ export async function canEncryptToAllUsers(client: MatrixClient, userIds: string
return true; return true;
} }
// Similar to ensureDMExists but also adds creation content
// without polluting ensureDMExists with unrelated stuff (also
// they're never encrypted).
export async function ensureVirtualRoomExists(
client: MatrixClient,
userId: string,
nativeRoomId: string,
): Promise<string | null> {
const existingDMRoom = findDMForUser(client, userId);
let roomId: string | null;
if (existingDMRoom) {
roomId = existingDMRoom.roomId;
} else {
roomId = await createRoom(client, {
dmUserId: userId,
spinner: false,
andView: false,
createOpts: {
creation_content: {
// This allows us to recognise that the room is a virtual room
// when it comes down our sync stream (we also put the ID of the
// respective native room in there because why not?)
[VIRTUAL_ROOM_EVENT_TYPE]: nativeRoomId,
},
},
});
}
return roomId;
}
export async function ensureDMExists(client: MatrixClient, userId: string): Promise<string | null> { export async function ensureDMExists(client: MatrixClient, userId: string): Promise<string | null> {
const existingDMRoom = findDMForUser(client, userId); const existingDMRoom = findDMForUser(client, userId);
let roomId: string | null; let roomId: string | null;

View File

@@ -3093,8 +3093,6 @@
"topic": "Gets or sets the room topic", "topic": "Gets or sets the room topic",
"topic_none": "This room has no topic.", "topic_none": "This room has no topic.",
"topic_room_error": "Failed to get room topic: Unable to find room (%(roomId)s", "topic_room_error": "Failed to get room topic: Unable to find room (%(roomId)s",
"tovirtual": "Switches to this room's virtual room, if it has one",
"tovirtual_not_found": "No virtual room for this room",
"unban": "Unbans user with given ID", "unban": "Unbans user with given ID",
"unflip": "Prepends ┬──┬ ( ゜-゜ノ) to a plain-text message", "unflip": "Prepends ┬──┬ ( ゜-゜ノ) to a plain-text message",
"unholdcall": "Takes the call in the current room off hold", "unholdcall": "Takes the call in the current room off hold",

View File

@@ -7,7 +7,6 @@ Please see LICENSE files in the repository root for full details.
*/ */
import { type MatrixClient, type Room, type RoomState, EventType, type EmptyObject } from "matrix-js-sdk/src/matrix"; import { type MatrixClient, type Room, type RoomState, EventType, type EmptyObject } from "matrix-js-sdk/src/matrix";
import { KnownMembership } from "matrix-js-sdk/src/types";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import SettingsStore from "../../settings/SettingsStore"; import SettingsStore from "../../settings/SettingsStore";
@@ -349,15 +348,6 @@ export class RoomListStoreClass extends AsyncStoreWithClient<EmptyObject> implem
} }
private async handleRoomUpdate(room: Room, cause: RoomUpdateCause): Promise<any> { private async handleRoomUpdate(room: Room, cause: RoomUpdateCause): Promise<any> {
if (cause === RoomUpdateCause.NewRoom && room.getMyMembership() === KnownMembership.Invite) {
// Let the visibility provider know that there is a new invited room. It would be nice
// if this could just be an event that things listen for but the point of this is that
// we delay doing anything about this room until the VoipUserMapper had had a chance
// to do the things it needs to do to decide if we should show this room or not, so
// an even wouldn't et us do that.
await VisibilityProvider.instance.onNewInvitedRoom(room);
}
if (!VisibilityProvider.instance.isRoomVisible(room)) { if (!VisibilityProvider.instance.isRoomVisible(room)) {
return; // don't do anything on rooms that aren't visible return; // don't do anything on rooms that aren't visible
} }

View File

@@ -8,10 +8,8 @@
import { type Room } from "matrix-js-sdk/src/matrix"; import { type Room } from "matrix-js-sdk/src/matrix";
import LegacyCallHandler from "../../../LegacyCallHandler";
import { RoomListCustomisations } from "../../../customisations/RoomList"; import { RoomListCustomisations } from "../../../customisations/RoomList";
import { isLocalRoom } from "../../../utils/localRoom/isLocalRoom"; import { isLocalRoom } from "../../../utils/localRoom/isLocalRoom";
import VoipUserMapper from "../../../VoipUserMapper";
export class VisibilityProvider { export class VisibilityProvider {
private static internalInstance: VisibilityProvider; private static internalInstance: VisibilityProvider;
@@ -25,22 +23,11 @@ export class VisibilityProvider {
return VisibilityProvider.internalInstance; return VisibilityProvider.internalInstance;
} }
public async onNewInvitedRoom(room: Room): Promise<void> {
await VoipUserMapper.sharedInstance().onNewInvitedRoom(room);
}
public isRoomVisible(room?: Room): boolean { public isRoomVisible(room?: Room): boolean {
if (!room) { if (!room) {
return false; return false;
} }
if (
LegacyCallHandler.instance.getSupportsVirtualRooms() &&
VoipUserMapper.sharedInstance().isVirtualRoom(room)
) {
return false;
}
// hide space rooms as they'll be shown in the SpacePanel // hide space rooms as they'll be shown in the SpacePanel
if (room.isSpaceRoom()) { if (room.isSpaceRoom()) {
return false; return false;

View File

@@ -29,8 +29,6 @@ import LegacyCallHandler, {
LegacyCallHandlerEvent, LegacyCallHandlerEvent,
PROTOCOL_PSTN, PROTOCOL_PSTN,
PROTOCOL_PSTN_PREFIXED, PROTOCOL_PSTN_PREFIXED,
PROTOCOL_SIP_NATIVE,
PROTOCOL_SIP_VIRTUAL,
} from "../../src/LegacyCallHandler"; } from "../../src/LegacyCallHandler";
import { mkStubRoom, stubClient, untilDispatch } from "../test-utils"; import { mkStubRoom, stubClient, untilDispatch } from "../test-utils";
import { MatrixClientPeg } from "../../src/MatrixClientPeg"; import { MatrixClientPeg } from "../../src/MatrixClientPeg";
@@ -75,9 +73,6 @@ const NATIVE_ALICE = "@alice:example.org";
const NATIVE_BOB = "@bob:example.org"; const NATIVE_BOB = "@bob:example.org";
const NATIVE_CHARLIE = "@charlie:example.org"; const NATIVE_CHARLIE = "@charlie:example.org";
// Virtual user for Bob
const VIRTUAL_BOB = "@virtual_bob:example.org";
//const REAL_ROOM_ID = "$room1:example.org"; //const REAL_ROOM_ID = "$room1:example.org";
// The rooms the user sees when they're communicating with these users // The rooms the user sees when they're communicating with these users
const NATIVE_ROOM_ALICE = "$alice_room:example.org"; const NATIVE_ROOM_ALICE = "$alice_room:example.org";
@@ -86,10 +81,6 @@ const NATIVE_ROOM_CHARLIE = "$charlie_room:example.org";
const FUNCTIONAL_USER = "@bot:example.com"; const FUNCTIONAL_USER = "@bot:example.com";
// The room we use to talk to virtual Bob (but that the user does not see)
// Bob has a virtual room, but Alice doesn't
const VIRTUAL_ROOM_BOB = "$virtual_bob_room:example.org";
// Bob's phone number // Bob's phone number
const BOB_PHONE_NUMBER = "01818118181"; const BOB_PHONE_NUMBER = "01818118181";
@@ -146,14 +137,6 @@ class FakeCall extends EventEmitter {
} }
} }
function untilCallHandlerEvent(callHandler: LegacyCallHandler, event: LegacyCallHandlerEvent): Promise<void> {
return new Promise<void>((resolve) => {
callHandler.addListener(event, () => {
resolve();
});
});
}
describe("LegacyCallHandler", () => { describe("LegacyCallHandler", () => {
let dmRoomMap; let dmRoomMap;
let callHandler: LegacyCallHandler; let callHandler: LegacyCallHandler;
@@ -162,7 +145,6 @@ describe("LegacyCallHandler", () => {
// what addresses the app has looked up via pstn and native lookup // what addresses the app has looked up via pstn and native lookup
let pstnLookup: string | null; let pstnLookup: string | null;
let nativeLookup: string | null;
const deviceId = "my-device"; const deviceId = "my-device";
beforeEach(async () => { beforeEach(async () => {
@@ -180,8 +162,6 @@ describe("LegacyCallHandler", () => {
MatrixClientPeg.safeGet().getThirdpartyProtocols = () => { MatrixClientPeg.safeGet().getThirdpartyProtocols = () => {
return Promise.resolve({ return Promise.resolve({
"m.id.phone": {} as IProtocol, "m.id.phone": {} as IProtocol,
"im.vector.protocol.sip_native": {} as IProtocol,
"im.vector.protocol.sip_virtual": {} as IProtocol,
}); });
}; };
@@ -193,7 +173,6 @@ describe("LegacyCallHandler", () => {
const nativeRoomAlice = mkStubDM(NATIVE_ROOM_ALICE, NATIVE_ALICE); const nativeRoomAlice = mkStubDM(NATIVE_ROOM_ALICE, NATIVE_ALICE);
const nativeRoomBob = mkStubDM(NATIVE_ROOM_BOB, NATIVE_BOB); const nativeRoomBob = mkStubDM(NATIVE_ROOM_BOB, NATIVE_BOB);
const nativeRoomCharie = mkStubDM(NATIVE_ROOM_CHARLIE, NATIVE_CHARLIE); const nativeRoomCharie = mkStubDM(NATIVE_ROOM_CHARLIE, NATIVE_CHARLIE);
const virtualBobRoom = mkStubDM(VIRTUAL_ROOM_BOB, VIRTUAL_BOB);
MatrixClientPeg.safeGet().getRoom = (roomId: string): Room | null => { MatrixClientPeg.safeGet().getRoom = (roomId: string): Room | null => {
switch (roomId) { switch (roomId) {
@@ -203,8 +182,6 @@ describe("LegacyCallHandler", () => {
return nativeRoomBob; return nativeRoomBob;
case NATIVE_ROOM_CHARLIE: case NATIVE_ROOM_CHARLIE:
return nativeRoomCharie; return nativeRoomCharie;
case VIRTUAL_ROOM_BOB:
return virtualBobRoom;
} }
return null; return null;
@@ -218,8 +195,6 @@ describe("LegacyCallHandler", () => {
return NATIVE_BOB; return NATIVE_BOB;
} else if (roomId === NATIVE_ROOM_CHARLIE) { } else if (roomId === NATIVE_ROOM_CHARLIE) {
return NATIVE_CHARLIE; return NATIVE_CHARLIE;
} else if (roomId === VIRTUAL_ROOM_BOB) {
return VIRTUAL_BOB;
} else { } else {
return null; return null;
} }
@@ -231,8 +206,6 @@ describe("LegacyCallHandler", () => {
return [NATIVE_ROOM_BOB]; return [NATIVE_ROOM_BOB];
} else if (userId === NATIVE_CHARLIE) { } else if (userId === NATIVE_CHARLIE) {
return [NATIVE_ROOM_CHARLIE]; return [NATIVE_ROOM_CHARLIE];
} else if (userId === VIRTUAL_BOB) {
return [VIRTUAL_ROOM_BOB];
} else { } else {
return []; return [];
} }
@@ -241,52 +214,18 @@ describe("LegacyCallHandler", () => {
DMRoomMap.setShared(dmRoomMap); DMRoomMap.setShared(dmRoomMap);
pstnLookup = null; pstnLookup = null;
nativeLookup = null;
MatrixClientPeg.safeGet().getThirdpartyUser = (proto: string, params: any) => { MatrixClientPeg.safeGet().getThirdpartyUser = (proto: string, params: any) => {
if ([PROTOCOL_PSTN, PROTOCOL_PSTN_PREFIXED].includes(proto)) { if ([PROTOCOL_PSTN, PROTOCOL_PSTN_PREFIXED].includes(proto)) {
pstnLookup = params["m.id.phone"]; pstnLookup = params["m.id.phone"];
return Promise.resolve([ return Promise.resolve([
{ {
userid: VIRTUAL_BOB, userid: NATIVE_BOB,
protocol: "m.id.phone", protocol: "m.id.phone",
fields: { fields: {},
is_native: true,
lookup_success: true,
},
}, },
]); ]);
} else if (proto === PROTOCOL_SIP_NATIVE) {
nativeLookup = params["virtual_mxid"];
if (params["virtual_mxid"] === VIRTUAL_BOB) {
return Promise.resolve([
{
userid: NATIVE_BOB,
protocol: "im.vector.protocol.sip_native",
fields: {
is_native: true,
lookup_success: true,
},
},
]);
}
return Promise.resolve([]);
} else if (proto === PROTOCOL_SIP_VIRTUAL) {
if (params["native_mxid"] === NATIVE_BOB) {
return Promise.resolve([
{
userid: VIRTUAL_BOB,
protocol: "im.vector.protocol.sip_virtual",
fields: {
is_virtual: true,
lookup_success: true,
},
},
]);
}
return Promise.resolve([]);
} }
return Promise.resolve([]); return Promise.resolve([]);
}; };
@@ -312,16 +251,14 @@ describe("LegacyCallHandler", () => {
await callHandler.dialNumber(BOB_PHONE_NUMBER); await callHandler.dialNumber(BOB_PHONE_NUMBER);
expect(pstnLookup).toEqual(BOB_PHONE_NUMBER); expect(pstnLookup).toEqual(BOB_PHONE_NUMBER);
expect(nativeLookup).toEqual(VIRTUAL_BOB);
// we should have switched to the native room for Bob // we should have switched to the native room for Bob
const viewRoomPayload = await untilDispatch(Action.ViewRoom); const viewRoomPayload = await untilDispatch(Action.ViewRoom);
expect(viewRoomPayload.room_id).toEqual(NATIVE_ROOM_BOB); expect(viewRoomPayload.room_id).toEqual(NATIVE_ROOM_BOB);
// Check that a call was started: its room on the protocol level // Check that a call was started: its room on the protocol level
// should be the virtual room
expect(fakeCall).not.toBeNull(); expect(fakeCall).not.toBeNull();
expect(fakeCall?.roomId).toEqual(VIRTUAL_ROOM_BOB); expect(fakeCall?.roomId).toEqual(NATIVE_ROOM_BOB);
// but it should appear to the user to be in thw native room for Bob // but it should appear to the user to be in thw native room for Bob
expect(callHandler.roomIdForCall(fakeCall!)).toEqual(NATIVE_ROOM_BOB); expect(callHandler.roomIdForCall(fakeCall!)).toEqual(NATIVE_ROOM_BOB);
@@ -338,7 +275,7 @@ describe("LegacyCallHandler", () => {
expect(viewRoomPayload.room_id).toEqual(NATIVE_ROOM_BOB); expect(viewRoomPayload.room_id).toEqual(NATIVE_ROOM_BOB);
expect(fakeCall).not.toBeNull(); expect(fakeCall).not.toBeNull();
expect(fakeCall!.roomId).toEqual(VIRTUAL_ROOM_BOB); expect(fakeCall!.roomId).toEqual(NATIVE_ROOM_BOB);
expect(callHandler.roomIdForCall(fakeCall!)).toEqual(NATIVE_ROOM_BOB); expect(callHandler.roomIdForCall(fakeCall!)).toEqual(NATIVE_ROOM_BOB);
}); });
@@ -346,8 +283,6 @@ describe("LegacyCallHandler", () => {
it("should move calls between rooms when remote asserted identity changes", async () => { it("should move calls between rooms when remote asserted identity changes", async () => {
callHandler.placeCall(NATIVE_ROOM_ALICE, CallType.Voice); callHandler.placeCall(NATIVE_ROOM_ALICE, CallType.Voice);
await untilCallHandlerEvent(callHandler, LegacyCallHandlerEvent.CallState);
// We placed the call in Alice's room so it should start off there // We placed the call in Alice's room so it should start off there
expect(callHandler.getCallForRoom(NATIVE_ROOM_ALICE)).toBe(fakeCall); expect(callHandler.getCallForRoom(NATIVE_ROOM_ALICE)).toBe(fakeCall);
@@ -517,10 +452,7 @@ describe("LegacyCallHandler without third party protocols", () => {
it("should still start a native call", async () => { it("should still start a native call", async () => {
callHandler.placeCall(NATIVE_ROOM_ALICE, CallType.Voice); callHandler.placeCall(NATIVE_ROOM_ALICE, CallType.Voice);
await untilCallHandlerEvent(callHandler, LegacyCallHandlerEvent.CallState);
// Check that a call was started: its room on the protocol level // Check that a call was started: its room on the protocol level
// should be the virtual room
expect(fakeCall).not.toBeNull(); expect(fakeCall).not.toBeNull();
expect(fakeCall!.roomId).toEqual(NATIVE_ROOM_ALICE); expect(fakeCall!.roomId).toEqual(NATIVE_ROOM_ALICE);

View File

@@ -14,7 +14,6 @@ import { type Command, Commands, getCommand } from "../../src/SlashCommands";
import { createTestClient } from "../test-utils"; import { createTestClient } from "../test-utils";
import { LocalRoom, LOCAL_ROOM_ID_PREFIX } from "../../src/models/LocalRoom"; import { LocalRoom, LOCAL_ROOM_ID_PREFIX } from "../../src/models/LocalRoom";
import SettingsStore from "../../src/settings/SettingsStore"; import SettingsStore from "../../src/settings/SettingsStore";
import LegacyCallHandler from "../../src/LegacyCallHandler";
import { SdkContextClass } from "../../src/contexts/SDKContext"; import { SdkContextClass } from "../../src/contexts/SDKContext";
import Modal from "../../src/Modal"; import Modal from "../../src/Modal";
import WidgetUtils from "../../src/utils/WidgetUtils"; import WidgetUtils from "../../src/utils/WidgetUtils";
@@ -196,46 +195,6 @@ describe("SlashCommands", () => {
}); });
}); });
describe("/tovirtual", () => {
beforeEach(() => {
command = findCommand("tovirtual")!;
});
describe("isEnabled", () => {
describe("when virtual rooms are supported", () => {
beforeEach(() => {
jest.spyOn(LegacyCallHandler.instance, "getSupportsVirtualRooms").mockReturnValue(true);
});
it("should return true for Room", () => {
setCurrentRoom();
expect(command.isEnabled(client)).toBe(true);
});
it("should return false for LocalRoom", () => {
setCurrentLocalRoom();
expect(command.isEnabled(client)).toBe(false);
});
});
describe("when virtual rooms are not supported", () => {
beforeEach(() => {
jest.spyOn(LegacyCallHandler.instance, "getSupportsVirtualRooms").mockReturnValue(false);
});
it("should return false for Room", () => {
setCurrentRoom();
expect(command.isEnabled(client)).toBe(false);
});
it("should return false for LocalRoom", () => {
setCurrentLocalRoom();
expect(command.isEnabled(client)).toBe(false);
});
});
});
});
describe("/part", () => { describe("/part", () => {
it("should part room matching alias if found", async () => { it("should part room matching alias if found", async () => {
const room1 = new Room("room-id", client, client.getSafeUserId()); const room1 = new Room("room-id", client, client.getSafeUserId());

View File

@@ -9,7 +9,6 @@ Please see LICENSE files in the repository root for full details.
import React, { createRef, type RefObject } from "react"; import React, { createRef, type RefObject } from "react";
import { mocked, type MockedObject } from "jest-mock"; import { mocked, type MockedObject } from "jest-mock";
import { import {
ClientEvent,
EventTimeline, EventTimeline,
EventType, EventType,
type IEvent, type IEvent,
@@ -68,7 +67,6 @@ import { DirectoryMember } from "../../../../src/utils/direct-messages";
import { createDmLocalRoom } from "../../../../src/utils/dm/createDmLocalRoom"; import { createDmLocalRoom } from "../../../../src/utils/dm/createDmLocalRoom";
import { UPDATE_EVENT } from "../../../../src/stores/AsyncStore"; import { UPDATE_EVENT } from "../../../../src/stores/AsyncStore";
import { SDKContext, SdkContextClass } from "../../../../src/contexts/SDKContext"; import { SDKContext, SdkContextClass } from "../../../../src/contexts/SDKContext";
import VoipUserMapper from "../../../../src/VoipUserMapper";
import WidgetUtils from "../../../../src/utils/WidgetUtils"; import WidgetUtils from "../../../../src/utils/WidgetUtils";
import { WidgetType } from "../../../../src/widgets/WidgetType"; import { WidgetType } from "../../../../src/widgets/WidgetType";
import WidgetStore from "../../../../src/stores/WidgetStore"; import WidgetStore from "../../../../src/stores/WidgetStore";
@@ -119,7 +117,6 @@ describe("RoomView", () => {
stores.client = cli; stores.client = cli;
stores.rightPanelStore.useUnitTestClient(cli); stores.rightPanelStore.useUnitTestClient(cli);
jest.spyOn(VoipUserMapper.sharedInstance(), "getVirtualRoomForRoom").mockResolvedValue(undefined);
crypto = cli.getCrypto()!; crypto = cli.getCrypto()!;
jest.spyOn(cli, "getCrypto").mockReturnValue(undefined); jest.spyOn(cli, "getCrypto").mockReturnValue(undefined);
}); });
@@ -417,26 +414,6 @@ describe("RoomView", () => {
await waitFor(() => expect(container.querySelector(".mx_E2EIcon_verified")).toBeInTheDocument()); await waitFor(() => expect(container.querySelector(".mx_E2EIcon_verified")).toBeInTheDocument());
}); });
describe("with virtual rooms", () => {
it("checks for a virtual room on initial load", async () => {
const { container } = await renderRoomView();
expect(VoipUserMapper.sharedInstance().getVirtualRoomForRoom).toHaveBeenCalledWith(room.roomId);
// quick check that rendered without error
expect(container.querySelector(".mx_ErrorBoundary")).toBeFalsy();
});
it("checks for a virtual room on room event", async () => {
await renderRoomView();
expect(VoipUserMapper.sharedInstance().getVirtualRoomForRoom).toHaveBeenCalledWith(room.roomId);
act(() => cli.emit(ClientEvent.Room, room));
// called again after room event
expect(VoipUserMapper.sharedInstance().getVirtualRoomForRoom).toHaveBeenCalledTimes(2);
});
});
describe("video rooms", () => { describe("video rooms", () => {
beforeEach(async () => { beforeEach(async () => {
await setupAsyncStoreWithClient(CallStore.instance, MatrixClientPeg.safeGet()); await setupAsyncStoreWithClient(CallStore.instance, MatrixClientPeg.safeGet());

View File

@@ -35,7 +35,6 @@ import { forEachRight } from "lodash";
import TimelinePanel from "../../../../src/components/structures/TimelinePanel"; import TimelinePanel from "../../../../src/components/structures/TimelinePanel";
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext"; import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
import { isCallEvent } from "../../../../src/components/structures/LegacyCallEventGrouper";
import { import {
filterConsole, filterConsole,
flushPromises, flushPromises,
@@ -115,22 +114,6 @@ const setupTestData = (): [MatrixClient, Room, MatrixEvent[]] => {
return [client, room, events]; return [client, room, events];
}; };
const setupOverlayTestData = (client: MatrixClient, mainEvents: MatrixEvent[]): [Room, MatrixEvent[]] => {
const virtualRoom = mkRoom(client, "virtualRoomId");
const overlayEvents = mockEvents(virtualRoom, 5);
// Set the event order that we'll be looking for in the timeline
overlayEvents[0].localTimestamp = 1000;
mainEvents[0].localTimestamp = 2000;
overlayEvents[1].localTimestamp = 3000;
overlayEvents[2].localTimestamp = 4000;
overlayEvents[3].localTimestamp = 5000;
mainEvents[1].localTimestamp = 6000;
overlayEvents[4].localTimestamp = 7000;
return [virtualRoom, overlayEvents];
};
const expectEvents = (container: HTMLElement, events: MatrixEvent[]): void => { const expectEvents = (container: HTMLElement, events: MatrixEvent[]): void => {
const eventTiles = container.querySelectorAll(".mx_EventTile"); const eventTiles = container.querySelectorAll(".mx_EventTile");
const eventTileIds = [...eventTiles].map((tileElement) => tileElement.getAttribute("data-event-id")); const eventTileIds = [...eventTiles].map((tileElement) => tileElement.getAttribute("data-event-id"));
@@ -518,298 +501,6 @@ describe("TimelinePanel", () => {
expect(paginateSpy).toHaveBeenCalledWith(EventTimeline.FORWARDS, 1, false); expect(paginateSpy).toHaveBeenCalledWith(EventTimeline.FORWARDS, 1, false);
}); });
it("advances the overlay timeline window", async () => {
const [client, room, events] = setupTestData();
const virtualRoom = mkRoom(client, "virtualRoomId");
const virtualEvents = mockEvents(virtualRoom);
const { timelineSet: overlayTimelineSet } = getProps(virtualRoom, virtualEvents);
const props = {
...getProps(room, events),
overlayTimelineSet,
};
const paginateSpy = jest.spyOn(TimelineWindow.prototype, "paginate").mockClear();
render(<TimelinePanel {...props} />);
await flushPromises();
const event = new MatrixEvent({ type: RoomEvent.Timeline, origin_server_ts: 0 });
const data = { timeline: props.timelineSet.getLiveTimeline(), liveEvent: true };
client.emit(RoomEvent.Timeline, event, room, false, false, data);
await flushPromises();
expect(paginateSpy).toHaveBeenCalledTimes(2);
});
});
describe("with overlayTimeline", () => {
it("renders merged timeline", async () => {
const [client, room, events] = setupTestData();
const virtualRoom = mkRoom(client, "virtualRoomId");
const virtualCallInvite = new MatrixEvent({
type: "m.call.invite",
room_id: virtualRoom.roomId,
event_id: `virtualCallEvent1`,
origin_server_ts: 0,
});
virtualCallInvite.localTimestamp = 2;
const virtualCallMetaEvent = new MatrixEvent({
type: "org.matrix.call.sdp_stream_metadata_changed",
room_id: virtualRoom.roomId,
event_id: `virtualCallEvent2`,
origin_server_ts: 0,
});
virtualCallMetaEvent.localTimestamp = 2;
const virtualEvents = [virtualCallInvite, ...mockEvents(virtualRoom), virtualCallMetaEvent];
const { timelineSet: overlayTimelineSet } = getProps(virtualRoom, virtualEvents);
const { container } = render(
<TimelinePanel
{...getProps(room, events)}
overlayTimelineSet={overlayTimelineSet}
overlayTimelineSetFilter={isCallEvent}
/>,
withClientContextRenderOptions(MatrixClientPeg.safeGet()),
);
await waitFor(() =>
expectEvents(container, [
// main timeline events are included
events[0],
events[1],
// virtual timeline call event is included
virtualCallInvite,
// virtual call event has no tile renderer => not rendered
]),
);
});
it.each([
["when it starts with no overlay events", true],
["to get enough overlay events", false],
])("expands the initial window %s", async (_s, startWithEmptyOverlayWindow) => {
const [client, room, events] = setupTestData();
const [virtualRoom, overlayEvents] = setupOverlayTestData(client, events);
let overlayEventsPage1: MatrixEvent[];
let overlayEventsPage2: MatrixEvent[];
let overlayEventsPage3: MatrixEvent[];
if (startWithEmptyOverlayWindow) {
overlayEventsPage1 = overlayEvents.slice(0, 3);
overlayEventsPage2 = [];
overlayEventsPage3 = overlayEvents.slice(3, 5);
} else {
overlayEventsPage1 = overlayEvents.slice(0, 2);
overlayEventsPage2 = overlayEvents.slice(2, 3);
overlayEventsPage3 = overlayEvents.slice(3, 5);
}
// Start with only page 2 of the overlay events in the window
const [overlayTimeline, overlayTimelineSet] = mkTimeline(virtualRoom, overlayEventsPage2);
setupPagination(client, overlayTimeline, overlayEventsPage1, overlayEventsPage3);
const { container } = render(
<TimelinePanel {...getProps(room, events)} overlayTimelineSet={overlayTimelineSet} />,
withClientContextRenderOptions(MatrixClientPeg.safeGet()),
);
await waitFor(() =>
expectEvents(container, [
overlayEvents[0],
events[0],
overlayEvents[1],
overlayEvents[2],
overlayEvents[3],
events[1],
overlayEvents[4],
]),
);
});
it("extends overlay window beyond main window at the start of the timeline", async () => {
const [client, room, events] = setupTestData();
const [virtualRoom, overlayEvents] = setupOverlayTestData(client, events);
// Delete event 0 so the TimelinePanel will still leave some stuff
// unloaded for us to test with
events.shift();
const overlayEventsPage1 = overlayEvents.slice(0, 2);
const overlayEventsPage2 = overlayEvents.slice(2, 5);
// Start with only page 2 of the overlay events in the window
const [overlayTimeline, overlayTimelineSet] = mkTimeline(virtualRoom, overlayEventsPage2);
setupPagination(client, overlayTimeline, overlayEventsPage1, null);
const { container } = render(
<TimelinePanel {...getProps(room, events)} overlayTimelineSet={overlayTimelineSet} />,
withClientContextRenderOptions(MatrixClientPeg.safeGet()),
);
await waitFor(() =>
expectEvents(container, [
// These first two are the newly loaded events
overlayEvents[0],
overlayEvents[1],
overlayEvents[2],
overlayEvents[3],
events[0],
overlayEvents[4],
]),
);
});
it("extends overlay window beyond main window at the end of the timeline", async () => {
const [client, room, events] = setupTestData();
const [virtualRoom, overlayEvents] = setupOverlayTestData(client, events);
// Delete event 1 so the TimelinePanel will still leave some stuff
// unloaded for us to test with
events.pop();
const overlayEventsPage1 = overlayEvents.slice(0, 2);
const overlayEventsPage2 = overlayEvents.slice(2, 5);
// Start with only page 1 of the overlay events in the window
const [overlayTimeline, overlayTimelineSet] = mkTimeline(virtualRoom, overlayEventsPage1);
setupPagination(client, overlayTimeline, null, overlayEventsPage2);
const { container } = render(
<TimelinePanel {...getProps(room, events)} overlayTimelineSet={overlayTimelineSet} />,
withClientContextRenderOptions(MatrixClientPeg.safeGet()),
);
await waitFor(() =>
expectEvents(container, [
overlayEvents[0],
events[0],
overlayEvents[1],
// These are the newly loaded events
overlayEvents[2],
overlayEvents[3],
overlayEvents[4],
]),
);
});
it("paginates", async () => {
const [client, room, events] = setupTestData();
const [virtualRoom, overlayEvents] = setupOverlayTestData(client, events);
const eventsPage1 = events.slice(0, 1);
const eventsPage2 = events.slice(1, 2);
// Start with only page 1 of the main events in the window
const [timeline, timelineSet] = mkTimeline(room, eventsPage1);
const [, overlayTimelineSet] = mkTimeline(virtualRoom, overlayEvents);
setupPagination(client, timeline, null, eventsPage2);
await withScrollPanelMountSpy(async (mountSpy) => {
const { container } = render(
<TimelinePanel
{...getProps(room, events)}
timelineSet={timelineSet}
overlayTimelineSet={overlayTimelineSet}
/>,
withClientContextRenderOptions(MatrixClientPeg.safeGet()),
);
await waitFor(() => expectEvents(container, [overlayEvents[0], events[0]]));
// ScrollPanel has no chance of working in jsdom, so we've no choice
// but to do some shady stuff to trigger the fill callback by hand
const scrollPanel = mountSpy.mock.contexts[0] as ScrollPanel;
scrollPanel.props.onFillRequest!(false);
await waitFor(() =>
expectEvents(container, [
overlayEvents[0],
events[0],
overlayEvents[1],
overlayEvents[2],
overlayEvents[3],
events[1],
overlayEvents[4],
]),
);
});
});
it.each([
["down", "main", true, false],
["down", "overlay", true, true],
["up", "main", false, false],
["up", "overlay", false, true],
])("unpaginates %s to an event from the %s timeline", async (_s1, _s2, backwards, fromOverlay) => {
const [client, room, events] = setupTestData();
const [virtualRoom, overlayEvents] = setupOverlayTestData(client, events);
let marker: MatrixEvent;
let expectedEvents: MatrixEvent[];
if (backwards) {
if (fromOverlay) {
marker = overlayEvents[1];
// Overlay events 01 and event 0 should be unpaginated
// Overlay events 23 should be hidden since they're at the edge of the window
expectedEvents = [events[1], overlayEvents[4]];
} else {
marker = events[0];
// Overlay event 0 and event 0 should be unpaginated
// Overlay events 13 should be hidden since they're at the edge of the window
expectedEvents = [events[1], overlayEvents[4]];
}
} else {
if (fromOverlay) {
marker = overlayEvents[4];
// Only the last overlay event should be unpaginated
expectedEvents = [
overlayEvents[0],
events[0],
overlayEvents[1],
overlayEvents[2],
overlayEvents[3],
events[1],
];
} else {
// Get rid of overlay event 4 so we can test the case where no overlay events get unpaginated
overlayEvents.pop();
marker = events[1];
// Only event 1 should be unpaginated
// Overlay events 12 should be hidden since they're at the edge of the window
expectedEvents = [overlayEvents[0], events[0]];
}
}
const [, overlayTimelineSet] = mkTimeline(virtualRoom, overlayEvents);
await withScrollPanelMountSpy(async (mountSpy) => {
const { container } = render(
<TimelinePanel {...getProps(room, events)} overlayTimelineSet={overlayTimelineSet} />,
withClientContextRenderOptions(MatrixClientPeg.safeGet()),
);
await waitFor(() =>
expectEvents(container, [
overlayEvents[0],
events[0],
overlayEvents[1],
overlayEvents[2],
overlayEvents[3],
events[1],
...(!backwards && !fromOverlay ? [] : [overlayEvents[4]]),
]),
);
// ScrollPanel has no chance of working in jsdom, so we've no choice
// but to do some shady stuff to trigger the unfill callback by hand
const scrollPanel = mountSpy.mock.contexts[0] as ScrollPanel;
scrollPanel.props.onUnfillRequest!(backwards, marker.getId()!);
await waitFor(() => expectEvents(container, expectedEvents));
});
});
}); });
describe("when a thread updates", () => { describe("when a thread updates", () => {

View File

@@ -19,7 +19,7 @@ exports[`FilePanel renders empty state 1`] = `
</p> </p>
</div> </div>
<button <button
aria-labelledby=":r0:" aria-labelledby="«r0»"
class="_icon-button_m2erp_8 _subtle-bg_m2erp_29" class="_icon-button_m2erp_8 _subtle-bg_m2erp_29"
data-testid="base-card-close-button" data-testid="base-card-close-button"
role="button" role="button"

View File

@@ -58,7 +58,7 @@ exports[`RoomView for a local room in state CREATING should match the snapshot 1
style="--cpd-icon-button-size: 100%;" style="--cpd-icon-button-size: 100%;"
> >
<svg <svg
aria-labelledby=":rg4:" aria-labelledby="«rg4»"
fill="currentColor" fill="currentColor"
height="1em" height="1em"
viewBox="0 0 24 24" viewBox="0 0 24 24"
@@ -74,7 +74,7 @@ exports[`RoomView for a local room in state CREATING should match the snapshot 1
<button <button
aria-disabled="false" aria-disabled="false"
aria-label="Voice call" aria-label="Voice call"
aria-labelledby=":rg9:" aria-labelledby="«rg9»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
@@ -99,7 +99,7 @@ exports[`RoomView for a local room in state CREATING should match the snapshot 1
</button> </button>
<button <button
aria-label="Threads" aria-label="Threads"
aria-labelledby=":rge:" aria-labelledby="«rge»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
@@ -125,7 +125,7 @@ exports[`RoomView for a local room in state CREATING should match the snapshot 1
</button> </button>
<button <button
aria-label="Room info" aria-label="Room info"
aria-labelledby=":rgj:" aria-labelledby="«rgj»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
@@ -154,7 +154,7 @@ exports[`RoomView for a local room in state CREATING should match the snapshot 1
> >
<div <div
aria-label="2 members" aria-label="2 members"
aria-labelledby=":rgo:" aria-labelledby="«rgo»"
class="mx_AccessibleButton mx_FacePile" class="mx_AccessibleButton mx_FacePile"
role="button" role="button"
tabindex="0" tabindex="0"
@@ -273,7 +273,7 @@ exports[`RoomView for a local room in state ERROR should match the snapshot 1`]
style="--cpd-icon-button-size: 100%;" style="--cpd-icon-button-size: 100%;"
> >
<svg <svg
aria-labelledby=":rh2:" aria-labelledby="«rh2»"
fill="currentColor" fill="currentColor"
height="1em" height="1em"
viewBox="0 0 24 24" viewBox="0 0 24 24"
@@ -289,7 +289,7 @@ exports[`RoomView for a local room in state ERROR should match the snapshot 1`]
<button <button
aria-disabled="false" aria-disabled="false"
aria-label="Voice call" aria-label="Voice call"
aria-labelledby=":rh7:" aria-labelledby="«rh7»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
@@ -314,7 +314,7 @@ exports[`RoomView for a local room in state ERROR should match the snapshot 1`]
</button> </button>
<button <button
aria-label="Threads" aria-label="Threads"
aria-labelledby=":rhc:" aria-labelledby="«rhc»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
@@ -340,7 +340,7 @@ exports[`RoomView for a local room in state ERROR should match the snapshot 1`]
</button> </button>
<button <button
aria-label="Room info" aria-label="Room info"
aria-labelledby=":rhh:" aria-labelledby="«rhh»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
@@ -369,7 +369,7 @@ exports[`RoomView for a local room in state ERROR should match the snapshot 1`]
> >
<div <div
aria-label="2 members" aria-label="2 members"
aria-labelledby=":rhm:" aria-labelledby="«rhm»"
class="mx_AccessibleButton mx_FacePile" class="mx_AccessibleButton mx_FacePile"
role="button" role="button"
tabindex="0" tabindex="0"
@@ -573,7 +573,7 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] =
style="--cpd-icon-button-size: 100%;" style="--cpd-icon-button-size: 100%;"
> >
<svg <svg
aria-labelledby=":rbo:" aria-labelledby="«rbo»"
fill="currentColor" fill="currentColor"
height="1em" height="1em"
viewBox="0 0 24 24" viewBox="0 0 24 24"
@@ -589,7 +589,7 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] =
<button <button
aria-disabled="false" aria-disabled="false"
aria-label="Voice call" aria-label="Voice call"
aria-labelledby=":rbt:" aria-labelledby="«rbt»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
@@ -614,7 +614,7 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] =
</button> </button>
<button <button
aria-label="Threads" aria-label="Threads"
aria-labelledby=":rc2:" aria-labelledby="«rc2»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
@@ -640,7 +640,7 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] =
</button> </button>
<button <button
aria-label="Room info" aria-label="Room info"
aria-labelledby=":rc7:" aria-labelledby="«rc7»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
@@ -669,7 +669,7 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] =
> >
<div <div
aria-label="2 members" aria-label="2 members"
aria-labelledby=":rcc:" aria-labelledby="«rcc»"
class="mx_AccessibleButton mx_FacePile" class="mx_AccessibleButton mx_FacePile"
role="button" role="button"
tabindex="0" tabindex="0"
@@ -950,7 +950,7 @@ exports[`RoomView for a local room in state NEW that is encrypted should match t
style="--cpd-icon-button-size: 100%;" style="--cpd-icon-button-size: 100%;"
> >
<svg <svg
aria-labelledby=":rdu:" aria-labelledby="«rdu»"
fill="currentColor" fill="currentColor"
height="1em" height="1em"
viewBox="0 0 24 24" viewBox="0 0 24 24"
@@ -966,7 +966,7 @@ exports[`RoomView for a local room in state NEW that is encrypted should match t
<button <button
aria-disabled="false" aria-disabled="false"
aria-label="Voice call" aria-label="Voice call"
aria-labelledby=":re3:" aria-labelledby="«re3»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
@@ -991,7 +991,7 @@ exports[`RoomView for a local room in state NEW that is encrypted should match t
</button> </button>
<button <button
aria-label="Threads" aria-label="Threads"
aria-labelledby=":re8:" aria-labelledby="«re8»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
@@ -1017,7 +1017,7 @@ exports[`RoomView for a local room in state NEW that is encrypted should match t
</button> </button>
<button <button
aria-label="Room info" aria-label="Room info"
aria-labelledby=":red:" aria-labelledby="«red»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
@@ -1046,7 +1046,7 @@ exports[`RoomView for a local room in state NEW that is encrypted should match t
> >
<div <div
aria-label="2 members" aria-label="2 members"
aria-labelledby=":rei:" aria-labelledby="«rei»"
class="mx_AccessibleButton mx_FacePile" class="mx_AccessibleButton mx_FacePile"
role="button" role="button"
tabindex="0" tabindex="0"
@@ -1408,7 +1408,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
style="--cpd-icon-button-size: 100%; --cpd-color-icon-tertiary: var(--cpd-color-icon-disabled);" style="--cpd-icon-button-size: 100%; --cpd-color-icon-tertiary: var(--cpd-color-icon-disabled);"
> >
<svg <svg
aria-labelledby=":r2c:" aria-labelledby="«r2c»"
fill="currentColor" fill="currentColor"
height="1em" height="1em"
viewBox="0 0 24 24" viewBox="0 0 24 24"
@@ -1424,7 +1424,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
<button <button
aria-disabled="true" aria-disabled="true"
aria-label="There's no one here to call" aria-label="There's no one here to call"
aria-labelledby=":r2h:" aria-labelledby="«r2h»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
@@ -1449,7 +1449,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
</button> </button>
<button <button
aria-label="Threads" aria-label="Threads"
aria-labelledby=":r2m:" aria-labelledby="«r2m»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
@@ -1475,7 +1475,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
</button> </button>
<button <button
aria-label="Room info" aria-label="Room info"
aria-labelledby=":r2r:" aria-labelledby="«r2r»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
@@ -1504,7 +1504,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
> >
<div <div
aria-label="0 members" aria-label="0 members"
aria-labelledby=":r30:" aria-labelledby="«r30»"
class="mx_AccessibleButton mx_FacePile" class="mx_AccessibleButton mx_FacePile"
role="button" role="button"
tabindex="0" tabindex="0"
@@ -1616,7 +1616,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
style="--cpd-icon-button-size: 100%; --cpd-color-icon-tertiary: var(--cpd-color-icon-disabled);" style="--cpd-icon-button-size: 100%; --cpd-color-icon-tertiary: var(--cpd-color-icon-disabled);"
> >
<svg <svg
aria-labelledby=":r2c:" aria-labelledby="«r2c»"
fill="currentColor" fill="currentColor"
height="1em" height="1em"
viewBox="0 0 24 24" viewBox="0 0 24 24"
@@ -1632,7 +1632,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
<button <button
aria-disabled="true" aria-disabled="true"
aria-label="There's no one here to call" aria-label="There's no one here to call"
aria-labelledby=":r2h:" aria-labelledby="«r2h»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
@@ -1657,7 +1657,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
</button> </button>
<button <button
aria-label="Threads" aria-label="Threads"
aria-labelledby=":r2m:" aria-labelledby="«r2m»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
@@ -1683,7 +1683,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
</button> </button>
<button <button
aria-label="Room info" aria-label="Room info"
aria-labelledby=":r2r:" aria-labelledby="«r2r»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
@@ -1712,7 +1712,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
> >
<div <div
aria-label="0 members" aria-label="0 members"
aria-labelledby=":r30:" aria-labelledby="«r30»"
class="mx_AccessibleButton mx_FacePile" class="mx_AccessibleButton mx_FacePile"
role="button" role="button"
tabindex="0" tabindex="0"
@@ -1780,7 +1780,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
tabindex="0" tabindex="0"
> >
<div <div
aria-labelledby=":r3e:" aria-labelledby="«r3e»"
class="mx_E2EIcon mx_E2EIcon_verified mx_MessageComposer_e2eIcon" class="mx_E2EIcon mx_E2EIcon_verified mx_MessageComposer_e2eIcon"
/> />
</span> </span>
@@ -1952,7 +1952,7 @@ exports[`RoomView video rooms should render joined video room view 1`] = `
aria-label="Open room settings" aria-label="Open room settings"
aria-live="off" aria-live="off"
class="_avatar_1qbcf_8 mx_BaseAvatar _avatar-imageless_1qbcf_52" class="_avatar_1qbcf_8 mx_BaseAvatar _avatar-imageless_1qbcf_52"
data-color="5" data-color="3"
data-testid="avatar-img" data-testid="avatar-img"
data-type="round" data-type="round"
role="button" role="button"
@@ -1979,14 +1979,14 @@ exports[`RoomView video rooms should render joined video room view 1`] = `
<span <span
class="mx_RoomHeader_truncated mx_lineClamp" class="mx_RoomHeader_truncated mx_lineClamp"
> >
!18:example.org !16:example.org
</span> </span>
</div> </div>
</div> </div>
</button> </button>
<button <button
aria-label="Chat" aria-label="Chat"
aria-labelledby=":r7c:" aria-labelledby="«r7c»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
@@ -2012,7 +2012,7 @@ exports[`RoomView video rooms should render joined video room view 1`] = `
</button> </button>
<button <button
aria-label="Threads" aria-label="Threads"
aria-labelledby=":r7h:" aria-labelledby="«r7h»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
@@ -2038,7 +2038,7 @@ exports[`RoomView video rooms should render joined video room view 1`] = `
</button> </button>
<button <button
aria-label="Room info" aria-label="Room info"
aria-labelledby=":r7m:" aria-labelledby="«r7m»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
@@ -2067,7 +2067,7 @@ exports[`RoomView video rooms should render joined video room view 1`] = `
> >
<div <div
aria-label="0 members" aria-label="0 members"
aria-labelledby=":r7r:" aria-labelledby="«r7r»"
class="mx_AccessibleButton mx_FacePile" class="mx_AccessibleButton mx_FacePile"
role="button" role="button"
tabindex="0" tabindex="0"
@@ -2140,7 +2140,7 @@ exports[`RoomView video rooms should render joined video room view 1`] = `
</p> </p>
</div> </div>
<button <button
aria-labelledby=":r84:" aria-labelledby="«r84»"
class="_icon-button_m2erp_8 _subtle-bg_m2erp_29" class="_icon-button_m2erp_8 _subtle-bg_m2erp_29"
data-testid="base-card-close-button" data-testid="base-card-close-button"
role="button" role="button"

View File

@@ -58,7 +58,7 @@ exports[`SpaceHierarchy <SpaceHierarchy /> renders 1`] = `
role="tree" role="tree"
> >
<li <li
aria-labelledby=":r8:" aria-labelledby="«r8»"
class="mx_SpaceHierarchy_roomTileWrapper" class="mx_SpaceHierarchy_roomTileWrapper"
role="treeitem" role="treeitem"
> >
@@ -88,7 +88,7 @@ exports[`SpaceHierarchy <SpaceHierarchy /> renders 1`] = `
class="mx_SpaceHierarchy_roomTile_name" class="mx_SpaceHierarchy_roomTile_name"
> >
<span <span
id=":r8:" id="«r8»"
> >
Unnamed Room Unnamed Room
</span> </span>
@@ -122,7 +122,7 @@ exports[`SpaceHierarchy <SpaceHierarchy /> renders 1`] = `
class="_container_1hel1_10" class="_container_1hel1_10"
> >
<input <input
aria-labelledby=":r8:" aria-labelledby="«r8»"
class="_input_1hel1_18" class="_input_1hel1_18"
id="checkbox_MwbPDmfGtm" id="checkbox_MwbPDmfGtm"
role="presentation" role="presentation"
@@ -156,7 +156,7 @@ exports[`SpaceHierarchy <SpaceHierarchy /> renders 1`] = `
</div> </div>
</li> </li>
<li <li
aria-labelledby=":rc:" aria-labelledby="«rc»"
class="mx_SpaceHierarchy_roomTileWrapper" class="mx_SpaceHierarchy_roomTileWrapper"
role="treeitem" role="treeitem"
> >
@@ -186,7 +186,7 @@ exports[`SpaceHierarchy <SpaceHierarchy /> renders 1`] = `
class="mx_SpaceHierarchy_roomTile_name" class="mx_SpaceHierarchy_roomTile_name"
> >
<span <span
id=":rc:" id="«rc»"
> >
Unnamed Room Unnamed Room
</span> </span>
@@ -220,7 +220,7 @@ exports[`SpaceHierarchy <SpaceHierarchy /> renders 1`] = `
class="_container_1hel1_10" class="_container_1hel1_10"
> >
<input <input
aria-labelledby=":rc:" aria-labelledby="«rc»"
class="_input_1hel1_18" class="_input_1hel1_18"
id="checkbox_GQvdMWe954" id="checkbox_GQvdMWe954"
role="presentation" role="presentation"
@@ -254,7 +254,7 @@ exports[`SpaceHierarchy <SpaceHierarchy /> renders 1`] = `
</div> </div>
</li> </li>
<li <li
aria-labelledby=":rg:" aria-labelledby="«rg»"
class="mx_SpaceHierarchy_roomTileWrapper" class="mx_SpaceHierarchy_roomTileWrapper"
role="treeitem" role="treeitem"
> >
@@ -284,7 +284,7 @@ exports[`SpaceHierarchy <SpaceHierarchy /> renders 1`] = `
class="mx_SpaceHierarchy_roomTile_name" class="mx_SpaceHierarchy_roomTile_name"
> >
<span <span
id=":rg:" id="«rg»"
> >
Knock room Knock room
</span> </span>
@@ -318,7 +318,7 @@ exports[`SpaceHierarchy <SpaceHierarchy /> renders 1`] = `
class="_container_1hel1_10" class="_container_1hel1_10"
> >
<input <input
aria-labelledby=":rg:" aria-labelledby="«rg»"
class="_input_1hel1_18" class="_input_1hel1_18"
id="checkbox_DVIAu5CsiH" id="checkbox_DVIAu5CsiH"
role="presentation" role="presentation"
@@ -353,7 +353,7 @@ exports[`SpaceHierarchy <SpaceHierarchy /> renders 1`] = `
</li> </li>
<li <li
aria-expanded="true" aria-expanded="true"
aria-labelledby=":rk:" aria-labelledby="«rk»"
class="mx_SpaceHierarchy_roomTileWrapper" class="mx_SpaceHierarchy_roomTileWrapper"
role="treeitem" role="treeitem"
> >
@@ -383,7 +383,7 @@ exports[`SpaceHierarchy <SpaceHierarchy /> renders 1`] = `
class="mx_SpaceHierarchy_roomTile_name" class="mx_SpaceHierarchy_roomTile_name"
> >
<span <span
id=":rk:" id="«rk»"
> >
Nested space Nested space
</span> </span>
@@ -417,7 +417,7 @@ exports[`SpaceHierarchy <SpaceHierarchy /> renders 1`] = `
class="_container_1hel1_10" class="_container_1hel1_10"
> >
<input <input
aria-labelledby=":rk:" aria-labelledby="«rk»"
class="_input_1hel1_18" class="_input_1hel1_18"
id="checkbox_RD7nyrA2oh" id="checkbox_RD7nyrA2oh"
role="presentation" role="presentation"
@@ -458,7 +458,7 @@ exports[`SpaceHierarchy <SpaceHierarchy /> renders 1`] = `
/> />
</li> </li>
<li <li
aria-labelledby=":ro:" aria-labelledby="«ro»"
class="mx_SpaceHierarchy_roomTileWrapper" class="mx_SpaceHierarchy_roomTileWrapper"
role="treeitem" role="treeitem"
> >
@@ -488,7 +488,7 @@ exports[`SpaceHierarchy <SpaceHierarchy /> renders 1`] = `
class="mx_SpaceHierarchy_roomTile_name" class="mx_SpaceHierarchy_roomTile_name"
> >
<span <span
id=":ro:" id="«ro»"
> >
Nested room Nested room
</span> </span>
@@ -510,7 +510,7 @@ exports[`SpaceHierarchy <SpaceHierarchy /> renders 1`] = `
Join Join
</div> </div>
<span <span
aria-labelledby=":rp:" aria-labelledby="«rp»"
tabindex="0" tabindex="0"
> >
<form <form
@@ -526,7 +526,7 @@ exports[`SpaceHierarchy <SpaceHierarchy /> renders 1`] = `
class="_container_1hel1_10" class="_container_1hel1_10"
> >
<input <input
aria-labelledby=":ro:" aria-labelledby="«ro»"
class="_input_1hel1_18" class="_input_1hel1_18"
disabled="" disabled=""
id="checkbox_jWVJIPauy1" id="checkbox_jWVJIPauy1"

View File

@@ -6,7 +6,7 @@ exports[`ThreadPanel Header expect that All filter for ThreadPanelHeader properl
class="mx_ThreadPanelHeader" class="mx_ThreadPanelHeader"
> >
<button <button
aria-labelledby=":r0:" aria-labelledby="«r0»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 28px;" style="--cpd-icon-button-size: 28px;"
@@ -44,7 +44,7 @@ exports[`ThreadPanel Header expect that My filter for ThreadPanelHeader properly
class="mx_ThreadPanelHeader" class="mx_ThreadPanelHeader"
> >
<button <button
aria-labelledby=":r6:" aria-labelledby="«r6»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 28px;" style="--cpd-icon-button-size: 28px;"

View File

@@ -33,6 +33,10 @@ describe("RoomListItemViewModel", () => {
room = mkStubRoom("roomId", "roomName", matrixClient); room = mkStubRoom("roomId", "roomName", matrixClient);
}); });
afterEach(() => {
jest.resetAllMocks();
});
it("should dispatch view room action on openRoom", async () => { it("should dispatch view room action on openRoom", async () => {
const { result: vm } = renderHook( const { result: vm } = renderHook(
() => useRoomListItemViewModel(room), () => useRoomListItemViewModel(room),
@@ -68,6 +72,20 @@ describe("RoomListItemViewModel", () => {
expect(vm.current.showHoverMenu).toBe(true); expect(vm.current.showHoverMenu).toBe(true);
}); });
it("should not show hover menu if user has an invitation notification", async () => {
mocked(hasAccessToOptionsMenu).mockReturnValue(true);
const notificationState = new RoomNotificationState(room, false);
jest.spyOn(RoomNotificationStateStore.instance, "getRoomState").mockReturnValue(notificationState);
jest.spyOn(notificationState, "invited", "get").mockReturnValue(false);
const { result: vm } = renderHook(
() => useRoomListItemViewModel(room),
withClientContextRenderOptions(room.client),
);
expect(vm.current.showHoverMenu).toBe(true);
});
describe("a11yLabel", () => { describe("a11yLabel", () => {
let notificationState: RoomNotificationState; let notificationState: RoomNotificationState;
beforeEach(() => { beforeEach(() => {
@@ -108,7 +126,10 @@ describe("RoomListItemViewModel", () => {
}, },
])("should return the $label label", ({ mock, expected }) => { ])("should return the $label label", ({ mock, expected }) => {
mock?.(); mock?.();
const { result: vm } = renderHook(() => useRoomListItemViewModel(room)); const { result: vm } = renderHook(
() => useRoomListItemViewModel(room),
withClientContextRenderOptions(room.client),
);
expect(vm.current.a11yLabel).toBe(expected); expect(vm.current.a11yLabel).toBe(expected);
}); });
}); });

View File

@@ -16,7 +16,7 @@ exports[`DecoratedRoomAvatar shows an avatar with globe icon and tooltip for pub
r r
</span> </span>
<div <div
aria-labelledby=":r0:" aria-labelledby="«r0»"
class="mx_DecoratedRoomAvatar_icon mx_DecoratedRoomAvatar_icon_globe" class="mx_DecoratedRoomAvatar_icon mx_DecoratedRoomAvatar_icon_globe"
tabindex="0" tabindex="0"
/> />
@@ -40,7 +40,7 @@ exports[`DecoratedRoomAvatar shows the presence indicator in a DM room that also
r r
</span> </span>
<div <div
aria-labelledby=":r6:" aria-labelledby="«r6»"
class="mx_DecoratedRoomAvatar_icon mx_DecoratedRoomAvatar_icon_online" class="mx_DecoratedRoomAvatar_icon mx_DecoratedRoomAvatar_icon_online"
tabindex="0" tabindex="0"
/> />

View File

@@ -7,7 +7,7 @@ exports[`WithPresenceIndicator renders presence indicator with tooltip for DM ro
> >
<span /> <span />
<div <div
aria-labelledby=":r0:" aria-labelledby="«r0»"
class="mx_WithPresenceIndicator_icon mx_WithPresenceIndicator_icon_online" class="mx_WithPresenceIndicator_icon mx_WithPresenceIndicator_icon_online"
style="width: 32px; height: 32px;" style="width: 32px; height: 32px;"
tabindex="0" tabindex="0"
@@ -23,7 +23,7 @@ exports[`WithPresenceIndicator renders presence indicator with tooltip for DM ro
> >
<span /> <span />
<div <div
aria-labelledby=":r6:" aria-labelledby="«r6»"
class="mx_WithPresenceIndicator_icon mx_WithPresenceIndicator_icon_offline" class="mx_WithPresenceIndicator_icon mx_WithPresenceIndicator_icon_offline"
style="width: 32px; height: 32px;" style="width: 32px; height: 32px;"
tabindex="0" tabindex="0"
@@ -39,7 +39,7 @@ exports[`WithPresenceIndicator renders presence indicator with tooltip for DM ro
> >
<span /> <span />
<div <div
aria-labelledby=":rc:" aria-labelledby="«rc»"
class="mx_WithPresenceIndicator_icon mx_WithPresenceIndicator_icon_away" class="mx_WithPresenceIndicator_icon mx_WithPresenceIndicator_icon_away"
style="width: 32px; height: 32px;" style="width: 32px; height: 32px;"
tabindex="0" tabindex="0"

View File

@@ -32,7 +32,7 @@ exports[`<BeaconListItem /> when a beacon is live and has locations renders beac
class="mx_BeaconListItem_interactions" class="mx_BeaconListItem_interactions"
> >
<a <a
aria-labelledby=":r0:" aria-labelledby="«r0»"
data-testid="open-location-in-osm" data-testid="open-location-in-osm"
href="https://www.openstreetmap.org/?mlat=51&mlon=41#map=16/51/41" href="https://www.openstreetmap.org/?mlat=51&mlon=41#map=16/51/41"
rel="noreferrer noopener" rel="noreferrer noopener"

View File

@@ -72,7 +72,7 @@ exports[`<DialogSidebar /> renders sidebar correctly with beacons 1`] = `
class="mx_BeaconListItem_interactions" class="mx_BeaconListItem_interactions"
> >
<a <a
aria-labelledby=":r8:" aria-labelledby="«r8»"
data-testid="open-location-in-osm" data-testid="open-location-in-osm"
href="https://www.openstreetmap.org/?mlat=51&mlon=41#map=16/51/41" href="https://www.openstreetmap.org/?mlat=51&mlon=41#map=16/51/41"
rel="noreferrer noopener" rel="noreferrer noopener"

View File

@@ -3,7 +3,7 @@
exports[`<ShareLatestLocation /> renders share buttons when there is a location 1`] = ` exports[`<ShareLatestLocation /> renders share buttons when there is a location 1`] = `
<DocumentFragment> <DocumentFragment>
<a <a
aria-labelledby=":r0:" aria-labelledby="«r0»"
data-testid="open-location-in-osm" data-testid="open-location-in-osm"
href="https://www.openstreetmap.org/?mlat=51&mlon=42#map=16/51/42" href="https://www.openstreetmap.org/?mlat=51&mlon=42#map=16/51/42"
rel="noreferrer noopener" rel="noreferrer noopener"

View File

@@ -37,22 +37,22 @@ exports[`ConfirmRejectInviteDialog can reject with options selected 1`] = `
class="mx_SettingsFlag_label" class="mx_SettingsFlag_label"
> >
<div <div
id="mx_LabelledToggleSwitch_:r7:" id="mx_LabelledToggleSwitch_«r7»"
> >
Ignore user Ignore user
</div> </div>
<span <span
class="mx_Caption" class="mx_Caption"
id="mx_LabelledToggleSwitch_:r7:_caption" id="mx_LabelledToggleSwitch_«r7»_caption"
> >
You will not see any messages or room invites from this user. You will not see any messages or room invites from this user.
</span> </span>
</span> </span>
<div <div
aria-checked="true" aria-checked="true"
aria-describedby="mx_LabelledToggleSwitch_:r7:_caption" aria-describedby="mx_LabelledToggleSwitch_«r7»_caption"
aria-disabled="false" aria-disabled="false"
aria-labelledby="mx_LabelledToggleSwitch_:r7:" aria-labelledby="mx_LabelledToggleSwitch_«r7»"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on mx_ToggleSwitch_enabled" class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on mx_ToggleSwitch_enabled"
role="switch" role="switch"
tabindex="0" tabindex="0"
@@ -69,22 +69,22 @@ exports[`ConfirmRejectInviteDialog can reject with options selected 1`] = `
class="mx_SettingsFlag_label" class="mx_SettingsFlag_label"
> >
<div <div
id="mx_LabelledToggleSwitch_:r8:" id="mx_LabelledToggleSwitch_«r8»"
> >
Report room Report room
</div> </div>
<span <span
class="mx_Caption" class="mx_Caption"
id="mx_LabelledToggleSwitch_:r8:_caption" id="mx_LabelledToggleSwitch_«r8»_caption"
> >
Report this room to your account provider. Report this room to your account provider.
</span> </span>
</span> </span>
<div <div
aria-checked="true" aria-checked="true"
aria-describedby="mx_LabelledToggleSwitch_:r8:_caption" aria-describedby="mx_LabelledToggleSwitch_«r8»_caption"
aria-disabled="false" aria-disabled="false"
aria-labelledby="mx_LabelledToggleSwitch_:r8:" aria-labelledby="mx_LabelledToggleSwitch_«r8»"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on mx_ToggleSwitch_enabled" class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on mx_ToggleSwitch_enabled"
role="switch" role="switch"
tabindex="0" tabindex="0"

View File

@@ -198,7 +198,7 @@ exports[`DevtoolsDialog renders the devtools dialog 1`] = `
> >
<label <label
class="_label_19upo_59" class="_label_19upo_59"
for="radix-:r4:" for="radix-«r4»"
> >
Element Call URL Element Call URL
</label> </label>
@@ -207,7 +207,7 @@ exports[`DevtoolsDialog renders the devtools dialog 1`] = `
> >
<input <input
class="_control_sqdq4_10" class="_control_sqdq4_10"
id="radix-:r4:" id="radix-«r4»"
name="input" name="input"
title="" title=""
value="" value=""

View File

@@ -75,7 +75,7 @@ exports[`<ManageRestrictedJoinRuleDialog /> should list spaces which are not par
class="_container_1hel1_10" class="_container_1hel1_10"
> >
<input <input
aria-describedby=":r5:" aria-describedby="«r5»"
class="_input_1hel1_18" class="_input_1hel1_18"
id="checkbox_vY7Q4uEh9K" id="checkbox_vY7Q4uEh9K"
type="checkbox" type="checkbox"
@@ -125,7 +125,7 @@ exports[`<ManageRestrictedJoinRuleDialog /> should list spaces which are not par
</label> </label>
<span <span
class="_message_19upo_85 _help-message_19upo_91" class="_message_19upo_85 _help-message_19upo_91"
id=":r5:" id="«r5»"
> >
0 members 0 members
</span> </span>

View File

@@ -43,7 +43,7 @@ exports[`ReportRoomDialog displays admin message 1`] = `
/> />
<span <span
class="_message_19upo_85 _help-message_19upo_91" class="_message_19upo_85 _help-message_19upo_91"
id="radix-:r8:" id="radix-«r8»"
> >
Report this room to your account provider. If the messages are encrypted, your admin will not be able to read them. Report this room to your account provider. If the messages are encrypted, your admin will not be able to read them.
</span> </span>
@@ -71,7 +71,7 @@ exports[`ReportRoomDialog displays admin message 1`] = `
class="mx_SettingsFlag_label" class="mx_SettingsFlag_label"
> >
<div <div
id="mx_LabelledToggleSwitch_:r9:" id="mx_LabelledToggleSwitch_«r9»"
> >
Leave room Leave room
</div> </div>
@@ -79,7 +79,7 @@ exports[`ReportRoomDialog displays admin message 1`] = `
<div <div
aria-checked="false" aria-checked="false"
aria-disabled="false" aria-disabled="false"
aria-labelledby="mx_LabelledToggleSwitch_:r9:" aria-labelledby="mx_LabelledToggleSwitch_«r9»"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_enabled" class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_enabled"
role="switch" role="switch"
tabindex="0" tabindex="0"

View File

@@ -50,7 +50,7 @@ exports[`<ServerPickerDialog /> should render dialog 1`] = `
class="mx_StyledRadioButton_content" class="mx_StyledRadioButton_content"
> >
<span <span
aria-labelledby=":r0:" aria-labelledby="«r0»"
class="mx_Login_underlinedServerName" class="mx_Login_underlinedServerName"
tabindex="0" tabindex="0"
> >

View File

@@ -30,7 +30,7 @@ exports[`AppTile destroys non-persisted right panel widget on room change 1`] =
/> />
</div> </div>
<button <button
aria-labelledby=":r0:" aria-labelledby="«r0»"
class="_icon-button_m2erp_8 _subtle-bg_m2erp_29" class="_icon-button_m2erp_8 _subtle-bg_m2erp_29"
data-testid="base-card-close-button" data-testid="base-card-close-button"
role="button" role="button"
@@ -336,8 +336,8 @@ exports[`AppTile for a pinned widget should render permission request 1`] = `
<span> <span>
Using this widget may share data Using this widget may share data
<div <div
aria-describedby=":r2j:" aria-describedby="«r2j»"
aria-labelledby=":r2i:" aria-labelledby="«r2i»"
class="mx_TextWithTooltip_target mx_TextWithTooltip_target--helpIcon" class="mx_TextWithTooltip_target mx_TextWithTooltip_target--helpIcon"
> >
<svg <svg

View File

@@ -3,7 +3,7 @@
exports[`<FacePile /> renders with a tooltip 1`] = ` exports[`<FacePile /> renders with a tooltip 1`] = `
<DocumentFragment> <DocumentFragment>
<div <div
aria-labelledby=":r0:" aria-labelledby="«r0»"
class="mx_AccessibleButton mx_FacePile" class="mx_AccessibleButton mx_FacePile"
role="button" role="button"
tabindex="0" tabindex="0"

View File

@@ -3,7 +3,7 @@
exports[`InfoTooltip should show tooltip on hover 1`] = ` exports[`InfoTooltip should show tooltip on hover 1`] = `
<DocumentFragment> <DocumentFragment>
<div <div
aria-describedby=":r2:" aria-describedby="«r2»"
class="mx_InfoTooltip" class="mx_InfoTooltip"
tabindex="0" tabindex="0"
> >

View File

@@ -18,7 +18,7 @@ exports[`<LabelledCheckbox /> should render with byline of "this is a byline" 1`
class="_container_1hel1_10" class="_container_1hel1_10"
> >
<input <input
aria-describedby=":r4:" aria-describedby="«r4»"
checked="" checked=""
class="_input_1hel1_18" class="_input_1hel1_18"
id="checkbox_vY7Q4uEh9K" id="checkbox_vY7Q4uEh9K"
@@ -57,7 +57,7 @@ exports[`<LabelledCheckbox /> should render with byline of "this is a byline" 1`
</label> </label>
<span <span
class="_message_19upo_85 _help-message_19upo_91" class="_message_19upo_85 _help-message_19upo_91"
id=":r4:" id="«r4»"
> >
this is a byline this is a byline
</span> </span>

View File

@@ -3,8 +3,8 @@
exports[`<RoomFacePile /> renders 1`] = ` exports[`<RoomFacePile /> renders 1`] = `
<DocumentFragment> <DocumentFragment>
<div <div
aria-describedby=":r1:" aria-describedby="«r1»"
aria-labelledby=":r0:" aria-labelledby="«r0»"
class="mx_AccessibleButton mx_FacePile" class="mx_AccessibleButton mx_FacePile"
role="button" role="button"
tabindex="0" tabindex="0"

View File

@@ -10,7 +10,7 @@ exports[`<SettingsField /> should render with the default label 1`] = `
> >
<label <label
class="_label_19upo_59" class="_label_19upo_59"
for="radix-:r0:" for="radix-«r0»"
> >
Element Call URL Element Call URL
</label> </label>
@@ -19,7 +19,7 @@ exports[`<SettingsField /> should render with the default label 1`] = `
> >
<input <input
class="_control_sqdq4_10" class="_control_sqdq4_10"
id="radix-:r0:" id="radix-«r0»"
name="input" name="input"
title="" title=""
value="" value=""

View File

@@ -26,7 +26,7 @@ exports[`<LocationShareMenu /> with live location disabled goes to labs flag scr
class="mx_SettingsFlag_label" class="mx_SettingsFlag_label"
> >
<div <div
id="mx_LabelledToggleSwitch_:r0:" id="mx_LabelledToggleSwitch_«r0»"
> >
Enable live location sharing Enable live location sharing
</div> </div>
@@ -34,7 +34,7 @@ exports[`<LocationShareMenu /> with live location disabled goes to labs flag scr
<div <div
aria-checked="false" aria-checked="false"
aria-disabled="false" aria-disabled="false"
aria-labelledby="mx_LabelledToggleSwitch_:r0:" aria-labelledby="mx_LabelledToggleSwitch_«r0»"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_enabled" class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_enabled"
role="switch" role="switch"
tabindex="0" tabindex="0"

View File

@@ -34,7 +34,7 @@ exports[`MLocationBody <MLocationBody> without error renders map correctly 1`] =
class="mx_MLocationBody" class="mx_MLocationBody"
> >
<div <div
aria-labelledby=":ri:" aria-labelledby="«ri»"
class="mx_MLocationBody_map" class="mx_MLocationBody_map"
> >
<div <div
@@ -76,7 +76,7 @@ exports[`MLocationBody <MLocationBody> without error renders marker correctly fo
class="mx_MLocationBody" class="mx_MLocationBody"
> >
<div <div
aria-labelledby=":ru:" aria-labelledby="«ru»"
class="mx_MLocationBody_map" class="mx_MLocationBody_map"
> >
<div <div

View File

@@ -91,7 +91,7 @@ exports[`<PollHistory /> renders a list of active polls when there are polls in
tabindex="0" tabindex="0"
> >
<div <div
aria-labelledby=":ra:" aria-labelledby="«ra»"
class="mx_PollListItem_content" class="mx_PollListItem_content"
> >
<span> <span>
@@ -116,7 +116,7 @@ exports[`<PollHistory /> renders a list of active polls when there are polls in
tabindex="0" tabindex="0"
> >
<div <div
aria-labelledby=":rf:" aria-labelledby="«rf»"
class="mx_PollListItem_content" class="mx_PollListItem_content"
> >
<span> <span>

View File

@@ -10,7 +10,7 @@ exports[`<PollListItem /> renders a poll 1`] = `
tabindex="0" tabindex="0"
> >
<div <div
aria-labelledby=":r0:" aria-labelledby="«r0»"
class="mx_PollListItem_content" class="mx_PollListItem_content"
> >
<span> <span>

View File

@@ -10,7 +10,7 @@ exports[`<PollListItemEnded /> renders a poll with no responses 1`] = `
tabindex="0" tabindex="0"
> >
<div <div
aria-labelledby=":r0:" aria-labelledby="«r0»"
class="mx_PollListItemEnded_content" class="mx_PollListItemEnded_content"
> >
<div <div

View File

@@ -19,7 +19,7 @@ exports[`<BaseCard /> should close when clicking X button 1`] = `
</p> </p>
</div> </div>
<button <button
aria-labelledby=":r0:" aria-labelledby="«r0»"
class="_icon-button_m2erp_8 _subtle-bg_m2erp_29" class="_icon-button_m2erp_8 _subtle-bg_m2erp_29"
data-testid="base-card-close-button" data-testid="base-card-close-button"
role="button" role="button"

View File

@@ -19,7 +19,7 @@ exports[`<ExtensionsCard /> should render empty state 1`] = `
</p> </p>
</div> </div>
<button <button
aria-labelledby=":r0:" aria-labelledby="«r0»"
class="_icon-button_m2erp_8 _subtle-bg_m2erp_29" class="_icon-button_m2erp_8 _subtle-bg_m2erp_29"
data-testid="base-card-close-button" data-testid="base-card-close-button"
role="button" role="button"
@@ -119,7 +119,7 @@ exports[`<ExtensionsCard /> should render widgets 1`] = `
</p> </p>
</div> </div>
<button <button
aria-labelledby=":r6:" aria-labelledby="«r6»"
class="_icon-button_m2erp_8 _subtle-bg_m2erp_29" class="_icon-button_m2erp_8 _subtle-bg_m2erp_29"
data-testid="base-card-close-button" data-testid="base-card-close-button"
role="button" role="button"

View File

@@ -19,7 +19,7 @@ exports[`<PinnedMessagesCard /> should show the empty state when there are no pi
</p> </p>
</div> </div>
<button <button
aria-labelledby=":re:" aria-labelledby="«re»"
class="_icon-button_m2erp_8 _subtle-bg_m2erp_29" class="_icon-button_m2erp_8 _subtle-bg_m2erp_29"
data-testid="base-card-close-button" data-testid="base-card-close-button"
role="button" role="button"
@@ -100,7 +100,7 @@ exports[`<PinnedMessagesCard /> should show two pinned messages 1`] = `
</p> </p>
</div> </div>
<button <button
aria-labelledby=":rk:" aria-labelledby="«rk»"
class="_icon-button_m2erp_8 _subtle-bg_m2erp_29" class="_icon-button_m2erp_8 _subtle-bg_m2erp_29"
data-testid="base-card-close-button" data-testid="base-card-close-button"
role="button" role="button"
@@ -157,7 +157,7 @@ exports[`<PinnedMessagesCard /> should show two pinned messages 1`] = `
class="mx_PinnedEventTile_top" class="mx_PinnedEventTile_top"
> >
<span <span
aria-labelledby=":rq:" aria-labelledby="«rq»"
class="mx_PinnedEventTile_sender mx_Username_color3" class="mx_PinnedEventTile_sender mx_Username_color3"
> >
@alice:example.org @alice:example.org
@@ -169,7 +169,7 @@ exports[`<PinnedMessagesCard /> should show two pinned messages 1`] = `
aria-label="Open menu" aria-label="Open menu"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
data-state="closed" data-state="closed"
id="radix-:rv:" id="radix-«rv»"
role="button" role="button"
style="--cpd-icon-button-size: 24px;" style="--cpd-icon-button-size: 24px;"
tabindex="0" tabindex="0"
@@ -235,7 +235,7 @@ exports[`<PinnedMessagesCard /> should show two pinned messages 1`] = `
class="mx_PinnedEventTile_top" class="mx_PinnedEventTile_top"
> >
<span <span
aria-labelledby=":r11:" aria-labelledby="«r11»"
class="mx_PinnedEventTile_sender mx_Username_color3" class="mx_PinnedEventTile_sender mx_Username_color3"
> >
@alice:example.org @alice:example.org
@@ -247,7 +247,7 @@ exports[`<PinnedMessagesCard /> should show two pinned messages 1`] = `
aria-label="Open menu" aria-label="Open menu"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
data-state="closed" data-state="closed"
id="radix-:r16:" id="radix-«r16»"
role="button" role="button"
style="--cpd-icon-button-size: 24px;" style="--cpd-icon-button-size: 24px;"
tabindex="0" tabindex="0"
@@ -321,7 +321,7 @@ exports[`<PinnedMessagesCard /> unpin all should not allow to unpinall 1`] = `
</p> </p>
</div> </div>
<button <button
aria-labelledby=":rt2:" aria-labelledby="«rt2»"
class="_icon-button_m2erp_8 _subtle-bg_m2erp_29" class="_icon-button_m2erp_8 _subtle-bg_m2erp_29"
data-testid="base-card-close-button" data-testid="base-card-close-button"
role="button" role="button"
@@ -378,7 +378,7 @@ exports[`<PinnedMessagesCard /> unpin all should not allow to unpinall 1`] = `
class="mx_PinnedEventTile_top" class="mx_PinnedEventTile_top"
> >
<span <span
aria-labelledby=":rt8:" aria-labelledby="«rt8»"
class="mx_PinnedEventTile_sender mx_Username_color3" class="mx_PinnedEventTile_sender mx_Username_color3"
> >
@alice:example.org @alice:example.org
@@ -390,7 +390,7 @@ exports[`<PinnedMessagesCard /> unpin all should not allow to unpinall 1`] = `
aria-label="Open menu" aria-label="Open menu"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
data-state="closed" data-state="closed"
id="radix-:rtd:" id="radix-«rtd»"
role="button" role="button"
style="--cpd-icon-button-size: 24px;" style="--cpd-icon-button-size: 24px;"
tabindex="0" tabindex="0"
@@ -456,7 +456,7 @@ exports[`<PinnedMessagesCard /> unpin all should not allow to unpinall 1`] = `
class="mx_PinnedEventTile_top" class="mx_PinnedEventTile_top"
> >
<span <span
aria-labelledby=":rtf:" aria-labelledby="«rtf»"
class="mx_PinnedEventTile_sender mx_Username_color3" class="mx_PinnedEventTile_sender mx_Username_color3"
> >
@alice:example.org @alice:example.org
@@ -468,7 +468,7 @@ exports[`<PinnedMessagesCard /> unpin all should not allow to unpinall 1`] = `
aria-label="Open menu" aria-label="Open menu"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
data-state="closed" data-state="closed"
id="radix-:rtk:" id="radix-«rtk»"
role="button" role="button"
style="--cpd-icon-button-size: 24px;" style="--cpd-icon-button-size: 24px;"
tabindex="0" tabindex="0"

View File

@@ -15,7 +15,7 @@ exports[`<RoomSummaryCard /> has button to edit topic 1`] = `
class="mx_BaseCard_header_spacer" class="mx_BaseCard_header_spacer"
/> />
<button <button
aria-labelledby=":rm:" aria-labelledby="«rm»"
class="_icon-button_m2erp_8 _subtle-bg_m2erp_29" class="_icon-button_m2erp_8 _subtle-bg_m2erp_29"
data-testid="base-card-close-button" data-testid="base-card-close-button"
role="button" role="button"
@@ -189,7 +189,7 @@ exports[`<RoomSummaryCard /> has button to edit topic 1`] = `
<input <input
aria-hidden="true" aria-hidden="true"
class="_input_19o42_24" class="_input_19o42_24"
id=":rr:" id="«rr»"
type="checkbox" type="checkbox"
/> />
<div <div
@@ -711,7 +711,7 @@ exports[`<RoomSummaryCard /> renders the room summary 1`] = `
class="mx_BaseCard_header_spacer" class="mx_BaseCard_header_spacer"
/> />
<button <button
aria-labelledby=":r0:" aria-labelledby="«r0»"
class="_icon-button_m2erp_8 _subtle-bg_m2erp_29" class="_icon-button_m2erp_8 _subtle-bg_m2erp_29"
data-testid="base-card-close-button" data-testid="base-card-close-button"
role="button" role="button"
@@ -848,7 +848,7 @@ exports[`<RoomSummaryCard /> renders the room summary 1`] = `
<input <input
aria-hidden="true" aria-hidden="true"
class="_input_19o42_24" class="_input_19o42_24"
id=":r5:" id="«r5»"
type="checkbox" type="checkbox"
/> />
<div <div
@@ -1370,7 +1370,7 @@ exports[`<RoomSummaryCard /> renders the room topic in the summary 1`] = `
class="mx_BaseCard_header_spacer" class="mx_BaseCard_header_spacer"
/> />
<button <button
aria-labelledby=":rb:" aria-labelledby="«rb»"
class="_icon-button_m2erp_8 _subtle-bg_m2erp_29" class="_icon-button_m2erp_8 _subtle-bg_m2erp_29"
data-testid="base-card-close-button" data-testid="base-card-close-button"
role="button" role="button"
@@ -1544,7 +1544,7 @@ exports[`<RoomSummaryCard /> renders the room topic in the summary 1`] = `
<input <input
aria-hidden="true" aria-hidden="true"
class="_input_19o42_24" class="_input_19o42_24"
id=":rg:" id="«rg»"
type="checkbox" type="checkbox"
/> />
<div <div

View File

@@ -19,7 +19,7 @@ exports[`<UserInfo /> with crypto enabled renders <BasicUserInfo /> 1`] = `
</p> </p>
</div> </div>
<button <button
aria-labelledby=":r6i:" aria-labelledby="«r6i»"
class="_icon-button_m2erp_8 _subtle-bg_m2erp_29" class="_icon-button_m2erp_8 _subtle-bg_m2erp_29"
data-testid="base-card-close-button" data-testid="base-card-close-button"
role="button" role="button"
@@ -305,7 +305,7 @@ exports[`<UserInfo /> with crypto enabled should render a deactivate button for
</p> </p>
</div> </div>
<button <button
aria-labelledby=":r6s:" aria-labelledby="«r6s»"
class="_icon-button_m2erp_8 _subtle-bg_m2erp_29" class="_icon-button_m2erp_8 _subtle-bg_m2erp_29"
data-testid="base-card-close-button" data-testid="base-card-close-button"
role="button" role="button"

View File

@@ -55,7 +55,7 @@ exports[`RoomHeader dm does not show the face pile for DMs 1`] = `
style="--cpd-icon-button-size: 100%; --cpd-color-icon-tertiary: var(--cpd-color-icon-disabled);" style="--cpd-icon-button-size: 100%; --cpd-color-icon-tertiary: var(--cpd-color-icon-disabled);"
> >
<svg <svg
aria-labelledby=":r1c8:" aria-labelledby="«r1c8»"
fill="currentColor" fill="currentColor"
height="1em" height="1em"
viewBox="0 0 24 24" viewBox="0 0 24 24"
@@ -71,7 +71,7 @@ exports[`RoomHeader dm does not show the face pile for DMs 1`] = `
<button <button
aria-disabled="true" aria-disabled="true"
aria-label="There's no one here to call" aria-label="There's no one here to call"
aria-labelledby=":r1cd:" aria-labelledby="«r1cd»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
@@ -96,7 +96,7 @@ exports[`RoomHeader dm does not show the face pile for DMs 1`] = `
</button> </button>
<button <button
aria-label="Threads" aria-label="Threads"
aria-labelledby=":r1ci:" aria-labelledby="«r1ci»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
@@ -122,7 +122,7 @@ exports[`RoomHeader dm does not show the face pile for DMs 1`] = `
</button> </button>
<button <button
aria-label="Room info" aria-label="Room info"
aria-labelledby=":r1cn:" aria-labelledby="«r1cn»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"

View File

@@ -3,7 +3,7 @@
exports[`<VideoRoomChatButton /> renders button with an unread marker when room is unread 1`] = ` exports[`<VideoRoomChatButton /> renders button with an unread marker when room is unread 1`] = `
<button <button
aria-label="Chat" aria-label="Chat"
aria-labelledby=":r6:" aria-labelledby="«r6»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
data-indicator="default" data-indicator="default"
role="button" role="button"

View File

@@ -24,7 +24,7 @@ exports[`<RoomListHeaderView /> compose menu should display the compose menu 1`]
aria-label="Open space menu" aria-label="Open space menu"
class="_icon-button_m2erp_8 mx_SpaceMenu_button" class="_icon-button_m2erp_8 mx_SpaceMenu_button"
data-state="closed" data-state="closed"
id="radix-:r0:" id="radix-«r0»"
role="button" role="button"
style="--cpd-icon-button-size: 20px;" style="--cpd-icon-button-size: 20px;"
tabindex="0" tabindex="0"
@@ -56,7 +56,7 @@ exports[`<RoomListHeaderView /> compose menu should display the compose menu 1`]
aria-label="Add" aria-label="Add"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
data-state="closed" data-state="closed"
id="radix-:r2:" id="radix-«r2»"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
tabindex="0" tabindex="0"
@@ -113,7 +113,7 @@ exports[`<RoomListHeaderView /> compose menu should not display the compose menu
aria-label="Open space menu" aria-label="Open space menu"
class="_icon-button_m2erp_8 mx_SpaceMenu_button" class="_icon-button_m2erp_8 mx_SpaceMenu_button"
data-state="closed" data-state="closed"
id="radix-:r4:" id="radix-«r4»"
role="button" role="button"
style="--cpd-icon-button-size: 20px;" style="--cpd-icon-button-size: 20px;"
tabindex="0" tabindex="0"
@@ -196,7 +196,7 @@ exports[`<RoomListHeaderView /> space menu should display the space menu 1`] = `
aria-label="Open space menu" aria-label="Open space menu"
class="_icon-button_m2erp_8 mx_SpaceMenu_button" class="_icon-button_m2erp_8 mx_SpaceMenu_button"
data-state="closed" data-state="closed"
id="radix-:rs:" id="radix-«rs»"
role="button" role="button"
style="--cpd-icon-button-size: 20px;" style="--cpd-icon-button-size: 20px;"
tabindex="0" tabindex="0"
@@ -228,7 +228,7 @@ exports[`<RoomListHeaderView /> space menu should display the space menu 1`] = `
aria-label="Add" aria-label="Add"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
data-state="closed" data-state="closed"
id="radix-:ru:" id="radix-«ru»"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
tabindex="0" tabindex="0"
@@ -286,7 +286,7 @@ exports[`<RoomListHeaderView /> space menu should not display the space menu 1`]
aria-label="Add" aria-label="Add"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
data-state="closed" data-state="closed"
id="radix-:r10:" id="radix-«r10»"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
tabindex="0" tabindex="0"

View File

@@ -11,10 +11,10 @@ exports[`<RoomListItemMenuView /> should render the more options menu 1`] = `
aria-expanded="false" aria-expanded="false"
aria-haspopup="menu" aria-haspopup="menu"
aria-label="More Options" aria-label="More Options"
aria-labelledby=":r2:" aria-labelledby="«r2»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
data-state="closed" data-state="closed"
id="radix-:r0:" id="radix-«r0»"
role="button" role="button"
style="--cpd-icon-button-size: 24px;" style="--cpd-icon-button-size: 24px;"
tabindex="0" tabindex="0"
@@ -42,10 +42,10 @@ exports[`<RoomListItemMenuView /> should render the more options menu 1`] = `
aria-expanded="false" aria-expanded="false"
aria-haspopup="menu" aria-haspopup="menu"
aria-label="Notification options" aria-label="Notification options"
aria-labelledby=":r9:" aria-labelledby="«r9»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
data-state="closed" data-state="closed"
id="radix-:r7:" id="radix-«r7»"
role="button" role="button"
style="--cpd-icon-button-size: 24px;" style="--cpd-icon-button-size: 24px;"
tabindex="0" tabindex="0"
@@ -86,10 +86,10 @@ exports[`<RoomListItemMenuView /> should render the notification options menu 1`
aria-expanded="false" aria-expanded="false"
aria-haspopup="menu" aria-haspopup="menu"
aria-label="More Options" aria-label="More Options"
aria-labelledby=":ri:" aria-labelledby="«ri»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
data-state="closed" data-state="closed"
id="radix-:rg:" id="radix-«rg»"
role="button" role="button"
style="--cpd-icon-button-size: 24px;" style="--cpd-icon-button-size: 24px;"
tabindex="0" tabindex="0"
@@ -117,10 +117,10 @@ exports[`<RoomListItemMenuView /> should render the notification options menu 1`
aria-expanded="false" aria-expanded="false"
aria-haspopup="menu" aria-haspopup="menu"
aria-label="Notification options" aria-label="Notification options"
aria-labelledby=":rp:" aria-labelledby="«rp»"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
data-state="closed" data-state="closed"
id="radix-:rn:" id="radix-«rn»"
role="button" role="button"
style="--cpd-icon-button-size: 24px;" style="--cpd-icon-button-size: 24px;"
tabindex="0" tabindex="0"

View File

@@ -245,7 +245,7 @@ exports[`<RoomListPanel /> should render the RoomListSearch component when UICom
aria-label="Add" aria-label="Add"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
data-state="closed" data-state="closed"
id="radix-:r0:" id="radix-«r0»"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
tabindex="0" tabindex="0"

View File

@@ -23,11 +23,17 @@ exports[`<NotificationDecoration /> should render the invitation decoration 1`]
data-testid="notification-decoration" data-testid="notification-decoration"
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: center; --mx-flex-gap: var(--cpd-space-1-5x); --mx-flex-wrap: nowrap;" style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: center; --mx-flex-gap: var(--cpd-space-1-5x); --mx-flex-wrap: nowrap;"
> >
<span <svg
class="_unread-counter_9mg0k_8" fill="var(--cpd-color-icon-accent-primary)"
height="20px"
viewBox="0 0 24 24"
width="20px"
xmlns="http://www.w3.org/2000/svg"
> >
1 <path
</span> d="M4 4h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2m0 5.111a1 1 0 0 0 .514.874l7 3.89a1 1 0 0 0 .972 0l7-3.89a1 1 0 1 0-.972-1.748L12 11.856 5.486 8.237A1 1 0 0 0 4 9.111"
/>
</svg>
</div> </div>
</DocumentFragment> </DocumentFragment>
`; `;

View File

@@ -25,7 +25,7 @@ exports[`<PinnedEventTile /> should render pinned event 1`] = `
class="mx_PinnedEventTile_top" class="mx_PinnedEventTile_top"
> >
<span <span
aria-labelledby=":r0:" aria-labelledby="«r0»"
class="mx_PinnedEventTile_sender mx_Username_color2" class="mx_PinnedEventTile_sender mx_Username_color2"
> >
@alice:server.org @alice:server.org
@@ -37,7 +37,7 @@ exports[`<PinnedEventTile /> should render pinned event 1`] = `
aria-label="Open menu" aria-label="Open menu"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
data-state="closed" data-state="closed"
id="radix-:r5:" id="radix-«r5»"
role="button" role="button"
style="--cpd-icon-button-size: 24px;" style="--cpd-icon-button-size: 24px;"
tabindex="0" tabindex="0"
@@ -101,7 +101,7 @@ exports[`<PinnedEventTile /> should render pinned event with thread info 1`] = `
class="mx_PinnedEventTile_top" class="mx_PinnedEventTile_top"
> >
<span <span
aria-labelledby=":r8:" aria-labelledby="«r8»"
class="mx_PinnedEventTile_sender mx_Username_color2" class="mx_PinnedEventTile_sender mx_Username_color2"
> >
@alice:server.org @alice:server.org
@@ -113,7 +113,7 @@ exports[`<PinnedEventTile /> should render pinned event with thread info 1`] = `
aria-label="Open menu" aria-label="Open menu"
class="_icon-button_m2erp_8" class="_icon-button_m2erp_8"
data-state="closed" data-state="closed"
id="radix-:rd:" id="radix-«rd»"
role="button" role="button"
style="--cpd-icon-button-size: 24px;" style="--cpd-icon-button-size: 24px;"
tabindex="0" tabindex="0"
@@ -181,7 +181,7 @@ exports[`<PinnedEventTile /> should render pinned event with thread info 1`] = `
exports[`<PinnedEventTile /> should render the menu with all the options 1`] = ` exports[`<PinnedEventTile /> should render the menu with all the options 1`] = `
<div <div
aria-label="Open menu" aria-label="Open menu"
aria-labelledby="radix-:r10:" aria-labelledby="radix-«r10»"
aria-orientation="vertical" aria-orientation="vertical"
class="_menu_19sse_8" class="_menu_19sse_8"
data-align="start" data-align="start"
@@ -190,7 +190,7 @@ exports[`<PinnedEventTile /> should render the menu with all the options 1`] = `
data-side="right" data-side="right"
data-state="open" data-state="open"
dir="ltr" dir="ltr"
id="radix-:r11:" id="radix-«r11»"
role="menu" role="menu"
style="outline: none; --radix-dropdown-menu-content-transform-origin: var(--radix-popper-transform-origin); --radix-dropdown-menu-content-available-width: var(--radix-popper-available-width); --radix-dropdown-menu-content-available-height: var(--radix-popper-available-height); --radix-dropdown-menu-trigger-width: var(--radix-popper-anchor-width); --radix-dropdown-menu-trigger-height: var(--radix-popper-anchor-height); pointer-events: auto;" style="outline: none; --radix-dropdown-menu-content-transform-origin: var(--radix-popper-transform-origin); --radix-dropdown-menu-content-available-width: var(--radix-popper-available-width); --radix-dropdown-menu-content-available-height: var(--radix-popper-available-height); --radix-dropdown-menu-trigger-width: var(--radix-popper-anchor-width); --radix-dropdown-menu-trigger-height: var(--radix-popper-anchor-height); pointer-events: auto;"
tabindex="-1" tabindex="-1"
@@ -372,7 +372,7 @@ exports[`<PinnedEventTile /> should render the menu with all the options 1`] = `
exports[`<PinnedEventTile /> should render the menu without unpin and delete 1`] = ` exports[`<PinnedEventTile /> should render the menu without unpin and delete 1`] = `
<div <div
aria-label="Open menu" aria-label="Open menu"
aria-labelledby="radix-:rl:" aria-labelledby="radix-«rl»"
aria-orientation="vertical" aria-orientation="vertical"
class="_menu_19sse_8" class="_menu_19sse_8"
data-align="start" data-align="start"
@@ -381,7 +381,7 @@ exports[`<PinnedEventTile /> should render the menu without unpin and delete 1`]
data-side="right" data-side="right"
data-state="open" data-state="open"
dir="ltr" dir="ltr"
id="radix-:rm:" id="radix-«rm»"
role="menu" role="menu"
style="outline: none; --radix-dropdown-menu-content-transform-origin: var(--radix-popper-transform-origin); --radix-dropdown-menu-content-available-width: var(--radix-popper-available-width); --radix-dropdown-menu-content-available-height: var(--radix-popper-available-height); --radix-dropdown-menu-trigger-width: var(--radix-popper-anchor-width); --radix-dropdown-menu-trigger-height: var(--radix-popper-anchor-height); pointer-events: auto;" style="outline: none; --radix-dropdown-menu-content-transform-origin: var(--radix-popper-transform-origin); --radix-dropdown-menu-content-available-width: var(--radix-popper-available-width); --radix-dropdown-menu-content-available-height: var(--radix-popper-available-height); --radix-dropdown-menu-trigger-width: var(--radix-popper-anchor-width); --radix-dropdown-menu-trigger-height: var(--radix-popper-anchor-height); pointer-events: auto;"
tabindex="-1" tabindex="-1"

View File

@@ -4,7 +4,7 @@ exports[`ReadReceiptGroup <ReadReceiptPerson /> should display a tooltip 1`] = `
<div <div
class="_tooltip_6ode6_8" class="_tooltip_6ode6_8"
data-floating-ui-focusable="" data-floating-ui-focusable=""
id=":r6:" id="«r6»"
role="tooltip" role="tooltip"
style="position: absolute; left: 0px; top: 0px; transform: translate(0px, 0px);" style="position: absolute; left: 0px; top: 0px; transform: translate(0px, 0px);"
tabindex="-1" tabindex="-1"
@@ -22,7 +22,7 @@ exports[`ReadReceiptGroup <ReadReceiptPerson /> should display a tooltip 1`] = `
stroke="none" stroke="none"
/> />
<clippath <clippath
id=":r9:" id="«r9»"
> >
<rect <rect
height="10" height="10"
@@ -33,13 +33,13 @@ exports[`ReadReceiptGroup <ReadReceiptPerson /> should display a tooltip 1`] = `
</clippath> </clippath>
</svg> </svg>
<span <span
id=":r4:" id="«r4»"
> >
Alice Alice
</span> </span>
<span <span
class="_caption_6ode6_28 cpd-theme-dark" class="_caption_6ode6_28 cpd-theme-dark"
id=":r5:" id="«r5»"
> >
@alice:example.org @alice:example.org
</span> </span>

View File

@@ -19,7 +19,7 @@ exports[`<ThirdPartyMemberInfo /> should render invite 1`] = `
</p> </p>
</div> </div>
<button <button
aria-labelledby=":r0:" aria-labelledby="«r0»"
class="_icon-button_m2erp_8 _subtle-bg_m2erp_29" class="_icon-button_m2erp_8 _subtle-bg_m2erp_29"
data-testid="base-card-close-button" data-testid="base-card-close-button"
role="button" role="button"
@@ -93,7 +93,7 @@ exports[`<ThirdPartyMemberInfo /> should render invite when room in not availabl
</p> </p>
</div> </div>
<button <button
aria-labelledby=":r6:" aria-labelledby="«r6»"
class="_icon-button_m2erp_8 _subtle-bg_m2erp_29" class="_icon-button_m2erp_8 _subtle-bg_m2erp_29"
data-testid="base-card-close-button" data-testid="base-card-close-button"
role="button" role="button"

View File

@@ -47,7 +47,7 @@ exports[`MemberTileView RoomMemberTileView should display an verified E2EIcon wh
class="mx_MemberTileView_right" class="mx_MemberTileView_right"
> >
<div <div
aria-labelledby=":ri:" aria-labelledby="«ri»"
class="mx_E2EIconView" class="mx_E2EIconView"
> >
<svg <svg
@@ -116,7 +116,7 @@ exports[`MemberTileView RoomMemberTileView should display an warning E2EIcon whe
class="mx_MemberTileView_right" class="mx_MemberTileView_right"
> >
<div <div
aria-labelledby=":r8:" aria-labelledby="«r8»"
class="mx_E2EIconView" class="mx_E2EIconView"
> >
<svg <svg

View File

@@ -27,7 +27,7 @@ exports[`<LayoutSwitcher /> should render 1`] = `
<label <label
aria-label="Modern" aria-label="Modern"
class="_label_19upo_59" class="_label_19upo_59"
for="radix-:r0:" for="radix-«r0»"
> >
<div <div
class="mxLayoutSwitcher_LayoutSelector_LayoutRadio_inline" class="mxLayoutSwitcher_LayoutSelector_LayoutRadio_inline"
@@ -38,7 +38,7 @@ exports[`<LayoutSwitcher /> should render 1`] = `
<input <input
checked="" checked=""
class="_input_1e0uz_18" class="_input_1e0uz_18"
id="radix-:r0:" id="radix-«r0»"
name="layout" name="layout"
title="" title=""
type="radio" type="radio"
@@ -154,7 +154,7 @@ exports[`<LayoutSwitcher /> should render 1`] = `
<label <label
aria-label="Message bubbles" aria-label="Message bubbles"
class="_label_19upo_59" class="_label_19upo_59"
for="radix-:r9:" for="radix-«r9»"
> >
<div <div
class="mxLayoutSwitcher_LayoutSelector_LayoutRadio_inline" class="mxLayoutSwitcher_LayoutSelector_LayoutRadio_inline"
@@ -164,7 +164,7 @@ exports[`<LayoutSwitcher /> should render 1`] = `
> >
<input <input
class="_input_1e0uz_18" class="_input_1e0uz_18"
id="radix-:r9:" id="radix-«r9»"
name="layout" name="layout"
title="" title=""
type="radio" type="radio"
@@ -280,7 +280,7 @@ exports[`<LayoutSwitcher /> should render 1`] = `
<label <label
aria-label="IRC (experimental)" aria-label="IRC (experimental)"
class="_label_19upo_59" class="_label_19upo_59"
for="radix-:ri:" for="radix-«ri»"
> >
<div <div
class="mxLayoutSwitcher_LayoutSelector_LayoutRadio_inline" class="mxLayoutSwitcher_LayoutSelector_LayoutRadio_inline"
@@ -290,7 +290,7 @@ exports[`<LayoutSwitcher /> should render 1`] = `
> >
<input <input
class="_input_1e0uz_18" class="_input_1e0uz_18"
id="radix-:ri:" id="radix-«ri»"
name="layout" name="layout"
title="" title=""
type="radio" type="radio"
@@ -414,9 +414,9 @@ exports[`<LayoutSwitcher /> should render 1`] = `
class="_container_19o42_10" class="_container_19o42_10"
> >
<input <input
aria-describedby="radix-:rs:" aria-describedby="radix-«rs»"
class="_input_19o42_24" class="_input_19o42_24"
id="radix-:rr:" id="radix-«rr»"
name="compactLayout" name="compactLayout"
title="" title=""
type="checkbox" type="checkbox"
@@ -431,13 +431,13 @@ exports[`<LayoutSwitcher /> should render 1`] = `
> >
<label <label
class="_label_19upo_59" class="_label_19upo_59"
for="radix-:rr:" for="radix-«rr»"
> >
Show compact text and messages Show compact text and messages
</label> </label>
<span <span
class="_message_19upo_85 _help-message_19upo_91" class="_message_19upo_85 _help-message_19upo_91"
id="radix-:rs:" id="radix-«rs»"
> >
Modern layout must be selected to use this feature. Modern layout must be selected to use this feature.
</span> </span>

View File

@@ -10,22 +10,22 @@ exports[`<Notifications /> main notification switches renders only enable notifi
class="mx_SettingsFlag_label" class="mx_SettingsFlag_label"
> >
<div <div
id="mx_LabelledToggleSwitch_:r0:" id="mx_LabelledToggleSwitch_«r0»"
> >
Enable notifications for this account Enable notifications for this account
</div> </div>
<span <span
class="mx_Caption" class="mx_Caption"
id="mx_LabelledToggleSwitch_:r0:_caption" id="mx_LabelledToggleSwitch_«r0»_caption"
> >
Turn off to disable notifications on all your devices and sessions Turn off to disable notifications on all your devices and sessions
</span> </span>
</span> </span>
<div <div
aria-checked="false" aria-checked="false"
aria-describedby="mx_LabelledToggleSwitch_:r0:_caption" aria-describedby="mx_LabelledToggleSwitch_«r0»_caption"
aria-disabled="false" aria-disabled="false"
aria-labelledby="mx_LabelledToggleSwitch_:r0:" aria-labelledby="mx_LabelledToggleSwitch_«r0»"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_enabled" class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_enabled"
role="switch" role="switch"
tabindex="0" tabindex="0"

View File

@@ -30,7 +30,7 @@ exports[`<SetIdServer /> renders expected fields 1`] = `
> >
<label <label
class="_label_19upo_59" class="_label_19upo_59"
for="radix-:r0:" for="radix-«r0»"
> >
Enter a new identity server Enter a new identity server
</label> </label>
@@ -39,7 +39,7 @@ exports[`<SetIdServer /> renders expected fields 1`] = `
> >
<input <input
class="_control_sqdq4_10" class="_control_sqdq4_10"
id="radix-:r0:" id="radix-«r0»"
name="input" name="input"
placeholder="" placeholder=""
title="" title=""

View File

@@ -32,7 +32,7 @@ exports[`<ThemeChoicePanel /> custom theme should display custom theme 1`] = `
> >
<input <input
class="_input_19o42_24" class="_input_19o42_24"
id="radix-:r28:" id="radix-«r28»"
name="systemTheme" name="systemTheme"
title="" title=""
type="checkbox" type="checkbox"
@@ -47,7 +47,7 @@ exports[`<ThemeChoicePanel /> custom theme should display custom theme 1`] = `
> >
<label <label
class="_label_19upo_59" class="_label_19upo_59"
for="radix-:r28:" for="radix-«r28»"
> >
Match system theme Match system theme
</label> </label>
@@ -69,7 +69,7 @@ exports[`<ThemeChoicePanel /> custom theme should display custom theme 1`] = `
<input <input
checked="" checked=""
class="_input_1e0uz_18" class="_input_1e0uz_18"
id="radix-:r29:" id="radix-«r29»"
name="themeSelector" name="themeSelector"
title="" title=""
type="radio" type="radio"
@@ -85,7 +85,7 @@ exports[`<ThemeChoicePanel /> custom theme should display custom theme 1`] = `
> >
<label <label
class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label" class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label"
for="radix-:r29:" for="radix-«r29»"
> >
Light Light
</label> </label>
@@ -102,7 +102,7 @@ exports[`<ThemeChoicePanel /> custom theme should display custom theme 1`] = `
> >
<input <input
class="_input_1e0uz_18" class="_input_1e0uz_18"
id="radix-:r2a:" id="radix-«r2a»"
name="themeSelector" name="themeSelector"
title="" title=""
type="radio" type="radio"
@@ -118,7 +118,7 @@ exports[`<ThemeChoicePanel /> custom theme should display custom theme 1`] = `
> >
<label <label
class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label" class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label"
for="radix-:r2a:" for="radix-«r2a»"
> >
Dark Dark
</label> </label>
@@ -135,7 +135,7 @@ exports[`<ThemeChoicePanel /> custom theme should display custom theme 1`] = `
> >
<input <input
class="_input_1e0uz_18" class="_input_1e0uz_18"
id="radix-:r2b:" id="radix-«r2b»"
name="themeSelector" name="themeSelector"
title="" title=""
type="radio" type="radio"
@@ -151,7 +151,7 @@ exports[`<ThemeChoicePanel /> custom theme should display custom theme 1`] = `
> >
<label <label
class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label" class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label"
for="radix-:r2b:" for="radix-«r2b»"
> >
High contrast High contrast
</label> </label>
@@ -168,7 +168,7 @@ exports[`<ThemeChoicePanel /> custom theme should display custom theme 1`] = `
> >
<input <input
class="_input_1e0uz_18" class="_input_1e0uz_18"
id="radix-:r2c:" id="radix-«r2c»"
name="themeSelector" name="themeSelector"
title="" title=""
type="radio" type="radio"
@@ -184,7 +184,7 @@ exports[`<ThemeChoicePanel /> custom theme should display custom theme 1`] = `
> >
<label <label
class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label" class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label"
for="radix-:r2c:" for="radix-«r2c»"
> >
Alice theme Alice theme
</label> </label>
@@ -202,7 +202,7 @@ exports[`<ThemeChoicePanel /> custom theme should display custom theme 1`] = `
> >
<label <label
class="_label_19upo_59" class="_label_19upo_59"
for="radix-:r2d:" for="radix-«r2d»"
> >
Add custom theme Add custom theme
</label> </label>
@@ -210,9 +210,9 @@ exports[`<ThemeChoicePanel /> custom theme should display custom theme 1`] = `
class="_controls_17lij_8" class="_controls_17lij_8"
> >
<input <input
aria-describedby="radix-:r2e:" aria-describedby="radix-«r2e»"
class="_control_sqdq4_10" class="_control_sqdq4_10"
id="radix-:r2d:" id="radix-«r2d»"
name="input" name="input"
title="" title=""
value="" value=""
@@ -220,7 +220,7 @@ exports[`<ThemeChoicePanel /> custom theme should display custom theme 1`] = `
</div> </div>
<span <span
class="_message_19upo_85 _help-message_19upo_91" class="_message_19upo_85 _help-message_19upo_91"
id="radix-:r2e:" id="radix-«r2e»"
> >
Enter the URL of a custom theme you want to apply. Enter the URL of a custom theme you want to apply.
</span> </span>
@@ -240,7 +240,7 @@ exports[`<ThemeChoicePanel /> custom theme should display custom theme 1`] = `
</span> </span>
<button <button
aria-label="Delete" aria-label="Delete"
aria-labelledby=":r2f:" aria-labelledby="«r2f»"
class="_icon-button_m2erp_8 _destructive_m2erp_74" class="_icon-button_m2erp_8 _destructive_m2erp_74"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
@@ -309,7 +309,7 @@ exports[`<ThemeChoicePanel /> custom theme should render the custom theme sectio
> >
<input <input
class="_input_19o42_24" class="_input_19o42_24"
id="radix-:r10:" id="radix-«r10»"
name="systemTheme" name="systemTheme"
title="" title=""
type="checkbox" type="checkbox"
@@ -324,7 +324,7 @@ exports[`<ThemeChoicePanel /> custom theme should render the custom theme sectio
> >
<label <label
class="_label_19upo_59" class="_label_19upo_59"
for="radix-:r10:" for="radix-«r10»"
> >
Match system theme Match system theme
</label> </label>
@@ -346,7 +346,7 @@ exports[`<ThemeChoicePanel /> custom theme should render the custom theme sectio
<input <input
checked="" checked=""
class="_input_1e0uz_18" class="_input_1e0uz_18"
id="radix-:r11:" id="radix-«r11»"
name="themeSelector" name="themeSelector"
title="" title=""
type="radio" type="radio"
@@ -362,7 +362,7 @@ exports[`<ThemeChoicePanel /> custom theme should render the custom theme sectio
> >
<label <label
class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label" class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label"
for="radix-:r11:" for="radix-«r11»"
> >
Light Light
</label> </label>
@@ -379,7 +379,7 @@ exports[`<ThemeChoicePanel /> custom theme should render the custom theme sectio
> >
<input <input
class="_input_1e0uz_18" class="_input_1e0uz_18"
id="radix-:r12:" id="radix-«r12»"
name="themeSelector" name="themeSelector"
title="" title=""
type="radio" type="radio"
@@ -395,7 +395,7 @@ exports[`<ThemeChoicePanel /> custom theme should render the custom theme sectio
> >
<label <label
class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label" class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label"
for="radix-:r12:" for="radix-«r12»"
> >
Dark Dark
</label> </label>
@@ -412,7 +412,7 @@ exports[`<ThemeChoicePanel /> custom theme should render the custom theme sectio
> >
<input <input
class="_input_1e0uz_18" class="_input_1e0uz_18"
id="radix-:r13:" id="radix-«r13»"
name="themeSelector" name="themeSelector"
title="" title=""
type="radio" type="radio"
@@ -428,7 +428,7 @@ exports[`<ThemeChoicePanel /> custom theme should render the custom theme sectio
> >
<label <label
class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label" class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label"
for="radix-:r13:" for="radix-«r13»"
> >
High contrast High contrast
</label> </label>
@@ -445,7 +445,7 @@ exports[`<ThemeChoicePanel /> custom theme should render the custom theme sectio
> >
<input <input
class="_input_1e0uz_18" class="_input_1e0uz_18"
id="radix-:r14:" id="radix-«r14»"
name="themeSelector" name="themeSelector"
title="" title=""
type="radio" type="radio"
@@ -461,7 +461,7 @@ exports[`<ThemeChoicePanel /> custom theme should render the custom theme sectio
> >
<label <label
class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label" class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label"
for="radix-:r14:" for="radix-«r14»"
> >
Alice theme Alice theme
</label> </label>
@@ -479,7 +479,7 @@ exports[`<ThemeChoicePanel /> custom theme should render the custom theme sectio
> >
<label <label
class="_label_19upo_59" class="_label_19upo_59"
for="radix-:r15:" for="radix-«r15»"
> >
Add custom theme Add custom theme
</label> </label>
@@ -487,9 +487,9 @@ exports[`<ThemeChoicePanel /> custom theme should render the custom theme sectio
class="_controls_17lij_8" class="_controls_17lij_8"
> >
<input <input
aria-describedby="radix-:r16:" aria-describedby="radix-«r16»"
class="_control_sqdq4_10" class="_control_sqdq4_10"
id="radix-:r15:" id="radix-«r15»"
name="input" name="input"
title="" title=""
value="" value=""
@@ -497,7 +497,7 @@ exports[`<ThemeChoicePanel /> custom theme should render the custom theme sectio
</div> </div>
<span <span
class="_message_19upo_85 _help-message_19upo_91" class="_message_19upo_85 _help-message_19upo_91"
id="radix-:r16:" id="radix-«r16»"
> >
Enter the URL of a custom theme you want to apply. Enter the URL of a custom theme you want to apply.
</span> </span>
@@ -517,7 +517,7 @@ exports[`<ThemeChoicePanel /> custom theme should render the custom theme sectio
</span> </span>
<button <button
aria-label="Delete" aria-label="Delete"
aria-labelledby=":r17:" aria-labelledby="«r17»"
class="_icon-button_m2erp_8 _destructive_m2erp_74" class="_icon-button_m2erp_8 _destructive_m2erp_74"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
@@ -586,7 +586,7 @@ exports[`<ThemeChoicePanel /> renders the theme choice UI 1`] = `
> >
<input <input
class="_input_19o42_24" class="_input_19o42_24"
id="radix-:r0:" id="radix-«r0»"
name="systemTheme" name="systemTheme"
title="" title=""
type="checkbox" type="checkbox"
@@ -601,7 +601,7 @@ exports[`<ThemeChoicePanel /> renders the theme choice UI 1`] = `
> >
<label <label
class="_label_19upo_59" class="_label_19upo_59"
for="radix-:r0:" for="radix-«r0»"
> >
Match system theme Match system theme
</label> </label>
@@ -623,7 +623,7 @@ exports[`<ThemeChoicePanel /> renders the theme choice UI 1`] = `
<input <input
checked="" checked=""
class="_input_1e0uz_18" class="_input_1e0uz_18"
id="radix-:r1:" id="radix-«r1»"
name="themeSelector" name="themeSelector"
title="" title=""
type="radio" type="radio"
@@ -639,7 +639,7 @@ exports[`<ThemeChoicePanel /> renders the theme choice UI 1`] = `
> >
<label <label
class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label" class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label"
for="radix-:r1:" for="radix-«r1»"
> >
Light Light
</label> </label>
@@ -656,7 +656,7 @@ exports[`<ThemeChoicePanel /> renders the theme choice UI 1`] = `
> >
<input <input
class="_input_1e0uz_18" class="_input_1e0uz_18"
id="radix-:r2:" id="radix-«r2»"
name="themeSelector" name="themeSelector"
title="" title=""
type="radio" type="radio"
@@ -672,7 +672,7 @@ exports[`<ThemeChoicePanel /> renders the theme choice UI 1`] = `
> >
<label <label
class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label" class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label"
for="radix-:r2:" for="radix-«r2»"
> >
Dark Dark
</label> </label>
@@ -689,7 +689,7 @@ exports[`<ThemeChoicePanel /> renders the theme choice UI 1`] = `
> >
<input <input
class="_input_1e0uz_18" class="_input_1e0uz_18"
id="radix-:r3:" id="radix-«r3»"
name="themeSelector" name="themeSelector"
title="" title=""
type="radio" type="radio"
@@ -705,7 +705,7 @@ exports[`<ThemeChoicePanel /> renders the theme choice UI 1`] = `
> >
<label <label
class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label" class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label"
for="radix-:r3:" for="radix-«r3»"
> >
High contrast High contrast
</label> </label>

View File

@@ -23,7 +23,7 @@ exports[`<FilteredDeviceListHeader /> renders correctly when all devices are sel
> >
<input <input
aria-label="Deselect all" aria-label="Deselect all"
aria-labelledby=":r9:" aria-labelledby="«r9»"
checked="" checked=""
class="_input_1hel1_18" class="_input_1hel1_18"
data-testid="device-select-all-checkbox" data-testid="device-select-all-checkbox"
@@ -89,7 +89,7 @@ exports[`<FilteredDeviceListHeader /> renders correctly when no devices are sele
> >
<input <input
aria-label="Select all" aria-label="Select all"
aria-labelledby=":r0:" aria-labelledby="«r0»"
class="_input_1hel1_18" class="_input_1hel1_18"
data-testid="device-select-all-checkbox" data-testid="device-select-all-checkbox"
id="device-select-all-checkbox" id="device-select-all-checkbox"

View File

@@ -219,10 +219,10 @@ exports[`<AdvancedPanel /> <OtherSettings /> should display the blacklist of unv
class="_container_19o42_10" class="_container_19o42_10"
> >
<input <input
aria-describedby="radix-:r7:" aria-describedby="radix-«r7»"
checked="" checked=""
class="_input_19o42_24" class="_input_19o42_24"
id="radix-:r6:" id="radix-«r6»"
name="neverSendEncrypted" name="neverSendEncrypted"
title="" title=""
type="checkbox" type="checkbox"
@@ -237,13 +237,13 @@ exports[`<AdvancedPanel /> <OtherSettings /> should display the blacklist of unv
> >
<label <label
class="_label_19upo_59" class="_label_19upo_59"
for="radix-:r6:" for="radix-«r6»"
> >
In encrypted rooms, only send messages to verified users In encrypted rooms, only send messages to verified users
</label> </label>
<span <span
class="_message_19upo_85 _help-message_19upo_91" class="_message_19upo_85 _help-message_19upo_91"
id="radix-:r7:" id="radix-«r7»"
> >
Warning: users who have not explicitly verified with you (e.g. using emoji) will not receive your encrypted messages. Also, unverified devices of verified users will not receive your encrypted messages. Warning: users who have not explicitly verified with you (e.g. using emoji) will not receive your encrypted messages. Also, unverified devices of verified users will not receive your encrypted messages.
</span> </span>

View File

@@ -253,13 +253,13 @@ exports[`<ChangeRecoveryKey /> flow to set up a recovery key should ask the user
> >
<label <label
class="_label_19upo_59" class="_label_19upo_59"
for="radix-:r0:" for="radix-«r0»"
> >
Enter recovery key Enter recovery key
</label> </label>
<input <input
class="_control_sqdq4_10" class="_control_sqdq4_10"
id="radix-:r0:" id="radix-«r0»"
name="recoveryKey" name="recoveryKey"
required="" required=""
title="" title=""
@@ -388,23 +388,23 @@ exports[`<ChangeRecoveryKey /> flow to set up a recovery key should ask the user
<label <label
class="_label_19upo_59" class="_label_19upo_59"
data-invalid="true" data-invalid="true"
for="radix-:r0:" for="radix-«r0»"
> >
Enter recovery key Enter recovery key
</label> </label>
<input <input
aria-describedby="radix-:r1:" aria-describedby="radix-«r1»"
aria-invalid="true" aria-invalid="true"
class="_control_sqdq4_10" class="_control_sqdq4_10"
data-invalid="true" data-invalid="true"
id="radix-:r0:" id="radix-«r0»"
name="recoveryKey" name="recoveryKey"
required="" required=""
title="" title=""
/> />
<span <span
class="_message_19upo_85 _error-message_19upo_95" class="_message_19upo_85 _error-message_19upo_95"
id="radix-:r1:" id="radix-«r1»"
> >
<svg <svg
fill="currentColor" fill="currentColor"

View File

@@ -21,7 +21,7 @@ exports[`<Notifications /> correctly handles the loading/disabled state 1`] = `
class="mx_SettingsFlag_label" class="mx_SettingsFlag_label"
> >
<div <div
id="mx_LabelledToggleSwitch_:r17:" id="mx_LabelledToggleSwitch_«r17»"
> >
Enable notifications for this account Enable notifications for this account
</div> </div>
@@ -29,7 +29,7 @@ exports[`<Notifications /> correctly handles the loading/disabled state 1`] = `
<div <div
aria-checked="true" aria-checked="true"
aria-disabled="true" aria-disabled="true"
aria-labelledby="mx_LabelledToggleSwitch_:r17:" aria-labelledby="mx_LabelledToggleSwitch_«r17»"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on" class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on"
role="switch" role="switch"
tabindex="0" tabindex="0"
@@ -46,7 +46,7 @@ exports[`<Notifications /> correctly handles the loading/disabled state 1`] = `
class="mx_SettingsFlag_label" class="mx_SettingsFlag_label"
> >
<div <div
id="mx_LabelledToggleSwitch_:r18:" id="mx_LabelledToggleSwitch_«r18»"
> >
Enable desktop notifications for this session Enable desktop notifications for this session
</div> </div>
@@ -54,7 +54,7 @@ exports[`<Notifications /> correctly handles the loading/disabled state 1`] = `
<div <div
aria-checked="false" aria-checked="false"
aria-disabled="false" aria-disabled="false"
aria-labelledby="mx_LabelledToggleSwitch_:r18:" aria-labelledby="mx_LabelledToggleSwitch_«r18»"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_enabled" class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_enabled"
role="switch" role="switch"
tabindex="0" tabindex="0"
@@ -71,7 +71,7 @@ exports[`<Notifications /> correctly handles the loading/disabled state 1`] = `
class="mx_SettingsFlag_label" class="mx_SettingsFlag_label"
> >
<div <div
id="mx_LabelledToggleSwitch_:r19:" id="mx_LabelledToggleSwitch_«r19»"
> >
Show message preview in desktop notification Show message preview in desktop notification
</div> </div>
@@ -79,7 +79,7 @@ exports[`<Notifications /> correctly handles the loading/disabled state 1`] = `
<div <div
aria-checked="false" aria-checked="false"
aria-disabled="false" aria-disabled="false"
aria-labelledby="mx_LabelledToggleSwitch_:r19:" aria-labelledby="mx_LabelledToggleSwitch_«r19»"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_enabled" class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_enabled"
role="switch" role="switch"
tabindex="0" tabindex="0"
@@ -96,7 +96,7 @@ exports[`<Notifications /> correctly handles the loading/disabled state 1`] = `
class="mx_SettingsFlag_label" class="mx_SettingsFlag_label"
> >
<div <div
id="mx_LabelledToggleSwitch_:r1a:" id="mx_LabelledToggleSwitch_«r1a»"
> >
Enable audible notifications for this session Enable audible notifications for this session
</div> </div>
@@ -104,7 +104,7 @@ exports[`<Notifications /> correctly handles the loading/disabled state 1`] = `
<div <div
aria-checked="true" aria-checked="true"
aria-disabled="false" aria-disabled="false"
aria-labelledby="mx_LabelledToggleSwitch_:r1a:" aria-labelledby="mx_LabelledToggleSwitch_«r1a»"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on mx_ToggleSwitch_enabled" class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on mx_ToggleSwitch_enabled"
role="switch" role="switch"
tabindex="0" tabindex="0"
@@ -758,7 +758,7 @@ exports[`<Notifications /> correctly handles the loading/disabled state 1`] = `
class="_container_1hel1_10" class="_container_1hel1_10"
> >
<input <input
aria-describedby=":r24:" aria-describedby="«r24»"
checked="" checked=""
class="_input_1hel1_18" class="_input_1hel1_18"
disabled="" disabled=""
@@ -798,7 +798,7 @@ exports[`<Notifications /> correctly handles the loading/disabled state 1`] = `
</label> </label>
<span <span
class="_message_19upo_85 _help-message_19upo_91" class="_message_19upo_85 _help-message_19upo_91"
id=":r24:" id="«r24»"
> >
Enter keywords here, or use for spelling variations or nicknames Enter keywords here, or use for spelling variations or nicknames
</span> </span>
@@ -998,7 +998,7 @@ exports[`<Notifications /> matches the snapshot 1`] = `
class="mx_SettingsFlag_label" class="mx_SettingsFlag_label"
> >
<div <div
id="mx_LabelledToggleSwitch_:r0:" id="mx_LabelledToggleSwitch_«r0»"
> >
Enable notifications for this account Enable notifications for this account
</div> </div>
@@ -1006,7 +1006,7 @@ exports[`<Notifications /> matches the snapshot 1`] = `
<div <div
aria-checked="true" aria-checked="true"
aria-disabled="false" aria-disabled="false"
aria-labelledby="mx_LabelledToggleSwitch_:r0:" aria-labelledby="mx_LabelledToggleSwitch_«r0»"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on mx_ToggleSwitch_enabled" class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on mx_ToggleSwitch_enabled"
role="switch" role="switch"
tabindex="0" tabindex="0"
@@ -1023,7 +1023,7 @@ exports[`<Notifications /> matches the snapshot 1`] = `
class="mx_SettingsFlag_label" class="mx_SettingsFlag_label"
> >
<div <div
id="mx_LabelledToggleSwitch_:r1:" id="mx_LabelledToggleSwitch_«r1»"
> >
Enable desktop notifications for this session Enable desktop notifications for this session
</div> </div>
@@ -1031,7 +1031,7 @@ exports[`<Notifications /> matches the snapshot 1`] = `
<div <div
aria-checked="false" aria-checked="false"
aria-disabled="false" aria-disabled="false"
aria-labelledby="mx_LabelledToggleSwitch_:r1:" aria-labelledby="mx_LabelledToggleSwitch_«r1»"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_enabled" class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_enabled"
role="switch" role="switch"
tabindex="0" tabindex="0"
@@ -1048,7 +1048,7 @@ exports[`<Notifications /> matches the snapshot 1`] = `
class="mx_SettingsFlag_label" class="mx_SettingsFlag_label"
> >
<div <div
id="mx_LabelledToggleSwitch_:r2:" id="mx_LabelledToggleSwitch_«r2»"
> >
Show message preview in desktop notification Show message preview in desktop notification
</div> </div>
@@ -1056,7 +1056,7 @@ exports[`<Notifications /> matches the snapshot 1`] = `
<div <div
aria-checked="false" aria-checked="false"
aria-disabled="false" aria-disabled="false"
aria-labelledby="mx_LabelledToggleSwitch_:r2:" aria-labelledby="mx_LabelledToggleSwitch_«r2»"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_enabled" class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_enabled"
role="switch" role="switch"
tabindex="0" tabindex="0"
@@ -1073,7 +1073,7 @@ exports[`<Notifications /> matches the snapshot 1`] = `
class="mx_SettingsFlag_label" class="mx_SettingsFlag_label"
> >
<div <div
id="mx_LabelledToggleSwitch_:r3:" id="mx_LabelledToggleSwitch_«r3»"
> >
Enable audible notifications for this session Enable audible notifications for this session
</div> </div>
@@ -1081,7 +1081,7 @@ exports[`<Notifications /> matches the snapshot 1`] = `
<div <div
aria-checked="true" aria-checked="true"
aria-disabled="false" aria-disabled="false"
aria-labelledby="mx_LabelledToggleSwitch_:r3:" aria-labelledby="mx_LabelledToggleSwitch_«r3»"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on mx_ToggleSwitch_enabled" class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on mx_ToggleSwitch_enabled"
role="switch" role="switch"
tabindex="0" tabindex="0"
@@ -1724,7 +1724,7 @@ exports[`<Notifications /> matches the snapshot 1`] = `
class="_container_1hel1_10" class="_container_1hel1_10"
> >
<input <input
aria-describedby=":rt:" aria-describedby="«rt»"
checked="" checked=""
class="_input_1hel1_18" class="_input_1hel1_18"
id="checkbox_kBerF1ejc4" id="checkbox_kBerF1ejc4"
@@ -1763,7 +1763,7 @@ exports[`<Notifications /> matches the snapshot 1`] = `
</label> </label>
<span <span
class="_message_19upo_85 _help-message_19upo_91" class="_message_19upo_85 _help-message_19upo_91"
id=":rt:" id="«rt»"
> >
Enter keywords here, or use for spelling variations or nicknames Enter keywords here, or use for spelling variations or nicknames
</span> </span>

View File

@@ -46,7 +46,7 @@ exports[`AppearanceUserSettingsTab should render 1`] = `
<input <input
class="_input_1e0uz_18" class="_input_1e0uz_18"
disabled="" disabled=""
id="radix-:r0:" id="radix-«r0»"
name="themeSelector" name="themeSelector"
title="" title=""
type="radio" type="radio"
@@ -62,7 +62,7 @@ exports[`AppearanceUserSettingsTab should render 1`] = `
> >
<label <label
class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label" class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label"
for="radix-:r0:" for="radix-«r0»"
> >
Light Light
</label> </label>
@@ -80,7 +80,7 @@ exports[`AppearanceUserSettingsTab should render 1`] = `
<input <input
class="_input_1e0uz_18" class="_input_1e0uz_18"
disabled="" disabled=""
id="radix-:r1:" id="radix-«r1»"
name="themeSelector" name="themeSelector"
title="" title=""
type="radio" type="radio"
@@ -96,7 +96,7 @@ exports[`AppearanceUserSettingsTab should render 1`] = `
> >
<label <label
class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label" class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label"
for="radix-:r1:" for="radix-«r1»"
> >
Dark Dark
</label> </label>
@@ -114,7 +114,7 @@ exports[`AppearanceUserSettingsTab should render 1`] = `
<input <input
class="_input_1e0uz_18" class="_input_1e0uz_18"
disabled="" disabled=""
id="radix-:r2:" id="radix-«r2»"
name="themeSelector" name="themeSelector"
title="" title=""
type="radio" type="radio"
@@ -130,7 +130,7 @@ exports[`AppearanceUserSettingsTab should render 1`] = `
> >
<label <label
class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label" class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label"
for="radix-:r2:" for="radix-«r2»"
> >
High contrast High contrast
</label> </label>
@@ -170,7 +170,7 @@ exports[`AppearanceUserSettingsTab should render 1`] = `
<label <label
aria-label="Modern" aria-label="Modern"
class="_label_19upo_59" class="_label_19upo_59"
for="radix-:r3:" for="radix-«r3»"
> >
<div <div
class="mxLayoutSwitcher_LayoutSelector_LayoutRadio_inline" class="mxLayoutSwitcher_LayoutSelector_LayoutRadio_inline"
@@ -181,7 +181,7 @@ exports[`AppearanceUserSettingsTab should render 1`] = `
<input <input
checked="" checked=""
class="_input_1e0uz_18" class="_input_1e0uz_18"
id="radix-:r3:" id="radix-«r3»"
name="layout" name="layout"
title="" title=""
type="radio" type="radio"
@@ -297,7 +297,7 @@ exports[`AppearanceUserSettingsTab should render 1`] = `
<label <label
aria-label="Message bubbles" aria-label="Message bubbles"
class="_label_19upo_59" class="_label_19upo_59"
for="radix-:rc:" for="radix-«rc»"
> >
<div <div
class="mxLayoutSwitcher_LayoutSelector_LayoutRadio_inline" class="mxLayoutSwitcher_LayoutSelector_LayoutRadio_inline"
@@ -307,7 +307,7 @@ exports[`AppearanceUserSettingsTab should render 1`] = `
> >
<input <input
class="_input_1e0uz_18" class="_input_1e0uz_18"
id="radix-:rc:" id="radix-«rc»"
name="layout" name="layout"
title="" title=""
type="radio" type="radio"
@@ -423,7 +423,7 @@ exports[`AppearanceUserSettingsTab should render 1`] = `
<label <label
aria-label="IRC (experimental)" aria-label="IRC (experimental)"
class="_label_19upo_59" class="_label_19upo_59"
for="radix-:rl:" for="radix-«rl»"
> >
<div <div
class="mxLayoutSwitcher_LayoutSelector_LayoutRadio_inline" class="mxLayoutSwitcher_LayoutSelector_LayoutRadio_inline"
@@ -433,7 +433,7 @@ exports[`AppearanceUserSettingsTab should render 1`] = `
> >
<input <input
class="_input_1e0uz_18" class="_input_1e0uz_18"
id="radix-:rl:" id="radix-«rl»"
name="layout" name="layout"
title="" title=""
type="radio" type="radio"
@@ -557,9 +557,9 @@ exports[`AppearanceUserSettingsTab should render 1`] = `
class="_container_19o42_10" class="_container_19o42_10"
> >
<input <input
aria-describedby="radix-:rv:" aria-describedby="radix-«rv»"
class="_input_19o42_24" class="_input_19o42_24"
id="radix-:ru:" id="radix-«ru»"
name="compactLayout" name="compactLayout"
title="" title=""
type="checkbox" type="checkbox"
@@ -574,13 +574,13 @@ exports[`AppearanceUserSettingsTab should render 1`] = `
> >
<label <label
class="_label_19upo_59" class="_label_19upo_59"
for="radix-:ru:" for="radix-«ru»"
> >
Show compact text and messages Show compact text and messages
</label> </label>
<span <span
class="_message_19upo_85 _help-message_19upo_91" class="_message_19upo_85 _help-message_19upo_91"
id="radix-:rv:" id="radix-«rv»"
> >
Modern layout must be selected to use this feature. Modern layout must be selected to use this feature.
</span> </span>

View File

@@ -213,7 +213,7 @@ exports[`<SecurityUserSettingsTab /> renders security section 1`] = `
> >
<label <label
class="_label_19upo_59" class="_label_19upo_59"
for="radix-:r1:" for="radix-«r1»"
> >
Enter a new identity server Enter a new identity server
</label> </label>
@@ -222,7 +222,7 @@ exports[`<SecurityUserSettingsTab /> renders security section 1`] = `
> >
<input <input
class="_control_sqdq4_10" class="_control_sqdq4_10"
id="radix-:r1:" id="radix-«r1»"
name="input" name="input"
placeholder="" placeholder=""
title="" title=""

View File

@@ -397,7 +397,7 @@ exports[`<SessionManagerTab /> goes to filtered list from security recommendatio
> >
<input <input
aria-label="Select all" aria-label="Select all"
aria-labelledby=":r4q:" aria-labelledby="«r4q»"
class="_input_1hel1_18" class="_input_1hel1_18"
data-testid="device-select-all-checkbox" data-testid="device-select-all-checkbox"
id="device-select-all-checkbox" id="device-select-all-checkbox"

View File

@@ -51,7 +51,7 @@ exports[`<SidebarUserSettingsTab /> renders sidebar settings with guest spa url
class="_container_1hel1_10" class="_container_1hel1_10"
> >
<input <input
aria-describedby=":r1:" aria-describedby="«r1»"
checked="" checked=""
class="_input_1hel1_18" class="_input_1hel1_18"
disabled="" disabled=""
@@ -99,7 +99,7 @@ exports[`<SidebarUserSettingsTab /> renders sidebar settings with guest spa url
</label> </label>
<span <span
class="_message_19upo_85 _help-message_19upo_91" class="_message_19upo_85 _help-message_19upo_91"
id=":r1:" id="«r1»"
> >
Home is useful for getting an overview of everything. Home is useful for getting an overview of everything.
</span> </span>
@@ -119,7 +119,7 @@ exports[`<SidebarUserSettingsTab /> renders sidebar settings with guest spa url
class="_container_1hel1_10" class="_container_1hel1_10"
> >
<input <input
aria-describedby=":r5:" aria-describedby="«r5»"
class="_input_1hel1_18" class="_input_1hel1_18"
data-testid="mx_SidebarUserSettingsTab_homeAllRoomsCheckbox" data-testid="mx_SidebarUserSettingsTab_homeAllRoomsCheckbox"
id="checkbox_38QgU2Pomx" id="checkbox_38QgU2Pomx"
@@ -154,7 +154,7 @@ exports[`<SidebarUserSettingsTab /> renders sidebar settings with guest spa url
</label> </label>
<span <span
class="_message_19upo_85 _help-message_19upo_91" class="_message_19upo_85 _help-message_19upo_91"
id=":r5:" id="«r5»"
> >
Show all your rooms in Home, even if they're in a space. Show all your rooms in Home, even if they're in a space.
</span> </span>
@@ -174,7 +174,7 @@ exports[`<SidebarUserSettingsTab /> renders sidebar settings with guest spa url
class="_container_1hel1_10" class="_container_1hel1_10"
> >
<input <input
aria-describedby=":r9:" aria-describedby="«r9»"
class="_input_1hel1_18" class="_input_1hel1_18"
id="checkbox_wKpa6hpi3Y" id="checkbox_wKpa6hpi3Y"
type="checkbox" type="checkbox"
@@ -220,7 +220,7 @@ exports[`<SidebarUserSettingsTab /> renders sidebar settings with guest spa url
</label> </label>
<span <span
class="_message_19upo_85 _help-message_19upo_91" class="_message_19upo_85 _help-message_19upo_91"
id=":r9:" id="«r9»"
> >
Group all your favourite rooms and people in one place. Group all your favourite rooms and people in one place.
</span> </span>
@@ -240,7 +240,7 @@ exports[`<SidebarUserSettingsTab /> renders sidebar settings with guest spa url
class="_container_1hel1_10" class="_container_1hel1_10"
> >
<input <input
aria-describedby=":rd:" aria-describedby="«rd»"
class="_input_1hel1_18" class="_input_1hel1_18"
id="checkbox_EetmBG4yVC" id="checkbox_EetmBG4yVC"
type="checkbox" type="checkbox"
@@ -289,7 +289,7 @@ exports[`<SidebarUserSettingsTab /> renders sidebar settings with guest spa url
</label> </label>
<span <span
class="_message_19upo_85 _help-message_19upo_91" class="_message_19upo_85 _help-message_19upo_91"
id=":rd:" id="«rd»"
> >
Group all your people in one place. Group all your people in one place.
</span> </span>
@@ -309,7 +309,7 @@ exports[`<SidebarUserSettingsTab /> renders sidebar settings with guest spa url
class="_container_1hel1_10" class="_container_1hel1_10"
> >
<input <input
aria-describedby=":rh:" aria-describedby="«rh»"
class="_input_1hel1_18" class="_input_1hel1_18"
id="checkbox_eEefiPqpMR" id="checkbox_eEefiPqpMR"
type="checkbox" type="checkbox"
@@ -343,7 +343,7 @@ exports[`<SidebarUserSettingsTab /> renders sidebar settings with guest spa url
</label> </label>
<span <span
class="_message_19upo_85 _help-message_19upo_91" class="_message_19upo_85 _help-message_19upo_91"
id=":rh:" id="«rh»"
> >
Group all your rooms that aren't part of a space in one place. Group all your rooms that aren't part of a space in one place.
</span> </span>
@@ -363,7 +363,7 @@ exports[`<SidebarUserSettingsTab /> renders sidebar settings with guest spa url
class="_container_1hel1_10" class="_container_1hel1_10"
> >
<input <input
aria-describedby=":rl:" aria-describedby="«rl»"
class="_input_1hel1_18" class="_input_1hel1_18"
id="checkbox_MwbPDmfGtm" id="checkbox_MwbPDmfGtm"
type="checkbox" type="checkbox"
@@ -409,7 +409,7 @@ exports[`<SidebarUserSettingsTab /> renders sidebar settings with guest spa url
</label> </label>
<span <span
class="_message_19upo_85 _help-message_19upo_91" class="_message_19upo_85 _help-message_19upo_91"
id=":rl:" id="«rl»"
> >
Group all private video rooms and conferences. In conferences you can invite people outside of matrix. Group all private video rooms and conferences. In conferences you can invite people outside of matrix.
</span> </span>
@@ -476,7 +476,7 @@ exports[`<SidebarUserSettingsTab /> renders sidebar settings without guest spa u
class="_container_1hel1_10" class="_container_1hel1_10"
> >
<input <input
aria-describedby=":rp:" aria-describedby="«rp»"
checked="" checked=""
class="_input_1hel1_18" class="_input_1hel1_18"
disabled="" disabled=""
@@ -524,7 +524,7 @@ exports[`<SidebarUserSettingsTab /> renders sidebar settings without guest spa u
</label> </label>
<span <span
class="_message_19upo_85 _help-message_19upo_91" class="_message_19upo_85 _help-message_19upo_91"
id=":rp:" id="«rp»"
> >
Home is useful for getting an overview of everything. Home is useful for getting an overview of everything.
</span> </span>
@@ -544,7 +544,7 @@ exports[`<SidebarUserSettingsTab /> renders sidebar settings without guest spa u
class="_container_1hel1_10" class="_container_1hel1_10"
> >
<input <input
aria-describedby=":rt:" aria-describedby="«rt»"
class="_input_1hel1_18" class="_input_1hel1_18"
data-testid="mx_SidebarUserSettingsTab_homeAllRoomsCheckbox" data-testid="mx_SidebarUserSettingsTab_homeAllRoomsCheckbox"
id="checkbox_38QgU2Pomx" id="checkbox_38QgU2Pomx"
@@ -579,7 +579,7 @@ exports[`<SidebarUserSettingsTab /> renders sidebar settings without guest spa u
</label> </label>
<span <span
class="_message_19upo_85 _help-message_19upo_91" class="_message_19upo_85 _help-message_19upo_91"
id=":rt:" id="«rt»"
> >
Show all your rooms in Home, even if they're in a space. Show all your rooms in Home, even if they're in a space.
</span> </span>
@@ -599,7 +599,7 @@ exports[`<SidebarUserSettingsTab /> renders sidebar settings without guest spa u
class="_container_1hel1_10" class="_container_1hel1_10"
> >
<input <input
aria-describedby=":r11:" aria-describedby="«r11»"
class="_input_1hel1_18" class="_input_1hel1_18"
id="checkbox_wKpa6hpi3Y" id="checkbox_wKpa6hpi3Y"
type="checkbox" type="checkbox"
@@ -645,7 +645,7 @@ exports[`<SidebarUserSettingsTab /> renders sidebar settings without guest spa u
</label> </label>
<span <span
class="_message_19upo_85 _help-message_19upo_91" class="_message_19upo_85 _help-message_19upo_91"
id=":r11:" id="«r11»"
> >
Group all your favourite rooms and people in one place. Group all your favourite rooms and people in one place.
</span> </span>
@@ -665,7 +665,7 @@ exports[`<SidebarUserSettingsTab /> renders sidebar settings without guest spa u
class="_container_1hel1_10" class="_container_1hel1_10"
> >
<input <input
aria-describedby=":r15:" aria-describedby="«r15»"
class="_input_1hel1_18" class="_input_1hel1_18"
id="checkbox_EetmBG4yVC" id="checkbox_EetmBG4yVC"
type="checkbox" type="checkbox"
@@ -714,7 +714,7 @@ exports[`<SidebarUserSettingsTab /> renders sidebar settings without guest spa u
</label> </label>
<span <span
class="_message_19upo_85 _help-message_19upo_91" class="_message_19upo_85 _help-message_19upo_91"
id=":r15:" id="«r15»"
> >
Group all your people in one place. Group all your people in one place.
</span> </span>
@@ -734,7 +734,7 @@ exports[`<SidebarUserSettingsTab /> renders sidebar settings without guest spa u
class="_container_1hel1_10" class="_container_1hel1_10"
> >
<input <input
aria-describedby=":r19:" aria-describedby="«r19»"
class="_input_1hel1_18" class="_input_1hel1_18"
id="checkbox_eEefiPqpMR" id="checkbox_eEefiPqpMR"
type="checkbox" type="checkbox"
@@ -768,7 +768,7 @@ exports[`<SidebarUserSettingsTab /> renders sidebar settings without guest spa u
</label> </label>
<span <span
class="_message_19upo_85 _help-message_19upo_91" class="_message_19upo_85 _help-message_19upo_91"
id=":r19:" id="«r19»"
> >
Group all your rooms that aren't part of a space in one place. Group all your rooms that aren't part of a space in one place.
</span> </span>
@@ -788,7 +788,7 @@ exports[`<SidebarUserSettingsTab /> renders sidebar settings without guest spa u
class="_container_1hel1_10" class="_container_1hel1_10"
> >
<input <input
aria-describedby=":r1d:" aria-describedby="«r1d»"
class="_input_1hel1_18" class="_input_1hel1_18"
id="checkbox_MwbPDmfGtm" id="checkbox_MwbPDmfGtm"
type="checkbox" type="checkbox"
@@ -834,7 +834,7 @@ exports[`<SidebarUserSettingsTab /> renders sidebar settings without guest spa u
</label> </label>
<span <span
class="_message_19upo_85 _help-message_19upo_91" class="_message_19upo_85 _help-message_19upo_91"
id=":r1d:" id="«r1d»"
> >
Group all private video rooms and conferences. Group all private video rooms and conferences.
</span> </span>

View File

@@ -231,12 +231,12 @@ exports[`<SpacePanel /> should show all activated MetaSpaces in the correct orde
class="mx_ThreadsActivityCentre_container" class="mx_ThreadsActivityCentre_container"
> >
<button <button
aria-controls=":r12:" aria-controls="«r12»"
aria-describedby=":r12:" aria-describedby="«r12»"
aria-expanded="true" aria-expanded="true"
aria-haspopup="dialog" aria-haspopup="dialog"
aria-label="Threads" aria-label="Threads"
aria-labelledby=":r14:" aria-labelledby="«r14»"
class="_icon-button_m2erp_8 mx_ThreadsActivityCentreButton" class="_icon-button_m2erp_8 mx_ThreadsActivityCentreButton"
data-floating-ui-inert="" data-floating-ui-inert=""
role="button" role="button"
@@ -275,7 +275,7 @@ exports[`<SpacePanel /> should show all activated MetaSpaces in the correct orde
tabindex="0" tabindex="0"
/> />
<span <span
aria-owns=":r19:" aria-owns="«r19»"
data-floating-ui-inert="" data-floating-ui-inert=""
style="border: 0px; height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: fixed; white-space: nowrap; width: 1px; top: 0px; left: 0px;" style="border: 0px; height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: fixed; white-space: nowrap; width: 1px; top: 0px; left: 0px;"
/> />

View File

@@ -4,7 +4,7 @@ exports[`<SpaceSettingsVisibilityTab /> for a public space Access renders guest
<div <div
aria-checked="true" aria-checked="true"
aria-disabled="false" aria-disabled="false"
aria-labelledby="mx_LabelledToggleSwitch_:rb:" aria-labelledby="mx_LabelledToggleSwitch_«rb»"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on mx_ToggleSwitch_enabled" class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on mx_ToggleSwitch_enabled"
role="switch" role="switch"
tabindex="0" tabindex="0"
@@ -122,7 +122,7 @@ exports[`<SpaceSettingsVisibilityTab /> renders container 1`] = `
class="mx_SettingsFlag_label" class="mx_SettingsFlag_label"
> >
<div <div
id="mx_LabelledToggleSwitch_:r0:" id="mx_LabelledToggleSwitch_«r0»"
> >
Preview Space Preview Space
</div> </div>
@@ -130,7 +130,7 @@ exports[`<SpaceSettingsVisibilityTab /> renders container 1`] = `
<div <div
aria-checked="true" aria-checked="true"
aria-disabled="false" aria-disabled="false"
aria-labelledby="mx_LabelledToggleSwitch_:r0:" aria-labelledby="mx_LabelledToggleSwitch_«r0»"
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on mx_ToggleSwitch_enabled" class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on mx_ToggleSwitch_enabled"
role="switch" role="switch"
tabindex="0" tabindex="0"

View File

@@ -2,7 +2,7 @@
exports[`ThreadsActivityCentre renders notifications matching the snapshot 1`] = ` exports[`ThreadsActivityCentre renders notifications matching the snapshot 1`] = `
<div <div
aria-labelledby="radix-:r33:" aria-labelledby="radix-«r33»"
aria-orientation="vertical" aria-orientation="vertical"
class="_menu_19sse_8" class="_menu_19sse_8"
data-align="start" data-align="start"
@@ -11,14 +11,14 @@ exports[`ThreadsActivityCentre renders notifications matching the snapshot 1`] =
data-side="top" data-side="top"
data-state="open" data-state="open"
dir="ltr" dir="ltr"
id="radix-:r34:" id="radix-«r34»"
role="menu" role="menu"
style="outline: none; --radix-dropdown-menu-content-transform-origin: var(--radix-popper-transform-origin); --radix-dropdown-menu-content-available-width: var(--radix-popper-available-width); --radix-dropdown-menu-content-available-height: var(--radix-popper-available-height); --radix-dropdown-menu-trigger-width: var(--radix-popper-anchor-width); --radix-dropdown-menu-trigger-height: var(--radix-popper-anchor-height); pointer-events: auto;" style="outline: none; --radix-dropdown-menu-content-transform-origin: var(--radix-popper-transform-origin); --radix-dropdown-menu-content-available-width: var(--radix-popper-available-width); --radix-dropdown-menu-content-available-height: var(--radix-popper-available-height); --radix-dropdown-menu-trigger-width: var(--radix-popper-anchor-width); --radix-dropdown-menu-trigger-height: var(--radix-popper-anchor-height); pointer-events: auto;"
tabindex="-1" tabindex="-1"
> >
<h3 <h3
class="_typography_6v6n8_153 _font-body-sm-semibold_6v6n8_36 _menu-title_1sgvx_8 _title_19sse_74" class="_typography_6v6n8_153 _font-body-sm-semibold_6v6n8_36 _menu-title_1sgvx_8 _title_19sse_74"
id=":r3b:" id="«r3b»"
> >
Threads activity Threads activity
</h3> </h3>
@@ -145,15 +145,15 @@ exports[`ThreadsActivityCentre should close the release announcement when the TA
class="mx_ThreadsActivityCentre_container" class="mx_ThreadsActivityCentre_container"
> >
<button <button
aria-controls="radix-:r1d:" aria-controls="radix-«r1d»"
aria-disabled="false" aria-disabled="false"
aria-expanded="true" aria-expanded="true"
aria-haspopup="menu" aria-haspopup="menu"
aria-label="Threads" aria-label="Threads"
aria-labelledby=":r1e:" aria-labelledby="«r1e»"
class="_icon-button_m2erp_8 mx_ThreadsActivityCentreButton" class="_icon-button_m2erp_8 mx_ThreadsActivityCentreButton"
data-state="open" data-state="open"
id="radix-:r1c:" id="radix-«r1c»"
role="button" role="button"
style="--cpd-icon-button-size: 32px;" style="--cpd-icon-button-size: 32px;"
tabindex="0" tabindex="0"
@@ -183,7 +183,7 @@ exports[`ThreadsActivityCentre should close the release announcement when the TA
aria-hidden="true" aria-hidden="true"
data-aria-hidden="true" data-aria-hidden="true"
data-floating-ui-portal="" data-floating-ui-portal=""
id=":r1i:" id="«r1i»"
> >
<div <div
class="_tooltip_6ode6_8 _invisible_6ode6_21" class="_tooltip_6ode6_8 _invisible_6ode6_21"
@@ -204,7 +204,7 @@ exports[`ThreadsActivityCentre should close the release announcement when the TA
stroke="none" stroke="none"
/> />
<clippath <clippath
id=":r1j:" id="«r1j»"
> >
<rect <rect
height="10" height="10"
@@ -215,7 +215,7 @@ exports[`ThreadsActivityCentre should close the release announcement when the TA
</clippath> </clippath>
</svg> </svg>
<span <span
id=":r1e:" id="«r1e»"
> >
Threads Threads
</span> </span>
@@ -227,7 +227,7 @@ exports[`ThreadsActivityCentre should close the release announcement when the TA
style="position: fixed; left: 0px; top: 0px; transform: translate(0px, -8px); min-width: max-content; --radix-popper-transform-origin: 0% 0px; --radix-popper-available-width: 0px; --radix-popper-available-height: -8px; --radix-popper-anchor-width: 0px; --radix-popper-anchor-height: 0px;" style="position: fixed; left: 0px; top: 0px; transform: translate(0px, -8px); min-width: max-content; --radix-popper-transform-origin: 0% 0px; --radix-popper-available-width: 0px; --radix-popper-available-height: -8px; --radix-popper-anchor-width: 0px; --radix-popper-anchor-height: 0px;"
> >
<div <div
aria-labelledby="radix-:r1c:" aria-labelledby="radix-«r1c»"
aria-orientation="vertical" aria-orientation="vertical"
class="_menu_19sse_8" class="_menu_19sse_8"
data-align="start" data-align="start"
@@ -236,14 +236,14 @@ exports[`ThreadsActivityCentre should close the release announcement when the TA
data-side="top" data-side="top"
data-state="open" data-state="open"
dir="ltr" dir="ltr"
id="radix-:r1d:" id="radix-«r1d»"
role="menu" role="menu"
style="outline: none; --radix-dropdown-menu-content-transform-origin: var(--radix-popper-transform-origin); --radix-dropdown-menu-content-available-width: var(--radix-popper-available-width); --radix-dropdown-menu-content-available-height: var(--radix-popper-available-height); --radix-dropdown-menu-trigger-width: var(--radix-popper-anchor-width); --radix-dropdown-menu-trigger-height: var(--radix-popper-anchor-height); pointer-events: auto;" style="outline: none; --radix-dropdown-menu-content-transform-origin: var(--radix-popper-transform-origin); --radix-dropdown-menu-content-available-width: var(--radix-popper-available-width); --radix-dropdown-menu-content-available-height: var(--radix-popper-available-height); --radix-dropdown-menu-trigger-width: var(--radix-popper-anchor-width); --radix-dropdown-menu-trigger-height: var(--radix-popper-anchor-height); pointer-events: auto;"
tabindex="-1" tabindex="-1"
> >
<h3 <h3
class="_typography_6v6n8_153 _font-body-sm-semibold_6v6n8_36 _menu-title_1sgvx_8 _title_19sse_74" class="_typography_6v6n8_153 _font-body-sm-semibold_6v6n8_36 _menu-title_1sgvx_8 _title_19sse_74"
id=":r1k:" id="«r1k»"
> >
Threads activity Threads activity
</h3> </h3>
@@ -270,7 +270,7 @@ exports[`ThreadsActivityCentre should close the release announcement when the TA
exports[`ThreadsActivityCentre should match snapshot when empty 1`] = ` exports[`ThreadsActivityCentre should match snapshot when empty 1`] = `
<div <div
aria-labelledby="radix-:r3n:" aria-labelledby="radix-«r3n»"
aria-orientation="vertical" aria-orientation="vertical"
class="_menu_19sse_8" class="_menu_19sse_8"
data-align="start" data-align="start"
@@ -279,14 +279,14 @@ exports[`ThreadsActivityCentre should match snapshot when empty 1`] = `
data-side="top" data-side="top"
data-state="open" data-state="open"
dir="ltr" dir="ltr"
id="radix-:r3o:" id="radix-«r3o»"
role="menu" role="menu"
style="outline: none; --radix-dropdown-menu-content-transform-origin: var(--radix-popper-transform-origin); --radix-dropdown-menu-content-available-width: var(--radix-popper-available-width); --radix-dropdown-menu-content-available-height: var(--radix-popper-available-height); --radix-dropdown-menu-trigger-width: var(--radix-popper-anchor-width); --radix-dropdown-menu-trigger-height: var(--radix-popper-anchor-height); pointer-events: auto;" style="outline: none; --radix-dropdown-menu-content-transform-origin: var(--radix-popper-transform-origin); --radix-dropdown-menu-content-available-width: var(--radix-popper-available-width); --radix-dropdown-menu-content-available-height: var(--radix-popper-available-height); --radix-dropdown-menu-trigger-width: var(--radix-popper-anchor-width); --radix-dropdown-menu-trigger-height: var(--radix-popper-anchor-height); pointer-events: auto;"
tabindex="-1" tabindex="-1"
> >
<h3 <h3
class="_typography_6v6n8_153 _font-body-sm-semibold_6v6n8_36 _menu-title_1sgvx_8 _title_19sse_74" class="_typography_6v6n8_153 _font-body-sm-semibold_6v6n8_36 _menu-title_1sgvx_8 _title_19sse_74"
id=":r3v:" id="«r3v»"
> >
Threads activity Threads activity
</h3> </h3>
@@ -304,7 +304,7 @@ exports[`ThreadsActivityCentre should match snapshot when empty 1`] = `
exports[`ThreadsActivityCentre should order the room with the same notification level by most recent 1`] = ` exports[`ThreadsActivityCentre should order the room with the same notification level by most recent 1`] = `
<div <div
aria-labelledby="radix-:r40:" aria-labelledby="radix-«r40»"
aria-orientation="vertical" aria-orientation="vertical"
class="_menu_19sse_8" class="_menu_19sse_8"
data-align="start" data-align="start"
@@ -313,14 +313,14 @@ exports[`ThreadsActivityCentre should order the room with the same notification
data-side="top" data-side="top"
data-state="open" data-state="open"
dir="ltr" dir="ltr"
id="radix-:r41:" id="radix-«r41»"
role="menu" role="menu"
style="outline: none; --radix-dropdown-menu-content-transform-origin: var(--radix-popper-transform-origin); --radix-dropdown-menu-content-available-width: var(--radix-popper-available-width); --radix-dropdown-menu-content-available-height: var(--radix-popper-available-height); --radix-dropdown-menu-trigger-width: var(--radix-popper-anchor-width); --radix-dropdown-menu-trigger-height: var(--radix-popper-anchor-height); pointer-events: auto;" style="outline: none; --radix-dropdown-menu-content-transform-origin: var(--radix-popper-transform-origin); --radix-dropdown-menu-content-available-width: var(--radix-popper-available-width); --radix-dropdown-menu-content-available-height: var(--radix-popper-available-height); --radix-dropdown-menu-trigger-width: var(--radix-popper-anchor-width); --radix-dropdown-menu-trigger-height: var(--radix-popper-anchor-height); pointer-events: auto;"
tabindex="-1" tabindex="-1"
> >
<h3 <h3
class="_typography_6v6n8_153 _font-body-sm-semibold_6v6n8_36 _menu-title_1sgvx_8 _title_19sse_74" class="_typography_6v6n8_153 _font-body-sm-semibold_6v6n8_36 _menu-title_1sgvx_8 _title_19sse_74"
id=":r48:" id="«r48»"
> >
Threads activity Threads activity
</h3> </h3>
@@ -482,12 +482,12 @@ exports[`ThreadsActivityCentre should render the release announcement 1`] = `
class="mx_ThreadsActivityCentre_container" class="mx_ThreadsActivityCentre_container"
> >
<button <button
aria-controls=":ra:" aria-controls="«ra»"
aria-describedby=":ra:" aria-describedby="«ra»"
aria-expanded="true" aria-expanded="true"
aria-haspopup="dialog" aria-haspopup="dialog"
aria-label="Threads" aria-label="Threads"
aria-labelledby=":rc:" aria-labelledby="«rc»"
class="_icon-button_m2erp_8 mx_ThreadsActivityCentreButton" class="_icon-button_m2erp_8 mx_ThreadsActivityCentreButton"
data-floating-ui-inert="" data-floating-ui-inert=""
role="button" role="button"
@@ -526,7 +526,7 @@ exports[`ThreadsActivityCentre should render the release announcement 1`] = `
tabindex="0" tabindex="0"
/> />
<span <span
aria-owns=":rh:" aria-owns="«rh»"
data-floating-ui-inert="" data-floating-ui-inert=""
style="border: 0px; height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: fixed; white-space: nowrap; width: 1px; top: 0px; left: 0px;" style="border: 0px; height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: fixed; white-space: nowrap; width: 1px; top: 0px; left: 0px;"
/> />
@@ -542,7 +542,7 @@ exports[`ThreadsActivityCentre should render the release announcement 1`] = `
<div <div
data-floating-ui-inert="" data-floating-ui-inert=""
data-floating-ui-portal="" data-floating-ui-portal=""
id=":rg:" id="«rg»"
> >
<div <div
class="_tooltip_6ode6_8 _invisible_6ode6_21" class="_tooltip_6ode6_8 _invisible_6ode6_21"
@@ -563,7 +563,7 @@ exports[`ThreadsActivityCentre should render the release announcement 1`] = `
stroke="none" stroke="none"
/> />
<clippath <clippath
id=":ri:" id="«ri»"
> >
<rect <rect
height="10" height="10"
@@ -574,7 +574,7 @@ exports[`ThreadsActivityCentre should render the release announcement 1`] = `
</clippath> </clippath>
</svg> </svg>
<span <span
id=":rc:" id="«rc»"
> >
Threads Threads
</span> </span>
@@ -582,7 +582,7 @@ exports[`ThreadsActivityCentre should render the release announcement 1`] = `
</div> </div>
<div <div
data-floating-ui-portal="" data-floating-ui-portal=""
id=":rh:" id="«rh»"
> >
<span <span
data-floating-ui-focus-guard="" data-floating-ui-focus-guard=""
@@ -592,11 +592,11 @@ exports[`ThreadsActivityCentre should render the release announcement 1`] = `
tabindex="0" tabindex="0"
/> />
<div <div
aria-describedby=":r9:" aria-describedby="«r9»"
aria-labelledby=":r8:" aria-labelledby="«r8»"
class="_content_3xq91_8" class="_content_3xq91_8"
data-floating-ui-focusable="" data-floating-ui-focusable=""
id=":ra:" id="«ra»"
role="dialog" role="dialog"
style="position: absolute; left: 0px; top: 0px; transform: translate(0px, 0px);" style="position: absolute; left: 0px; top: 0px; transform: translate(0px, 0px);"
tabindex="-1" tabindex="-1"
@@ -614,7 +614,7 @@ exports[`ThreadsActivityCentre should render the release announcement 1`] = `
stroke="none" stroke="none"
/> />
<clippath <clippath
id=":rj:" id="«rj»"
> >
<rect <rect
height="20" height="20"
@@ -626,13 +626,13 @@ exports[`ThreadsActivityCentre should render the release announcement 1`] = `
</svg> </svg>
<h3 <h3
class="_typography_6v6n8_153 _font-body-lg-semibold_6v6n8_74 _header_3xq91_37" class="_typography_6v6n8_153 _font-body-lg-semibold_6v6n8_74 _header_3xq91_37"
id=":r8:" id="«r8»"
> >
Threads Activity Centre Threads Activity Centre
</h3> </h3>
<span <span
class="_typography_6v6n8_153 _font-body-sm-regular_6v6n8_31 _description_3xq91_43" class="_typography_6v6n8_153 _font-body-sm-regular_6v6n8_31 _description_3xq91_43"
id=":r9:" id="«r9»"
> >
Threads notifications have moved, find them here from now on. Threads notifications have moved, find them here from now on.
</span> </span>

View File

@@ -40,9 +40,10 @@ describe("useProfileInfo", () => {
result.current.search({ query }); result.current.search({ query });
}); });
await waitFor(() => expect(result.current.ready).toBe(true)); await waitFor(() => {
expect(result.current.ready).toBe(true);
expect(result.current.profile?.display_name).toBe(query); expect(result.current.profile?.display_name).toBe(query);
});
}); });
it("should work with empty queries", async () => { it("should work with empty queries", async () => {

View File

@@ -77,9 +77,8 @@ describe("usePublicRoomDirectory", () => {
await waitFor(() => { await waitFor(() => {
expect(result.current.ready).toBe(true); expect(result.current.ready).toBe(true);
expect(result.current.publicRooms[0].name).toEqual(query);
}); });
expect(result.current.publicRooms[0].name).toEqual(query);
}); });
it("should recover from a server exception", async () => { it("should recover from a server exception", async () => {

View File

@@ -45,9 +45,11 @@ describe("useUserDirectory", () => {
act(() => { act(() => {
result.current.search({ limit: 1, query }); result.current.search({ limit: 1, query });
}); });
await waitFor(() => expect(result.current.ready).toBe(true)); await waitFor(() => {
expect(result.current.ready).toBe(true);
expect(result.current.loading).toBe(false);
});
expect(result.current.loading).toBe(false);
expect(result.current.users[0].name).toBe(query); expect(result.current.users[0].name).toBe(query);
}); });

View File

@@ -14,7 +14,7 @@ exports[`link-tooltip wraps single anchor 1`] = `
<span <span
aria-labelledby=":r0:" aria-labelledby="«r0»"
tabindex="0" tabindex="0"
> >
<a <a

View File

@@ -10,22 +10,10 @@ import { mocked } from "jest-mock";
import { type Room, RoomType } from "matrix-js-sdk/src/matrix"; import { type Room, RoomType } from "matrix-js-sdk/src/matrix";
import { VisibilityProvider } from "../../../../../src/stores/room-list/filters/VisibilityProvider"; import { VisibilityProvider } from "../../../../../src/stores/room-list/filters/VisibilityProvider";
import LegacyCallHandler from "../../../../../src/LegacyCallHandler";
import VoipUserMapper from "../../../../../src/VoipUserMapper";
import { LocalRoom, LOCAL_ROOM_ID_PREFIX } from "../../../../../src/models/LocalRoom"; import { LocalRoom, LOCAL_ROOM_ID_PREFIX } from "../../../../../src/models/LocalRoom";
import { RoomListCustomisations } from "../../../../../src/customisations/RoomList"; import { RoomListCustomisations } from "../../../../../src/customisations/RoomList";
import { createTestClient } from "../../../../test-utils"; import { createTestClient } from "../../../../test-utils";
jest.mock("../../../../../src/VoipUserMapper", () => ({
sharedInstance: jest.fn(),
}));
jest.mock("../../../../../src/LegacyCallHandler", () => ({
instance: {
getSupportsVirtualRooms: jest.fn(),
},
}));
jest.mock("../../../../../src/customisations/RoomList", () => ({ jest.mock("../../../../../src/customisations/RoomList", () => ({
RoomListCustomisations: { RoomListCustomisations: {
isRoomVisible: jest.fn(), isRoomVisible: jest.fn(),
@@ -46,16 +34,6 @@ const createLocalRoom = (): LocalRoom => {
}; };
describe("VisibilityProvider", () => { describe("VisibilityProvider", () => {
let mockVoipUserMapper: VoipUserMapper;
beforeEach(() => {
mockVoipUserMapper = {
onNewInvitedRoom: jest.fn(),
isVirtualRoom: jest.fn(),
} as unknown as VoipUserMapper;
mocked(VoipUserMapper.sharedInstance).mockReturnValue(mockVoipUserMapper);
});
describe("instance", () => { describe("instance", () => {
it("should return an instance", () => { it("should return an instance", () => {
const visibilityProvider = VisibilityProvider.instance; const visibilityProvider = VisibilityProvider.instance;
@@ -64,28 +42,7 @@ describe("VisibilityProvider", () => {
}); });
}); });
describe("onNewInvitedRoom", () => {
it("should call onNewInvitedRoom on VoipUserMapper.sharedInstance", async () => {
const room = {} as unknown as Room;
await VisibilityProvider.instance.onNewInvitedRoom(room);
expect(mockVoipUserMapper.onNewInvitedRoom).toHaveBeenCalledWith(room);
});
});
describe("isRoomVisible", () => { describe("isRoomVisible", () => {
describe("for a virtual room", () => {
beforeEach(() => {
mocked(LegacyCallHandler.instance.getSupportsVirtualRooms).mockReturnValue(true);
mocked(mockVoipUserMapper.isVirtualRoom).mockReturnValue(true);
});
it("should return return false", () => {
const room = createRoom();
expect(VisibilityProvider.instance.isRoomVisible(room)).toBe(false);
expect(mockVoipUserMapper.isVirtualRoom).toHaveBeenCalledWith(room);
});
});
it("should return false without room", () => { it("should return false without room", () => {
expect(VisibilityProvider.instance.isRoomVisible()).toBe(false); expect(VisibilityProvider.instance.isRoomVisible()).toBe(false);
}); });

View File

@@ -2599,6 +2599,11 @@
resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.1.0.tgz#f817d1d3265ac5415dadc67edab30ae196696438" resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.1.0.tgz#f817d1d3265ac5415dadc67edab30ae196696438"
integrity sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg== integrity sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==
"@rrweb/types@^2.0.0-alpha.18":
version "2.0.0-alpha.18"
resolved "https://registry.yarnpkg.com/@rrweb/types/-/types-2.0.0-alpha.18.tgz#e1d9af844cebbf30a2be8808f6cf64f5df3e7f50"
integrity sha512-iMH3amHthJZ9x3gGmBPmdfim7wLGygC2GciIkw2A6SO8giSn8PHYtRT8OKNH4V+k3SZ6RSnYHcTQxBA7pSWZ3Q==
"@rtsao/scc@^1.1.0": "@rtsao/scc@^1.1.0":
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8" resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8"
@@ -3346,10 +3351,10 @@
dependencies: dependencies:
"@types/react" "*" "@types/react" "*"
"@types/react-dom@19.0.4": "@types/react-dom@19.1.2":
version "19.0.4" version "19.1.2"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-19.0.4.tgz#bedba97f9346bd4c0fe5d39e689713804ec9ac89" resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-19.1.2.tgz#bd1fe3b8c28a3a2e942f85314dcfb71f531a242f"
integrity sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg== integrity sha512-XGJkWF41Qq305SKWEILa1O8vzhb3aOo3ogBlSmiqNko/WmRb6QIaweuZCXjKygVDXpzXb5wyxKTSOsmkuqj+Qw==
"@types/react-redux@^7.1.20": "@types/react-redux@^7.1.20":
version "7.1.34" version "7.1.34"
@@ -3374,10 +3379,10 @@
"@types/prop-types" "*" "@types/prop-types" "*"
"@types/react" "*" "@types/react" "*"
"@types/react@*", "@types/react@19.0.10": "@types/react@*", "@types/react@19.1.1":
version "19.0.10" version "19.1.1"
resolved "https://registry.yarnpkg.com/@types/react/-/react-19.0.10.tgz#d0c66dafd862474190fe95ce11a68de69ed2b0eb" resolved "https://registry.yarnpkg.com/@types/react/-/react-19.1.1.tgz#f7f2bb4a0a8d22b9ee4b8f6e27f0c78d76eb7f9b"
integrity sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g== integrity sha512-ePapxDL7qrgqSF67s0h9m412d9DbXyC1n59O2st+9rjuuamWsZuD2w55rqY12CbzsZ7uVXb5Nw0gEp9Z8MMutQ==
dependencies: dependencies:
csstype "^3.0.2" csstype "^3.0.2"
@@ -3644,9 +3649,9 @@
integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==
"@vector-im/compound-design-tokens@^4.0.0": "@vector-im/compound-design-tokens@^4.0.0":
version "4.0.1" version "4.0.2"
resolved "https://registry.yarnpkg.com/@vector-im/compound-design-tokens/-/compound-design-tokens-4.0.1.tgz#5c4ea7ad664d8e6206dc42e41649c80ef060a760" resolved "https://registry.yarnpkg.com/@vector-im/compound-design-tokens/-/compound-design-tokens-4.0.2.tgz#27363d26446eaa21880ab126fa51fec112e6fd86"
integrity sha512-V4AsK1FVFxZ6DmmCoeAi8FyvE7ODMlXPWjqRGotcnVaoGNrDQrVz2ZGV85DCz5ISxB3iynYASe6OXsDVXT1zFA== integrity sha512-y13bhPyJ5OzbGRl21F6+Y2adrjyK+mu67yKTx+o8MfmIpJzMSn4KkHZtcujMquWSh0e5ZAufsnk4VYvxbSpr1A==
"@vector-im/compound-web@^7.10.1": "@vector-im/compound-web@^7.10.1":
version "7.10.1" version "7.10.1"
@@ -4740,10 +4745,10 @@ caniuse-api@^3.0.0:
lodash.memoize "^4.1.2" lodash.memoize "^4.1.2"
lodash.uniq "^4.5.0" lodash.uniq "^4.5.0"
caniuse-lite@1.0.30001713, caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001646, caniuse-lite@^1.0.30001688: caniuse-lite@1.0.30001714, caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001646, caniuse-lite@^1.0.30001688:
version "1.0.30001713" version "1.0.30001714"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001713.tgz#6b33a8857e6c7dcb41a0caa2dd0f0489c823a52d" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001714.tgz#cfd27ff07e6fa20a0f45c7a10d28a0ffeaba2122"
integrity sha512-wCIWIg+A4Xr7NfhTuHdX+/FKh3+Op3LBbSp2N5Pfx6T/LhdQy3GTyoTg48BReaW/MyMNZAkTadsBtai3ldWK0Q== integrity sha512-mtgapdwDLSSBnCI3JokHM7oEQBLxiJKVRtg10AxM1AyeiKcM96f0Mkbqeq+1AbiCtvMcHRulAAEMu693JrSWqg==
chalk@5.2.0: chalk@5.2.0:
version "5.2.0" version "5.2.0"
@@ -8999,9 +9004,9 @@ makeerror@1.0.12:
tmpl "1.0.5" tmpl "1.0.5"
maplibre-gl@^5.0.0: maplibre-gl@^5.0.0:
version "5.3.0" version "5.3.1"
resolved "https://registry.yarnpkg.com/maplibre-gl/-/maplibre-gl-5.3.0.tgz#31fcc6f689dd0d342446a2baa29bbb8015f9f3dc" resolved "https://registry.yarnpkg.com/maplibre-gl/-/maplibre-gl-5.3.1.tgz#bae6408da2d708ee20aa2d8b44f8e39de8c7cd93"
integrity sha512-qru6B6jHlDPR4Q9/P4W1zEPbPofR4wwYbrrjiHKWI7yLtyXmpJ1/G1KaIYDr5uNdFbPZ7uiZAWdqtfdNLmIhGg== integrity sha512-Ihx+oUUSsZkjMou1Cw5J6silE+5OtFFQSPslWF9+7v4yFC/XDHrpsORYO9lWE4KZI0djCEUpZQJpkpnMArAbeA==
dependencies: dependencies:
"@mapbox/geojson-rewind" "^0.5.2" "@mapbox/geojson-rewind" "^0.5.2"
"@mapbox/jsonlint-lines-primitives" "^2.0.2" "@mapbox/jsonlint-lines-primitives" "^2.0.2"
@@ -10582,14 +10587,15 @@ postcss@^8.4.40, postcss@^8.5.3:
picocolors "^1.1.1" picocolors "^1.1.1"
source-map-js "^1.2.1" source-map-js "^1.2.1"
posthog-js@1.157.2: posthog-js@1.236.1:
version "1.157.2" version "1.236.1"
resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.157.2.tgz#dc2515818ead408aefb900e90c535fb57beb1f59" resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.236.1.tgz#36d726e30439b0de054059d11213101ca5dd9822"
integrity sha512-ATYKGs+Q51u26nHHhrhWNh1whqFm7j/rwQQYw+y6/YzNmRlo+YsqrGZji9nqXb9/4fo0ModDr+ZmuOI3hKkUXA== integrity sha512-my3MGaQfBO4FOL0RAW2mCxDkivCyt8KOenYrbeES5D5wh3SQGy0OhDH3boTKO6b6dchsAjieqtOGoRFomKXZ+A==
dependencies: dependencies:
core-js "^3.38.1"
fflate "^0.4.8" fflate "^0.4.8"
preact "^10.19.3" preact "^10.19.3"
web-vitals "^4.0.1" web-vitals "^4.2.4"
potpack@^2.0.0: potpack@^2.0.0:
version "2.0.0" version "2.0.0"
@@ -10887,11 +10893,11 @@ react-clientside-effect@^1.2.7:
"@babel/runtime" "^7.12.13" "@babel/runtime" "^7.12.13"
react-dom@^19.0.0: react-dom@^19.0.0:
version "19.0.0" version "19.1.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.0.0.tgz#43446f1f01c65a4cd7f7588083e686a6726cfb57" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.1.0.tgz#133558deca37fa1d682708df8904b25186793623"
integrity sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ== integrity sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==
dependencies: dependencies:
scheduler "^0.25.0" scheduler "^0.26.0"
react-focus-lock@^2.5.1: react-focus-lock@^2.5.1:
version "2.13.6" version "2.13.6"
@@ -10905,10 +10911,10 @@ react-focus-lock@^2.5.1:
use-callback-ref "^1.3.3" use-callback-ref "^1.3.3"
use-sidecar "^1.1.3" use-sidecar "^1.1.3"
react-is@19.0.0, react-is@^17.0.1, react-is@^18.0.0: react-is@19.1.0, react-is@^17.0.1, react-is@^18.0.0:
version "19.0.0" version "19.1.0"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-19.0.0.tgz#d6669fd389ff022a9684f708cf6fa4962d1fea7a" resolved "https://registry.yarnpkg.com/react-is/-/react-is-19.1.0.tgz#805bce321546b7e14c084989c77022351bbdd11b"
integrity sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g== integrity sha512-Oe56aUPnkHyyDxxkvqtd7KkdQP5uIUfHxd5XTb3wE9d/kRnZLmKbDB0GWk919tdQ+mxxPtG6EAs6RMT6i1qtHg==
react-is@^16.13.1, react-is@^16.7.0: react-is@^16.13.1, react-is@^16.7.0:
version "16.13.1" version "16.13.1"
@@ -10998,9 +11004,9 @@ react-virtualized@^9.22.5:
react-lifecycles-compat "^3.0.4" react-lifecycles-compat "^3.0.4"
react@^19.0.0: react@^19.0.0:
version "19.0.0" version "19.1.0"
resolved "https://registry.yarnpkg.com/react/-/react-19.0.0.tgz#6e1969251b9f108870aa4bff37a0ce9ddfaaabdd" resolved "https://registry.yarnpkg.com/react/-/react-19.1.0.tgz#926864b6c48da7627f004795d6cce50e90793b75"
integrity sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ== integrity sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==
read-cache@^1.0.0: read-cache@^1.0.0:
version "1.0.0" version "1.0.0"
@@ -11449,10 +11455,10 @@ saxes@^6.0.0:
dependencies: dependencies:
xmlchars "^2.2.0" xmlchars "^2.2.0"
scheduler@^0.25.0: scheduler@^0.26.0:
version "0.25.0" version "0.26.0"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.25.0.tgz#336cd9768e8cceebf52d3c80e3dcf5de23e7e015" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.26.0.tgz#4ce8a8c2a2095f13ea11bf9a445be50c555d6337"
integrity sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA== integrity sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==
schema-utils@^3.0.0: schema-utils@^3.0.0:
version "3.3.0" version "3.3.0"
@@ -12998,10 +13004,10 @@ web-streams-polyfill@^4.0.0:
resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-4.1.0.tgz#3ba095d0eb3ef6377cd126e8354b2cdba286e0d3" resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-4.1.0.tgz#3ba095d0eb3ef6377cd126e8354b2cdba286e0d3"
integrity sha512-A7Jxrg7+eV+eZR/CIdESDnRGFb6/bcKukGvJBB5snI6cw3is1c2qamkYstC1bY1p08TyMRlN9eTMkxmnKJBPBw== integrity sha512-A7Jxrg7+eV+eZR/CIdESDnRGFb6/bcKukGvJBB5snI6cw3is1c2qamkYstC1bY1p08TyMRlN9eTMkxmnKJBPBw==
web-vitals@^4.0.1: web-vitals@^4.2.4:
version "4.2.3" version "4.2.4"
resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-4.2.3.tgz#270c4baecfbc6ec6fc15da1989e465e5f9b94fb7" resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-4.2.4.tgz#1d20bc8590a37769bd0902b289550936069184b7"
integrity sha512-/CFAm1mNxSmOj6i0Co+iGFJ58OS4NRGVP+AWS/l509uIK5a1bSoIVaHz/ZumpHTfHSZBpgrJ+wjfpAOrTHok5Q== integrity sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==
webcrypto-core@^1.8.0: webcrypto-core@^1.8.0:
version "1.8.1" version "1.8.1"