Compare commits

..

39 Commits

Author SHA1 Message Date
David Baker
3016866a4b Make the right function a real function, then the 'this' param works 2023-09-26 18:30:39 +01:00
David Baker
2cfa007d4c Typo
Co-authored-by: Robin <robin@robin.town>
2023-09-26 17:31:00 +01:00
David Baker
4613d43c3c Re-enable livekit rageshake logging & with depth limit
Puts livekit logs back in the rageshake logs and adds a recursion
limit to the object serialiser in rageshake.
2023-09-26 12:08:08 +01:00
David Baker
a1aaacaad7 Merge pull request #1592 from vector-im/dbkr/use_loglevel
Use the loglevel library's extensions
2023-09-26 11:14:47 +01:00
renovate[bot]
1d018eeead Update dependency @vector-im/compound-web to v0.4.4 (#1600)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-09-26 11:50:54 +02:00
Robin
39ee20ab0c Merge pull request #1598 from vector-im/renovate/sdp-transform-2.x-lockfile
Update dependency @types/sdp-transform to v2.4.7
2023-09-25 17:28:08 -04:00
Robin
499ba0e059 Merge pull request #1597 from vector-im/renovate/node-18.x-lockfile
Update dependency @types/node to v18.18.0
2023-09-25 17:27:33 -04:00
Robin
6f425abd5f Merge pull request #1599 from vector-im/renovate/vector-im-compound-design-tokens-0.x
Update dependency @vector-im/compound-design-tokens to ^0.0.6
2023-09-25 17:27:09 -04:00
Robin
87fb3398d4 Merge pull request #1596 from vector-im/renovate/grecaptcha-3.x-lockfile
Update dependency @types/grecaptcha to v3.0.5
2023-09-25 17:26:20 -04:00
renovate[bot]
a57db61aed Update dependency @types/node to v18.18.0 2023-09-25 21:24:05 +00:00
renovate[bot]
0423f2f4bb Update dependency @vector-im/compound-design-tokens to ^0.0.6 2023-09-25 21:23:48 +00:00
renovate[bot]
01c9454f92 Update dependency @types/sdp-transform to v2.4.7 2023-09-25 21:23:34 +00:00
David Baker
31446e7997 Typo
Co-authored-by: Robin <robin@robin.town>
2023-09-25 20:55:04 +01:00
Robin
02db81d846 Merge pull request #1521 from vector-im/renovate/testing-library-jest-dom-6.x
Update dependency @testing-library/jest-dom to v6
2023-09-25 14:44:37 -04:00
renovate[bot]
5f72ec2416 Update dependency @types/grecaptcha to v3.0.5 2023-09-25 18:42:41 +00:00
Robin
4330b46086 Add @types/jest, which we depend on 2023-09-25 14:41:52 -04:00
David Baker
c546042d18 Use the loglevel library's extensions
...instead of monkey patching the console log objects. We use a logging
framework everywhere now (this fixes the times when we didn't...)
so there's not really a reason to do this the hacky way anymore.

This means that log lines now appear to come from whatever else is
intercepting the logger (eg. sentry) rather than rageshake.ts.

Opinions on this welcome on whether it's better or not.
2023-09-25 18:04:34 +01:00
Robin
7dac9caa6b Merge pull request #1532 from vector-im/renovate/i18next-23.x
Update dependency i18next to v23
2023-09-25 12:34:05 -04:00
Robin
15566770f9 Upgrade react-i18next, too 2023-09-25 12:31:27 -04:00
renovate[bot]
f053ecfa98 Update dependency i18next to v23 2023-09-25 16:28:17 +00:00
Robin
39dd60598e Merge pull request #1537 from vector-im/renovate/i18next-parser-8.x
Update dependency i18next-parser to v8
2023-09-25 12:27:20 -04:00
renovate[bot]
e790c13112 Update dependency i18next-parser to v8 2023-09-25 16:22:46 +00:00
Robin
946ab6ff1a Merge pull request #1591 from vector-im/renovate/dompurify-3.x-lockfile
Update dependency @types/dompurify to v3.0.3
2023-09-25 12:21:49 -04:00
Robin
e730926eab Merge pull request #1536 from vector-im/renovate/i18next-http-backend-2.x
Update dependency i18next-http-backend to v2
2023-09-25 12:08:01 -04:00
Robin
7195bf7672 Merge pull request #1590 from vector-im/renovate/radix-ui-react-dialog-1.x-lockfile
Update dependency @radix-ui/react-dialog to v1.0.5
2023-09-25 12:06:59 -04:00
renovate[bot]
8e2c1dd164 Update dependency i18next-http-backend to v2 2023-09-25 16:04:50 +00:00
renovate[bot]
448865b0d5 Update dependency @types/dompurify to v3.0.3 2023-09-25 16:04:20 +00:00
renovate[bot]
c75b21e0cb Update dependency @radix-ui/react-dialog to v1.0.5 2023-09-25 16:04:05 +00:00
Robin
8a22aa55a6 Merge pull request #1535 from vector-im/renovate/i18next-browser-languagedetector-7.x
Update dependency i18next-browser-languagedetector to v7
2023-09-25 12:03:34 -04:00
Robin
b6e9a0869a Merge pull request #1575 from vector-im/renovate/d3-7.x-lockfile
Update dependency @types/d3 to v7.4.1
2023-09-25 12:00:16 -04:00
Robin
37e69f6023 Merge pull request #1589 from robintown/swap-buttons
Swap the microphone and video buttons
2023-09-25 11:39:47 -04:00
Robin
d672190c6f Swap the microphone and video buttons
Per feedback and discussion with design, we should keep them in the order they were previously.
2023-09-25 10:39:18 -04:00
David Baker
ac6747bbf3 Merge pull request #1578 from vector-im/renovate/livekit-client-1.x-lockfile
Update dependency livekit-client to v1.13.4
2023-09-25 10:18:09 +01:00
renovate[bot]
6c5e9226cf Update dependency livekit-client to v1.13.4 2023-09-25 09:14:27 +00:00
David Baker
845b4e133b Merge pull request #1577 from vector-im/revert-1566-dbkr/lklogs
Revert "Capture livekit's logs in rageshakes"
2023-09-25 09:37:08 +01:00
David Baker
b0f63eb2ff Revert "Capture livekit's logs in rageshakes" 2023-09-25 09:32:32 +01:00
renovate[bot]
0a12766171 Update dependency @types/d3 to v7.4.1 2023-09-23 00:26:17 +00:00
renovate[bot]
703aa661ea Update dependency i18next-browser-languagedetector to v7 2023-09-19 18:45:14 +00:00
renovate[bot]
edd4ff077b Update dependency @testing-library/jest-dom to v6 2023-09-19 16:04:01 +00:00
23 changed files with 522 additions and 415 deletions

View File

@@ -33,6 +33,8 @@ module.exports = {
rules: {
// We're aiming to convert this code to strict mode
"@typescript-eslint/no-non-null-assertion": "off",
// We should use the js-sdk logger, never console directly.
"no-console": ["error"],
},
},
],

View File

@@ -47,15 +47,15 @@
"@sentry/react": "^6.13.3",
"@sentry/tracing": "^6.13.3",
"@use-gesture/react": "^10.2.11",
"@vector-im/compound-design-tokens": "^0.0.5",
"@vector-im/compound-design-tokens": "^0.0.6",
"@vector-im/compound-web": "^0.4.0",
"@vitejs/plugin-basic-ssl": "^1.0.1",
"@vitejs/plugin-react": "^4.0.1",
"classnames": "^2.3.1",
"events": "^3.3.0",
"i18next": "^21.10.0",
"i18next-browser-languagedetector": "^6.1.8",
"i18next-http-backend": "^1.4.4",
"i18next": "^23.0.0",
"i18next-browser-languagedetector": "^7.0.0",
"i18next-http-backend": "^2.0.0",
"livekit-client": "^1.12.3",
"lodash": "^4.17.21",
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#6385c9c0dab8fe67bd3a8992a4777f243fdd1b68",
@@ -68,7 +68,7 @@
"re-resizable": "^6.9.0",
"react": "18",
"react-dom": "18",
"react-i18next": "^11.18.6",
"react-i18next": "^13.0.0",
"react-json-view": "^1.21.3",
"react-router-dom": "^5.2.0",
"react-use-clipboard": "^1.0.7",
@@ -85,13 +85,14 @@
"@react-types/dialog": "^3.5.5",
"@sentry/vite-plugin": "^2.0.0",
"@storybook/react": "^6.5.0-alpha.5",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/jest-dom": "^6.0.0",
"@testing-library/react": "^14.0.0",
"@types/content-type": "^1.1.5",
"@types/d3": "^7.4.0",
"@types/dom-screen-wake-lock": "^1.0.1",
"@types/dompurify": "^3.0.2",
"@types/grecaptcha": "^3.0.4",
"@types/jest": "^29.5.5",
"@types/node": "^18.13.0",
"@types/react-router-dom": "^5.3.3",
"@types/request": "^2.48.8",
@@ -109,7 +110,7 @@
"eslint-plugin-matrix-org": "^0.4.0",
"eslint-plugin-react": "^7.29.4",
"eslint-plugin-react-hooks": "^4.5.0",
"i18next-parser": "^6.6.0",
"i18next-parser": "^8.0.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^29.2.2",
"jest-environment-jsdom": "^29.3.1",

View File

@@ -44,7 +44,6 @@ import {
import { translatedError } from "./TranslatedError";
import { useEventTarget } from "./useEvents";
import { Config } from "./config/Config";
import { useUrlParams } from "./UrlParams";
declare global {
interface Window {
@@ -153,7 +152,7 @@ interface Props {
export const ClientProvider: FC<Props> = ({ children }) => {
const history = useHistory();
const { token, userId, deviceId, baseUrl } = useUrlParams();
// null = signed out, undefined = loading
const [initClientState, setInitClientState] = useState<
InitResult | null | undefined
@@ -166,26 +165,12 @@ export const ClientProvider: FC<Props> = ({ children }) => {
// the client.
if (initializing.current) return;
initializing.current = true;
const tokenLogin =
!token && !userId
? undefined
: ({
token,
userId,
deviceId,
homeserver: baseUrl,
} as {
token: string;
userId: string;
deviceId: string;
homeserver: string;
});
loadClient(tokenLogin)
loadClient()
.then(setInitClientState)
.catch((err) => logger.error(err))
.finally(() => (initializing.current = false));
}, [token, userId, deviceId, baseUrl]);
}, []);
const changePassword = useCallback(
async (password: string) => {
@@ -354,12 +339,7 @@ type InitResult = {
passwordlessUser: boolean;
};
async function loadClient(tokenLogin?: {
token: string;
userId: string;
deviceId: string;
homeserver: string;
}): Promise<InitResult | null> {
async function loadClient(): Promise<InitResult | null> {
if (widget) {
// We're inside a widget, so let's engage *matryoshka mode*
logger.log("Using a matryoshka client");
@@ -371,15 +351,7 @@ async function loadClient(tokenLogin?: {
} else {
// We're running as a standalone application
try {
let session = loadSession();
if (tokenLogin) {
session = {
user_id: tokenLogin.userId,
device_id: tokenLogin.deviceId, //"TOKEN_DEVICE",
access_token: tokenLogin.token,
passwordlessUser: false,
};
}
const session = loadSession();
if (!session) {
logger.log("No session stored; continuing without a client");
return null;
@@ -390,7 +362,7 @@ async function loadClient(tokenLogin?: {
/* eslint-disable camelcase */
const { user_id, device_id, access_token, passwordlessUser } = session;
const initClientParams = {
baseUrl: tokenLogin?.homeserver ?? Config.defaultHomeserverUrl()!,
baseUrl: Config.defaultHomeserverUrl()!,
accessToken: access_token,
userId: user_id,
deviceId: device_id,
@@ -399,7 +371,7 @@ async function loadClient(tokenLogin?: {
};
try {
const client = await initClient(initClientParams, !tokenLogin);
const client = await initClient(initClientParams, true);
return {
client,
passwordlessUser,

View File

@@ -19,6 +19,7 @@ import { useLocation } from "react-router-dom";
import classNames from "classnames";
import { Trans, useTranslation } from "react-i18next";
import * as Sentry from "@sentry/react";
import { logger } from "matrix-js-sdk/src/logger";
import { Header, HeaderLogo, LeftNav, RightNav } from "./Header";
import { LinkButton, Button } from "./button";
@@ -57,7 +58,7 @@ export function ErrorView({ error }: ErrorViewProps) {
const { t } = useTranslation();
useEffect(() => {
console.error(error);
logger.error(error);
Sentry.captureException(error);
}, [error]);

View File

@@ -108,16 +108,6 @@ interface UrlParams {
* E2EE password
*/
password: string | null;
/**
* Token for a user for instance login. This is used for bridge gosts.
*/
token: string | null;
/**
* Setting this flag skips the lobby and brings you in the call directly.
* In the widget this can be combined with preload to pass the device settings
* with the join widget action.
*/
skipLobby: boolean;
}
// This is here as a stopgap, but what would be far nicer is a function that
@@ -210,8 +200,6 @@ export const getUrlParams = (
fontScale: Number.isNaN(fontScale) ? null : fontScale,
analyticsID: parser.getParam("analyticsID"),
allowIceFallback: parser.getFlagParam("allowIceFallback"),
token: parser.getParam("token"),
skipLobby: parser.getFlagParam("skipLobby"),
};
};

View File

@@ -27,6 +27,7 @@ import { useHistory, useLocation } from "react-router-dom";
import { captureException } from "@sentry/react";
import { sleep } from "matrix-js-sdk/src/utils";
import { Trans, useTranslation } from "react-i18next";
import { logger } from "matrix-js-sdk/src/logger";
import { FieldRow, InputField, ErrorMessage } from "../input/Input";
import { Button } from "../button";
@@ -97,7 +98,7 @@ export const RegisterPage: FC = () => {
await newClient.joinRoom(roomId);
} else {
captureException(error);
console.error(`Couldn't join room ${roomId}`, error);
logger.error(`Couldn't join room ${roomId}`, error);
}
}
}

View File

@@ -17,6 +17,7 @@ limitations under the License.
import { useEffect, useCallback, useRef, useState } from "react";
import { randomString } from "matrix-js-sdk/src/randomstring";
import { useTranslation } from "react-i18next";
import { logger } from "matrix-js-sdk/src/logger";
import { translatedError } from "../TranslatedError";
@@ -74,7 +75,7 @@ export const useRecaptcha = (sitekey?: string) => {
}
if (!window.grecaptcha) {
console.log("Recaptcha not loaded");
logger.log("Recaptcha not loaded");
return Promise.reject(translatedError("Recaptcha not loaded", t));
}

View File

@@ -85,17 +85,12 @@ export const useManageRoomSharedKey = (roomId: string): string | null => {
export const useIsRoomE2EE = (roomId: string): boolean | null => {
const { client } = useClient();
const { token } = useUrlParams();
const isRoomForBridgedCall = !!token;
const room = useMemo(() => client?.getRoom(roomId) ?? null, [roomId, client]);
// For now, rooms in widget mode are never considered encrypted.
// In the future, when widget mode gains encryption support, then perhaps we
// should inspect the e2eEnabled URL parameter here?
return useMemo(
() =>
!isRoomForBridgedCall &&
widget === null &&
(room === null || !room.getCanonicalAlias()),
[room, isRoomForBridgedCall]
() => widget === null && (room === null || !room.getCanonicalAlias()),
[room]
);
};

View File

@@ -20,6 +20,7 @@ import { MatrixClient } from "matrix-js-sdk/src/client";
import { randomString } from "matrix-js-sdk/src/randomstring";
import { useTranslation } from "react-i18next";
import { Heading } from "@vector-im/compound-web";
import { logger } from "matrix-js-sdk/src/logger";
import {
createRoom,
@@ -97,7 +98,7 @@ export function RegisteredView({ client }: Props) {
setError(undefined);
setJoinExistingCallModalOpen(true);
} else {
console.error(error);
logger.error(error);
setLoading(false);
setError(error);
}

View File

@@ -19,6 +19,7 @@ import { useHistory } from "react-router-dom";
import { randomString } from "matrix-js-sdk/src/randomstring";
import { Trans, useTranslation } from "react-i18next";
import { Heading } from "@vector-im/compound-web";
import { logger } from "matrix-js-sdk/src/logger";
import { useClient } from "../ClientContext";
import { Header, HeaderLogo, LeftNav, RightNav } from "../Header";
@@ -130,7 +131,7 @@ export const UnauthenticatedView: FC = () => {
}
submit().catch((error) => {
console.error(error);
logger.error(error);
setLoading(false);
setError(error);
reset();

View File

@@ -24,20 +24,21 @@ import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { createBrowserHistory } from "history";
import "./index.css";
import { setLogLevel as setLKLogLevel } from "livekit-client";
import { logger } from "matrix-js-sdk/src/logger";
import {
setLogExtension as setLKLogExtension,
setLogLevel,
} from "livekit-client";
import App from "./App";
import { init as initRageshake } from "./settings/rageshake";
import { Initializer } from "./initializer";
initRageshake();
// set livekit's log level: we do this after initialising rageshakes because
// we need rageshake to do its monkey patching first, so the livekit
// logger gets the patched log funxction, so it picks up livekit's
// logs.
setLKLogLevel("debug");
setLogLevel("debug");
setLKLogExtension(global.mx_rage_logger.log);
console.info(`Element Call ${import.meta.env.VITE_APP_VERSION || "dev"}`);
logger.info(`Element Call ${import.meta.env.VITE_APP_VERSION || "dev"}`);
const root = createRoot(document.getElementById("root")!);

View File

@@ -177,7 +177,7 @@ export async function initClient(
try {
await client.store.startup();
} catch (error) {
console.error(
logger.error(
"Error starting matrix client store. Falling back to memory store.",
error
);

View File

@@ -19,6 +19,7 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { User, UserEvent } from "matrix-js-sdk/src/models/user";
import { FileType } from "matrix-js-sdk/src/http-api";
import { useState, useCallback, useEffect } from "react";
import { logger } from "matrix-js-sdk/src/logger";
interface ProfileLoadState {
success: boolean;
@@ -127,7 +128,7 @@ export function useProfile(client: MatrixClient | undefined) {
}));
}
} else {
console.error("Client not initialized before calling saveProfile");
logger.error("Client not initialized before calling saveProfile");
}
},
[client]

View File

@@ -60,7 +60,6 @@ interface Props {
isPasswordlessUser: boolean;
confineToRoom: boolean;
preload: boolean;
skipLobby: boolean;
hideHeader: boolean;
rtcSession: MatrixRTCSession;
}
@@ -70,7 +69,6 @@ export function GroupCallView({
isPasswordlessUser,
confineToRoom,
preload,
skipLobby,
hideHeader,
rtcSession,
}: Props) {
@@ -135,17 +133,18 @@ export function GroupCallView({
latestMuteStates.current = muteStates;
useEffect(() => {
if (skipLobby) {
// widget && preload
const defaultDeviceSetup = async (
requestedDeviceData: JoinCallData
): Promise<void> => {
if (widget && preload) {
// In preload mode, wait for a join action before entering
const onJoin = async (ev: CustomEvent<IWidgetApiRequest>) => {
// XXX: I think this is broken currently - LiveKit *won't* request
// 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
// for the following name-matching logic to do anything useful.
const devices = await Room.getLocalDevices(undefined, true);
const { audioInput, videoInput } = requestedDeviceData;
const { audioInput, videoInput } = ev.detail
.data as unknown as JoinCallData;
if (audioInput === null) {
latestMuteStates.current!.audio.setEnabled?.(false);
} else {
@@ -185,27 +184,27 @@ export function GroupCallView({
latestMuteStates.current!.video.setEnabled?.(true);
}
}
};
// In preload mode, wait for a join action before entering
if (widget && preload) {
const onJoin = async (ev: CustomEvent<IWidgetApiRequest>) => {
defaultDeviceSetup(ev.detail.data as unknown as JoinCallData);
enterRTCSession(rtcSession);
await Promise.all([
widget!.api.setAlwaysOnScreen(true),
widget!.api.transport.reply(ev.detail, {}),
]);
};
widget.lazyActions.on(ElementWidgetActions.JoinCall, onJoin);
return () => {
widget!.lazyActions.off(ElementWidgetActions.JoinCall, onJoin);
};
} else {
defaultDeviceSetup({ audioInput: null, videoInput: null });
enterRTCSession(rtcSession);
}
PosthogAnalytics.instance.eventCallEnded.cacheStartCall(new Date());
// we only have room sessions right now, so call ID is the emprty string - we use the room ID
PosthogAnalytics.instance.eventCallStarted.track(
rtcSession.room.roomId
);
await Promise.all([
widget!.api.setAlwaysOnScreen(true),
widget!.api.transport.reply(ev.detail, {}),
]);
};
widget.lazyActions.on(ElementWidgetActions.JoinCall, onJoin);
return () => {
widget!.lazyActions.off(ElementWidgetActions.JoinCall, onJoin);
};
}
}, [rtcSession, preload, skipLobby]);
}, [rtcSession, preload]);
const [left, setLeft] = useState(false);
const [leaveError, setLeaveError] = useState<Error | undefined>(undefined);

View File

@@ -344,19 +344,19 @@ export function InCallView({
const buttons: JSX.Element[] = [];
buttons.push(
<VideoButton
key="2"
muted={!muteStates.video.enabled}
onPress={toggleCamera}
disabled={muteStates.video.setEnabled === null}
data-testid="incall_videomute"
/>,
<MicButton
key="1"
muted={!muteStates.audio.enabled}
onPress={toggleMicrophone}
disabled={muteStates.audio.setEnabled === null}
data-testid="incall_mute"
/>,
<VideoButton
key="2"
muted={!muteStates.video.enabled}
onPress={toggleCamera}
disabled={muteStates.video.setEnabled === null}
data-testid="incall_videomute"
/>
);

View File

@@ -129,16 +129,16 @@ export const LobbyView: FC<Props> = ({
<div className={inCallStyles.footer}>
{recentsButtonInFooter && recentsButton}
<div className={inCallStyles.buttons}>
<VideoButton
muted={!muteStates.video.enabled}
onPress={onVideoPress}
disabled={muteStates.video.setEnabled === null}
/>
<MicButton
muted={!muteStates.audio.enabled}
onPress={onAudioPress}
disabled={muteStates.audio.setEnabled === null}
/>
<VideoButton
muted={!muteStates.video.enabled}
onPress={onVideoPress}
disabled={muteStates.video.setEnabled === null}
/>
<SettingsButton onPress={openSettings} />
{!confineToRoom && <HangupButton onPress={onLeaveClick} />}
</div>

View File

@@ -17,6 +17,7 @@ limitations under the License.
import { useCallback, useState } from "react";
import { useLocation } from "react-router-dom";
import { Trans, useTranslation } from "react-i18next";
import { logger } from "matrix-js-sdk/src/logger";
import styles from "./RoomAuthView.module.css";
import { Button } from "../button";
@@ -46,7 +47,7 @@ export function RoomAuthView() {
typeof dataForDisplayName === "string" ? dataForDisplayName : "";
registerPasswordlessUser(displayName).catch((error) => {
console.error("Failed to register passwordless user", e);
logger.error("Failed to register passwordless user", e);
setLoading(false);
setError(error);
});

View File

@@ -16,6 +16,7 @@ limitations under the License.
import { FC, useEffect, useState, useCallback, ReactNode } from "react";
import { MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
import { logger } from "matrix-js-sdk/src/logger";
import { useClientLegacy } from "../ClientContext";
import { ErrorView, LoadingView } from "../FullScreenView";
@@ -30,20 +31,14 @@ import { platform } from "../Platform";
import { AppSelectionModal } from "./AppSelectionModal";
export const RoomPage: FC = () => {
const {
confineToRoom,
appPrompt,
preload,
hideHeader,
displayName,
skipLobby,
} = useUrlParams();
const { confineToRoom, appPrompt, preload, hideHeader, displayName } =
useUrlParams();
const { roomAlias, roomId, viaServers } = useRoomIdentifier();
const roomIdOrAlias = roomId ?? roomAlias;
if (!roomIdOrAlias) {
console.error("No room specified");
logger.error("No room specified");
}
const [optInAnalytics, setOptInAnalytics] = useOptInAnalytics();
@@ -83,11 +78,10 @@ export const RoomPage: FC = () => {
isPasswordlessUser={passwordlessUser}
confineToRoom={confineToRoom}
preload={preload}
skipLobby={skipLobby}
hideHeader={hideHeader}
/>
),
[client, passwordlessUser, confineToRoom, preload, hideHeader, skipLobby]
[client, passwordlessUser, confineToRoom, preload, hideHeader]
);
let content: ReactNode;

View File

@@ -24,6 +24,7 @@ import {
Track,
} from "livekit-client";
import classNames from "classnames";
import { logger } from "matrix-js-sdk/src/logger";
import { Avatar } from "../Avatar";
import styles from "./VideoPreview.module.css";
@@ -80,7 +81,7 @@ export const VideoPreview: FC<Props> = ({
},
},
(error) => {
console.error("Error while creating preview Tracks:", error);
logger.error("Error while creating preview Tracks:", error);
}
);
const videoTrack = useMemo(

View File

@@ -50,15 +50,13 @@ const MAX_LOG_SIZE = 1024 * 1024 * 5; // 5 MB
// we can batch the writes a little.
const MAX_FLUSH_INTERVAL_MS = 2 * 1000;
// only descend this far into nested object trees
const DEPTH_LIMIT = 3;
enum ConsoleLoggerEvent {
Log = "log",
}
type LogFunction = (
...args: (Error | DOMException | object | string)[]
) => void;
type LogFunctionName = "log" | "info" | "warn" | "error";
// A class which monkey-patches the global console and stores log lines.
interface LogEntry {
@@ -69,37 +67,11 @@ interface LogEntry {
class ConsoleLogger extends EventEmitter {
private logs = "";
private originalFunctions: { [key in LogFunctionName]?: LogFunction } = {};
public monkeyPatch(consoleObj: Console): void {
// Monkey-patch console logging
const consoleFunctionsToLevels = {
log: "I",
info: "I",
warn: "W",
error: "E",
};
Object.entries(consoleFunctionsToLevels).forEach(([name, level]) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const originalFn = consoleObj[name].bind(consoleObj);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
this.originalFunctions[name] = originalFn;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
consoleObj[name] = (...args) => {
this.log(level, ...args);
originalFn(...args);
};
});
}
public log(
level: string,
...args: (Error | DOMException | object | string)[]
): void {
public log = (
level: LogLevel,
...args: (Error | DOMException | object | string | undefined)[]
): void => {
// We don't know what locale the user may be running so use ISO strings
const ts = new Date().toISOString();
@@ -129,7 +101,7 @@ class ConsoleLogger extends EventEmitter {
this.logs += line;
this.emit(ConsoleLoggerEvent.Log);
}
};
/**
* Returns the log lines to flush to disk and empties the internal log buffer
@@ -510,7 +482,7 @@ declare global {
*/
export function init(): Promise<void> {
global.mx_rage_logger = new ConsoleLogger();
global.mx_rage_logger.monkeyPatch(window.console);
setLogExtension(global.mx_rage_logger.log);
return tryInitStorage();
}
@@ -581,13 +553,61 @@ type StringifyReplacer = (
// Injects `<$ cycle-trimmed $>` wherever it cuts a cyclical object relationship
const getCircularReplacer = (): StringifyReplacer => {
const seen = new WeakSet();
return (key: string, value: unknown): unknown => {
const depthMap = new WeakMap<object, number>();
return function (this: unknown, key: string, value: unknown): unknown {
if (typeof value === "object" && value !== null) {
if (seen.has(value)) {
return "<$ cycle-trimmed $>";
}
seen.add(value);
let depth = 0;
if (this) {
depth = depthMap.get(this) ?? 0;
}
depthMap.set(value, depth + 1);
if (depth > DEPTH_LIMIT) return "<$ object-pruned $>";
}
return value;
};
};
enum LogLevel {
trace = 0,
debug = 1,
info = 2,
warn = 3,
error = 4,
silent = 5,
}
type LogExtensionFunc = (
level: LogLevel,
...rest: (Error | DOMException | object | string)[]
) => void;
type LogLevelString = keyof typeof LogLevel;
/**
* This method borrowed from livekit (who also use loglevel and in turn essentially
* took loglevel's example honouring log levels). Adds a loglevel logging extension
* in the recommended way.
*/
export function setLogExtension(extension: LogExtensionFunc) {
const originalFactory = logger.methodFactory;
logger.methodFactory = function (methodName, configLevel, loggerName) {
const rawMethod = originalFactory(methodName, configLevel, loggerName);
const logLevel = LogLevel[methodName as LogLevelString];
const needLog = logLevel >= configLevel && logLevel < LogLevel.silent;
return (...args) => {
rawMethod.apply(this, args);
if (needLog) {
extension(logLevel, ...args);
}
};
};
logger.setLevel(logger.getLevel()); // Be sure to call setLevel method in order to apply plugin
}

View File

@@ -26,6 +26,7 @@ import {
import pako from "pako";
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { ClientEvent } from "matrix-js-sdk/src/client";
import { logger } from "matrix-js-sdk/src/logger";
import { getLogsForReport } from "./rageshake";
import { useClient } from "../ClientContext";
@@ -296,7 +297,7 @@ export function useSubmitRageshake(): {
setState({ sending: false, sent: true, error: undefined });
} catch (error) {
setState({ sending: false, sent: false, error: error as Error });
console.error(error);
logger.error(error);
}
},
[client, inspectorState, sending]

View File

@@ -38,6 +38,7 @@ import {
} from "@react-spring/web";
import useMeasure from "react-use-measure";
import { ResizeObserver as JuggleResizeObserver } from "@juggle/resize-observer";
import { logger } from "matrix-js-sdk/src/logger";
import styles from "./VideoGrid.module.css";
import { Layout } from "../room/LayoutToggle";
@@ -298,7 +299,7 @@ function getFreedomLayoutTilePositions(
}
if (tileCount > 12) {
console.warn("Over 12 tiles is not currently supported");
logger.warn("Over 12 tiles is not currently supported");
}
const { layoutDirection, itemGridRatio } = getGridLayout(

621
yarn.lock

File diff suppressed because it is too large Load Diff