Merge branch 'langleyd/history-visibililty-ux' of https://github.com/element-hq/element-web into langleyd/history-visibililty-ux

This commit is contained in:
David Langley 2025-12-01 20:53:57 +00:00
commit b484fc83a7
97 changed files with 616 additions and 172 deletions

View File

@ -70,7 +70,6 @@
},
"resolutions": {
"**/pretty-format/react-is": "19.2.0",
"@playwright/test": "1.56.1",
"@types/react": "19.2.6",
"@types/react-dom": "19.2.3",
"oidc-client-ts": "3.4.1",
@ -185,7 +184,7 @@
"@element-hq/element-call-embedded": "0.16.1",
"@element-hq/element-web-playwright-common": "^2.0.0",
"@peculiar/webcrypto": "^1.4.3",
"@playwright/test": "^1.50.1",
"@playwright/test": "1.57.0",
"@principalstudio/html-webpack-inject-preload": "^1.2.7",
"@sentry/webpack-plugin": "^4.0.0",
"@storybook/react-vite": "^10.0.7",

View File

@ -45,6 +45,9 @@
"test:storybook:ci": "concurrently -k -s first -n \"SB,TEST\" \"yarn storybook --no-open\" \"wait-on tcp:6007 && yarn test-storybook --url http://localhost:6007/ --ci --maxWorkers=2\"",
"test:storybook:update": "playwright-screenshots --entrypoint yarn --with-node-modules && playwright-screenshots --entrypoint /work/node_modules/.bin/test-storybook --with-node-modules --url http://host.docker.internal:6007/ --updateSnapshot"
},
"resolutions": {
"playwright": "1.57.0"
},
"dependencies": {
"@vector-im/compound-design-tokens": "^6.3.0",
"classnames": "^2.5.1",
@ -57,7 +60,7 @@
},
"devDependencies": {
"@element-hq/element-web-playwright-common": "^2.0.0",
"@playwright/test": "^1.50.1",
"@playwright/test": "1.57.0",
"@storybook/addon-a11y": "^10.0.7",
"@storybook/addon-designs": "^11.0.1",
"@storybook/addon-docs": "^10.0.7",

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

@ -65,3 +65,9 @@ export const WithAvatarImage: Story = {
avatar: <img alt="Example" src="https://picsum.photos/32/32" />,
},
};
export const WithoutClose: Story = {
args: {
onClose: undefined,
},
};

View File

@ -41,7 +41,7 @@ interface BannerProps {
/**
* Called when the user presses the "dismiss" button.
*/
onClose: MouseEventHandler<HTMLButtonElement>;
onClose?: MouseEventHandler<HTMLButtonElement>;
}
/**
@ -82,9 +82,11 @@ export function Banner({
<span className={styles.content}>{children}</span>
<div className={styles.actions}>
{actions}
<Button kind="secondary" size="sm" onClick={onClose}>
{_t("action|dismiss")}
</Button>
{onClose && (
<Button kind="secondary" size="sm" onClick={onClose}>
{_t("action|dismiss")}
</Button>
)}
</div>
</div>
);

View File

@ -1046,12 +1046,12 @@
resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.9.tgz#d229a7b7f9dac167a156992ef23c7f023653f53b"
integrity sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==
"@playwright/test@^1.50.1":
version "1.56.1"
resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.56.1.tgz#6e3bf3d0c90c5cf94bf64bdb56fd15a805c8bd3f"
integrity sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==
"@playwright/test@1.57.0":
version "1.57.0"
resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.57.0.tgz#a14720ffa9ed7ef7edbc1f60784fc6134acbb003"
integrity sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==
dependencies:
playwright "1.56.1"
playwright "1.57.0"
"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
version "1.1.2"
@ -5771,31 +5771,17 @@ pkg-types@^2.3.0:
exsolve "^1.0.7"
pathe "^2.0.3"
playwright-core@1.56.0, playwright-core@>=1.2.0:
version "1.56.0"
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.56.0.tgz#14b40ea436551b0bcefe19c5bfb8d1804c83739c"
integrity sha512-1SXl7pMfemAMSDn5rkPeZljxOCYAmQnYLBTExuh6E8USHXGSX3dx6lYZN/xPpTz1vimXmPA9CDnILvmJaB8aSQ==
playwright-core@1.57.0, playwright-core@>=1.2.0:
version "1.57.0"
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.57.0.tgz#3dcc9a865af256fa9f0af0d67fc8dd54eecaebf5"
integrity sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==
playwright-core@1.56.1:
version "1.56.1"
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.56.1.tgz#24a66481e5cd33a045632230aa2c4f0cb6b1db3d"
integrity sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==
playwright@1.56.1:
version "1.56.1"
resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.56.1.tgz#62e3b99ddebed0d475e5936a152c88e68be55fbf"
integrity sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==
playwright@1.57.0, playwright@^1.14.0:
version "1.57.0"
resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.57.0.tgz#74d1dacff5048dc40bf4676940b1901e18ad0f46"
integrity sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==
dependencies:
playwright-core "1.56.1"
optionalDependencies:
fsevents "2.3.2"
playwright@^1.14.0:
version "1.56.0"
resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.56.0.tgz#71c533c61da33e95812f8c6fa53960e073548d9a"
integrity sha512-X5Q1b8lOdWIE4KAoHpW3SE8HvUB+ZZsUoN64ZhjnN8dOb1UpujxBtENGiZFE+9F/yhzJwYa+ca3u43FeLbboHA==
dependencies:
playwright-core "1.56.0"
playwright-core "1.57.0"
optionalDependencies:
fsevents "2.3.2"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 990 KiB

After

Width:  |  Height:  |  Size: 984 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@ -36,6 +36,8 @@ Please see LICENSE files in the repository root for full details.
/* align with settings icon */
margin-left: 21px;
margin-right: 8px;
width: 100%;
/**
* modify internal css of the compound component
@ -50,7 +52,8 @@ Please see LICENSE files in the repository root for full details.
/* align with settings label */
margin-right: 14px;
/* required to set the icon width when into a flex container */
min-width: 24px;
width: 24px;
flex-shrink: 0;
}
& .mx_QuickSettingsButton_label {

View File

@ -457,7 +457,7 @@ Please see LICENSE files in the repository root for full details.
}
.mx_SpacePanel_iconPreferences::before {
mask-image: url("$(res)/img/element-icons/settings/preference.svg");
mask-image: url("@vector-im/compound-design-tokens/icons/preferences.svg");
}
.mx_SpacePanel_noIcon {

View File

@ -23,6 +23,8 @@
/* align with settings icon */
margin-left: 21px;
margin-right: 8px;
width: 100%;
/**
* modify internal css of the compound component
@ -31,13 +33,20 @@
& > div {
display: flex;
align-items: center;
&::before {
inline-size: 8px;
block-size: 8px;
left: 17px;
}
}
& .mx_ThreadsActivityCentreButton_Icon {
/* align with settings label */
margin-right: 14px;
/* required to set the icon width when into a flex container */
min-width: 24px;
width: 24px;
flex-shrink: 0;
}
& .mx_ThreadsActivityCentreButton_Text {

View File

@ -40,7 +40,7 @@ Please see LICENSE files in the repository root for full details.
mask-repeat: no-repeat;
mask-position: center;
background-color: $muted-fg-color;
mask-image: url("$(res)/img/element-icons/upload.svg");
mask-image: url("@vector-im/compound-design-tokens/icons/share.svg");
}
}

View File

