mirror of
https://github.com/element-hq/element-web.git
synced 2025-09-17 11:04:05 +02:00
Compare commits
33 Commits
hs/user-pr
...
compound-w
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c6690e16a | ||
|
|
817d1f309c | ||
|
|
942a02dff9 | ||
|
|
fecb387c52 | ||
|
|
f67825cff3 | ||
|
|
db50519cca | ||
|
|
6cf8dc570b | ||
|
|
f396b28c68 | ||
|
|
3900a1e20d | ||
|
|
667827eeb3 | ||
|
|
8e67cfe3c4 | ||
|
|
043d812b1d | ||
|
|
644be3155c | ||
|
|
92034aaff9 | ||
|
|
fb502a68a0 | ||
|
|
e456782efd | ||
|
|
f83093cc44 | ||
|
|
c45ad3063f | ||
|
|
e06d76e3f7 | ||
|
|
9dddaf732c | ||
|
|
87b4918d34 | ||
|
|
c6f47cfd8e | ||
|
|
f76a535439 | ||
|
|
97653c1da7 | ||
|
|
b578393d16 | ||
|
|
a112dfe1db | ||
|
|
4b4cb896eb | ||
|
|
6a1c0502aa | ||
|
|
ea5e525133 | ||
|
|
14d16364db | ||
|
|
19e6aaf1c4 | ||
|
|
a8856ca389 | ||
|
|
54f325e871 |
@@ -126,7 +126,7 @@ test.describe("'Turn on key storage' toast", () => {
|
||||
await toast.getByRole("button", { name: "Continue" }).click();
|
||||
|
||||
// Then we see the Encryption settings dialog with an option to turn on key storage
|
||||
await expect(page.getByRole("checkbox", { name: "Allow key storage" })).toBeVisible();
|
||||
await expect(page.getByRole("switch", { name: "Allow key storage" })).toBeVisible();
|
||||
|
||||
// And when we close that
|
||||
await page.getByRole("button", { name: "Close dialog" }).click();
|
||||
@@ -153,7 +153,7 @@ test.describe("'Turn on key storage' toast", () => {
|
||||
await page.getByRole("button", { name: "Go to Settings" }).click();
|
||||
|
||||
// Then we see Encryption settings again
|
||||
await expect(page.getByRole("checkbox", { name: "Allow key storage" })).toBeVisible();
|
||||
await expect(page.getByRole("switch", { name: "Allow key storage" })).toBeVisible();
|
||||
|
||||
// And when we close that, see the toast, click Dismiss, and Yes, Dismiss
|
||||
await page.getByRole("button", { name: "Close dialog" }).click();
|
||||
|
||||
@@ -300,9 +300,9 @@ export async function doTwoWaySasVerification(page: Page, verifier: JSHandle<Ver
|
||||
export async function enableKeyBackup(app: ElementAppPage): Promise<string> {
|
||||
const encryptionTab = await app.settings.openUserSettings("Encryption");
|
||||
|
||||
const keyStorageToggle = encryptionTab.getByRole("checkbox", { name: "Allow key storage" });
|
||||
const keyStorageToggle = encryptionTab.getByRole("switch", { name: "Allow key storage" });
|
||||
if (!(await keyStorageToggle.isChecked())) {
|
||||
await encryptionTab.getByRole("checkbox", { name: "Allow key storage" }).click();
|
||||
await encryptionTab.getByRole("switch", { name: "Allow key storage" }).click();
|
||||
}
|
||||
|
||||
await encryptionTab.getByRole("button", { name: "Set up recovery" }).click();
|
||||
@@ -323,11 +323,11 @@ export async function enableKeyBackup(app: ElementAppPage): Promise<string> {
|
||||
export async function disableKeyBackup(app: ElementAppPage): Promise<void> {
|
||||
const encryptionTab = await app.settings.openUserSettings("Encryption");
|
||||
|
||||
const keyStorageToggle = encryptionTab.getByRole("checkbox", { name: "Allow key storage" });
|
||||
const keyStorageToggle = encryptionTab.getByRole("switch", { name: "Allow key storage" });
|
||||
if (await keyStorageToggle.isChecked()) {
|
||||
await encryptionTab.getByRole("checkbox", { name: "Allow key storage" }).click();
|
||||
await encryptionTab.getByRole("switch", { name: "Allow key storage" }).click();
|
||||
await encryptionTab.getByRole("button", { name: "Delete key storage" }).click();
|
||||
await encryptionTab.getByRole("checkbox", { name: "Allow key storage" }).isVisible();
|
||||
await encryptionTab.getByRole("switch", { name: "Allow key storage" }).isVisible();
|
||||
|
||||
// Wait for the update to account data to stick
|
||||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
||||
|
||||
@@ -100,3 +100,51 @@ test.describe("permalinks", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe("triple-click message selection", () => {
|
||||
test.use({
|
||||
displayName: "Alice",
|
||||
});
|
||||
|
||||
test("should select entire message line when triple-clicking on message with pills", async ({
|
||||
page,
|
||||
app,
|
||||
user,
|
||||
bot,
|
||||
}) => {
|
||||
await bot.prepareClient();
|
||||
|
||||
const roomId = await app.client.createRoom({ name: "Test Room" });
|
||||
await app.client.inviteUser(roomId, bot.credentials.userId);
|
||||
await app.viewRoomByName("Test Room");
|
||||
|
||||
// Send a message with user and room pills
|
||||
await app.client.sendMessage(
|
||||
roomId,
|
||||
`Testing triple-click message selection. ` +
|
||||
`User: ${permalinkPrefix}${bot.credentials.userId}, ` +
|
||||
`Room: ${permalinkPrefix}${roomId}, ` +
|
||||
`Message: ${permalinkPrefix}${roomId}/$dummy-event, ` +
|
||||
`and @room mention.`,
|
||||
);
|
||||
|
||||
const timeline = page.locator(".mx_RoomView_timeline");
|
||||
const messageTile = timeline.locator(".mx_EventTile").last();
|
||||
|
||||
// Triple-click on the message body to select its entire content
|
||||
const messageBody = messageTile.locator(".mx_EventTile_body");
|
||||
await messageBody.click({ clickCount: 3 });
|
||||
|
||||
// Get the expected text content of the message, including pills
|
||||
const expectedText = await messageBody.innerText();
|
||||
|
||||
// Get the currently selected text from the page
|
||||
const selectedText = await page.evaluate(() => {
|
||||
const selection = window.getSelection();
|
||||
return selection ? selection.toString().trim() : "";
|
||||
});
|
||||
|
||||
// Verify that the selected text exactly matches the message content
|
||||
expect(selectedText).toBe(expectedText);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -85,7 +85,7 @@ class Helpers {
|
||||
* Return the system theme toggle
|
||||
*/
|
||||
getMatchSystemThemeCheckbox() {
|
||||
return this.getThemePanel().getByRole("checkbox", { name: "Match system theme" });
|
||||
return this.getThemePanel().getByRole("switch", { name: "Match system theme" });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -219,7 +219,7 @@ class Helpers {
|
||||
* Return the compact layout checkbox
|
||||
*/
|
||||
getCompactLayoutCheckbox() {
|
||||
return this.getMessageLayoutPanel().getByRole("checkbox", { name: "Show compact text and messages" });
|
||||
return this.getMessageLayoutPanel().getByRole("switch", { name: "Show compact text and messages" });
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -117,7 +117,7 @@ test.describe("Encryption tab", () => {
|
||||
await verifySession(app, recoveryKey.encodedPrivateKey);
|
||||
await util.openEncryptionTab();
|
||||
|
||||
await page.getByRole("checkbox", { name: "Allow key storage" }).click();
|
||||
await page.getByRole("switch", { name: "Allow key storage" }).click();
|
||||
|
||||
await expect(
|
||||
page.getByRole("heading", { name: "Are you sure you want to turn off key storage and delete it?" }),
|
||||
@@ -136,7 +136,7 @@ test.describe("Encryption tab", () => {
|
||||
|
||||
await page.getByRole("button", { name: "Delete key storage" }).click();
|
||||
|
||||
await expect(page.getByRole("checkbox", { name: "Allow key storage" })).not.toBeChecked();
|
||||
await expect(page.getByRole("switch", { name: "Allow key storage" })).not.toBeChecked();
|
||||
|
||||
for (const prom of deleteRequestPromises) {
|
||||
const request = await prom;
|
||||
|
||||
@@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { SynapseContainer as BaseSynapseContainer } from "@element-hq/element-web-playwright-common/lib/testcontainers";
|
||||
|
||||
const TAG = "develop@sha256:18e9e77eac01709e9ab4d26cf20c36bf5a1567756bb5a78c00cabf366d65a950";
|
||||
const TAG = "develop@sha256:8f0926e3323c9221e99e04783e6ec873b623fa6372342d0f19e151e4affc6147";
|
||||
|
||||
/**
|
||||
* SynapseContainer which freezes the docker digest to stabilise tests,
|
||||
|
||||
@@ -11,8 +11,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
line-height: $font-17px;
|
||||
border-radius: $font-16px;
|
||||
vertical-align: text-top;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
@@ -57,6 +56,8 @@ Please see LICENSE files in the repository root for full details.
|
||||
margin-inline-start: -0.3em; /* Otherwise the gap is too large */
|
||||
margin-inline-end: 0.2em;
|
||||
min-width: $font-16px; /* ensure the avatar is not compressed */
|
||||
user-select: text;
|
||||
vertical-align: -2.5px;
|
||||
}
|
||||
|
||||
.mx_Pill_text {
|
||||
|
||||
@@ -145,6 +145,9 @@ export default class BaseDialog extends React.Component<IProps> {
|
||||
const lockProps: Record<string, any> = {
|
||||
"onKeyDown": this.onKeyDown,
|
||||
"role": "dialog",
|
||||
// Allow the dialog to be keyboard focusable
|
||||
// So the escape key handling works in more cases (say you select the header)
|
||||
"tabIndex": -1,
|
||||
// This should point to a node describing the dialog.
|
||||
// If we were about to completely follow this recommendation we'd need to
|
||||
// make all the components relying on BaseDialog to be aware of it.
|
||||
|
||||
@@ -12,9 +12,7 @@ import { type MatrixEvent, MsgType } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import DisambiguatedProfile from "./DisambiguatedProfile";
|
||||
import { useRoomMemberProfile } from "../../../hooks/room/useRoomMemberProfile";
|
||||
import ModuleApi from "../../../modules/Api";
|
||||
import { CustomComponentsApi } from "../../../modules/customComponentApi";
|
||||
import { MessageProfileComponentProps } from "@element-hq/element-web-module-api";
|
||||
|
||||
interface IProps {
|
||||
mxEvent: MatrixEvent;
|
||||
onClick?(): void;
|
||||
@@ -26,25 +24,17 @@ export default function SenderProfile({ mxEvent, onClick, withTooltip }: IProps)
|
||||
userId: mxEvent.getSender(),
|
||||
member: mxEvent.sender,
|
||||
});
|
||||
|
||||
if (mxEvent.getContent().msgtype === MsgType.Emote) {
|
||||
return <></>;
|
||||
}
|
||||
const moduleRenderer = ModuleApi.customComponents.messageProfileRenderer;
|
||||
const renderFn = (moduleProps: MessageProfileComponentProps) => <DisambiguatedProfile
|
||||
fallbackName={moduleProps.mxEvent.sender ?? ""}
|
||||
onClick={moduleProps.onClick}
|
||||
member={moduleProps.member}
|
||||
colored={true}
|
||||
emphasizeDisplayName={true}
|
||||
withTooltip={withTooltip}
|
||||
/>;
|
||||
|
||||
const modProps = {
|
||||
onClick,
|
||||
mxEvent: CustomComponentsApi.getModuleMatrixEvent(mxEvent)!,
|
||||
member: member || undefined,
|
||||
};
|
||||
|
||||
return moduleRenderer ? moduleRenderer(modProps, renderFn) : renderFn(modProps);
|
||||
return mxEvent.getContent().msgtype !== MsgType.Emote ? (
|
||||
<DisambiguatedProfile
|
||||
fallbackName={mxEvent.getSender() ?? ""}
|
||||
onClick={onClick}
|
||||
member={member}
|
||||
colored={true}
|
||||
emphasizeDisplayName={true}
|
||||
withTooltip={withTooltip}
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ import { Flex } from "../../../../shared-components/utils/Flex";
|
||||
import PresenceLabel from "../../rooms/PresenceLabel";
|
||||
import CopyableText from "../../elements/CopyableText";
|
||||
import { UserInfoHeaderVerificationView } from "./UserInfoHeaderVerificationView";
|
||||
import ModuleApi from "../../../../modules/Api";
|
||||
|
||||
export interface UserInfoHeaderViewProps {
|
||||
member: Member;
|
||||
@@ -49,27 +48,6 @@ export const UserInfoHeaderView: React.FC<UserInfoHeaderViewProps> = ({
|
||||
);
|
||||
}
|
||||
|
||||
const moduleRenderer = ModuleApi.customComponents.userInfoRenderer;
|
||||
let usernameSection;
|
||||
if (moduleRenderer && vm.userIdentifier) {
|
||||
usernameSection = moduleRenderer(
|
||||
{
|
||||
userId: vm.userIdentifier,
|
||||
},
|
||||
(props) => <Text size="sm" weight="semibold" className="mx_UserInfo_profile_mxid">
|
||||
<CopyableText getTextToCopy={() => props.userId} border={false}>
|
||||
{props.userId}
|
||||
</CopyableText>
|
||||
</Text>,
|
||||
);
|
||||
} else {
|
||||
usernameSection = <Text size="sm" weight="semibold" className="mx_UserInfo_profile_mxid">
|
||||
<CopyableText getTextToCopy={() => vm.userIdentifier} border={false}>
|
||||
{vm.userIdentifier}
|
||||
</CopyableText>
|
||||
</Text>;
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div className="mx_UserInfo_avatar">
|
||||
@@ -105,7 +83,11 @@ export const UserInfoHeaderView: React.FC<UserInfoHeaderViewProps> = ({
|
||||
</Flex>
|
||||
</Tooltip>
|
||||
)}
|
||||
{usernameSection}
|
||||
<Text size="sm" weight="semibold" className="mx_UserInfo_profile_mxid">
|
||||
<CopyableText getTextToCopy={() => vm.userIdentifier} border={false}>
|
||||
{vm.userIdentifier}
|
||||
</CopyableText>
|
||||
</Text>
|
||||
</Flex>
|
||||
{!hideVerificationSection && <UserInfoHeaderVerificationView member={member} devices={devices} />}
|
||||
</Container>
|
||||
|
||||
@@ -531,12 +531,15 @@ export class MessageComposer extends React.Component<IProps, IState> {
|
||||
if (!this.props.e2eStatus) {
|
||||
leftIcon = (
|
||||
<div className="mx_MessageComposer_e2eIconWrapper">
|
||||
<LockOffIcon
|
||||
width={12}
|
||||
height={12}
|
||||
color="var(--cpd-color-icon-info-primary)"
|
||||
className="mx_E2EIcon mx_MessageComposer_e2eIcon"
|
||||
/>
|
||||
<Tooltip label={_t("composer|room_unencrypted")}>
|
||||
<LockOffIcon
|
||||
aria-label={_t("composer|room_unencrypted")}
|
||||
width={12}
|
||||
height={12}
|
||||
color="var(--cpd-color-icon-info-primary)"
|
||||
className="mx_E2EIcon mx_MessageComposer_e2eIcon"
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
} else if (this.props.e2eStatus !== E2EStatus.Normal) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React, { useCallback, useRef, type JSX } from "react";
|
||||
import React, { useCallback, useRef, useState, type JSX } from "react";
|
||||
import { type Room } from "matrix-js-sdk/src/matrix";
|
||||
import { type ScrollIntoViewLocation } from "react-virtuoso";
|
||||
import { isEqual } from "lodash";
|
||||
@@ -33,6 +33,7 @@ export function RoomList({ vm: { roomsResult, activeIndex } }: RoomListProps): J
|
||||
const lastSpaceId = useRef<string | undefined>(undefined);
|
||||
const lastFilterKeys = useRef<FilterKey[] | undefined>(undefined);
|
||||
const roomCount = roomsResult.rooms.length;
|
||||
const [isScrolling, setIsScrolling] = useState(false);
|
||||
const getItemComponent = useCallback(
|
||||
(
|
||||
index: number,
|
||||
@@ -57,10 +58,11 @@ export function RoomList({ vm: { roomsResult, activeIndex } }: RoomListProps): J
|
||||
roomIndex={index}
|
||||
roomCount={roomCount}
|
||||
onFocus={onFocus}
|
||||
listIsScrolling={isScrolling}
|
||||
/>
|
||||
);
|
||||
},
|
||||
[activeIndex, roomCount],
|
||||
[activeIndex, roomCount, isScrolling],
|
||||
);
|
||||
|
||||
const getItemKey = useCallback((item: Room): string => {
|
||||
@@ -116,6 +118,7 @@ export function RoomList({ vm: { roomsResult, activeIndex } }: RoomListProps): J
|
||||
getItemKey={getItemKey}
|
||||
isItemFocusable={() => true}
|
||||
onKeyDown={keyDownCallback}
|
||||
isScrolling={setIsScrolling}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -41,6 +41,10 @@ interface RoomListItemViewProps extends React.HTMLAttributes<HTMLButtonElement>
|
||||
* The total number of rooms in the list
|
||||
*/
|
||||
roomCount: number;
|
||||
/**
|
||||
* Whether the list is currently scrolling
|
||||
*/
|
||||
listIsScrolling: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,6 +57,7 @@ export const RoomListItemView = memo(function RoomListItemView({
|
||||
onFocus,
|
||||
roomIndex: index,
|
||||
roomCount: count,
|
||||
listIsScrolling,
|
||||
...props
|
||||
}: RoomListItemViewProps): JSX.Element {
|
||||
const ref = useRef<HTMLButtonElement>(null);
|
||||
@@ -141,7 +146,11 @@ export const RoomListItemView = memo(function RoomListItemView({
|
||||
</Flex>
|
||||
);
|
||||
|
||||
if (!vm.showContextMenu) return content;
|
||||
// Rendering multiple context menus can causes crashes in radix upstream,
|
||||
// See https://github.com/radix-ui/primitives/issues/2717.
|
||||
// We also don't need the context menu while scrolling so can improve scroll performance
|
||||
// by not rendering it.
|
||||
if (!vm.showContextMenu || listIsScrolling) return content;
|
||||
|
||||
return (
|
||||
<RoomListItemContextMenuView
|
||||
|
||||
@@ -646,12 +646,12 @@
|
||||
"mode_plain": "Skrýt formátování",
|
||||
"mode_rich_text": "Zobrazit formátování",
|
||||
"no_perms_notice": "Nemáte oprávnění zveřejňovat příspěvky v této místnosti",
|
||||
"placeholder": "Odeslat zprávu…",
|
||||
"placeholder_encrypted": "Odeslat šifrovanou zprávu…",
|
||||
"placeholder_reply": "Odpovědět…",
|
||||
"placeholder_reply_encrypted": "Odeslat šifrovanou odpověď…",
|
||||
"placeholder_thread": "Odpovědět na vlákno…",
|
||||
"placeholder_thread_encrypted": "Odpovědět na zašifrované vlákno…",
|
||||
"placeholder": "Odeslat nešifrovanou zprávu…",
|
||||
"placeholder_encrypted": "Odeslat zprávu...",
|
||||
"placeholder_reply": "Odeslat nešifrovanou odpověď…",
|
||||
"placeholder_reply_encrypted": "Odeslat odpověď…",
|
||||
"placeholder_thread": "Odpovědět v nešifrovaném vláknu…",
|
||||
"placeholder_thread_encrypted": "Odpovědět ve vláknu…",
|
||||
"poll_button": "Hlasování",
|
||||
"poll_button_no_perms_description": "Nemáte oprávnění zahajovat hlasování v této místnosti.",
|
||||
"poll_button_no_perms_title": "Vyžaduje oprávnění",
|
||||
@@ -922,7 +922,8 @@
|
||||
},
|
||||
"privacy_warning": "Ujistěte se, že tuto obrazovku nikdo nevidí!",
|
||||
"restoring": "Obnovení klíčů ze zálohy",
|
||||
"security_key_title": "Klíč pro obnovení"
|
||||
"security_key_label": "Klíč pro obnovení",
|
||||
"security_key_title": "Zadejte klíč pro obnovení"
|
||||
},
|
||||
"bootstrap_title": "Příprava klíčů",
|
||||
"confirm_encryption_setup_body": "Kliknutím na tlačítko níže potvrďte nastavení šifrování.",
|
||||
@@ -1367,6 +1368,10 @@
|
||||
"name_email_mxid_share_space": "Pozvěte někoho pomocí jeho jména, e-mailové adresy, uživatelského jména (například <userId/>) nebo <a>sdílejte tento prostor</a>.",
|
||||
"name_mxid_share_room": "Pozvěte někoho pomocí svého jména, uživatelského jména (například <userId />) nebo <a>sdílejte tuto místnost</a>.",
|
||||
"name_mxid_share_space": "Pozvěte někoho pomocí jeho jména, uživatelského jména (například <userId/>) nebo <a>sdílejte tento prostor</a>.",
|
||||
"progress": {
|
||||
"dont_close": "Nezavírejte aplikaci, dokud neskončíte.",
|
||||
"preparing": "Příprava pozvánek..."
|
||||
},
|
||||
"recents_section": "Nedávné konverzace",
|
||||
"room_failed_partial": "Poslali jsme ostatním, ale níže uvedení lidé nemohli být pozváni do <RoomName/>",
|
||||
"room_failed_partial_title": "Některé pozvánky nebylo možné odeslat",
|
||||
@@ -1535,6 +1540,9 @@
|
||||
"render_reaction_images_description": "Někdy se označují jako \"vlastní emoji\".",
|
||||
"report_to_moderators": "Nahlásit moderátorům",
|
||||
"report_to_moderators_description": "V místnostech, které podporují moderování, můžete pomocí tlačítka \"Nahlásit\" nahlásit zneužití moderátorům místnosti.",
|
||||
"share_history_on_invite": "Sdílet šifrovanou historii s novými členy",
|
||||
"share_history_on_invite_description": "Při pozvání uživatele do šifrované místnosti, u které je viditelnost historie nastavena na „sdílená“, sdílet šifrovanou historii s tímto uživatelem a přijmout šifrovanou historii, když jste pozváni do takové místnosti.",
|
||||
"share_history_on_invite_warning": "Tato funkce je EXPERIMENTÁLNÍ a nejsou v ní implementována všechna bezpečnostní opatření. Neaktivujte ji na produkčních účtech.",
|
||||
"sliding_sync": "Režim klouzavé synchronizace",
|
||||
"sliding_sync_description": "V aktivním vývoji, nelze zakázat.",
|
||||
"sliding_sync_disabled_notice": "Pro vypnutí se odhlaste a znovu přihlaste",
|
||||
@@ -1657,6 +1665,7 @@
|
||||
"filter_placeholder": "Najít člena místnosti",
|
||||
"invite_button_no_perms_tooltip": "Nemáte oprávnění zvát uživatele",
|
||||
"invited_label": "Pozván",
|
||||
"list_title": "Seznam členů",
|
||||
"no_matches": "Žádné shody"
|
||||
},
|
||||
"member_list_back_action_label": "Členové místnosti",
|
||||
@@ -1761,6 +1770,7 @@
|
||||
},
|
||||
"power_level": {
|
||||
"admin": "Správce",
|
||||
"creator": "Vlastník",
|
||||
"custom": "Vlastní (%(level)s)",
|
||||
"custom_level": "Vlastní úroveň",
|
||||
"default": "Výchozí",
|
||||
@@ -1914,6 +1924,7 @@
|
||||
"thread_list": {
|
||||
"context_menu_label": "Možnosti vláken"
|
||||
},
|
||||
"title": "Pravý panel",
|
||||
"video_room_chat": {
|
||||
"title": "Chatovat"
|
||||
}
|
||||
@@ -3400,6 +3411,7 @@
|
||||
"unable_to_find": "Pokusili jste se načíst bod na časové ose místnosti, ale nepodařilo se ho najít."
|
||||
},
|
||||
"m.audio": {
|
||||
"audio_player": "Audio přehrávač",
|
||||
"error_downloading_audio": "Chyba při stahování audia",
|
||||
"error_processing_audio": "Došlo k chybě při zpracovávání hlasové zprávy",
|
||||
"error_processing_voice_message": "Chyba při zpracování hlasové zprávy",
|
||||
|
||||
@@ -654,6 +654,7 @@
|
||||
"poll_button_no_perms_description": "You do not have permission to start polls in this room.",
|
||||
"poll_button_no_perms_title": "Permission Required",
|
||||
"replying_title": "Replying",
|
||||
"room_unencrypted": "Messages in this room are not end-to-end encrypted",
|
||||
"room_upgraded_link": "The conversation continues here.",
|
||||
"room_upgraded_notice": "This room has been replaced and is no longer active.",
|
||||
"send_button_title": "Send message",
|
||||
|
||||
@@ -654,6 +654,7 @@
|
||||
"poll_button_no_perms_description": "Vous n’avez pas la permission de démarrer un sondage dans ce salon.",
|
||||
"poll_button_no_perms_title": "Autorisation requise",
|
||||
"replying_title": "Répond",
|
||||
"room_unencrypted": "Les messages dans ce salon ne sont pas chiffrés de bout en bout",
|
||||
"room_upgraded_link": "La discussion continue ici.",
|
||||
"room_upgraded_notice": "Ce salon a été remplacé et n’est plus actif.",
|
||||
"send_button_title": "Envoyer le message",
|
||||
@@ -1366,6 +1367,10 @@
|
||||
"name_email_mxid_share_space": "Invitez quelqu’un grâce à son nom, adresse e-mail, nom d’utilisateur (tel que <userId/>) ou <a>partagez cet espace</a>.",
|
||||
"name_mxid_share_room": "Invitez quelqu’un à partir de son nom, pseudo (comme <userId/>) ou <a>partagez ce salon</a>.",
|
||||
"name_mxid_share_space": "Invitez quelqu’un grâce à son nom, nom d’utilisateur (tel que <userId/>) ou <a>partagez cet espace</a>.",
|
||||
"progress": {
|
||||
"dont_close": "Ne fermez pas l\"application tant que l'opération est en cours",
|
||||
"preparing": "Préparation des invitations..."
|
||||
},
|
||||
"recents_section": "Conversations récentes",
|
||||
"room_failed_partial": "Nous avons envoyé les invitations, mais les personnes ci-dessous n’ont pas pu être invitées à rejoindre <RoomName/>",
|
||||
"room_failed_partial_title": "Certaines invitations n’ont pas pu être envoyées",
|
||||
|
||||
@@ -654,6 +654,7 @@
|
||||
"poll_button_no_perms_description": "Du har ikke tillatelse til å starte avstemninger i dette rommet.",
|
||||
"poll_button_no_perms_title": "Tillatelse kreves",
|
||||
"replying_title": "Svarer på",
|
||||
"room_unencrypted": "Meldinger i dette rommet er ikke ende-til-ende krypterte",
|
||||
"room_upgraded_link": "Samtalen fortsetter her.",
|
||||
"room_upgraded_notice": "Dette rommet har blitt erstattet og er ikke lenger aktivt.",
|
||||
"send_button_title": "Send melding",
|
||||
|
||||
@@ -23,14 +23,12 @@ import { type IWidgetApiRequest, type ClientWidgetApi, type IWidgetData } from "
|
||||
import {
|
||||
type MatrixRTCSession,
|
||||
MatrixRTCSessionEvent,
|
||||
type CallMembership,
|
||||
MatrixRTCSessionManagerEvents,
|
||||
} from "matrix-js-sdk/src/matrixrtc";
|
||||
|
||||
import type EventEmitter from "events";
|
||||
import type { IApp } from "../stores/WidgetStore";
|
||||
import SettingsStore from "../settings/SettingsStore";
|
||||
import MediaDeviceHandler, { MediaDeviceKindEnum } from "../MediaDeviceHandler";
|
||||
import { timeout } from "../utils/promise";
|
||||
import WidgetUtils from "../utils/WidgetUtils";
|
||||
import { WidgetType } from "../widgets/WidgetType";
|
||||
@@ -193,18 +191,6 @@ export abstract class Call extends TypedEventEmitter<CallEvent, CallEventHandler
|
||||
*/
|
||||
public abstract clean(): Promise<void>;
|
||||
|
||||
/**
|
||||
* Contacts the widget to connect to the call or prompt the user to connect to the call.
|
||||
* @param {MediaDeviceInfo | null} audioInput The audio input to use, or
|
||||
* null to start muted.
|
||||
* @param {MediaDeviceInfo | null} audioInput The video input to use, or
|
||||
* null to start muted.
|
||||
*/
|
||||
protected abstract performConnection(
|
||||
audioInput: MediaDeviceInfo | null,
|
||||
videoInput: MediaDeviceInfo | null,
|
||||
): Promise<void>;
|
||||
|
||||
/**
|
||||
* Contacts the widget to disconnect from the call.
|
||||
*/
|
||||
@@ -212,28 +198,10 @@ export abstract class Call extends TypedEventEmitter<CallEvent, CallEventHandler
|
||||
|
||||
/**
|
||||
* Starts the communication between the widget and the call.
|
||||
* The call then waits for the necessary requirements to actually perform the connection
|
||||
* or connects right away depending on the call type. (Jitsi, Legacy, ElementCall...)
|
||||
* It uses the media devices set in MediaDeviceHandler.
|
||||
* The widget associated with the call must be active
|
||||
* for this to succeed.
|
||||
* The widget associated with the call must be active for this to succeed.
|
||||
* Only call this if the call state is: ConnectionState.Disconnected.
|
||||
*/
|
||||
public async start(): Promise<void> {
|
||||
const { [MediaDeviceKindEnum.AudioInput]: audioInputs, [MediaDeviceKindEnum.VideoInput]: videoInputs } =
|
||||
(await MediaDeviceHandler.getDevices())!;
|
||||
|
||||
let audioInput: MediaDeviceInfo | null = null;
|
||||
if (!MediaDeviceHandler.startWithAudioMuted) {
|
||||
const deviceId = MediaDeviceHandler.getAudioInput();
|
||||
audioInput = audioInputs.find((d) => d.deviceId === deviceId) ?? audioInputs[0] ?? null;
|
||||
}
|
||||
let videoInput: MediaDeviceInfo | null = null;
|
||||
if (!MediaDeviceHandler.startWithVideoMuted) {
|
||||
const deviceId = MediaDeviceHandler.getVideoInput();
|
||||
videoInput = videoInputs.find((d) => d.deviceId === deviceId) ?? videoInputs[0] ?? null;
|
||||
}
|
||||
|
||||
const messagingStore = WidgetMessagingStore.instance;
|
||||
this.messaging = messagingStore.getMessagingForUid(this.widgetUid) ?? null;
|
||||
if (!this.messaging) {
|
||||
@@ -254,13 +222,23 @@ export abstract class Call extends TypedEventEmitter<CallEvent, CallEventHandler
|
||||
throw new Error(`Failed to bind call widget in room ${this.roomId}: ${e}`);
|
||||
}
|
||||
}
|
||||
await this.performConnection(audioInput, videoInput);
|
||||
}
|
||||
|
||||
protected setConnected(): void {
|
||||
this.room.on(RoomEvent.MyMembership, this.onMyMembership);
|
||||
window.addEventListener("beforeunload", this.beforeUnload);
|
||||
this.connectionState = ConnectionState.Connected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually marks the call as disconnected.
|
||||
*/
|
||||
protected setDisconnected(): void {
|
||||
this.room.off(RoomEvent.MyMembership, this.onMyMembership);
|
||||
window.removeEventListener("beforeunload", this.beforeUnload);
|
||||
this.connectionState = ConnectionState.Disconnected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnects the user from the call.
|
||||
*/
|
||||
@@ -273,15 +251,6 @@ export abstract class Call extends TypedEventEmitter<CallEvent, CallEventHandler
|
||||
this.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually marks the call as disconnected.
|
||||
*/
|
||||
public setDisconnected(): void {
|
||||
this.room.off(RoomEvent.MyMembership, this.onMyMembership);
|
||||
window.removeEventListener("beforeunload", this.beforeUnload);
|
||||
this.connectionState = ConnectionState.Disconnected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops further communication with the widget and tells the UI to close.
|
||||
*/
|
||||
@@ -467,66 +436,10 @@ export class JitsiCall extends Call {
|
||||
});
|
||||
}
|
||||
|
||||
protected async performConnection(
|
||||
audioInput: MediaDeviceInfo | null,
|
||||
videoInput: MediaDeviceInfo | null,
|
||||
): Promise<void> {
|
||||
// Ensure that the messaging doesn't get stopped while we're waiting for responses
|
||||
const dontStopMessaging = new Promise<void>((resolve, reject) => {
|
||||
const messagingStore = WidgetMessagingStore.instance;
|
||||
|
||||
const listener = (uid: string): void => {
|
||||
if (uid === this.widgetUid) {
|
||||
cleanup();
|
||||
reject(new Error("Messaging stopped"));
|
||||
}
|
||||
};
|
||||
const done = (): void => {
|
||||
cleanup();
|
||||
resolve();
|
||||
};
|
||||
const cleanup = (): void => {
|
||||
messagingStore.off(WidgetMessagingStoreEvent.StopMessaging, listener);
|
||||
this.off(CallEvent.ConnectionState, done);
|
||||
};
|
||||
|
||||
messagingStore.on(WidgetMessagingStoreEvent.StopMessaging, listener);
|
||||
this.on(CallEvent.ConnectionState, done);
|
||||
});
|
||||
|
||||
// Empirically, it's possible for Jitsi Meet to crash instantly at startup,
|
||||
// sending a hangup event that races with the rest of this method, so we need
|
||||
// to add the hangup listener now rather than later
|
||||
public async start(): Promise<void> {
|
||||
await super.start();
|
||||
this.messaging!.on(`action:${ElementWidgetActions.JoinCall}`, this.onJoin);
|
||||
this.messaging!.on(`action:${ElementWidgetActions.HangupCall}`, this.onHangup);
|
||||
|
||||
// Actually perform the join
|
||||
const response = waitForEvent(
|
||||
this.messaging!,
|
||||
`action:${ElementWidgetActions.JoinCall}`,
|
||||
(ev: CustomEvent<IWidgetApiRequest>) => {
|
||||
ev.preventDefault();
|
||||
this.messaging!.transport.reply(ev.detail, {}); // ack
|
||||
return true;
|
||||
},
|
||||
);
|
||||
const request = this.messaging!.transport.send(ElementWidgetActions.JoinCall, {
|
||||
audioInput: audioInput?.label ?? null,
|
||||
videoInput: videoInput?.label ?? null,
|
||||
});
|
||||
try {
|
||||
await Promise.race([Promise.all([request, response]), dontStopMessaging]);
|
||||
} catch (e) {
|
||||
// If it timed out, clean up our advance preparations
|
||||
this.messaging!.off(`action:${ElementWidgetActions.HangupCall}`, this.onHangup);
|
||||
|
||||
if (this.messaging!.transport.ready) {
|
||||
// The messaging still exists, which means Jitsi might still be going in the background
|
||||
this.messaging!.transport.send(ElementWidgetActions.HangupCall, { force: true });
|
||||
}
|
||||
|
||||
throw new Error(`Failed to join call in room ${this.roomId}: ${e}`);
|
||||
}
|
||||
|
||||
ActiveWidgetStore.instance.on(ActiveWidgetStoreEvent.Dock, this.onDock);
|
||||
ActiveWidgetStore.instance.on(ActiveWidgetStoreEvent.Undock, this.onUndock);
|
||||
}
|
||||
@@ -549,18 +462,17 @@ export class JitsiCall extends Call {
|
||||
}
|
||||
}
|
||||
|
||||
public setDisconnected(): void {
|
||||
// During tests this.messaging can be undefined
|
||||
this.messaging?.off(`action:${ElementWidgetActions.HangupCall}`, this.onHangup);
|
||||
public close(): void {
|
||||
this.messaging!.off(`action:${ElementWidgetActions.JoinCall}`, this.onJoin);
|
||||
this.messaging!.off(`action:${ElementWidgetActions.HangupCall}`, this.onHangup);
|
||||
ActiveWidgetStore.instance.off(ActiveWidgetStoreEvent.Dock, this.onDock);
|
||||
ActiveWidgetStore.instance.off(ActiveWidgetStoreEvent.Undock, this.onUndock);
|
||||
|
||||
super.setDisconnected();
|
||||
super.close();
|
||||
}
|
||||
|
||||
public destroy(): void {
|
||||
this.room.off(RoomStateEvent.Update, this.onRoomState);
|
||||
this.on(CallEvent.ConnectionState, this.onConnectionState);
|
||||
this.off(CallEvent.ConnectionState, this.onConnectionState);
|
||||
if (this.participantsExpirationTimer !== null) {
|
||||
clearTimeout(this.participantsExpirationTimer);
|
||||
this.participantsExpirationTimer = null;
|
||||
@@ -612,27 +524,21 @@ export class JitsiCall extends Call {
|
||||
await this.messaging!.transport.send(ElementWidgetActions.SpotlightLayout, {});
|
||||
};
|
||||
|
||||
private readonly onJoin = (ev: CustomEvent<IWidgetApiRequest>): void => {
|
||||
ev.preventDefault();
|
||||
this.messaging!.transport.reply(ev.detail, {}); // ack
|
||||
this.setConnected();
|
||||
};
|
||||
|
||||
private readonly onHangup = async (ev: CustomEvent<IWidgetApiRequest>): Promise<void> => {
|
||||
// If we're already in the middle of a client-initiated disconnection,
|
||||
// ignore the event
|
||||
if (this.connectionState === ConnectionState.Disconnecting) return;
|
||||
|
||||
ev.preventDefault();
|
||||
|
||||
// In case this hangup is caused by Jitsi Meet crashing at startup,
|
||||
// wait for the connection event in order to avoid racing
|
||||
if (this.connectionState === ConnectionState.Disconnected) {
|
||||
await waitForEvent(this, CallEvent.ConnectionState);
|
||||
}
|
||||
|
||||
this.messaging!.transport.reply(ev.detail, {}); // ack
|
||||
this.setDisconnected();
|
||||
this.close();
|
||||
// In video rooms we immediately want to restart the call after hangup
|
||||
// The lobby will be shown again and it connects to all signals from Jitsi.
|
||||
if (isVideoRoom(this.room)) {
|
||||
this.start();
|
||||
}
|
||||
if (!isVideoRoom(this.room)) this.close();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -860,54 +766,38 @@ export class ElementCall extends Call {
|
||||
ElementCall.createOrGetCallWidget(room.roomId, room.client, skipLobby, isVideoRoom(room));
|
||||
}
|
||||
|
||||
protected async performConnection(
|
||||
audioInput: MediaDeviceInfo | null,
|
||||
videoInput: MediaDeviceInfo | null,
|
||||
): Promise<void> {
|
||||
public async start(): Promise<void> {
|
||||
await super.start();
|
||||
this.messaging!.on(`action:${ElementWidgetActions.JoinCall}`, this.onJoin);
|
||||
this.messaging!.on(`action:${ElementWidgetActions.HangupCall}`, this.onHangup);
|
||||
this.messaging!.once(`action:${ElementWidgetActions.Close}`, this.onClose);
|
||||
this.messaging!.on(`action:${ElementWidgetActions.Close}`, this.onClose);
|
||||
this.messaging!.on(`action:${ElementWidgetActions.DeviceMute}`, this.onDeviceMute);
|
||||
|
||||
// TODO: Watch for a widget action telling us that the join button was clicked, rather than
|
||||
// relying on the MatrixRTC session state, to set the state to connecting
|
||||
const session = this.client.matrixRTC.getActiveRoomSession(this.room);
|
||||
if (session) {
|
||||
await waitForEvent(
|
||||
session,
|
||||
MatrixRTCSessionEvent.MembershipsChanged,
|
||||
(_, newMemberships: CallMembership[]) =>
|
||||
newMemberships.some((m) => m.sender === this.client.getUserId()),
|
||||
false, // allow user to wait as long as they want (no timeout)
|
||||
);
|
||||
} else {
|
||||
await waitForEvent(
|
||||
this.client.matrixRTC,
|
||||
MatrixRTCSessionManagerEvents.SessionStarted,
|
||||
(roomId: string, session: MatrixRTCSession) =>
|
||||
this.session.callId === session.callId && roomId === this.roomId,
|
||||
false, // allow user to wait as long as they want (no timeout)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected async performDisconnection(): Promise<void> {
|
||||
const response = waitForEvent(
|
||||
this.messaging!,
|
||||
`action:${ElementWidgetActions.HangupCall}`,
|
||||
(ev: CustomEvent<IWidgetApiRequest>) => {
|
||||
ev.preventDefault();
|
||||
this.messaging!.transport.reply(ev.detail, {}); // ack
|
||||
return true;
|
||||
},
|
||||
);
|
||||
const request = this.messaging!.transport.send(ElementWidgetActions.HangupCall, {});
|
||||
try {
|
||||
await this.messaging!.transport.send(ElementWidgetActions.HangupCall, {});
|
||||
await waitForEvent(
|
||||
this.session,
|
||||
MatrixRTCSessionEvent.MembershipsChanged,
|
||||
(_, newMemberships: CallMembership[]) =>
|
||||
!newMemberships.some((m) => m.sender === this.client.getUserId()),
|
||||
);
|
||||
await Promise.all([request, response]);
|
||||
} catch (e) {
|
||||
throw new Error(`Failed to hangup call in room ${this.roomId}: ${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
public setDisconnected(): void {
|
||||
public close(): void {
|
||||
this.messaging!.off(`action:${ElementWidgetActions.JoinCall}`, this.onJoin);
|
||||
this.messaging!.off(`action:${ElementWidgetActions.HangupCall}`, this.onHangup);
|
||||
this.messaging!.off(`action:${ElementWidgetActions.Close}`, this.onClose);
|
||||
this.messaging!.off(`action:${ElementWidgetActions.DeviceMute}`, this.onDeviceMute);
|
||||
super.setDisconnected();
|
||||
super.close();
|
||||
}
|
||||
|
||||
public destroy(): void {
|
||||
@@ -954,22 +844,27 @@ export class ElementCall extends Call {
|
||||
this.messaging!.transport.reply(ev.detail, {}); // ack
|
||||
};
|
||||
|
||||
private readonly onJoin = (ev: CustomEvent<IWidgetApiRequest>): void => {
|
||||
ev.preventDefault();
|
||||
this.messaging!.transport.reply(ev.detail, {}); // ack
|
||||
this.setConnected();
|
||||
};
|
||||
|
||||
private readonly onHangup = async (ev: CustomEvent<IWidgetApiRequest>): Promise<void> => {
|
||||
// If we're already in the middle of a client-initiated disconnection,
|
||||
// ignore the event
|
||||
if (this.connectionState === ConnectionState.Disconnecting) return;
|
||||
|
||||
ev.preventDefault();
|
||||
this.messaging!.transport.reply(ev.detail, {}); // ack
|
||||
this.setDisconnected();
|
||||
// In video rooms we immediately want to reconnect after hangup
|
||||
// This starts the lobby again and connects to all signals from EC.
|
||||
if (isVideoRoom(this.room)) {
|
||||
this.start();
|
||||
}
|
||||
};
|
||||
|
||||
private readonly onClose = async (ev: CustomEvent<IWidgetApiRequest>): Promise<void> => {
|
||||
ev.preventDefault();
|
||||
this.messaging!.transport.reply(ev.detail, {}); // ack
|
||||
// User is done with the call; tell the UI to close it
|
||||
this.close();
|
||||
this.setDisconnected(); // Just in case the widget forgot to emit a hangup action (maybe it's in an error state)
|
||||
this.close(); // User is done with the call; tell the UI to close it
|
||||
};
|
||||
|
||||
public clean(): Promise<void> {
|
||||
|
||||
@@ -16,8 +16,6 @@ import type {
|
||||
CustomMessageRenderHints as ModuleCustomCustomMessageRenderHints,
|
||||
MatrixEvent as ModuleMatrixEvent,
|
||||
CustomRoomPreviewBarRenderFunction,
|
||||
MessageProfileRenderFunction,
|
||||
UserInfoRenderFunction,
|
||||
} from "@element-hq/element-web-module-api";
|
||||
import type React from "react";
|
||||
|
||||
@@ -44,7 +42,7 @@ export class CustomComponentsApi implements ICustomComponentsApi {
|
||||
* @param mxEvent
|
||||
* @returns An event object, or `null` if the event was not a message event.
|
||||
*/
|
||||
public static getModuleMatrixEvent(mxEvent: MatrixEvent): ModuleMatrixEvent | null {
|
||||
private static getModuleMatrixEvent(mxEvent: MatrixEvent): ModuleMatrixEvent | null {
|
||||
const eventId = mxEvent.getId();
|
||||
const roomId = mxEvent.getRoomId();
|
||||
const sender = mxEvent.sender;
|
||||
@@ -140,8 +138,6 @@ export class CustomComponentsApi implements ICustomComponentsApi {
|
||||
}
|
||||
|
||||
private _roomPreviewBarRenderer?: CustomRoomPreviewBarRenderFunction;
|
||||
private _userInfoRenderer?: UserInfoRenderFunction;
|
||||
private _messageProfileRenderer?: MessageProfileRenderFunction;
|
||||
|
||||
/**
|
||||
* Get the custom room preview bar renderer, if any has been registered.
|
||||
@@ -157,25 +153,4 @@ export class CustomComponentsApi implements ICustomComponentsApi {
|
||||
public registerRoomPreviewBar(renderer: CustomRoomPreviewBarRenderFunction): void {
|
||||
this._roomPreviewBarRenderer = renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the custom user info renderer, if any has been registered.
|
||||
*/
|
||||
public get messageProfileRenderer(): MessageProfileRenderFunction | undefined {
|
||||
return this._messageProfileRenderer;
|
||||
}
|
||||
|
||||
public registerMessageProfile(renderer: MessageProfileRenderFunction): void {
|
||||
this._messageProfileRenderer = renderer;
|
||||
}
|
||||
/**
|
||||
* Get the custom user info renderer, if any has been registered.
|
||||
*/
|
||||
public get userInfoRenderer(): UserInfoRenderFunction | undefined {
|
||||
return this._userInfoRenderer;
|
||||
}
|
||||
|
||||
public registerUserInfo(renderer: UserInfoRenderFunction): void {
|
||||
this._userInfoRenderer = renderer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,6 @@ export class MockedCall extends Call {
|
||||
// No action needed for any of the following methods since this is just a mock
|
||||
public async clean(): Promise<void> {}
|
||||
// Public to allow spying
|
||||
public async performConnection(): Promise<void> {}
|
||||
public async performDisconnection(): Promise<void> {}
|
||||
|
||||
public destroy() {
|
||||
|
||||
@@ -7,6 +7,7 @@ exports[`dialogTermsInteractionCallback should render a dialog with the expected
|
||||
class=""
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
|
||||
@@ -12,6 +12,7 @@ exports[`<NewRecoveryMethodDialog /> when key backup is disabled 1`] = `
|
||||
class="mx_KeyBackupFailedDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
@@ -83,6 +84,7 @@ exports[`<NewRecoveryMethodDialog /> when key backup is enabled 1`] = `
|
||||
class="mx_KeyBackupFailedDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
|
||||
@@ -388,6 +388,7 @@ exports[`<MatrixChat /> with an existing session onAction() room actions leave_r
|
||||
class="mx_QuestionDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
@@ -444,6 +445,7 @@ exports[`<MatrixChat /> with an existing session onAction() room actions leave_r
|
||||
class="mx_QuestionDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
|
||||
@@ -1,225 +1,6 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`RoomView for a local room in state CREATING should match the snapshot 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="mx_RoomView mx_RoomView--local"
|
||||
>
|
||||
<header
|
||||
class="flex mx_RoomHeader light-panel"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<button
|
||||
aria-label="Open room settings"
|
||||
aria-live="off"
|
||||
class="_avatar_1qbcf_8 mx_BaseAvatar _avatar-imageless_1qbcf_52"
|
||||
data-color="3"
|
||||
data-testid="avatar-img"
|
||||
data-type="round"
|
||||
role="button"
|
||||
style="--cpd-avatar-size: 40px;"
|
||||
tabindex="-1"
|
||||
>
|
||||
u
|
||||
</button>
|
||||
<button
|
||||
aria-label="Room info"
|
||||
class="mx_RoomHeader_infoWrapper"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="mx_RoomHeader_info box-flex"
|
||||
style="--mx-box-flex: 1;"
|
||||
>
|
||||
<div
|
||||
aria-level="1"
|
||||
class="_typography_6v6n8_153 _font-body-lg-semibold_6v6n8_74 mx_RoomHeader_heading"
|
||||
dir="auto"
|
||||
role="heading"
|
||||
>
|
||||
<span
|
||||
class="mx_RoomHeader_truncated mx_lineClamp"
|
||||
>
|
||||
@user:example.com
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
aria-label="Video call"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 32px;"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_zr2a0_17"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
aria-labelledby="«rg4»"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M6 4h10a2 2 0 0 1 2 2v4.286l3.35-2.871a1 1 0 0 1 1.65.76v7.65a1 1 0 0 1-1.65.76L18 13.715V18a2 2 0 0 1-2 2H6a4 4 0 0 1-4-4V8a4 4 0 0 1 4-4"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
aria-label="Voice call"
|
||||
aria-labelledby="«rg9»"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 32px;"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_zr2a0_17"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="m20.958 16.374.039 3.527q0 .427-.33.756-.33.33-.756.33a16 16 0 0 1-6.57-1.105 16.2 16.2 0 0 1-5.563-3.663 16.1 16.1 0 0 1-3.653-5.573 16.3 16.3 0 0 1-1.115-6.56q0-.427.33-.757T4.095 3l3.528.039a1.07 1.07 0 0 1 1.085.93l.543 3.954q.039.271-.039.504a1.1 1.1 0 0 1-.271.426l-1.64 1.64q.505 1.008 1.154 1.909c.433.6 1.444 1.696 1.444 1.696s1.095 1.01 1.696 1.444q.9.65 1.909 1.153l1.64-1.64q.193-.193.426-.27t.504-.04l3.954.543q.406.059.668.359t.262.727"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Threads"
|
||||
aria-labelledby="«rge»"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 32px;"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_zr2a0_17"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
class=""
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M4 3h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H6l-2.293 2.293c-.63.63-1.707.184-1.707-.707V5a2 2 0 0 1 2-2m3 7h10q.424 0 .712-.287A.97.97 0 0 0 18 9a.97.97 0 0 0-.288-.713A.97.97 0 0 0 17 8H7a.97.97 0 0 0-.713.287A.97.97 0 0 0 6 9q0 .424.287.713Q6.576 10 7 10m0 4h6q.424 0 .713-.287A.97.97 0 0 0 14 13a.97.97 0 0 0-.287-.713A.97.97 0 0 0 13 12H7a.97.97 0 0 0-.713.287A.97.97 0 0 0 6 13q0 .424.287.713Q6.576 14 7 14"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Room info"
|
||||
aria-labelledby="«rgj»"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 32px;"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_zr2a0_17"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
class=""
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12 17q.424 0 .713-.288A.97.97 0 0 0 13 16v-4a.97.97 0 0 0-.287-.713A.97.97 0 0 0 12 11a.97.97 0 0 0-.713.287A.97.97 0 0 0 11 12v4q0 .424.287.712.288.288.713.288m0-8q.424 0 .713-.287A.97.97 0 0 0 13 8a.97.97 0 0 0-.287-.713A.97.97 0 0 0 12 7a.97.97 0 0 0-.713.287A.97.97 0 0 0 11 8q0 .424.287.713Q11.576 9 12 9m0 13a9.7 9.7 0 0 1-3.9-.788 10.1 10.1 0 0 1-3.175-2.137q-1.35-1.35-2.137-3.175A9.7 9.7 0 0 1 2 12q0-2.075.788-3.9a10.1 10.1 0 0 1 2.137-3.175q1.35-1.35 3.175-2.137A9.7 9.7 0 0 1 12 2q2.075 0 3.9.788a10.1 10.1 0 0 1 3.175 2.137q1.35 1.35 2.137 3.175A9.7 9.7 0 0 1 22 12a9.7 9.7 0 0 1-.788 3.9 10.1 10.1 0 0 1-2.137 3.175q-1.35 1.35-3.175 2.137A9.7 9.7 0 0 1 12 22"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
<div
|
||||
class="_typography_6v6n8_153 _font-body-sm-medium_6v6n8_41"
|
||||
>
|
||||
<div
|
||||
aria-label="2 members"
|
||||
aria-labelledby="«rgo»"
|
||||
class="mx_AccessibleButton mx_FacePile"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="_stacked-avatars_1qbcf_102"
|
||||
>
|
||||
<span
|
||||
class="_avatar_1qbcf_8 mx_BaseAvatar _avatar-imageless_1qbcf_52"
|
||||
data-color="2"
|
||||
data-testid="avatar-img"
|
||||
data-type="round"
|
||||
role="presentation"
|
||||
style="--cpd-avatar-size: 20px;"
|
||||
>
|
||||
u
|
||||
</span>
|
||||
<span
|
||||
class="_avatar_1qbcf_8 mx_BaseAvatar _avatar-imageless_1qbcf_52"
|
||||
data-color="3"
|
||||
data-testid="avatar-img"
|
||||
data-type="round"
|
||||
role="presentation"
|
||||
style="--cpd-avatar-size: 20px;"
|
||||
>
|
||||
u
|
||||
</span>
|
||||
</div>
|
||||
2
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div
|
||||
class="mx_RoomView_body"
|
||||
>
|
||||
<div
|
||||
class="mx_LargeLoader"
|
||||
>
|
||||
<div
|
||||
class="mx_Spinner"
|
||||
>
|
||||
<div
|
||||
aria-label="Loading…"
|
||||
class="mx_Spinner_icon"
|
||||
data-testid="spinner"
|
||||
role="progressbar"
|
||||
style="width: 45px; height: 45px;"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="mx_LargeLoader_text"
|
||||
>
|
||||
We're creating a room with @user:example.com
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`RoomView for a local room in state ERROR should match the snapshot 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="mx_RoomView mx_RoomView--local"
|
||||
@@ -410,6 +191,225 @@ exports[`RoomView for a local room in state ERROR should match the snapshot 1`]
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div
|
||||
class="mx_RoomView_body"
|
||||
>
|
||||
<div
|
||||
class="mx_LargeLoader"
|
||||
>
|
||||
<div
|
||||
class="mx_Spinner"
|
||||
>
|
||||
<div
|
||||
aria-label="Loading…"
|
||||
class="mx_Spinner_icon"
|
||||
data-testid="spinner"
|
||||
role="progressbar"
|
||||
style="width: 45px; height: 45px;"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="mx_LargeLoader_text"
|
||||
>
|
||||
We're creating a room with @user:example.com
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`RoomView for a local room in state ERROR should match the snapshot 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="mx_RoomView mx_RoomView--local"
|
||||
>
|
||||
<header
|
||||
class="flex mx_RoomHeader light-panel"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<button
|
||||
aria-label="Open room settings"
|
||||
aria-live="off"
|
||||
class="_avatar_1qbcf_8 mx_BaseAvatar _avatar-imageless_1qbcf_52"
|
||||
data-color="3"
|
||||
data-testid="avatar-img"
|
||||
data-type="round"
|
||||
role="button"
|
||||
style="--cpd-avatar-size: 40px;"
|
||||
tabindex="-1"
|
||||
>
|
||||
u
|
||||
</button>
|
||||
<button
|
||||
aria-label="Room info"
|
||||
class="mx_RoomHeader_infoWrapper"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="mx_RoomHeader_info box-flex"
|
||||
style="--mx-box-flex: 1;"
|
||||
>
|
||||
<div
|
||||
aria-level="1"
|
||||
class="_typography_6v6n8_153 _font-body-lg-semibold_6v6n8_74 mx_RoomHeader_heading"
|
||||
dir="auto"
|
||||
role="heading"
|
||||
>
|
||||
<span
|
||||
class="mx_RoomHeader_truncated mx_lineClamp"
|
||||
>
|
||||
@user:example.com
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
aria-label="Video call"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 32px;"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_zr2a0_17"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
aria-labelledby="«ri0»"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M6 4h10a2 2 0 0 1 2 2v4.286l3.35-2.871a1 1 0 0 1 1.65.76v7.65a1 1 0 0 1-1.65.76L18 13.715V18a2 2 0 0 1-2 2H6a4 4 0 0 1-4-4V8a4 4 0 0 1 4-4"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
aria-label="Voice call"
|
||||
aria-labelledby="«ri5»"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 32px;"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_zr2a0_17"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="m20.958 16.374.039 3.527q0 .427-.33.756-.33.33-.756.33a16 16 0 0 1-6.57-1.105 16.2 16.2 0 0 1-5.563-3.663 16.1 16.1 0 0 1-3.653-5.573 16.3 16.3 0 0 1-1.115-6.56q0-.427.33-.757T4.095 3l3.528.039a1.07 1.07 0 0 1 1.085.93l.543 3.954q.039.271-.039.504a1.1 1.1 0 0 1-.271.426l-1.64 1.64q.505 1.008 1.154 1.909c.433.6 1.444 1.696 1.444 1.696s1.095 1.01 1.696 1.444q.9.65 1.909 1.153l1.64-1.64q.193-.193.426-.27t.504-.04l3.954.543q.406.059.668.359t.262.727"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Threads"
|
||||
aria-labelledby="«ria»"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 32px;"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_zr2a0_17"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
class=""
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M4 3h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H6l-2.293 2.293c-.63.63-1.707.184-1.707-.707V5a2 2 0 0 1 2-2m3 7h10q.424 0 .712-.287A.97.97 0 0 0 18 9a.97.97 0 0 0-.288-.713A.97.97 0 0 0 17 8H7a.97.97 0 0 0-.713.287A.97.97 0 0 0 6 9q0 .424.287.713Q6.576 10 7 10m0 4h6q.424 0 .713-.287A.97.97 0 0 0 14 13a.97.97 0 0 0-.287-.713A.97.97 0 0 0 13 12H7a.97.97 0 0 0-.713.287A.97.97 0 0 0 6 13q0 .424.287.713Q6.576 14 7 14"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Room info"
|
||||
aria-labelledby="«rif»"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 32px;"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_zr2a0_17"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
class=""
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12 17q.424 0 .713-.288A.97.97 0 0 0 13 16v-4a.97.97 0 0 0-.287-.713A.97.97 0 0 0 12 11a.97.97 0 0 0-.713.287A.97.97 0 0 0 11 12v4q0 .424.287.712.288.288.713.288m0-8q.424 0 .713-.287A.97.97 0 0 0 13 8a.97.97 0 0 0-.287-.713A.97.97 0 0 0 12 7a.97.97 0 0 0-.713.287A.97.97 0 0 0 11 8q0 .424.287.713Q11.576 9 12 9m0 13a9.7 9.7 0 0 1-3.9-.788 10.1 10.1 0 0 1-3.175-2.137q-1.35-1.35-2.137-3.175A9.7 9.7 0 0 1 2 12q0-2.075.788-3.9a10.1 10.1 0 0 1 2.137-3.175q1.35-1.35 3.175-2.137A9.7 9.7 0 0 1 12 2q2.075 0 3.9.788a10.1 10.1 0 0 1 3.175 2.137q1.35 1.35 2.137 3.175A9.7 9.7 0 0 1 22 12a9.7 9.7 0 0 1-.788 3.9 10.1 10.1 0 0 1-2.137 3.175q-1.35 1.35-3.175 2.137A9.7 9.7 0 0 1 12 22"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
<div
|
||||
class="_typography_6v6n8_153 _font-body-sm-medium_6v6n8_41"
|
||||
>
|
||||
<div
|
||||
aria-label="2 members"
|
||||
aria-labelledby="«rik»"
|
||||
class="mx_AccessibleButton mx_FacePile"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="_stacked-avatars_1qbcf_102"
|
||||
>
|
||||
<span
|
||||
class="_avatar_1qbcf_8 mx_BaseAvatar _avatar-imageless_1qbcf_52"
|
||||
data-color="2"
|
||||
data-testid="avatar-img"
|
||||
data-type="round"
|
||||
role="presentation"
|
||||
style="--cpd-avatar-size: 20px;"
|
||||
>
|
||||
u
|
||||
</span>
|
||||
<span
|
||||
class="_avatar_1qbcf_8 mx_BaseAvatar _avatar-imageless_1qbcf_52"
|
||||
data-color="3"
|
||||
data-testid="avatar-img"
|
||||
data-type="round"
|
||||
role="presentation"
|
||||
style="--cpd-avatar-size: 20px;"
|
||||
>
|
||||
u
|
||||
</span>
|
||||
</div>
|
||||
2
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<main
|
||||
aria-label="Room content"
|
||||
class="mx_RoomView_body"
|
||||
@@ -583,7 +583,7 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] =
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
aria-labelledby="«rbo»"
|
||||
aria-labelledby="«rca»"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
@@ -599,7 +599,7 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] =
|
||||
<button
|
||||
aria-disabled="false"
|
||||
aria-label="Voice call"
|
||||
aria-labelledby="«rbt»"
|
||||
aria-labelledby="«rcf»"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
@@ -625,7 +625,7 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] =
|
||||
</button>
|
||||
<button
|
||||
aria-label="Threads"
|
||||
aria-labelledby="«rc2»"
|
||||
aria-labelledby="«rck»"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
@@ -652,7 +652,7 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] =
|
||||
</button>
|
||||
<button
|
||||
aria-label="Room info"
|
||||
aria-labelledby="«rc7»"
|
||||
aria-labelledby="«rcp»"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
@@ -682,7 +682,7 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] =
|
||||
>
|
||||
<div
|
||||
aria-label="2 members"
|
||||
aria-labelledby="«rcc»"
|
||||
aria-labelledby="«rcu»"
|
||||
class="mx_AccessibleButton mx_FacePile"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
@@ -800,6 +800,8 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] =
|
||||
class="mx_MessageComposer_e2eIconWrapper"
|
||||
>
|
||||
<svg
|
||||
aria-label="Messages in this room are not end-to-end encrypted"
|
||||
aria-labelledby="«rd7»"
|
||||
class="mx_E2EIcon mx_MessageComposer_e2eIcon"
|
||||
color="var(--cpd-color-icon-info-primary)"
|
||||
fill="currentColor"
|
||||
@@ -982,7 +984,7 @@ exports[`RoomView for a local room in state NEW that is encrypted should match t
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
aria-labelledby="«rdu»"
|
||||
aria-labelledby="«rem»"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
@@ -998,7 +1000,7 @@ exports[`RoomView for a local room in state NEW that is encrypted should match t
|
||||
<button
|
||||
aria-disabled="false"
|
||||
aria-label="Voice call"
|
||||
aria-labelledby="«re3»"
|
||||
aria-labelledby="«rer»"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
@@ -1024,7 +1026,7 @@ exports[`RoomView for a local room in state NEW that is encrypted should match t
|
||||
</button>
|
||||
<button
|
||||
aria-label="Threads"
|
||||
aria-labelledby="«re8»"
|
||||
aria-labelledby="«rf0»"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
@@ -1051,7 +1053,7 @@ exports[`RoomView for a local room in state NEW that is encrypted should match t
|
||||
</button>
|
||||
<button
|
||||
aria-label="Room info"
|
||||
aria-labelledby="«red»"
|
||||
aria-labelledby="«rf5»"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
@@ -1081,7 +1083,7 @@ exports[`RoomView for a local room in state NEW that is encrypted should match t
|
||||
>
|
||||
<div
|
||||
aria-label="2 members"
|
||||
aria-labelledby="«rei»"
|
||||
aria-labelledby="«rfa»"
|
||||
class="mx_AccessibleButton mx_FacePile"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
@@ -1194,6 +1196,8 @@ exports[`RoomView for a local room in state NEW that is encrypted should match t
|
||||
class="mx_MessageComposer_e2eIconWrapper"
|
||||
>
|
||||
<svg
|
||||
aria-label="Messages in this room are not end-to-end encrypted"
|
||||
aria-labelledby="«rfj»"
|
||||
class="mx_E2EIcon mx_MessageComposer_e2eIcon"
|
||||
color="var(--cpd-color-icon-info-primary)"
|
||||
fill="currentColor"
|
||||
@@ -1462,7 +1466,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
aria-labelledby="«r2c»"
|
||||
aria-labelledby="«r2i»"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
@@ -1478,7 +1482,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
|
||||
<button
|
||||
aria-disabled="false"
|
||||
aria-label="Voice call"
|
||||
aria-labelledby="«r2h»"
|
||||
aria-labelledby="«r2n»"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
@@ -1504,7 +1508,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
|
||||
</button>
|
||||
<button
|
||||
aria-label="Threads"
|
||||
aria-labelledby="«r2m»"
|
||||
aria-labelledby="«r2s»"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
@@ -1531,7 +1535,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
|
||||
</button>
|
||||
<button
|
||||
aria-label="Room info"
|
||||
aria-labelledby="«r2r»"
|
||||
aria-labelledby="«r31»"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
@@ -1561,7 +1565,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
|
||||
>
|
||||
<div
|
||||
aria-label="0 members"
|
||||
aria-labelledby="«r30»"
|
||||
aria-labelledby="«r36»"
|
||||
class="mx_AccessibleButton mx_FacePile"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
@@ -1674,7 +1678,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
aria-labelledby="«r2c»"
|
||||
aria-labelledby="«r2i»"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
@@ -1690,7 +1694,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
|
||||
<button
|
||||
aria-disabled="false"
|
||||
aria-label="Voice call"
|
||||
aria-labelledby="«r2h»"
|
||||
aria-labelledby="«r2n»"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
@@ -1716,7 +1720,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
|
||||
</button>
|
||||
<button
|
||||
aria-label="Threads"
|
||||
aria-labelledby="«r2m»"
|
||||
aria-labelledby="«r2s»"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
@@ -1743,7 +1747,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
|
||||
</button>
|
||||
<button
|
||||
aria-label="Room info"
|
||||
aria-labelledby="«r2r»"
|
||||
aria-labelledby="«r31»"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
@@ -1773,7 +1777,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
|
||||
>
|
||||
<div
|
||||
aria-label="0 members"
|
||||
aria-labelledby="«r30»"
|
||||
aria-labelledby="«r36»"
|
||||
class="mx_AccessibleButton mx_FacePile"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
@@ -1841,7 +1845,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
aria-labelledby="«r3e»"
|
||||
aria-labelledby="«r3k»"
|
||||
class="mx_E2EIcon mx_E2EIcon_verified mx_MessageComposer_e2eIcon"
|
||||
data-testid="e2e-icon"
|
||||
>
|
||||
@@ -2052,7 +2056,7 @@ exports[`RoomView video rooms should render joined video room view 1`] = `
|
||||
</button>
|
||||
<button
|
||||
aria-label="Chat"
|
||||
aria-labelledby="«r7c»"
|
||||
aria-labelledby="«r7i»"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
@@ -2079,7 +2083,7 @@ exports[`RoomView video rooms should render joined video room view 1`] = `
|
||||
</button>
|
||||
<button
|
||||
aria-label="Threads"
|
||||
aria-labelledby="«r7h»"
|
||||
aria-labelledby="«r7n»"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
@@ -2106,7 +2110,7 @@ exports[`RoomView video rooms should render joined video room view 1`] = `
|
||||
</button>
|
||||
<button
|
||||
aria-label="Room info"
|
||||
aria-labelledby="«r7m»"
|
||||
aria-labelledby="«r7s»"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
@@ -2136,7 +2140,7 @@ exports[`RoomView video rooms should render joined video room view 1`] = `
|
||||
>
|
||||
<div
|
||||
aria-label="0 members"
|
||||
aria-labelledby="«r7r»"
|
||||
aria-labelledby="«r81»"
|
||||
class="mx_AccessibleButton mx_FacePile"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
@@ -2212,7 +2216,7 @@ exports[`RoomView video rooms should render joined video room view 1`] = `
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
aria-labelledby="«r84»"
|
||||
aria-labelledby="«r8a»"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="secondary"
|
||||
data-testid="base-card-close-button"
|
||||
@@ -2271,6 +2275,8 @@ exports[`RoomView video rooms should render joined video room view 1`] = `
|
||||
class="mx_MessageComposer_e2eIconWrapper"
|
||||
>
|
||||
<svg
|
||||
aria-label="Messages in this room are not end-to-end encrypted"
|
||||
aria-labelledby="«r8j»"
|
||||
class="mx_E2EIcon mx_MessageComposer_e2eIcon"
|
||||
color="var(--cpd-color-icon-info-primary)"
|
||||
fill="currentColor"
|
||||
|
||||
@@ -14,7 +14,13 @@ import BaseDialog from "../../../../../src/components/views/dialogs/BaseDialog.t
|
||||
describe("BaseDialog", () => {
|
||||
it("calls onFinished when Escape is pressed", async () => {
|
||||
const onFinished = jest.fn();
|
||||
render(<BaseDialog onFinished={onFinished} />);
|
||||
const { container } = render(<BaseDialog onFinished={onFinished} />);
|
||||
// Autolock's autofocus in the empty dialog is focusing on the close button and bringing up the tooltip
|
||||
// So we either need to call escape twice(one for the tooltip and one for the dialog) or focus
|
||||
// on the dialog first.
|
||||
const dialog = container.querySelector('[role="dialog"]') as HTMLElement;
|
||||
dialog?.focus();
|
||||
await userEvent.keyboard("{Escape}");
|
||||
await userEvent.keyboard("{Escape}");
|
||||
expect(onFinished).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -13,6 +13,7 @@ exports[`<ChangelogDialog /> should fetch github proxy url for each repo with ol
|
||||
class="mx_QuestionDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
|
||||
@@ -13,6 +13,7 @@ exports[`ConfirmRejectInviteDialog can reject with options selected 1`] = `
|
||||
class="mx_DeclineAndBlockInviteDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
|
||||
@@ -13,6 +13,7 @@ exports[`ConfirmUserActionDialog renders 1`] = `
|
||||
class="mx_ConfirmUserActionDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
|
||||
@@ -12,6 +12,7 @@ exports[`DevtoolsDialog renders the devtools dialog 1`] = `
|
||||
class="mx_QuestionDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
@@ -33,6 +34,7 @@ exports[`DevtoolsDialog renders the devtools dialog 1`] = `
|
||||
>
|
||||
Room ID: !id
|
||||
<div
|
||||
aria-describedby="«r2»"
|
||||
aria-label="Copy"
|
||||
class="mx_AccessibleButton mx_CopyableText_copyButton"
|
||||
role="button"
|
||||
|
||||
@@ -7,6 +7,7 @@ exports[`<ExportDialog /> renders export dialog 1`] = `
|
||||
class="mx_ExportDialog false mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
|
||||
@@ -13,6 +13,7 @@ exports[`FeedbackDialog should respect feedback config 1`] = `
|
||||
class="mx_QuestionDialog mx_FeedbackDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
|
||||
@@ -13,6 +13,7 @@ exports[`LogoutDialog Prompts user to go to settings if there is a backup on the
|
||||
class="mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
@@ -73,6 +74,7 @@ exports[`LogoutDialog Prompts user to go to settings if there is a backup on the
|
||||
</details>
|
||||
</div>
|
||||
<div
|
||||
aria-describedby="«rq»"
|
||||
aria-label="Close dialog"
|
||||
class="mx_AccessibleButton mx_Dialog_cancelButton"
|
||||
role="button"
|
||||
@@ -100,6 +102,7 @@ exports[`LogoutDialog Prompts user to go to settings if there is no backup on th
|
||||
class="mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
@@ -160,6 +163,7 @@ exports[`LogoutDialog Prompts user to go to settings if there is no backup on th
|
||||
</details>
|
||||
</div>
|
||||
<div
|
||||
aria-describedby="«r10»"
|
||||
aria-label="Close dialog"
|
||||
class="mx_AccessibleButton mx_Dialog_cancelButton"
|
||||
role="button"
|
||||
@@ -187,6 +191,7 @@ exports[`LogoutDialog shows a regular dialog when crypto is disabled 1`] = `
|
||||
class="mx_QuestionDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
|
||||
@@ -12,6 +12,7 @@ exports[`<ManageRestrictedJoinRuleDialog /> should list spaces which are not par
|
||||
class="mx_ManageRestrictedJoinRuleDialog"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
@@ -189,6 +190,7 @@ exports[`<ManageRestrictedJoinRuleDialog /> should render empty state 1`] = `
|
||||
class="mx_ManageRestrictedJoinRuleDialog"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
|
||||
@@ -13,6 +13,7 @@ exports[`ManualDeviceKeyVerificationDialog should render correctly 1`] = `
|
||||
class="mx_QuestionDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
|
||||
@@ -12,6 +12,7 @@ exports[`<MessageEditHistory /> should match the snapshot 1`] = `
|
||||
class="mx_MessageEditHistoryDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
@@ -102,6 +103,7 @@ exports[`<MessageEditHistory /> should match the snapshot 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
aria-describedby="«r2»"
|
||||
aria-label="Close dialog"
|
||||
class="mx_AccessibleButton mx_Dialog_cancelButton"
|
||||
role="button"
|
||||
@@ -128,6 +130,7 @@ exports[`<MessageEditHistory /> should support events with 1`] = `
|
||||
class="mx_MessageEditHistoryDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
@@ -315,6 +318,7 @@ exports[`<MessageEditHistory /> should support events with 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
aria-describedby="«r8»"
|
||||
aria-label="Close dialog"
|
||||
class="mx_AccessibleButton mx_Dialog_cancelButton"
|
||||
role="button"
|
||||
|
||||
@@ -13,6 +13,7 @@ exports[`ReportRoomDialog displays admin message 1`] = `
|
||||
class="mx_ReportRoomDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
|
||||
@@ -13,6 +13,7 @@ exports[`<ServerPickerDialog /> should render dialog 1`] = `
|
||||
class="mx_ServerPickerDialog"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
|
||||
@@ -13,6 +13,7 @@ exports[`ShareDialog should not render the QR code if disabled 1`] = `
|
||||
class="mx_ShareDialog"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
@@ -143,6 +144,7 @@ exports[`ShareDialog should not render the socials if disabled 1`] = `
|
||||
class="mx_ShareDialog"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
@@ -229,6 +231,7 @@ exports[`ShareDialog should render a share dialog for a matrix event 1`] = `
|
||||
class="mx_ShareDialog"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
@@ -402,6 +405,7 @@ exports[`ShareDialog should render a share dialog for a room 1`] = `
|
||||
class="mx_ShareDialog"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
@@ -574,6 +578,7 @@ exports[`ShareDialog should render a share dialog for a room member 1`] = `
|
||||
class="mx_ShareDialog"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
@@ -719,6 +724,7 @@ exports[`ShareDialog should render a share dialog for an URL 1`] = `
|
||||
class="mx_ShareDialog"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
|
||||
@@ -12,6 +12,7 @@ exports[`<UnpinAllDialog /> should render 1`] = `
|
||||
class="mx_UnpinAllDialog"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
|
||||
@@ -12,6 +12,7 @@ exports[`<UntrustedDeviceDialog /> should display the dialog for the device of a
|
||||
class="mx_UntrustedDeviceDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
@@ -91,6 +92,7 @@ exports[`<UntrustedDeviceDialog /> should display the dialog for the device of t
|
||||
class="mx_UntrustedDeviceDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
|
||||
@@ -12,6 +12,7 @@ exports[`CreateSecretStorageDialog handles the happy path 1`] = `
|
||||
class="mx_CreateSecretStorageDialog"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
@@ -140,6 +141,7 @@ exports[`CreateSecretStorageDialog handles the happy path 2`] = `
|
||||
class="mx_CreateSecretStorageDialog"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
@@ -231,6 +233,7 @@ exports[`CreateSecretStorageDialog when there is an error fetching the backup ve
|
||||
class="mx_CreateSecretStorageDialog"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
|
||||
@@ -12,6 +12,7 @@ exports[`ExportE2eKeysDialog renders 1`] = `
|
||||
class="mx_exportE2eKeysDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
|
||||
@@ -12,6 +12,7 @@ exports[`ImportE2eKeysDialog renders 1`] = `
|
||||
class="mx_importE2eKeysDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
|
||||
@@ -12,6 +12,7 @@ exports[`<RestoreKeyBackupDialog /> should display an error when recovery key is
|
||||
class="mx_RestoreKeyBackupDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
@@ -112,6 +113,7 @@ exports[`<RestoreKeyBackupDialog /> should not raise an error when recovery is v
|
||||
class="mx_RestoreKeyBackupDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
@@ -211,6 +213,7 @@ exports[`<RestoreKeyBackupDialog /> should render 1`] = `
|
||||
class="mx_RestoreKeyBackupDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
@@ -283,6 +286,7 @@ exports[`<RestoreKeyBackupDialog /> should render 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
aria-describedby="«r2»"
|
||||
aria-label="Close dialog"
|
||||
class="mx_AccessibleButton mx_Dialog_cancelButton"
|
||||
role="button"
|
||||
@@ -309,6 +313,7 @@ exports[`<RestoreKeyBackupDialog /> should restore key backup when Recovery key
|
||||
class="mx_RestoreKeyBackupDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
@@ -374,6 +379,7 @@ exports[`<RestoreKeyBackupDialog /> should restore key backup when passphrase is
|
||||
class="mx_RestoreKeyBackupDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
@@ -439,6 +445,7 @@ exports[`<RestoreKeyBackupDialog /> should restore key backup when the key is ca
|
||||
class="mx_RestoreKeyBackupDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
@@ -478,6 +485,7 @@ exports[`<RestoreKeyBackupDialog /> should restore key backup when the key is ca
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
aria-describedby="«rk»"
|
||||
aria-label="Close dialog"
|
||||
class="mx_AccessibleButton mx_Dialog_cancelButton"
|
||||
role="button"
|
||||
@@ -504,6 +512,7 @@ exports[`<RestoreKeyBackupDialog /> should restore key backup when the key is in
|
||||
class="mx_RestoreKeyBackupDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
@@ -543,6 +552,7 @@ exports[`<RestoreKeyBackupDialog /> should restore key backup when the key is in
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
aria-describedby="«rq»"
|
||||
aria-label="Close dialog"
|
||||
class="mx_AccessibleButton mx_Dialog_cancelButton"
|
||||
role="button"
|
||||
|
||||
@@ -340,8 +340,8 @@ exports[`AppTile for a pinned widget should render permission request 1`] = `
|
||||
<span>
|
||||
Using this widget may share data
|
||||
<div
|
||||
aria-describedby="«r2j»"
|
||||
aria-labelledby="«r2i»"
|
||||
aria-describedby="«r2n»"
|
||||
aria-labelledby="«r2m»"
|
||||
class="mx_TextWithTooltip_target mx_TextWithTooltip_target--helpIcon"
|
||||
>
|
||||
<svg
|
||||
|
||||
@@ -21,6 +21,7 @@ exports[`<ImageView /> renders correctly 1`] = `
|
||||
class="mx_ImageView_toolbar"
|
||||
>
|
||||
<div
|
||||
aria-describedby="«r2»"
|
||||
aria-label="Zoom out"
|
||||
class="mx_AccessibleButton mx_ImageView_button mx_ImageView_button_zoomOut"
|
||||
role="button"
|
||||
|
||||
@@ -32,6 +32,7 @@ exports[`<LocationViewDialog /> renders map correctly 1`] = `
|
||||
class="mx_ZoomButtons"
|
||||
>
|
||||
<div
|
||||
aria-describedby="«r6»"
|
||||
aria-label="Zoom in"
|
||||
class="mx_AccessibleButton mx_ZoomButtons_button"
|
||||
data-testid="map-zoom-in-button"
|
||||
|
||||
@@ -151,7 +151,7 @@ describe("CallEvent", () => {
|
||||
}),
|
||||
);
|
||||
defaultDispatcher.unregister(dispatcherRef);
|
||||
await act(() => call.start());
|
||||
act(() => call.setConnectionState(ConnectionState.Connected));
|
||||
|
||||
// Test that the leave button works
|
||||
fireEvent.click(screen.getByRole("button", { name: "Leave" }));
|
||||
|
||||
@@ -215,6 +215,7 @@ exports[`<RoomSummaryCard /> has button to edit topic 1`] = `
|
||||
aria-hidden="true"
|
||||
class="_input_19o42_24"
|
||||
id="«rv»"
|
||||
role="switch"
|
||||
type="checkbox"
|
||||
/>
|
||||
<div
|
||||
@@ -939,6 +940,7 @@ exports[`<RoomSummaryCard /> renders the room summary 1`] = `
|
||||
aria-hidden="true"
|
||||
class="_input_19o42_24"
|
||||
id="«r5»"
|
||||
role="switch"
|
||||
type="checkbox"
|
||||
/>
|
||||
<div
|
||||
@@ -1701,6 +1703,7 @@ exports[`<RoomSummaryCard /> renders the room topic in the summary 1`] = `
|
||||
aria-hidden="true"
|
||||
class="_input_19o42_24"
|
||||
id="«ri»"
|
||||
role="switch"
|
||||
type="checkbox"
|
||||
/>
|
||||
<div
|
||||
|
||||
@@ -52,7 +52,6 @@ import * as ShieldUtils from "../../../../../../src/utils/ShieldUtils";
|
||||
import { Container, WidgetLayoutStore } from "../../../../../../src/stores/widgets/WidgetLayoutStore";
|
||||
import MatrixClientContext from "../../../../../../src/contexts/MatrixClientContext";
|
||||
import { _t } from "../../../../../../src/languageHandler";
|
||||
import * as UseCall from "../../../../../../src/hooks/useCall";
|
||||
import { SdkContextClass } from "../../../../../../src/contexts/SDKContext";
|
||||
import WidgetStore, { type IApp } from "../../../../../../src/stores/WidgetStore";
|
||||
import { UIFeature } from "../../../../../../src/settings/UIFeature";
|
||||
@@ -96,6 +95,10 @@ describe("RoomHeader", () => {
|
||||
|
||||
setCardSpy = jest.spyOn(RightPanelStore.instance, "setCard");
|
||||
jest.spyOn(ShieldUtils, "shieldStatusForRoom").mockResolvedValue(ShieldUtils.E2EStatus.Normal);
|
||||
|
||||
// Mock CallStore.instance.getCall to return null by default
|
||||
// Individual tests can override this when they need a specific Call object
|
||||
jest.spyOn(CallStore.instance, "getCall").mockReturnValue(null);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -555,7 +558,8 @@ describe("RoomHeader", () => {
|
||||
|
||||
it("join button is shown if there is an ongoing call", async () => {
|
||||
mockRoomMembers(room, 3);
|
||||
jest.spyOn(UseCall, "useParticipantCount").mockReturnValue(3);
|
||||
// Mock CallStore to return a call with 3 participants
|
||||
jest.spyOn(CallStore.instance, "getCall").mockReturnValue(createMockCall(ROOM_ID, 3));
|
||||
render(<RoomHeader room={room} />, getWrapper());
|
||||
const joinButton = getByLabelText(document.body, "Join");
|
||||
expect(joinButton).not.toHaveAttribute("aria-disabled", "true");
|
||||
@@ -563,7 +567,8 @@ describe("RoomHeader", () => {
|
||||
|
||||
it("join button is disabled if there is an other ongoing call", async () => {
|
||||
mockRoomMembers(room, 3);
|
||||
jest.spyOn(UseCall, "useParticipantCount").mockReturnValue(3);
|
||||
// Mock CallStore to return a call with 3 participants
|
||||
jest.spyOn(CallStore.instance, "getCall").mockReturnValue(createMockCall(ROOM_ID, 3));
|
||||
jest.spyOn(CallStore.prototype, "connectedCalls", "get").mockReturnValue(
|
||||
new Set([{ roomId: "some_other_room" } as Call]),
|
||||
);
|
||||
@@ -583,7 +588,8 @@ describe("RoomHeader", () => {
|
||||
|
||||
it("close lobby button is shown if there is an ongoing call but we are viewing the lobby", async () => {
|
||||
mockRoomMembers(room, 3);
|
||||
jest.spyOn(UseCall, "useParticipantCount").mockReturnValue(3);
|
||||
// Mock CallStore to return a call with 3 participants
|
||||
jest.spyOn(CallStore.instance, "getCall").mockReturnValue(createMockCall(ROOM_ID, 3));
|
||||
jest.spyOn(SdkContextClass.instance.roomViewStore, "isViewingCall").mockReturnValue(true);
|
||||
|
||||
render(<RoomHeader room={room} />, getWrapper());
|
||||
@@ -789,6 +795,34 @@ describe("RoomHeader", () => {
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates a mock Call object with stable participants to prevent React dependency errors
|
||||
*/
|
||||
function createMockCall(roomId: string = "!1:example.org", participantCount: number = 0): Call {
|
||||
const participants = new Map();
|
||||
|
||||
// Create mock participants with devices
|
||||
for (let i = 0; i < participantCount; i++) {
|
||||
const mockMember = {
|
||||
userId: `@user-${i}:example.org`,
|
||||
name: `Member ${i}`,
|
||||
} as RoomMember;
|
||||
|
||||
const deviceSet = new Set([`device-${i}`]);
|
||||
participants.set(mockMember, deviceSet);
|
||||
}
|
||||
|
||||
return {
|
||||
roomId,
|
||||
participants,
|
||||
widget: { id: "test-widget" },
|
||||
connectionState: "disconnected",
|
||||
on: jest.fn(),
|
||||
off: jest.fn(),
|
||||
emit: jest.fn(),
|
||||
} as unknown as Call;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param count the number of users to create
|
||||
|
||||
@@ -37,6 +37,7 @@ describe("<RoomListItemView />", () => {
|
||||
onFocus: jest.fn(),
|
||||
roomIndex: 0,
|
||||
roomCount: 1,
|
||||
listIsScrolling: false,
|
||||
};
|
||||
|
||||
return render(<RoomListItemView {...defaultProps} {...props} />, withClientContextRenderOptions(matrixClient));
|
||||
@@ -128,6 +129,7 @@ describe("<RoomListItemView />", () => {
|
||||
onFocus={jest.fn()}
|
||||
roomIndex={0}
|
||||
roomCount={1}
|
||||
listIsScrolling={false}
|
||||
/>,
|
||||
);
|
||||
|
||||
@@ -191,4 +193,26 @@ describe("<RoomListItemView />", () => {
|
||||
await user.keyboard("{Escape}");
|
||||
expect(screen.queryByRole("menu")).toBeNull();
|
||||
});
|
||||
|
||||
test("should not render context menu when list is scrolling", async () => {
|
||||
const user = userEvent.setup();
|
||||
|
||||
mocked(useRoomListItemViewModel).mockReturnValue({
|
||||
...defaultValue,
|
||||
showContextMenu: true,
|
||||
});
|
||||
|
||||
renderRoomListItem({
|
||||
listIsScrolling: true,
|
||||
});
|
||||
|
||||
const button = screen.getByRole("option", { name: `Open room ${room.name}` });
|
||||
await user.pointer([{ target: button }, { keys: "[MouseRight]", target: button }]);
|
||||
|
||||
// Context menu should not appear when scrolling
|
||||
expect(screen.queryByRole("menu")).toBeNull();
|
||||
|
||||
// But the room item itself should still be rendered
|
||||
expect(button).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -46,6 +46,7 @@ import { UIComponent } from "../../../../../src/settings/UIFeature";
|
||||
import { MessagePreviewStore } from "../../../../../src/stores/room-list/MessagePreviewStore";
|
||||
import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg";
|
||||
import SettingsStore from "../../../../../src/settings/SettingsStore";
|
||||
import { ConnectionState } from "../../../../../src/models/Call";
|
||||
|
||||
jest.mock("../../../../../src/customisations/helpers/UIComponents", () => ({
|
||||
shouldShowComponent: jest.fn(),
|
||||
@@ -215,7 +216,7 @@ describe("RoomTile", () => {
|
||||
it("tracks connection state", async () => {
|
||||
renderRoomTile();
|
||||
screen.getByText("Video");
|
||||
await act(() => call.start());
|
||||
act(() => call.setConnectionState(ConnectionState.Connected));
|
||||
screen.getByText("Joined");
|
||||
await act(() => call.disconnect());
|
||||
screen.getByText("Video");
|
||||
|
||||
@@ -185,7 +185,7 @@ exports[`<PinnedEventTile /> should render the menu with all the options 1`] = `
|
||||
aria-label="Open menu"
|
||||
aria-labelledby="radix-«r10»"
|
||||
aria-orientation="vertical"
|
||||
class="_menu_19sse_8"
|
||||
class="_menu_1glhz_8"
|
||||
data-align="start"
|
||||
data-orientation="vertical"
|
||||
data-radix-menu-content=""
|
||||
@@ -376,7 +376,7 @@ exports[`<PinnedEventTile /> should render the menu without unpin and delete 1`]
|
||||
aria-label="Open menu"
|
||||
aria-labelledby="radix-«rl»"
|
||||
aria-orientation="vertical"
|
||||
class="_menu_19sse_8"
|
||||
class="_menu_1glhz_8"
|
||||
data-align="start"
|
||||
data-orientation="vertical"
|
||||
data-radix-menu-content=""
|
||||
|
||||
@@ -70,12 +70,12 @@ describe("<LayoutSwitcher />", () => {
|
||||
await SettingsStore.setValue("useCompactLayout", null, SettingLevel.DEVICE, true);
|
||||
await renderLayoutSwitcher();
|
||||
|
||||
expect(screen.getByRole("checkbox", { name: "Show compact text and messages" })).toBeChecked();
|
||||
expect(screen.getByRole("switch", { name: "Show compact text and messages" })).toBeChecked();
|
||||
});
|
||||
|
||||
it("should change the setting when toggled", async () => {
|
||||
await renderLayoutSwitcher();
|
||||
act(() => screen.getByRole("checkbox", { name: "Show compact text and messages" }).click());
|
||||
act(() => screen.getByRole("switch", { name: "Show compact text and messages" }).click());
|
||||
|
||||
await waitFor(() => expect(SettingsStore.getValue("useCompactLayout")).toBe(true));
|
||||
});
|
||||
@@ -83,7 +83,7 @@ describe("<LayoutSwitcher />", () => {
|
||||
it("should be disabled when the modern layout is not enabled", async () => {
|
||||
await SettingsStore.setValue("layout", null, SettingLevel.DEVICE, Layout.Bubble);
|
||||
await renderLayoutSwitcher();
|
||||
expect(screen.getByRole("checkbox", { name: "Show compact text and messages" })).toBeDisabled();
|
||||
expect(screen.getByRole("switch", { name: "Show compact text and messages" })).toBeDisabled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -56,24 +56,24 @@ describe("<ThemeChoicePanel />", () => {
|
||||
describe("system theme", () => {
|
||||
it("should disable Match system theme", async () => {
|
||||
render(<ThemeChoicePanel />);
|
||||
expect(screen.getByRole("checkbox", { name: "Match system theme" })).not.toBeChecked();
|
||||
expect(screen.getByRole("switch", { name: "Match system theme" })).not.toBeChecked();
|
||||
});
|
||||
|
||||
it("should enable Match system theme", async () => {
|
||||
await enableSystemTheme(true);
|
||||
|
||||
render(<ThemeChoicePanel />);
|
||||
expect(screen.getByRole("checkbox", { name: "Match system theme" })).toBeChecked();
|
||||
expect(screen.getByRole("switch", { name: "Match system theme" })).toBeChecked();
|
||||
});
|
||||
|
||||
it("should change the system theme when clicked", async () => {
|
||||
jest.spyOn(SettingsStore, "setValue");
|
||||
|
||||
render(<ThemeChoicePanel />);
|
||||
act(() => screen.getByRole("checkbox", { name: "Match system theme" }).click());
|
||||
act(() => screen.getByRole("switch", { name: "Match system theme" }).click());
|
||||
|
||||
// The system theme should be enabled
|
||||
expect(screen.getByRole("checkbox", { name: "Match system theme" })).toBeChecked();
|
||||
expect(screen.getByRole("switch", { name: "Match system theme" })).toBeChecked();
|
||||
expect(SettingsStore.setValue).toHaveBeenCalledWith("use_system_theme", null, "device", true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -418,6 +418,7 @@ exports[`<LayoutSwitcher /> should render 1`] = `
|
||||
class="_input_19o42_24"
|
||||
id="radix-«rr»"
|
||||
name="compactLayout"
|
||||
role="switch"
|
||||
title=""
|
||||
type="checkbox"
|
||||
/>
|
||||
|
||||
@@ -34,6 +34,7 @@ exports[`<ThemeChoicePanel /> custom theme should display custom theme 1`] = `
|
||||
class="_input_19o42_24"
|
||||
id="radix-«r28»"
|
||||
name="systemTheme"
|
||||
role="switch"
|
||||
title=""
|
||||
type="checkbox"
|
||||
/>
|
||||
@@ -312,6 +313,7 @@ exports[`<ThemeChoicePanel /> custom theme should render the custom theme sectio
|
||||
class="_input_19o42_24"
|
||||
id="radix-«r10»"
|
||||
name="systemTheme"
|
||||
role="switch"
|
||||
title=""
|
||||
type="checkbox"
|
||||
/>
|
||||
@@ -590,6 +592,7 @@ exports[`<ThemeChoicePanel /> renders the theme choice UI 1`] = `
|
||||
class="_input_19o42_24"
|
||||
id="radix-«r0»"
|
||||
name="systemTheme"
|
||||
role="switch"
|
||||
title=""
|
||||
type="checkbox"
|
||||
/>
|
||||
|
||||
@@ -74,7 +74,7 @@ describe("<AdvancedPanel />", () => {
|
||||
await renderAdvancedPanel();
|
||||
|
||||
expect(screen.getByTestId("otherSettings")).toMatchSnapshot();
|
||||
const checkbox = screen.getByRole("checkbox", {
|
||||
const checkbox = screen.getByRole("switch", {
|
||||
name: "In encrypted rooms, only send messages to verified users",
|
||||
});
|
||||
expect(checkbox).toBeChecked();
|
||||
|
||||
@@ -224,6 +224,7 @@ exports[`<AdvancedPanel /> <OtherSettings /> should display the blacklist of unv
|
||||
class="_input_19o42_24"
|
||||
id="radix-«r6»"
|
||||
name="neverSendEncrypted"
|
||||
role="switch"
|
||||
title=""
|
||||
type="checkbox"
|
||||
/>
|
||||
|
||||
@@ -117,6 +117,7 @@ exports[`<SecurityRoomSettingsTab /> join rule handles error when updating join
|
||||
class="mx_ErrorDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
@@ -159,6 +160,7 @@ exports[`<SecurityRoomSettingsTab /> join rule warns when trying to make an encr
|
||||
class="mx_QuestionDialog mx_Dialog_fixedWidth"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
|
||||
@@ -561,6 +561,7 @@ exports[`AppearanceUserSettingsTab should render 1`] = `
|
||||
class="_input_19o42_24"
|
||||
id="radix-«ru»"
|
||||
name="compactLayout"
|
||||
role="switch"
|
||||
title=""
|
||||
type="checkbox"
|
||||
/>
|
||||
|
||||
@@ -13,6 +13,7 @@ exports[`<AddExistingToSpaceDialog /> looks as expected 1`] = `
|
||||
class="mx_AddExistingToSpaceDialog"
|
||||
data-focus-lock-disabled="false"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_Dialog_header"
|
||||
|
||||
@@ -4,7 +4,7 @@ exports[`ThreadsActivityCentre renders notifications matching the snapshot 1`] =
|
||||
<div
|
||||
aria-labelledby="radix-«r2f»"
|
||||
aria-orientation="vertical"
|
||||
class="_menu_19sse_8"
|
||||
class="_menu_1glhz_8"
|
||||
data-align="start"
|
||||
data-orientation="vertical"
|
||||
data-radix-menu-content=""
|
||||
@@ -17,7 +17,7 @@ exports[`ThreadsActivityCentre renders notifications matching the snapshot 1`] =
|
||||
tabindex="-1"
|
||||
>
|
||||
<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_1glhz_74"
|
||||
id="«r2n»"
|
||||
>
|
||||
Threads activity
|
||||
@@ -230,7 +230,7 @@ exports[`ThreadsActivityCentre should close the release announcement when the TA
|
||||
<div
|
||||
aria-labelledby="radix-«ro»"
|
||||
aria-orientation="vertical"
|
||||
class="_menu_19sse_8"
|
||||
class="_menu_1glhz_8"
|
||||
data-align="start"
|
||||
data-orientation="vertical"
|
||||
data-radix-menu-content=""
|
||||
@@ -243,7 +243,7 @@ exports[`ThreadsActivityCentre should close the release announcement when the TA
|
||||
tabindex="-1"
|
||||
>
|
||||
<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_1glhz_74"
|
||||
id="«r10»"
|
||||
>
|
||||
Threads activity
|
||||
@@ -273,7 +273,7 @@ exports[`ThreadsActivityCentre should match snapshot when empty 1`] = `
|
||||
<div
|
||||
aria-labelledby="radix-«r33»"
|
||||
aria-orientation="vertical"
|
||||
class="_menu_19sse_8"
|
||||
class="_menu_1glhz_8"
|
||||
data-align="start"
|
||||
data-orientation="vertical"
|
||||
data-radix-menu-content=""
|
||||
@@ -286,7 +286,7 @@ exports[`ThreadsActivityCentre should match snapshot when empty 1`] = `
|
||||
tabindex="-1"
|
||||
>
|
||||
<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_1glhz_74"
|
||||
id="«r3b»"
|
||||
>
|
||||
Threads activity
|
||||
@@ -307,7 +307,7 @@ exports[`ThreadsActivityCentre should order the room with the same notification
|
||||
<div
|
||||
aria-labelledby="radix-«r3c»"
|
||||
aria-orientation="vertical"
|
||||
class="_menu_19sse_8"
|
||||
class="_menu_1glhz_8"
|
||||
data-align="start"
|
||||
data-orientation="vertical"
|
||||
data-radix-menu-content=""
|
||||
@@ -320,7 +320,7 @@ exports[`ThreadsActivityCentre should order the room with the same notification
|
||||
tabindex="-1"
|
||||
>
|
||||
<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_1glhz_74"
|
||||
id="«r3k»"
|
||||
>
|
||||
Threads activity
|
||||
|
||||
@@ -41,7 +41,6 @@ import {
|
||||
ElementCall,
|
||||
} from "../../../src/models/Call";
|
||||
import { stubClient, mkEvent, mkRoomMember, setupAsyncStoreWithClient, mockPlatformPeg } from "../../test-utils";
|
||||
import MediaDeviceHandler, { MediaDeviceKindEnum } from "../../../src/MediaDeviceHandler";
|
||||
import { MatrixClientPeg } from "../../../src/MatrixClientPeg";
|
||||
import WidgetStore from "../../../src/stores/WidgetStore";
|
||||
import { WidgetMessagingStore } from "../../../src/stores/widgets/WidgetMessagingStore";
|
||||
@@ -55,18 +54,6 @@ import RoomListStore from "../../../src/stores/room-list/RoomListStore.ts";
|
||||
import { DefaultTagID } from "../../../src/stores/room-list/models.ts";
|
||||
import DMRoomMap from "../../../src/utils/DMRoomMap.ts";
|
||||
|
||||
jest.spyOn(MediaDeviceHandler, "getDevices").mockResolvedValue({
|
||||
[MediaDeviceKindEnum.AudioInput]: [
|
||||
{ deviceId: "1", groupId: "1", kind: "audioinput", label: "Headphones", toJSON: () => {} },
|
||||
],
|
||||
[MediaDeviceKindEnum.VideoInput]: [
|
||||
{ deviceId: "2", groupId: "2", kind: "videoinput", label: "Built-in webcam", toJSON: () => {} },
|
||||
],
|
||||
[MediaDeviceKindEnum.AudioOutput]: [],
|
||||
});
|
||||
jest.spyOn(MediaDeviceHandler, "getAudioInput").mockReturnValue("1");
|
||||
jest.spyOn(MediaDeviceHandler, "getVideoInput").mockReturnValue("2");
|
||||
|
||||
const enabledSettings = new Set(["feature_group_calls", "feature_video_rooms", "feature_element_call_video_rooms"]);
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation(
|
||||
(settingName): any => enabledSettings.has(settingName) || undefined,
|
||||
@@ -140,14 +127,7 @@ const cleanUpClientRoomAndStores = (client: MatrixClient, room: Room) => {
|
||||
client.reEmitter.stopReEmitting(room, [RoomStateEvent.Events]);
|
||||
};
|
||||
|
||||
const setUpWidget = (
|
||||
call: Call,
|
||||
): {
|
||||
widget: Widget;
|
||||
messaging: Mocked<ClientWidgetApi>;
|
||||
audioMutedSpy: jest.SpyInstance<boolean, []>;
|
||||
videoMutedSpy: jest.SpyInstance<boolean, []>;
|
||||
} => {
|
||||
const setUpWidget = (call: Call): { widget: Widget; messaging: Mocked<ClientWidgetApi> } => {
|
||||
call.widget.data = { ...call.widget, skipLobby: true };
|
||||
const widget = new Widget(call.widget);
|
||||
|
||||
@@ -165,23 +145,45 @@ const setUpWidget = (
|
||||
} as unknown as Mocked<ClientWidgetApi>;
|
||||
WidgetMessagingStore.instance.storeMessaging(widget, call.roomId, messaging);
|
||||
|
||||
const audioMutedSpy = jest.spyOn(MediaDeviceHandler, "startWithAudioMuted", "get");
|
||||
const videoMutedSpy = jest.spyOn(MediaDeviceHandler, "startWithVideoMuted", "get");
|
||||
|
||||
return { widget, messaging, audioMutedSpy, videoMutedSpy };
|
||||
return { widget, messaging };
|
||||
};
|
||||
|
||||
const cleanUpCallAndWidget = (
|
||||
call: Call,
|
||||
widget: Widget,
|
||||
audioMutedSpy: jest.SpyInstance<boolean, []>,
|
||||
videoMutedSpy: jest.SpyInstance<boolean, []>,
|
||||
) => {
|
||||
async function connect(call: Call, messaging: Mocked<ClientWidgetApi>, startWidget = true): Promise<void> {
|
||||
async function sessionConnect() {
|
||||
await new Promise<void>((r) => {
|
||||
setTimeout(() => r(), 400);
|
||||
});
|
||||
messaging.emit(`action:${ElementWidgetActions.JoinCall}`, new CustomEvent("widgetapirequest", {}));
|
||||
}
|
||||
async function runTimers() {
|
||||
jest.advanceTimersByTime(500);
|
||||
jest.advanceTimersByTime(500);
|
||||
}
|
||||
sessionConnect();
|
||||
await Promise.all([...(startWidget ? [call.start()] : []), runTimers()]);
|
||||
}
|
||||
|
||||
async function disconnect(call: Call, messaging: Mocked<ClientWidgetApi>): Promise<void> {
|
||||
async function sessionDisconnect() {
|
||||
await new Promise<void>((r) => {
|
||||
setTimeout(() => r(), 400);
|
||||
});
|
||||
messaging.emit(`action:${ElementWidgetActions.HangupCall}`, new CustomEvent("widgetapirequest", {}));
|
||||
}
|
||||
async function runTimers() {
|
||||
jest.advanceTimersByTime(500);
|
||||
jest.advanceTimersByTime(500);
|
||||
}
|
||||
sessionDisconnect();
|
||||
const promise = call.disconnect();
|
||||
runTimers();
|
||||
await promise;
|
||||
}
|
||||
|
||||
const cleanUpCallAndWidget = (call: Call, widget: Widget) => {
|
||||
call.destroy();
|
||||
jest.clearAllMocks();
|
||||
WidgetMessagingStore.instance.stopMessaging(widget, call.roomId);
|
||||
audioMutedSpy.mockRestore();
|
||||
videoMutedSpy.mockRestore();
|
||||
};
|
||||
|
||||
describe("JitsiCall", () => {
|
||||
@@ -225,8 +227,6 @@ describe("JitsiCall", () => {
|
||||
let call: JitsiCall;
|
||||
let widget: Widget;
|
||||
let messaging: Mocked<ClientWidgetApi>;
|
||||
let audioMutedSpy: jest.SpyInstance<boolean, []>;
|
||||
let videoMutedSpy: jest.SpyInstance<boolean, []>;
|
||||
|
||||
beforeEach(async () => {
|
||||
jest.useFakeTimers();
|
||||
@@ -237,7 +237,7 @@ describe("JitsiCall", () => {
|
||||
if (maybeCall === null) throw new Error("Failed to create call");
|
||||
call = maybeCall;
|
||||
|
||||
({ widget, messaging, audioMutedSpy, videoMutedSpy } = setUpWidget(call));
|
||||
({ widget, messaging } = setUpWidget(call));
|
||||
|
||||
mocked(messaging.transport).send.mockImplementation(async (action, data): Promise<any> => {
|
||||
if (action === ElementWidgetActions.JoinCall) {
|
||||
@@ -255,102 +255,37 @@ describe("JitsiCall", () => {
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => cleanUpCallAndWidget(call, widget, audioMutedSpy, videoMutedSpy));
|
||||
afterEach(() => cleanUpCallAndWidget(call, widget));
|
||||
|
||||
it("connects muted", async () => {
|
||||
it("connects", async () => {
|
||||
expect(call.connectionState).toBe(ConnectionState.Disconnected);
|
||||
audioMutedSpy.mockReturnValue(true);
|
||||
videoMutedSpy.mockReturnValue(true);
|
||||
|
||||
await call.start();
|
||||
await connect(call, messaging);
|
||||
expect(call.connectionState).toBe(ConnectionState.Connected);
|
||||
expect(messaging.transport.send).toHaveBeenCalledWith(ElementWidgetActions.JoinCall, {
|
||||
audioInput: null,
|
||||
videoInput: null,
|
||||
});
|
||||
});
|
||||
|
||||
it("connects unmuted", async () => {
|
||||
expect(call.connectionState).toBe(ConnectionState.Disconnected);
|
||||
audioMutedSpy.mockReturnValue(false);
|
||||
videoMutedSpy.mockReturnValue(false);
|
||||
|
||||
await call.start();
|
||||
expect(call.connectionState).toBe(ConnectionState.Connected);
|
||||
expect(messaging.transport.send).toHaveBeenCalledWith(ElementWidgetActions.JoinCall, {
|
||||
audioInput: "Headphones",
|
||||
videoInput: "Built-in webcam",
|
||||
});
|
||||
});
|
||||
|
||||
it("waits for messaging when connecting", async () => {
|
||||
it("waits for messaging when starting", async () => {
|
||||
// Temporarily remove the messaging to simulate connecting while the
|
||||
// widget is still initializing
|
||||
WidgetMessagingStore.instance.stopMessaging(widget, room.roomId);
|
||||
expect(call.connectionState).toBe(ConnectionState.Disconnected);
|
||||
|
||||
const connect = call.start();
|
||||
const startup = call.start();
|
||||
WidgetMessagingStore.instance.storeMessaging(widget, room.roomId, messaging);
|
||||
await connect;
|
||||
await startup;
|
||||
await connect(call, messaging, false);
|
||||
expect(call.connectionState).toBe(ConnectionState.Connected);
|
||||
});
|
||||
|
||||
it("doesn't stop messaging when connecting", async () => {
|
||||
// Temporarily remove the messaging to simulate connecting while the
|
||||
// widget is still initializing
|
||||
jest.useFakeTimers();
|
||||
const oldSendMock = messaging.transport.send;
|
||||
mocked(messaging.transport).send.mockImplementation(async (action: string): Promise<any> => {
|
||||
if (action === ElementWidgetActions.JoinCall) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
messaging.emit(
|
||||
`action:${ElementWidgetActions.JoinCall}`,
|
||||
new CustomEvent("widgetapirequest", { detail: {} }),
|
||||
);
|
||||
}
|
||||
});
|
||||
expect(call.connectionState).toBe(ConnectionState.Disconnected);
|
||||
|
||||
const connect = call.start();
|
||||
async function runTimers() {
|
||||
jest.advanceTimersByTime(500);
|
||||
jest.advanceTimersByTime(1000);
|
||||
}
|
||||
async function runStopMessaging() {
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
WidgetMessagingStore.instance.stopMessaging(widget, room.roomId);
|
||||
}
|
||||
runStopMessaging();
|
||||
runTimers();
|
||||
let connectError;
|
||||
try {
|
||||
await connect;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
connectError = e;
|
||||
}
|
||||
expect(connectError).toBeDefined();
|
||||
// const connect2 = await connect;
|
||||
// expect(connect2).toThrow();
|
||||
messaging.transport.send = oldSendMock;
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it("fails to connect if the widget returns an error", async () => {
|
||||
mocked(messaging.transport).send.mockRejectedValue(new Error("never!!1! >:("));
|
||||
await expect(call.start()).rejects.toBeDefined();
|
||||
});
|
||||
|
||||
it("fails to disconnect if the widget returns an error", async () => {
|
||||
await call.start();
|
||||
mocked(messaging.transport).send.mockRejectedValue(new Error("never!!1! >:("));
|
||||
await connect(call, messaging);
|
||||
mocked(messaging.transport).send.mockRejectedValue(new Error("never!"));
|
||||
await expect(call.disconnect()).rejects.toBeDefined();
|
||||
});
|
||||
|
||||
it("handles remote disconnection", async () => {
|
||||
expect(call.connectionState).toBe(ConnectionState.Disconnected);
|
||||
|
||||
await call.start();
|
||||
await connect(call, messaging);
|
||||
expect(call.connectionState).toBe(ConnectionState.Connected);
|
||||
|
||||
const callback = jest.fn();
|
||||
@@ -358,7 +293,6 @@ describe("JitsiCall", () => {
|
||||
call.on(CallEvent.ConnectionState, callback);
|
||||
|
||||
messaging.emit(`action:${ElementWidgetActions.HangupCall}`, new CustomEvent("widgetapirequest", {}));
|
||||
messaging.emit(`action:${ElementWidgetActions.Close}`, new CustomEvent("widgetapirequest", {}));
|
||||
await waitFor(() => {
|
||||
expect(callback).toHaveBeenNthCalledWith(1, ConnectionState.Disconnected, ConnectionState.Connected);
|
||||
});
|
||||
@@ -368,14 +302,14 @@ describe("JitsiCall", () => {
|
||||
|
||||
it("disconnects", async () => {
|
||||
expect(call.connectionState).toBe(ConnectionState.Disconnected);
|
||||
await call.start();
|
||||
await connect(call, messaging);
|
||||
expect(call.connectionState).toBe(ConnectionState.Connected);
|
||||
await call.disconnect();
|
||||
expect(call.connectionState).toBe(ConnectionState.Disconnected);
|
||||
});
|
||||
|
||||
it("disconnects when we leave the room", async () => {
|
||||
await call.start();
|
||||
await connect(call, messaging);
|
||||
expect(call.connectionState).toBe(ConnectionState.Connected);
|
||||
room.emit(RoomEvent.MyMembership, room, KnownMembership.Leave);
|
||||
expect(call.connectionState).toBe(ConnectionState.Disconnected);
|
||||
@@ -383,14 +317,14 @@ describe("JitsiCall", () => {
|
||||
|
||||
it("reconnects after disconnect in video rooms", async () => {
|
||||
expect(call.connectionState).toBe(ConnectionState.Disconnected);
|
||||
await call.start();
|
||||
await connect(call, messaging);
|
||||
expect(call.connectionState).toBe(ConnectionState.Connected);
|
||||
await call.disconnect();
|
||||
expect(call.connectionState).toBe(ConnectionState.Disconnected);
|
||||
});
|
||||
|
||||
it("remains connected if we stay in the room", async () => {
|
||||
await call.start();
|
||||
await connect(call, messaging);
|
||||
expect(call.connectionState).toBe(ConnectionState.Connected);
|
||||
room.emit(RoomEvent.MyMembership, room, KnownMembership.Join);
|
||||
expect(call.connectionState).toBe(ConnectionState.Connected);
|
||||
@@ -416,7 +350,7 @@ describe("JitsiCall", () => {
|
||||
|
||||
// Now, stub out client.sendStateEvent so we can test our local echo
|
||||
client.sendStateEvent.mockReset();
|
||||
await call.start();
|
||||
await connect(call, messaging);
|
||||
expect(call.participants).toEqual(
|
||||
new Map([
|
||||
[alice, new Set(["alices_device"])],
|
||||
@@ -429,8 +363,8 @@ describe("JitsiCall", () => {
|
||||
});
|
||||
|
||||
it("updates room state when connecting and disconnecting", async () => {
|
||||
await connect(call, messaging);
|
||||
const now1 = Date.now();
|
||||
await call.start();
|
||||
await waitFor(
|
||||
() =>
|
||||
expect(
|
||||
@@ -457,7 +391,7 @@ describe("JitsiCall", () => {
|
||||
});
|
||||
|
||||
it("repeatedly updates room state while connected", async () => {
|
||||
await call.start();
|
||||
await connect(call, messaging);
|
||||
await waitFor(
|
||||
() =>
|
||||
expect(client.sendStateEvent).toHaveBeenLastCalledWith(
|
||||
@@ -487,7 +421,7 @@ describe("JitsiCall", () => {
|
||||
const onConnectionState = jest.fn();
|
||||
call.on(CallEvent.ConnectionState, onConnectionState);
|
||||
|
||||
await call.start();
|
||||
await connect(call, messaging);
|
||||
await call.disconnect();
|
||||
expect(onConnectionState.mock.calls).toEqual([
|
||||
[ConnectionState.Connected, ConnectionState.Disconnected],
|
||||
@@ -502,7 +436,7 @@ describe("JitsiCall", () => {
|
||||
const onParticipants = jest.fn();
|
||||
call.on(CallEvent.Participants, onParticipants);
|
||||
|
||||
await call.start();
|
||||
await connect(call, messaging);
|
||||
await call.disconnect();
|
||||
expect(onParticipants.mock.calls).toEqual([
|
||||
[new Map([[alice, new Set(["alices_device"])]]), new Map()],
|
||||
@@ -515,7 +449,7 @@ describe("JitsiCall", () => {
|
||||
});
|
||||
|
||||
it("switches to spotlight layout when the widget becomes a PiP", async () => {
|
||||
await call.start();
|
||||
await connect(call, messaging);
|
||||
ActiveWidgetStore.instance.emit(ActiveWidgetStoreEvent.Undock);
|
||||
expect(messaging.transport.send).toHaveBeenCalledWith(ElementWidgetActions.SpotlightLayout, {});
|
||||
ActiveWidgetStore.instance.emit(ActiveWidgetStoreEvent.Dock);
|
||||
@@ -559,7 +493,7 @@ describe("JitsiCall", () => {
|
||||
});
|
||||
|
||||
it("doesn't clean up valid devices", async () => {
|
||||
await call.start();
|
||||
await connect(call, messaging);
|
||||
await client.sendStateEvent(
|
||||
room.roomId,
|
||||
JitsiCall.MEMBER_EVENT_TYPE,
|
||||
@@ -624,47 +558,6 @@ describe("ElementCall", () => {
|
||||
jest.spyOn(room, "getJoinedMembers").mockReturnValue(memberIds.map((id) => ({ userId: id }) as RoomMember));
|
||||
}
|
||||
|
||||
const callConnectProcedure = async (call: ElementCall, startWidget = true): Promise<void> => {
|
||||
async function sessionConnect() {
|
||||
await new Promise<void>((r) => {
|
||||
setTimeout(() => r(), 400);
|
||||
});
|
||||
client.matrixRTC.emit(MatrixRTCSessionManagerEvents.SessionStarted, call.roomId, {
|
||||
sessionId: undefined,
|
||||
} as unknown as MatrixRTCSession);
|
||||
call.session?.emit(
|
||||
MatrixRTCSessionEvent.MembershipsChanged,
|
||||
[],
|
||||
[{ sender: client.getUserId() } as CallMembership],
|
||||
);
|
||||
}
|
||||
async function runTimers() {
|
||||
jest.advanceTimersByTime(500);
|
||||
jest.advanceTimersByTime(500);
|
||||
}
|
||||
sessionConnect();
|
||||
await Promise.all([...(startWidget ? [call.start()] : []), runTimers()]);
|
||||
};
|
||||
const callDisconnectionProcedure: (call: ElementCall) => Promise<void> = async (call) => {
|
||||
async function sessionDisconnect() {
|
||||
await new Promise<void>((r) => {
|
||||
setTimeout(() => r(), 400);
|
||||
});
|
||||
client.matrixRTC.emit(MatrixRTCSessionManagerEvents.SessionStarted, call.roomId, {
|
||||
sessionId: undefined,
|
||||
} as unknown as MatrixRTCSession);
|
||||
call.session?.emit(MatrixRTCSessionEvent.MembershipsChanged, [], []);
|
||||
}
|
||||
async function runTimers() {
|
||||
jest.advanceTimersByTime(500);
|
||||
jest.advanceTimersByTime(500);
|
||||
}
|
||||
sessionDisconnect();
|
||||
const promise = call.disconnect();
|
||||
runTimers();
|
||||
await promise;
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
({ client, room, alice } = setUpClientRoomAndStores());
|
||||
@@ -886,8 +779,6 @@ describe("ElementCall", () => {
|
||||
let call: ElementCall;
|
||||
let widget: Widget;
|
||||
let messaging: Mocked<ClientWidgetApi>;
|
||||
let audioMutedSpy: jest.SpyInstance<boolean, []>;
|
||||
let videoMutedSpy: jest.SpyInstance<boolean, []>;
|
||||
|
||||
beforeEach(async () => {
|
||||
jest.useFakeTimers();
|
||||
@@ -898,27 +789,28 @@ describe("ElementCall", () => {
|
||||
if (maybeCall === null) throw new Error("Failed to create call");
|
||||
call = maybeCall;
|
||||
|
||||
({ widget, messaging, audioMutedSpy, videoMutedSpy } = setUpWidget(call));
|
||||
({ widget, messaging } = setUpWidget(call));
|
||||
});
|
||||
|
||||
afterEach(() => cleanUpCallAndWidget(call, widget, audioMutedSpy, videoMutedSpy));
|
||||
afterEach(() => cleanUpCallAndWidget(call, widget));
|
||||
// TODO refactor initial device configuration to use the EW settings.
|
||||
// Add tests for passing EW device configuration to the widget.
|
||||
it("waits for messaging when connecting", async () => {
|
||||
it("waits for messaging when starting", async () => {
|
||||
// Temporarily remove the messaging to simulate connecting while the
|
||||
// widget is still initializing
|
||||
|
||||
WidgetMessagingStore.instance.stopMessaging(widget, room.roomId);
|
||||
expect(call.connectionState).toBe(ConnectionState.Disconnected);
|
||||
|
||||
const connect = callConnectProcedure(call);
|
||||
const startup = call.start();
|
||||
WidgetMessagingStore.instance.storeMessaging(widget, room.roomId, messaging);
|
||||
await connect;
|
||||
await startup;
|
||||
await connect(call, messaging, false);
|
||||
expect(call.connectionState).toBe(ConnectionState.Connected);
|
||||
});
|
||||
|
||||
it("fails to disconnect if the widget returns an error", async () => {
|
||||
await callConnectProcedure(call);
|
||||
await connect(call, messaging);
|
||||
mocked(messaging.transport).send.mockRejectedValue(new Error("never!!1! >:("));
|
||||
await expect(call.disconnect()).rejects.toBeDefined();
|
||||
});
|
||||
@@ -926,7 +818,7 @@ describe("ElementCall", () => {
|
||||
it("handles remote disconnection", async () => {
|
||||
expect(call.connectionState).toBe(ConnectionState.Disconnected);
|
||||
|
||||
await callConnectProcedure(call);
|
||||
await connect(call, messaging);
|
||||
expect(call.connectionState).toBe(ConnectionState.Connected);
|
||||
|
||||
messaging.emit(`action:${ElementWidgetActions.HangupCall}`, new CustomEvent("widgetapirequest", {}));
|
||||
@@ -936,35 +828,35 @@ describe("ElementCall", () => {
|
||||
|
||||
it("disconnects", async () => {
|
||||
expect(call.connectionState).toBe(ConnectionState.Disconnected);
|
||||
await callConnectProcedure(call);
|
||||
await connect(call, messaging);
|
||||
expect(call.connectionState).toBe(ConnectionState.Connected);
|
||||
await callDisconnectionProcedure(call);
|
||||
await disconnect(call, messaging);
|
||||
expect(call.connectionState).toBe(ConnectionState.Disconnected);
|
||||
});
|
||||
|
||||
it("disconnects when we leave the room", async () => {
|
||||
await callConnectProcedure(call);
|
||||
await connect(call, messaging);
|
||||
expect(call.connectionState).toBe(ConnectionState.Connected);
|
||||
room.emit(RoomEvent.MyMembership, room, KnownMembership.Leave);
|
||||
expect(call.connectionState).toBe(ConnectionState.Disconnected);
|
||||
});
|
||||
|
||||
it("remains connected if we stay in the room", async () => {
|
||||
await callConnectProcedure(call);
|
||||
await connect(call, messaging);
|
||||
expect(call.connectionState).toBe(ConnectionState.Connected);
|
||||
room.emit(RoomEvent.MyMembership, room, KnownMembership.Join);
|
||||
expect(call.connectionState).toBe(ConnectionState.Connected);
|
||||
});
|
||||
|
||||
it("disconnects if the widget dies", async () => {
|
||||
await callConnectProcedure(call);
|
||||
await connect(call, messaging);
|
||||
expect(call.connectionState).toBe(ConnectionState.Connected);
|
||||
WidgetMessagingStore.instance.stopMessaging(widget, room.roomId);
|
||||
expect(call.connectionState).toBe(ConnectionState.Disconnected);
|
||||
});
|
||||
|
||||
it("acknowledges mute_device widget action", async () => {
|
||||
await callConnectProcedure(call);
|
||||
await connect(call, messaging);
|
||||
const preventDefault = jest.fn();
|
||||
const mockEv = {
|
||||
preventDefault,
|
||||
@@ -980,8 +872,8 @@ describe("ElementCall", () => {
|
||||
const onConnectionState = jest.fn();
|
||||
call.on(CallEvent.ConnectionState, onConnectionState);
|
||||
|
||||
await callConnectProcedure(call);
|
||||
await callDisconnectionProcedure(call);
|
||||
await connect(call, messaging);
|
||||
await disconnect(call, messaging);
|
||||
expect(onConnectionState.mock.calls).toEqual([
|
||||
[ConnectionState.Connected, ConnectionState.Disconnected],
|
||||
[ConnectionState.Disconnecting, ConnectionState.Connected],
|
||||
@@ -1003,10 +895,10 @@ describe("ElementCall", () => {
|
||||
});
|
||||
|
||||
it("ends the call immediately if the session ended", async () => {
|
||||
await callConnectProcedure(call);
|
||||
await connect(call, messaging);
|
||||
const onDestroy = jest.fn();
|
||||
call.on(CallEvent.Destroy, onDestroy);
|
||||
await callDisconnectionProcedure(call);
|
||||
await disconnect(call, messaging);
|
||||
// this will be called automatically
|
||||
// disconnect -> widget sends state event -> session manager notices no-one left
|
||||
client.matrixRTC.emit(
|
||||
@@ -1048,8 +940,6 @@ describe("ElementCall", () => {
|
||||
let call: ElementCall;
|
||||
let widget: Widget;
|
||||
let messaging: Mocked<ClientWidgetApi>;
|
||||
let audioMutedSpy: jest.SpyInstance<boolean, []>;
|
||||
let videoMutedSpy: jest.SpyInstance<boolean, []>;
|
||||
|
||||
beforeEach(async () => {
|
||||
jest.useFakeTimers();
|
||||
@@ -1062,64 +952,29 @@ describe("ElementCall", () => {
|
||||
if (maybeCall === null) throw new Error("Failed to create call");
|
||||
call = maybeCall;
|
||||
|
||||
({ widget, messaging, audioMutedSpy, videoMutedSpy } = setUpWidget(call));
|
||||
({ widget, messaging } = setUpWidget(call));
|
||||
});
|
||||
|
||||
afterEach(() => cleanUpCallAndWidget(call, widget, audioMutedSpy, videoMutedSpy));
|
||||
afterEach(() => cleanUpCallAndWidget(call, widget));
|
||||
|
||||
it("doesn't end the call when the last participant leaves", async () => {
|
||||
await callConnectProcedure(call);
|
||||
await connect(call, messaging);
|
||||
const onDestroy = jest.fn();
|
||||
call.on(CallEvent.Destroy, onDestroy);
|
||||
await callDisconnectionProcedure(call);
|
||||
await disconnect(call, messaging);
|
||||
expect(onDestroy).not.toHaveBeenCalled();
|
||||
call.off(CallEvent.Destroy, onDestroy);
|
||||
});
|
||||
|
||||
it("connect to call with ongoing session", async () => {
|
||||
// Mock membership getter used by `roomSessionForRoom`.
|
||||
// This makes sure the roomSession will not be empty.
|
||||
jest.spyOn(MatrixRTCSession, "callMembershipsForRoom").mockImplementation(() => [
|
||||
{ fakeVal: "fake membership", getMsUntilExpiry: () => 1000 } as unknown as CallMembership,
|
||||
]);
|
||||
// Create ongoing session
|
||||
const roomSession = MatrixRTCSession.roomSessionForRoom(client, room);
|
||||
const roomSessionEmitSpy = jest.spyOn(roomSession, "emit");
|
||||
|
||||
// Make sure the created session ends up in the call.
|
||||
// `getActiveRoomSession` will be used during `call.connect`
|
||||
// `getRoomSession` will be used during `Call.get`
|
||||
client.matrixRTC.getActiveRoomSession.mockImplementation(() => {
|
||||
return roomSession;
|
||||
});
|
||||
client.matrixRTC.getRoomSession.mockImplementation(() => {
|
||||
return roomSession;
|
||||
});
|
||||
|
||||
ElementCall.create(room);
|
||||
const call = Call.get(room);
|
||||
if (!(call instanceof ElementCall)) throw new Error("Failed to create call");
|
||||
expect(call.session).toBe(roomSession);
|
||||
await callConnectProcedure(call);
|
||||
expect(roomSessionEmitSpy).toHaveBeenCalledWith(
|
||||
"memberships_changed",
|
||||
[],
|
||||
[{ sender: "@alice:example.org" }],
|
||||
);
|
||||
expect(call.connectionState).toBe(ConnectionState.Connected);
|
||||
call.destroy();
|
||||
});
|
||||
|
||||
it("handles remote disconnection and reconnect right after", async () => {
|
||||
expect(call.connectionState).toBe(ConnectionState.Disconnected);
|
||||
await callConnectProcedure(call);
|
||||
await connect(call, messaging);
|
||||
expect(call.connectionState).toBe(ConnectionState.Connected);
|
||||
|
||||
messaging.emit(`action:${ElementWidgetActions.HangupCall}`, new CustomEvent("widgetapirequest", {}));
|
||||
messaging.emit(`action:${ElementWidgetActions.Close}`, new CustomEvent("widgetapirequest", {}));
|
||||
// We should now be able to reconnect without manually starting the widget
|
||||
expect(call.connectionState).toBe(ConnectionState.Disconnected);
|
||||
await callConnectProcedure(call, false);
|
||||
await connect(call, messaging, false);
|
||||
await waitFor(() => expect(call.connectionState).toBe(ConnectionState.Connected), { interval: 5 });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -28,6 +28,7 @@ import "../../../../../src/stores/room-list/RoomListStore"; // must be imported
|
||||
import { Algorithm } from "../../../../../src/stores/room-list/algorithms/Algorithm";
|
||||
import { CallStore } from "../../../../../src/stores/CallStore";
|
||||
import { WidgetMessagingStore } from "../../../../../src/stores/widgets/WidgetMessagingStore";
|
||||
import { ConnectionState } from "../../../../../src/models/Call";
|
||||
|
||||
describe("Algorithm", () => {
|
||||
useMockedCalls();
|
||||
@@ -83,7 +84,7 @@ describe("Algorithm", () => {
|
||||
|
||||
MockedCall.create(roomWithCall, "1");
|
||||
const call = CallStore.instance.getCall(roomWithCall.roomId);
|
||||
if (call === null) throw new Error("Failed to create call");
|
||||
if (!(call instanceof MockedCall)) throw new Error("Failed to create call");
|
||||
|
||||
const widget = new Widget(call.widget);
|
||||
WidgetMessagingStore.instance.storeMessaging(widget, roomWithCall.roomId, {
|
||||
@@ -93,7 +94,7 @@ describe("Algorithm", () => {
|
||||
// End of setup
|
||||
|
||||
expect(algorithm.getOrderedRooms()[DefaultTagID.Untagged]).toEqual([room, roomWithCall]);
|
||||
await call.start();
|
||||
call.setConnectionState(ConnectionState.Connected);
|
||||
expect(algorithm.getOrderedRooms()[DefaultTagID.Untagged]).toEqual([roomWithCall, room]);
|
||||
await call.disconnect();
|
||||
expect(algorithm.getOrderedRooms()[DefaultTagID.Untagged]).toEqual([room, roomWithCall]);
|
||||
|
||||
570
yarn.lock
570
yarn.lock
@@ -2088,41 +2088,41 @@
|
||||
"@figspec/components" "^1.0.1"
|
||||
"@lit-labs/react" "^1.0.2"
|
||||
|
||||
"@floating-ui/core@^1.6.0":
|
||||
version "1.6.8"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.8.tgz#aa43561be075815879305965020f492cdb43da12"
|
||||
integrity sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==
|
||||
"@floating-ui/core@^1.7.3":
|
||||
version "1.7.3"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.7.3.tgz#462d722f001e23e46d86fd2bd0d21b7693ccb8b7"
|
||||
integrity sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==
|
||||
dependencies:
|
||||
"@floating-ui/utils" "^0.2.8"
|
||||
"@floating-ui/utils" "^0.2.10"
|
||||
|
||||
"@floating-ui/dom@^1.0.0":
|
||||
version "1.6.11"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.11.tgz#8631857838d34ee5712339eb7cbdfb8ad34da723"
|
||||
integrity sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ==
|
||||
"@floating-ui/dom@^1.7.3":
|
||||
version "1.7.3"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.7.3.tgz#6174ac3409e6a064bbdf1f4bb07188ee9461f8cf"
|
||||
integrity sha512-uZA413QEpNuhtb3/iIKoYMSK07keHPYeXF02Zhd6e213j+d1NamLix/mCLxBUDW/Gx52sPH2m+chlUsyaBs/Ag==
|
||||
dependencies:
|
||||
"@floating-ui/core" "^1.6.0"
|
||||
"@floating-ui/utils" "^0.2.8"
|
||||
"@floating-ui/core" "^1.7.3"
|
||||
"@floating-ui/utils" "^0.2.10"
|
||||
|
||||
"@floating-ui/react-dom@^2.0.0", "@floating-ui/react-dom@^2.1.2":
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.2.tgz#a1349bbf6a0e5cb5ded55d023766f20a4d439a31"
|
||||
integrity sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==
|
||||
"@floating-ui/react-dom@^2.0.0", "@floating-ui/react-dom@^2.1.5":
|
||||
version "2.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.5.tgz#d11e3726d2eb385d8cf3216348742907c1d49fcf"
|
||||
integrity sha512-HDO/1/1oH9fjj4eLgegrlH3dklZpHtUYYFiVwMUwfGvk9jWDRWqkklA2/NFScknrcNSspbV868WjXORvreDX+Q==
|
||||
dependencies:
|
||||
"@floating-ui/dom" "^1.0.0"
|
||||
"@floating-ui/dom" "^1.7.3"
|
||||
|
||||
"@floating-ui/react@^0.27.0":
|
||||
version "0.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/react/-/react-0.27.0.tgz#e0931fd09374ab4b8ce1a1af5cb44d1ccd1bb95a"
|
||||
integrity sha512-WLEksq7fJapXSJbmfiyq9pAW0a7ZFMEJToFE4oTDESxGjoa+nZu3YMjmZE2KvoUtQhqOK2yMMfWQFZyeWD0wGQ==
|
||||
version "0.27.15"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/react/-/react-0.27.15.tgz#1005b01e8de79ff98de9a93717bdd1bd4fcd1949"
|
||||
integrity sha512-0LGxhBi3BB1DwuSNQAmuaSuertFzNAerlMdPbotjTVnvPtdOs7CkrHLaev5NIXemhzDXNC0tFzuseut7cWA5mw==
|
||||
dependencies:
|
||||
"@floating-ui/react-dom" "^2.1.2"
|
||||
"@floating-ui/utils" "^0.2.8"
|
||||
"@floating-ui/react-dom" "^2.1.5"
|
||||
"@floating-ui/utils" "^0.2.10"
|
||||
tabbable "^6.0.0"
|
||||
|
||||
"@floating-ui/utils@^0.2.8":
|
||||
version "0.2.8"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.8.tgz#21a907684723bbbaa5f0974cf7730bd797eb8e62"
|
||||
integrity sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==
|
||||
"@floating-ui/utils@^0.2.10":
|
||||
version "0.2.10"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.10.tgz#a2a1e3812d14525f725d011a73eceb41fef5bc1c"
|
||||
integrity sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==
|
||||
|
||||
"@fontsource/inconsolata@^5":
|
||||
version "5.2.6"
|
||||
@@ -2912,286 +2912,289 @@
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
|
||||
integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==
|
||||
|
||||
"@radix-ui/primitive@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.0.tgz#42ef83b3b56dccad5d703ae8c42919a68798bbe2"
|
||||
integrity sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==
|
||||
"@radix-ui/primitive@1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.2.tgz#83f415c4425f21e3d27914c12b3272a32e3dae65"
|
||||
integrity sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==
|
||||
|
||||
"@radix-ui/react-arrow@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz#744f388182d360b86285217e43b6c63633f39e7a"
|
||||
integrity sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==
|
||||
"@radix-ui/react-arrow@1.1.7":
|
||||
version "1.1.7"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz#e14a2657c81d961598c5e72b73dd6098acc04f09"
|
||||
integrity sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==
|
||||
dependencies:
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
"@radix-ui/react-primitive" "2.1.3"
|
||||
|
||||
"@radix-ui/react-collection@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.1.0.tgz#f18af78e46454a2360d103c2251773028b7724ed"
|
||||
integrity sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==
|
||||
"@radix-ui/react-collection@1.1.7":
|
||||
version "1.1.7"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.1.7.tgz#d05c25ca9ac4695cc19ba91f42f686e3ea2d9aec"
|
||||
integrity sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==
|
||||
dependencies:
|
||||
"@radix-ui/react-compose-refs" "1.1.0"
|
||||
"@radix-ui/react-context" "1.1.0"
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
"@radix-ui/react-slot" "1.1.0"
|
||||
"@radix-ui/react-compose-refs" "1.1.2"
|
||||
"@radix-ui/react-context" "1.1.2"
|
||||
"@radix-ui/react-primitive" "2.1.3"
|
||||
"@radix-ui/react-slot" "1.2.3"
|
||||
|
||||
"@radix-ui/react-compose-refs@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz#656432461fc8283d7b591dcf0d79152fae9ecc74"
|
||||
integrity sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==
|
||||
"@radix-ui/react-compose-refs@1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz#a2c4c47af6337048ee78ff6dc0d090b390d2bb30"
|
||||
integrity sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==
|
||||
|
||||
"@radix-ui/react-context-menu@^2.2.1":
|
||||
version "2.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-context-menu/-/react-context-menu-2.2.2.tgz#efcddc559fc3011721b65148f062d04027f76c7a"
|
||||
integrity sha512-99EatSTpW+hRYHt7m8wdDlLtkmTovEe8Z/hnxUPV+SKuuNL5HWNhQI4QSdjZqNSgXHay2z4M3Dym73j9p2Gx5Q==
|
||||
version "2.2.15"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-context-menu/-/react-context-menu-2.2.15.tgz#d61a7c8badbcad72fadb9ed87efaa21df60b0a99"
|
||||
integrity sha512-UsQUMjcYTsBjTSXw0P3GO0werEQvUY2plgRQuKoCTtkNr45q1DiL51j4m7gxhABzZ0BadoXNsIbg7F3KwiUBbw==
|
||||
dependencies:
|
||||
"@radix-ui/primitive" "1.1.0"
|
||||
"@radix-ui/react-context" "1.1.1"
|
||||
"@radix-ui/react-menu" "2.1.2"
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
"@radix-ui/react-use-callback-ref" "1.1.0"
|
||||
"@radix-ui/react-use-controllable-state" "1.1.0"
|
||||
"@radix-ui/primitive" "1.1.2"
|
||||
"@radix-ui/react-context" "1.1.2"
|
||||
"@radix-ui/react-menu" "2.1.15"
|
||||
"@radix-ui/react-primitive" "2.1.3"
|
||||
"@radix-ui/react-use-callback-ref" "1.1.1"
|
||||
"@radix-ui/react-use-controllable-state" "1.2.2"
|
||||
|
||||
"@radix-ui/react-context@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.0.tgz#6df8d983546cfd1999c8512f3a8ad85a6e7fcee8"
|
||||
integrity sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==
|
||||
|
||||
"@radix-ui/react-context@1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.1.tgz#82074aa83a472353bb22e86f11bcbd1c61c4c71a"
|
||||
integrity sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==
|
||||
"@radix-ui/react-context@1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.2.tgz#61628ef269a433382c364f6f1e3788a6dc213a36"
|
||||
integrity sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==
|
||||
|
||||
"@radix-ui/react-dialog@^1.1.1":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.1.2.tgz#d9345575211d6f2d13e209e84aec9a8584b54d6c"
|
||||
integrity sha512-Yj4dZtqa2o+kG61fzB0H2qUvmwBA2oyQroGLyNtBj1beo1khoQ3q1a2AO8rrQYjd8256CO9+N8L9tvsS+bnIyA==
|
||||
version "1.1.14"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.1.14.tgz#4c69c80c258bc6561398cfce055202ea11075107"
|
||||
integrity sha512-+CpweKjqpzTmwRwcYECQcNYbI8V9VSQt0SNFKeEBLgfucbsLssU6Ppq7wUdNXEGb573bMjFhVjKVll8rmV6zMw==
|
||||
dependencies:
|
||||
"@radix-ui/primitive" "1.1.0"
|
||||
"@radix-ui/react-compose-refs" "1.1.0"
|
||||
"@radix-ui/react-context" "1.1.1"
|
||||
"@radix-ui/react-dismissable-layer" "1.1.1"
|
||||
"@radix-ui/react-focus-guards" "1.1.1"
|
||||
"@radix-ui/react-focus-scope" "1.1.0"
|
||||
"@radix-ui/react-id" "1.1.0"
|
||||
"@radix-ui/react-portal" "1.1.2"
|
||||
"@radix-ui/react-presence" "1.1.1"
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
"@radix-ui/react-slot" "1.1.0"
|
||||
"@radix-ui/react-use-controllable-state" "1.1.0"
|
||||
aria-hidden "^1.1.1"
|
||||
react-remove-scroll "2.6.0"
|
||||
"@radix-ui/primitive" "1.1.2"
|
||||
"@radix-ui/react-compose-refs" "1.1.2"
|
||||
"@radix-ui/react-context" "1.1.2"
|
||||
"@radix-ui/react-dismissable-layer" "1.1.10"
|
||||
"@radix-ui/react-focus-guards" "1.1.2"
|
||||
"@radix-ui/react-focus-scope" "1.1.7"
|
||||
"@radix-ui/react-id" "1.1.1"
|
||||
"@radix-ui/react-portal" "1.1.9"
|
||||
"@radix-ui/react-presence" "1.1.4"
|
||||
"@radix-ui/react-primitive" "2.1.3"
|
||||
"@radix-ui/react-slot" "1.2.3"
|
||||
"@radix-ui/react-use-controllable-state" "1.2.2"
|
||||
aria-hidden "^1.2.4"
|
||||
react-remove-scroll "^2.6.3"
|
||||
|
||||
"@radix-ui/react-direction@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.1.0.tgz#a7d39855f4d077adc2a1922f9c353c5977a09cdc"
|
||||
integrity sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==
|
||||
|
||||
"@radix-ui/react-dismissable-layer@1.1.1":
|
||||
"@radix-ui/react-direction@1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz#cbdcb739c5403382bdde5f9243042ba643883396"
|
||||
integrity sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.1.1.tgz#39e5a5769e676c753204b792fbe6cf508e550a14"
|
||||
integrity sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==
|
||||
|
||||
"@radix-ui/react-dismissable-layer@1.1.10":
|
||||
version "1.1.10"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.10.tgz#429b9bada3672c6895a5d6a642aca6ecaf4f18c3"
|
||||
integrity sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ==
|
||||
dependencies:
|
||||
"@radix-ui/primitive" "1.1.0"
|
||||
"@radix-ui/react-compose-refs" "1.1.0"
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
"@radix-ui/react-use-callback-ref" "1.1.0"
|
||||
"@radix-ui/react-use-escape-keydown" "1.1.0"
|
||||
"@radix-ui/primitive" "1.1.2"
|
||||
"@radix-ui/react-compose-refs" "1.1.2"
|
||||
"@radix-ui/react-primitive" "2.1.3"
|
||||
"@radix-ui/react-use-callback-ref" "1.1.1"
|
||||
"@radix-ui/react-use-escape-keydown" "1.1.1"
|
||||
|
||||
"@radix-ui/react-dropdown-menu@^2.1.1":
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.2.tgz#acc49577130e3c875ef0133bd1e271ea3392d924"
|
||||
integrity sha512-GVZMR+eqK8/Kes0a36Qrv+i20bAPXSn8rCBTHx30w+3ECnR5o3xixAlqcVaYvLeyKUsm0aqyhWfmUcqufM8nYA==
|
||||
version "2.1.15"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.15.tgz#f507320de8e11bc1e671a6ec0c27a7a89e725131"
|
||||
integrity sha512-mIBnOjgwo9AH3FyKaSWoSu/dYj6VdhJ7frEPiGTeXCdUFHjl9h3mFh2wwhEtINOmYXWhdpf1rY2minFsmaNgVQ==
|
||||
dependencies:
|
||||
"@radix-ui/primitive" "1.1.0"
|
||||
"@radix-ui/react-compose-refs" "1.1.0"
|
||||
"@radix-ui/react-context" "1.1.1"
|
||||
"@radix-ui/react-id" "1.1.0"
|
||||
"@radix-ui/react-menu" "2.1.2"
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
"@radix-ui/react-use-controllable-state" "1.1.0"
|
||||
"@radix-ui/primitive" "1.1.2"
|
||||
"@radix-ui/react-compose-refs" "1.1.2"
|
||||
"@radix-ui/react-context" "1.1.2"
|
||||
"@radix-ui/react-id" "1.1.1"
|
||||
"@radix-ui/react-menu" "2.1.15"
|
||||
"@radix-ui/react-primitive" "2.1.3"
|
||||
"@radix-ui/react-use-controllable-state" "1.2.2"
|
||||
|
||||
"@radix-ui/react-focus-guards@1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz#8635edd346304f8b42cae86b05912b61aef27afe"
|
||||
integrity sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==
|
||||
"@radix-ui/react-focus-guards@1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.2.tgz#4ec9a7e50925f7fb661394460045b46212a33bed"
|
||||
integrity sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA==
|
||||
|
||||
"@radix-ui/react-focus-scope@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.0.tgz#ebe2891a298e0a33ad34daab2aad8dea31caf0b2"
|
||||
integrity sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==
|
||||
"@radix-ui/react-focus-scope@1.1.7":
|
||||
version "1.1.7"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz#dfe76fc103537d80bf42723a183773fd07bfb58d"
|
||||
integrity sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==
|
||||
dependencies:
|
||||
"@radix-ui/react-compose-refs" "1.1.0"
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
"@radix-ui/react-use-callback-ref" "1.1.0"
|
||||
"@radix-ui/react-compose-refs" "1.1.2"
|
||||
"@radix-ui/react-primitive" "2.1.3"
|
||||
"@radix-ui/react-use-callback-ref" "1.1.1"
|
||||
|
||||
"@radix-ui/react-form@^0.1.0":
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-form/-/react-form-0.1.0.tgz#7111a6aa54a2bde0d11fb72643f9ffc871ac58ad"
|
||||
integrity sha512-1/oVYPDjbFILOLIarcGcMKo+y6SbTVT/iUKVEw59CF4offwZgBgC3ZOeSBewjqU0vdA6FWTPWTN63obj55S/tQ==
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-form/-/react-form-0.1.7.tgz#acbf7ef57bbed1e76ea1f2d3b18eff465519435c"
|
||||
integrity sha512-IXLKFnaYvFg/KkeV5QfOX7tRnwHXp127koOFUjLWMTrRv5Rny3DQcAtIFFeA/Cli4HHM8DuJCXAUsgnFVJndlw==
|
||||
dependencies:
|
||||
"@radix-ui/primitive" "1.1.0"
|
||||
"@radix-ui/react-compose-refs" "1.1.0"
|
||||
"@radix-ui/react-context" "1.1.0"
|
||||
"@radix-ui/react-id" "1.1.0"
|
||||
"@radix-ui/react-label" "2.1.0"
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
"@radix-ui/primitive" "1.1.2"
|
||||
"@radix-ui/react-compose-refs" "1.1.2"
|
||||
"@radix-ui/react-context" "1.1.2"
|
||||
"@radix-ui/react-id" "1.1.1"
|
||||
"@radix-ui/react-label" "2.1.7"
|
||||
"@radix-ui/react-primitive" "2.1.3"
|
||||
|
||||
"@radix-ui/react-id@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.1.0.tgz#de47339656594ad722eb87f94a6b25f9cffae0ed"
|
||||
integrity sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==
|
||||
"@radix-ui/react-id@1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.1.1.tgz#1404002e79a03fe062b7e3864aa01e24bd1471f7"
|
||||
integrity sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==
|
||||
dependencies:
|
||||
"@radix-ui/react-use-layout-effect" "1.1.0"
|
||||
"@radix-ui/react-use-layout-effect" "1.1.1"
|
||||
|
||||
"@radix-ui/react-label@2.1.0":
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-label/-/react-label-2.1.0.tgz#3aa2418d70bb242be37c51ff5e51a2adcbc372e3"
|
||||
integrity sha512-peLblDlFw/ngk3UWq0VnYaOLy6agTZZ+MUO/WhVfm14vJGML+xH4FAl2XQGLqdefjNb7ApRg6Yn7U42ZhmYXdw==
|
||||
"@radix-ui/react-label@2.1.7":
|
||||
version "2.1.7"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-label/-/react-label-2.1.7.tgz#ad959ff9c6e4968d533329eb95696e1ba8ad72ab"
|
||||
integrity sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==
|
||||
dependencies:
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
"@radix-ui/react-primitive" "2.1.3"
|
||||
|
||||
"@radix-ui/react-menu@2.1.2":
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-menu/-/react-menu-2.1.2.tgz#91f6815845a4298dde775563ed2d80b7ad667899"
|
||||
integrity sha512-lZ0R4qR2Al6fZ4yCCZzu/ReTFrylHFxIqy7OezIpWF4bL0o9biKo0pFIvkaew3TyZ9Fy5gYVrR5zCGZBVbO1zg==
|
||||
"@radix-ui/react-menu@2.1.15":
|
||||
version "2.1.15"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-menu/-/react-menu-2.1.15.tgz#a1a8f06cab3c309f9998cdbd2b3ad279e42ed483"
|
||||
integrity sha512-tVlmA3Vb9n8SZSd+YSbuFR66l87Wiy4du+YE+0hzKQEANA+7cWKH1WgqcEX4pXqxUFQKrWQGHdvEfw00TjFiew==
|
||||
dependencies:
|
||||
"@radix-ui/primitive" "1.1.0"
|
||||
"@radix-ui/react-collection" "1.1.0"
|
||||
"@radix-ui/react-compose-refs" "1.1.0"
|
||||
"@radix-ui/react-context" "1.1.1"
|
||||
"@radix-ui/react-direction" "1.1.0"
|
||||
"@radix-ui/react-dismissable-layer" "1.1.1"
|
||||
"@radix-ui/react-focus-guards" "1.1.1"
|
||||
"@radix-ui/react-focus-scope" "1.1.0"
|
||||
"@radix-ui/react-id" "1.1.0"
|
||||
"@radix-ui/react-popper" "1.2.0"
|
||||
"@radix-ui/react-portal" "1.1.2"
|
||||
"@radix-ui/react-presence" "1.1.1"
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
"@radix-ui/react-roving-focus" "1.1.0"
|
||||
"@radix-ui/react-slot" "1.1.0"
|
||||
"@radix-ui/react-use-callback-ref" "1.1.0"
|
||||
aria-hidden "^1.1.1"
|
||||
react-remove-scroll "2.6.0"
|
||||
"@radix-ui/primitive" "1.1.2"
|
||||
"@radix-ui/react-collection" "1.1.7"
|
||||
"@radix-ui/react-compose-refs" "1.1.2"
|
||||
"@radix-ui/react-context" "1.1.2"
|
||||
"@radix-ui/react-direction" "1.1.1"
|
||||
"@radix-ui/react-dismissable-layer" "1.1.10"
|
||||
"@radix-ui/react-focus-guards" "1.1.2"
|
||||
"@radix-ui/react-focus-scope" "1.1.7"
|
||||
"@radix-ui/react-id" "1.1.1"
|
||||
"@radix-ui/react-popper" "1.2.7"
|
||||
"@radix-ui/react-portal" "1.1.9"
|
||||
"@radix-ui/react-presence" "1.1.4"
|
||||
"@radix-ui/react-primitive" "2.1.3"
|
||||
"@radix-ui/react-roving-focus" "1.1.10"
|
||||
"@radix-ui/react-slot" "1.2.3"
|
||||
"@radix-ui/react-use-callback-ref" "1.1.1"
|
||||
aria-hidden "^1.2.4"
|
||||
react-remove-scroll "^2.6.3"
|
||||
|
||||
"@radix-ui/react-popper@1.2.0":
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.2.0.tgz#a3e500193d144fe2d8f5d5e60e393d64111f2a7a"
|
||||
integrity sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==
|
||||
"@radix-ui/react-popper@1.2.7":
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.2.7.tgz#531cf2eebb3d3270d58f7d8136e4517646429978"
|
||||
integrity sha512-IUFAccz1JyKcf/RjB552PlWwxjeCJB8/4KxT7EhBHOJM+mN7LdW+B3kacJXILm32xawcMMjb2i0cIZpo+f9kiQ==
|
||||
dependencies:
|
||||
"@floating-ui/react-dom" "^2.0.0"
|
||||
"@radix-ui/react-arrow" "1.1.0"
|
||||
"@radix-ui/react-compose-refs" "1.1.0"
|
||||
"@radix-ui/react-context" "1.1.0"
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
"@radix-ui/react-use-callback-ref" "1.1.0"
|
||||
"@radix-ui/react-use-layout-effect" "1.1.0"
|
||||
"@radix-ui/react-use-rect" "1.1.0"
|
||||
"@radix-ui/react-use-size" "1.1.0"
|
||||
"@radix-ui/rect" "1.1.0"
|
||||
"@radix-ui/react-arrow" "1.1.7"
|
||||
"@radix-ui/react-compose-refs" "1.1.2"
|
||||
"@radix-ui/react-context" "1.1.2"
|
||||
"@radix-ui/react-primitive" "2.1.3"
|
||||
"@radix-ui/react-use-callback-ref" "1.1.1"
|
||||
"@radix-ui/react-use-layout-effect" "1.1.1"
|
||||
"@radix-ui/react-use-rect" "1.1.1"
|
||||
"@radix-ui/react-use-size" "1.1.1"
|
||||
"@radix-ui/rect" "1.1.1"
|
||||
|
||||
"@radix-ui/react-portal@1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.2.tgz#51eb46dae7505074b306ebcb985bf65cc547d74e"
|
||||
integrity sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg==
|
||||
"@radix-ui/react-portal@1.1.9":
|
||||
version "1.1.9"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.9.tgz#14c3649fe48ec474ac51ed9f2b9f5da4d91c4472"
|
||||
integrity sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==
|
||||
dependencies:
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
"@radix-ui/react-use-layout-effect" "1.1.0"
|
||||
"@radix-ui/react-primitive" "2.1.3"
|
||||
"@radix-ui/react-use-layout-effect" "1.1.1"
|
||||
|
||||
"@radix-ui/react-presence@1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.1.tgz#98aba423dba5e0c687a782c0669dcd99de17f9b1"
|
||||
integrity sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==
|
||||
"@radix-ui/react-presence@1.1.4":
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.4.tgz#253ac0ad4946c5b4a9c66878335f5cf07c967ced"
|
||||
integrity sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA==
|
||||
dependencies:
|
||||
"@radix-ui/react-compose-refs" "1.1.0"
|
||||
"@radix-ui/react-use-layout-effect" "1.1.0"
|
||||
"@radix-ui/react-compose-refs" "1.1.2"
|
||||
"@radix-ui/react-use-layout-effect" "1.1.1"
|
||||
|
||||
"@radix-ui/react-primitive@2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz#fe05715faa9203a223ccc0be15dc44b9f9822884"
|
||||
integrity sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==
|
||||
"@radix-ui/react-primitive@2.1.3":
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz#db9b8bcff49e01be510ad79893fb0e4cda50f1bc"
|
||||
integrity sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==
|
||||
dependencies:
|
||||
"@radix-ui/react-slot" "1.1.0"
|
||||
"@radix-ui/react-slot" "1.2.3"
|
||||
|
||||
"@radix-ui/react-progress@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-progress/-/react-progress-1.1.0.tgz#28c267885ec154fc557ec7a66cb462787312f7e2"
|
||||
integrity sha512-aSzvnYpP725CROcxAOEBVZZSIQVQdHgBr2QQFKySsaD14u8dNT0batuXI+AAGDdAHfXH8rbnHmjYFqVJ21KkRg==
|
||||
version "1.1.7"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-progress/-/react-progress-1.1.7.tgz#a2b76398b3f24b6bd5e37f112b1e30fbedd4f38e"
|
||||
integrity sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg==
|
||||
dependencies:
|
||||
"@radix-ui/react-context" "1.1.0"
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
"@radix-ui/react-context" "1.1.2"
|
||||
"@radix-ui/react-primitive" "2.1.3"
|
||||
|
||||
"@radix-ui/react-roving-focus@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz#b30c59daf7e714c748805bfe11c76f96caaac35e"
|
||||
integrity sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==
|
||||
"@radix-ui/react-roving-focus@1.1.10":
|
||||
version "1.1.10"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.10.tgz#46030496d2a490c4979d29a7e1252465e51e4b0b"
|
||||
integrity sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q==
|
||||
dependencies:
|
||||
"@radix-ui/primitive" "1.1.0"
|
||||
"@radix-ui/react-collection" "1.1.0"
|
||||
"@radix-ui/react-compose-refs" "1.1.0"
|
||||
"@radix-ui/react-context" "1.1.0"
|
||||
"@radix-ui/react-direction" "1.1.0"
|
||||
"@radix-ui/react-id" "1.1.0"
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
"@radix-ui/react-use-callback-ref" "1.1.0"
|
||||
"@radix-ui/react-use-controllable-state" "1.1.0"
|
||||
"@radix-ui/primitive" "1.1.2"
|
||||
"@radix-ui/react-collection" "1.1.7"
|
||||
"@radix-ui/react-compose-refs" "1.1.2"
|
||||
"@radix-ui/react-context" "1.1.2"
|
||||
"@radix-ui/react-direction" "1.1.1"
|
||||
"@radix-ui/react-id" "1.1.1"
|
||||
"@radix-ui/react-primitive" "2.1.3"
|
||||
"@radix-ui/react-use-callback-ref" "1.1.1"
|
||||
"@radix-ui/react-use-controllable-state" "1.2.2"
|
||||
|
||||
"@radix-ui/react-separator@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-separator/-/react-separator-1.1.0.tgz#ee0f4d86003b0e3ea7bc6ccab01ea0adee32663e"
|
||||
integrity sha512-3uBAs+egzvJBDZAzvb/n4NxxOYpnspmWxO2u5NbZ8Y6FM/NdrGSF9bop3Cf6F6C71z1rTSn8KV0Fo2ZVd79lGA==
|
||||
version "1.1.7"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-separator/-/react-separator-1.1.7.tgz#a18bd7fd07c10fda1bba14f2a3032e7b1a2b3470"
|
||||
integrity sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==
|
||||
dependencies:
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
"@radix-ui/react-primitive" "2.1.3"
|
||||
|
||||
"@radix-ui/react-slot@1.1.0", "@radix-ui/react-slot@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.1.0.tgz#7c5e48c36ef5496d97b08f1357bb26ed7c714b84"
|
||||
integrity sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==
|
||||
"@radix-ui/react-slot@1.2.3", "@radix-ui/react-slot@^1.1.0":
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.2.3.tgz#502d6e354fc847d4169c3bc5f189de777f68cfe1"
|
||||
integrity sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==
|
||||
dependencies:
|
||||
"@radix-ui/react-compose-refs" "1.1.0"
|
||||
"@radix-ui/react-compose-refs" "1.1.2"
|
||||
|
||||
"@radix-ui/react-use-callback-ref@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz#bce938ca413675bc937944b0d01ef6f4a6dc5bf1"
|
||||
integrity sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==
|
||||
"@radix-ui/react-use-callback-ref@1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz#62a4dba8b3255fdc5cc7787faeac1c6e4cc58d40"
|
||||
integrity sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==
|
||||
|
||||
"@radix-ui/react-use-controllable-state@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz#1321446857bb786917df54c0d4d084877aab04b0"
|
||||
integrity sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==
|
||||
"@radix-ui/react-use-controllable-state@1.2.2":
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz#905793405de57d61a439f4afebbb17d0645f3190"
|
||||
integrity sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==
|
||||
dependencies:
|
||||
"@radix-ui/react-use-callback-ref" "1.1.0"
|
||||
"@radix-ui/react-use-effect-event" "0.0.2"
|
||||
"@radix-ui/react-use-layout-effect" "1.1.1"
|
||||
|
||||
"@radix-ui/react-use-escape-keydown@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz#31a5b87c3b726504b74e05dac1edce7437b98754"
|
||||
integrity sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==
|
||||
"@radix-ui/react-use-effect-event@0.0.2":
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz#090cf30d00a4c7632a15548512e9152217593907"
|
||||
integrity sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==
|
||||
dependencies:
|
||||
"@radix-ui/react-use-callback-ref" "1.1.0"
|
||||
"@radix-ui/react-use-layout-effect" "1.1.1"
|
||||
|
||||
"@radix-ui/react-use-layout-effect@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz#3c2c8ce04827b26a39e442ff4888d9212268bd27"
|
||||
integrity sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==
|
||||
|
||||
"@radix-ui/react-use-rect@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz#13b25b913bd3e3987cc9b073a1a164bb1cf47b88"
|
||||
integrity sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==
|
||||
"@radix-ui/react-use-escape-keydown@1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz#b3fed9bbea366a118f40427ac40500aa1423cc29"
|
||||
integrity sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==
|
||||
dependencies:
|
||||
"@radix-ui/rect" "1.1.0"
|
||||
"@radix-ui/react-use-callback-ref" "1.1.1"
|
||||
|
||||
"@radix-ui/react-use-size@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz#b4dba7fbd3882ee09e8d2a44a3eed3a7e555246b"
|
||||
integrity sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==
|
||||
"@radix-ui/react-use-layout-effect@1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz#0c4230a9eed49d4589c967e2d9c0d9d60a23971e"
|
||||
integrity sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==
|
||||
|
||||
"@radix-ui/react-use-rect@1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz#01443ca8ed071d33023c1113e5173b5ed8769152"
|
||||
integrity sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==
|
||||
dependencies:
|
||||
"@radix-ui/react-use-layout-effect" "1.1.0"
|
||||
"@radix-ui/rect" "1.1.1"
|
||||
|
||||
"@radix-ui/rect@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.1.0.tgz#f817d1d3265ac5415dadc67edab30ae196696438"
|
||||
integrity sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==
|
||||
"@radix-ui/react-use-size@1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz#6de276ffbc389a537ffe4316f5b0f24129405b37"
|
||||
integrity sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==
|
||||
dependencies:
|
||||
"@radix-ui/react-use-layout-effect" "1.1.1"
|
||||
|
||||
"@radix-ui/rect@1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.1.1.tgz#78244efe12930c56fd255d7923865857c41ac8cb"
|
||||
integrity sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==
|
||||
|
||||
"@rollup/plugin-inject@^5.0.5":
|
||||
version "5.0.5"
|
||||
@@ -4684,10 +4687,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@vector-im/compound-design-tokens/-/compound-design-tokens-6.0.0.tgz#a07975ee46307fc31c2ec64a216b6be2b3b27fb3"
|
||||
integrity sha512-Jk0NsLPCvdcuZi6an1cfyf4MDcIuoPlvja5ZWgJcORyGQZV1eLMHPYKShq9gj+EYk/BXZoPvQ1d6/T+/LSCNPA==
|
||||
|
||||
|
||||
"@vector-im/compound-web@^8.1.2":
|
||||
version "8.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@vector-im/compound-web/-/compound-web-8.1.2.tgz#a8af8681b442e63e07b8f25204528b1b022c1db2"
|
||||
integrity sha512-F9UyQBwRThwju+STz84iJy6JGWQ7UIxaprstfsGpiyS/3ror4E6m/mfwbrNjT0l3fhrhk6sRiTAMlcBRzYgdMQ==
|
||||
version "8.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@vector-im/compound-web/-/compound-web-8.2.1.tgz#e16ce566c836e6c0fa3318128e57fda0a4542514"
|
||||
integrity sha512-mqIMbBtnY3RvpCOVBhE8YouSGwU/efllJR3q4Ds1/Z/rS0/dh3Mok2frG4zRg8wdDa91VI9XHBEjeugUrpRbzw==
|
||||
dependencies:
|
||||
"@floating-ui/react" "^0.27.0"
|
||||
"@radix-ui/react-context-menu" "^2.2.1"
|
||||
@@ -4701,7 +4705,6 @@
|
||||
|
||||
"@vector-im/matrix-wysiwyg-wasm@link:../../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.39.0-a6238e517f23a2f3025d9c65445914771c63b163-integrity/node_modules/bindings/wysiwyg-wasm":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
|
||||
"@vector-im/matrix-wysiwyg@2.39.0":
|
||||
version "2.39.0"
|
||||
@@ -5160,10 +5163,10 @@ argparse@^2.0.1:
|
||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
|
||||
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
|
||||
|
||||
aria-hidden@^1.1.1:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.4.tgz#b78e383fdbc04d05762c78b4a25a501e736c4522"
|
||||
integrity sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==
|
||||
aria-hidden@^1.2.4:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.6.tgz#73051c9b088114c795b1ea414e9c0fff874ffc1a"
|
||||
integrity sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==
|
||||
dependencies:
|
||||
tslib "^2.0.0"
|
||||
|
||||
@@ -9336,13 +9339,6 @@ interpret@^3.1.1:
|
||||
resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4"
|
||||
integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==
|
||||
|
||||
invariant@^2.2.4:
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
|
||||
integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
|
||||
dependencies:
|
||||
loose-envify "^1.0.0"
|
||||
|
||||
ip-regex@^4.0.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5"
|
||||
@@ -10855,7 +10851,7 @@ long@^5.2.0:
|
||||
resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1"
|
||||
integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==
|
||||
|
||||
loose-envify@^1.0.0, loose-envify@^1.4.0:
|
||||
loose-envify@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
||||
@@ -13187,37 +13183,36 @@ react-redux@^7.2.0:
|
||||
prop-types "^15.7.2"
|
||||
react-is "^17.0.2"
|
||||
|
||||
react-remove-scroll-bar@^2.3.6:
|
||||
version "2.3.6"
|
||||
resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz#3e585e9d163be84a010180b18721e851ac81a29c"
|
||||
integrity sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==
|
||||
react-remove-scroll-bar@^2.3.7:
|
||||
version "2.3.8"
|
||||
resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz#99c20f908ee467b385b68a3469b4a3e750012223"
|
||||
integrity sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==
|
||||
dependencies:
|
||||
react-style-singleton "^2.2.1"
|
||||
react-style-singleton "^2.2.2"
|
||||
tslib "^2.0.0"
|
||||
|
||||
react-remove-scroll@2.6.0:
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.6.0.tgz#fb03a0845d7768a4f1519a99fdb84983b793dc07"
|
||||
integrity sha512-I2U4JVEsQenxDAKaVa3VZ/JeJZe0/2DxPWL8Tj8yLKctQJQiZM52pn/GWFpSp8dftjM3pSAHVJZscAnC/y+ySQ==
|
||||
react-remove-scroll@^2.6.3:
|
||||
version "2.7.1"
|
||||
resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz#d2101d414f6d81d7d3bf033f3c1cb4785789f753"
|
||||
integrity sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==
|
||||
dependencies:
|
||||
react-remove-scroll-bar "^2.3.6"
|
||||
react-style-singleton "^2.2.1"
|
||||
react-remove-scroll-bar "^2.3.7"
|
||||
react-style-singleton "^2.2.3"
|
||||
tslib "^2.1.0"
|
||||
use-callback-ref "^1.3.0"
|
||||
use-sidecar "^1.1.2"
|
||||
use-callback-ref "^1.3.3"
|
||||
use-sidecar "^1.1.3"
|
||||
|
||||
react-string-replace@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/react-string-replace/-/react-string-replace-1.1.1.tgz#8413a598c60e397fe77df3464f2889f00ba25989"
|
||||
integrity sha512-26TUbLzLfHQ5jO5N7y3Mx88eeKo0Ml0UjCQuX4BMfOd/JX+enQqlKpL1CZnmjeBRvQE8TR+ds9j1rqx9CxhKHQ==
|
||||
|
||||
react-style-singleton@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.1.tgz#f99e420492b2d8f34d38308ff660b60d0b1205b4"
|
||||
integrity sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==
|
||||
react-style-singleton@^2.2.2, react-style-singleton@^2.2.3:
|
||||
version "2.2.3"
|
||||
resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.3.tgz#4265608be69a4d70cfe3047f2c6c88b2c3ace388"
|
||||
integrity sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==
|
||||
dependencies:
|
||||
get-nonce "^1.0.0"
|
||||
invariant "^2.2.4"
|
||||
tslib "^2.0.0"
|
||||
|
||||
react-transition-group@^4.4.1:
|
||||
@@ -15270,13 +15265,6 @@ url@^0.11.4:
|
||||
punycode "^1.4.1"
|
||||
qs "^6.12.3"
|
||||
|
||||
use-callback-ref@^1.3.0:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.2.tgz#6134c7f6ff76e2be0b56c809b17a650c942b1693"
|
||||
integrity sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==
|
||||
dependencies:
|
||||
tslib "^2.0.0"
|
||||
|
||||
use-callback-ref@^1.3.3:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.3.tgz#98d9fab067075841c5b2c6852090d5d0feabe2bf"
|
||||
@@ -15289,7 +15277,7 @@ use-memo-one@^1.1.1:
|
||||
resolved "https://registry.yarnpkg.com/use-memo-one/-/use-memo-one-1.1.3.tgz#2fd2e43a2169eabc7496960ace8c79efef975e99"
|
||||
integrity sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==
|
||||
|
||||
use-sidecar@^1.1.2, use-sidecar@^1.1.3:
|
||||
use-sidecar@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.3.tgz#10e7fd897d130b896e2c546c63a5e8233d00efdb"
|
||||
integrity sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==
|
||||
@@ -15376,9 +15364,9 @@ vary@^1.1.2, vary@~1.1.2:
|
||||
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
|
||||
|
||||
vaul@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/vaul/-/vaul-1.1.0.tgz#7da4bc965e0b184ada632f1208096b0f5575d920"
|
||||
integrity sha512-YhO/bikcauk48hzhMhvIvT+U87cuCbNbKk9fF4Ou5UkI9t2KkBMernmdP37pCzF15hrv55fcny1YhexK8h6GVQ==
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/vaul/-/vaul-1.1.2.tgz#c959f8b9dc2ed4f7d99366caee433fbef91f5ba9"
|
||||
integrity sha512-ZFkClGpWyI2WUQjdLJ/BaGuV6AVQiJ3uELGk3OYtP+B6yCO7Cmn9vPFXVJkRaGkOJu3m8bQMgtyzNHixULceQA==
|
||||
dependencies:
|
||||
"@radix-ui/react-dialog" "^1.1.1"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user