Use the New MatrixRTCSession MembershipManager (#3015)

* provide option to use the New MembershipManager

* fix cryptoApi import change

* add error screen

* bump js-sdk

* rename to `setUnrecoverableError` and remove onLeave call because that will be handled by an effect.

* this was doing nothing (it is a fragment back when there was no deprecated `rtcSession.room`)

* rename to error

* Update src/utils/errors.ts

Co-authored-by: Hugh Nimmo-Smith <hughns@users.noreply.github.com>

* Update src/utils/errors.ts

Co-authored-by: Hugh Nimmo-Smith <hughns@users.noreply.github.com>

* review

* bump js-sdk

* expose lk log level changing in `window`

* bump js-sdk
 - always log "Missing own membership: force re-join"
 - also check insertions queue

* change lk log level to warn

* Bump js-sdk

* Bump js-sdk

* .

* Bump js-sdk

* show user count based on meberships not users.

Signed-off-by: Timo K <toger5@hotmail.de>

* bump js-sdk

* rename setting name

* remove unused import

* js sdk bump

* remove `window.setLKLogLevel`

* bump js sdk with reverted incompatible change

* bump js-sdk with one less merge

---------

Signed-off-by: Timo K <toger5@hotmail.de>
Co-authored-by: Hugh Nimmo-Smith <hughns@users.noreply.github.com>
Co-authored-by: Hugh Nimmo-Smith <hughns@element.io>
This commit is contained in:
Timo
2025-03-07 17:27:04 +01:00
committed by GitHub
parent c9f2a1c943
commit 750db09156
11 changed files with 127 additions and 53 deletions

View File

@@ -70,7 +70,8 @@
"livekit_sfu": "LiveKit SFU: {{url}}", "livekit_sfu": "LiveKit SFU: {{url}}",
"matrix_id": "Matrix ID: {{id}}", "matrix_id": "Matrix ID: {{id}}",
"show_connection_stats": "Show connection statistics", "show_connection_stats": "Show connection statistics",
"show_non_member_tiles": "Show tiles for non-member media" "show_non_member_tiles": "Show tiles for non-member media",
"use_new_membership_manager": "Use the new implementation of the call MembershipManager"
}, },
"disconnected_banner": "Connectivity to the server has been lost.", "disconnected_banner": "Connectivity to the server has been lost.",
"error": { "error": {

View File

@@ -91,7 +91,7 @@
"livekit-client": "^2.5.7", "livekit-client": "^2.5.7",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"loglevel": "^1.9.1", "loglevel": "^1.9.1",
"matrix-js-sdk": "^36.1.0", "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#0cdb07544d9926cf0855a76ca5cc7dab253bdb24",
"matrix-widget-api": "1.11.0", "matrix-widget-api": "1.11.0",
"normalize.css": "^8.0.1", "normalize.css": "^8.0.1",
"observable-hooks": "^4.2.3", "observable-hooks": "^4.2.3",

View File

@@ -16,12 +16,15 @@ import {
} from "react"; } from "react";
import { type MatrixClient } from "matrix-js-sdk/src/client"; import { type MatrixClient } from "matrix-js-sdk/src/client";
import { import {
Room as LivekitRoom,
isE2EESupported as isE2EESupportedBrowser, isE2EESupported as isE2EESupportedBrowser,
Room,
} from "livekit-client"; } from "livekit-client";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { type MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession"; import {
import { JoinRule } from "matrix-js-sdk/src/matrix"; MatrixRTCSessionEvent,
type MatrixRTCSession,
} from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
import { JoinRule, type Room } from "matrix-js-sdk/src/matrix";
import { import {
OfflineIcon, OfflineIcon,
WebBrowserIcon, WebBrowserIcon,
@@ -66,8 +69,14 @@ import {
ElementCallError, ElementCallError,
ErrorCategory, ErrorCategory,
ErrorCode, ErrorCode,
RTCSessionError,
} from "../utils/errors.ts"; } from "../utils/errors.ts";
import { ElementCallRichError } from "../RichError.tsx"; import { ElementCallRichError } from "../RichError.tsx";
import {
useNewMembershipManagerSetting as useNewMembershipManagerSetting,
useSetting,
} from "../settings/settings";
import { useTypedEventEmitter } from "../useEvents";
declare global { declare global {
interface Window { interface Window {
@@ -126,6 +135,18 @@ export const GroupCallView: FC<Props> = ({
}; };
}, [rtcSession]); }, [rtcSession]);
useTypedEventEmitter(
rtcSession,
MatrixRTCSessionEvent.MembershipManagerError,
(error) => {
setError(
new RTCSessionError(
ErrorCode.MEMBERSHIP_MANAGER_UNRECOVERABLE,
error.message ?? error,
),
);
},
);
useEffect(() => { useEffect(() => {
// Sanity check the room object // Sanity check the room object
if (client.getRoom(rtcSession.room.roomId) !== rtcSession.room) if (client.getRoom(rtcSession.room.roomId) !== rtcSession.room)
@@ -134,11 +155,14 @@ export const GroupCallView: FC<Props> = ({
); );
}, [client, rtcSession.room]); }, [client, rtcSession.room]);
const room = rtcSession.room as Room;
const { displayName, avatarUrl } = useProfile(client); const { displayName, avatarUrl } = useProfile(client);
const roomName = useRoomName(rtcSession.room); const roomName = useRoomName(room);
const roomAvatar = useRoomAvatar(rtcSession.room); const roomAvatar = useRoomAvatar(room);
const { perParticipantE2EE, returnToLobby } = useUrlParams(); const { perParticipantE2EE, returnToLobby } = useUrlParams();
const e2eeSystem = useRoomEncryptionSystem(rtcSession.room.roomId); const e2eeSystem = useRoomEncryptionSystem(room.roomId);
const [useNewMembershipManager] = useSetting(useNewMembershipManagerSetting);
usePageTitle(roomName); usePageTitle(roomName);
const matrixInfo = useMemo((): MatrixInfo => { const matrixInfo = useMemo((): MatrixInfo => {
@@ -146,21 +170,13 @@ export const GroupCallView: FC<Props> = ({
userId: client.getUserId()!, userId: client.getUserId()!,
displayName: displayName!, displayName: displayName!,
avatarUrl: avatarUrl!, avatarUrl: avatarUrl!,
roomId: rtcSession.room.roomId, roomId: room.roomId,
roomName, roomName,
roomAlias: rtcSession.room.getCanonicalAlias(), roomAlias: room.getCanonicalAlias(),
roomAvatar, roomAvatar,
e2eeSystem, e2eeSystem,
}; };
}, [ }, [client, displayName, avatarUrl, roomName, room, roomAvatar, e2eeSystem]);
client,
displayName,
avatarUrl,
rtcSession.room,
roomName,
roomAvatar,
e2eeSystem,
]);
// Count each member only once, regardless of how many devices they use // Count each member only once, regardless of how many devices they use
const participantCount = useMemo( const participantCount = useMemo(
@@ -175,13 +191,18 @@ export const GroupCallView: FC<Props> = ({
const enterRTCSessionOrError = async ( const enterRTCSessionOrError = async (
rtcSession: MatrixRTCSession, rtcSession: MatrixRTCSession,
perParticipantE2EE: boolean, perParticipantE2EE: boolean,
newMembershipManager: boolean,
): Promise<void> => { ): Promise<void> => {
try { try {
await enterRTCSession(rtcSession, perParticipantE2EE); await enterRTCSession(
rtcSession,
perParticipantE2EE,
newMembershipManager,
);
} catch (e) { } catch (e) {
if (e instanceof ElementCallError) { if (e instanceof ElementCallError) {
// e.code === ErrorCode.MISSING_LIVE_KIT_SERVICE_URL) // e.code === ErrorCode.MISSING_LIVE_KIT_SERVICE_URL)
setEnterRTCError(e); setError(e);
} else { } else {
logger.error(`Unknown Error while entering RTC session`, e); logger.error(`Unknown Error while entering RTC session`, e);
const error = new ElementCallError( const error = new ElementCallError(
@@ -189,7 +210,7 @@ export const GroupCallView: FC<Props> = ({
ErrorCode.UNKNOWN_ERROR, ErrorCode.UNKNOWN_ERROR,
ErrorCategory.UNKNOWN, ErrorCategory.UNKNOWN,
); );
setEnterRTCError(error); setError(error);
} }
} }
}; };
@@ -203,7 +224,7 @@ export const GroupCallView: FC<Props> = ({
// permissions and give you device names unless you specify a kind, but // permissions and give you device names unless you specify a kind, but
// here we want all kinds of devices. This needs a fix in livekit-client // here we want all kinds of devices. This needs a fix in livekit-client
// for the following name-matching logic to do anything useful. // for the following name-matching logic to do anything useful.
const devices = await Room.getLocalDevices(undefined, true); const devices = await LivekitRoom.getLocalDevices(undefined, true);
if (audioInput) { if (audioInput) {
const deviceId = findDeviceByName(audioInput, "audioinput", devices); const deviceId = findDeviceByName(audioInput, "audioinput", devices);
@@ -243,7 +264,11 @@ export const GroupCallView: FC<Props> = ({
await defaultDeviceSetup( await defaultDeviceSetup(
ev.detail.data as unknown as JoinCallData, ev.detail.data as unknown as JoinCallData,
); );
await enterRTCSessionOrError(rtcSession, perParticipantE2EE); await enterRTCSessionOrError(
rtcSession,
perParticipantE2EE,
useNewMembershipManager,
);
widget.api.transport.reply(ev.detail, {}); widget.api.transport.reply(ev.detail, {});
})().catch((e) => { })().catch((e) => {
logger.error("Error joining RTC session", e); logger.error("Error joining RTC session", e);
@@ -256,13 +281,21 @@ export const GroupCallView: FC<Props> = ({
} else { } else {
// No lobby and no preload: we enter the rtc session right away // No lobby and no preload: we enter the rtc session right away
(async (): Promise<void> => { (async (): Promise<void> => {
await enterRTCSessionOrError(rtcSession, perParticipantE2EE); await enterRTCSessionOrError(
rtcSession,
perParticipantE2EE,
useNewMembershipManager,
);
})().catch((e) => { })().catch((e) => {
logger.error("Error joining RTC session", e); logger.error("Error joining RTC session", e);
}); });
} }
} else { } else {
void enterRTCSessionOrError(rtcSession, perParticipantE2EE); void enterRTCSessionOrError(
rtcSession,
perParticipantE2EE,
useNewMembershipManager,
);
} }
} }
}, [ }, [
@@ -273,12 +306,11 @@ export const GroupCallView: FC<Props> = ({
perParticipantE2EE, perParticipantE2EE,
latestDevices, latestDevices,
latestMuteStates, latestMuteStates,
useNewMembershipManager,
]); ]);
const [left, setLeft] = useState(false); const [left, setLeft] = useState(false);
const [enterRTCError, setEnterRTCError] = useState<ElementCallError | null>( const [error, setError] = useState<ElementCallError | null>(null);
null,
);
const navigate = useNavigate(); const navigate = useNavigate();
const onLeave = useCallback( const onLeave = useCallback(
@@ -292,7 +324,7 @@ export const GroupCallView: FC<Props> = ({
// Otherwise the iFrame gets killed before the callEnded event got tracked. // Otherwise the iFrame gets killed before the callEnded event got tracked.
const posthogRequest = new Promise((resolve) => { const posthogRequest = new Promise((resolve) => {
PosthogAnalytics.instance.eventCallEnded.track( PosthogAnalytics.instance.eventCallEnded.track(
rtcSession.room.roomId, room.roomId,
rtcSession.memberships.length, rtcSession.memberships.length,
sendInstantly, sendInstantly,
rtcSession, rtcSession,
@@ -321,11 +353,12 @@ export const GroupCallView: FC<Props> = ({
}); });
}, },
[ [
leaveSoundContext,
widget, widget,
rtcSession, rtcSession,
room.roomId,
isPasswordlessUser, isPasswordlessUser,
confineToRoom, confineToRoom,
leaveSoundContext,
navigate, navigate,
], ],
); );
@@ -351,7 +384,7 @@ export const GroupCallView: FC<Props> = ({
} }
}, [widget, isJoined, rtcSession]); }, [widget, isJoined, rtcSession]);
const joinRule = useJoinRule(rtcSession.room); const joinRule = useJoinRule(room);
const [shareModalOpen, setInviteModalOpen] = useState(false); const [shareModalOpen, setInviteModalOpen] = useState(false);
const onDismissInviteModal = useCallback( const onDismissInviteModal = useCallback(
@@ -379,8 +412,12 @@ export const GroupCallView: FC<Props> = ({
const onReconnect = useCallback(() => { const onReconnect = useCallback(() => {
setLeft(false); setLeft(false);
resetError(); resetError();
enterRTCSessionOrError(rtcSession, perParticipantE2EE).catch((e) => { enterRTCSessionOrError(
logger.error("Error re-entering RTC session", e); rtcSession,
perParticipantE2EE,
useNewMembershipManager,
).catch((e) => {
logger.error("Error re-entering RTC session on reconnect", e);
}); });
}, [resetError]); }, [resetError]);
@@ -402,7 +439,7 @@ export const GroupCallView: FC<Props> = ({
); );
} }
return GroupCallErrorPage; return GroupCallErrorPage;
}, [onLeave, rtcSession, perParticipantE2EE, t]); }, [t, rtcSession, onLeave, perParticipantE2EE, useNewMembershipManager]);
if (!isE2EESupportedBrowser() && e2eeSystem.kind !== E2eeType.NONE) { if (!isE2EESupportedBrowser() && e2eeSystem.kind !== E2eeType.NONE) {
// If we have a encryption system but the browser does not support it. // If we have a encryption system but the browser does not support it.
@@ -417,7 +454,7 @@ export const GroupCallView: FC<Props> = ({
const shareModal = ( const shareModal = (
<InviteModal <InviteModal
room={rtcSession.room} room={room}
open={shareModalOpen} open={shareModalOpen}
onDismiss={onDismissInviteModal} onDismiss={onDismissInviteModal}
/> />
@@ -430,7 +467,11 @@ export const GroupCallView: FC<Props> = ({
matrixInfo={matrixInfo} matrixInfo={matrixInfo}
muteStates={muteStates} muteStates={muteStates}
onEnter={() => onEnter={() =>
void enterRTCSessionOrError(rtcSession, perParticipantE2EE) void enterRTCSessionOrError(
rtcSession,
perParticipantE2EE,
useNewMembershipManager,
)
} }
confineToRoom={confineToRoom} confineToRoom={confineToRoom}
hideHeader={hideHeader} hideHeader={hideHeader}
@@ -441,11 +482,11 @@ export const GroupCallView: FC<Props> = ({
); );
let body: ReactNode; let body: ReactNode;
if (enterRTCError) { if (error) {
// If an ElementCallError was recorded, then create a component that will fail to render and throw // If an ElementCallError was recorded, then create a component that will fail to render and throw
// an ElementCallRichError error. This will then be handled by the ErrorBoundary component. // an ElementCallRichError error. This will then be handled by the ErrorBoundary component.
const ErrorComponent = (): ReactNode => { const ErrorComponent = (): ReactNode => {
throw new ElementCallRichError(enterRTCError); throw new ElementCallRichError(error);
}; };
body = <ErrorComponent />; body = <ErrorComponent />;
} else if (isJoined) { } else if (isJoined) {

View File

@@ -111,6 +111,7 @@ test("It joins the correct Session", async () => {
{ {
manageMediaKeys: false, manageMediaKeys: false,
useLegacyMemberEvents: false, useLegacyMemberEvents: false,
useNewMembershipManager: true,
}, },
); );
}); });

View File

@@ -97,6 +97,7 @@ async function makePreferredLivekitFoci(
export async function enterRTCSession( export async function enterRTCSession(
rtcSession: MatrixRTCSession, rtcSession: MatrixRTCSession,
encryptMedia: boolean, encryptMedia: boolean,
useNewMembershipManager = true,
): Promise<void> { ): Promise<void> {
PosthogAnalytics.instance.eventCallEnded.cacheStartCall(new Date()); PosthogAnalytics.instance.eventCallEnded.cacheStartCall(new Date());
PosthogAnalytics.instance.eventCallStarted.track(rtcSession.room.roomId); PosthogAnalytics.instance.eventCallStarted.track(rtcSession.room.roomId);
@@ -114,6 +115,7 @@ export async function enterRTCSession(
await makePreferredLivekitFoci(rtcSession, livekitAlias), await makePreferredLivekitFoci(rtcSession, livekitAlias),
makeActiveFocus(), makeActiveFocus(),
{ {
useNewMembershipManager,
manageMediaKeys: encryptMedia, manageMediaKeys: encryptMedia,
...(useDeviceSessionMemberEvents !== undefined && { ...(useDeviceSessionMemberEvents !== undefined && {
useLegacyMemberEvents: !useDeviceSessionMemberEvents, useLegacyMemberEvents: !useDeviceSessionMemberEvents,

View File

@@ -15,6 +15,7 @@ import {
debugTileLayout as debugTileLayoutSetting, debugTileLayout as debugTileLayoutSetting,
showNonMemberTiles as showNonMemberTilesSetting, showNonMemberTiles as showNonMemberTilesSetting,
showConnectionStats as showConnectionStatsSetting, showConnectionStats as showConnectionStatsSetting,
useNewMembershipManagerSetting,
} from "./settings"; } from "./settings";
import type { MatrixClient } from "matrix-js-sdk/src/client"; import type { MatrixClient } from "matrix-js-sdk/src/client";
import type { Room as LivekitRoom } from "livekit-client"; import type { Room as LivekitRoom } from "livekit-client";
@@ -38,6 +39,10 @@ export const DeveloperSettingsTab: FC<Props> = ({ client, livekitRoom }) => {
showConnectionStatsSetting, showConnectionStatsSetting,
); );
const [useNewMembershipManager, setNewMembershipManager] = useSetting(
useNewMembershipManagerSetting,
);
const sfuUrl = useMemo((): URL | null => { const sfuUrl = useMemo((): URL | null => {
if (livekitRoom?.engine.client.ws?.url) { if (livekitRoom?.engine.client.ws?.url) {
// strip the URL params // strip the URL params
@@ -134,6 +139,20 @@ export const DeveloperSettingsTab: FC<Props> = ({ client, livekitRoom }) => {
)} )}
/> />
</FieldRow> </FieldRow>
<FieldRow>
<InputField
id="useNewMembershipManager"
type="checkbox"
label={t("developer_mode.use_new_membership_manager")}
checked={!!useNewMembershipManager}
onChange={useCallback(
(event: ChangeEvent<HTMLInputElement>): void => {
setNewMembershipManager(event.target.checked);
},
[setNewMembershipManager],
)}
/>
</FieldRow>
{livekitRoom ? ( {livekitRoom ? (
<> <>
<p> <p>

View File

@@ -113,4 +113,8 @@ export const soundEffectVolumeSetting = new Setting<number>(
0.5, 0.5,
); );
export const useNewMembershipManagerSetting = new Setting<boolean>(
"new-membership-manager",
true,
);
export const alwaysShowSelf = new Setting<boolean>("always-show-self", true); export const alwaysShowSelf = new Setting<boolean>("always-show-self", true);

View File

@@ -9,10 +9,10 @@ import { type ComponentProps, useCallback, useEffect, useState } from "react";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { import {
ClientEvent, ClientEvent,
type Crypto,
type MatrixClient, type MatrixClient,
type MatrixEvent, type MatrixEvent,
} from "matrix-js-sdk/src/matrix"; } from "matrix-js-sdk/src/matrix";
import { type CryptoApi } from "matrix-js-sdk/src/crypto-api";
import { getLogsForReport } from "./rageshake"; import { getLogsForReport } from "./rageshake";
import { useClient } from "../ClientContext"; import { useClient } from "../ClientContext";
@@ -34,7 +34,7 @@ const gzip = async (text: string): Promise<Blob> => {
* Collects crypto related information. * Collects crypto related information.
*/ */
async function collectCryptoInfo( async function collectCryptoInfo(
cryptoApi: Crypto.CryptoApi, cryptoApi: CryptoApi,
body: FormData, body: FormData,
): Promise<void> { ): Promise<void> {
body.append("crypto_version", cryptoApi.getVersion()); body.append("crypto_version", cryptoApi.getVersion());
@@ -82,7 +82,7 @@ async function collectCryptoInfo(
*/ */
async function collectRecoveryInfo( async function collectRecoveryInfo(
client: MatrixClient, client: MatrixClient,
cryptoApi: Crypto.CryptoApi, cryptoApi: CryptoApi,
body: FormData, body: FormData,
): Promise<void> { ): Promise<void> {
const secretStorage = client.secretStorage; const secretStorage = client.secretStorage;

View File

@@ -13,6 +13,7 @@ export enum ErrorCode {
*/ */
MISSING_MATRIX_RTC_FOCUS = "MISSING_MATRIX_RTC_FOCUS", MISSING_MATRIX_RTC_FOCUS = "MISSING_MATRIX_RTC_FOCUS",
CONNECTION_LOST_ERROR = "CONNECTION_LOST_ERROR", CONNECTION_LOST_ERROR = "CONNECTION_LOST_ERROR",
MEMBERSHIP_MANAGER_UNRECOVERABLE = "MEMBERSHIP_MANAGER_UNRECOVERABLE",
UNKNOWN_ERROR = "UNKNOWN_ERROR", UNKNOWN_ERROR = "UNKNOWN_ERROR",
} }
@@ -20,6 +21,7 @@ export enum ErrorCategory {
/** Calling is not supported, server misconfigured (JWT service missing, no MSC support ...)*/ /** Calling is not supported, server misconfigured (JWT service missing, no MSC support ...)*/
CONFIGURATION_ISSUE = "CONFIGURATION_ISSUE", CONFIGURATION_ISSUE = "CONFIGURATION_ISSUE",
NETWORK_CONNECTIVITY = "NETWORK_CONNECTIVITY", NETWORK_CONNECTIVITY = "NETWORK_CONNECTIVITY",
RTC_SESSION_FAILURE = "RTC_SESSION_FAILURE",
UNKNOWN = "UNKNOWN", UNKNOWN = "UNKNOWN",
// SYSTEM_FAILURE / FEDERATION_FAILURE .. // SYSTEM_FAILURE / FEDERATION_FAILURE ..
} }
@@ -72,3 +74,9 @@ export class ConnectionLostError extends ElementCallError {
); );
} }
} }
export class RTCSessionError extends ElementCallError {
public constructor(code: ErrorCode, message: string) {
super("RTCSession Error", code, ErrorCategory.RTC_SESSION_FAILURE, message);
}
}

View File

@@ -69,7 +69,7 @@ async function waitForSync(client: MatrixClient): Promise<void> {
* otherwise rust crypto will throw since it is not ready to initialize a new session. * otherwise rust crypto will throw since it is not ready to initialize a new session.
* If another client is running make sure `.logout()` is called before executing this function. * If another client is running make sure `.logout()` is called before executing this function.
* @param clientOptions Object of options passed through to the client * @param clientOptions Object of options passed through to the client
* @param restore If the rust crypto should be reset before the cient initialization or * @param restore If the rust crypto should be reset before the client initialization or
* if the initialization should try to restore the crypto state from the indexDB. * if the initialization should try to restore the crypto state from the indexDB.
* @returns The MatrixClient instance * @returns The MatrixClient instance
*/ */
@@ -160,7 +160,6 @@ export async function initClient(
); );
} }
client.setGlobalErrorOnUnknownDevices(false);
// Once startClient is called, syncs are run asynchronously. // Once startClient is called, syncs are run asynchronously.
// Also, sync completion is communicated only via events. // Also, sync completion is communicated only via events.
// So, apply the event listener *before* starting the client. // So, apply the event listener *before* starting the client.

View File

@@ -1787,10 +1787,10 @@
dependencies: dependencies:
"@bufbuild/protobuf" "^1.10.0" "@bufbuild/protobuf" "^1.10.0"
"@matrix-org/matrix-sdk-crypto-wasm@^12.1.0": "@matrix-org/matrix-sdk-crypto-wasm@^14.0.1":
version "12.1.0" version "14.0.1"
resolved "https://registry.yarnpkg.com/@matrix-org/matrix-sdk-crypto-wasm/-/matrix-sdk-crypto-wasm-12.1.0.tgz#2aef64eab2d30c0a1ace9c0fe876f53aa2949f14" resolved "https://registry.yarnpkg.com/@matrix-org/matrix-sdk-crypto-wasm/-/matrix-sdk-crypto-wasm-14.0.1.tgz#e258ef84bcc7889f0e7eb3a7dbecf0830a6dd606"
integrity sha512-NhJFu/8FOGjnW7mDssRUzaMSwXrYOcCqgAjZyAw9KQ9unNADKEi7KoIKe7GtrG2PWtm36y2bUf+hB8vhSY6Wdw== integrity sha512-CgLpHs6nTw5pjSsMBi9xbQnBXf2l8YhImQP9cv8nbGSCYdYjFI0FilMXffzjWV5HThpNHri/3pF20ahZtuS3VA==
"@matrix-org/olm@3.2.15": "@matrix-org/olm@3.2.15":
version "3.2.15" version "3.2.15"
@@ -6334,13 +6334,12 @@ matrix-events-sdk@0.0.1:
resolved "https://registry.yarnpkg.com/matrix-events-sdk/-/matrix-events-sdk-0.0.1.tgz#c8c38911e2cb29023b0bbac8d6f32e0de2c957dd" resolved "https://registry.yarnpkg.com/matrix-events-sdk/-/matrix-events-sdk-0.0.1.tgz#c8c38911e2cb29023b0bbac8d6f32e0de2c957dd"
integrity sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA== integrity sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA==
matrix-js-sdk@^36.1.0: "matrix-js-sdk@github:matrix-org/matrix-js-sdk#0cdb07544d9926cf0855a76ca5cc7dab253bdb24":
version "36.1.0" version "37.0.0"
resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-36.1.0.tgz#3685a85c0c1adf4e2c3622bce76c11430963f23d" resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/0cdb07544d9926cf0855a76ca5cc7dab253bdb24"
integrity sha512-KNPswMSAGKDxBybJedxRpWadaRes9paxmjTCUsQT8t1Jg3ZENraAt6ynIaxh6PxazAH9D5ly6EYKHaLMLbZ1Dg==
dependencies: dependencies:
"@babel/runtime" "^7.12.5" "@babel/runtime" "^7.12.5"
"@matrix-org/matrix-sdk-crypto-wasm" "^12.1.0" "@matrix-org/matrix-sdk-crypto-wasm" "^14.0.1"
"@matrix-org/olm" "3.2.15" "@matrix-org/olm" "3.2.15"
another-json "^0.2.0" another-json "^0.2.0"
bs58 "^6.0.0" bs58 "^6.0.0"