@ -156,7 +156,7 @@ Please see LICENSE files in the repository root for full details.
}
.mx_IconizedContextMenu_developerTools::before {
mask-image: url("$(res)/img/element-icons/settings/flask.svg");
mask-image: url("@vector-im/compound-design-tokens/icons/labs.svg");
}
.mx_IconizedContextMenu_checked::before {

View File

@ -41,7 +41,7 @@ Please see LICENSE files in the repository root for full details.
}
.mx_MessageContextMenu_iconUnhidePreview::before {
mask-image: url("$(res)/img/element-icons/settings/appearance.svg");
mask-image: url("@vector-im/compound-design-tokens/icons/visibility-on.svg");
}
.mx_MessageContextMenu_iconOpenInMapSite::before {
@ -88,7 +88,7 @@ Please see LICENSE files in the repository root for full details.
}
.mx_MessageContextMenu_iconEdit::before {
mask-image: url("$(res)/img/element-icons/room/message-bar/edit.svg");
mask-image: url("@vector-im/compound-design-tokens/icons/edit.svg");
}
.mx_MessageContextMenu_iconReply::before {
@ -100,7 +100,7 @@ Please see LICENSE files in the repository root for full details.
}
.mx_MessageContextMenu_iconReact::before {
mask-image: url("$(res)/img/element-icons/room/message-bar/emoji.svg");
mask-image: url("@vector-im/compound-design-tokens/icons/reaction-add.svg");
}
.mx_MessageContextMenu_iconViewInRoom::before {

View File

@ -34,7 +34,7 @@ Please see LICENSE files in the repository root for full details.
}
.mx_RoomSettingsDialog_pollsIcon::before {
mask-image: url("$(res)/img/element-icons/room/composer/poll.svg");
mask-image: url("@vector-im/compound-design-tokens/icons/polls.svg");
}
.mx_RoomSettingsDialog_warningIcon::before {

View File

@ -28,5 +28,5 @@ Please see LICENSE files in the repository root for full details.
}
.mx_SpacePreferencesDialog_appearanceIcon::before {
mask-image: url("$(res)/img/element-icons/settings/appearance.svg");
mask-image: url("@vector-im/compound-design-tokens/icons/visibility-on.svg");
}

View File

@ -45,10 +45,10 @@ Please see LICENSE files in the repository root for full details.
mask-repeat: no-repeat;
mask-position: center;
mask-size: cover;
mask-image: url("$(res)/img/element-icons/room/composer/attach.svg");
mask-image: url("@vector-im/compound-design-tokens/icons/attachment.svg");
background-color: $secondary-content;
width: 15px;
height: 15px;
width: 16px;
height: 16px;
position: absolute;
top: 8px;

View File

