Compare commits

...

6 Commits

Author SHA1 Message Date
Robin
9565d2685e Stop using deprecated Element Call URL parameters
These deprecated parameters will be removed very soon (planned for Element Call version 0.15.0) and we no longer have to care about backward compatibility with old versions of Element Call (due to the embedding/bundling work), so now is the right time to migrate.
2025-07-28 20:30:35 +02:00
Richard van der Hoff
7e40e3697f MatrixChat test robustness fixes (#30413)
* MatrixChat-test: clean up better in `afterEach`

Make the MatrixChat tests behave better by letting them finish their work in an
`act` in afterEach. Otherwise we can end up mounting new components during
cleanup, which run tasks in the background

* MatrixChat-test: clean up dispatcher test

This test was kicking off a dispatcher job which would then open a
UserDeviceSettings dialog once the test had finished. That would then throw
exceptions because some of the mock environment had been torn down.

We're just testing that it opens the right dialog, so better to intercept
`createDialog`.

Aso add an `act` to reduce warnings, and replace a `flushPromises` with a
`waitFor` to make the test more robust.
2025-07-28 16:32:53 +00:00
David Langley
beaabd5b44 bump wysiwyg to 2.39.0 (#30421) 2025-07-28 15:21:24 +01:00
Robin
a23a2c03d3 Allow Element Call to send call notifications (#30404)
* Allow Element Call to send call notifications

Currently Element Web is responsible for sending the call notification event, but this is planned to be changed soon. As of the upcoming Element Call 0.14.0 release, it will request the capability to send call notifications itself, and we should auto-approve this capability.

* Add reaction capability missing from test

Element Call does in fact request this one.
2025-07-27 13:37:10 +00:00
Richard van der Hoff
c2c040dd42 Lifecycle: add a bit more logging (#30414)
... to see what exactly it thinks is wrong with the session

This may be useful in debugging
https://github.com/element-hq/element-web/issues/30337 and
https://github.com/element-hq/element-web/issues/29708. but will likely be
useful in any case.
2025-07-25 16:17:19 +01:00
Florian Duros
c98358cb26 Fix e2e shield being invisible in white mode for encrypted room (#30408)
* fix: e2e icon for encrypted room

* test(e2e): add screenshot for grey shield in encrypted room
2025-07-25 10:56:21 +00:00
10 changed files with 53 additions and 27 deletions

View File

@@ -99,7 +99,7 @@
"@types/react-virtualized": "^9.21.30",
"@vector-im/compound-design-tokens": "^5.0.0",
"@vector-im/compound-web": "^8.1.2",
"@vector-im/matrix-wysiwyg": "2.38.4",
"@vector-im/matrix-wysiwyg": "2.39.0",
"@zxcvbn-ts/core": "^3.0.4",
"@zxcvbn-ts/language-common": "^3.0.4",
"@zxcvbn-ts/language-en": "^3.0.2",

View File

@@ -158,6 +158,8 @@ test.describe("Cryptography", function () {
await page.getByRole("textbox", { name: "Send a message…" }).press("Enter");
await checkDMRoom(page);
const bobRoomId = await bobJoin(page, bob);
await expect(page.locator(".mx_MessageComposer_e2eIcon")).toMatchScreenshot("composer-e2e-icon-normal.png");
await testMessages(page, bob, bobRoomId);
await verify(app, bob);

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 B

View File

@@ -52,7 +52,13 @@ Please see LICENSE files in the repository root for full details.
.mx_E2EIcon_normal::after {
mask-image: url("$(res)/img/e2e/normal.svg");
background-color: white;
background-color: var(--cpd-color-icon-tertiary);
}
.mx_E2EIcon_verified {
.mx_E2EIcon_normal::after {
background-color: white;
}
}
.mx_E2EIcon_verified::after {

View File

@@ -621,6 +621,9 @@ export async function restoreSessionFromStorage(opts?: { ignoreGuest?: boolean }
await getStoredSessionVars();
if (hasAccessToken && !accessToken) {
logger.warn(
"restoreSessionFromStorage: storage indicates we should have an access token, but we do not. Displaying StorageEvictedDialog",
);
await abortLogin();
}
@@ -823,6 +826,7 @@ async function doSetLoggedIn(
// crypto store, we'll be generally confused when handling encrypted data.
// Show a modal recommending a full reset of storage.
if (results.dataInLocalStorage && results.cryptoInited && !results.dataInCryptoStore) {
logger.warn("doSetLoggedIn: StorageManager consistency check failed; displaying StorageEvictedDialog.");
await abortLogin();
}

View File

@@ -669,12 +669,12 @@ export class ElementCall extends Call {
// Splice together the Element Call URL for this call
const params = new URLSearchParams({
embed: "true", // We're embedding EC within another application
confineToRoom: "true", // Only show the call interface for the configured room
// Template variables are used, so that this can be configured using the widget data.
skipLobby: "$skipLobby", // Skip the lobby in case we show a lobby component of our own.
returnToLobby: "$returnToLobby", // Returns to the lobby (instead of blank screen) when the call ends. (For video rooms)
perParticipantE2EE: "$perParticipantE2EE",
hideHeader: "true", // Hide the header since our room header is enough
header: "none", // Hide the header since our room header is enough
userId: client.getUserId()!,
deviceId: client.getDeviceId()!,
roomId: roomId,

View File

@@ -168,6 +168,7 @@ export class StopGapWidgetDriver extends WidgetDriver {
WidgetEventCapability.forStateEvent(EventDirection.Receive, EventType.RoomCreate).raw,
);
const sendRoomEvents = [EventType.CallNotify, EventType.RTCNotification];
const sendRecvRoomEvents = [
"io.element.call.encryption_keys",
"org.matrix.rageshake_request",
@@ -175,10 +176,10 @@ export class StopGapWidgetDriver extends WidgetDriver {
EventType.RoomRedaction,
"io.element.call.reaction",
];
for (const eventType of sendRecvRoomEvents) {
for (const eventType of [...sendRoomEvents, ...sendRecvRoomEvents])
this.allowedCapabilities.add(WidgetEventCapability.forRoomEvent(EventDirection.Send, eventType).raw);
for (const eventType of sendRecvRoomEvents)
this.allowedCapabilities.add(WidgetEventCapability.forRoomEvent(EventDirection.Receive, eventType).raw);
}
const sendRecvToDevice = [
EventType.CallInvite,

View File

@@ -71,6 +71,8 @@ import { SetupEncryptionStore } from "../../../../src/stores/SetupEncryptionStor
import { ShareFormat } from "../../../../src/dispatcher/payloads/SharePayload.ts";
import { clearStorage } from "../../../../src/Lifecycle";
import RoomListStore from "../../../../src/stores/room-list/RoomListStore.ts";
import UserSettingsDialog from "../../../../src/components/views/dialogs/UserSettingsDialog.tsx";
import { SdkContextClass } from "../../../../src/contexts/SDKContext.ts";
jest.mock("matrix-js-sdk/src/oidc/authorize", () => ({
completeAuthorizationCodeGrant: jest.fn(),
@@ -268,6 +270,10 @@ describe("<MatrixChat />", () => {
// (must be sync otherwise the next test will start before it happens)
act(() => defaultDispatcher.dispatch({ action: Action.OnLoggedOut }, true));
// that will cause the Login to kick off an update in the background, which we need to allow to finish within
// an `act` to avoid warnings
await flushPromises();
localStorage.clear();
});
@@ -640,22 +646,29 @@ describe("<MatrixChat />", () => {
});
describe("onAction()", () => {
beforeEach(() => {
jest.spyOn(defaultDispatcher, "dispatch").mockClear();
jest.spyOn(defaultDispatcher, "fire").mockClear();
afterEach(() => {
jest.restoreAllMocks();
});
it("should open user device settings", async () => {
it("ViewUserDeviceSettings should open user device settings", async () => {
await getComponentAndWaitForReady();
defaultDispatcher.dispatch({
action: Action.ViewUserDeviceSettings,
});
const createDialog = jest.spyOn(Modal, "createDialog").mockReturnValue({} as any);
await flushPromises();
await act(async () => {
defaultDispatcher.dispatch({
action: Action.ViewUserDeviceSettings,
});
expect(defaultDispatcher.dispatch).toHaveBeenCalledWith({
action: Action.ViewUserSettings,
initialTabId: UserTab.SessionManager,
await waitFor(() =>
expect(createDialog).toHaveBeenCalledWith(
UserSettingsDialog,
{ initialTabId: UserTab.SessionManager, sdkContext: expect.any(SdkContextClass) },
/*className=*/ undefined,
/*isPriority=*/ false,
/*isStatic=*/ true,
),
);
});
});
@@ -674,10 +687,6 @@ describe("<MatrixChat />", () => {
jest.spyOn(ReleaseAnnouncementStore.instance, "getReleaseAnnouncement").mockReturnValue(null);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe("forget_room", () => {
it("should dispatch after_forget_room action on successful forget", async () => {
await clearAllModals();

View File

@@ -92,12 +92,16 @@ describe("StopGapWidgetDriver", () => {
"m.always_on_screen",
"town.robin.msc3846.turn_servers",
"org.matrix.msc2762.timeline:!1:example.org",
"org.matrix.msc2762.send.event:org.matrix.msc4075.call.notify",
"org.matrix.msc2762.send.event:org.matrix.msc4075.rtc.notification",
"org.matrix.msc2762.send.event:org.matrix.rageshake_request",
"org.matrix.msc2762.receive.event:org.matrix.rageshake_request",
"org.matrix.msc2762.send.event:m.reaction",
"org.matrix.msc2762.receive.event:m.reaction",
"org.matrix.msc2762.send.event:m.room.redaction",
"org.matrix.msc2762.receive.event:m.room.redaction",
"org.matrix.msc2762.send.event:io.element.call.reaction",
"org.matrix.msc2762.receive.event:io.element.call.reaction",
"org.matrix.msc2762.receive.state_event:m.room.create",
"org.matrix.msc2762.receive.state_event:m.room.name",
"org.matrix.msc2762.receive.state_event:m.room.member",

View File

@@ -4543,16 +4543,16 @@
classnames "^2.5.1"
vaul "^1.0.0"
"@vector-im/matrix-wysiwyg-wasm@link:../../../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.4-fb0001dea01010a1e3ffc7042596e2d001ce9389-integrity/node_modules/bindings/wysiwyg-wasm":
"@vector-im/matrix-wysiwyg-wasm@link:../../bindings/wysiwyg-wasm":
version "0.0.0"
uid ""
"@vector-im/matrix-wysiwyg@2.38.4":
version "2.38.4"
resolved "https://registry.yarnpkg.com/@vector-im/matrix-wysiwyg/-/matrix-wysiwyg-2.38.4.tgz#fb0001dea01010a1e3ffc7042596e2d001ce9389"
integrity sha512-X6ky+1cf33SPdEVd6iTmOKfZZ2mDJv9cz3sHtDhuclS6uitK3QE8td/pmGqBj4ek2Ia4y0mnU61LfxvMry1SMA==
"@vector-im/matrix-wysiwyg@2.39.0":
version "2.39.0"
resolved "https://registry.yarnpkg.com/@vector-im/matrix-wysiwyg/-/matrix-wysiwyg-2.39.0.tgz#a6238e517f23a2f3025d9c65445914771c63b163"
integrity sha512-OROXnzPcQWrCMoUpIrCKEC4FYU+9SsRomUgu+VbJwWtBDkCbfvLD4z6w/mgiADw3iTUpBPgmcWJoGxesFuB20Q==
dependencies:
"@vector-im/matrix-wysiwyg-wasm" "link:../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.4-fb0001dea01010a1e3ffc7042596e2d001ce9389-integrity/node_modules/bindings/wysiwyg-wasm"
"@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"
"@vitest/expect@3.2.4":
version "3.2.4"