From 3cc396f42c25f3c1c2f69cf66612c39b1c4b8e56 Mon Sep 17 00:00:00 2001 From: "Timo K." Date: Tue, 7 Jul 2026 19:05:10 +0200 Subject: [PATCH 1/9] fix getChild before rageshake setup --- sdk/helper.ts | 2 +- sdk/main.ts | 4 +++- src/e2ee/matrixKeyProvider.ts | 10 +++++----- src/livekit/MatrixAudioRenderer.tsx | 2 +- src/settings/rageshake.ts | 5 +++-- src/state/CallViewModel/CallViewModel.ts | 3 ++- 6 files changed, 15 insertions(+), 11 deletions(-) diff --git a/sdk/helper.ts b/sdk/helper.ts index 47de4a939..c3f0c13c2 100644 --- a/sdk/helper.ts +++ b/sdk/helper.ts @@ -15,9 +15,9 @@ import { scan } from "rxjs"; import { type WidgetHelpers } from "../src/widget"; import { type LivekitRoomItem } from "../src/state/CallViewModel/CallViewModel"; -export const logger = rootLogger.getChild("[MatrixRTCSdk]"); export const tryMakeSticky = (widget: WidgetHelpers): void => { + const logger = rootLogger.getChild("[MatrixRTCSdk]"); logger.info("try making sticky MatrixRTCSdk"); void widget.api .setAlwaysOnScreen(true) diff --git a/sdk/main.ts b/sdk/main.ts index b94a7eb51..6e558fc94 100644 --- a/sdk/main.ts +++ b/sdk/main.ts @@ -52,7 +52,8 @@ import { getUrlParams } from "../src/UrlParams"; import { MuteStates } from "../src/state/MuteStates"; import { MediaDevices } from "../src/state/MediaDevices"; import { E2eeType } from "../src/e2ee/e2eeType"; -import { currentAndPrev, logger, TEXT_LK_TOPIC, tryMakeSticky } from "./helper"; +import { currentAndPrev, TEXT_LK_TOPIC, tryMakeSticky } from "./helper"; +import {logger as rootLogger} from "matrix-js-sdk/lib/logger" import { ElementWidgetActions, widget as _widget, @@ -104,6 +105,7 @@ export async function createMatrixRTCSdk( id: string = "", sticky: boolean = false, ): Promise { + const logger = rootLogger.getChild("[MatrixRTCSdk]"); const scope = new ObservableScope(); // widget client diff --git a/src/e2ee/matrixKeyProvider.ts b/src/e2ee/matrixKeyProvider.ts index 63a96755f..f1a66a28a 100644 --- a/src/e2ee/matrixKeyProvider.ts +++ b/src/e2ee/matrixKeyProvider.ts @@ -10,15 +10,15 @@ import { type MatrixRTCSession, MatrixRTCSessionEvent, } from "matrix-js-sdk/lib/matrixrtc"; -import { logger as rootLogger } from "matrix-js-sdk/lib/logger"; +import { logger as rootLogger, type Logger } from "matrix-js-sdk/lib/logger"; import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager"; -const logger = rootLogger.getChild("[MatrixKeyProvider]"); export class MatrixKeyProvider extends BaseKeyProvider { private rtcSession?: MatrixRTCSession; - + private logger: Logger; public constructor() { super({ ratchetWindowSize: 10, keyringSize: 256 }); + this.logger = rootLogger.getChild("[MatrixKeyProvider]"); } public setRTCSession(rtcSession: MatrixRTCSession): void { @@ -60,12 +60,12 @@ export class MatrixKeyProvider extends BaseKeyProvider { encryptionKeyIndex, ); - logger.debug( + this.logger.debug( `Sent new key to livekit room=${this.rtcSession?.room.roomId} participantId=${rtcBackendIdentity} (before hash: ${membershipParts.userId}:${membershipParts.deviceId}) encryptionKeyIndex=${encryptionKeyIndex}`, ); }, (e) => { - logger.error( + this.logger.error( `Failed to create key material from buffer for livekit room=${this.rtcSession?.room.roomId} participantId before hash=${membershipParts.userId}:${membershipParts.deviceId} encryptionKeyIndex=${encryptionKeyIndex}`, e, ); diff --git a/src/livekit/MatrixAudioRenderer.tsx b/src/livekit/MatrixAudioRenderer.tsx index 10579c1b9..316294dac 100644 --- a/src/livekit/MatrixAudioRenderer.tsx +++ b/src/livekit/MatrixAudioRenderer.tsx @@ -40,7 +40,6 @@ export interface MatrixAudioRendererProps { muted?: boolean; } -const prefixedLogger = logger.getChild("[MatrixAudioRenderer]"); /** * Takes care of handling remote participants’ audio tracks and makes sure that microphones and screen share are audible. * @@ -60,6 +59,7 @@ export function LivekitRoomAudioRenderer({ validIdentities, muted, }: MatrixAudioRendererProps): ReactNode { + const prefixedLogger = logger.getChild("[MatrixAudioRenderer]"); const tracks = useTracks( [ Track.Source.Microphone, diff --git a/src/settings/rageshake.ts b/src/settings/rageshake.ts index bf534671d..b9ecbff50 100644 --- a/src/settings/rageshake.ts +++ b/src/settings/rageshake.ts @@ -467,7 +467,7 @@ declare global { // eslint-disable-next-line no-var, camelcase var mx_rage_initStoragePromise: Promise | undefined; } - +export let rageshakeLogger: Logger; /** * Configure rage shaking support for sending bug reports. * Modifies globals. @@ -477,7 +477,8 @@ export async function init(): Promise { global.mx_rage_logger = new ConsoleLogger(); // configure loglevel based loggers: - setLogExtension(logger, global.mx_rage_logger.log); + rageshakeLogger = logger; + setLogExtension(rageshakeLogger, global.mx_rage_logger.log); // intercept console logging so that we can get matrix_sdk logs: // this is nasty, but no logging hooks are provided diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 27676cb50..f992d542b 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -157,7 +157,7 @@ import { } from "../media/RingingMediaViewModel.ts"; import { type GridTileViewModel } from "../TileViewModel.ts"; -const logger = rootLogger.getChild("[CallViewModel]"); + //TODO // Larger rename // member,membership -> rtcMember @@ -411,6 +411,7 @@ export function createCallViewModel$( reactionsSubject$: Observable>, trackProcessorState$: Behavior, ): CallViewModel { + const logger = rootLogger.getChild("[CallViewModel]"); const client = matrixRoom.client; const userId = client.getUserId(); const deviceId = client.getDeviceId(); From a6921e2bfbb641d5406be5be2f9f4fb397163c69 Mon Sep 17 00:00:00 2001 From: "Timo K." Date: Tue, 7 Jul 2026 19:12:11 +0200 Subject: [PATCH 2/9] all the other logs --- src/room/InCallView.tsx | 5 +++-- .../CallViewModel/CallNotificationLifecycle.ts | 3 +-- .../localMember/HomeserverConnected.ts | 6 +----- .../CallViewModel/localMember/LocalTransport.ts | 16 ++++++++++++---- .../remoteMembers/MatrixMemberMetadata.ts | 3 +-- 5 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index 5872cfb44..8982226ab 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -94,7 +94,7 @@ declare module "react" { } } -const logger = rootLogger.getChild("[InCallView]"); + export interface ActiveCallProps extends Omit< InCallViewProps, @@ -116,7 +116,7 @@ export const ActiveCall: FC = (props) => { const mediaDevices = useMediaDevices(); const trackProcessorState$ = useTrackProcessorObservable$(); useEffect(() => { - logger.info("START CALL VIEW SCOPE"); + rootLogger.info("START CALL VIEW SCOPE"); const scope = new ObservableScope(); const reactionsReader = new ReactionsReader(scope, props.rtcSession); const { autoLeaveWhenOthersLeft, waitForCallPickup, sendNotificationType } = @@ -218,6 +218,7 @@ export const InCallView: FC = ({ muteStates, onShareClick, }) => { + const logger = rootLogger.getChild("[InCallView]"); const { t } = useTranslation(); const { sendReaction, toggleRaisedHand } = useReactionsSender(); diff --git a/src/state/CallViewModel/CallNotificationLifecycle.ts b/src/state/CallViewModel/CallNotificationLifecycle.ts index 4d7007b9e..59930fd64 100644 --- a/src/state/CallViewModel/CallNotificationLifecycle.ts +++ b/src/state/CallViewModel/CallNotificationLifecycle.ts @@ -39,8 +39,6 @@ import { type Behavior } from "../Behavior"; import { type Epoch, type ObservableScope } from "../ObservableScope"; import { type RoomMemberMap } from "./remoteMembers/MatrixMemberMetadata"; -const logger = rootLogger.getChild("[CallNotificationLifecycle]"); - export type AutoLeaveReason = "allOthersLeft" | "timeout" | "decline"; export interface RingAttempt { @@ -114,6 +112,7 @@ export function createCallNotificationLifecycle$({ */ autoLeave$: Observable; } { + const logger = rootLogger.getChild("[CallNotificationLifecycle]"); let ringAttempts$: Observable = NEVER; if (options.waitForCallPickup) ringAttempts$ = sentCallNotification$.pipe( diff --git a/src/state/CallViewModel/localMember/HomeserverConnected.ts b/src/state/CallViewModel/localMember/HomeserverConnected.ts index 227c21c31..45e9f6cbb 100644 --- a/src/state/CallViewModel/localMember/HomeserverConnected.ts +++ b/src/state/CallViewModel/localMember/HomeserverConnected.ts @@ -31,11 +31,6 @@ import { type ObservableScope } from "../../ObservableScope"; import { type Behavior } from "../../Behavior"; import { type NodeStyleEventEmitter } from "../../../utils/test"; -/** - * Logger instance (scoped child) for homeserver connection updates. - */ -const logger = rootLogger.getChild("[HomeserverConnected]"); - export type HomeserverDisconnectReason = "sync" | "membership" | "probablyLeft"; export interface HomeserverConnected { @@ -70,6 +65,7 @@ export function createHomeserverConnected$( Pick, gracePeriodMs?: number, ): HomeserverConnected { + const logger = rootLogger.getChild("[HomeserverConnected]"); // Get grace period from parameter or config (default 10000ms) const graceMs = gracePeriodMs ?? Config.get().sync_disconnect_grace_period_ms; diff --git a/src/state/CallViewModel/localMember/LocalTransport.ts b/src/state/CallViewModel/localMember/LocalTransport.ts index 10ea79c44..7eebbd4c9 100644 --- a/src/state/CallViewModel/localMember/LocalTransport.ts +++ b/src/state/CallViewModel/localMember/LocalTransport.ts @@ -25,7 +25,7 @@ import { switchMap, tap, } from "rxjs"; -import { logger as rootLogger } from "matrix-js-sdk/lib/logger"; +import { logger as rootLogger, type Logger } from "matrix-js-sdk/lib/logger"; import { AutoDiscovery } from "matrix-js-sdk/lib/autodiscovery"; import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager"; @@ -46,8 +46,6 @@ import { areLivekitTransportsEqual } from "../remoteMembers/MatrixLivekitMembers import { customLivekitUrl } from "../../../settings/settings.ts"; import { RtcTransportAutoDiscovery } from "./RtcTransportAutoDiscovery.ts"; -const logger = rootLogger.getChild("[LocalTransport]"); - /* * It figures out “which LiveKit focus URL/alias the local user should use,” * optionally aligning with the oldest member, and ensures the SFU path is primed @@ -140,9 +138,14 @@ export const createLocalTransport$ = ({ forceJwtEndpoint, delayId$, }: Props): LocalTransport => { + const logger = rootLogger.getChild("[LocalTransport]"); // The LiveKit transport in use by the oldest RTC membership. `null` when the // oldest member has no such transport. - const oldestMemberTransport$ = observerOldestMembership$(scope, memberships$); + const oldestMemberTransport$ = observerOldestMembership$( + scope, + memberships$, + logger, + ); const transportDiscovery = new RtcTransportAutoDiscovery({ client: client, @@ -209,6 +212,7 @@ export const createLocalTransport$ = ({ client, ownMembershipIdentity, roomId, + logger, ); } @@ -248,6 +252,7 @@ export const createLocalTransport$ = ({ function observerOldestMembership$( scope: ObservableScope, memberships$: Behavior>, + logger: Logger, ): Behavior { return scope.behavior( memberships$.pipe( @@ -307,6 +312,7 @@ async function doOpenIdAndJWTFromUrl( > & OpenIDClientParts, delayId?: string, + logger: Logger, ): Promise { const sfuConfig = await getSFUConfigWithOpenID( client, @@ -337,6 +343,7 @@ function observeLocalTransportForOldestMembership( OpenIDClientParts, ownMembershipIdentity: CallMembershipIdentityParts, roomId: string, + logger: Logger, ): LocalTransport { // Ensure we can authenticate with the SFU. const authenticatedOldestMemberTransport$ = oldestMemberTransport$.pipe( @@ -355,6 +362,7 @@ function observeLocalTransportForOldestMembership( roomId, client, undefined, + logger, ), ).pipe( catchError((e: unknown) => { diff --git a/src/state/CallViewModel/remoteMembers/MatrixMemberMetadata.ts b/src/state/CallViewModel/remoteMembers/MatrixMemberMetadata.ts index 19c6fdcd5..6a448128c 100644 --- a/src/state/CallViewModel/remoteMembers/MatrixMemberMetadata.ts +++ b/src/state/CallViewModel/remoteMembers/MatrixMemberMetadata.ts @@ -22,8 +22,6 @@ import { } from "../../../utils/displayname"; import { type Behavior } from "../../Behavior"; -const logger = rootLogger.getChild("[MatrixMemberMetadata]"); - export type RoomMemberMap = Map< string, Pick @@ -67,6 +65,7 @@ export const memberDisplaynames$ = ( memberships$: Behavior[]>, roomMembers$: Behavior, ): Behavior> => { + const logger = rootLogger.getChild("[MatrixMemberMetadata]"); // This map tracks userIds that at some point needed disambiguation. // This is a memory leak bound to the number of participants. // A call application will always increase the memory if there have been more members in a call. From 706cddafb0ceeb952c6fa2a1262457987fde0c8a Mon Sep 17 00:00:00 2001 From: "Timo K." Date: Tue, 7 Jul 2026 19:34:03 +0200 Subject: [PATCH 3/9] Add lint rule to make sure future child loggers are setup correctly --- .oxlintrc.json | 1 + eslint/NoTopLevelLoggerGetChild.js | 92 +++++++++++++++++++++++++++++ eslint/index.js | 1 + src/livekit/MatrixAudioRenderer.tsx | 6 +- 4 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 eslint/NoTopLevelLoggerGetChild.js diff --git a/.oxlintrc.json b/.oxlintrc.json index 819e54396..d06f2a473 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -34,6 +34,7 @@ "/*\nCopyright %%CURRENT_YEAR%% Element Creations Ltd.\n\nSPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial\nPlease see LICENSE in the repository root for full details.\n*/\n\n" ], "element-call/no-observablescope-leak": "error", + "element-call/no-top-level-logger-get-child": "error", "jsdoc/empty-tags": "error", "jsdoc/check-property-names": "error", "jsdoc/require-param-description": "warn", diff --git a/eslint/NoTopLevelLoggerGetChild.js b/eslint/NoTopLevelLoggerGetChild.js new file mode 100644 index 000000000..324115d9e --- /dev/null +++ b/eslint/NoTopLevelLoggerGetChild.js @@ -0,0 +1,92 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { ESLintUtils } from "@typescript-eslint/utils"; + +/** + * Node types that introduce a new non-module scope. A getChild() call nested + * inside any of these is considered "not at the top level". + */ +const FUNCTION_OR_CLASS_TYPES = new Set([ + "FunctionDeclaration", + "FunctionExpression", + "ArrowFunctionExpression", + "ClassBody", +]); + +const rule = ESLintUtils.RuleCreator( + () => "https://github.com/element-hq/element-call", +)({ + name: "no-top-level-logger-get-child", + meta: { + type: "problem", + docs: { + description: + "Disallow calling logger.getChild() at the top level of a module." + + "`getChild` has to be called after the rageshake logger `init()`." + + "If it is called at the top level the child logger will never be setup for rageshakes.", + }, + messages: { + noTopLevelGetChild: + "Do not call logger.getChild() at the top level of a module; move it inside a function or class instead that gets called after rageshake logger `init()` is called.", + }, + schema: [], + }, + create(context) { + // Tracks the local binding names that refer to the logger imported from + // 'matrix-js-sdk/lib/logger', e.g. both `logger` and `rootLogger` in: + // import { logger } from "matrix-js-sdk/lib/logger"; + // import { logger as rootLogger } from "matrix-js-sdk/lib/logger"; + const loggerNames = new Set(); + + return { + ImportDeclaration(node) { + if (node.source.value !== "matrix-js-sdk/lib/logger") return; + for (const specifier of node.specifiers) { + if ( + specifier.type === "ImportSpecifier" && + specifier.imported.name === "logger" + ) { + loggerNames.add(specifier.local.name); + } + } + }, + + CallExpression(node) { + // Must be a non-computed member expression call: something.getChild(...) + if ( + node.callee.type !== "MemberExpression" || + node.callee.computed || + node.callee.property.type !== "Identifier" || + node.callee.property.name !== "getChild" + ) + return; + + // The receiver must be one of the tracked logger names. + const object = node.callee.object; + if (object.type !== "Identifier" || !loggerNames.has(object.name)) + return; + + // Flag the call only when it is at module top level — i.e. there is no + // enclosing function or class body anywhere in the ancestor chain. + const ancestors = context.sourceCode.getAncestors(node); + const isTopLevel = !ancestors.some((a) => + FUNCTION_OR_CLASS_TYPES.has(a.type), + ); + + if (isTopLevel) { + context.report({ + messageId: "noTopLevelGetChild", + node, + }); + } + }, + }; + }, +}); + +export default rule; diff --git a/eslint/index.js b/eslint/index.js index ec050ad76..95b4d061f 100644 --- a/eslint/index.js +++ b/eslint/index.js @@ -2,5 +2,6 @@ module.exports = { rules: { "copyright-header": require("./CopyrightHeader").default, "no-observablescope-leak": require("./NoObservableScopeLeak").default, + "no-top-level-logger-get-child": require("./NoTopLevelLoggerGetChild").default, }, }; diff --git a/src/livekit/MatrixAudioRenderer.tsx b/src/livekit/MatrixAudioRenderer.tsx index 316294dac..e3970e9f3 100644 --- a/src/livekit/MatrixAudioRenderer.tsx +++ b/src/livekit/MatrixAudioRenderer.tsx @@ -14,7 +14,7 @@ import { AudioTrack, type AudioTrackProps, } from "@livekit/components-react"; -import { logger } from "matrix-js-sdk/lib/logger"; +import { logger as rootLogger } from "matrix-js-sdk/lib/logger"; import { useEarpieceAudioConfig } from "../MediaDevicesContext"; import { useReactiveState } from "../useReactiveState"; @@ -59,7 +59,7 @@ export function LivekitRoomAudioRenderer({ validIdentities, muted, }: MatrixAudioRendererProps): ReactNode { - const prefixedLogger = logger.getChild("[MatrixAudioRenderer]"); + const logger = rootLogger.getChild("[MatrixAudioRenderer]"); const tracks = useTracks( [ Track.Source.Microphone, @@ -80,7 +80,7 @@ export function LivekitRoomAudioRenderer({ if (!isValid) { // TODO make sure to also skip the warn logging for the local identity // Log that there is an invalid identity, that means that someone is publishing audio that is not expected to be in the call. - prefixedLogger.warn( + logger.warn( `Audio track ${ref.participant.identity} from ${url} has no matching matrix call member`, `current members: ${validIdentities.join()}`, `track will not get rendered`, From 2b84c587f2787dbda87a6df16d6be7be1dc75c96 Mon Sep 17 00:00:00 2001 From: "Timo K." Date: Tue, 7 Jul 2026 19:45:22 +0200 Subject: [PATCH 4/9] lint --- src/state/CallViewModel/CallViewModel.ts | 5 +++-- src/state/CallViewModel/localMember/LocalTransport.ts | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index f992d542b..cd16f6839 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -40,7 +40,7 @@ import { timer, takeUntil, } from "rxjs"; -import { logger as rootLogger } from "matrix-js-sdk/lib/logger"; +import { type Logger, logger as rootLogger } from "matrix-js-sdk/lib/logger"; import { MembershipManagerEvent, type LivekitTransportConfig, @@ -157,7 +157,6 @@ import { } from "../media/RingingMediaViewModel.ts"; import { type GridTileViewModel } from "../TileViewModel.ts"; - //TODO // Larger rename // member,membership -> rtcMember @@ -421,6 +420,7 @@ export function createCallViewModel$( const livekitKeyProvider = getE2eeKeyProvider( options.encryptionSystem, matrixRTCSession, + logger, ); // matrix_rtc_mode in config.json overrides the user's Developer Settings choice. // It is validated at config load (src/config/Config.ts) so the cast is safe. @@ -1798,6 +1798,7 @@ export function createCallViewModel$( function getE2eeKeyProvider( e2eeSystem: EncryptionSystem, rtcSession: MatrixRTCSession, + logger: Logger, ): BaseKeyProvider | undefined { if (e2eeSystem.kind === E2eeType.NONE) return undefined; diff --git a/src/state/CallViewModel/localMember/LocalTransport.ts b/src/state/CallViewModel/localMember/LocalTransport.ts index 7eebbd4c9..e255ca946 100644 --- a/src/state/CallViewModel/localMember/LocalTransport.ts +++ b/src/state/CallViewModel/localMember/LocalTransport.ts @@ -193,6 +193,7 @@ export const createLocalTransport$ = ({ roomId, client, delayId ?? undefined, + logger, ); } catch (e) { logger.error( @@ -312,7 +313,7 @@ async function doOpenIdAndJWTFromUrl( > & OpenIDClientParts, delayId?: string, - logger: Logger, + logger?: Logger, ): Promise { const sfuConfig = await getSFUConfigWithOpenID( client, From eefa6f843dd4eb7c64b14d1aa55e336e74f15e97 Mon Sep 17 00:00:00 2001 From: "Timo K." Date: Tue, 7 Jul 2026 19:52:50 +0200 Subject: [PATCH 5/9] fmt --- eslint/NoTopLevelLoggerGetChild.js | 6 +++--- eslint/index.js | 3 ++- sdk/helper.ts | 1 - sdk/main.ts | 2 +- src/room/InCallView.tsx | 2 -- 5 files changed, 6 insertions(+), 8 deletions(-) diff --git a/eslint/NoTopLevelLoggerGetChild.js b/eslint/NoTopLevelLoggerGetChild.js index 324115d9e..3d9752c47 100644 --- a/eslint/NoTopLevelLoggerGetChild.js +++ b/eslint/NoTopLevelLoggerGetChild.js @@ -26,9 +26,9 @@ const rule = ESLintUtils.RuleCreator( type: "problem", docs: { description: - "Disallow calling logger.getChild() at the top level of a module." + - "`getChild` has to be called after the rageshake logger `init()`." + - "If it is called at the top level the child logger will never be setup for rageshakes.", + "Disallow calling logger.getChild() at the top level of a module." + + "`getChild` has to be called after the rageshake logger `init()`." + + "If it is called at the top level the child logger will never be setup for rageshakes.", }, messages: { noTopLevelGetChild: diff --git a/eslint/index.js b/eslint/index.js index 95b4d061f..1f2e7629e 100644 --- a/eslint/index.js +++ b/eslint/index.js @@ -2,6 +2,7 @@ module.exports = { rules: { "copyright-header": require("./CopyrightHeader").default, "no-observablescope-leak": require("./NoObservableScopeLeak").default, - "no-top-level-logger-get-child": require("./NoTopLevelLoggerGetChild").default, + "no-top-level-logger-get-child": require("./NoTopLevelLoggerGetChild") + .default, }, }; diff --git a/sdk/helper.ts b/sdk/helper.ts index c3f0c13c2..9f7e02a7d 100644 --- a/sdk/helper.ts +++ b/sdk/helper.ts @@ -15,7 +15,6 @@ import { scan } from "rxjs"; import { type WidgetHelpers } from "../src/widget"; import { type LivekitRoomItem } from "../src/state/CallViewModel/CallViewModel"; - export const tryMakeSticky = (widget: WidgetHelpers): void => { const logger = rootLogger.getChild("[MatrixRTCSdk]"); logger.info("try making sticky MatrixRTCSdk"); diff --git a/sdk/main.ts b/sdk/main.ts index 6e558fc94..a001af65c 100644 --- a/sdk/main.ts +++ b/sdk/main.ts @@ -53,7 +53,7 @@ import { MuteStates } from "../src/state/MuteStates"; import { MediaDevices } from "../src/state/MediaDevices"; import { E2eeType } from "../src/e2ee/e2eeType"; import { currentAndPrev, TEXT_LK_TOPIC, tryMakeSticky } from "./helper"; -import {logger as rootLogger} from "matrix-js-sdk/lib/logger" +import { logger as rootLogger } from "matrix-js-sdk/lib/logger"; import { ElementWidgetActions, widget as _widget, diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index 8982226ab..bf5918724 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -94,8 +94,6 @@ declare module "react" { } } - - export interface ActiveCallProps extends Omit< InCallViewProps, "vm" | "livekitRoom" | "connState" | "footerVm" From 1e6d3d3357baafb8bcdc307379b73df8cd01c2ed Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Jul 2026 14:02:37 +0000 Subject: [PATCH 6/9] Update GitHub Actions --- .github/workflows/zizmor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml index 104e073ef..caeac8286 100644 --- a/.github/workflows/zizmor.yml +++ b/.github/workflows/zizmor.yml @@ -15,9 +15,9 @@ jobs: security-events: write # Required for upload-sarif (used by zizmor-action) to upload SARIF files. steps: - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Run zizmor 🌈 - uses: zizmorcore/zizmor-action@b1d7e1fb5de872772f31590499237e7cce841e8e # v0.5.3 + uses: zizmorcore/zizmor-action@192e21d79ab29983730a13d1382995c2307fbcaa # v0.5.7 From 000ee66cfe157772894a5708b02eb1aba3082206 Mon Sep 17 00:00:00 2001 From: Robin Date: Wed, 8 Jul 2026 17:00:33 +0200 Subject: [PATCH 7/9] Use vitest's default for scoped class names It reduces confusion when reading snapshots if class names are still scoped to their respective CSS modules. It also discourages the use of class names in tests, which is a good thing. (https://testing-library.com/docs/guiding-principles) Thanks to Johannes for the suggestion. --- vitest.config.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/vitest.config.ts b/vitest.config.ts index 2dc9382c6..c5e908e4b 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -18,12 +18,7 @@ export default defineConfig((configEnv) => extends: true, test: { name: "unit", - css: { - include: /.+/, - modules: { - classNameStrategy: "non-scoped", - }, - }, + css: { include: /.+/ }, setupFiles: ["src/vitest.setup.ts"], environment: "jsdom", include: ["src/**/*.test.ts", "src/**/*.test.tsx"], From 943ce5b853abf429de053c97512c85112091176f Mon Sep 17 00:00:00 2001 From: Robin Date: Wed, 8 Jul 2026 17:06:09 +0200 Subject: [PATCH 8/9] Update test snapshots to use scoped class names --- src/__snapshots__/AppBar.test.tsx.snap | 16 +- src/__snapshots__/Modal.test.tsx.snap | 18 +- src/__snapshots__/QrCode.test.tsx.snap | 2 +- src/__snapshots__/Toast.test.tsx.snap | 2 +- .../ReactionToggleButton.test.tsx.snap | 2 +- .../MediaMuteAndSwitchButton.test.tsx.snap | 4 +- .../RaisedHandIndicator.test.tsx.snap | 12 +- .../GroupCallErrorBoundary.test.tsx.snap | 252 +++++++++--------- .../__snapshots__/InCallView.test.tsx.snap | 56 ++-- .../__snapshots__/LobbyView.test.tsx.snap | 102 +++---- .../DeveloperSettingsTab.test.tsx.snap | 38 +-- 11 files changed, 252 insertions(+), 252 deletions(-) diff --git a/src/__snapshots__/AppBar.test.tsx.snap b/src/__snapshots__/AppBar.test.tsx.snap index 482189481..99b322ac3 100644 --- a/src/__snapshots__/AppBar.test.tsx.snap +++ b/src/__snapshots__/AppBar.test.tsx.snap @@ -3,12 +3,12 @@ exports[`AppBar > renders 1`] = `
@@ -46,12 +46,12 @@ exports[`AppBar > renders 1`] = ` exports[`AppBar > renders with title and subtitle 1`] = `

Title

Subtitle
diff --git a/src/__snapshots__/Modal.test.tsx.snap b/src/__snapshots__/Modal.test.tsx.snap index 648bdfd50..4753701eb 100644 --- a/src/__snapshots__/Modal.test.tsx.snap +++ b/src/__snapshots__/Modal.test.tsx.snap @@ -3,7 +3,7 @@ exports[`the content is rendered when the modal is open 1`] = `