@ -41,7 +41,7 @@ Please see LICENSE files in the repository root for full details.
mask-repeat: no-repeat;
mask-size: contain;
mask-position: center;
mask-image: url("$(res)/img/element-icons/room/composer/poll.svg");
mask-image: url("@vector-im/compound-design-tokens/icons/polls.svg");
}
.mx_MPollBody_totalVotes {

View File

@ -27,7 +27,7 @@ Please see LICENSE files in the repository root for full details.
mask-repeat: no-repeat;
mask-position: center;
background-color: $tertiary-content;
mask-image: url("$(res)/img/element-icons/room/message-bar/emoji.svg");
mask-image: url("@vector-im/compound-design-tokens/icons/reaction-add.svg");
}
&.mx_ReactionsRow_addReactionButton_active {

View File

@ -15,7 +15,7 @@ Please see LICENSE files in the repository root for full details.
}
.mx_EmojiButton_icon::before {
mask-image: url("$(res)/img/element-icons/room/composer/emoji.svg");
mask-image: url("@vector-im/compound-design-tokens/icons/reaction.svg");
}
.mx_MessageComposer_wysiwyg {

View File

@ -245,11 +245,11 @@ Please see LICENSE files in the repository root for full details.
}
.mx_MessageComposer_upload::before {
mask-image: url("$(res)/img/element-icons/room/composer/attach.svg");
mask-image: url("@vector-im/compound-design-tokens/icons/attachment.svg");
}
.mx_MessageComposer_poll::before {
mask-image: url("$(res)/img/element-icons/room/composer/poll.svg");
mask-image: url("@vector-im/compound-design-tokens/icons/polls.svg");
}
.mx_MessageComposer_voiceMessage::before {
@ -257,7 +257,7 @@ Please see LICENSE files in the repository root for full details.
}
.mx_MessageComposer_plain_text::before {
mask-image: url("$(res)/img/element-icons/room/composer/plain_text.svg");
mask-image: url("@vector-im/compound-design-tokens/icons/text-formatting.svg");
}
.mx_MessageComposer_rich_text::before {
@ -274,7 +274,6 @@ Please see LICENSE files in the repository root for full details.
.mx_MessageComposer_buttonMenu::before {
mask-image: url("@vector-im/compound-design-tokens/icons/overflow-horizontal.svg");
mask-size: 24px;
}
.mx_MessageComposer_sendMessage {

View File

@ -1,3 +0,0 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M15.8155 13.0336L11.2282 17.4193C9.08205 19.45 5.53015 19.6024 3.45617 17.4193C1.4888 15.3484 1.48412 12.0136 3.63032 9.98294L11.8691 2.10597C13.2999 0.752226 15.5435 0.535035 16.984 2.05147C18.5968 3.7491 18.1298 5.99061 16.699 7.34435L8.6284 14.9682C7.913 15.645 6.7551 15.7233 6.03771 14.9682C5.34842 14.2426 5.45967 13.0625 6.17507 12.3856L10.9045 7.86398" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 554 B

View File

@ -1,7 +0,0 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="path-1-inside-1" fill="white">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10 20C15.5228 20 20 15.5228 20 10C20 4.47715 15.5228 0 10 0C4.47715 0 0 4.47715 0 10C0 15.5228 4.47715 20 10 20ZM7.99989 7.5C7.99989 8.33 7.32989 9 6.49989 9C5.66989 9 4.99989 8.33 4.99989 7.5C4.99989 6.67 5.66989 6 6.49989 6C7.32989 6 7.99989 6.67 7.99989 7.5ZM14.9999 7.5C14.9999 8.33 14.3299 9 13.4999 9C12.6699 9 11.9999 8.33 11.9999 7.5C11.9999 6.67 12.6699 6 13.4999 6C14.3299 6 14.9999 6.67 14.9999 7.5ZM9.99989 15.5C12.3299 15.5 14.3099 14.04 15.1099 12H4.88989C5.68989 14.04 7.66989 15.5 9.99989 15.5Z"/>
</mask>
<path fill-rule="evenodd" clip-rule="evenodd" d="M10 20C15.5228 20 20 15.5228 20 10C20 4.47715 15.5228 0 10 0C4.47715 0 0 4.47715 0 10C0 15.5228 4.47715 20 10 20ZM7.99989 7.5C7.99989 8.33 7.32989 9 6.49989 9C5.66989 9 4.99989 8.33 4.99989 7.5C4.99989 6.67 5.66989 6 6.49989 6C7.32989 6 7.99989 6.67 7.99989 7.5ZM14.9999 7.5C14.9999 8.33 14.3299 9 13.4999 9C12.6699 9 11.9999 8.33 11.9999 7.5C11.9999 6.67 12.6699 6 13.4999 6C14.3299 6 14.9999 6.67 14.9999 7.5ZM9.99989 15.5C12.3299 15.5 14.3099 14.04 15.1099 12H4.88989C5.68989 14.04 7.66989 15.5 9.99989 15.5Z" fill="#737D8C"/>
<path d="M15.1099 12L16.0384 12.3641L16.5724 11.0026H15.1099V12ZM4.88989 12V11.0026H3.42744L3.96136 12.3641L4.88989 12ZM19.0026 10C19.0026 14.972 14.972 19.0026 10 19.0026V20.9974C16.0737 20.9974 20.9974 16.0737 20.9974 10H19.0026ZM10 0.997378C14.972 0.997378 19.0026 5.02799 19.0026 10H20.9974C20.9974 3.92632 16.0737 -0.997378 10 -0.997378V0.997378ZM0.997378 10C0.997378 5.02799 5.02799 0.997378 10 0.997378V-0.997378C3.92632 -0.997378 -0.997378 3.92632 -0.997378 10H0.997378ZM10 19.0026C5.02799 19.0026 0.997378 14.972 0.997378 10H-0.997378C-0.997378 16.0737 3.92632 20.9974 10 20.9974V19.0026ZM6.49989 9.99738C7.88073 9.99738 8.99727 8.88084 8.99727 7.5H7.00251C7.00251 7.77916 6.77906 8.00262 6.49989 8.00262V9.99738ZM4.00251 7.5C4.00251 8.88084 5.11906 9.99738 6.49989 9.99738V8.00262C6.22073 8.00262 5.99727 7.77916 5.99727 7.5H4.00251ZM6.49989 5.00262C5.11906 5.00262 4.00251 6.11916 4.00251 7.5H5.99727C5.99727 7.22084 6.22073 6.99738 6.49989 6.99738V5.00262ZM8.99727 7.5C8.99727 6.11916 7.88073 5.00262 6.49989 5.00262V6.99738C6.77906 6.99738 7.00251 7.22084 7.00251 7.5H8.99727ZM13.4999 9.99738C14.8807 9.99738 15.9973 8.88084 15.9973 7.5H14.0025C14.0025 7.77916 13.7791 8.00262 13.4999 8.00262V9.99738ZM11.0025 7.5C11.0025 8.88084 12.1191 9.99738 13.4999 9.99738V8.00262C13.2207 8.00262 12.9973 7.77916 12.9973 7.5H11.0025ZM13.4999 5.00262C12.1191 5.00262 11.0025 6.11916 11.0025 7.5H12.9973C12.9973 7.22084 13.2207 6.99738 13.4999 6.99738V5.00262ZM15.9973 7.5C15.9973 6.11916 14.8807 5.00262 13.4999 5.00262V6.99738C13.7791 6.99738 14.0025 7.22084 14.0025 7.5H15.9973ZM14.1814 11.6359C13.5241 13.3119 11.9006 14.5026 9.99989 14.5026V16.4974C12.7592 16.4974 15.0957 14.7681 16.0384 12.3641L14.1814 11.6359ZM4.88989 12.9974H15.1099V11.0026H4.88989V12.9974ZM9.99989 14.5026C8.09919 14.5026 6.47569 13.3119 5.81842 11.6359L3.96136 12.3641C4.9041 14.7681 7.24059 16.4974 9.99989 16.4974V14.5026Z" fill="#737D8C" mask="url(#path-1-inside-1)"/>
</svg>

Before

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_2168_154906)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.5467 15.8667L13.6667 13.7333H7.00005L6.13338 15.8667C5.93338 16.3467 5.46672 16.6667 4.94672 16.6667C4.02672 16.6667 3.40005 15.72 3.76005 14.88L5.00323 12.0059H15.6635L16.9067 14.88C17.2667 15.72 16.6534 16.6667 15.7334 16.6667C15.2134 16.6667 14.7467 16.3467 14.5467 15.8667ZM13.6435 7.33594L11.7334 2.92C11.4934 2.36 10.9467 2 10.3334 2C9.72005 2 9.17338 2.36 8.93338 2.92L7.02326 7.33594H9.32912L10.3334 4.64L11.3376 7.33594H13.6435Z" fill="currentColor"/>
<path d="M1 9.67708C1 10.4104 1.6 11.0104 2.33333 11.0104H18.3333C19.0667 11.0104 19.6667 10.4104 19.6667 9.67708C19.6667 8.94375 19.0667 8.34375 18.3333 8.34375H2.33333C1.6 8.34375 1 8.94375 1 9.67708Z" fill="currentColor"/>
</g>
<defs>
<clipPath id="clip0_2168_154906">
<rect width="20" height="20" fill="white"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,5 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3 9.5C3 9.22386 3.22386 9 3.5 9H6.5C6.77614 9 7 9.22386 7 9.5V22H3V9.5Z" fill="currentColor"/>
<path d="M17 13.5C17 13.2239 17.2239 13 17.5 13H20.5C20.7761 13 21 13.2239 21 13.5V22H17V13.5Z" fill="currentColor"/>
<path d="M10 2.5C10 2.22386 10.2239 2 10.5 2H13.5C13.7761 2 14 2.22386 14 2.5V22H10V2.5Z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 438 B

View File

@ -1,4 +0,0 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3 14L15 14" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5 10.5L12 3.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 330 B

View File

@ -1,3 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M20 1C19.4477 1 19 1.44772 19 2V4H17C16.4477 4 16 4.44771 16 5C16 5.55228 16.4477 6 17 6H19V8C19 8.55228 19.4477 9 20 9C20.5523 9 21 8.55228 21 8V6H23C23.5523 6 24 5.55228 24 5C24 4.44772 23.5523 4 23 4H21V2C21 1.44772 20.5523 1 20 1ZM7 9.5C7 8.67 7.67 8 8.5 8C9.33 8 10 8.67 10 9.5C10 10.33 9.33 11 8.5 11C7.67 11 7 10.33 7 9.5ZM15.5 11C16.33 11 17 10.33 17 9.5C17 8.67 16.33 8 15.5 8C14.67 8 14 8.67 14 9.5C14 10.33 14.67 11 15.5 11ZM12 17.5C14.33 17.5 16.31 16.04 17.11 14H6.89001C7.69001 16.04 9.67001 17.5 12 17.5ZM4 12C4 7.58172 7.58172 4 12 4C12.6108 4 13.2045 4.06827 13.7742 4.1972C14.3129 4.3191 14.8484 3.98125 14.9703 3.44258C15.0922 2.90392 14.7543 2.36843 14.2156 2.24653C13.502 2.08504 12.7603 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 11.7878 21.9934 11.5771 21.9803 11.368C21.9459 10.8168 21.4711 10.3978 20.9199 10.4323C20.3687 10.4667 19.9498 10.9414 19.9842 11.4926C19.9947 11.6603 20 11.8295 20 12C20 16.4183 16.4183 20 12 20C7.58172 20 4 16.4183 4 12Z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="21.87" height="20.801"><path fill="currentColor" d="m4.178 20.801 6.758-4.91 6.756 4.91-2.58-7.946 6.758-4.91h-8.352L10.936 0 8.354 7.945H0l6.758 4.91-2.58 7.946z"/></svg>

Before

Width:  |  Height:  |  Size: 220 B

View File

@ -1,3 +0,0 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.2962 6.95039C17.2815 8.16305 17.3023 9.84863 16.3296 11.0714C14.9497 12.806 12.5144 15 9.02365 15C5.5329 15 3.09759 12.806 1.71772 11.0714C0.744983 9.84863 0.765783 8.16305 1.75111 6.95039C3.16323 5.21247 5.6278 3 9.02365 3C12.4195 3 14.8841 5.21247 16.2962 6.95039ZM13 9C13 11.2091 11.2091 13 9 13C6.79086 13 5 11.2091 5 9C5 6.79086 6.79086 5 9 5C11.2091 5 13 6.79086 13 9ZM9 11C10.1046 11 11 10.1046 11 9C11 7.89543 10.1046 7 9 7C7.89543 7 7 7.89543 7 9C7 10.1046 7.89543 11 9 11Z" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 655 B

View File

@ -1,3 +0,0 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.5 3C7.32843 3 8 2.32843 8 1.5C8 0.671573 7.32843 0 6.5 0C5.67157 0 5 0.671573 5 1.5C5 2.32843 5.67157 3 6.5 3ZM15.2041 14.7404L11.598 8.73148L11.624 6.96296H12.1176C12.2554 6.96296 12.3876 6.91224 12.485 6.82194C12.5825 6.73164 12.6372 6.60918 12.6372 6.48148C12.6372 6.35378 12.5825 6.23132 12.485 6.14102C12.3876 6.05073 12.2554 6 12.1176 6H5.88237C5.74456 6 5.6124 6.05073 5.51495 6.14102C5.41751 6.23132 5.36277 6.35378 5.36277 6.48148C5.36277 6.60918 5.41751 6.73164 5.51495 6.82194C5.6124 6.91224 5.74456 6.96296 5.88237 6.96296H6.376L6.40198 8.73148L2.79592 14.7404C2.59646 15.0747 2.49454 15.4515 2.50023 15.8335C2.50591 16.2155 2.619 16.5895 2.82833 16.9186C3.03766 17.2477 3.336 17.5206 3.69389 17.7102C4.05179 17.8999 4.45686 17.9997 4.86914 18H13.1309C13.5431 17.9997 13.9482 17.8999 14.3061 17.7102C14.664 17.5206 14.9623 17.2477 15.1717 16.9186C15.381 16.5895 15.4941 16.2155 15.4998 15.8335C15.5055 15.4515 15.4035 15.0747 15.2041 14.7404ZM7.37364 9.08778C7.41831 9.01432 7.44159 8.93136 7.44118 8.84704L7.4152 6.96296H10.5848L10.5588 8.84704C10.5584 8.93136 10.5817 9.01432 10.6264 9.08778L12.4814 12.1837C11.4354 12.1572 10.3977 12.0034 9.3949 11.7263C8.31816 11.4355 7.20603 11.2721 6.08502 11.24L7.37364 9.08778ZM13 3.5C13 4.32843 12.3284 5 11.5 5C10.6716 5 10 4.32843 10 3.5C10 2.67157 10.6716 2 11.5 2C12.3284 2 13 2.67157 13 3.5Z" fill="#737D8C"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,3 +0,0 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6 4C3.23858 4 1 6.23858 1 9C1 11.7614 3.23858 14 6 14H12C14.7614 14 17 11.7614 17 9C17 6.23858 14.7614 4 12 4H6ZM9 9C9 10.6569 7.65685 12 6 12C4.34315 12 3 10.6569 3 9C3 7.34315 4.34315 6 6 6C7.65685 6 9 7.34315 9 9Z" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 386 B

View File

@ -1,4 +0,0 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.99902 14L8.99902 4" stroke="black" stroke-width="1.5" stroke-linecap="round"/>
<path d="M12.5352 7.52441L8.99944 4.00012L5.46373 7.52441" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 336 B

View File

@ -140,7 +140,7 @@ const IMAGE_THUMBNAIL_MIN_REDUCTION_PERCENT = 0.1; // 10%
// and videos tend to be much larger.
// Image mime types for which to always include a thumbnail for even if it is larger than the input for wider support.
const ALWAYS_INCLUDE_THUMBNAIL = ["image/avif", "image/webp"];
const ALWAYS_INCLUDE_THUMBNAIL = ["image/avif", "image/webp", "image/svg+xml"];
/**
* Read the metadata for an image file and create and upload a thumbnail of the image.

View File

@ -11,7 +11,6 @@ import React, { type JSX } from "react";
import { FilesIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import { _t } from "../../../languageHandler";
import { getBlobSafeMimeType } from "../../../utils/blobs";
import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
import { fileSize } from "../../../utils/FileUtils";
@ -23,10 +22,11 @@ interface IProps {
onFinished: (uploadConfirmed: boolean, uploadAll?: boolean) => void;
}
export default class UploadConfirmDialog extends React.Component<IProps> {
private readonly objectUrl: string;
private readonly mimeType: string;
interface IState {
objectUrl?: string;
}
export default class UploadConfirmDialog extends React.Component<IProps, IState> {
public static defaultProps: Partial<IProps> = {
totalFiles: 1,
currentIndex: 0,
@ -35,15 +35,22 @@ export default class UploadConfirmDialog extends React.Component<IProps> {
public constructor(props: IProps) {
super(props);
// Create a fresh `Blob` for previewing (even though `File` already is
// one) so we can adjust the MIME type if needed.
this.mimeType = getBlobSafeMimeType(props.file.type);
const blob = new Blob([props.file], { type: this.mimeType });
this.objectUrl = URL.createObjectURL(blob);
this.state = {};
}
public componentDidMount(): void {
if (this.props.file.type.startsWith("image/") || this.props.file.type.startsWith("video/")) {
this.setState({
// We do not filter the mimetype using getBlobSafeMimeType here as if the user is uploading the file
// themselves they should be trusting it enough to open/load it, and it will be rendered into a hidden
// canvas for thumbnail generation anyway
objectUrl: URL.createObjectURL(this.props.file),
});
}
}
public componentWillUnmount(): void {
if (this.objectUrl) URL.revokeObjectURL(this.objectUrl);
if (this.state.objectUrl) URL.revokeObjectURL(this.state.objectUrl);
}
private onCancelClick = (): void => {
@ -70,17 +77,23 @@ export default class UploadConfirmDialog extends React.Component<IProps> {
}
const fileId = `mx-uploadconfirmdialog-${this.props.file.name}`;
const mimeType = this.props.file.type;
let preview: JSX.Element | undefined;
let placeholder: JSX.Element | undefined;
if (this.mimeType.startsWith("image/")) {
if (mimeType.startsWith("image/")) {
preview = (
<img className="mx_UploadConfirmDialog_imagePreview" src={this.objectUrl} aria-labelledby={fileId} />
<img
className="mx_UploadConfirmDialog_imagePreview"
src={this.state.objectUrl}
aria-labelledby={fileId}
/>
);
} else if (this.mimeType.startsWith("video/")) {
} else if (mimeType.startsWith("video/")) {
preview = (
<video
className="mx_UploadConfirmDialog_imagePreview"
src={this.objectUrl}
src={this.state.objectUrl}
playsInline
controls={false}
/>

View File

@ -35,6 +35,7 @@ import MediaProcessingError from "./shared/MediaProcessingError";
import { DecryptError, DownloadError } from "../../../utils/DecryptFile";
import { HiddenMediaPlaceholder } from "./HiddenMediaPlaceholder";
import { useMediaVisible } from "../../../hooks/useMediaVisible";
import { isMimeTypeAllowed } from "../../../utils/blobs.ts";
enum Placeholder {
NoImage,
@ -101,7 +102,16 @@ export class MImageBodyInner extends React.Component<IProps, IState> {
}
const content = this.props.mxEvent.getContent<ImageContent>();
const httpUrl = this.state.contentUrl;
let httpUrl = this.state.contentUrl;
if (
this.props.mediaEventHelper?.media.isEncrypted &&
!isMimeTypeAllowed(this.props.mediaEventHelper.sourceBlob.cachedValue?.type ?? "")
) {
// contentUrl will be a blob URI mime-type=application/octet-stream so fall back to the thumbUrl instead
httpUrl = this.state.thumbUrl;
}
if (!httpUrl) return;
const params: Omit<ComponentProps<typeof ImageView>, "onFinished"> = {
src: httpUrl,
@ -647,6 +657,15 @@ export class MImageBodyInner extends React.Component<IProps, IState> {
public render(): React.ReactNode {
const content = this.props.mxEvent.getContent<ImageContent>();
// Fall back to MFileBody if we are unable to render this image e.g. in the case of a blob svg
if (
this.props.mediaEventHelper?.media.isEncrypted &&
!isMimeTypeAllowed(content.info?.mimetype ?? "") &&
!content.info?.thumbnail_info
) {
return <MFileBody {...this.props} />;
}
if (this.state.error) {
let errorText = _t("timeline|m.image|error");
if (this.state.error instanceof DecryptError) {

View File

@ -9,8 +9,8 @@ Please see LICENSE files in the repository root for full details.
import React, { useEffect, useState, useContext, type JSX } from "react";
import { MatrixEvent, M_TEXT } from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger";
import { PollsEndIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import { Icon as PollIcon } from "../../../../res/img/element-icons/room/composer/poll.svg";
import MatrixClientContext, { useMatrixClientContext } from "../../../contexts/MatrixClientContext";
import { _t } from "../../../languageHandler";
import { textForEvent } from "../../../TextForEvent";
@ -93,7 +93,7 @@ export const MPollEndBody = ({ mxEvent, ref, ...props }: IBodyProps): JSX.Elemen
const pollEndFallbackMessage = M_TEXT.findIn<string>(mxEvent.getContent()) || textForEvent(mxEvent, cli);
return (
<>
<PollIcon className="mx_MPollEndBody_icon" />
<PollsEndIcon className="mx_MPollEndBody_icon" />
{!isLoadingPollStartEvent && pollEndFallbackMessage}
</>
);

View File

@ -30,10 +30,10 @@ import {
DeleteIcon,
RestartIcon,
ThreadsIcon,
EditIcon,
ReactionAddIcon,
} from "@vector-im/compound-design-tokens/assets/web/icons";
import { Icon as EditIcon } from "../../../../res/img/element-icons/room/message-bar/edit.svg";
import { Icon as EmojiIcon } from "../../../../res/img/element-icons/room/message-bar/emoji.svg";
import { Icon as ExpandMessageIcon } from "../../../../res/img/element-icons/expand-message.svg";
import { Icon as CollapseMessageIcon } from "../../../../res/img/element-icons/collapse-message.svg";
import { _t } from "../../../languageHandler";
@ -190,7 +190,7 @@ const ReactButton: React.FC<IReactButtonProps> = ({ mxEvent, reactions, onFocusC
tabIndex={isActive ? 0 : -1}
placement="left"
>
<EmojiIcon />
<ReactionAddIcon />
</ContextMenuTooltipButton>
{contextMenu}

View File

@ -10,8 +10,8 @@ import React from "react";
import { type PollStartEvent } from "matrix-js-sdk/src/extensible_events_v1/PollStartEvent";
import { type MatrixEvent } from "matrix-js-sdk/src/matrix";
import { Tooltip } from "@vector-im/compound-web";
import { PollsIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import { Icon as PollIcon } from "../../../../../res/img/element-icons/room/composer/poll.svg";
import { formatLocalDateShort } from "../../../../DateUtils";
import { _t } from "../../../../languageHandler";
@ -31,7 +31,7 @@ export const PollListItem: React.FC<Props> = ({ event, onClick }) => {
<Tooltip label={_t("right_panel|poll|view_poll")} placement="top" isTriggerInteractive={false}>
<div className="mx_PollListItem_content">
<span>{formattedDate}</span>
<PollIcon className="mx_PollListItem_icon" />
<PollsIcon className="mx_PollListItem_icon" />
<span className="mx_PollListItem_question">{pollEvent.question.text}</span>
</div>
</Tooltip>

View File

@ -10,8 +10,8 @@ import React, { useEffect, useState } from "react";
import { type PollAnswerSubevent } from "matrix-js-sdk/src/extensible_events_v1/PollStartEvent";
import { type MatrixEvent, type Poll, PollEvent, type Relations } from "matrix-js-sdk/src/matrix";
import { Tooltip } from "@vector-im/compound-web";
import { PollsEndIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import { Icon as PollIcon } from "../../../../../res/img/element-icons/room/composer/poll.svg";
import { _t } from "../../../../languageHandler";
import { formatLocalDateShort } from "../../../../DateUtils";
import { allVotes, collectUserVotes, countVotes } from "../../messages/MPollBody";
@ -94,7 +94,7 @@ export const PollListItemEnded: React.FC<Props> = ({ event, poll, onClick }) =>
<Tooltip label={_t("right_panel|poll|view_poll")} placement="top" isTriggerInteractive={false}>
<div className="mx_PollListItemEnded_content">
<div className="mx_PollListItemEnded_title">
<PollIcon className="mx_PollListItemEnded_icon" />
<PollsEndIcon className="mx_PollListItemEnded_icon" />
<span className="mx_PollListItemEnded_question">{pollEvent.question.text}</span>
<Caption>{formattedDate}</Caption>
</div>

View File

@ -316,9 +316,6 @@ export default async function createRoom(client: MatrixClient, opts: IOpts): Pro
return Promise.reject(err);
}
})
.finally(function () {
if (modal) modal.close();
})
.then(async (res): Promise<void> => {
roomId = res.room_id;
@ -340,6 +337,9 @@ export default async function createRoom(client: MatrixClient, opts: IOpts): Pro
if (opts.dmUserId) await Rooms.setDMRoom(client, roomId, opts.dmUserId);
})
.finally(function () {
if (modal) modal.close();
})
.then(() => {
if (opts.parentSpace) {
return SpaceStore.instance.addRoomToSpace(

View File

@ -64,8 +64,7 @@ export async function decryptFile(file?: EncryptedFile, info?: MediaEventInfo):
// they introduce XSS attacks if the Blob URI is viewed directly in the
// browser (e.g. by copying the URI into a new tab or window.)
// See warning at top of file.
let mimetype = info?.mimetype ? info.mimetype.split(";")[0].trim() : "";
mimetype = getBlobSafeMimeType(mimetype);
const mimetype = getBlobSafeMimeType(info?.mimetype?.split(";")[0].trim() ?? "");
return new Blob([dataArray], { type: mimetype });
} catch (e) {

View File

@ -14,6 +14,7 @@ import { LazyValue } from "./LazyValue";
import { type Media, mediaFromContent } from "../customisations/Media";
import { decryptFile } from "./DecryptFile";
import { type IDestroyable } from "./IDestroyable";
import { getBlobSafeMimeType } from "./blobs.ts";
// TODO: We should consider caching the blobs. https://github.com/vector-im/element-web/issues/17192
@ -82,7 +83,7 @@ export class MediaEventHelper implements IDestroyable {
.downloadSource()
.then((r) => r.blob())
// Set the mime type from the event info on the blob
.then((blob) => blob.slice(0, blob.size, content.info?.mimetype ?? blob.type))
.then((blob) => blob.slice(0, blob.size, getBlobSafeMimeType(content.info?.mimetype ?? blob.type)))
);
};
@ -107,7 +108,9 @@ export class MediaEventHelper implements IDestroyable {
fetch(thumbnailHttp)
.then((r) => r.blob())
// Set the mime type from the event info on the blob
.then((blob) => blob.slice(0, blob.size, content.info?.thumbnail_info?.mimetype ?? blob.type))
.then((blob) =>
blob.slice(0, blob.size, getBlobSafeMimeType(content.info?.thumbnail_info?.mimetype ?? blob.type)),
)
);
};

View File

@ -66,8 +66,20 @@ const ALLOWED_BLOB_MIMETYPES = [
"audio/x-flac",
];
/**
* Checks whether the given mime type is in the allowed mimetype list
* @param mimetype - the mimetype to check
*/
export function isMimeTypeAllowed(mimetype: string): boolean {
return ALLOWED_BLOB_MIMETYPES.includes(mimetype);
}
/**
* Returns the input mimetype if it is allowed, `application/octet-stream` otherwise
* @param mimetype - the mimetype to check
*/
export function getBlobSafeMimeType(mimetype: string): string {
if (!ALLOWED_BLOB_MIMETYPES.includes(mimetype)) {
if (!isMimeTypeAllowed(mimetype)) {
return "application/octet-stream";
}
return mimetype;

View File

@ -0,0 +1,27 @@
/*
Copyright 2025 Element Creations Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import React from "react";
import { render } from "jest-matrix-react";
import { secureRandomString } from "matrix-js-sdk/src/randomstring";
import UploadConfirmDialog from "../../../../../src/components/views/dialogs/UploadConfirmDialog.tsx";
describe("<UploadConfirmDialog />", () => {
it("should display image preview", () => {
const url = "blob:null/1234-5678-9101-1121";
jest.spyOn(URL, "createObjectURL").mockReturnValue(url);
const file = new File([secureRandomString(1024 * 124)], "image.png", { type: "image/png" });
const { asFragment, getByRole } = render(
<UploadConfirmDialog file={file} currentIndex={0} totalFiles={1} onFinished={jest.fn()} />,
);
expect(getByRole("img")).toHaveAttribute("src", url);
expect(asFragment()).toMatchSnapshot();
});
});

View File

@ -0,0 +1,80 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`<UploadConfirmDialog /> should display image preview 1`] = `
<DocumentFragment>
<div
data-focus-guard="true"
style="width: 1px; height: 0px; padding: 0px; overflow: hidden; position: fixed; top: 1px; left: 1px;"
tabindex="0"
/>
<div
aria-describedby="mx_Dialog_content"
aria-labelledby="mx_BaseDialog_title"
class="mx_UploadConfirmDialog"
data-focus-lock-disabled="false"
role="dialog"
tabindex="-1"
>
<div
class="mx_Dialog_header"
>
<h1
class="mx_Heading_h3 mx_Dialog_title"
id="mx_BaseDialog_title"
>
Upload files
</h1>
</div>
<div
id="mx_Dialog_content"
>
<div
class="mx_UploadConfirmDialog_previewOuter"
>
<div
class="mx_UploadConfirmDialog_previewInner"
>
<div>
<img
aria-labelledby="mx-uploadconfirmdialog-image.png"
class="mx_UploadConfirmDialog_imagePreview"
src="blob:null/1234-5678-9101-1121"
/>
</div>
<div
id="mx-uploadconfirmdialog-image.png"
>
image.png (124 KB)
</div>
</div>
</div>
</div>
<div
class="mx_Dialog_buttons"
>
<span
class="mx_Dialog_buttons_row"
>
<button
class="mx_Dialog_primary"
data-testid="dialog-primary-button"
type="button"
>
Upload
</button>
</span>
</div>
<div
aria-label="Close dialog"
class="mx_AccessibleButton mx_Dialog_cancelButton"
role="button"
tabindex="0"
/>
</div>
<div
data-focus-guard="true"
style="width: 1px; height: 0px; padding: 0px; overflow: hidden; position: fixed; top: 1px; left: 1px;"
tabindex="0"
/>
</DocumentFragment>
`;

View File

@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
*/
import React from "react";
import { fireEvent, render, screen, waitFor, waitForElementToBeRemoved } from "jest-matrix-react";
import { fireEvent, render, screen, waitFor, waitForElementToBeRemoved, within } from "jest-matrix-react";
import { EventType, getHttpUriForMxc, MatrixEvent, Room } from "matrix-js-sdk/src/matrix";
import fetchMock from "fetch-mock-jest";
import encrypt from "matrix-encrypt-attachment";
@ -70,6 +70,7 @@ describe("<MImageBody/>", () => {
info: {
w: 40,
h: 50,
mimetype: "image/png",
},
file: {
url: "mxc://server/encrypted-image",
@ -304,4 +305,76 @@ describe("<MImageBody/>", () => {
expect(container.querySelector(".mx_MImageBody_banner")).toHaveTextContent("...alt for a test image");
});
it("should render MFileBody for svg with no thumbnail", async () => {
const event = new MatrixEvent({
room_id: "!room:server",
sender: senderUserId,
type: EventType.RoomMessage,
content: {
info: {
w: 40,
h: 50,
mimetype: "image/svg+xml",
},
file: {
url: "mxc://server/encrypted-svg",
},
},
});
const { container, asFragment } = render(
<MImageBody {...props} mxEvent={event} mediaEventHelper={new MediaEventHelper(event)} />,
withClientContextRenderOptions(cli),
);
expect(container.querySelector(".mx_MFileBody")).toHaveTextContent("Attachment");
expect(asFragment()).toMatchSnapshot();
});
it("should open ImageView using thumbnail for encrypted svg", async () => {
const url = "https://server/_matrix/media/v3/download/server/encrypted-svg";
fetchMock.getOnce(url, { status: 200 });
const thumbUrl = "https://server/_matrix/media/v3/download/server/svg-thumbnail";
fetchMock.getOnce(thumbUrl, { status: 200 });
const event = new MatrixEvent({
room_id: "!room:server",
sender: senderUserId,
type: EventType.RoomMessage,
origin_server_ts: 1234567890,
content: {
info: {
w: 40,
h: 50,
mimetype: "image/svg+xml",
thumbnail_file: {
url: "mxc://server/svg-thumbnail",
},
thumbnail_info: { mimetype: "image/png" },
},
file: {
url: "mxc://server/encrypted-svg",
},
},
});
const mediaEventHelper = new MediaEventHelper(event);
mediaEventHelper.thumbnailUrl["prom"] = Promise.resolve(thumbUrl);
mediaEventHelper.sourceUrl["prom"] = Promise.resolve(url);
const { findByRole } = render(
<MImageBody {...props} mxEvent={event} mediaEventHelper={mediaEventHelper} />,
withClientContextRenderOptions(cli),
);
fireEvent.click(await findByRole("link"));
const dialog = await screen.findByRole("dialog");
await expect(within(dialog).findByRole("img")).resolves.toHaveAttribute(
"src",
"https://server/_matrix/media/v3/download/server/svg-thumbnail",
);
expect(dialog).toMatchSnapshot();
});
});

View File

@ -47,6 +47,147 @@ exports[`<MImageBody/> should generate a thumbnail if one isn't included for ani
</div>
`;
exports[`<MImageBody/> should open ImageView using thumbnail for encrypted svg 1`] = `
<div
aria-label="Image view"
class="mx_ImageView"
data-focus-lock-disabled="false"
role="dialog"
>
<div
class="mx_ImageView_panel"
>
<div
class="mx_ImageView_info_wrapper"
>
<button
aria-label="Profile picture"
aria-live="off"
class="_avatar_1qbcf_8 mx_BaseAvatar mx_Dialog_nonDialogButton _avatar-imageless_1qbcf_52"
data-color="2"
data-testid="avatar-img"
data-type="round"
role="button"
style="--cpd-avatar-size: 32px;"
>
o
</button>
<div
class="mx_ImageView_info"
>
<div
class="mx_ImageView_info_sender"
>
@other_use:server
</div>
<a
aria-live="off"
class="mx_MessageTimestamp"
href="https://matrix.to/#/!room:server/undefined"
>
Thu, Jan 15, 1970, 06:56
</a>
</div>
</div>
<div
class="mx_ImageView_title"
>
Image
</div>
<div
class="mx_ImageView_toolbar"
>
<div
aria-label="Zoom out"
class="mx_AccessibleButton mx_ImageView_button mx_ImageView_button_zoomOut"
role="button"
tabindex="0"
/>
<div
aria-label="Zoom in"
class="mx_AccessibleButton mx_ImageView_button mx_ImageView_button_zoomIn"
role="button"
tabindex="0"
/>
<div
aria-label="Rotate Left"
class="mx_AccessibleButton mx_ImageView_button mx_ImageView_button_rotateCCW"
role="button"
tabindex="0"
/>
<div
aria-label="Rotate Right"
class="mx_AccessibleButton mx_ImageView_button mx_ImageView_button_rotateCW"
role="button"
tabindex="0"
/>
<div
aria-label="Download"
class="mx_AccessibleButton mx_ImageView_button mx_ImageView_button_download"
role="button"
tabindex="0"
/>
<div
aria-expanded="false"
aria-haspopup="true"
aria-label="Options"
class="mx_AccessibleButton mx_ImageView_button mx_ImageView_button_more"
role="button"
tabindex="0"
/>
<div
aria-label="Close"
class="mx_AccessibleButton mx_ImageView_button mx_ImageView_button_close"
role="button"
tabindex="0"
/>
</div>
</div>
<div
class="mx_ImageView_image_wrapper"
>
<img
alt="Attachment"
class="mx_ImageView_image "
draggable="true"
src="https://server/_matrix/media/v3/download/server/svg-thumbnail"
style="transform: translateX(-512px)
translateY(NaNpx)
scale(0)
rotate(0deg); cursor: zoom-out;"
/>
</div>
</div>
`;
exports[`<MImageBody/> should render MFileBody for svg with no thumbnail 1`] = `
<DocumentFragment>
<span
class="mx_MFileBody"
>
<div
class="mx_AccessibleButton mx_MediaBody mx_MFileBody_info"
role="button"
tabindex="0"
>
<span
class="mx_MFileBody_info_icon"
/>
<span
aria-labelledby="_r_0_"
tabindex="0"
>
<span
class="mx_MFileBody_info_filename"
>
Attachment
</span>
</span>
</div>
</span>
</DocumentFragment>
`;
exports[`<MImageBody/> should show a thumbnail while image is being downloaded 1`] = `
<div>
<div

View File

@ -2,9 +2,21 @@
exports[`<MPollEndBody /> when poll start event does not exist in current timeline fetches the related poll start event and displays a poll tile 1`] = `
<div>
<div
<svg
class="mx_MPollEndBody_icon"
/>
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M21 10.659V19q0 .824-.587 1.413A1.93 1.93 0 0 1 19 21H5q-.824 0-1.412-.587A1.93 1.93 0 0 1 3 19V5q0-.824.587-1.412A1.93 1.93 0 0 1 5 3h8.341A6 6 0 0 0 13 5H5v14h14v-8a6 6 0 0 0 2-.341"
/>
<path
d="M13.803 8a6 6 0 0 0 1.88 2H13a.97.97 0 0 1-.713-.287A.97.97 0 0 1 12 9q0-.424.287-.713A.97.97 0 0 1 13 8zm2.91 7.713A.97.97 0 0 1 16 16h-3a.97.97 0 0 1-.713-.287A.97.97 0 0 1 12 15q0-.424.287-.713A.97.97 0 0 1 13 14h3q.424 0 .712.287.288.288.288.713 0 .424-.288.713m-6.299-5.3A1.93 1.93 0 0 1 9 11q-.825 0-1.412-.588A1.93 1.93 0 0 1 7 9q0-.825.588-1.412A1.93 1.93 0 0 1 9 7q.825 0 1.412.588Q11 8.175 11 9t-.588 1.412m.001 6.001A1.93 1.93 0 0 1 9 17q-.825 0-1.412-.587A1.93 1.93 0 0 1 7 15q0-.825.588-1.412A1.93 1.93 0 0 1 9 13q.825 0 1.412.588Q11 14.175 11 15q0 .824-.588 1.413m12.295-14.12a1 1 0 0 1 0 1.414l-4 4a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L18 5.586l3.293-3.293a1 1 0 0 1 1.414 0"
/>
</svg>
</div>
`;

View File

@ -97,9 +97,18 @@ exports[`<PollHistory /> renders a list of active polls when there are polls in
<span>
02/02/23
</span>
<div
<svg
class="mx_PollListItem_icon"
/>
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M16 10q.424 0 .712-.287A.97.97 0 0 0 17 9a.97.97 0 0 0-.288-.713A.97.97 0 0 0 16 8h-3a.97.97 0 0 0-.713.287A.97.97 0 0 0 12 9q0 .424.287.713.288.287.713.287zm0 6q.424 0 .712-.287A.97.97 0 0 0 17 15a.97.97 0 0 0-.288-.713A.97.97 0 0 0 16 14h-3a.97.97 0 0 0-.713.287A.97.97 0 0 0 12 15q0 .424.287.713.288.287.713.287zm-7-5q.825 0 1.412-.588Q11 9.826 11 9t-.588-1.412A1.93 1.93 0 0 0 9 7q-.825 0-1.412.588A1.93 1.93 0 0 0 7 9q0 .825.588 1.412Q8.175 11 9 11m0 6q.825 0 1.412-.587Q11 15.825 11 15t-.588-1.412A1.93 1.93 0 0 0 9 13q-.825 0-1.412.588A1.93 1.93 0 0 0 7 15q0 .824.588 1.413Q8.175 17 9 17m-4 4q-.824 0-1.412-.587A1.93 1.93 0 0 1 3 19V5q0-.824.587-1.412A1.93 1.93 0 0 1 5 3h14q.824 0 1.413.587Q21 4.176 21 5v14q0 .824-.587 1.413A1.93 1.93 0 0 1 19 21zm0-2h14V5H5z"
/>
</svg>
<span
class="mx_PollListItem_question"
>
@ -122,9 +131,18 @@ exports[`<PollHistory /> renders a list of active polls when there are polls in
<span>
02/02/23
</span>
<div
<svg
class="mx_PollListItem_icon"
/>
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M16 10q.424 0 .712-.287A.97.97 0 0 0 17 9a.97.97 0 0 0-.288-.713A.97.97 0 0 0 16 8h-3a.97.97 0 0 0-.713.287A.97.97 0 0 0 12 9q0 .424.287.713.288.287.713.287zm0 6q.424 0 .712-.287A.97.97 0 0 0 17 15a.97.97 0 0 0-.288-.713A.97.97 0 0 0 16 14h-3a.97.97 0 0 0-.713.287A.97.97 0 0 0 12 15q0 .424.287.713.288.287.713.287zm-7-5q.825 0 1.412-.588Q11 9.826 11 9t-.588-1.412A1.93 1.93 0 0 0 9 7q-.825 0-1.412.588A1.93 1.93 0 0 0 7 9q0 .825.588 1.412Q8.175 11 9 11m0 6q.825 0 1.412-.587Q11 15.825 11 15t-.588-1.412A1.93 1.93 0 0 0 9 13q-.825 0-1.412.588A1.93 1.93 0 0 0 7 15q0 .824.588 1.413Q8.175 17 9 17m-4 4q-.824 0-1.412-.587A1.93 1.93 0 0 1 3 19V5q0-.824.587-1.412A1.93 1.93 0 0 1 5 3h14q.824 0 1.413.587Q21 4.176 21 5v14q0 .824-.587 1.413A1.93 1.93 0 0 1 19 21zm0-2h14V5H5z"
/>
</svg>
<span
class="mx_PollListItem_question"
>

View File

@ -16,9 +16,18 @@ exports[`<PollListItem /> renders a poll 1`] = `
<span>
01/01/70
</span>
<div
<svg
class="mx_PollListItem_icon"
/>
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M16 10q.424 0 .712-.287A.97.97 0 0 0 17 9a.97.97 0 0 0-.288-.713A.97.97 0 0 0 16 8h-3a.97.97 0 0 0-.713.287A.97.97 0 0 0 12 9q0 .424.287.713.288.287.713.287zm0 6q.424 0 .712-.287A.97.97 0 0 0 17 15a.97.97 0 0 0-.288-.713A.97.97 0 0 0 16 14h-3a.97.97 0 0 0-.713.287A.97.97 0 0 0 12 15q0 .424.287.713.288.287.713.287zm-7-5q.825 0 1.412-.588Q11 9.826 11 9t-.588-1.412A1.93 1.93 0 0 0 9 7q-.825 0-1.412.588A1.93 1.93 0 0 0 7 9q0 .825.588 1.412Q8.175 11 9 11m0 6q.825 0 1.412-.587Q11 15.825 11 15t-.588-1.412A1.93 1.93 0 0 0 9 13q-.825 0-1.412.588A1.93 1.93 0 0 0 7 15q0 .824.588 1.413Q8.175 17 9 17m-4 4q-.824 0-1.412-.587A1.93 1.93 0 0 1 3 19V5q0-.824.587-1.412A1.93 1.93 0 0 1 5 3h14q.824 0 1.413.587Q21 4.176 21 5v14q0 .824-.587 1.413A1.93 1.93 0 0 1 19 21zm0-2h14V5H5z"
/>
</svg>
<span
class="mx_PollListItem_question"
>

View File

@ -16,9 +16,21 @@ exports[`<PollListItemEnded /> renders a poll with no responses 1`] = `
<div
class="mx_PollListItemEnded_title"
>
<div
<svg
class="mx_PollListItemEnded_icon"
/>
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M21 10.659V19q0 .824-.587 1.413A1.93 1.93 0 0 1 19 21H5q-.824 0-1.412-.587A1.93 1.93 0 0 1 3 19V5q0-.824.587-1.412A1.93 1.93 0 0 1 5 3h8.341A6 6 0 0 0 13 5H5v14h14v-8a6 6 0 0 0 2-.341"
/>
<path
d="M13.803 8a6 6 0 0 0 1.88 2H13a.97.97 0 0 1-.713-.287A.97.97 0 0 1 12 9q0-.424.287-.713A.97.97 0 0 1 13 8zm2.91 7.713A.97.97 0 0 1 16 16h-3a.97.97 0 0 1-.713-.287A.97.97 0 0 1 12 15q0-.424.287-.713A.97.97 0 0 1 13 14h3q.424 0 .712.287.288.288.288.713 0 .424-.288.713m-6.299-5.3A1.93 1.93 0 0 1 9 11q-.825 0-1.412-.588A1.93 1.93 0 0 1 7 9q0-.825.588-1.412A1.93 1.93 0 0 1 9 7q.825 0 1.412.588Q11 8.175 11 9t-.588 1.412m.001 6.001A1.93 1.93 0 0 1 9 17q-.825 0-1.412-.587A1.93 1.93 0 0 1 7 15q0-.825.588-1.412A1.93 1.93 0 0 1 9 13q.825 0 1.412.588Q11 14.175 11 15q0 .824-.588 1.413m12.295-14.12a1 1 0 0 1 0 1.414l-4 4a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L18 5.586l3.293-3.293a1 1 0 0 1 1.414 0"
/>
</svg>
<span
class="mx_PollListItemEnded_question"
>

View File

@ -121,7 +121,19 @@ exports[`<LayoutSwitcher /> should render 1`] = `
role="button"
tabindex="0"
>
<div />
<svg
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M15.706 2.637a2 2 0 0 1 2.829 0l2.828 2.828a2 2 0 0 1 0 2.829L9.605 20.052a1 1 0 0 1-.465.263L3.483 21.73a1 1 0 0 1-1.212-1.213l1.414-5.657a1 1 0 0 1 .263-.465zm1.224 7.262L14.102 7.07l-8.544 8.544-.943 3.771 3.771-.943z"
fill-rule="evenodd"
/>
</svg>
</div>
<div
aria-expanded="false"
@ -248,7 +260,19 @@ exports[`<LayoutSwitcher /> should render 1`] = `
role="button"
tabindex="0"
>
<div />
<svg
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M15.706 2.637a2 2 0 0 1 2.829 0l2.828 2.828a2 2 0 0 1 0 2.829L9.605 20.052a1 1 0 0 1-.465.263L3.483 21.73a1 1 0 0 1-1.212-1.213l1.414-5.657a1 1 0 0 1 .263-.465zm1.224 7.262L14.102 7.07l-8.544 8.544-.943 3.771 3.771-.943z"
fill-rule="evenodd"
/>
</svg>
</div>
<div
aria-expanded="false"
@ -378,7 +402,19 @@ exports[`<LayoutSwitcher /> should render 1`] = `
role="button"
tabindex="0"
>
<div />
<svg
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M15.706 2.637a2 2 0 0 1 2.829 0l2.828 2.828a2 2 0 0 1 0 2.829L9.605 20.052a1 1 0 0 1-.465.263L3.483 21.73a1 1 0 0 1-1.212-1.213l1.414-5.657a1 1 0 0 1 .263-.465zm1.224 7.262L14.102 7.07l-8.544 8.544-.943 3.771 3.771-.943z"
fill-rule="evenodd"
/>
</svg>
</div>
<div
aria-expanded="false"

View File

@ -264,7 +264,19 @@ exports[`AppearanceUserSettingsTab should render 1`] = `
role="button"
tabindex="0"
>
<div />
<svg
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M15.706 2.637a2 2 0 0 1 2.829 0l2.828 2.828a2 2 0 0 1 0 2.829L9.605 20.052a1 1 0 0 1-.465.263L3.483 21.73a1 1 0 0 1-1.212-1.213l1.414-5.657a1 1 0 0 1 .263-.465zm1.224 7.262L14.102 7.07l-8.544 8.544-.943 3.771 3.771-.943z"
fill-rule="evenodd"
/>
</svg>
</div>
<div
aria-expanded="false"
@ -391,7 +403,19 @@ exports[`AppearanceUserSettingsTab should render 1`] = `
role="button"
tabindex="0"
>
<div />
<svg
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M15.706 2.637a2 2 0 0 1 2.829 0l2.828 2.828a2 2 0 0 1 0 2.829L9.605 20.052a1 1 0 0 1-.465.263L3.483 21.73a1 1 0 0 1-1.212-1.213l1.414-5.657a1 1 0 0 1 .263-.465zm1.224 7.262L14.102 7.07l-8.544 8.544-.943 3.771 3.771-.943z"
fill-rule="evenodd"
/>
</svg>
</div>
<div
aria-expanded="false"
@ -521,7 +545,19 @@ exports[`AppearanceUserSettingsTab should render 1`] = `
role="button"
tabindex="0"
>
<div />
<svg
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M15.706 2.637a2 2 0 0 1 2.829 0l2.828 2.828a2 2 0 0 1 0 2.829L9.605 20.052a1 1 0 0 1-.465.263L3.483 21.73a1 1 0 0 1-1.212-1.213l1.414-5.657a1 1 0 0 1 .263-.465zm1.224 7.262L14.102 7.07l-8.544 8.544-.943 3.771 3.771-.943z"
fill-rule="evenodd"
/>
</svg>
</div>
<div
aria-expanded="false"

View File

@ -2590,12 +2590,12 @@
resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.9.tgz#d229a7b7f9dac167a156992ef23c7f023653f53b"
integrity sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==
"@playwright/test@1.56.1", "@playwright/test@^1.50.1":
version "1.56.1"
resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.56.1.tgz#6e3bf3d0c90c5cf94bf64bdb56fd15a805c8bd3f"
integrity sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==
"@playwright/test@1.57.0":
version "1.57.0"
resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.57.0.tgz#a14720ffa9ed7ef7edbc1f60784fc6134acbb003"
integrity sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==
dependencies:
playwright "1.56.1"
playwright "1.57.0"
"@polka/url@^1.0.0-next.24":
version "1.0.0-next.28"
@ -10455,17 +10455,17 @@ pkg-dir@^4.2.0:
dependencies:
find-up "^4.0.0"
playwright-core@1.56.1, playwright-core@^1.51.0:
version "1.56.1"
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.56.1.tgz#24a66481e5cd33a045632230aa2c4f0cb6b1db3d"
integrity sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==
playwright-core@1.57.0, playwright-core@^1.51.0:
version "1.57.0"
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.57.0.tgz#3dcc9a865af256fa9f0af0d67fc8dd54eecaebf5"
integrity sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==
playwright@1.56.1:
version "1.56.1"
resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.56.1.tgz#62e3b99ddebed0d475e5936a152c88e68be55fbf"
integrity sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==
playwright@1.57.0:
version "1.57.0"
resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.57.0.tgz#74d1dacff5048dc40bf4676940b1901e18ad0f46"
integrity sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==
dependencies:
playwright-core "1.56.1"
playwright-core "1.57.0"
optionalDependencies:
fsevents "2.3.2"